summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Grosser <tobias@grosser.es>2015-02-04 20:55:43 +0000
committerTobias Grosser <tobias@grosser.es>2015-02-04 20:55:43 +0000
commit52a25237d894fd5736a90f11df2c5c9391d13fd5 (patch)
tree2b0e65b1e1de52b56aaa9b04999fe6223d1a7b0f
parentb6472fe3da9a20bcceb7b24af4ce9f0c4e79b254 (diff)
downloadbcm5719-llvm-52a25237d894fd5736a90f11df2c5c9391d13fd5.tar.gz
bcm5719-llvm-52a25237d894fd5736a90f11df2c5c9391d13fd5.zip
Import isl(+imath) as an external library into Polly
With this patch Polly is always GPL-free (no dependency on GMP any more). As a result, building and distributing Polly will be easier. Furthermore, there is no need to tightly coordinate isl and Polly releases anymore. We import isl b3e0fa7a05d as well as imath 4d707e5ef2. These are the git versions Polly currently was tested with when using utils/checkout_isl.sh. The imported libraries are both MIT-style licensed. We build isl and imath with -fvisibility=hidden to avoid clashes in case other projects (such as gcc) use conflicting versions of isl. The use of imath can temporarily reduce compile-time performance of Polly. We will work on performance tuning in tree. Patches to isl should be contributed first to the main isl repository and can then later be reimported to Polly. This patch is also a prerequisite for the upcoming isl C++ interface. llvm-svn: 228193
-rw-r--r--polly/CMakeLists.txt28
-rw-r--r--polly/Makefile.config.in27
-rw-r--r--polly/autoconf/aclocal.m48
-rw-r--r--polly/autoconf/configure.ac10
-rw-r--r--polly/cmake/FindGmp.cmake19
-rw-r--r--polly/cmake/FindIsl.cmake19
-rwxr-xr-xpolly/configure179
-rw-r--r--polly/lib/CMakeLists.txt80
-rw-r--r--polly/lib/External/README.txt17
-rw-r--r--polly/lib/External/isl/.gitignore53
-rw-r--r--polly/lib/External/isl/AUTHORS42
-rw-r--r--polly/lib/External/isl/ChangeLog134
-rw-r--r--polly/lib/External/isl/LICENSE19
-rw-r--r--polly/lib/External/isl/Makefile.am329
-rw-r--r--polly/lib/External/isl/README53
-rwxr-xr-xpolly/lib/External/isl/autogen.sh2
-rw-r--r--polly/lib/External/isl/basis_reduction_tab.c267
-rw-r--r--polly/lib/External/isl/basis_reduction_templ.c358
-rw-r--r--polly/lib/External/isl/bound.c291
-rwxr-xr-xpolly/lib/External/isl/bound_test.sh.in35
-rw-r--r--polly/lib/External/isl/cat.c58
-rw-r--r--polly/lib/External/isl/closure.c34
-rw-r--r--polly/lib/External/isl/codegen.c138
-rw-r--r--polly/lib/External/isl/codegen_test.sh.in21
-rw-r--r--polly/lib/External/isl/configure.ac236
-rw-r--r--polly/lib/External/isl/doc/Makefile.am17
-rw-r--r--polly/lib/External/isl/doc/SubmittingPatches52
-rw-r--r--polly/lib/External/isl/doc/chicago.bst1726
-rw-r--r--polly/lib/External/isl/doc/chicago.sty320
-rw-r--r--polly/lib/External/isl/doc/implementation.tex2036
-rw-r--r--polly/lib/External/isl/doc/isl.bib313
-rw-r--r--polly/lib/External/isl/doc/manual.tex75
-rwxr-xr-xpolly/lib/External/isl/doc/mypod2latex14
-rw-r--r--polly/lib/External/isl/doc/user.pod8039
-rw-r--r--polly/lib/External/isl/gitversion.h1
-rw-r--r--polly/lib/External/isl/imath/ChangeLog377
-rw-r--r--polly/lib/External/isl/imath/LICENSE20
-rw-r--r--polly/lib/External/isl/imath/README.md106
-rw-r--r--polly/lib/External/isl/imath/bintest.c106
-rw-r--r--polly/lib/External/isl/imath/bug-swap.c25
-rw-r--r--polly/lib/External/isl/imath/contrib/Makefile.msvc84
-rw-r--r--polly/lib/External/isl/imath/contrib/README3
-rw-r--r--polly/lib/External/isl/imath/divide.txt43
-rw-r--r--polly/lib/External/isl/imath/doc.txt820
-rw-r--r--polly/lib/External/isl/imath/examples/basecvt.c121
-rw-r--r--polly/lib/External/isl/imath/examples/findprime.c72
-rw-r--r--polly/lib/External/isl/imath/examples/imcalc.c1471
-rw-r--r--polly/lib/External/isl/imath/examples/input.c120
-rw-r--r--polly/lib/External/isl/imath/examples/randprime.c261
-rw-r--r--polly/lib/External/isl/imath/examples/rounding.c83
-rw-r--r--polly/lib/External/isl/imath/examples/rsakey.c325
-rwxr-xr-xpolly/lib/External/isl/imath/findsizes.py174
-rwxr-xr-xpolly/lib/External/isl/imath/findthreshold.py89
-rw-r--r--polly/lib/External/isl/imath/gmp_compat.c861
-rw-r--r--polly/lib/External/isl/imath/gmp_compat.h229
-rw-r--r--polly/lib/External/isl/imath/imath.c3668
-rw-r--r--polly/lib/External/isl/imath/imath.h232
-rw-r--r--polly/lib/External/isl/imath/imdrover.c1780
-rw-r--r--polly/lib/External/isl/imath/imdrover.h106
-rw-r--r--polly/lib/External/isl/imath/imrat.c1141
-rw-r--r--polly/lib/External/isl/imath/imrat.h124
-rw-r--r--polly/lib/External/isl/imath/imtest.c474
-rw-r--r--polly/lib/External/isl/imath/imtimer.c259
-rw-r--r--polly/lib/External/isl/imath/iprime.c116
-rw-r--r--polly/lib/External/isl/imath/iprime.h48
-rw-r--r--polly/lib/External/isl/imath/pi.c177
-rw-r--r--polly/lib/External/isl/imath/rsamath.c203
-rw-r--r--polly/lib/External/isl/imath/rsamath.h94
-rw-r--r--polly/lib/External/isl/imath/rtest.c124
-rw-r--r--polly/lib/External/isl/imath/tests/add.t848
-rw-r--r--polly/lib/External/isl/imath/tests/bigmul.t10
-rw-r--r--polly/lib/External/isl/imath/tests/bigsqr.t11
-rw-r--r--polly/lib/External/isl/imath/tests/compare.t31
-rw-r--r--polly/lib/External/isl/imath/tests/conv.t228
-rw-r--r--polly/lib/External/isl/imath/tests/div.t963
-rw-r--r--polly/lib/External/isl/imath/tests/egcd.t752
-rw-r--r--polly/lib/External/isl/imath/tests/emod.t756
-rw-r--r--polly/lib/External/isl/imath/tests/emodv.t305
-rw-r--r--polly/lib/External/isl/imath/tests/expt.t154
-rw-r--r--polly/lib/External/isl/imath/tests/gcd.t761
-rw-r--r--polly/lib/External/isl/imath/tests/gmp-compat-test/.gitignore10
-rw-r--r--polly/lib/External/isl/imath/tests/gmp-compat-test/README106
-rwxr-xr-xpolly/lib/External/isl/imath/tests/gmp-compat-test/genctest.py266
-rwxr-xr-xpolly/lib/External/isl/imath/tests/gmp-compat-test/gendata.py338
-rwxr-xr-xpolly/lib/External/isl/imath/tests/gmp-compat-test/genpytest.py134
-rw-r--r--polly/lib/External/isl/imath/tests/gmp-compat-test/gmp_custom_test.c24
-rw-r--r--polly/lib/External/isl/imath/tests/gmp-compat-test/gmpapi.py103
-rw-r--r--polly/lib/External/isl/imath/tests/gmp-compat-test/imath_custom_test.c24
-rwxr-xr-xpolly/lib/External/isl/imath/tests/gmp-compat-test/runtest3
-rwxr-xr-xpolly/lib/External/isl/imath/tests/gmp-compat-test/runtest.py117
-rw-r--r--polly/lib/External/isl/imath/tests/init.t12
-rw-r--r--polly/lib/External/isl/imath/tests/invmod.t452
-rw-r--r--polly/lib/External/isl/imath/tests/lcm.t780
-rw-r--r--polly/lib/External/isl/imath/tests/mod.t754
-rw-r--r--polly/lib/External/isl/imath/tests/mul.t864
-rw-r--r--polly/lib/External/isl/imath/tests/neg.t9
-rw-r--r--polly/lib/External/isl/imath/tests/pi1024.txt1
-rw-r--r--polly/lib/External/isl/imath/tests/pi1500-10.txt1
-rw-r--r--polly/lib/External/isl/imath/tests/pi1698-16.txt1
-rw-r--r--polly/lib/External/isl/imath/tests/qadd.t803
-rw-r--r--polly/lib/External/isl/imath/tests/qaddz.t800
-rw-r--r--polly/lib/External/isl/imath/tests/qdiv.t803
-rw-r--r--polly/lib/External/isl/imath/tests/qdivz.t800
-rw-r--r--polly/lib/External/isl/imath/tests/qmisc.t49
-rw-r--r--polly/lib/External/isl/imath/tests/qmul.t803
-rw-r--r--polly/lib/External/isl/imath/tests/qmulz.t800
-rw-r--r--polly/lib/External/isl/imath/tests/qsub.t803
-rw-r--r--polly/lib/External/isl/imath/tests/qsubz.t800
-rw-r--r--polly/lib/External/isl/imath/tests/qtodec.t1303
-rw-r--r--polly/lib/External/isl/imath/tests/root.t44
-rw-r--r--polly/lib/External/isl/imath/tests/set.t12
-rw-r--r--polly/lib/External/isl/imath/tests/sqr.t755
-rw-r--r--polly/lib/External/isl/imath/tests/sub.t849
-rw-r--r--polly/lib/External/isl/imath/tests/test.bc155
-rwxr-xr-xpolly/lib/External/isl/imath/tests/test.sh77
-rw-r--r--polly/lib/External/isl/imath_wrap/gmp_compat.c2
-rw-r--r--polly/lib/External/isl/imath_wrap/gmp_compat.h2
-rw-r--r--polly/lib/External/isl/imath_wrap/imath.c2
-rw-r--r--polly/lib/External/isl/imath_wrap/imath.h2
-rw-r--r--polly/lib/External/isl/imath_wrap/imrat.c2
-rw-r--r--polly/lib/External/isl/imath_wrap/imrat.h2
-rw-r--r--polly/lib/External/isl/imath_wrap/wrap.h172
-rw-r--r--polly/lib/External/isl/include/isl/aff.h663
-rw-r--r--polly/lib/External/isl/include/isl/aff_type.h36
-rw-r--r--polly/lib/External/isl/include/isl/arg.h314
-rw-r--r--polly/lib/External/isl/include/isl/ast.h159
-rw-r--r--polly/lib/External/isl/include/isl/ast_build.h100
-rw-r--r--polly/lib/External/isl/include/isl/ast_type.h71
-rw-r--r--polly/lib/External/isl/include/isl/band.h56
-rw-r--r--polly/lib/External/isl/include/isl/constraint.h148
-rw-r--r--polly/lib/External/isl/include/isl/ctx.h246
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/aff_int.h45
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/ast_int.h17
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/constraint_int.h25
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/ilp_int.h23
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/int.h136
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/map_int.h27
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/mat_int.h19
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/point_int.h20
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/polynomial_int.h32
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/set_int.h27
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/union_map_int.h18
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/val_int.h18
-rw-r--r--polly/lib/External/isl/include/isl/deprecated/vec_int.h22
-rw-r--r--polly/lib/External/isl/include/isl/dim.h174
-rw-r--r--polly/lib/External/isl/include/isl/flow.h77
-rw-r--r--polly/lib/External/isl/include/isl/hash.h85
-rw-r--r--polly/lib/External/isl/include/isl/hmap.h56
-rw-r--r--polly/lib/External/isl/include/isl/id.h39
-rw-r--r--polly/lib/External/isl/include/isl/id_to_ast_expr.h13
-rw-r--r--polly/lib/External/isl/include/isl/id_to_pw_aff.h13
-rw-r--r--polly/lib/External/isl/include/isl/ilp.h33
-rw-r--r--polly/lib/External/isl/include/isl/list.h76
-rw-r--r--polly/lib/External/isl/include/isl/local_space.h92
-rw-r--r--polly/lib/External/isl/include/isl/lp.h37
-rw-r--r--polly/lib/External/isl/include/isl/map.h697
-rw-r--r--polly/lib/External/isl/include/isl/map_to_basic_set.h13
-rw-r--r--polly/lib/External/isl/include/isl/map_type.h35
-rw-r--r--polly/lib/External/isl/include/isl/mat.h111
-rw-r--r--polly/lib/External/isl/include/isl/multi.h123
-rw-r--r--polly/lib/External/isl/include/isl/obj.h55
-rw-r--r--polly/lib/External/isl/include/isl/options.h50
-rw-r--r--polly/lib/External/isl/include/isl/point.h45
-rw-r--r--polly/lib/External/isl/include/isl/polynomial.h623
-rw-r--r--polly/lib/External/isl/include/isl/polynomial_type.h31
-rw-r--r--polly/lib/External/isl/include/isl/printer.h62
-rw-r--r--polly/lib/External/isl/include/isl/schedule.h93
-rw-r--r--polly/lib/External/isl/include/isl/set.h540
-rw-r--r--polly/lib/External/isl/include/isl/set_type.h6
-rw-r--r--polly/lib/External/isl/include/isl/space.h173
-rw-r--r--polly/lib/External/isl/include/isl/stream.h103
-rw-r--r--polly/lib/External/isl/include/isl/union_map.h249
-rw-r--r--polly/lib/External/isl/include/isl/union_map_type.h21
-rw-r--r--polly/lib/External/isl/include/isl/union_set.h147
-rw-r--r--polly/lib/External/isl/include/isl/union_set_type.h6
-rw-r--r--polly/lib/External/isl/include/isl/val.h114
-rw-r--r--polly/lib/External/isl/include/isl/val_gmp.h21
-rw-r--r--polly/lib/External/isl/include/isl/vec.h78
-rw-r--r--polly/lib/External/isl/include/isl/version.h14
-rw-r--r--polly/lib/External/isl/include/isl/vertices.h47
-rw-r--r--polly/lib/External/isl/interface/Makefile.am32
-rw-r--r--polly/lib/External/isl/interface/all.h4
-rw-r--r--polly/lib/External/isl/interface/extract_interface.cc388
-rw-r--r--polly/lib/External/isl/interface/extract_interface.h3
-rw-r--r--polly/lib/External/isl/interface/isl.py.top29
-rw-r--r--polly/lib/External/isl/interface/python.cc519
-rw-r--r--polly/lib/External/isl/interface/python.h7
-rw-r--r--polly/lib/External/isl/isl.py100
-rw-r--r--polly/lib/External/isl/isl_aff.c6809
-rw-r--r--polly/lib/External/isl/isl_aff_private.h158
-rw-r--r--polly/lib/External/isl/isl_affine_hull.c1405
-rw-r--r--polly/lib/External/isl/isl_arg.c1308
-rw-r--r--polly/lib/External/isl/isl_ast.c2069
-rw-r--r--polly/lib/External/isl/isl_ast_build.c2162
-rw-r--r--polly/lib/External/isl/isl_ast_build_expr.c1779
-rw-r--r--polly/lib/External/isl/isl_ast_build_expr.h22
-rw-r--r--polly/lib/External/isl/isl_ast_build_private.h267
-rw-r--r--polly/lib/External/isl/isl_ast_codegen.c3921
-rw-r--r--polly/lib/External/isl/isl_ast_graft.c1242
-rw-r--r--polly/lib/External/isl/isl_ast_graft_private.h97
-rw-r--r--polly/lib/External/isl/isl_ast_int.c13
-rw-r--r--polly/lib/External/isl/isl_ast_private.h114
-rw-r--r--polly/lib/External/isl/isl_band.c726
-rw-r--r--polly/lib/External/isl/isl_band_private.h47
-rw-r--r--polly/lib/External/isl/isl_basis_reduction.h27
-rw-r--r--polly/lib/External/isl/isl_bernstein.c555
-rw-r--r--polly/lib/External/isl/isl_bernstein.h4
-rw-r--r--polly/lib/External/isl/isl_blk.c134
-rw-r--r--polly/lib/External/isl/isl_blk.h40
-rw-r--r--polly/lib/External/isl/isl_bound.c331
-rw-r--r--polly/lib/External/isl/isl_bound.h20
-rw-r--r--polly/lib/External/isl/isl_coalesce.c1745
-rw-r--r--polly/lib/External/isl/isl_config.h169
-rw-r--r--polly/lib/External/isl/isl_config_post.h13
-rw-r--r--polly/lib/External/isl/isl_constraint.c1437
-rw-r--r--polly/lib/External/isl/isl_constraint_private.h32
-rw-r--r--polly/lib/External/isl/isl_convex_hull.c2829
-rw-r--r--polly/lib/External/isl/isl_ctx.c334
-rw-r--r--polly/lib/External/isl/isl_ctx_private.h34
-rw-r--r--polly/lib/External/isl/isl_deprecated.c10
-rw-r--r--polly/lib/External/isl/isl_dim.c258
-rw-r--r--polly/lib/External/isl/isl_dim_map.c233
-rw-r--r--polly/lib/External/isl/isl_dim_map.h36
-rw-r--r--polly/lib/External/isl/isl_equalities.c782
-rw-r--r--polly/lib/External/isl/isl_equalities.h33
-rw-r--r--polly/lib/External/isl/isl_factorization.c331
-rw-r--r--polly/lib/External/isl/isl_factorization.h29
-rw-r--r--polly/lib/External/isl/isl_farkas.c403
-rw-r--r--polly/lib/External/isl/isl_flow.c1496
-rw-r--r--polly/lib/External/isl/isl_fold.c1711
-rw-r--r--polly/lib/External/isl/isl_gmp.c24
-rw-r--r--polly/lib/External/isl/isl_hash.c230
-rw-r--r--polly/lib/External/isl/isl_hide_deprecated.h53
-rw-r--r--polly/lib/External/isl/isl_hmap_templ.c388
-rw-r--r--polly/lib/External/isl/isl_id.c242
-rw-r--r--polly/lib/External/isl/isl_id_private.h41
-rw-r--r--polly/lib/External/isl/isl_id_to_ast_expr.c11
-rw-r--r--polly/lib/External/isl/isl_id_to_pw_aff.c11
-rw-r--r--polly/lib/External/isl/isl_ilp.c642
-rw-r--r--polly/lib/External/isl/isl_ilp_private.h11
-rw-r--r--polly/lib/External/isl/isl_imath.c53
-rw-r--r--polly/lib/External/isl/isl_imath.h8
-rw-r--r--polly/lib/External/isl/isl_input.c3370
-rw-r--r--polly/lib/External/isl/isl_int.h46
-rw-r--r--polly/lib/External/isl/isl_int_gmp.h88
-rw-r--r--polly/lib/External/isl/isl_int_imath.h76
-rw-r--r--polly/lib/External/isl/isl_list_templ.c522
-rw-r--r--polly/lib/External/isl/isl_list_templ.h16
-rw-r--r--polly/lib/External/isl/isl_local_space.c1363
-rw-r--r--polly/lib/External/isl/isl_local_space_private.h75
-rw-r--r--polly/lib/External/isl/isl_lp.c362
-rw-r--r--polly/lib/External/isl/isl_lp_private.h21
-rw-r--r--polly/lib/External/isl/isl_map.c12888
-rw-r--r--polly/lib/External/isl/isl_map_lexopt_templ.c142
-rw-r--r--polly/lib/External/isl/isl_map_private.h408
-rw-r--r--polly/lib/External/isl/isl_map_simplify.c3257
-rw-r--r--polly/lib/External/isl/isl_map_subtract.c900
-rw-r--r--polly/lib/External/isl/isl_map_to_basic_set.c10
-rw-r--r--polly/lib/External/isl/isl_mat.c1742
-rw-r--r--polly/lib/External/isl/isl_mat_private.h46
-rw-r--r--polly/lib/External/isl/isl_morph.c917
-rw-r--r--polly/lib/External/isl/isl_morph.h86
-rw-r--r--polly/lib/External/isl/isl_multi_templ.c1498
-rw-r--r--polly/lib/External/isl/isl_multi_templ.h18
-rw-r--r--polly/lib/External/isl/isl_obj.c335
-rw-r--r--polly/lib/External/isl/isl_options.c305
-rw-r--r--polly/lib/External/isl/isl_options_private.h67
-rw-r--r--polly/lib/External/isl/isl_output.c2698
-rw-r--r--polly/lib/External/isl/isl_point.c585
-rw-r--r--polly/lib/External/isl/isl_point_private.h12
-rw-r--r--polly/lib/External/isl/isl_polynomial.c4866
-rw-r--r--polly/lib/External/isl/isl_polynomial_private.h253
-rw-r--r--polly/lib/External/isl/isl_power_templ.c81
-rw-r--r--polly/lib/External/isl/isl_printer.c449
-rw-r--r--polly/lib/External/isl/isl_printer_private.h18
-rw-r--r--polly/lib/External/isl/isl_pw_templ.c2100
-rw-r--r--polly/lib/External/isl/isl_range.c491
-rw-r--r--polly/lib/External/isl/isl_range.h6
-rw-r--r--polly/lib/External/isl/isl_reordering.c205
-rw-r--r--polly/lib/External/isl/isl_reordering.h31
-rw-r--r--polly/lib/External/isl/isl_sample.c1301
-rw-r--r--polly/lib/External/isl/isl_sample.h35
-rw-r--r--polly/lib/External/isl/isl_scan.c324
-rw-r--r--polly/lib/External/isl/isl_scan.h24
-rw-r--r--polly/lib/External/isl/isl_schedule.c672
-rw-r--r--polly/lib/External/isl/isl_schedule_private.h44
-rw-r--r--polly/lib/External/isl/isl_scheduler.c4148
-rw-r--r--polly/lib/External/isl/isl_seq.c321
-rw-r--r--polly/lib/External/isl/isl_seq.h60
-rw-r--r--polly/lib/External/isl/isl_set_list.c21
-rw-r--r--polly/lib/External/isl/isl_sort.c157
-rw-r--r--polly/lib/External/isl/isl_sort.h9
-rw-r--r--polly/lib/External/isl/isl_space.c2379
-rw-r--r--polly/lib/External/isl/isl_space_private.h60
-rw-r--r--polly/lib/External/isl/isl_stream.c778
-rw-r--r--polly/lib/External/isl/isl_stream_private.h21
-rw-r--r--polly/lib/External/isl/isl_tab.c3509
-rw-r--r--polly/lib/External/isl/isl_tab.h304
-rw-r--r--polly/lib/External/isl/isl_tab_pip.c5681
-rw-r--r--polly/lib/External/isl/isl_tarjan.c138
-rw-r--r--polly/lib/External/isl/isl_tarjan.h40
-rw-r--r--polly/lib/External/isl/isl_test.c5176
-rw-r--r--polly/lib/External/isl/isl_transitive_closure.c2981
-rw-r--r--polly/lib/External/isl/isl_union_map.c3373
-rw-r--r--polly/lib/External/isl/isl_union_map_private.h10
-rw-r--r--polly/lib/External/isl/isl_union_templ.c1107
-rw-r--r--polly/lib/External/isl/isl_val.c1624
-rw-r--r--polly/lib/External/isl/isl_val_gmp.c128
-rw-r--r--polly/lib/External/isl/isl_val_imath.c64
-rw-r--r--polly/lib/External/isl/isl_val_private.h70
-rw-r--r--polly/lib/External/isl/isl_vec.c579
-rw-r--r--polly/lib/External/isl/isl_vec_private.h24
-rw-r--r--polly/lib/External/isl/isl_version.c14
-rw-r--r--polly/lib/External/isl/isl_vertices.c1578
-rw-r--r--polly/lib/External/isl/isl_vertices_private.h64
-rw-r--r--polly/lib/External/isl/m4/ax_c___attribute__.m466
-rw-r--r--polly/lib/External/isl/m4/ax_cc_maxopt.m4188
-rw-r--r--polly/lib/External/isl/m4/ax_cflags_warn_all.m4149
-rw-r--r--polly/lib/External/isl/m4/ax_check_compiler_flags.m474
-rw-r--r--polly/lib/External/isl/m4/ax_compiler_vendor.m463
-rw-r--r--polly/lib/External/isl/m4/ax_create_pkgconfig_info.m4351
-rw-r--r--polly/lib/External/isl/m4/ax_create_stdint_h.m4739
-rw-r--r--polly/lib/External/isl/m4/ax_detect_git_head.m432
-rw-r--r--polly/lib/External/isl/m4/ax_detect_gmp.m448
-rw-r--r--polly/lib/External/isl/m4/ax_detect_imath.m415
-rw-r--r--polly/lib/External/isl/m4/ax_gcc_archflag.m4213
-rw-r--r--polly/lib/External/isl/m4/ax_gcc_warn_unused_result.m456
-rw-r--r--polly/lib/External/isl/m4/ax_gcc_x86_cpuid.m477
-rw-r--r--polly/lib/External/isl/m4/ax_set_warning_flags.m417
-rw-r--r--polly/lib/External/isl/m4/ax_submodule.m471
-rw-r--r--polly/lib/External/isl/mp_get_memory_functions.c14
-rw-r--r--polly/lib/External/isl/pip.c382
-rwxr-xr-xpolly/lib/External/isl/pip_test.sh.in28
-rw-r--r--polly/lib/External/isl/polyhedron_detect_equalities.c24
-rw-r--r--polly/lib/External/isl/polyhedron_minimize.c105
-rw-r--r--polly/lib/External/isl/polyhedron_sample.c36
-rw-r--r--polly/lib/External/isl/polytope_scan.c104
-rw-r--r--polly/lib/External/isl/print.c100
-rw-r--r--polly/lib/External/isl/print_templ.c33
-rw-r--r--polly/lib/External/isl/test_inputs/affine.polylib9
-rw-r--r--polly/lib/External/isl/test_inputs/affine2.polylib9
-rw-r--r--polly/lib/External/isl/test_inputs/affine3.polylib7
-rw-r--r--polly/lib/External/isl/test_inputs/application.omega3
-rw-r--r--polly/lib/External/isl/test_inputs/application2.omega3
-rw-r--r--polly/lib/External/isl/test_inputs/basicLinear.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/basicLinear2.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/basicTest.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/boulet.pip13
-rw-r--r--polly/lib/External/isl/test_inputs/brisebarre.pip34
-rw-r--r--polly/lib/External/isl/test_inputs/cg1.pip15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic2.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic3.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic3.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic4.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/atomic4.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/4-param.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/4-param.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/README2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block2.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block3.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/block3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c18
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c20
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/christian.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/christian.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/classen.c86
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/classen.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/classen2.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/classen2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/constant.c18
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/constant.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/constbound.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/constbound.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/darte.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/darte.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dealII.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dealII.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dot.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dot.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dot2.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/dot2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c23
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/emploi.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/emploi.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/equality.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/equality.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/equality2.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/equality2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/esced.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/esced.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/ex1.c15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/ex1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/faber.c155
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/faber.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gauss.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gauss.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.c20
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/guide.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/guide.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/iftest.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/iftest.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/largeur.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/largeur.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c32
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lex.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lex.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/logo.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/logo.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/logopar.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/logopar.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lu.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lu.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lu2.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lu2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lux.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/lux.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/merge.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/merge.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod3.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod4.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mod4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mode.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mode.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/orc.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/orc.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/otl.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/otl.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/param-split.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/param-split.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c54
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c85
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c18
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c33
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/singleton.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/singleton.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride2.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride3.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride4.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/stride4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/swim.c159
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/swim.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/test.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/test.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/tiling.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/tiling.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/union.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/union.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/unroll.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/unroll.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.c348
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.c23
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vivien.c85
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vivien.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.c77
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters.c15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters2.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters3.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/walters3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/yosr.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/yosr.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/youcef.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/youcef.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/disjuncts.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/disjuncts.in7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/dwt.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/dwt.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/empty.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/empty.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/hoist.c45
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/hoist.in10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/hoist2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/hoist2.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/lu.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/lu.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/mod.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/mod.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/README5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/basics-0.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/basics-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/basics-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/basics-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.c15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/collard-0.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/collard-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gc-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gc-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ge-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ge-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ge-1.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ge-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-3.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-4.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-5.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/gist-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.c15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.c16
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.c18
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.c20
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.c22
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.c22
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-0.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-1.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-2.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-3.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m1-0.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m1-1.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m10-0.c7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m10-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m10-1.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m10-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m11-0.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m11-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m12-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m12-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m12-1.c25
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m12-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m2-0.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m2-1.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m2-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m3-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m3-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m4-0.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m4-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m4-1.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m4-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m7-0.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m7-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m7-1.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m7-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m8-0.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m8-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m8-1.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m8-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m9-0.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m9-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m9-1.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/m9-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/olda-0.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/olda-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/olda-1.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/olda-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p6-0.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p6-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p6-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/p6-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.c1
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.c13
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c35
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.c27
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.c55
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.c26
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.c35
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.c21
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/x-0.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/x-0.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/x-1.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/omega/x-1.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/README2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.c12
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/roman.c32
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/roman.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separate.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separate.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separate2.c9
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separate2.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class.c17
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class.in6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class2.c15
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class2.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class3.c29
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class3.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class4.c20
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/separation_class4.in10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift2.c43
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift2.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift_unroll.c14
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/shift_unroll.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/single_valued.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/single_valued.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride.in6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride5.c3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride5.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride6.c4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride6.in3
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride7.c6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/stride7.in7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll.c5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll10.c29
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll10.in4
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll2.c11
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll2.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll3.c2
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll3.in6
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll4.c22
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll4.in5
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll6.c8
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll6.in7
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll7.c10
-rw-r--r--polly/lib/External/isl/test_inputs/codegen/unroll7.in5
-rw-r--r--polly/lib/External/isl/test_inputs/convex0.polylib11
-rw-r--r--polly/lib/External/isl/test_inputs/convex1.polylib17
-rw-r--r--polly/lib/External/isl/test_inputs/convex10.polylib17
-rw-r--r--polly/lib/External/isl/test_inputs/convex11.polylib14
-rw-r--r--polly/lib/External/isl/test_inputs/convex12.polylib12
-rw-r--r--polly/lib/External/isl/test_inputs/convex13.polylib17
-rw-r--r--polly/lib/External/isl/test_inputs/convex14.polylib14
-rw-r--r--polly/lib/External/isl/test_inputs/convex15.polylib66
-rw-r--r--polly/lib/External/isl/test_inputs/convex2.polylib24
-rw-r--r--polly/lib/External/isl/test_inputs/convex3.polylib10
-rw-r--r--polly/lib/External/isl/test_inputs/convex4.polylib9
-rw-r--r--polly/lib/External/isl/test_inputs/convex5.polylib12
-rw-r--r--polly/lib/External/isl/test_inputs/convex6.polylib17
-rw-r--r--polly/lib/External/isl/test_inputs/convex7.polylib9
-rw-r--r--polly/lib/External/isl/test_inputs/convex8.polylib24
-rw-r--r--polly/lib/External/isl/test_inputs/convex9.polylib14
-rw-r--r--polly/lib/External/isl/test_inputs/devos.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/equality1.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/equality2.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/equality3.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/equality4.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/equality5.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/esced.pip27
-rw-r--r--polly/lib/External/isl/test_inputs/ex.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/ex2.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/faddeev.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/fimmel.pip12
-rw-r--r--polly/lib/External/isl/test_inputs/gist1.polylib14
-rw-r--r--polly/lib/External/isl/test_inputs/linearExample.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/max.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/neg.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/negative.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/philippe.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/philippe3vars.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/philippe3vars3pars.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/philippeNeg.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/philippePolynomialCoeff.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/philippePolynomialCoeff1P.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/product.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/seghir-vd.pip17
-rw-r--r--polly/lib/External/isl/test_inputs/set.omega1
-rw-r--r--polly/lib/External/isl/test_inputs/small.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/sor1d.pip28
-rw-r--r--polly/lib/External/isl/test_inputs/split.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/square.pip9
-rw-r--r--polly/lib/External/isl/test_inputs/sven.pip7
-rw-r--r--polly/lib/External/isl/test_inputs/test3Deg3Var.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/tobi.pip15
-rw-r--r--polly/lib/External/isl/test_inputs/toplas.pwqp1
-rw-r--r--polly/lib/External/isl/test_inputs/unexpanded.pwqp1
-rw-r--r--polly/lib/Makefile80
1025 files changed, 177286 insertions, 242 deletions
diff --git a/polly/CMakeLists.txt b/polly/CMakeLists.txt
index 6e72fbabfc6..76919181ada 100644
--- a/polly/CMakeLists.txt
+++ b/polly/CMakeLists.txt
@@ -76,23 +76,29 @@ endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
+# Define the FLAGS for the compilation of isl and imath
+#
+# Those are the only C files we have in the repository. Hence, we can just use
+# the CFLAGS to identify them.
+#
+# We first set the visibility of all isl functions to hidden to ensure we do
+# not clash with other isl versions that got linked into a program that uses
+# Polly. (This happens e.g when linking Polly with dragonegg)
+#
+# We also disable all warnings, as these should be fixed upstream. There is
+# no value in reporting them here.
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden -w")
+
# Add path for custom modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${POLLY_SOURCE_DIR}/cmake")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
-FIND_PACKAGE(Isl REQUIRED)
-set(POLLY_LINK_LIBS ${ISL_LIBRARY})
-
FIND_PACKAGE(Pluto)
if(PLUTO_FOUND)
set(POLLY_LINK_LIBS ${POLLY_LINK_LIBS} ${PLUTO_LIBRARY})
endif(PLUTO_FOUND)
-if(GMP_FOUND)
- set(POLLY_LINK_LIBS ${POLLY_LINK_LIBS} ${GMP_LIBRARY})
-endif(GMP_FOUND)
-
option(POLLY_ENABLE_GPGPU_CODEGEN "Enable GPGPU code generation feature" OFF)
if (POLLY_ENABLE_GPGPU_CODEGEN)
# Do not require CUDA, as GPU code generation test cases can be run without
@@ -118,6 +124,9 @@ include_directories(
BEFORE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_CURRENT_SOURCE_DIR}/lib/JSON/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/External/isl/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/External/isl/imath
+ ${CMAKE_CURRENT_SOURCE_DIR}/lib/External/isl
${CMAKE_CURRENT_BINARY_DIR}/include
)
@@ -151,7 +160,10 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/polly/Config/config.h.cmake
# Add target to check formatting of polly files
file( GLOB_RECURSE files *.h *.cpp)
file( GLOB_RECURSE jsonfiles lib/JSON/*.h lib/JSON/*.cpp)
-list( REMOVE_ITEM files ${jsonfiles} )
+file( GLOB_RECURSE islfiles lib/External/isl/*.h lib/External/isl/*.c
+ lib/External/isl/include/isl/*.h lib/External/isl/imath/*.h
+ lib/External/isl/imath/*.c)
+list( REMOVE_ITEM files ${jsonfiles} ${islfiles})
add_custom_command( OUTPUT formatting COMMAND
CLANG_FORMAT=${LLVM_BINARY_DIR}/bin/clang-format
${CMAKE_CURRENT_SOURCE_DIR}/utils/check_format.sh ${files})
diff --git a/polly/Makefile.config.in b/polly/Makefile.config.in
index c84be0baea7..fed157a3f28 100644
--- a/polly/Makefile.config.in
+++ b/polly/Makefile.config.in
@@ -28,13 +28,30 @@ endif
POLLY_CXXFLAGS += "-fno-rtti -fno-exceptions"
+# Define the FLAGS for the compilation of isl and imath
+#
+# Those are the only C files we have in the repository. Hence, we can just use
+# the CFLAGS to identify them.
+#
+# We first set the visibility of all isl functions to hidden to ensure we do
+# not clash with other isl versions that got linked into a program that uses
+# Polly. (This happens e.g when linking Polly with dragonegg)
+#
+# We also disable all warnings, as these should be fixed upstream. There is
+# no value in reporting them here.
+POLLY_CFLAGS := -fvisibility=hidden
+POLLY_CFLAGS += -w
+
PLUTO_FOUND := @pluto_found@
CUDALIB_FOUND := @cuda_found@
-# Set include directroys
-POLLY_INC := @gmp_inc@ @isl_inc@ @cuda_inc@\
- @pluto_inc@ -I$(POLLY_SRC_ROOT)/lib/JSON/include
+# Set include directories
+POLLY_INC := @cuda_inc@ \
+ @pluto_inc@ -I$(POLLY_SRC_ROOT)/lib/JSON/include \
+ -I$(POLLY_SRC_ROOT)/lib/External/isl/include \
+ -I$(POLLY_SRC_ROOT)/lib/External/isl/imath \
+ -I$(POLLY_SRC_ROOT)/lib/External/isl
-POLLY_LD := @gmp_ld@ @isl_ld@ @cuda_ld@ @pluto_ld@
+POLLY_LD := @cuda_ld@ @pluto_ld@
-POLLY_LIB := @gmp_lib@ @isl_lib@ @cuda_lib@ @pluto_lib@
+POLLY_LIB := @cuda_lib@ @pluto_lib@
diff --git a/polly/autoconf/aclocal.m4 b/polly/autoconf/aclocal.m4
index d5030643642..07893d5893b 100644
--- a/polly/autoconf/aclocal.m4
+++ b/polly/autoconf/aclocal.m4
@@ -1,8 +1,7 @@
-# generated automatically by aclocal 1.11.6 -*- Autoconf -*-
+# generated automatically by aclocal 1.14.1 -*- Autoconf -*-
+
+# Copyright (C) 1996-2013 Free Software Foundation, Inc.
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
-# Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -12,6 +11,7 @@
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
+m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
dnl find_lib_and_headers(name, verify-header, library-name, requirded?)
dnl Export
dnl name_inc in -I"include-path" form
diff --git a/polly/autoconf/configure.ac b/polly/autoconf/configure.ac
index 15008f8c064..0fd7103537a 100644
--- a/polly/autoconf/configure.ac
+++ b/polly/autoconf/configure.ac
@@ -72,18 +72,10 @@ dnl **************************************************************************
dnl **************************************************************************
dnl * Set the location of various third-party software packages
dnl **************************************************************************
-dnl Find Gmp
-find_lib_and_headers([gmp], [gmp.h], [gmp])
-
-dnl Find Isl
-saved_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="$CXXFLAGS"
-find_lib_and_headers([isl], [isl/val.h], [isl], [required])
-CXXFLAGS=$saved_CXXFLAGS
dnl Check that we have libpluto.
saved_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="$CXXFLAGS $gmp_inc $isl_inc"
+CXXFLAGS="$CXXFLAGS"
find_lib_and_headers([pluto], [pluto/libpluto.h], [pluto])
CXXFLAGS=$saved_CXXFLAGS
AS_IF([test "x$pluto_found" = "xyes"],
diff --git a/polly/cmake/FindGmp.cmake b/polly/cmake/FindGmp.cmake
deleted file mode 100644
index 60def58152c..00000000000
--- a/polly/cmake/FindGmp.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-FIND_PATH(GMP_INCLUDE_DIR gmp.h)
-
-FIND_LIBRARY(GMP_LIBRARY NAMES gmp)
-
-IF (GMP_INCLUDE_DIR AND GMP_LIBRARY)
- SET(GMP_FOUND TRUE)
-ENDIF (GMP_INCLUDE_DIR AND GMP_LIBRARY)
-
-
-IF (GMP_FOUND)
- IF (NOT GMP_FIND_QUIETLY)
- MESSAGE(STATUS "Found GMP: ${GMP_LIBRARY}")
- ENDIF (NOT GMP_FIND_QUIETLY)
-ELSE (GMP_FOUND)
- IF (GMP_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find GMP")
- ENDIF (GMP_FIND_REQUIRED)
-ENDIF (GMP_FOUND)
-
diff --git a/polly/cmake/FindIsl.cmake b/polly/cmake/FindIsl.cmake
deleted file mode 100644
index 1c46e72454a..00000000000
--- a/polly/cmake/FindIsl.cmake
+++ /dev/null
@@ -1,19 +0,0 @@
-FIND_PATH(ISL_INCLUDE_DIR isl/val.h)
-
-FIND_LIBRARY(ISL_LIBRARY NAMES isl)
-
-IF (ISL_INCLUDE_DIR AND ISL_LIBRARY)
- SET(ISL_FOUND TRUE)
-ENDIF (ISL_INCLUDE_DIR AND ISL_LIBRARY)
-
-
-IF (ISL_FOUND)
- IF (NOT Isl_FIND_QUIETLY)
- MESSAGE(STATUS "Found Isl: ${ISL_LIBRARY}")
- ENDIF (NOT Isl_FIND_QUIETLY)
-ELSE (ISL_FOUND)
- IF (Isl_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find Isl")
- ENDIF (Isl_FIND_REQUIRED)
-ENDIF (ISL_FOUND)
-
diff --git a/polly/configure b/polly/configure
index 591ee39f3b6..8e324391dd8 100755
--- a/polly/configure
+++ b/polly/configure
@@ -595,14 +595,6 @@ pluto_ld
pluto_lib
pluto_inc
pluto_found
-isl_ld
-isl_lib
-isl_inc
-isl_found
-gmp_ld
-gmp_lib
-gmp_inc
-gmp_found
OBJEXT
EXEEXT
ac_ct_CXX
@@ -655,8 +647,6 @@ ac_user_opts='
enable_option_checking
with_llvmsrc
with_llvmobj
-with_gmp
-with_isl
with_pluto
enable_polly_gpu_codegen
with_cuda
@@ -1287,8 +1277,6 @@ Optional Packages:
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--with-llvmsrc Location of LLVM Source Code
--with-llvmobj Location of LLVM Object Code
- --with-gmp prefix of gmp
- --with-isl prefix of isl
--with-pluto prefix of pluto
--with-cuda prefix of cuda
@@ -1899,8 +1887,8 @@ fi
-
-
+saved_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="$CXXFLAGS"
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -2420,169 +2408,6 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
OLD_LDFLAGS=$LDFLAGS;
OLD_LIBS=$LIBS;
- LIBS="$LIBS -lgmp";
-
- # Get include path and lib path
-
-# Check whether --with-gmp was given.
-if test "${with_gmp+set}" = set; then :
- withval=$with_gmp; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
- given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
-else
- given_inc_path=inc_not_give_gmp;
- given_lib_path=lib_not_give_gmp
-
-fi
-
- # Check for library and headers works
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gmp: gmp.h in $given_inc_path, and libgmp in $given_lib_path" >&5
-$as_echo_n "checking for gmp: gmp.h in $given_inc_path, and libgmp in $given_lib_path... " >&6; }
-
- # try to compile a file that includes a header of the library
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <gmp.h>
-int
-main ()
-{
-;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
-$as_echo "ok" >&6; }
- gmp_found="yes"
-
- if test "x$given_inc_path" != "xinc_not_give_gmp"; then :
- gmp_inc="-I$given_inc_path"
-
-fi
- gmp_lib="-lgmp"
-
- if test "x$given_lib_path" != "xlib_not_give_gmp"; then :
- gmp_ld="-L$given_lib_path"
-
-fi
-else
- if test "x" = "xrequired"; then :
- as_fn_error $? "gmp required but not found" "$LINENO" 5
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
-fi
-
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
- # reset original CXXFLAGS
- CXXFLAGS=$OLD_CXXFLAGS
- LDFLAGS=$OLD_LDFLAGS;
- LIBS=$OLD_LIBS
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-
-saved_CXXFLAGS=$CXXFLAGS
-CXXFLAGS="$CXXFLAGS"
-
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- OLD_CXXFLAGS=$CXXFLAGS;
- OLD_LDFLAGS=$LDFLAGS;
- OLD_LIBS=$LIBS;
-
- LIBS="$LIBS -lisl";
-
- # Get include path and lib path
-
-# Check whether --with-isl was given.
-if test "${with_isl+set}" = set; then :
- withval=$with_isl; given_inc_path="$withval/include"; CXXFLAGS="-I$given_inc_path $CXXFLAGS";
- given_lib_path="$withval/lib"; LDFLAGS="-L$given_lib_path $LDFLAGS"
-else
- given_inc_path=inc_not_give_isl;
- given_lib_path=lib_not_give_isl
-
-fi
-
- # Check for library and headers works
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for isl: isl/val.h in $given_inc_path, and libisl in $given_lib_path" >&5
-$as_echo_n "checking for isl: isl/val.h in $given_inc_path, and libisl in $given_lib_path... " >&6; }
-
- # try to compile a file that includes a header of the library
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <isl/val.h>
-int
-main ()
-{
-;
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_link "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
-$as_echo "ok" >&6; }
- isl_found="yes"
-
- if test "x$given_inc_path" != "xinc_not_give_isl"; then :
- isl_inc="-I$given_inc_path"
-
-fi
- isl_lib="-lisl"
-
- if test "x$given_lib_path" != "xlib_not_give_isl"; then :
- isl_ld="-L$given_lib_path"
-
-fi
-else
- if test "xrequired" = "xrequired"; then :
- as_fn_error $? "isl required but not found" "$LINENO" 5
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
-$as_echo "not found" >&6; }
-fi
-
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-
- # reset original CXXFLAGS
- CXXFLAGS=$OLD_CXXFLAGS
- LDFLAGS=$OLD_LDFLAGS;
- LIBS=$OLD_LIBS
- ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-
-CXXFLAGS=$saved_CXXFLAGS
-CXXFLAGS="$CXXFLAGS $gmp_inc $isl_inc"
-
- ac_ext=cpp
-ac_cpp='$CXXCPP $CPPFLAGS'
-ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
-
- OLD_CXXFLAGS=$CXXFLAGS;
- OLD_LDFLAGS=$LDFLAGS;
- OLD_LIBS=$LIBS;
-
LIBS="$LIBS -lpluto";
# Get include path and lib path
diff --git a/polly/lib/CMakeLists.txt b/polly/lib/CMakeLists.txt
index 96254580496..6e9a8ba534b 100644
--- a/polly/lib/CMakeLists.txt
+++ b/polly/lib/CMakeLists.txt
@@ -20,6 +20,85 @@ if (GPU_CODEGEN)
CodeGen/PTXGenerator.cpp)
endif (GPU_CODEGEN)
+set (ISL_FILES
+ External/isl/basis_reduction_tab.c
+ External/isl/isl_aff.c
+ External/isl/isl_affine_hull.c
+ External/isl/isl_arg.c
+ External/isl/isl_ast_build.c
+ External/isl/isl_ast_build_expr.c
+ External/isl/isl_ast.c
+ External/isl/isl_ast_codegen.c
+ External/isl/isl_ast_graft.c
+ External/isl/isl_band.c
+ External/isl/isl_bernstein.c
+ External/isl/isl_blk.c
+ External/isl/isl_bound.c
+ External/isl/isl_coalesce.c
+ External/isl/isl_constraint.c
+ External/isl/isl_convex_hull.c
+ External/isl/isl_ctx.c
+ External/isl/isl_deprecated.c
+ External/isl/isl_dim.c
+ External/isl/isl_dim_map.c
+ External/isl/isl_equalities.c
+ External/isl/isl_factorization.c
+ External/isl/isl_farkas.c
+ External/isl/isl_flow.c
+ External/isl/isl_fold.c
+ External/isl/isl_hash.c
+ External/isl/isl_id.c
+ External/isl/isl_id_to_ast_expr.c
+ External/isl/isl_id_to_pw_aff.c
+ External/isl/isl_ilp.c
+ External/isl/isl_imath.c
+ External/isl/isl_input.c
+ External/isl/isl_local_space.c
+ External/isl/isl_lp.c
+ External/isl/isl_map.c
+ External/isl/isl_map_simplify.c
+ External/isl/isl_map_subtract.c
+ External/isl/isl_map_to_basic_set.c
+ External/isl/isl_mat.c
+ External/isl/isl_morph.c
+ External/isl/isl_obj.c
+ External/isl/isl_options.c
+ External/isl/isl_output.c
+ External/isl/isl_point.c
+ External/isl/isl_polynomial.c
+ External/isl/isl_printer.c
+ External/isl/isl_range.c
+ External/isl/isl_reordering.c
+ External/isl/isl_sample.c
+ External/isl/isl_scan.c
+ External/isl/isl_schedule.c
+ External/isl/isl_scheduler.c
+ External/isl/isl_seq.c
+ External/isl/isl_set_list.c
+ External/isl/isl_sort.c
+ External/isl/isl_space.c
+ External/isl/isl_stream.c
+ External/isl/isl_tab.c
+ External/isl/isl_tab_pip.c
+ External/isl/isl_tarjan.c
+ External/isl/isl_transitive_closure.c
+ External/isl/isl_union_map.c
+ External/isl/isl_val.c
+ External/isl/isl_val_imath.c
+ External/isl/isl_vec.c
+ External/isl/isl_version.c
+ External/isl/isl_vertices.c
+ External/isl/print.c
+ External/isl/imath/gmp_compat.c
+ External/isl/imath/imath.c
+ External/isl/imath/imdrover.c
+ External/isl/imath/imrat.c
+ External/isl/imath/iprime.c
+ External/isl/imath/pi.c
+ External/isl/imath/rsamath.c
+ )
+
+
add_polly_library(Polly
Analysis/Dependences.cpp
Analysis/ScopDetection.cpp
@@ -47,6 +126,7 @@ add_polly_library(Polly
Transform/IndependentBlocks.cpp
Transform/ScheduleOptimizer.cpp
${POLLY_PLUTO_FILES}
+ ${ISL_FILES}
)
# Build a monolithic Polly.a and a thin module LLVMPolly.moduleext that links to
diff --git a/polly/lib/External/README.txt b/polly/lib/External/README.txt
new file mode 100644
index 00000000000..81ef08f767b
--- /dev/null
+++ b/polly/lib/External/README.txt
@@ -0,0 +1,17 @@
+The libraries in this directory are mirrored from external projects.
+
+Patches to them should first be contributed upstream and then return to Polly
+as normal (re)imports of these updated libraries.
+
+We currently have the following external libraries.
+
+# isl
+License: MIT-STYLE
+Details: isl/LICENSE
+Version: b3e0fa7a05d
+
+# imath
+License: MIT-STYLE
+Details: isl/imath/LICENSE
+Version: 4d707e5ef2
+
diff --git a/polly/lib/External/isl/.gitignore b/polly/lib/External/isl/.gitignore
new file mode 100644
index 00000000000..b2fd552a482
--- /dev/null
+++ b/polly/lib/External/isl/.gitignore
@@ -0,0 +1,53 @@
+# ignore objects and archives
+*.[oa]
+*.lo
+*.la
+
+.deps/
+.libs/
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+config.guess
+isl_config.h.in
+isl_config.h.in~
+compile
+config.log
+config.status
+config.sub
+configure
+depcomp
+doc/Makefile
+doc/Makefile.in
+include/isl/config.h
+include/isl/stdint.h
+include/stamp-h2
+include/isl/stamp-h2
+install-sh
+isl-uninstalled.pc
+isl-uninstalled.sh
+isl.pc
+isl.pc.in
+isl_bound
+isl_cat
+isl_closure
+isl_pip
+isl_polyhedron_detect_equalities
+isl_polyhedron_minimize
+isl_polyhedron_sample
+isl_polytope_scan
+isl_test
+libtool
+ltmain.sh
+m4/libtool.m4
+m4/ltoptions.m4
+m4/ltsugar.m4
+m4/ltversion.m4
+m4/lt~obsolete.m4
+missing
+stamp-h1
+test-driver
+
+bound_test.sh
+pip_test.sh
diff --git a/polly/lib/External/isl/AUTHORS b/polly/lib/External/isl/AUTHORS
new file mode 100644
index 00000000000..a08f5b12fb0
--- /dev/null
+++ b/polly/lib/External/isl/AUTHORS
@@ -0,0 +1,42 @@
+isl was written by
+
+ Sven Verdoolaege
+2006-2007 Leiden Institute of Advanced Computer Science
+ Universiteit Leiden
+ Niels Bohrweg 1
+ 2333 CA Leiden
+ The Netherlands
+2008-2009 K.U.Leuven
+ Departement Computerwetenschappen
+ Celestijnenlaan 200A
+ B-3001 Leuven
+ Belgium
+2010-2011 INRIA Saclay - Ile-de-France
+ Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod
+ 91893 Orsay
+ France
+2011-2012 consultant for Leiden Institute of Advanced Computer Science
+2012-2014 Ecole Normale Superieure
+ 45 rue d'Ulm, 75230 Paris
+ France
+2014 INRIA Rocquencourt
+ Domaine de Voluceau - Rocquencourt, B.P. 105
+ 78153 Le Chesnay
+ France
+
+Contributions by
+
+Mythri Alle
+Riyadh Baghdadi
+Serge Belyshev
+Ray Donnelly
+Johannes Doerfert
+Tobias Grosser
+Alexandre Isoard
+Andreas Kloeckner
+Sebastian Pop
+Louis-Noel Pouchet
+Uday Kumar Reddy
+Sven van Haastregt
+
+The merge sort implementation was written by Jeffrey Stedfast.
diff --git a/polly/lib/External/isl/ChangeLog b/polly/lib/External/isl/ChangeLog
new file mode 100644
index 00000000000..a802e45909a
--- /dev/null
+++ b/polly/lib/External/isl/ChangeLog
@@ -0,0 +1,134 @@
+version: 0.14
+date: Sat Oct 25 16:08:47 CEST 2014
+changes:
+ - support IMath as an optional replacement for GMP
+ - minor AST generator improvements
+---
+version: 0.13
+date: Mon Apr 14 11:08:45 CEST 2014
+changes:
+ - deprecate isl_int
+ - improved support for multi piecewise quasi-affine expressions
+ - allow the user to impose a bound on the number of low-level operations
+ - add isl_id_to_ast_expr and isl_id_to_pw_aff
+ - add isl_schedule_constraints
+ - hide internal structure of isl_vec
+ - remove support for piplib
+---
+version: 0.12.2
+date: Sun Jan 12 12:09:46 CET 2014
+changes:
+ - MinGW-w64 build fix
+ - fix simplification bug
+---
+version: 0.12.1
+date: Wed Jul 24 12:54:46 CEST 2013
+changes:
+ - handle malloc returning NULL on zero-size allocation
+ - fix regression in AST generator
+---
+version: 0.12
+date: Sun Jun 23 20:23:05 CEST 2013
+changes:
+ - add isl_val abstraction
+---
+version: 0.11.2
+date: Tue Apr 9 18:45:10 CEST 2013
+changes:
+ - make code generation output the same on Solaris
+ - fix some hard to trigger bugs
+---
+version: 0.11.1
+date: Mon Dec 10 11:55:30 CET 2012
+changes:
+ - add LICENSE file to distribution
+ - make code generation output independent of endianness
+---
+version: 0.11
+date: Mon Dec 3 08:17:18 CET 2012
+changes:
+ - change license from LGPL 2.1 to MIT
+ - add support for multi piecewise quasi-affine expressions
+ - add code generation
+ - various minor bug fixes
+---
+version: 0.10
+date: Sun Jun 3 18:00:16 CEST 2012
+changes:
+ - support for interaction with dependence analysis
+ - add public API for vectors
+ - improved support for (piecewise) multi quasi-affine expressions
+ - various minor bug fixes
+---
+version: 0.09
+date: Sat Dec 17 18:19:26 CET 2011
+changes:
+ - improved argument parsing
+ - hide internal structure of isl_options
+ - improved support for parameter sets
+ - configurable scheduling
+---
+version: 0.08
+date: Fri Oct 21 12:36:20 CEST 2011
+changes:
+ - improved parsing
+ - drop isl_div abstraction
+ - rename isl_dim to isl_space
+ - |-
+ explicitly differentiate between spaces of maps,
+ sets and parameter sets
+ - add support for identifiers
+ - add support for (piecewise) multi quasi-affine expressions
+ - preliminary Python bindings
+---
+version: 0.07
+date: Tue Jul 12 19:34:51 CEST 2011
+changes:
+ - hide internal structures of isl_div and isl_constraint
+ - preliminary scheduling
+ - add support for local spaces and (piecewise) quasi-affine expressions
+---
+version: 0.06
+date: Fri Mar 18 15:59:16 CET 2011
+changes:
+ - improved parsing
+ - consistency changes in API
+ - hide internal structure of isl_ctx
+---
+version: 0.05.1
+date: Wed Jan 5 10:21:42 CET 2011
+changes:
+ - fix simple symmetry detection in parametric integer programming
+---
+version: 0.05
+date: Thu Dec 23 17:03:14 CET 2010
+changes:
+ - rename header files from isl_header.h to isl/header.h
+ - add higher level interface for dependence analysis
+ - improved argument parsing
+ - optionally triangulate domains during Bernstein expansion
+ - support extended PolyLib format
+ - hide internal structure of some data types
+ - improved coalescing
+ - add simple symmetry detection in parametric integer programming
+---
+version: 0.04
+date: Fri Sep 10 12:57:50 CEST 2010
+changes:
+ - rename isl_pw_qpolynomial_fold_add
+ - add isl_map_apply_pw_qpolynomial_fold
+ - support named and nested spaces
+ - support union sets and maps
+ - add public API for matrices
+---
+version: 0.03
+date: Tue Jun 29 13:16:46 CEST 2010
+changes:
+ - new printing functions
+ - support for "may" accesses in dependence analysis
+ - improved coalescing
+ - improved transitive closure
+ - fix several hard to trigger bugs
+ - improved argument parsing
+ - support parametric vertex enumeration for barvinok
+ - optionally use Bernstein expansion to compute bounds
diff --git a/polly/lib/External/isl/LICENSE b/polly/lib/External/isl/LICENSE
new file mode 100644
index 00000000000..e93f5973e00
--- /dev/null
+++ b/polly/lib/External/isl/LICENSE
@@ -0,0 +1,19 @@
+MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/polly/lib/External/isl/Makefile.am b/polly/lib/External/isl/Makefile.am
new file mode 100644
index 00000000000..f975d6a2499
--- /dev/null
+++ b/polly/lib/External/isl/Makefile.am
@@ -0,0 +1,329 @@
+if HAVE_CLANG
+ MAYBE_INTERFACE = interface
+endif
+SUBDIRS = . $(MAYBE_INTERFACE) doc
+DIST_SUBDIRS = $(MAYBE_INTERFACE) doc
+
+ACLOCAL_AMFLAGS = -I m4
+AUTOMAKE_OPTIONS = nostdinc subdir-objects
+
+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
+
+if IMATH_FOR_MP
+
+MP_SRC = \
+ 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
+
+DEPRECATED_SRC =
+MP_INCLUDE_H =
+endif
+
+if GMP_FOR_MP
+if NEED_GET_MEMORY_FUNCTIONS
+GET_MEMORY_FUNCTIONS=mp_get_memory_functions.c
+endif
+
+MP_SRC = \
+ $(GET_MEMORY_FUNCTIONS) \
+ isl_int_gmp.h \
+ isl_gmp.c \
+ isl_val_gmp.c
+
+DEPRECATED_SRC = isl_ast_int.c
+MP_INCLUDE_H = include/isl/val_gmp.h
+endif
+
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(srcdir)/include -Iinclude/ @MP_CPPFLAGS@
+AM_CFLAGS = @WARNING_FLAGS@
+
+libisl_la_SOURCES = \
+ $(MP_SRC) \
+ $(DEPRECATED_SRC) \
+ 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 \
+ isl_ast_graft_private.h \
+ isl_band.c \
+ isl_band_private.h \
+ isl_basis_reduction.h \
+ basis_reduction_tab.c \
+ isl_bernstein.c \
+ isl_bernstein.h \
+ isl_blk.c \
+ isl_blk.h \
+ isl_bound.c \
+ isl_bound.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.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_lp_private.h \
+ isl_map.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_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 \
+ isl_schedule_private.h \
+ isl_scheduler.c \
+ isl_set_list.c \
+ isl_sort.c \
+ isl_sort.h \
+ isl_space.c \
+ isl_space_private.h \
+ isl_stream.c \
+ isl_stream_private.h \
+ isl_seq.c \
+ isl_seq.h \
+ isl_tab.c \
+ isl_tab.h \
+ isl_tab_pip.c \
+ isl_tarjan.c \
+ isl_tarjan.h \
+ isl_transitive_closure.c \
+ isl_union_map.c \
+ isl_union_map_private.h \
+ isl_val.c \
+ isl_val_private.h \
+ isl_vec_private.h \
+ isl_vec.c \
+ isl_version.c \
+ isl_vertices_private.h \
+ isl_vertices.c
+libisl_la_LIBADD = @MP_LIBS@
+libisl_la_LDFLAGS = -version-info @versioninfo@ \
+ @MP_LDFLAGS@
+
+isl_test_LDFLAGS = @MP_LDFLAGS@
+isl_test_LDADD = libisl.la @MP_LIBS@
+
+isl_polyhedron_sample_LDADD = libisl.la
+isl_polyhedron_sample_SOURCES = \
+ polyhedron_sample.c
+
+isl_pip_LDFLAGS = @MP_LDFLAGS@
+isl_pip_LDADD = libisl.la @MP_LIBS@
+isl_pip_SOURCES = \
+ pip.c
+
+isl_codegen_LDFLAGS = @MP_LDFLAGS@
+isl_codegen_LDADD = libisl.la @MP_LIBS@
+isl_codegen_SOURCES = \
+ codegen.c
+
+isl_bound_LDFLAGS = @MP_LDFLAGS@
+isl_bound_LDADD = libisl.la @MP_LIBS@
+isl_bound_SOURCES = \
+ bound.c
+
+isl_polyhedron_minimize_LDFLAGS = @MP_LDFLAGS@
+isl_polyhedron_minimize_LDADD = libisl.la @MP_LIBS@
+isl_polyhedron_minimize_SOURCES = \
+ polyhedron_minimize.c
+
+isl_polytope_scan_LDADD = libisl.la
+isl_polytope_scan_SOURCES = \
+ polytope_scan.c
+
+isl_polyhedron_detect_equalities_LDADD = libisl.la
+isl_polyhedron_detect_equalities_SOURCES = \
+ polyhedron_detect_equalities.c
+
+isl_cat_LDADD = libisl.la
+isl_cat_SOURCES = \
+ cat.c
+
+isl_closure_LDADD = libisl.la
+isl_closure_SOURCES = \
+ closure.c
+
+nodist_pkginclude_HEADERS = \
+ include/isl/stdint.h
+pkginclude_HEADERS = \
+ $(MP_INCLUDE_H) \
+ include/isl/aff.h \
+ include/isl/aff_type.h \
+ include/isl/arg.h \
+ include/isl/ast.h \
+ include/isl/ast_type.h \
+ include/isl/ast_build.h \
+ include/isl/band.h \
+ include/isl/constraint.h \
+ include/isl/ctx.h \
+ include/isl/dim.h \
+ include/isl/flow.h \
+ include/isl/id.h \
+ include/isl/id_to_ast_expr.h \
+ include/isl/id_to_pw_aff.h \
+ include/isl/ilp.h \
+ include/isl/hash.h \
+ include/isl/hmap.h \
+ include/isl/list.h \
+ include/isl/local_space.h \
+ include/isl/lp.h \
+ include/isl/mat.h \
+ include/isl/map.h \
+ include/isl/map_to_basic_set.h \
+ include/isl/map_type.h \
+ include/isl/multi.h \
+ include/isl/obj.h \
+ include/isl/options.h \
+ include/isl/point.h \
+ include/isl/polynomial.h \
+ include/isl/polynomial_type.h \
+ include/isl/printer.h \
+ include/isl/schedule.h \
+ include/isl/set.h \
+ include/isl/set_type.h \
+ include/isl/space.h \
+ include/isl/stream.h \
+ include/isl/union_map.h \
+ include/isl/union_map_type.h \
+ include/isl/union_set.h \
+ include/isl/union_set_type.h \
+ include/isl/val.h \
+ include/isl/vec.h \
+ include/isl/version.h \
+ include/isl/vertices.h
+deprecateddir = $(pkgincludedir)/deprecated
+deprecated_HEADERS = \
+ include/isl/deprecated/int.h \
+ include/isl/deprecated/aff_int.h \
+ include/isl/deprecated/ast_int.h \
+ include/isl/deprecated/constraint_int.h \
+ include/isl/deprecated/ilp_int.h \
+ include/isl/deprecated/map_int.h \
+ include/isl/deprecated/mat_int.h \
+ include/isl/deprecated/point_int.h \
+ include/isl/deprecated/polynomial_int.h \
+ include/isl/deprecated/set_int.h \
+ include/isl/deprecated/union_map_int.h \
+ include/isl/deprecated/val_int.h \
+ include/isl/deprecated/vec_int.h
+
+EXTRA_DIST = \
+ LICENSE \
+ isl_config_post.h \
+ basis_reduction_templ.c \
+ isl_hmap_templ.c \
+ isl_list_templ.c \
+ isl_list_templ.h \
+ isl_map_lexopt_templ.c \
+ isl_multi_templ.c \
+ isl_multi_templ.h \
+ print_templ.c \
+ isl_power_templ.c \
+ isl_pw_templ.c \
+ isl_union_templ.c \
+ isl.py \
+ doc/SubmittingPatches \
+ doc/chicago.bst \
+ doc/chicago.sty \
+ doc/implementation.tex \
+ doc/isl.bib \
+ doc/mypod2latex \
+ doc/manual.tex \
+ doc/user.pod \
+ imath/gmp_compat.c \
+ imath/gmp_compat.h \
+ imath/imath.c \
+ imath/imath.h \
+ imath/imrat.c \
+ imath/imrat.h \
+ interface/all.h \
+ interface/isl.py.top \
+ test_inputs
+
+dist-hook:
+ echo @GIT_HEAD_VERSION@ > $(distdir)/GIT_HEAD_ID
+ (cd doc; make manual.pdf)
+ cp doc/manual.pdf $(distdir)/doc/
+
+pkgconfigdir=$(pkgconfig_libdir)
+pkgconfig_DATA = $(pkgconfig_libfile)
+
+gitversion.h: @GIT_HEAD@
+ $(AM_V_GEN)echo '#define GIT_HEAD_ID "'@GIT_HEAD_VERSION@'"' > $@
+
+install-data-local: $(srcdir)/isl.py
+ @libisl=`sed -ne "/^library_names=/{s/.*='//;s/'$$//;s/ .*//;p;}" \
+ $(builddir)/libisl.la`; \
+ case $$libisl in \
+ '') echo Cannot find isl library name. GDB bindings not installed.;; \
+ *) echo $(INSTALL_DATA) $(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
diff --git a/polly/lib/External/isl/README b/polly/lib/External/isl/README
new file mode 100644
index 00000000000..9f48a0a76f9
--- /dev/null
+++ b/polly/lib/External/isl/README
@@ -0,0 +1,53 @@
+isl is a thread-safe C library for manipulating sets and relations
+of integer points bounded by affine constraints. The descriptions of
+the sets and relations may involve both parameters and existentially
+quantified variables. All computations are performed in exact integer
+arithmetic using GMP.
+
+isl is released under the MIT license, but depends on the LGPL GMP
+library.
+
+Minimal compilation instructions:
+
+ ./configure
+ make
+ make install
+
+If you are taking the source from the git repository, then you first
+need to do
+
+ git clone git://repo.or.cz/isl.git
+ ./autogen.sh
+
+For more information, see doc/user.pod or the generated documentation.
+
+New releases are announced on http://freecode.com/projects/isl
+
+If you use isl, you can let me know by stacking
+https://www.ohloh.net/p/isl on ohloh.
+
+For bug reports, feature requests and questions,
+contact http://groups.google.com/group/isl-development
+
+Whenever you report a bug, please mention the exact version of isl
+that you are using (output of "./isl_cat --version"). If you are unable
+to compile isl, then report the git version (output of "git describe")
+or the version included in the name of the tarball.
+
+If you use isl for your research, you are invited do cite
+the following paper and/or the paper(s) describing the specific
+operations you use.
+
+@incollection{Verdoolaege2010isl,
+ author = {Verdoolaege, Sven},
+ title = {isl: An Integer Set Library for the Polyhedral Model},
+ booktitle = {Mathematical Software - ICMS 2010},
+ series = {Lecture Notes in Computer Science},
+ editor = {Fukuda, Komei and Hoeven, Joris and Joswig, Michael and
+ Takayama, Nobuki},
+ publisher = {Springer},
+ isbn = {978-3-642-15581-9},
+ pages = {299-302},
+ volume = {6327},
+ year = {2010}
+}
diff --git a/polly/lib/External/isl/autogen.sh b/polly/lib/External/isl/autogen.sh
new file mode 100755
index 00000000000..68f4a174b46
--- /dev/null
+++ b/polly/lib/External/isl/autogen.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+autoreconf -i
diff --git a/polly/lib/External/isl/basis_reduction_tab.c b/polly/lib/External/isl/basis_reduction_tab.c
new file mode 100644
index 00000000000..112d423dbe0
--- /dev/null
+++ b/polly/lib/External/isl/basis_reduction_tab.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl_map_private.h>
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include <isl_int.h>
+#include <isl_config.h>
+
+struct tab_lp {
+ struct isl_ctx *ctx;
+ struct isl_vec *row;
+ struct isl_tab *tab;
+ struct isl_tab_undo **stack;
+ isl_int *obj;
+ isl_int opt;
+ isl_int opt_denom;
+ isl_int tmp;
+ isl_int tmp2;
+ int neq;
+ unsigned dim;
+ /* number of constraints in initial product tableau */
+ int con_offset;
+ /* objective function has fixed or no integer value */
+ int is_fixed;
+};
+
+#ifdef USE_GMP_FOR_MP
+#define GBR_type mpq_t
+#define GBR_init(v) mpq_init(v)
+#define GBR_clear(v) mpq_clear(v)
+#define GBR_set(a,b) mpq_set(a,b)
+#define GBR_set_ui(a,b) mpq_set_ui(a,b,1)
+#define GBR_mul(a,b,c) mpq_mul(a,b,c)
+#define GBR_lt(a,b) (mpq_cmp(a,b) < 0)
+#define GBR_is_zero(a) (mpq_sgn(a) == 0)
+#define GBR_numref(a) mpq_numref(a)
+#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))
+#endif /* USE_GMP_FOR_MP */
+
+#ifdef USE_IMATH_FOR_MP
+#include <imrat.h>
+
+#define GBR_type mp_rat
+#define GBR_init(v) v = mp_rat_alloc()
+#define GBR_clear(v) mp_rat_free(v)
+#define GBR_set(a,b) mp_rat_copy(b,a)
+#define GBR_set_ui(a,b) mp_rat_set_uvalue(a,b,1)
+#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))
+#endif /* USE_IMATH_FOR_MP */
+
+static struct tab_lp *init_lp(struct isl_tab *tab);
+static void set_lp_obj(struct tab_lp *lp, isl_int *row, int dim);
+static int solve_lp(struct tab_lp *lp);
+static void get_obj_val(struct tab_lp* lp, GBR_type *F);
+static void delete_lp(struct tab_lp *lp);
+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);
+static int del_lp_row(struct tab_lp *lp) WARN_UNUSED;
+static int cut_lp_to_hyperplane(struct tab_lp *lp, isl_int *row);
+
+#define GBR_LP struct tab_lp
+#define GBR_lp_init(P) init_lp(P)
+#define GBR_lp_set_obj(lp, obj, dim) set_lp_obj(lp, obj, dim)
+#define GBR_lp_solve(lp) solve_lp(lp)
+#define GBR_lp_get_obj_val(lp, F) get_obj_val(lp, F)
+#define GBR_lp_delete(lp) delete_lp(lp)
+#define GBR_lp_next_row(lp) lp->neq
+#define GBR_lp_add_row(lp, row, dim) add_lp_row(lp, row, dim)
+#define GBR_lp_get_alpha(lp, row, alpha) get_alpha(lp, row, alpha)
+#define GBR_lp_del_row(lp) del_lp_row(lp)
+#define GBR_lp_is_fixed(lp) (lp)->is_fixed
+#define GBR_lp_cut(lp, obj) cut_lp_to_hyperplane(lp, obj)
+#include "basis_reduction_templ.c"
+
+/* Set up a tableau for the Cartesian product of bset with itself.
+ * This could be optimized by first setting up a tableau for bset
+ * and then performing the Cartesian product on the tableau.
+ */
+static struct isl_tab *gbr_tab(struct isl_tab *tab, struct isl_vec *row)
+{
+ unsigned dim;
+ struct isl_tab *prod;
+
+ if (!tab || !row)
+ return NULL;
+
+ dim = tab->n_var;
+ prod = isl_tab_product(tab, tab);
+ if (isl_tab_extend_cons(prod, 3 * dim + 1) < 0) {
+ isl_tab_free(prod);
+ return NULL;
+ }
+ return prod;
+}
+
+static struct tab_lp *init_lp(struct isl_tab *tab)
+{
+ struct tab_lp *lp = NULL;
+
+ if (!tab)
+ return NULL;
+
+ lp = isl_calloc_type(tab->mat->ctx, struct tab_lp);
+ if (!lp)
+ return NULL;
+
+ isl_int_init(lp->opt);
+ isl_int_init(lp->opt_denom);
+ isl_int_init(lp->tmp);
+ isl_int_init(lp->tmp2);
+
+ lp->dim = tab->n_var;
+
+ lp->ctx = tab->mat->ctx;
+ isl_ctx_ref(lp->ctx);
+
+ lp->stack = isl_alloc_array(lp->ctx, struct isl_tab_undo *, lp->dim);
+
+ lp->row = isl_vec_alloc(lp->ctx, 1 + 2 * lp->dim);
+ if (!lp->row)
+ goto error;
+ lp->tab = gbr_tab(tab, lp->row);
+ if (!lp->tab)
+ goto error;
+ lp->con_offset = lp->tab->n_con;
+ lp->obj = NULL;
+ lp->neq = 0;
+
+ return lp;
+error:
+ delete_lp(lp);
+ return NULL;
+}
+
+static void set_lp_obj(struct tab_lp *lp, isl_int *row, int dim)
+{
+ lp->obj = row;
+}
+
+static int solve_lp(struct tab_lp *lp)
+{
+ enum isl_lp_result res;
+ unsigned flags = 0;
+
+ lp->is_fixed = 0;
+
+ isl_int_set_si(lp->row->el[0], 0);
+ isl_seq_cpy(lp->row->el + 1, lp->obj, lp->dim);
+ isl_seq_neg(lp->row->el + 1 + lp->dim, lp->obj, lp->dim);
+ if (lp->neq)
+ flags = ISL_TAB_SAVE_DUAL;
+ res = isl_tab_min(lp->tab, lp->row->el, lp->ctx->one,
+ &lp->opt, &lp->opt_denom, flags);
+ isl_int_mul_ui(lp->opt_denom, lp->opt_denom, 2);
+ if (isl_int_abs_lt(lp->opt, lp->opt_denom)) {
+ struct isl_vec *sample = isl_tab_get_sample_value(lp->tab);
+ if (!sample)
+ return -1;
+ isl_seq_inner_product(lp->obj, sample->el + 1, lp->dim, &lp->tmp);
+ isl_seq_inner_product(lp->obj, sample->el + 1 + lp->dim, lp->dim, &lp->tmp2);
+ isl_int_cdiv_q(lp->tmp, lp->tmp, sample->el[0]);
+ isl_int_fdiv_q(lp->tmp2, lp->tmp2, sample->el[0]);
+ if (isl_int_ge(lp->tmp, lp->tmp2))
+ lp->is_fixed = 1;
+ isl_vec_free(sample);
+ }
+ isl_int_divexact_ui(lp->opt_denom, lp->opt_denom, 2);
+ if (res != isl_lp_ok)
+ return -1;
+ return 0;
+}
+
+/* The current objective function has a fixed (or no) integer value.
+ * Cut the tableau to the hyperplane that fixes this value in
+ * both halves of the tableau.
+ * Return 1 if the resulting tableau is empty.
+ */
+static int cut_lp_to_hyperplane(struct tab_lp *lp, isl_int *row)
+{
+ enum isl_lp_result res;
+
+ isl_int_set_si(lp->row->el[0], 0);
+ isl_seq_cpy(lp->row->el + 1, row, lp->dim);
+ isl_seq_clr(lp->row->el + 1 + lp->dim, lp->dim);
+ res = isl_tab_min(lp->tab, lp->row->el, lp->ctx->one,
+ &lp->tmp, NULL, 0);
+ if (res != isl_lp_ok)
+ return -1;
+
+ isl_int_neg(lp->row->el[0], lp->tmp);
+ if (isl_tab_add_eq(lp->tab, lp->row->el) < 0)
+ return -1;
+
+ isl_seq_cpy(lp->row->el + 1 + lp->dim, row, lp->dim);
+ isl_seq_clr(lp->row->el + 1, lp->dim);
+ if (isl_tab_add_eq(lp->tab, lp->row->el) < 0)
+ return -1;
+
+ lp->con_offset += 2;
+
+ return lp->tab->empty;
+}
+
+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);
+}
+
+static void delete_lp(struct tab_lp *lp)
+{
+ if (!lp)
+ return;
+
+ isl_int_clear(lp->opt);
+ isl_int_clear(lp->opt_denom);
+ isl_int_clear(lp->tmp);
+ isl_int_clear(lp->tmp2);
+ isl_vec_free(lp->row);
+ free(lp->stack);
+ isl_tab_free(lp->tab);
+ isl_ctx_deref(lp->ctx);
+ free(lp);
+}
+
+static int add_lp_row(struct tab_lp *lp, isl_int *row, int dim)
+{
+ lp->stack[lp->neq] = isl_tab_snap(lp->tab);
+
+ isl_int_set_si(lp->row->el[0], 0);
+ isl_seq_cpy(lp->row->el + 1, row, lp->dim);
+ isl_seq_neg(lp->row->el + 1 + lp->dim, row, lp->dim);
+
+ if (isl_tab_add_valid_eq(lp->tab, lp->row->el) < 0)
+ return -1;
+
+ return lp->neq++;
+}
+
+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]);
+}
+
+static int del_lp_row(struct tab_lp *lp)
+{
+ lp->neq--;
+ return isl_tab_rollback(lp->tab, lp->stack[lp->neq]);
+}
diff --git a/polly/lib/External/isl/basis_reduction_templ.c b/polly/lib/External/isl/basis_reduction_templ.c
new file mode 100644
index 00000000000..98d8141372b
--- /dev/null
+++ b/polly/lib/External/isl/basis_reduction_templ.c
@@ -0,0 +1,358 @@
+/*
+ * Copyright 2006-2007 Universiteit Leiden
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
+ * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
+ * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
+ * B-3001 Leuven, Belgium
+ */
+
+#include <stdlib.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_vec_private.h>
+#include <isl_options_private.h>
+#include "isl_basis_reduction.h"
+
+static void save_alpha(GBR_LP *lp, int first, int n, GBR_type *alpha)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ GBR_lp_get_alpha(lp, first + i, &alpha[i]);
+}
+
+/* Compute a reduced basis for the set represented by the tableau "tab".
+ * tab->basis, which must be initialized by the calling function to an affine
+ * unimodular basis, is updated to reflect the reduced basis.
+ * The first tab->n_zero rows of the basis (ignoring the constant row)
+ * are assumed to correspond to equalities and are left untouched.
+ * tab->n_zero is updated to reflect any additional equalities that
+ * have been detected in the first rows of the new basis.
+ * The final tab->n_unbounded rows of the basis are assumed to correspond
+ * to unbounded directions and are also left untouched.
+ * In particular this means that the remaining rows are assumed to
+ * correspond to bounded directions.
+ *
+ * This function implements the algorithm described in
+ * "An Implementation of the Generalized Basis Reduction Algorithm
+ * for Integer Programming" of Cook el al. to compute a reduced basis.
+ * We use \epsilon = 1/4.
+ *
+ * If ctx->opt->gbr_only_first is set, the user is only interested
+ * in the first direction. In this case we stop the basis reduction when
+ * the width in the first direction becomes smaller than 2.
+ */
+struct isl_tab *isl_tab_compute_reduced_basis(struct isl_tab *tab)
+{
+ unsigned dim;
+ struct isl_ctx *ctx;
+ struct isl_mat *B;
+ int unbounded;
+ int i;
+ GBR_LP *lp = NULL;
+ GBR_type F_old, alpha, F_new;
+ int row;
+ isl_int tmp;
+ struct isl_vec *b_tmp;
+ GBR_type *F = NULL;
+ GBR_type *alpha_buffer[2] = { NULL, NULL };
+ GBR_type *alpha_saved;
+ GBR_type F_saved;
+ int use_saved = 0;
+ isl_int mu[2];
+ GBR_type mu_F[2];
+ GBR_type two;
+ GBR_type one;
+ int empty = 0;
+ int fixed = 0;
+ int fixed_saved = 0;
+ int mu_fixed[2];
+ int n_bounded;
+ int gbr_only_first;
+
+ if (!tab)
+ return NULL;
+
+ if (tab->empty)
+ return tab;
+
+ ctx = tab->mat->ctx;
+ gbr_only_first = ctx->opt->gbr_only_first;
+ dim = tab->n_var;
+ B = tab->basis;
+ if (!B)
+ return tab;
+
+ n_bounded = dim - tab->n_unbounded;
+ if (n_bounded <= tab->n_zero + 1)
+ return tab;
+
+ isl_int_init(tmp);
+ isl_int_init(mu[0]);
+ isl_int_init(mu[1]);
+
+ GBR_init(alpha);
+ GBR_init(F_old);
+ GBR_init(F_new);
+ GBR_init(F_saved);
+ GBR_init(mu_F[0]);
+ GBR_init(mu_F[1]);
+ GBR_init(two);
+ GBR_init(one);
+
+ b_tmp = isl_vec_alloc(ctx, dim);
+ if (!b_tmp)
+ goto error;
+
+ F = isl_alloc_array(ctx, GBR_type, n_bounded);
+ alpha_buffer[0] = isl_alloc_array(ctx, GBR_type, n_bounded);
+ alpha_buffer[1] = isl_alloc_array(ctx, GBR_type, n_bounded);
+ alpha_saved = alpha_buffer[0];
+
+ if (!F || !alpha_buffer[0] || !alpha_buffer[1])
+ goto error;
+
+ for (i = 0; i < n_bounded; ++i) {
+ GBR_init(F[i]);
+ GBR_init(alpha_buffer[0][i]);
+ GBR_init(alpha_buffer[1][i]);
+ }
+
+ GBR_set_ui(two, 2);
+ GBR_set_ui(one, 1);
+
+ lp = GBR_lp_init(tab);
+ if (!lp)
+ goto error;
+
+ i = tab->n_zero;
+
+ GBR_lp_set_obj(lp, B->row[1+i]+1, dim);
+ ctx->stats->gbr_solved_lps++;
+ unbounded = GBR_lp_solve(lp);
+ isl_assert(ctx, !unbounded, goto error);
+ GBR_lp_get_obj_val(lp, &F[i]);
+
+ if (GBR_lt(F[i], one)) {
+ if (!GBR_is_zero(F[i])) {
+ empty = GBR_lp_cut(lp, B->row[1+i]+1);
+ if (empty)
+ goto done;
+ GBR_set_ui(F[i], 0);
+ }
+ tab->n_zero++;
+ }
+
+ do {
+ if (i+1 == tab->n_zero) {
+ GBR_lp_set_obj(lp, B->row[1+i+1]+1, dim);
+ ctx->stats->gbr_solved_lps++;
+ unbounded = GBR_lp_solve(lp);
+ isl_assert(ctx, !unbounded, goto error);
+ GBR_lp_get_obj_val(lp, &F_new);
+ fixed = GBR_lp_is_fixed(lp);
+ GBR_set_ui(alpha, 0);
+ } else
+ if (use_saved) {
+ row = GBR_lp_next_row(lp);
+ GBR_set(F_new, F_saved);
+ fixed = fixed_saved;
+ GBR_set(alpha, alpha_saved[i]);
+ } else {
+ row = GBR_lp_add_row(lp, B->row[1+i]+1, dim);
+ GBR_lp_set_obj(lp, B->row[1+i+1]+1, dim);
+ ctx->stats->gbr_solved_lps++;
+ unbounded = GBR_lp_solve(lp);
+ isl_assert(ctx, !unbounded, goto error);
+ GBR_lp_get_obj_val(lp, &F_new);
+ fixed = GBR_lp_is_fixed(lp);
+
+ GBR_lp_get_alpha(lp, row, &alpha);
+
+ if (i > 0)
+ save_alpha(lp, row-i, i, alpha_saved);
+
+ if (GBR_lp_del_row(lp) < 0)
+ goto error;
+ }
+ GBR_set(F[i+1], F_new);
+
+ GBR_floor(mu[0], alpha);
+ GBR_ceil(mu[1], alpha);
+
+ if (isl_int_eq(mu[0], mu[1]))
+ isl_int_set(tmp, mu[0]);
+ else {
+ int j;
+
+ for (j = 0; j <= 1; ++j) {
+ isl_int_set(tmp, mu[j]);
+ isl_seq_combine(b_tmp->el,
+ ctx->one, B->row[1+i+1]+1,
+ tmp, B->row[1+i]+1, dim);
+ GBR_lp_set_obj(lp, b_tmp->el, dim);
+ ctx->stats->gbr_solved_lps++;
+ unbounded = GBR_lp_solve(lp);
+ isl_assert(ctx, !unbounded, goto error);
+ GBR_lp_get_obj_val(lp, &mu_F[j]);
+ mu_fixed[j] = GBR_lp_is_fixed(lp);
+ if (i > 0)
+ save_alpha(lp, row-i, i, alpha_buffer[j]);
+ }
+
+ if (GBR_lt(mu_F[0], mu_F[1]))
+ j = 0;
+ else
+ j = 1;
+
+ isl_int_set(tmp, mu[j]);
+ GBR_set(F_new, mu_F[j]);
+ fixed = mu_fixed[j];
+ alpha_saved = alpha_buffer[j];
+ }
+ isl_seq_combine(B->row[1+i+1]+1, ctx->one, B->row[1+i+1]+1,
+ tmp, B->row[1+i]+1, dim);
+
+ if (i+1 == tab->n_zero && fixed) {
+ if (!GBR_is_zero(F[i+1])) {
+ empty = GBR_lp_cut(lp, B->row[1+i+1]+1);
+ if (empty)
+ goto done;
+ GBR_set_ui(F[i+1], 0);
+ }
+ tab->n_zero++;
+ }
+
+ GBR_set(F_old, F[i]);
+
+ use_saved = 0;
+ /* mu_F[0] = 4 * F_new; mu_F[1] = 3 * F_old */
+ GBR_set_ui(mu_F[0], 4);
+ GBR_mul(mu_F[0], mu_F[0], F_new);
+ GBR_set_ui(mu_F[1], 3);
+ GBR_mul(mu_F[1], mu_F[1], F_old);
+ if (GBR_lt(mu_F[0], mu_F[1])) {
+ B = isl_mat_swap_rows(B, 1 + i, 1 + i + 1);
+ if (i > tab->n_zero) {
+ use_saved = 1;
+ GBR_set(F_saved, F_new);
+ fixed_saved = fixed;
+ if (GBR_lp_del_row(lp) < 0)
+ goto error;
+ --i;
+ } else {
+ GBR_set(F[tab->n_zero], F_new);
+ if (gbr_only_first && GBR_lt(F[tab->n_zero], two))
+ break;
+
+ if (fixed) {
+ if (!GBR_is_zero(F[tab->n_zero])) {
+ empty = GBR_lp_cut(lp, B->row[1+tab->n_zero]+1);
+ if (empty)
+ goto done;
+ GBR_set_ui(F[tab->n_zero], 0);
+ }
+ tab->n_zero++;
+ }
+ }
+ } else {
+ GBR_lp_add_row(lp, B->row[1+i]+1, dim);
+ ++i;
+ }
+ } while (i < n_bounded - 1);
+
+ if (0) {
+done:
+ if (empty < 0) {
+error:
+ isl_mat_free(B);
+ B = NULL;
+ }
+ }
+
+ GBR_lp_delete(lp);
+
+ if (alpha_buffer[1])
+ for (i = 0; i < n_bounded; ++i) {
+ GBR_clear(F[i]);
+ GBR_clear(alpha_buffer[0][i]);
+ GBR_clear(alpha_buffer[1][i]);
+ }
+ free(F);
+ free(alpha_buffer[0]);
+ free(alpha_buffer[1]);
+
+ isl_vec_free(b_tmp);
+
+ GBR_clear(alpha);
+ GBR_clear(F_old);
+ GBR_clear(F_new);
+ GBR_clear(F_saved);
+ GBR_clear(mu_F[0]);
+ GBR_clear(mu_F[1]);
+ GBR_clear(two);
+ GBR_clear(one);
+
+ isl_int_clear(tmp);
+ isl_int_clear(mu[0]);
+ isl_int_clear(mu[1]);
+
+ tab->basis = B;
+
+ return tab;
+}
+
+/* Compute an affine form of a reduced basis of the given basic
+ * non-parametric set, which is assumed to be bounded and not
+ * include any integer divisions.
+ * The first column and the first row correspond to the constant term.
+ *
+ * If the input contains any equalities, we first create an initial
+ * basis with the equalities first. Otherwise, we start off with
+ * the identity matrix.
+ */
+struct isl_mat *isl_basic_set_reduced_basis(struct isl_basic_set *bset)
+{
+ struct isl_mat *basis;
+ struct isl_tab *tab;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_dim(bset, isl_dim_div) != 0)
+ isl_die(bset->ctx, isl_error_invalid,
+ "no integer division allowed", return NULL);
+ if (isl_basic_set_dim(bset, isl_dim_param) != 0)
+ isl_die(bset->ctx, isl_error_invalid,
+ "no parameters allowed", return NULL);
+
+ tab = isl_tab_from_basic_set(bset, 0);
+ if (!tab)
+ return NULL;
+
+ if (bset->n_eq == 0)
+ tab->basis = isl_mat_identity(bset->ctx, 1 + tab->n_var);
+ else {
+ isl_mat *eq;
+ unsigned nvar = isl_basic_set_total_dim(bset);
+ eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq,
+ 1, nvar);
+ eq = isl_mat_left_hermite(eq, 0, NULL, &tab->basis);
+ tab->basis = isl_mat_lin_to_aff(tab->basis);
+ tab->n_zero = bset->n_eq;
+ isl_mat_free(eq);
+ }
+ tab = isl_tab_compute_reduced_basis(tab);
+ if (!tab)
+ return NULL;
+
+ basis = isl_mat_copy(tab->basis);
+
+ isl_tab_free(tab);
+
+ return basis;
+}
diff --git a/polly/lib/External/isl/bound.c b/polly/lib/External/isl/bound.c
new file mode 100644
index 00000000000..4aaaf13e5ce
--- /dev/null
+++ b/polly/lib/External/isl/bound.c
@@ -0,0 +1,291 @@
+#include <assert.h>
+#include <isl/stream.h>
+#include <isl_map_private.h>
+#include <isl_polynomial_private.h>
+#include <isl_scan.h>
+#include <isl/options.h>
+#include <isl/deprecated/point_int.h>
+#include <isl/deprecated/polynomial_int.h>
+
+struct bound_options {
+ struct isl_options *isl;
+ unsigned verify;
+ int print_all;
+ int continue_on_error;
+};
+
+ISL_ARGS_START(struct bound_options, bound_options_args)
+ISL_ARG_CHILD(struct bound_options, isl, "isl", &isl_options_args,
+ "isl options")
+ISL_ARG_BOOL(struct bound_options, verify, 'T', "verify", 0, NULL)
+ISL_ARG_BOOL(struct bound_options, print_all, 'A', "print-all", 0, NULL)
+ISL_ARG_BOOL(struct bound_options, continue_on_error, '\0', "continue-on-error", 0, NULL)
+ISL_ARGS_END
+
+ISL_ARG_DEF(bound_options, struct bound_options, bound_options_args)
+
+static __isl_give isl_set *set_bounds(__isl_take isl_set *set)
+{
+ unsigned nparam;
+ int i, r;
+ isl_point *pt, *pt2;
+ isl_set *box;
+
+ nparam = isl_set_dim(set, isl_dim_param);
+ r = nparam >= 8 ? 5 : nparam >= 5 ? 15 : 50;
+
+ pt = isl_set_sample_point(isl_set_copy(set));
+ pt2 = isl_point_copy(pt);
+
+ for (i = 0; i < nparam; ++i) {
+ pt = isl_point_add_ui(pt, isl_dim_param, i, r);
+ pt2 = isl_point_sub_ui(pt2, isl_dim_param, i, r);
+ }
+
+ box = isl_set_box_from_points(pt, pt2);
+
+ return isl_set_intersect(set, box);
+}
+
+struct verify_point_bound {
+ struct bound_options *options;
+ int stride;
+ int n;
+ int exact;
+ int error;
+
+ isl_pw_qpolynomial_fold *pwf;
+ isl_pw_qpolynomial_fold *bound;
+};
+
+static int verify_point(__isl_take isl_point *pnt, void *user)
+{
+ int i;
+ unsigned nvar;
+ unsigned nparam;
+ struct verify_point_bound *vpb = (struct verify_point_bound *) user;
+ isl_int t;
+ isl_ctx *ctx;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_val *bound = NULL;
+ isl_val *opt = NULL;
+ isl_set *dom = NULL;
+ isl_printer *p;
+ const char *minmax;
+ int bounded;
+ int sign;
+ int ok;
+ FILE *out = vpb->options->print_all ? stdout : stderr;
+
+ vpb->n--;
+
+ if (1) {
+ minmax = "ub";
+ sign = 1;
+ } else {
+ minmax = "lb";
+ sign = -1;
+ }
+
+ ctx = isl_point_get_ctx(pnt);
+ p = isl_printer_to_file(ctx, out);
+
+ isl_int_init(t);
+
+ pwf = isl_pw_qpolynomial_fold_copy(vpb->pwf);
+
+ nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param);
+ for (i = 0; i < nparam; ++i) {
+ isl_point_get_coordinate(pnt, isl_dim_param, i, &t);
+ pwf = isl_pw_qpolynomial_fold_fix_dim(pwf, isl_dim_param, i, t);
+ }
+
+ bound = isl_pw_qpolynomial_fold_eval(
+ isl_pw_qpolynomial_fold_copy(vpb->bound),
+ isl_point_copy(pnt));
+
+ dom = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf));
+ bounded = isl_set_is_bounded(dom);
+
+ if (bounded < 0)
+ goto error;
+
+ if (!bounded)
+ opt = isl_pw_qpolynomial_fold_eval(
+ isl_pw_qpolynomial_fold_copy(pwf),
+ isl_set_sample_point(isl_set_copy(dom)));
+ else if (sign > 0)
+ opt = isl_pw_qpolynomial_fold_max(isl_pw_qpolynomial_fold_copy(pwf));
+ else
+ opt = isl_pw_qpolynomial_fold_min(isl_pw_qpolynomial_fold_copy(pwf));
+
+ nvar = isl_set_dim(dom, isl_dim_set);
+ if (vpb->exact && bounded)
+ ok = isl_val_eq(opt, bound);
+ else if (sign > 0)
+ ok = isl_val_le(opt, bound);
+ else
+ ok = isl_val_le(bound, opt);
+ if (ok < 0)
+ goto error;
+
+ if (vpb->options->print_all || !ok) {
+ p = isl_printer_print_str(p, minmax);
+ p = isl_printer_print_str(p, "(");
+ for (i = 0; i < nparam; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, ", ");
+ isl_point_get_coordinate(pnt, isl_dim_param, i, &t);
+ p = isl_printer_print_isl_int(p, t);
+ }
+ p = isl_printer_print_str(p, ") = ");
+ p = isl_printer_print_val(p, bound);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, bounded ? "opt" : "sample");
+ p = isl_printer_print_str(p, " = ");
+ p = isl_printer_print_val(p, opt);
+ if (ok)
+ p = isl_printer_print_str(p, ". OK");
+ else
+ p = isl_printer_print_str(p, ". NOT OK");
+ p = isl_printer_end_line(p);
+ } else if ((vpb->n % vpb->stride) == 0) {
+ p = isl_printer_print_str(p, "o");
+ p = isl_printer_flush(p);
+ }
+
+ if (0) {
+error:
+ ok = 0;
+ }
+
+ isl_pw_qpolynomial_fold_free(pwf);
+ isl_val_free(bound);
+ isl_val_free(opt);
+ isl_point_free(pnt);
+ isl_set_free(dom);
+
+ isl_int_clear(t);
+
+ isl_printer_free(p);
+
+ if (!ok)
+ vpb->error = 1;
+
+ if (vpb->options->continue_on_error)
+ ok = 1;
+
+ return (vpb->n >= 1 && ok) ? 0 : -1;
+}
+
+static int check_solution(__isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_pw_qpolynomial_fold *bound, int exact,
+ struct bound_options *options)
+{
+ struct verify_point_bound vpb;
+ isl_int count, max;
+ isl_set *dom;
+ isl_set *context;
+ int i, r, n;
+
+ dom = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf));
+ context = isl_set_params(isl_set_copy(dom));
+ context = isl_set_remove_divs(context);
+ context = set_bounds(context);
+
+ isl_int_init(count);
+ isl_int_init(max);
+
+ isl_int_set_si(max, 200);
+ r = isl_set_count_upto(context, max, &count);
+ assert(r >= 0);
+ n = isl_int_get_si(count);
+
+ isl_int_clear(max);
+ isl_int_clear(count);
+
+ vpb.options = options;
+ vpb.pwf = pwf;
+ vpb.bound = bound;
+ vpb.n = n;
+ vpb.stride = n > 70 ? 1 + (n + 1)/70 : 1;
+ vpb.error = 0;
+ vpb.exact = exact;
+
+ if (!options->print_all) {
+ for (i = 0; i < vpb.n; i += vpb.stride)
+ printf(".");
+ printf("\r");
+ fflush(stdout);
+ }
+
+ isl_set_foreach_point(context, verify_point, &vpb);
+
+ isl_set_free(context);
+ isl_set_free(dom);
+ isl_pw_qpolynomial_fold_free(pwf);
+ isl_pw_qpolynomial_fold_free(bound);
+
+ if (!options->print_all)
+ printf("\n");
+
+ if (vpb.error) {
+ fprintf(stderr, "Check failed !\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ isl_ctx *ctx;
+ isl_pw_qpolynomial_fold *copy;
+ isl_pw_qpolynomial_fold *pwf;
+ struct isl_stream *s;
+ struct isl_obj obj;
+ struct bound_options *options;
+ int exact;
+ int r = 0;
+
+ options = bound_options_new_with_defaults();
+ assert(options);
+ argc = bound_options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&bound_options_args, options);
+
+ s = isl_stream_new_file(ctx, stdin);
+ obj = isl_stream_read_obj(s);
+ if (obj.type == isl_obj_pw_qpolynomial)
+ pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max,
+ obj.v);
+ else if (obj.type == isl_obj_pw_qpolynomial_fold)
+ pwf = obj.v;
+ else {
+ obj.type->free(obj.v);
+ isl_die(ctx, isl_error_invalid, "invalid input", goto error);
+ }
+
+ if (options->verify)
+ copy = isl_pw_qpolynomial_fold_copy(pwf);
+
+ pwf = isl_pw_qpolynomial_fold_bound(pwf, &exact);
+ pwf = isl_pw_qpolynomial_fold_coalesce(pwf);
+
+ if (options->verify) {
+ r = check_solution(copy, pwf, exact, options);
+ } else {
+ if (!exact)
+ printf("# NOT exact\n");
+ isl_pw_qpolynomial_fold_print(pwf, stdout, 0);
+ fprintf(stdout, "\n");
+ isl_pw_qpolynomial_fold_free(pwf);
+ }
+
+error:
+ isl_stream_free(s);
+
+ isl_ctx_free(ctx);
+
+ return r;
+}
diff --git a/polly/lib/External/isl/bound_test.sh.in b/polly/lib/External/isl/bound_test.sh.in
new file mode 100755
index 00000000000..e3fc037ecaf
--- /dev/null
+++ b/polly/lib/External/isl/bound_test.sh.in
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+EXEEXT=@EXEEXT@
+
+BOUND_TESTS="\
+ basicLinear2.pwqp \
+ basicLinear.pwqp \
+ basicTestParameterPosNeg.pwqp \
+ basicTest.pwqp \
+ devos.pwqp \
+ equality1.pwqp \
+ equality2.pwqp \
+ equality3.pwqp \
+ equality4.pwqp \
+ equality5.pwqp \
+ faddeev.pwqp \
+ linearExample.pwqp \
+ neg.pwqp \
+ philippe3vars3pars.pwqp \
+ philippe3vars.pwqp \
+ philippeNeg.pwqp \
+ philippePolynomialCoeff1P.pwqp \
+ philippePolynomialCoeff.pwqp \
+ philippe.pwqp \
+ product.pwqp \
+ split.pwqp \
+ test3Deg3Var.pwqp \
+ toplas.pwqp \
+ unexpanded.pwqp"
+
+for i in $BOUND_TESTS; do
+ echo $i;
+ ./isl_bound$EXEEXT -T --bound=bernstein < $srcdir/test_inputs/$i || exit
+ ./isl_bound$EXEEXT -T --bound=range < $srcdir/test_inputs/$i || exit
+done
diff --git a/polly/lib/External/isl/cat.c b/polly/lib/External/isl/cat.c
new file mode 100644
index 00000000000..63131420592
--- /dev/null
+++ b/polly/lib/External/isl/cat.c
@@ -0,0 +1,58 @@
+#include <assert.h>
+#include <isl/obj.h>
+#include <isl/printer.h>
+#include <isl/stream.h>
+#include <isl/options.h>
+
+struct isl_arg_choice cat_format[] = {
+ {"isl", ISL_FORMAT_ISL},
+ {"omega", ISL_FORMAT_OMEGA},
+ {"polylib", ISL_FORMAT_POLYLIB},
+ {"ext-polylib", ISL_FORMAT_EXT_POLYLIB},
+ {"latex", ISL_FORMAT_LATEX},
+ {0}
+};
+
+struct cat_options {
+ struct isl_options *isl;
+ unsigned format;
+};
+
+ISL_ARGS_START(struct cat_options, cat_options_args)
+ISL_ARG_CHILD(struct cat_options, isl, "isl", &isl_options_args, "isl options")
+ISL_ARG_CHOICE(struct cat_options, format, 0, "format", \
+ cat_format, ISL_FORMAT_ISL, "output format")
+ISL_ARGS_END
+
+ISL_ARG_DEF(cat_options, struct cat_options, cat_options_args)
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx;
+ struct isl_stream *s;
+ struct isl_obj obj;
+ struct cat_options *options;
+ isl_printer *p;
+
+ options = cat_options_new_with_defaults();
+ assert(options);
+ argc = cat_options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&cat_options_args, options);
+
+ s = isl_stream_new_file(ctx, stdin);
+ obj = isl_stream_read_obj(s);
+ isl_stream_free(s);
+
+ p = isl_printer_to_file(ctx, stdout);
+ p = isl_printer_set_output_format(p, options->format);
+ p = obj.type->print(p, obj.v);
+ p = isl_printer_end_line(p);
+ isl_printer_free(p);
+
+ obj.type->free(obj.v);
+
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/closure.c b/polly/lib/External/isl/closure.c
new file mode 100644
index 00000000000..a0faa15820a
--- /dev/null
+++ b/polly/lib/External/isl/closure.c
@@ -0,0 +1,34 @@
+#include <assert.h>
+#include <isl/map.h>
+#include <isl/options.h>
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx;
+ struct isl_map *map;
+ struct isl_options *options;
+ int exact;
+
+ options = isl_options_new_with_defaults();
+ assert(options);
+ argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
+
+ map = isl_map_read_from_file(ctx, stdin);
+ map = isl_map_transitive_closure(map, &exact);
+ if (!exact)
+ printf("# NOT exact\n");
+ isl_map_print(map, stdout, 0, ISL_FORMAT_ISL);
+ printf("\n");
+ map = isl_map_compute_divs(map);
+ map = isl_map_coalesce(map);
+ printf("# coalesced\n");
+ isl_map_print(map, stdout, 0, ISL_FORMAT_ISL);
+ printf("\n");
+ isl_map_free(map);
+
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/codegen.c b/polly/lib/External/isl/codegen.c
new file mode 100644
index 00000000000..e9cd692fe8d
--- /dev/null
+++ b/polly/lib/External/isl/codegen.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2012 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
+ */
+
+/* This program prints an AST that scans the domain elements of
+ * the domain of a given schedule in the order of their image(s).
+ *
+ * The input consists of three sets/relations.
+ * - a schedule
+ * - a context
+ * - a relation describing AST generation options
+ */
+
+#include <assert.h>
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+#include <isl/options.h>
+#include <isl/set.h>
+
+struct options {
+ struct isl_options *isl;
+ unsigned atomic;
+ unsigned separate;
+};
+
+ISL_ARGS_START(struct options, options_args)
+ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
+ISL_ARG_BOOL(struct options, atomic, 0, "atomic", 0,
+ "globally set the atomic option")
+ISL_ARG_BOOL(struct options, separate, 0, "separate", 0,
+ "globally set the separate option")
+ISL_ARGS_END
+
+ISL_ARG_DEF(options, struct options, options_args)
+
+/* Return a universal, 1-dimensional set with the given name.
+ */
+static __isl_give isl_union_set *universe(isl_ctx *ctx, const char *name)
+{
+ isl_space *space;
+
+ space = isl_space_set_alloc(ctx, 0, 1);
+ space = isl_space_set_tuple_name(space, isl_dim_set, name);
+ return isl_union_set_from_set(isl_set_universe(space));
+}
+
+/* Set the "name" option for the entire schedule domain.
+ */
+static __isl_give isl_union_map *set_universe(__isl_take isl_union_map *opt,
+ __isl_keep isl_union_map *schedule, const char *name)
+{
+ isl_ctx *ctx;
+ isl_union_set *domain, *target;
+ isl_union_map *option;
+
+ ctx = isl_union_map_get_ctx(opt);
+
+ domain = isl_union_map_range(isl_union_map_copy(schedule));
+ domain = isl_union_set_universe(domain);
+ target = universe(ctx, name);
+ option = isl_union_map_from_domain_and_range(domain, target);
+ opt = isl_union_map_union(opt, option);
+
+ return opt;
+}
+
+/* Update the build options based on the user-specified options.
+ *
+ * If the --separate or --atomic options were specified, then
+ * we clear any separate or atomic options that may already exist in "opt".
+ */
+static __isl_give isl_ast_build *set_options(__isl_take isl_ast_build *build,
+ __isl_take isl_union_map *opt, struct options *options,
+ __isl_keep isl_union_map *schedule)
+{
+ if (options->separate || options->atomic) {
+ isl_ctx *ctx;
+ isl_union_set *target;
+
+ ctx = isl_union_map_get_ctx(schedule);
+
+ target = universe(ctx, "separate");
+ opt = isl_union_map_subtract_range(opt, target);
+ target = universe(ctx, "atomic");
+ opt = isl_union_map_subtract_range(opt, target);
+ }
+
+ if (options->separate)
+ opt = set_universe(opt, schedule, "separate");
+ if (options->atomic)
+ opt = set_universe(opt, schedule, "atomic");
+
+ build = isl_ast_build_set_options(build, opt);
+
+ return build;
+}
+
+int main(int argc, char **argv)
+{
+ isl_ctx *ctx;
+ isl_set *context;
+ isl_union_map *schedule;
+ isl_union_map *options_map;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+ struct options *options;
+ isl_printer *p;
+
+ options = options_new_with_defaults();
+ assert(options);
+ argc = options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&options_args, options);
+
+ schedule = isl_union_map_read_from_file(ctx, stdin);
+ context = isl_set_read_from_file(ctx, stdin);
+ options_map = isl_union_map_read_from_file(ctx, stdin);
+
+ build = isl_ast_build_from_context(context);
+ build = set_options(build, options_map, options, schedule);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+
+ p = isl_printer_to_file(ctx, stdout);
+ p = isl_printer_set_output_format(p, ISL_FORMAT_C);
+ p = isl_printer_print_ast_node(p, tree);
+ isl_printer_free(p);
+
+ isl_ast_node_free(tree);
+
+ isl_ctx_free(ctx);
+ return 0;
+}
diff --git a/polly/lib/External/isl/codegen_test.sh.in b/polly/lib/External/isl/codegen_test.sh.in
new file mode 100644
index 00000000000..36a1815b762
--- /dev/null
+++ b/polly/lib/External/isl/codegen_test.sh.in
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+EXEEXT=@EXEEXT@
+srcdir=@srcdir@
+
+failed=0
+
+for i in $srcdir/test_inputs/codegen/*.in \
+ $srcdir/test_inputs/codegen/cloog/*.in \
+ $srcdir/test_inputs/codegen/omega/*.in \
+ $srcdir/test_inputs/codegen/pldi2012/*.in; do
+ echo $i;
+ base=`basename $i .in`
+ test=test-$base.c
+ dir=`dirname $i`
+ ref=$dir/$base.c
+ (./isl_codegen$EXEEXT < $i > $test &&
+ diff -uw $ref $test && rm $test) || failed=1
+done
+
+test $failed -eq 0 || exit
diff --git a/polly/lib/External/isl/configure.ac b/polly/lib/External/isl/configure.ac
new file mode 100644
index 00000000000..f5d684b2d82
--- /dev/null
+++ b/polly/lib/External/isl/configure.ac
@@ -0,0 +1,236 @@
+AC_INIT([isl], [0.14], [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=14:0:1
+
+if test "x$prefix" != "xNONE"; then
+ prefix_wd=`cd $prefix && pwd`
+ srcdir_wd=`cd $srcdir && pwd`
+ wd=`pwd`
+ if test "x$prefix_wd" = "x$srcdir_wd"; then
+ AC_MSG_ERROR(Installation in source directory not supported)
+ fi
+ if test "x$prefix_wd" = "x$wd"; then
+ AC_MSG_ERROR(Installation in build directory not supported)
+ fi
+fi
+
+AC_PROG_CC
+AC_PROG_CXX
+
+AX_CC_MAXOPT
+AX_GCC_WARN_UNUSED_RESULT
+AX_C___ATTRIBUTE__
+
+AC_PROG_LIBTOOL
+
+AC_CHECK_PROG(PERL, perl, perl, [])
+AC_CHECK_PROG(PDFLATEX, pdflatex, pdflatex, [])
+AC_CHECK_PROG(POD2HTML, pod2html, pod2html, [])
+
+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],
+ [Which package to use to represent
+ multi-precision integers [default=gmp]])],
+ [], [with_int=gmp])
+case "$with_int" in
+gmp|imath)
+ ;;
+*)
+ AC_MSG_ERROR([bad value ${withval} for --with-int (use gmp or imath)])
+esac
+
+AC_SUBST(MP_CPPFLAGS)
+AC_SUBST(MP_LDFLAGS)
+AC_SUBST(MP_LIBS)
+case "$with_int" in
+gmp)
+ AX_DETECT_GMP
+ ;;
+imath)
+ AX_DETECT_IMATH
+ ;;
+esac
+
+AM_CONDITIONAL(IMATH_FOR_MP, test x$with_int = ximath)
+AM_CONDITIONAL(GMP_FOR_MP, test x$with_int = xgmp)
+AC_CHECK_DECLS(ffs,[],[],[#include <strings.h>])
+AC_CHECK_DECLS(__builtin_ffs,[],[],[])
+
+AC_SUBST(CLANG_CXXFLAGS)
+AC_SUBST(CLANG_LDFLAGS)
+AC_SUBST(CLANG_LIBS)
+AX_SUBMODULE(clang,system|no,no)
+case "$with_clang" in
+system)
+ AC_PROG_GREP
+ llvm_config="llvm-config"
+ AC_CHECK_PROG([llvm_config_found], ["$llvm_config"], [yes])
+ if test "x$with_clang_prefix" != "x"; then
+ llvm_config="$with_clang_prefix/bin/llvm-config"
+ if test -x "$llvm_config"; then
+ llvm_config_found=yes
+ fi
+ fi
+ if test "$llvm_config_found" != yes; then
+ AC_MSG_ERROR([llvm-config not found])
+ fi
+ CLANG_CXXFLAGS=`$llvm_config --cxxflags`
+ CLANG_LDFLAGS=`$llvm_config --ldflags`
+ targets=`$llvm_config --targets-built`
+ components="$targets asmparser bitreader support mc"
+ $llvm_config --components | $GREP option > /dev/null 2> /dev/null
+ if test $? -eq 0; then
+ components="$components option"
+ fi
+ CLANG_LIBS=`$llvm_config --libs $components`
+ systemlibs=`$llvm_config --system-libs 2> /dev/null | tail -1`
+ if test $? -eq 0; then
+ CLANG_LIBS="$CLANG_LIBS $systemlibs"
+ fi
+ CLANG_PREFIX=`$llvm_config --prefix`
+ AC_DEFINE_UNQUOTED(CLANG_PREFIX, ["$CLANG_PREFIX"],
+ [Clang installation prefix])
+
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CLANG_CXXFLAGS $CPPFLAGS"
+ AC_LANG_PUSH(C++)
+ AC_CHECK_HEADER([clang/Basic/SourceLocation.h], [],
+ [AC_ERROR([clang header file not found])])
+ AC_EGREP_HEADER([getDefaultTargetTriple], [llvm/Support/Host.h], [],
+ [AC_DEFINE([getDefaultTargetTriple], [getHostTriple],
+ [Define to getHostTriple for older versions of clang])])
+ AC_EGREP_HEADER([getExpansionLineNumber],
+ [clang/Basic/SourceLocation.h], [],
+ [AC_DEFINE([getExpansionLineNumber],
+ [getInstantiationLineNumber],
+ [Define to getInstantiationLineNumber for older versions of clang])])
+ AC_EGREP_HEADER([DiagnosticsEngine],
+ [clang/Basic/Diagnostic.h], [],
+ [AC_DEFINE([DiagnosticsEngine],
+ [Diagnostic],
+ [Define to Diagnostic for older versions of clang])])
+ AC_EGREP_HEADER([ArrayRef], [clang/Driver/Driver.h],
+ [AC_DEFINE([USE_ARRAYREF], [],
+ [Define if Driver::BuildCompilation takes ArrayRef])])
+ AC_EGREP_HEADER([CXXIsProduction], [clang/Driver/Driver.h],
+ [AC_DEFINE([HAVE_CXXISPRODUCTION], [],
+ [Define if Driver constructor takes CXXIsProduction argument])])
+ AC_EGREP_HEADER([ IsProduction], [clang/Driver/Driver.h],
+ [AC_DEFINE([HAVE_ISPRODUCTION], [],
+ [Define if Driver constructor takes IsProduction argument])])
+ AC_TRY_COMPILE([#include <clang/Driver/Driver.h>], [
+ using namespace clang;
+ DiagnosticsEngine *Diags;
+ new driver::Driver("", "", "", *Diags);
+ ], [AC_DEFINE([DRIVER_CTOR_TAKES_DEFAULTIMAGENAME], [],
+ [Define if Driver constructor takes default image name])])
+ AC_EGREP_HEADER([void HandleTopLevelDecl\(], [clang/AST/ASTConsumer.h],
+ [AC_DEFINE([HandleTopLevelDeclReturn], [void],
+ [Return type of HandleTopLevelDeclReturn])
+ AC_DEFINE([HandleTopLevelDeclContinue], [],
+ [Return type of HandleTopLevelDeclReturn])],
+ [AC_DEFINE([HandleTopLevelDeclReturn], [bool],
+ [Return type of HandleTopLevelDeclReturn])
+ AC_DEFINE([HandleTopLevelDeclContinue], [true],
+ [Return type of HandleTopLevelDeclReturn])])
+ AC_CHECK_HEADER([clang/Basic/DiagnosticOptions.h],
+ [AC_DEFINE([HAVE_BASIC_DIAGNOSTICOPTIONS_H], [],
+ [Define if clang/Basic/DiagnosticOptions.h exists])])
+ AC_TRY_COMPILE([#include <clang/Basic/TargetInfo.h>], [
+ using namespace clang;
+ std::shared_ptr<TargetOptions> TO;
+ DiagnosticsEngine *Diags;
+ TargetInfo::CreateTargetInfo(*Diags, TO);
+ ], [AC_DEFINE([CREATETARGETINFO_TAKES_SHARED_PTR], [],
+ [Define if TargetInfo::CreateTargetInfo takes shared_ptr])])
+ AC_TRY_COMPILE([#include <clang/Basic/TargetInfo.h>], [
+ using namespace clang;
+ TargetOptions *TO;
+ DiagnosticsEngine *Diags;
+ TargetInfo::CreateTargetInfo(*Diags, TO);
+ ], [AC_DEFINE([CREATETARGETINFO_TAKES_POINTER], [],
+ [Define if TargetInfo::CreateTargetInfo takes pointer])])
+ AC_TRY_COMPILE([#include <clang/Frontend/CompilerInstance.h>], [
+ using namespace clang;
+ DiagnosticConsumer *client;
+ CompilerInstance *Clang;
+ Clang->createDiagnostics(client);
+ ], [], [AC_DEFINE([CREATEDIAGNOSTICS_TAKES_ARG], [],
+ [Define if CompilerInstance::createDiagnostics takes argc and argv])])
+ AC_TRY_COMPILE([#include <clang/Lex/HeaderSearchOptions.h>], [
+ using namespace clang;
+ HeaderSearchOptions HSO;
+ HSO.AddPath("", frontend::Angled, false, false);
+ ], [AC_DEFINE([ADDPATH_TAKES_4_ARGUMENTS], [],
+ [Define if HeaderSearchOptions::AddPath takes 4 arguments])])
+ AC_EGREP_HEADER([getNumParams],
+ [clang/AST/CanonicalType.h],
+ [AC_DEFINE([getNumArgs], [getNumParams],
+ [Define to getNumParams for newer versions of clang])
+ AC_DEFINE([getArgType], [getParamType],
+ [Define to getParamType for newer versions of clang])])
+ AC_EGREP_HEADER([getReturnType],
+ [clang/AST/CanonicalType.h], [],
+ [AC_DEFINE([getReturnType], [getResultType],
+ [Define to getResultType for older versions of clang])])
+ AC_TRY_COMPILE([#include <clang/Frontend/CompilerInstance.h>], [
+ using namespace clang;
+ CompilerInstance *Clang;
+ Clang->createPreprocessor(TU_Complete);
+ ], [AC_DEFINE([CREATEPREPROCESSOR_TAKES_TUKIND], [],
+ [Define if CompilerInstance::createPreprocessor takes
+ TranslationUnitKind])])
+ AC_EGREP_HEADER([setMainFileID], [clang/Basic/SourceManager.h],
+ [AC_DEFINE([HAVE_SETMAINFILEID], [],
+ [Define if SourceManager has a setMainFileID method])])
+ AC_CHECK_HEADER([llvm/ADT/OwningPtr.h],
+ [AC_DEFINE([HAVE_ADT_OWNINGPTR_H], [],
+ [Define if llvm/ADT/OwningPtr.h exists])])
+ AC_LANG_POP
+ CPPFLAGS="$SAVE_CPPFLAGS"
+
+ SAVE_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$CLANG_LDFLAGS $LDFLAGS"
+ AC_SUBST(LIB_CLANG_EDIT)
+ AC_CHECK_LIB([clangEdit], [main], [LIB_CLANG_EDIT=-lclangEdit], [])
+ LDFLAGS="$SAVE_LDFLAGS"
+ ;;
+esac
+AM_CONDITIONAL(HAVE_CLANG, test $with_clang = system)
+
+AX_SET_WARNING_FLAGS
+
+AC_SUBST(WARNING_FLAGS)
+
+PACKAGE_CFLAGS="$MP_CPPFLAGS"
+PACKAGE_LDFLAGS="$MP_LDFLAGS"
+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)
+AC_CONFIG_FILES(Makefile)
+AC_CONFIG_FILES(doc/Makefile)
+if test $with_clang = system; then
+ AC_CONFIG_FILES(interface/Makefile)
+fi
+AC_CONFIG_FILES([bound_test.sh], [chmod +x bound_test.sh])
+AC_CONFIG_FILES([codegen_test.sh], [chmod +x codegen_test.sh])
+AC_CONFIG_FILES([pip_test.sh], [chmod +x pip_test.sh])
+AC_CONFIG_COMMANDS_POST([
+ dnl pass on arguments to subdir configures, but don't
+ dnl add them to config.status
+ ac_configure_args="$ac_configure_args $isl_configure_args"
+])
+AC_OUTPUT
diff --git a/polly/lib/External/isl/doc/Makefile.am b/polly/lib/External/isl/doc/Makefile.am
new file mode 100644
index 00000000000..aa79a6c9516
--- /dev/null
+++ b/polly/lib/External/isl/doc/Makefile.am
@@ -0,0 +1,17 @@
+if GENERATE_DOC
+export TEXINPUTS := $(srcdir):$(TEXINPUTS)
+export BIBINPUTS := $(srcdir):$(BIBINPUTS)
+export BSTINPUTS := $(srcdir):$(BSTINPUTS)
+
+user.tex: user.pod
+ $(PERL) $(srcdir)/mypod2latex $< $@
+manual.pdf: manual.tex user.tex $(srcdir)/implementation.tex
+ (cd ..; echo "@GIT_HEAD_VERSION@") > version.tex
+ $(PDFLATEX) $<
+ bibtex manual
+ $(PDFLATEX) $<
+ $(PDFLATEX) $<
+user.html: user.pod
+ (cd ..; echo "@GIT_HEAD_VERSION@") > version
+ $(POD2HTML) --infile=$< --outfile=$@ --title="Integer Set Library: Manual [version `cat version`]"
+endif
diff --git a/polly/lib/External/isl/doc/SubmittingPatches b/polly/lib/External/isl/doc/SubmittingPatches
new file mode 100644
index 00000000000..2c2b93881bc
--- /dev/null
+++ b/polly/lib/External/isl/doc/SubmittingPatches
@@ -0,0 +1,52 @@
+[Mostly copied from git's SubmittingPatches]
+
+ Commits:
+
+ - make commits of logical units
+ - check for unnecessary whitespace with "git diff --check"
+ before committing
+ - do not check in commented out code or unneeded files
+ - the first line of the commit message should be a short
+ description and should skip the full stop
+ - the body should provide a meaningful commit message, which
+ includes motivation for the change, and contrasts
+ its implementation with previous behaviour
+ - if you want your work included in isl.git, add a
+ "Signed-off-by: Your Name <you@example.com>" line to the
+ commit message (or just use the option "-s" when
+ committing) to confirm that you agree to the Developer's
+ Certificate of Origin
+ - make sure that you have tests for the bug you are fixing
+ - make sure that the test suite passes after your commit
+
+ Patch:
+
+ - use "git format-patch -M" to create the patch
+ - do not PGP sign your patch
+ - send a single patch per mail, e.g., using git-send-email(1)
+ - do not attach your patch, but read in the mail
+ body, unless you cannot teach your mailer to
+ leave the formatting of the patch alone.
+ - be careful doing cut & paste into your mailer, not to
+ corrupt whitespaces.
+ - provide additional information (which is unsuitable for
+ the commit message) between the "---" and the diffstat
+ - if you change, add, or remove a command line option or
+ make some other user interface change, the associated
+ documentation should be updated as well.
+ - if your name is not writable in ASCII, make sure that
+ you send off a message in the correct encoding.
+ - send the patch to the development mailing list
+ (isl-development@googlegroups.com). If you use
+ git-send-email(1), please test it first by sending email
+ to yourself.
+
+ Revisions:
+
+ - add the revision number inside square brackets to
+ the subject line (e.g., use --subject-prefix='PATCH v2'
+ when creating the patch)
+ - recall the major issues discovered during the previous
+ review and explain how you addressed them or why you
+ disagree. Do so either in a cover letter, between the
+ "---" and the diffstat or in a separate message.
diff --git a/polly/lib/External/isl/doc/chicago.bst b/polly/lib/External/isl/doc/chicago.bst
new file mode 100644
index 00000000000..ba058338b97
--- /dev/null
+++ b/polly/lib/External/isl/doc/chicago.bst
@@ -0,0 +1,1726 @@
+%%% ====================================================================
+%%% @BibTeX-style-file{
+%%% author = "Glenn Paulley",
+%%% version = "4",
+%%% date = "28 August 1992",
+%%% time = "10:23:39 199",
+%%% filename = "chicago.bst",
+%%% address = "Data Structuring Group
+%%% Department of Computer Science
+%%% University of Waterloo
+%%% Waterloo, Ontario, Canada
+%%% N2L 3G1",
+%%% telephone = "(519) 885-1211",
+%%% FAX = "(519) 885-1208",
+%%% checksum = "26323 1654 5143 37417",
+%%% email = "gnpaulle@bluebox.uwaterloo.ca",
+%%% codetable = "ISO/ASCII",
+%%% keywords = "",
+%%% supported = "yes",
+%%% abstract = "A BibTeX bibliography style that follows the
+%%% `B' reference style of the 13th Edition of
+%%% the Chicago Manual of Style. A detailed
+%%% feature list is given below.",
+%%% docstring = "The checksum field above contains a CRC-16
+%%% checksum as the first value, followed by the
+%%% equivalent of the standard UNIX wc (word
+%%% count) utility output of lines, words, and
+%%% characters. This is produced by Robert
+%%% Solovay's checksum utility.",
+%%% }
+%%% ====================================================================
+%
+% "Chicago" BibTeX style, chicago.bst
+% ===================================
+%
+% BibTeX `chicago' style file for BibTeX version 0.99c, LaTeX version 2.09
+% Place it in a file called chicago.bst in the BibTeX search path.
+% You need to include chicago.sty as a \documentstyle option.
+% (Placing it in the same directory as the LaTeX document should also work.)
+% This "chicago" style is based on newapa.bst (American Psych. Assoc.)
+% found at ymir.claremont.edu.
+%
+% Citation format: (author-last-name year)
+% (author-last-name and author-last-name year)
+% (author-last-name, author-last-name, and author-last-name year)
+% (author-last-name et al. year)
+% (author-last-name)
+% author-last-name (year)
+% (author-last-name and author-last-name)
+% (author-last-name et al.)
+% (year) or (year,year)
+% year or year,year
+%
+% Reference list ordering: alphabetical by author or whatever passes
+% for author in the absence of one.
+%
+% This BibTeX style has support for abbreviated author lists and for
+% year-only citations. This is done by having the citations
+% actually look like
+%
+% \citeauthoryear{full-author-info}{abbrev-author-info}{year}
+%
+% The LaTeX style has to have the following (or similar)
+%
+% \let\@internalcite\cite
+% \def\fullcite{\def\citeauthoryear##1##2##3{##1, ##3}\@internalcite}
+% \def\fullciteA{\def\citeauthoryear##1##2##3{##1}\@internalcite}
+% \def\shortcite{\def\citeauthoryear##1##2##3{##2, ##3}\@internalcite}
+% \def\shortciteA{\def\citeauthoryear##1##2##3{##2}\@internalcite}
+% \def\citeyear{\def\citeauthoryear##1##2##3{##3}\@internalcite}
+%
+% These TeX macro definitions are found in chicago.sty. Additional
+% commands to manipulate different components of a citation can be defined
+% so that, for example, you can list author's names without parentheses
+% if using a citation as a noun or object in a sentence.
+%
+% This file was originally copied from newapa.bst at ymir.claremont.edu.
+%
+% Features of chicago.bst:
+% =======================
+%
+% - full names used in citations, but abbreviated citations are available
+% (see above)
+% - if an entry has a "month", then the month and year are also printed
+% as part of that bibitem.
+% - all conjunctions use "and" instead of "\&"
+% - major modification from Chicago Manual of Style (13th ed.) is that
+% only the first author in a reference appears last name first-
+% additional authors appear as J. Q. Public.
+% - pages are listed as "pp. xx-xx" in all entry types except
+% article entries.
+% - book, inbook, and manual use "location: publisher" (or organization)
+% for address and publisher. All other types list publishers separately.
+% - "pp." are used to identify page numbers for all entry types except
+% articles.
+% - organization is used as a citation label if neither author nor editor
+% is present (for manuals).
+% - "et al." is used for long author and editor lists, or when "others"
+% is used.
+%
+% Modifications and bug fixes from newapa.bst:
+% ===========================================
+%
+% - added month, year to bib entries if month is present
+% - fixed bug with In proceedings, added necessary comma after title
+% - all conjunctions changed to "and" from "\&"
+% - fixed bug with author labels in my.full.label: "et al." now is
+% generated when "others" is an author name
+% - major modification from Chicago Manual of Style (13th ed.) is that
+% only the first author in a reference appears last name first-
+% additional authors appear as J. Q. Public.
+% - pages are listed as "pp. xx-xx" in all entry types except
+% article entries. Unnecessary (IMHO) "()" around page numbers
+% were removed, and page numbers now don't end with a period.
+% - created chicago.sty for use with this bibstyle (required).
+% - fixed bugs in FUNCTION {format.vol.num.pages} for missing volume,
+% number, and /or pages. Renamed to format.jour.vol.
+% - fixed bug in formatting booktitles: additional period an error if
+% book has a volume.
+% - fixed bug: editors usually given redundant period before next clause
+% (format.editors.dot) removed.
+% - added label support for organizations, if both author and editor
+% are missing (from alpha.bst). If organization is too long, then
+% the key field is used for abbreviated citations.
+% - In proceedings or books of several volumes, no comma was written
+% between the "Volume x" and the page numbers (this was intentional
+% in newapa.bst). Fixed.
+% - Some journals may not have volumes/numbers, only month/year (eg.
+% IEEE Computer). Fixed bug in article style that assumed volume/number
+% was always present.
+%
+% Original documentation for newapa.sty:
+% =====================================
+%
+% This version was made by modifying the master file made by
+% Oren Patashnik (PATASHNIK@SCORE.STANFORD.EDU), and the 'named' BibTeX
+% style of Peter F. Patel-Schneider.
+%
+% Copyright (C) 1985, all rights reserved.
+% Copying of this file is authorized only if either
+% (1) you make absolutely no changes to your copy, including name, or
+% (2) if you do make changes, you name it something other than 'newapa.bst'.
+% There are undoubtably bugs in this style. If you make bug fixes,
+% improvements, etc. please let me know. My e-mail address is:
+% spencer@cgrg.ohio.state.edu or 71160.3141@compuserve.com
+%
+% This style was made from 'plain.bst', 'named.bst', and 'apalike.bst',
+% with lots of tweaking to make it look like APA style, along with tips
+% from Young Ryu and Brian Reiser's modifications of 'apalike.bst'.
+
+ENTRY
+ { address
+ author
+ booktitle
+ chapter
+ edition
+ editor
+ fjournal
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ volume
+ year
+ }
+ {}
+ { label.year extra.label sort.year sort.label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t u }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+% Use a colon to separate output. Used only for address/publisher
+% combination in book/inbook types, address/institution for manuals,
+% and organization:publisher for proceedings (inproceedings).
+%
+FUNCTION {output.nonnull.colon}
+{ 's :=
+ output.state mid.sentence =
+ { ": " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.colon}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check.colon}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.year.check}
+{ year empty$
+ { "empty year in " cite$ * warning$ }
+ { write$
+ " (" year * extra.label *
+ month empty$
+ { ")" * }
+ { ", " * month * ")" * }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+}
+
+
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+%
+% Emphasize the top string on the stack.
+%
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+%
+% Emphasize the top string on the stack, but add a trailing space.
+%
+FUNCTION {emphasize.space}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "\/}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+%
+% Format bibliographical entries with the first author last name first,
+% and subsequent authors with initials followed by last name.
+% All names are formatted in this routine.
+%
+FUNCTION {format.names}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { nameptr #1 =
+ {s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't := }
+ {s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't := }
+ if$
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't :=
+ "\protect \index {" * t * "|hyperemph}" *
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {my.full.label}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{vv~}{ll}" format.name$ 't := % get the next name
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't :=
+ "\protect \index {" * t * "|bold}" *
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+
+}
+
+FUNCTION {format.names.fml}
+%
+% Format names in "familiar" format, with first initial followed by
+% last name. Like format.names, ALL names are formatted.
+%
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't :=
+
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * }
+% { " \& " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+ { "" }
+ { author format.names }
+ if$
+}
+
+FUNCTION {format.key}
+{ empty$
+ { key field.or.null }
+ { "" }
+ if$
+}
+
+%
+% Format editor names for use in the "in" types: inbook, incollection,
+% inproceedings: first initial, then last names. When editors are the
+% LABEL for an entry, then format.editor is used which lists editors
+% by last name first.
+%
+FUNCTION {format.editors.fml}
+{ editor empty$
+ { "" }
+ { editor format.names.fml
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+%
+% Format editor names for use in labels, last names first.
+%
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor format.names
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ { title "t" change.case$ }
+ if$
+}
+
+% Note that the APA style requres case changes
+% in article titles. The following does not
+% change cases. If you perfer it, uncomment the
+% following and comment out the above.
+
+%FUNCTION {format.title}
+%{ title empty$
+% { "" }
+% { title }
+% if$
+%}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.btitle}
+{ edition empty$
+ { title emphasize }
+ { title empty$
+ { title emphasize }
+ { volume empty$ % gnp - check for volume, then don't need period
+ { "{\em " title * "\/} (" * edition * " ed.)" * "." * }
+ { "{\em " title * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.emphasize.booktitle}
+{ edition empty$
+ { booktitle emphasize }
+ { booktitle empty$
+ { booktitle emphasize }
+ { volume empty$ % gnp - extra period an error if book has a volume
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * "." *}
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+ }
+
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ series empty$
+ 'skip$
+ { " of " * series emphasize * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { "Number" } % gnp - changed to mixed case always
+ { "Number" }
+ if$
+ number tie.or.space.connect
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { " in " * series * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "pp.\ " pages n.dashify tie.or.space.connect } % gnp - removed ()
+ { "pp.\ " pages tie.or.space.connect }
+ if$
+ }
+ if$
+}
+
+% By Young (and Spencer)
+% GNP - fixed bugs with missing volume, number, and/or pages
+%
+% Format journal, volume, number, pages for article types.
+%
+FUNCTION {format.jour.vol}
+{ fjournal empty$
+ { journal empty$
+ { "no journal in " cite$ * warning$
+ "" }
+ { journal emphasize.space }
+ if$
+ }
+ { fjournal emphasize.space }
+ if$
+ number empty$
+ { volume empty$
+ { "no number and no volume in " cite$ * warning$
+ "" * }
+ { "~{\em " * Volume * "}" * }
+ if$
+ }
+ { volume empty$
+ {"no volume for " cite$ * warning$
+ "~(" * number * ")" * }
+ { "~" *
+ volume emphasize.space
+ "(" * number * ")" * * }
+ if$
+ }
+ if$
+ pages empty$
+ {"page numbers missing in " cite$ * warning$
+ "" * } % gnp - place a null string on the stack for output
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { ", " * pages n.dashify * } % gnp - removed pp. for articles
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "Chapter" } % gnp - changed to mixed case
+ { type "t" change.case$ }
+ if$
+ chapter tie.or.space.connect
+ pages empty$
+ {"page numbers missing in " cite$ * warning$} % gnp - added check
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ { editor empty$
+ { "In " format.emphasize.booktitle * }
+ { "In " format.editors.fml * ", " * format.emphasize.booktitle * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+ { "Technical Report" }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ }
+ { number tie.or.space.connect }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ "See"
+ "\citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ editor num.names$ duplicate$
+ #2 >
+ { pop$ " et~al." * }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ "In "
+ }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ " of " *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { "{\em " * series * "\/}" * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ "See"
+ " \citeN{" * crossref * "}" *
+}
+
+% format.lab.names:
+%
+% determines "short" names for the abbreviated author information.
+% "Long" labels are created in calc.label, using the routine my.full.label
+% to format author and editor fields.
+%
+% There are 4 cases for labels. (n=3 in the example)
+% a) one author Foo
+% b) one to n Foo, Bar and Baz
+% c) use of "and others" Foo, Bar et al.
+% d) more than n Foo et al.
+%
+FUNCTION {format.lab.names}
+{ 's :=
+ s num.names$ 'numnames :=
+ numnames #2 > % change number to number of others allowed before
+ % forcing "et al".
+ { s #1 "{vv~}{ll}" format.name$
+ "\protect \index {" *
+ s #1 "{vv~}{ll}{, jj}{, f.}" format.name$ *
+ "}" *
+ "\protect\chicagoetal/" * }
+ {
+ numnames #1 - 'namesleft :=
+ #2 'nameptr :=
+ s #1 "{vv~}{ll}" format.name$
+ "\protect \index {" *
+ s #1 "{vv~}{ll}{, jj}{, f.}" format.name$ *
+ "}" *
+ { namesleft #0 > }
+ { nameptr numnames =
+ { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { "\protect\chicagoetal/" * }
+ { "\protect\chicagoand/" * s nameptr "{vv~}{ll}" format.name$ *
+ "\protect \index {" *
+ s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ *
+ "}" *
+ }
+ if$
+ }
+ { ", " * s nameptr "{vv~}{ll}" format.name$ * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ }
+ if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+ { key empty$
+ { "no key, author in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+ { key empty$
+ { "no key, editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if author is null.
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "no key, author or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if editor is null.
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "no key, editor or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "no key, author, or editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {calc.label.orig}
+%
+% Changed - GNP. See also author.organization.sort, editor.organization.sort
+% Form label for BibTeX entry. The classification of which fields are used
+% for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+% The change here from newapa is to also include organization as a
+% citation label if author or editor is missing.
+%
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.label
+ { type$ "proceedings" =
+ 'editor.key.organization.label
+ { type$ "manual" =
+ 'author.key.organization.label
+ 'author.key.label
+ if$
+ }
+ if$
+ }
+ if$
+
+ author empty$ % generate the full label citation information.
+ { editor empty$
+ { organization empty$
+ { "no author, editor, or organization in " cite$ * warning$
+ "??" }
+ { organization }
+ if$
+ }
+ { editor my.full.label }
+ if$
+ }
+ { author.key.label }
+ if$
+
+% leave label on the stack, to be popped when required.
+
+ "}{" * swap$ *
+% year field.or.null purify$ #-1 #4 substring$ *
+%
+% save the year for sort processing afterwards (adding a, b, c, etc.)
+%
+ year field.or.null purify$ #-1 #4 substring$
+ 'label.year :=
+}
+
+FUNCTION {calc.label}
+%
+% Changed - GNP. See also author.organization.sort, editor.organization.sort
+% Form label for BibTeX entry. The classification of which fields are used
+% for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+% The change here from newapa is to also include organization as a
+% citation label if author or editor is missing.
+%
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.label
+ { type$ "proceedings" =
+ 'editor.key.organization.label
+ { type$ "manual" =
+ 'author.key.organization.label
+ 'author.key.label
+ if$
+ }
+ if$
+ }
+ if$
+
+ author empty$ % generate the full label citation information.
+ { editor empty$
+ { organization empty$
+ { "no author, editor, or organization in " cite$ * warning$
+ "??" }
+ { organization }
+ if$
+ }
+ { editor my.full.label }
+ if$
+ }
+ { author my.full.label }
+ if$
+
+% leave label on the stack, to be popped when required.
+
+ "}{" * swap$ * "}{" * title * "}{" *
+% year field.or.null purify$ #-1 #4 substring$ *
+%
+% save the year for sort processing afterwards (adding a, b, c, etc.)
+%
+ year field.or.null purify$ #-1 #4 substring$
+ 'label.year :=
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+
+ "\bibitem[\protect\citeauthortitleyear{" write$
+ calc.label write$
+ sort.year write$
+ "}]{" write$
+
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.jour.vol output
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check }
+ { format.authors
+ output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ howpublished output
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check
+ }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages
+ "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher
+ "publisher" output.check.colon
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output % gnp - was special.output.nonnull
+% left out comma before page numbers
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { format.incoll.inproc.crossref
+ output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ format.pages output
+ new.sentence
+ organization output
+ publisher output.colon
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { editor empty$
+ { organization "organization" output.check
+ organization format.key output } % if all else fails, use key
+ { format.editors "author and editor" output.check }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ organization address new.block.checkb
+% Reversed the order of "address" and "organization", added the ":".
+ address output
+ organization "organization" output.check.colon
+% address output
+% ":" output
+% organization output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ "Master's thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ title howpublished new.block.checkb
+ format.title output
+ new.block
+ howpublished output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ new.block
+ "Ph.\ D. thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization output
+ organization format.key output } % gnp - changed from author format.key
+ { format.editors output.nonnull }
+ if$
+% author format.key output % gnp - removed (should be either
+% editor or organization
+ output.year.check % added (newapa)
+ new.block
+ format.btitle
+ "title" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ new.sentence
+ organization output
+ publisher output.colon
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution
+ "institution" output.check
+ address output
+ new.block
+ note output
+ fin.entry
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ note "note" output.check
+ fin.entry
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"January"}
+
+MACRO {feb} {"February"}
+
+MACRO {mar} {"March"}
+
+MACRO {apr} {"April"}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"August"}
+
+MACRO {sep} {"September"}
+
+MACRO {oct} {"October"}
+
+MACRO {nov} {"November"}
+
+MACRO {dec} {"December"}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {ai} {"Artificial Intelligence"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+ {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+
+
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { nameptr #2 =
+ { year field.or.null purify$ #-1 #4 substring$ * }
+ 'skip$
+ if$
+ nameptr #1 >
+ { " " * }
+ 'skip$
+ if$
+ s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't :=
+ nameptr numnames = t "others" = and
+ { " et~al" * }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ "" }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.sort}
+{ editor empty$
+ { key empty$
+ { "to sort, need editor or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+ { "missing author in " cite$ * warning$
+ editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.organization.sort}
+%
+% added - GNP. Stack author or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.organization.sort}
+%
+% added - GNP. Stack editor or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {presort}
+%
+% Presort creates the bibentry's label via a call to calc.label, and then
+% sorts the entries based on entry type. Chicago.bst adds support for
+% including organizations as the sort key; the following is stolen from
+% alpha.bst.
+%
+{ %calc.label sortify % recalculate bibitem label
+ %year field.or.null purify$ #-1 #4 substring$ * % add year
+ %duplicate$ warning$
+ %" "
+ %*
+ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ #1 entry.max$ substring$ % added for newapa
+ 'sort.label := % added for newapa
+ sort.label % added for newapa
+ %*
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT % by label, year, author/editor, title
+
+STRINGS { last.label next.extra }
+
+INTEGERS { last.extra.num }
+
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+ "" 'next.extra :=
+ #0 'last.extra.num :=
+}
+
+FUNCTION {forward.pass}
+%
+% Pass through all entries, comparing current entry to last one.
+% Need to concatenate year to the stack (done by calc.label) to determine
+% if two entries are the same (see presort)
+%
+{ last.label
+ calc.label.orig year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ = % are they equal?
+ { last.extra.num #1 + 'last.extra.num :=
+ last.extra.num int.to.chr$ 'extra.label :=
+ }
+ { "a" chr.to.int$ 'last.extra.num :=
+ "" 'extra.label :=
+ calc.label.orig year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ 'last.label := % assign to last.label
+ }
+ if$
+}
+
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+ { "a" 'extra.label := }
+ 'skip$
+ if$
+ label.year extra.label * 'sort.year :=
+ extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+
+ITERATE {forward.pass}
+
+REVERSE {reverse.pass}
+
+FUNCTION {bib.sort.order}
+{ sort.label
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {bib.sort.order}
+
+SORT % by sort.label, year, title --- giving final bib. order.
+
+FUNCTION {begin.bib}
+
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{}" write$ newline$
+}
+
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib}
+
diff --git a/polly/lib/External/isl/doc/chicago.sty b/polly/lib/External/isl/doc/chicago.sty
new file mode 100644
index 00000000000..33588dba923
--- /dev/null
+++ b/polly/lib/External/isl/doc/chicago.sty
@@ -0,0 +1,320 @@
+% -*- LaTeX -*-
+%%% ====================================================================
+%%% @LaTeX-style-file{
+%%% author = "Glenn Paulley",
+%%% version = "4",
+%%% date = "31 August 1992",
+%%% time = "09:42:44 199",
+%%% filename = "chicago.sty",
+%%% address = "Data Structuring Group
+%%% Department of Computer Science
+%%% University of Waterloo
+%%% Waterloo, Ontario, Canada
+%%% N2L 3G1",
+%%% telephone = "(519) 885-1211",
+%%% FAX = "(519) 885-1208",
+%%% checksum = "44674 264 1050 10394",
+%%% email = "gnpaulle@bluebox.uwaterloo.ca",
+%%% codetable = "ISO/ASCII",
+%%% keywords = "",
+%%% supported = "yes",
+%%% abstract = "Contains the LaTeX style command definitions
+%%% for the Chicago BibTeX styles chicago.bst and
+%%% chicagoa.bst. For details, see below.",
+%%% docstring = "The checksum field above contains a CRC-16
+%%% checksum as the first value, followed by the
+%%% equivalent of the standard UNIX wc (word
+%%% count) utility output of lines, words, and
+%%% characters. This is produced by Robert
+%%% Solovay's checksum utility.",
+%%% }
+%%% ====================================================================
+%
+% chicago.sty: Style file for use with bibtex style chicago.bst, for
+% bibliographies formatted according to the 13th Edition of the Chicago
+% Manual of Style.
+%
+% 'newapa.bst' was made from 'plain.bst', 'named.bst', and 'apalike.bst',
+% with lots of tweaking to make it look like APA style, along with tips
+% from Young Ryu and Brian Reiser's modifications of 'apalike.bst'.
+% newapa.sty formed the basis of this style, chicago.sty. Author-date
+% references in newapa.bst formed the basis for chicago.bst. Chicagoa.bst
+% supports annotations.
+%
+% Version 4 (August, 1992):
+% - fixed chicago.bst and chicagoa.bst to handle long author lists in
+% sorting
+% - fixed chicago.bst and chicagoa.bst so that missing page numbers in
+% ``article'' entries are handled correctly
+% - modified chicago.sty to format entries with 2nd and subsequent lines
+% indented.
+%
+% Citation format: (author-last-name year)
+% (author-last-name and author-last-name year)
+% (author-last-name et al. year)
+% (author-last-name)
+% author-last-name
+% author-last-name (year)
+% (author-last-name and author-last-name)
+% (author-last-name et al.)
+% (year) or (year,year)
+% year or year,year
+%
+% Reference list ordering: alphabetical by author or whatever passes
+% for author in the absence of one.
+%
+% This BibTeX style has support for abbreviated author lists and for
+% year-only citations. This is done by having the citations
+% actually look like
+%
+% \citeauthoryear{full-author-info}{abbrev-author-info}{year}
+%
+% The LaTeX style has to have the following (or similar)
+%
+% \let\@internalcite\cite
+% \def\fullcite{\def\citeauthoryear##1##2##3{##1, ##3}\@internalcite}
+% \def\fullciteA{\def\citeauthoryear##1##2##3{##1}\@internalcite}
+% \def\shortcite{\def\citeauthoryear##1##2##3{##2, ##3}\@internalcite}
+% \def\shortciteA{\def\citeauthoryear##1##2##3{##2}\@internalcite}
+% \def\citeyear{\def\citeauthoryear##1##2##3{##3}\@internalcite}
+%
+% -------------------------------------------------------------------------
+% This file implements citations for the ``chicago'' bibliography style.
+% Place it in a file called chicago.sty in the TeX search path.
+%(Placing it in the same directory as the LaTeX document should also work.)
+%
+% This file is a modification of the ``newapa'' LaTeX style,
+% originally adapted by Steven Spencer from the ``apalike'' LaTeX style.
+% It was originally modified by Stephen N. Spencer, with further
+% modifications by Young U. Ryu.
+%
+% The ``chicago'' BibTeX bibliography style creates citations with labels:
+% \citeauthoryear{author-info}{abbrev. author-info}{year}
+%
+% These labels are processed by the following LaTeX commands:
+%
+% \cite{key}
+% which produces citations with full author list and year.
+% eg. (Brown 1978; Jarke, Turner, Stohl, et al. 1985)
+% \citeNP{key}
+% which produces citations with full author list and year, but without
+% enclosing parentheses:
+% eg. Brown 1978; Jarke, Turner and Stohl 1985
+% \citeA{key}
+% which produces citations with only the full author list.
+% eg. (Brown; Jarke, Turner and Stohl)
+% \citeANP{key}
+% which produces citations with only the full author list, without
+% parentheses eg. Brown; Jarke, Turner and Stohl
+% \citeN{key}
+% which produces citations with the full author list and year, but
+% can be used as nouns in a sentence; no parentheses appear around
+% the author names, but only around the year.
+% eg. Shneiderman (1978) states that......
+% \citeN should only be used for a single citation.
+% \shortcite{key}
+% which produces citations with abbreviated author list and year.
+% \shortciteNP{key}
+% which produces citations with abbreviated author list and year.
+% \shortciteA{key}
+% which produces only the abbreviated author list.
+% \shortciteANP{key}
+% which produces only the abbreviated author list.
+% \shortciteN{key}
+% which produces the abbreviated author list and year, with only the
+% year in parentheses. Use with only one citation.
+% \citeyear{key}
+% which produces the year information only, within parentheses.
+% \citeyearNP{key}
+% which produces the year information only.
+%
+% Abbreviated author lists use the ``et al.'' construct.
+%
+% `NP' means `no parentheses'.
+%
+% This LaTeX style file must be used with the ``chicago'' or ``chicagoa''
+% (annotated chicago style) BibTeX styles.
+%
+\typeout{Using Chicago Manual of Style bibliography: 31 August 1992}
+%
+% -------------------------------------------------------------------------
+%
+% Citation macros.
+%
+\def\chicagoand/{ and }
+\def\chicagoetal/{ et~al.}
+%
+\let\@internalcite\cite
+%
+\def\cite{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthortitleyear##1##2##3##4{##1\ ##4}\@internalcite}
+\def\citeNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##1\ ##4}\@internalcite}
+\def\citetitleN{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2)\else{)}\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##3\ (##1; ##4}\@citedata}
+\def\citeN{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2)\else{)}\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##1\ (##4}\@citedata}
+\def\citeA{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthortitleyear##1##2##3##4{##1}\@internalcite}
+\def\citeANP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##1}\@internalcite}
+%
+\def\shortcite{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthortitleyear##1##2##3##4{##2\ ##4}\@internalcite}
+\def\shortciteNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##2\ ##4}\@internalcite}
+\def\shortciteN{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2)\else{)}\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##2\ (##4}\@citedata}
+\def\shortciteA{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthortitleyear##1##2##3##4{##2}\@internalcite}
+\def\shortciteANP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##2}\@internalcite}
+%
+\def\citeyear{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{(##1\if@tempswa , ##2\fi)}%
+ \def\citeauthortitleyear##1##2##3##4{##4}\@citedata}
+\def\citeyearNP{\def\@citeseppen{-1000}%
+ \def\@cite##1##2{##1\if@tempswa , ##2\fi}%
+ \def\citeauthortitleyear##1##2##3##4{##4}\@citedata}
+
+%
+% \@citedata and \@citedatax:
+%
+% Place commas in-between citations in the same \citeyear, \citeyearNP,
+% \citeN, or \shortciteN command.
+% Use something like \citeN{ref1,ref2,ref3} and \citeN{ref4} for a list.
+%
+\def\@citedata{%
+ \@ifnextchar [{\@tempswatrue\@citedatax}%
+ {\@tempswafalse\@citedatax[]}%
+}
+
+\def\@citedatax[#1]#2{%
+\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
+ \def\@citea{}\@cite{\@for\@citeb:=#2\do%
+ {\@citea\def\@citea{), }\@ifundefined% by Young
+ {b@\@citeb}{{\bf ?}%
+ \@warning{Citation `\@citeb' on page \thepage \space undefined}}%
+{\csname b@\@citeb\endcsname}}}{#1}}%
+
+\@ifpackageloaded{hyperref}{%
+ \let\BRorg@citedatax\@citedatax
+ \def\@citedatax[#1]#2{%
+ \BRorg@citedatax[#1]{#2}%
+ \Hy@backout{#2}%
+ }%
+}{}
+\@ifpackageloaded{hyperref}{%
+\def\hyperemph#1{{\em\hyperpage{#1}}}%
+\def\bold#1{{\bf\hyperpage{#1}}}%
+}{%
+\def\hyperemph#1{{\em #1}}%
+\def\bold#1{{\bf #1}}%
+}
+
+\def\BR@@lbibitem[#1]#2#3\par{%
+ \BRorg@bibitem[#1]{#2}#3\hfill\penalty100\hbox{}
+ \newblock
+ \backref\hfill[{\csname br@#2\endcsname}%
+ ]\parskip=-10pt\penalty-10000\hbox{}\nobreak\par
+}%
+\def\BR@@bibitem#1#2\par{%
+ \BRorg@bibitem{#1}#2
+ \newblock
+ \backref\penalty-100\hbox{}\nobreak\hfill[\hbox{\csname br@#2\endcsname}%
+ ]\par
+}
+\def\thepageorcolor{\thepage}
+\def\Hy@backout#1{%
+ \@bsphack
+ \ifx\@empty\@currentlabel
+ \protected@write\@auxout{}{%
+ \string\@writefile{brf}{%
+ \string\backcite{#1}{{\thepageorcolor}{(document)}{Doc-Start}}%
+ }%
+ }%
+ \else
+ \protected@write\@auxout{}{%
+ \string\@writefile{brf}{%
+ \string\backcite{#1}{{\thepageorcolor}{\@currentlabel}{\@currentHref}}%
+ }%
+ }%
+ \fi
+ \@esphack
+}
+
+% don't box citations, separate with ; and a space
+% also, make the penalty between citations negative: a good place to break.
+%
+\def\@citex[#1]#2{%
+\if@filesw\immediate\write\@auxout{\string\citation{#2}}\fi%
+ \def\@citea{}\@cite{\@for\@citeb:=#2\do%
+ {\@citea\def\@citea{; }\@ifundefined% by Young
+ {b@\@citeb}{{\bf ?}%
+ \@warning{Citation `\@citeb' on page \thepage \space undefined}}%
+{\csname b@\@citeb\endcsname}}}{#1}}%
+
+% (from apalike.sty)
+% No labels in the bibliography.
+%
+\def\@biblabel#1{}
+
+% (from apalike.sty)
+% Set length of hanging indentation for bibliography entries.
+%
+\newlength{\bibhang}
+\setlength{\bibhang}{2em}
+
+% Indent second and subsequent lines of bibliographic entries. Stolen
+% from openbib.sty: \newblock is set to {}.
+
+\newdimen\bibindent
+\bibindent=1.5em
+\@ifundefined{refname}%
+ {\@ifundefined{chapter}%
+ {\newcommand{\refname}{References}}%
+ {\newcommand{\refname}{Bibliography}}%
+ }%
+ {}%
+\@ifundefined{chapter}%
+ {\def\thebibliography#1{\section*{\refname\@mkboth
+ {\uppercase{\refname}}{\uppercase{\refname}}}
+ \addcontentsline{toc}{section}{References}
+ \list
+ {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}
+ \leftmargin\labelwidth
+ \advance\leftmargin\labelsep
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \usecounter{enumi}}
+ \def\newblock{}
+ \sloppy
+ \sfcode`\.=1000\relax}}
+ {\def\thebibliography#1{\chapter*{\refname\@mkboth
+ {\refname}{\refname}}
+ \addcontentsline{toc}{chapter}{References}
+ \list
+ {[\arabic{enumi}]}{\settowidth\labelwidth{[#1]}
+ \leftmargin\labelwidth
+ \advance\leftmargin\labelsep
+ \advance\leftmargin\bibindent
+ \itemindent -\bibindent
+ \listparindent \itemindent
+ \parsep \z@
+ \usecounter{enumi}}
+ \def\newblock{}
+ \sloppy
+ \sfcode`\.=1000\relax}}
diff --git a/polly/lib/External/isl/doc/implementation.tex b/polly/lib/External/isl/doc/implementation.tex
new file mode 100644
index 00000000000..76d1acd5896
--- /dev/null
+++ b/polly/lib/External/isl/doc/implementation.tex
@@ -0,0 +1,2036 @@
+\section{Sets and Relations}
+
+\begin{definition}[Polyhedral Set]
+A {\em polyhedral set}\index{polyhedral set} $S$ is a finite union of basic sets
+$S = \bigcup_i S_i$, each of which can be represented using affine
+constraints
+$$
+S_i : \Z^n \to 2^{\Z^d} : \vec s \mapsto
+S_i(\vec s) =
+\{\, \vec x \in \Z^d \mid \exists \vec z \in \Z^e :
+A \vec x + B \vec s + D \vec z + \vec c \geq \vec 0 \,\}
+,
+$$
+with $A \in \Z^{m \times d}$,
+$B \in \Z^{m \times n}$,
+$D \in \Z^{m \times e}$
+and $\vec c \in \Z^m$.
+\end{definition}
+
+\begin{definition}[Parameter Domain of a Set]
+Let $S \in \Z^n \to 2^{\Z^d}$ be a set.
+The {\em parameter domain} of $S$ is the set
+$$\pdom S \coloneqq \{\, \vec s \in \Z^n \mid S(\vec s) \ne \emptyset \,\}.$$
+\end{definition}
+
+\begin{definition}[Polyhedral Relation]
+A {\em polyhedral relation}\index{polyhedral relation}
+$R$ is a finite union of basic relations
+$R = \bigcup_i R_i$ of type
+$\Z^n \to 2^{\Z^{d_1+d_2}}$,
+each of which can be represented using affine
+constraints
+$$
+R_i = \vec s \mapsto
+R_i(\vec s) =
+\{\, \vec x_1 \to \vec x_2 \in \Z^{d_1} \times \Z^{d_2}
+\mid \exists \vec z \in \Z^e :
+A_1 \vec x_1 + A_2 \vec x_2 + B \vec s + D \vec z + \vec c \geq \vec 0 \,\}
+,
+$$
+with $A_i \in \Z^{m \times d_i}$,
+$B \in \Z^{m \times n}$,
+$D \in \Z^{m \times e}$
+and $\vec c \in \Z^m$.
+\end{definition}
+
+\begin{definition}[Parameter Domain of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation.
+The {\em parameter domain} of $R$ is the set
+$$\pdom R \coloneqq \{\, \vec s \in \Z^n \mid R(\vec s) \ne \emptyset \,\}.$$
+\end{definition}
+
+\begin{definition}[Domain of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation.
+The {\em domain} of $R$ is the polyhedral set
+$$\domain R \coloneqq \vec s \mapsto
+\{\, \vec x_1 \in \Z^{d_1} \mid \exists \vec x_2 \in \Z^{d_2} :
+(\vec x_1, \vec x_2) \in R(\vec s) \,\}
+.
+$$
+\end{definition}
+
+\begin{definition}[Range of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation.
+The {\em range} of $R$ is the polyhedral set
+$$
+\range R \coloneqq \vec s \mapsto
+\{\, \vec x_2 \in \Z^{d_2} \mid \exists \vec x_1 \in \Z^{d_1} :
+(\vec x_1, \vec x_2) \in R(\vec s) \,\}
+.
+$$
+\end{definition}
+
+\begin{definition}[Composition of Relations]
+Let $R \in \Z^n \to 2^{\Z^{d_1+d_2}}$ and
+$S \in \Z^n \to 2^{\Z^{d_2+d_3}}$ be two relations,
+then the composition of
+$R$ and $S$ is defined as
+$$
+S \circ R \coloneqq
+\vec s \mapsto
+\{\, \vec x_1 \to \vec x_3 \in \Z^{d_1} \times \Z^{d_3}
+\mid \exists \vec x_2 \in \Z^{d_2} :
+\vec x_1 \to \vec x_2 \in R(\vec s) \wedge
+\vec x_2 \to \vec x_3 \in S(\vec s)
+\,\}
+.
+$$
+\end{definition}
+
+\begin{definition}[Difference Set of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation.
+The difference set ($\Delta \, R$) of $R$ is the set
+of differences between image elements and the corresponding
+domain elements,
+$$
+\diff R \coloneqq
+\vec s \mapsto
+\{\, \vec \delta \in \Z^{d} \mid \exists \vec x \to \vec y \in R :
+\vec \delta = \vec y - \vec x
+\,\}
+$$
+\end{definition}
+
+\section{Simple Hull}\label{s:simple hull}
+
+It is sometimes useful to have a single
+basic set or basic relation that contains a given set or relation.
+For rational sets, the obvious choice would be to compute the
+(rational) convex hull. For integer sets, the obvious choice
+would be the integer hull.
+However, {\tt isl} currently does not support an integer hull operation
+and even if it did, it would be fairly expensive to compute.
+The convex hull operation is supported, but it is also fairly
+expensive to compute given only an implicit representation.
+
+Usually, it is not required to compute the exact integer hull,
+and an overapproximation of this hull is sufficient.
+The ``simple hull'' of a set is such an overapproximation
+and it is defined as the (inclusion-wise) smallest basic set
+that is described by constraints that are translates of
+the constraints in the input set.
+This means that the simple hull is relatively cheap to compute
+and that the number of constraints in the simple hull is no
+larger than the number of constraints in the input.
+\begin{definition}[Simple Hull of a Set]
+The {\em simple hull} of a set
+$S = \bigcup_{1 \le i \le v} S_i$, with
+$$
+S : \Z^n \to 2^{\Z^d} : \vec s \mapsto
+S(\vec s) =
+\left\{\, \vec x \in \Z^d \mid \exists \vec z \in \Z^e :
+\bigvee_{1 \le i \le v}
+A_i \vec x + B_i \vec s + D_i \vec z + \vec c_i \geq \vec 0 \,\right\}
+$$
+is the set
+$$
+H : \Z^n \to 2^{\Z^d} : \vec s \mapsto
+S(\vec s) =
+\left\{\, \vec x \in \Z^d \mid \exists \vec z \in \Z^e :
+\bigwedge_{1 \le i \le v}
+A_i \vec x + B_i \vec s + D_i \vec z + \vec c_i + \vec K_i \geq \vec 0
+\,\right\}
+,
+$$
+with $\vec K_i$ the (component-wise) smallest non-negative integer vectors
+such that $S \subseteq H$.
+\end{definition}
+The $\vec K_i$ can be obtained by solving a number of
+LP problems, one for each element of each $\vec K_i$.
+If any LP problem is unbounded, then the corresponding constraint
+is dropped.
+
+\section{Parametric Integer Programming}
+
+\subsection{Introduction}\label{s:intro}
+
+Parametric integer programming \shortcite{Feautrier88parametric}
+is used to solve many problems within the context of the polyhedral model.
+Here, we are mainly interested in dependence analysis \shortcite{Fea91}
+and in computing a unique representation for existentially quantified
+variables. The latter operation has been used for counting elements
+in sets involving such variables
+\shortcite{BouletRe98,Verdoolaege2005experiences} and lies at the core
+of the internal representation of {\tt isl}.
+
+Parametric integer programming was first implemented in \texttt{PipLib}.
+An alternative method for parametric integer programming
+was later implemented in {\tt barvinok} \cite{barvinok-0.22}.
+This method is not based on Feautrier's algorithm, but on rational
+generating functions \cite{Woods2003short} and was inspired by the
+``digging'' technique of \shortciteN{DeLoera2004Three} for solving
+non-parametric integer programming problems.
+
+In the following sections, we briefly recall the dual simplex
+method combined with Gomory cuts and describe some extensions
+and optimizations. The main algorithm is applied to a matrix
+data structure known as a tableau. In case of parametric problems,
+there are two tableaus, one for the main problem and one for
+the constraints on the parameters, known as the context tableau.
+The handling of the context tableau is described in \autoref{s:context}.
+
+\subsection{The Dual Simplex Method}
+
+Tableaus can be represented in several slightly different ways.
+In {\tt isl}, the dual simplex method uses the same representation
+as that used by its incremental LP solver based on the \emph{primal}
+simplex method. The implementation of this LP solver is based
+on that of {\tt Simplify} \shortcite{Detlefs2005simplify}, which, in turn,
+was derived from the work of \shortciteN{Nelson1980phd}.
+In the original \shortcite{Nelson1980phd}, the tableau was implemented
+as a sparse matrix, but neither {\tt Simplify} nor the current
+implementation of {\tt isl} does so.
+
+Given some affine constraints on the variables,
+$A \vec x + \vec b \ge \vec 0$, the tableau represents the relationship
+between the variables $\vec x$ and non-negative variables
+$\vec y = A \vec x + \vec b$ corresponding to the constraints.
+The initial tableau contains $\begin{pmatrix}
+\vec b & A
+\end{pmatrix}$ and expresses the constraints $\vec y$ in the rows in terms
+of the variables $\vec x$ in the columns. The main operation defined
+on a tableau exchanges a column and a row variable and is called a pivot.
+During this process, some coefficients may become rational.
+As in the \texttt{PipLib} implementation,
+{\tt isl} maintains a shared denominator per row.
+The sample value of a tableau is one where each column variable is assigned
+zero and each row variable is assigned the constant term of the row.
+This sample value represents a valid solution if each constraint variable
+is assigned a non-negative value, i.e., if the constant terms of
+rows corresponding to constraints are all non-negative.
+
+The dual simplex method starts from an initial sample value that
+may be invalid, but that is known to be (lexicographically) no
+greater than any solution, and gradually increments this sample value
+through pivoting until a valid solution is obtained.
+In particular, each pivot exchanges a row variable
+$r = -n + \sum_i a_i \, c_i$ with negative
+sample value $-n$ with a column variable $c_j$
+such that $a_j > 0$. Since $c_j = (n + r - \sum_{i\ne j} a_i \, c_i)/a_j$,
+the new row variable will have a positive sample value $n$.
+If no such column can be found, then the problem is infeasible.
+By always choosing the column that leads to the (lexicographically)
+smallest increment in the variables $\vec x$,
+the first solution found is guaranteed to be the (lexicographically)
+minimal solution \cite{Feautrier88parametric}.
+In order to be able to determine the smallest increment, the tableau
+is (implicitly) extended with extra rows defining the original
+variables in terms of the column variables.
+If we assume that all variables are non-negative, then we know
+that the zero vector is no greater than the minimal solution and
+then the initial extended tableau looks as follows.
+$$
+\begin{tikzpicture}
+\matrix (m) [matrix of math nodes]
+{
+& {} & 1 & \vec c \\
+\vec x && |(top)| \vec 0 & I \\
+\vec r && \vec b & |(bottom)|A \\
+};
+\begin{pgfonlayer}{background}
+\node (core) [inner sep=0pt,fill=black!20,right delimiter=),left delimiter=(,fit=(top)(bottom)] {};
+\end{pgfonlayer}
+\end{tikzpicture}
+$$
+Each column in this extended tableau is lexicographically positive
+and will remain so because of the column choice explained above.
+It is then clear that the value of $\vec x$ will increase in each step.
+Note that there is no need to store the extra rows explicitly.
+If a given $x_i$ is a column variable, then the corresponding row
+is the unit vector $e_i$. If, on the other hand, it is a row variable,
+then the row already appears somewhere else in the tableau.
+
+In case of parametric problems, the sign of the constant term
+may depend on the parameters. Each time the constant term of a constraint row
+changes, we therefore need to check whether the new term can attain
+negative and/or positive values over the current set of possible
+parameter values, i.e., the context.
+If all these terms can only attain non-negative values, the current
+state of the tableau represents a solution. If one of the terms
+can only attain non-positive values and is not identically zero,
+the corresponding row can be pivoted.
+Otherwise, we pick one of the terms that can attain both positive
+and negative values and split the context into a part where
+it only attains non-negative values and a part where it only attains
+negative values.
+
+\subsection{Gomory Cuts}
+
+The solution found by the dual simplex method may have
+non-integral coordinates. If so, some rational solutions
+(including the current sample value), can be cut off by
+applying a (parametric) Gomory cut.
+Let $r = b(\vec p) + \sp {\vec a} {\vec c}$ be the row
+corresponding to the first non-integral coordinate of $\vec x$,
+with $b(\vec p)$ the constant term, an affine expression in the
+parameters $\vec p$, i.e., $b(\vec p) = \sp {\vec f} {\vec p} + g$.
+Note that only row variables can attain
+non-integral values as the sample value of the column variables is zero.
+Consider the expression
+$b(\vec p) - \ceil{b(\vec p)} + \sp {\fract{\vec a}} {\vec c}$,
+with $\ceil\cdot$ the ceiling function and $\fract\cdot$ the
+fractional part. This expression is negative at the sample value
+since $\vec c = \vec 0$ and $r = b(\vec p)$ is fractional, i.e.,
+$\ceil{b(\vec p)} > b(\vec p)$. On the other hand, for each integral
+value of $r$ and $\vec c \ge 0$, the expression is non-negative
+because $b(\vec p) - \ceil{b(\vec p)} > -1$.
+Imposing this expression to be non-negative therefore does not
+invalidate any integral solutions, while it does cut away the current
+fractional sample value. To be able to formulate this constraint,
+a new variable $q = \floor{-b(\vec p)} = - \ceil{b(\vec p)}$ is added
+to the context. This integral variable is uniquely defined by the constraints
+$0 \le -d \, b(\vec p) - d \, q \le d - 1$, with $d$ the common
+denominator of $\vec f$ and $g$. In practice, the variable
+$q' = \floor{\sp {\fract{-f}} {\vec p} + \fract{-g}}$ is used instead
+and the coefficients of the new constraint are adjusted accordingly.
+The sign of the constant term of this new constraint need not be determined
+as it is non-positive by construction.
+When several of these extra context variables are added, it is important
+to avoid adding duplicates.
+Recent versions of {\tt PipLib} also check for such duplicates.
+
+\subsection{Negative Unknowns and Maximization}
+
+There are two places in the above algorithm where the unknowns $\vec x$
+are assumed to be non-negative: the initial tableau starts from
+sample value $\vec x = \vec 0$ and $\vec c$ is assumed to be non-negative
+during the construction of Gomory cuts.
+To deal with negative unknowns, \shortciteN[Appendix A.2]{Fea91}
+proposed to use a ``big parameter'', say $M$, that is taken to be
+an arbitrarily large positive number. Instead of looking for the
+lexicographically minimal value of $\vec x$, we search instead
+for the lexicographically minimal value of $\vec x' = \vec M + \vec x$.
+The sample value $\vec x' = \vec 0$ of the initial tableau then
+corresponds to $\vec x = -\vec M$, which is clearly not greater than
+any potential solution. The sign of the constant term of a row
+is determined lexicographically, with the coefficient of $M$ considered
+first. That is, if the coefficient of $M$ is not zero, then its sign
+is the sign of the entire term. Otherwise, the sign is determined
+by the remaining affine expression in the parameters.
+If the original problem has a bounded optimum, then the final sample
+value will be of the form $\vec M + \vec v$ and the optimal value
+of the original problem is then $\vec v$.
+Maximization problems can be handled in a similar way by computing
+the minimum of $\vec M - \vec x$.
+
+When the optimum is unbounded, the optimal value computed for
+the original problem will involve the big parameter.
+In the original implementation of {\tt PipLib}, the big parameter could
+even appear in some of the extra variables $\vec q$ created during
+the application of a Gomory cut. The final result could then contain
+implicit conditions on the big parameter through conditions on such
+$\vec q$ variables. This problem was resolved in later versions
+of {\tt PipLib} by taking $M$ to be divisible by any positive number.
+The big parameter can then never appear in any $\vec q$ because
+$\fract {\alpha M } = 0$. It should be noted, though, that an unbounded
+problem usually (but not always)
+indicates an incorrect formulation of the problem.
+
+The original version of {\tt PipLib} required the user to ``manually''
+add a big parameter, perform the reformulation and interpret the result
+\shortcite{Feautrier02}. Recent versions allow the user to simply
+specify that the unknowns may be negative or that the maximum should
+be computed and then these transformations are performed internally.
+Although there are some application, e.g.,
+that of \shortciteN{Feautrier92multi},
+where it is useful to have explicit control over the big parameter,
+negative unknowns and maximization are by far the most common applications
+of the big parameter and we believe that the user should not be bothered
+with such implementation issues.
+The current version of {\tt isl} therefore does not
+provide any interface for specifying big parameters. Instead, the user
+can specify whether a maximum needs to be computed and no assumptions
+are made on the sign of the unknowns. Instead, the sign of the unknowns
+is checked internally and a big parameter is automatically introduced when
+needed. For compatibility with {\tt PipLib}, the {\tt isl\_pip} tool
+does explicitly add non-negativity constraints on the unknowns unless
+the \verb+Urs_unknowns+ option is specified.
+Currently, there is also no way in {\tt isl} of expressing a big
+parameter in the output. Even though
+{\tt isl} makes the same divisibility assumption on the big parameter
+as recent versions of {\tt PipLib}, it will therefore eventually
+produce an error if the problem turns out to be unbounded.
+
+\subsection{Preprocessing}
+
+In this section, we describe some transformations that are
+or can be applied in advance to reduce the running time
+of the actual dual simplex method with Gomory cuts.
+
+\subsubsection{Feasibility Check and Detection of Equalities}
+
+Experience with the original {\tt PipLib} has shown that Gomory cuts
+do not perform very well on problems that are (non-obviously) empty,
+i.e., problems with rational solutions, but no integer solutions.
+In {\tt isl}, we therefore first perform a feasibility check on
+the original problem considered as a non-parametric problem
+over the combined space of unknowns and parameters.
+In fact, we do not simply check the feasibility, but we also
+check for implicit equalities among the integer points by computing
+the integer affine hull. The algorithm used is the same as that
+described in \autoref{s:GBR} below.
+Computing the affine hull is fairly expensive, but it can
+bring huge benefits if any equalities can be found or if the problem
+turns out to be empty.
+
+\subsubsection{Constraint Simplification}
+
+If the coefficients of the unknown and parameters in a constraint
+have a common factor, then this factor should be removed, possibly
+rounding down the constant term. For example, the constraint
+$2 x - 5 \ge 0$ should be simplified to $x - 3 \ge 0$.
+{\tt isl} performs such simplifications on all sets and relations.
+Recent versions of {\tt PipLib} also perform this simplification
+on the input.
+
+\subsubsection{Exploiting Equalities}\label{s:equalities}
+
+If there are any (explicit) equalities in the input description,
+{\tt PipLib} converts each into a pair of inequalities.
+It is also possible to write $r$ equalities as $r+1$ inequalities
+\shortcite{Feautrier02}, but it is even better to \emph{exploit} the
+equalities to reduce the dimensionality of the problem.
+Given an equality involving at least one unknown, we pivot
+the row corresponding to the equality with the column corresponding
+to the last unknown with non-zero coefficient. The new column variable
+can then be removed completely because it is identically zero,
+thereby reducing the dimensionality of the problem by one.
+The last unknown is chosen to ensure that the columns of the initial
+tableau remain lexicographically positive. In particular, if
+the equality is of the form $b + \sum_{i \le j} a_i \, x_i = 0$ with
+$a_j \ne 0$, then the (implicit) top rows of the initial tableau
+are changed as follows
+$$
+\begin{tikzpicture}
+\matrix [matrix of math nodes]
+{
+ & {} & |(top)| 0 & I_1 & |(j)| & \\
+j && 0 & & 1 & \\
+ && 0 & & & |(bottom)|I_2 \\
+};
+\node[overlay,above=2mm of j,anchor=south]{j};
+\begin{pgfonlayer}{background}
+\node (m) [inner sep=0pt,fill=black!20,right delimiter=),left delimiter=(,fit=(top)(bottom)] {};
+\end{pgfonlayer}
+\begin{scope}[xshift=4cm]
+\matrix [matrix of math nodes]
+{
+ & {} & |(top)| 0 & I_1 & \\
+j && |(left)| -b/a_j & -a_i/a_j & \\
+ && 0 & & |(bottom)|I_2 \\
+};
+\begin{pgfonlayer}{background}
+\node (m2) [inner sep=0pt,fill=black!20,right delimiter=),left delimiter=(,fit=(top)(bottom)(left)] {};
+\end{pgfonlayer}
+\end{scope}
+ \draw [shorten >=7mm,-to,thick,decorate,
+ decoration={snake,amplitude=.4mm,segment length=2mm,
+ pre=moveto,pre length=5mm,post length=8mm}]
+ (m) -- (m2);
+\end{tikzpicture}
+$$
+Currently, {\tt isl} also eliminates equalities involving only parameters
+in a similar way, provided at least one of the coefficients is equal to one.
+The application of parameter compression (see below)
+would obviate the need for removing parametric equalities.
+
+\subsubsection{Offline Symmetry Detection}\label{s:offline}
+
+Some problems, notably those of \shortciteN{Bygde2010licentiate},
+have a collection of constraints, say
+$b_i(\vec p) + \sp {\vec a} {\vec x} \ge 0$,
+that only differ in their (parametric) constant terms.
+These constant terms will be non-negative on different parts
+of the context and this context may have to be split for each
+of the constraints. In the worst case, the basic algorithm may
+have to consider all possible orderings of the constant terms.
+Instead, {\tt isl} introduces a new parameter, say $u$, and
+replaces the collection of constraints by the single
+constraint $u + \sp {\vec a} {\vec x} \ge 0$ along with
+context constraints $u \le b_i(\vec p)$.
+Any solution to the new system is also a solution
+to the original system since
+$\sp {\vec a} {\vec x} \ge -u \ge -b_i(\vec p)$.
+Conversely, $m = \min_i b_i(\vec p)$ satisfies the constraints
+on $u$ and therefore extends a solution to the new system.
+It can also be plugged into a new solution.
+See \autoref{s:post} for how this substitution is currently performed
+in {\tt isl}.
+The method described in this section can only detect symmetries
+that are explicitly available in the input.
+See \autoref{s:online} for the detection
+and exploitation of symmetries that appear during the course of
+the dual simplex method.
+
+\subsubsection{Parameter Compression}\label{s:compression}
+
+It may in some cases be apparent from the equalities in the problem
+description that there can only be a solution for a sublattice
+of the parameters. In such cases ``parameter compression''
+\shortcite{Meister2004PhD,Meister2008} can be used to replace
+the parameters by alternative ``dense'' parameters.
+For example, if there is a constraint $2x = n$, then the system
+will only have solutions for even values of $n$ and $n$ can be replaced
+by $2n'$. Similarly, the parameters $n$ and $m$ in a system with
+the constraint $2n = 3m$ can be replaced by a single parameter $n'$
+with $n=3n'$ and $m=2n'$.
+It is also possible to perform a similar compression on the unknowns,
+but it would be more complicated as the compression would have to
+preserve the lexicographical order. Moreover, due to our handling
+of equalities described above there should be
+no need for such variable compression.
+Although parameter compression has been implemented in {\tt isl},
+it is currently not yet used during parametric integer programming.
+
+\subsection{Postprocessing}\label{s:post}
+
+The output of {\tt PipLib} is a quast (quasi-affine selection tree).
+Each internal node in this tree corresponds to a split of the context
+based on a parametric constant term in the main tableau with indeterminate
+sign. Each of these nodes may introduce extra variables in the context
+corresponding to integer divisions. Each leaf of the tree prescribes
+the solution in that part of the context that satisfies all the conditions
+on the path leading to the leaf.
+Such a quast is a very economical way of representing the solution, but
+it would not be suitable as the (only) internal representation of
+sets and relations in {\tt isl}. Instead, {\tt isl} represents
+the constraints of a set or relation in disjunctive normal form.
+The result of a parametric integer programming problem is then also
+converted to this internal representation. Unfortunately, the conversion
+to disjunctive normal form can lead to an explosion of the size
+of the representation.
+In some cases, this overhead would have to be paid anyway in subsequent
+operations, but in other cases, especially for outside users that just
+want to solve parametric integer programming problems, we would like
+to avoid this overhead in future. That is, we are planning on introducing
+quasts or a related representation as one of several possible internal
+representations and on allowing the output of {\tt isl\_pip} to optionally
+be printed as a quast.
+
+Currently, {\tt isl} also does not have an internal representation
+for expressions such as $\min_i b_i(\vec p)$ from the offline
+symmetry detection of \autoref{s:offline}.
+Assume that one of these expressions has $n$ bounds $b_i(\vec p)$.
+If the expression
+does not appear in the affine expression describing the solution,
+but only in the constraints, and if moreover, the expression
+only appears with a positive coefficient, i.e.,
+$\min_i b_i(\vec p) \ge f_j(\vec p)$, then each of these constraints
+can simply be reduplicated $n$ times, once for each of the bounds.
+Otherwise, a conversion to disjunctive normal form
+leads to $n$ cases, each described as $u = b_i(\vec p)$ with constraints
+$b_i(\vec p) \le b_j(\vec p)$ for $j > i$
+and
+$b_i(\vec p) < b_j(\vec p)$ for $j < i$.
+Note that even though this conversion leads to a size increase
+by a factor of $n$, not detecting the symmetry could lead to
+an increase by a factor of $n!$ if all possible orderings end up being
+considered.
+
+\subsection{Context Tableau}\label{s:context}
+
+The main operation that a context tableau needs to provide is a test
+on the sign of an affine expression over the elements of the context.
+This sign can be determined by solving two integer linear feasibility
+problems, one with a constraint added to the context that enforces
+the expression to be non-negative and one where the expression is
+negative. As already mentioned by \shortciteN{Feautrier88parametric},
+any integer linear feasibility solver could be used, but the {\tt PipLib}
+implementation uses a recursive call to the dual simplex with Gomory
+cuts algorithm to determine the feasibility of a context.
+In {\tt isl}, two ways of handling the context have been implemented,
+one that performs the recursive call and one, used by default, that
+uses generalized basis reduction.
+We start with some optimizations that are shared between the two
+implementations and then discuss additional details of each of them.
+
+\subsubsection{Maintaining Witnesses}\label{s:witness}
+
+A common feature of both integer linear feasibility solvers is that
+they will not only say whether a set is empty or not, but if the set
+is non-empty, they will also provide a \emph{witness} for this result,
+i.e., a point that belongs to the set. By maintaining a list of such
+witnesses, we can avoid many feasibility tests during the determination
+of the signs of affine expressions. In particular, if the expression
+evaluates to a positive number on some of these points and to a negative
+number on some others, then no feasibility test needs to be performed.
+If all the evaluations are non-negative, we only need to check for the
+possibility of a negative value and similarly in case of all
+non-positive evaluations. Finally, in the rare case that all points
+evaluate to zero or at the start, when no points have been collected yet,
+one or two feasibility tests need to be performed depending on the result
+of the first test.
+
+When a new constraint is added to the context, the points that
+violate the constraint are temporarily removed. They are reconsidered
+when we backtrack over the addition of the constraint, as they will
+satisfy the negation of the constraint. It is only when we backtrack
+over the addition of the points that they are finally removed completely.
+When an extra integer division is added to the context,
+the new coordinates of the
+witnesses can easily be computed by evaluating the integer division.
+The idea of keeping track of witnesses was first used in {\tt barvinok}.
+
+\subsubsection{Choice of Constant Term on which to Split}
+
+Recall that if there are no rows with a non-positive constant term,
+but there are rows with an indeterminate sign, then the context
+needs to be split along the constant term of one of these rows.
+If there is more than one such row, then we need to choose which row
+to split on first. {\tt PipLib} uses a heuristic based on the (absolute)
+sizes of the coefficients. In particular, it takes the largest coefficient
+of each row and then selects the row where this largest coefficient is smaller
+than those of the other rows.
+
+In {\tt isl}, we take that row for which non-negativity of its constant
+term implies non-negativity of as many of the constant terms of the other
+rows as possible. The intuition behind this heuristic is that on the
+positive side, we will have fewer negative and indeterminate signs,
+while on the negative side, we need to perform a pivot, which may
+affect any number of rows meaning that the effect on the signs
+is difficult to predict. This heuristic is of course much more
+expensive to evaluate than the heuristic used by {\tt PipLib}.
+More extensive tests are needed to evaluate whether the heuristic is worthwhile.
+
+\subsubsection{Dual Simplex + Gomory Cuts}
+
+When a new constraint is added to the context, the first steps
+of the dual simplex method applied to this new context will be the same
+or at least very similar to those taken on the original context, i.e.,
+before the constraint was added. In {\tt isl}, we therefore apply
+the dual simplex method incrementally on the context and backtrack
+to a previous state when a constraint is removed again.
+An initial implementation that was never made public would also
+keep the Gomory cuts, but the current implementation backtracks
+to before the point where Gomory cuts are added before adding
+an extra constraint to the context.
+Keeping the Gomory cuts has the advantage that the sample value
+is always an integer point and that this point may also satisfy
+the new constraint. However, due to the technique of maintaining
+witnesses explained above,
+we would not perform a feasibility test in such cases and then
+the previously added cuts may be redundant, possibly resulting
+in an accumulation of a large number of cuts.
+
+If the parameters may be negative, then the same big parameter trick
+used in the main tableau is applied to the context. This big parameter
+is of course unrelated to the big parameter from the main tableau.
+Note that it is not a requirement for this parameter to be ``big'',
+but it does allow for some code reuse in {\tt isl}.
+In {\tt PipLib}, the extra parameter is not ``big'', but this may be because
+the big parameter of the main tableau also appears
+in the context tableau.
+
+Finally, it was reported by \shortciteN{Galea2009personal}, who
+worked on a parametric integer programming implementation
+in {\tt PPL} \shortcite{PPL},
+that it is beneficial to add cuts for \emph{all} rational coordinates
+in the context tableau. Based on this report,
+the initial {\tt isl} implementation was adapted accordingly.
+
+\subsubsection{Generalized Basis Reduction}\label{s:GBR}
+
+The default algorithm used in {\tt isl} for feasibility checking
+is generalized basis reduction \shortcite{Cook1991implementation}.
+This algorithm is also used in the {\tt barvinok} implementation.
+The algorithm is fairly robust, but it has some overhead.
+We therefore try to avoid calling the algorithm in easy cases.
+In particular, we incrementally keep track of points for which
+the entire unit hypercube positioned at that point lies in the context.
+This set is described by translates of the constraints of the context
+and if (rationally) non-empty, any rational point
+in the set can be rounded up to yield an integer point in the context.
+
+A restriction of the algorithm is that it only works on bounded sets.
+The affine hull of the recession cone therefore needs to be projected
+out first. As soon as the algorithm is invoked, we then also
+incrementally keep track of this recession cone. The reduced basis
+found by one call of the algorithm is also reused as initial basis
+for the next call.
+
+Some problems lead to the
+introduction of many integer divisions. Within a given context,
+some of these integer divisions may be equal to each other, even
+if the expressions are not identical, or they may be equal to some
+affine combination of other variables.
+To detect such cases, we compute the affine hull of the context
+each time a new integer division is added. The algorithm used
+for computing this affine hull is that of \shortciteN{Karr1976affine},
+while the points used in this algorithm are obtained by performing
+integer feasibility checks on that part of the context outside
+the current approximation of the affine hull.
+The list of witnesses is used to construct an initial approximation
+of the hull, while any extra points found during the construction
+of the hull is added to this list.
+Any equality found in this way that expresses an integer division
+as an \emph{integer} affine combination of other variables is
+propagated to the main tableau, where it is used to eliminate that
+integer division.
+
+\subsection{Experiments}
+
+\autoref{t:comparison} compares the execution times of {\tt isl}
+(with both types of context tableau)
+on some more difficult instances to those of other tools,
+run on an Intel Xeon W3520 @ 2.66GHz.
+Easier problems such as the
+test cases distributed with {\tt Pip\-Lib} can be solved so quickly
+that we would only be measuring overhead such as input/output and conversions
+and not the running time of the actual algorithm.
+We compare the following versions:
+{\tt piplib-1.4.0-5-g0132fd9},
+{\tt barvinok-0.32.1-73-gc5d7751},
+{\tt isl-0.05.1-82-g3a37260}
+and {\tt PPL} version 0.11.2.
+
+The first test case is the following dependence analysis problem
+originating from the Phideo project \shortcite{Verhaegh1995PhD}
+that was communicated to us by Bart Kienhuis:
+\begin{lstlisting}[flexiblecolumns=true,breaklines=true]{}
+lexmax { [j1,j2] -> [i1,i2,i3,i4,i5,i6,i7,i8,i9,i10] : 1 <= i1,j1 <= 8 and 1 <= i2,i3,i4,i5,i6,i7,i8,i9,i10 <= 2 and 1 <= j2 <= 128 and i1-1 = j1-1 and i2-1+2*i3-2+4*i4-4+8*i5-8+16*i6-16+32*i7-32+64*i8-64+128*i9-128+256*i10-256=3*j2-3+66 };
+\end{lstlisting}
+This problem was the main inspiration
+for some of the optimizations in \autoref{s:GBR}.
+The second group of test cases are projections used during counting.
+The first nine of these come from \shortciteN{Seghir2006minimizing}.
+The remaining two come from \shortciteN{Verdoolaege2005experiences} and
+were used to drive the first, Gomory cuts based, implementation
+in {\tt isl}.
+The third and final group of test cases are borrowed from
+\shortciteN{Bygde2010licentiate} and inspired the offline symmetry detection
+of \autoref{s:offline}. Without symmetry detection, the running times
+are 11s and 5.9s.
+All running times of {\tt barvinok} and {\tt isl} include a conversion
+to disjunctive normal form. Without this conversion, the final two
+cases can be solved in 0.07s and 0.21s.
+The {\tt PipLib} implementation has some fixed limits and will
+sometimes report the problem to be too complex (TC), while on some other
+problems it will run out of memory (OOM).
+The {\tt barvinok} implementation does not support problems
+with a non-trivial lineality space (line) nor maximization problems (max).
+The Gomory cuts based {\tt isl} implementation was terminated after 1000
+minutes on the first problem. The gbr version introduces some
+overhead on some of the easier problems, but is overall the clear winner.
+
+\begin{table}
+\begin{center}
+\begin{tabular}{lrrrrr}
+ & {\tt PipLib} & {\tt barvinok} & {\tt isl} cut & {\tt isl} gbr & {\tt PPL} \\
+\hline
+\hline
+% bart.pip
+Phideo & TC & 793m & $>$999m & 2.7s & 372m \\
+\hline
+e1 & 0.33s & 3.5s & 0.08s & 0.11s & 0.18s \\
+e3 & 0.14s & 0.13s & 0.10s & 0.10s & 0.17s \\
+e4 & 0.24s & 9.1s & 0.09s & 0.11s & 0.70s \\
+e5 & 0.12s & 6.0s & 0.06s & 0.14s & 0.17s \\
+e6 & 0.10s & 6.8s & 0.17s & 0.08s & 0.21s \\
+e7 & 0.03s & 0.27s & 0.04s & 0.04s & 0.03s \\
+e8 & 0.03s & 0.18s & 0.03s & 0.04s & 0.01s \\
+e9 & OOM & 70m & 2.6s & 0.94s & 22s \\
+vd & 0.04s & 0.10s & 0.03s & 0.03s & 0.03s \\
+bouleti & 0.25s & line & 0.06s & 0.06s & 0.15s \\
+difficult & OOM & 1.3s & 1.7s & 0.33s & 1.4s \\
+\hline
+cnt/sum & TC & max & 2.2s & 2.2s & OOM \\
+jcomplex & TC & max & 3.7s & 3.9s & OOM \\
+\end{tabular}
+\caption{Comparison of Execution Times}
+\label{t:comparison}
+\end{center}
+\end{table}
+
+\subsection{Online Symmetry Detection}\label{s:online}
+
+Manual experiments on small instances of the problems of
+\shortciteN{Bygde2010licentiate} and an analysis of the results
+by the approximate MPA method developed by \shortciteN{Bygde2010licentiate}
+have revealed that these problems contain many more symmetries
+than can be detected using the offline method of \autoref{s:offline}.
+In this section, we present an online detection mechanism that has
+not been implemented yet, but that has shown promising results
+in manual applications.
+
+Let us first consider what happens when we do not perform offline
+symmetry detection. At some point, one of the
+$b_i(\vec p) + \sp {\vec a} {\vec x} \ge 0$ constraints,
+say the $j$th constraint, appears as a column
+variable, say $c_1$, while the other constraints are represented
+as rows of the form $b_i(\vec p) - b_j(\vec p) + c$.
+The context is then split according to the relative order of
+$b_j(\vec p)$ and one of the remaining $b_i(\vec p)$.
+The offline method avoids this split by replacing all $b_i(\vec p)$
+by a single newly introduced parameter that represents the minimum
+of these $b_i(\vec p)$.
+In the online method the split is similarly avoided by the introduction
+of a new parameter. In particular, a new parameter is introduced
+that represents
+$\left| b_j(\vec p) - b_i(\vec p) \right|_+ =
+\max(b_j(\vec p) - b_i(\vec p), 0)$.
+
+In general, let $r = b(\vec p) + \sp {\vec a} {\vec c}$ be a row
+of the tableau such that the sign of $b(\vec p)$ is indeterminate
+and such that exactly one of the elements of $\vec a$ is a $1$,
+while all remaining elements are non-positive.
+That is, $r = b(\vec p) + c_j - f$ with $f = -\sum_{i\ne j} a_i c_i \ge 0$.
+We introduce a new parameter $t$ with
+context constraints $t \ge -b(\vec p)$ and $t \ge 0$ and replace
+the column variable $c_j$ by $c' + t$. The row $r$ is now equal
+to $b(\vec p) + t + c' - f$. The constant term of this row is always
+non-negative because any negative value of $b(\vec p)$ is compensated
+by $t \ge -b(\vec p)$ while and non-negative value remains non-negative
+because $t \ge 0$.
+
+We need to show that this transformation does not eliminate any valid
+solutions and that it does not introduce any spurious solutions.
+Given a valid solution for the original problem, we need to find
+a non-negative value of $c'$ satisfying the constraints.
+If $b(\vec p) \ge 0$, we can take $t = 0$ so that
+$c' = c_j - t = c_j \ge 0$.
+If $b(\vec p) < 0$, we can take $t = -b(\vec p)$.
+Since $r = b(\vec p) + c_j - f \ge 0$ and $f \ge 0$, we have
+$c' = c_j + b(\vec p) \ge 0$.
+Note that these choices amount to plugging in
+$t = \left|-b(\vec p)\right|_+ = \max(-b(\vec p), 0)$.
+Conversely, given a solution to the new problem, we need to find
+a non-negative value of $c_j$, but this is easy since $c_j = c' + t$
+and both of these are non-negative.
+
+Plugging in $t = \max(-b(\vec p), 0)$ can be performed as in
+\autoref{s:post}, but, as in the case of offline symmetry detection,
+it may be better to provide a direct representation for such
+expressions in the internal representation of sets and relations
+or at least in a quast-like output format.
+
+\section{Coalescing}\label{s:coalescing}
+
+See \shortciteN{Verdoolaege2009isl}, for now.
+More details will be added later.
+
+\section{Transitive Closure}
+
+\subsection{Introduction}
+
+\begin{definition}[Power of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation and
+$k \in \Z_{\ge 1}$
+a positive number, then power $k$ of relation $R$ is defined as
+\begin{equation}
+\label{eq:transitive:power}
+R^k \coloneqq
+\begin{cases}
+R & \text{if $k = 1$}
+\\
+R \circ R^{k-1} & \text{if $k \ge 2$}
+.
+\end{cases}
+\end{equation}
+\end{definition}
+
+\begin{definition}[Transitive Closure of a Relation]
+Let $R \in \Z^n \to 2^{\Z^{d+d}}$ be a relation,
+then the transitive closure $R^+$ of $R$ is the union
+of all positive powers of $R$,
+$$
+R^+ \coloneqq \bigcup_{k \ge 1} R^k
+.
+$$
+\end{definition}
+Alternatively, the transitive closure may be defined
+inductively as
+\begin{equation}
+\label{eq:transitive:inductive}
+R^+ \coloneqq R \cup \left(R \circ R^+\right)
+.
+\end{equation}
+
+Since the transitive closure of a polyhedral relation
+may no longer be a polyhedral relation \shortcite{Kelly1996closure},
+we can, in the general case, only compute an approximation
+of the transitive closure.
+Whereas \shortciteN{Kelly1996closure} compute underapproximations,
+we, like \shortciteN{Beletska2009}, compute overapproximations.
+That is, given a relation $R$, we will compute a relation $T$
+such that $R^+ \subseteq T$. Of course, we want this approximation
+to be as close as possible to the actual transitive closure
+$R^+$ and we want to detect the cases where the approximation is
+exact, i.e., where $T = R^+$.
+
+For computing an approximation of the transitive closure of $R$,
+we follow the same general strategy as \shortciteN{Beletska2009}
+and first compute an approximation of $R^k$ for $k \ge 1$ and then project
+out the parameter $k$ from the resulting relation.
+
+\begin{example}
+As a trivial example, consider the relation
+$R = \{\, x \to x + 1 \,\}$. The $k$th power of this map
+for arbitrary $k$ is
+$$
+R^k = k \mapsto \{\, x \to x + k \mid k \ge 1 \,\}
+.
+$$
+The transitive closure is then
+$$
+\begin{aligned}
+R^+ & = \{\, x \to y \mid \exists k \in \Z_{\ge 1} : y = x + k \,\}
+\\
+& = \{\, x \to y \mid y \ge x + 1 \,\}
+.
+\end{aligned}
+$$
+\end{example}
+
+\subsection{Computing an Approximation of $R^k$}
+\label{s:power}
+
+There are some special cases where the computation of $R^k$ is very easy.
+One such case is that where $R$ does not compose with itself,
+i.e., $R \circ R = \emptyset$ or $\domain R \cap \range R = \emptyset$.
+In this case, $R^k$ is only non-empty for $k=1$ where it is equal
+to $R$ itself.
+
+In general, it is impossible to construct a closed form
+of $R^k$ as a polyhedral relation.
+We will therefore need to make some approximations.
+As a first approximations, we will consider each of the basic
+relations in $R$ as simply adding one or more offsets to a domain element
+to arrive at an image element and ignore the fact that some of these
+offsets may only be applied to some of the domain elements.
+That is, we will only consider the difference set $\Delta\,R$ of the relation.
+In particular, we will first construct a collection $P$ of paths
+that move through
+a total of $k$ offsets and then intersect domain and range of this
+collection with those of $R$.
+That is,
+\begin{equation}
+\label{eq:transitive:approx}
+K = P \cap \left(\domain R \to \range R\right)
+,
+\end{equation}
+with
+\begin{equation}
+\label{eq:transitive:path}
+P = \vec s \mapsto \{\, \vec x \to \vec y \mid
+\exists k_i \in \Z_{\ge 0}, \vec\delta_i \in k_i \, \Delta_i(\vec s) :
+\vec y = \vec x + \sum_i \vec\delta_i
+\wedge
+\sum_i k_i = k > 0
+\,\}
+\end{equation}
+and with $\Delta_i$ the basic sets that compose
+the difference set $\Delta\,R$.
+Note that the number of basic sets $\Delta_i$ need not be
+the same as the number of basic relations in $R$.
+Also note that since addition is commutative, it does not
+matter in which order we add the offsets and so we are allowed
+to group them as we did in \eqref{eq:transitive:path}.
+
+If all the $\Delta_i$s are singleton sets
+$\Delta_i = \{\, \vec \delta_i \,\}$ with $\vec \delta_i \in \Z^d$,
+then \eqref{eq:transitive:path} simplifies to
+\begin{equation}
+\label{eq:transitive:singleton}
+P = \{\, \vec x \to \vec y \mid
+\exists k_i \in \Z_{\ge 0} :
+\vec y = \vec x + \sum_i k_i \, \vec \delta_i
+\wedge
+\sum_i k_i = k > 0
+\,\}
+\end{equation}
+and then the approximation computed in \eqref{eq:transitive:approx}
+is essentially the same as that of \shortciteN{Beletska2009}.
+If some of the $\Delta_i$s are not singleton sets or if
+some of $\vec \delta_i$s are parametric, then we need
+to resort to further approximations.
+
+To ease both the exposition and the implementation, we will for
+the remainder of this section work with extended offsets
+$\Delta_i' = \Delta_i \times \{\, 1 \,\}$.
+That is, each offset is extended with an extra coordinate that is
+set equal to one. The paths constructed by summing such extended
+offsets have the length encoded as the difference of their
+final coordinates. The path $P'$ can then be decomposed into
+paths $P_i'$, one for each $\Delta_i$,
+\begin{equation}
+\label{eq:transitive:decompose}
+P' = \left(
+(P_m' \cup \identity) \circ \cdots \circ
+(P_2' \cup \identity) \circ
+(P_1' \cup \identity)
+\right) \cap
+\{\,
+\vec x' \to \vec y' \mid y_{d+1} - x_{d+1} = k > 0
+\,\}
+,
+\end{equation}
+with
+$$
+P_i' = \vec s \mapsto \{\, \vec x' \to \vec y' \mid
+\exists k \in \Z_{\ge 1}, \vec \delta \in k \, \Delta_i'(\vec s) :
+\vec y' = \vec x' + \vec \delta
+\,\}
+.
+$$
+Note that each $P_i'$ contains paths of length at least one.
+We therefore need to take the union with the identity relation
+when composing the $P_i'$s to allow for paths that do not contain
+any offsets from one or more $\Delta_i'$.
+The path that consists of only identity relations is removed
+by imposing the constraint $y_{d+1} - x_{d+1} > 0$.
+Taking the union with the identity relation means that
+that the relations we compose in \eqref{eq:transitive:decompose}
+each consist of two basic relations. If there are $m$
+disjuncts in the input relation, then a direct application
+of the composition operation may therefore result in a relation
+with $2^m$ disjuncts, which is prohibitively expensive.
+It is therefore crucial to apply coalescing (\autoref{s:coalescing})
+after each composition.
+
+Let us now consider how to compute an overapproximation of $P_i'$.
+Those that correspond to singleton $\Delta_i$s are grouped together
+and handled as in \eqref{eq:transitive:singleton}.
+Note that this is just an optimization. The procedure described
+below would produce results that are at least as accurate.
+For simplicity, we first assume that no constraint in $\Delta_i'$
+involves any existentially quantified variables.
+We will return to existentially quantified variables at the end
+of this section.
+Without existentially quantified variables, we can classify
+the constraints of $\Delta_i'$ as follows
+\begin{enumerate}
+\item non-parametric constraints
+\begin{equation}
+\label{eq:transitive:non-parametric}
+A_1 \vec x + \vec c_1 \geq \vec 0
+\end{equation}
+\item purely parametric constraints
+\begin{equation}
+\label{eq:transitive:parametric}
+B_2 \vec s + \vec c_2 \geq \vec 0
+\end{equation}
+\item negative mixed constraints
+\begin{equation}
+\label{eq:transitive:mixed}
+A_3 \vec x + B_3 \vec s + \vec c_3 \geq \vec 0
+\end{equation}
+such that for each row $j$ and for all $\vec s$,
+$$
+\Delta_i'(\vec s) \cap
+\{\, \vec \delta' \mid B_{3,j} \vec s + c_{3,j} > 0 \,\}
+= \emptyset
+$$
+\item positive mixed constraints
+$$
+A_4 \vec x + B_4 \vec s + \vec c_4 \geq \vec 0
+$$
+such that for each row $j$, there is at least one $\vec s$ such that
+$$
+\Delta_i'(\vec s) \cap
+\{\, \vec \delta' \mid B_{4,j} \vec s + c_{4,j} > 0 \,\}
+\ne \emptyset
+$$
+\end{enumerate}
+We will use the following approximation $Q_i$ for $P_i'$:
+\begin{equation}
+\label{eq:transitive:Q}
+\begin{aligned}
+Q_i = \vec s \mapsto
+\{\,
+\vec x' \to \vec y'
+\mid {} & \exists k \in \Z_{\ge 1}, \vec f \in \Z^d :
+\vec y' = \vec x' + (\vec f, k)
+\wedge {}
+\\
+&
+A_1 \vec f + k \vec c_1 \geq \vec 0
+\wedge
+B_2 \vec s + \vec c_2 \geq \vec 0
+\wedge
+A_3 \vec f + B_3 \vec s + \vec c_3 \geq \vec 0
+\,\}
+.
+\end{aligned}
+\end{equation}
+To prove that $Q_i$ is indeed an overapproximation of $P_i'$,
+we need to show that for every $\vec s \in \Z^n$, for every
+$k \in \Z_{\ge 1}$ and for every $\vec f \in k \, \Delta_i(\vec s)$
+we have that
+$(\vec f, k)$ satisfies the constraints in \eqref{eq:transitive:Q}.
+If $\Delta_i(\vec s)$ is non-empty, then $\vec s$ must satisfy
+the constraints in \eqref{eq:transitive:parametric}.
+Each element $(\vec f, k) \in k \, \Delta_i'(\vec s)$ is a sum
+of $k$ elements $(\vec f_j, 1)$ in $\Delta_i'(\vec s)$.
+Each of these elements satisfies the constraints in
+\eqref{eq:transitive:non-parametric}, i.e.,
+$$
+\left[
+\begin{matrix}
+A_1 & \vec c_1
+\end{matrix}
+\right]
+\left[
+\begin{matrix}
+\vec f_j \\ 1
+\end{matrix}
+\right]
+\ge \vec 0
+.
+$$
+The sum of these elements therefore satisfies the same set of inequalities,
+i.e., $A_1 \vec f + k \vec c_1 \geq \vec 0$.
+Finally, the constraints in \eqref{eq:transitive:mixed} are such
+that for any $\vec s$ in the parameter domain of $\Delta$,
+we have $-\vec r(\vec s) \coloneqq B_3 \vec s + \vec c_3 \le \vec 0$,
+i.e., $A_3 \vec f_j \ge \vec r(\vec s) \ge \vec 0$
+and therefore also $A_3 \vec f \ge \vec r(\vec s)$.
+Note that if there are no mixed constraints and if the
+rational relaxation of $\Delta_i(\vec s)$, i.e.,
+$\{\, \vec x \in \Q^d \mid A_1 \vec x + \vec c_1 \ge \vec 0\,\}$,
+has integer vertices, then the approximation is exact, i.e.,
+$Q_i = P_i'$. In this case, the vertices of $\Delta'_i(\vec s)$
+generate the rational cone
+$\{\, \vec x' \in \Q^{d+1} \mid \left[
+\begin{matrix}
+A_1 & \vec c_1
+\end{matrix}
+\right] \vec x' \,\}$ and therefore $\Delta'_i(\vec s)$ is
+a Hilbert basis of this cone \shortcite[Theorem~16.4]{Schrijver1986}.
+
+Note however that, as pointed out by \shortciteN{DeSmet2010personal},
+if there \emph{are} any mixed constraints, then the above procedure may
+not compute the most accurate affine approximation of
+$k \, \Delta_i(\vec s)$ with $k \ge 1$.
+In particular, we only consider the negative mixed constraints that
+happen to appear in the description of $\Delta_i(\vec s)$, while we
+should instead consider \emph{all} valid such constraints.
+It is also sufficient to consider those constraints because any
+constraint that is valid for $k \, \Delta_i(\vec s)$ is also
+valid for $1 \, \Delta_i(\vec s) = \Delta_i(\vec s)$.
+Take therefore any constraint
+$\spv a x + \spv b s + c \ge 0$ valid for $\Delta_i(\vec s)$.
+This constraint is also valid for $k \, \Delta_i(\vec s)$ iff
+$k \, \spv a x + \spv b s + c \ge 0$.
+If $\spv b s + c$ can attain any positive value, then $\spv a x$
+may be negative for some elements of $\Delta_i(\vec s)$.
+We then have $k \, \spv a x < \spv a x$ for $k > 1$ and so the constraint
+is not valid for $k \, \Delta_i(\vec s)$.
+We therefore need to impose $\spv b s + c \le 0$ for all values
+of $\vec s$ such that $\Delta_i(\vec s)$ is non-empty, i.e.,
+$\vec b$ and $c$ need to be such that $- \spv b s - c \ge 0$ is a valid
+constraint of $\Delta_i(\vec s)$. That is, $(\vec b, c)$ are the opposites
+of the coefficients of a valid constraint of $\Delta_i(\vec s)$.
+The approximation of $k \, \Delta_i(\vec s)$ can therefore be obtained
+using three applications of Farkas' lemma. The first obtains the coefficients
+of constraints valid for $\Delta_i(\vec s)$. The second obtains
+the coefficients of constraints valid for the projection of $\Delta_i(\vec s)$
+onto the parameters. The opposite of the second set is then computed
+and intersected with the first set. The result is the set of coefficients
+of constraints valid for $k \, \Delta_i(\vec s)$. A final application
+of Farkas' lemma is needed to obtain the approximation of
+$k \, \Delta_i(\vec s)$ itself.
+
+\begin{example}
+Consider the relation
+$$
+n \to \{\, (x, y) \to (1 + x, 1 - n + y) \mid n \ge 2 \,\}
+.
+$$
+The difference set of this relation is
+$$
+\Delta = n \to \{\, (1, 1 - n) \mid n \ge 2 \,\}
+.
+$$
+Using our approach, we would only consider the mixed constraint
+$y - 1 + n \ge 0$, leading to the following approximation of the
+transitive closure:
+$$
+n \to \{\, (x, y) \to (o_0, o_1) \mid n \ge 2 \wedge o_1 \le 1 - n + y \wedge o_0 \ge 1 + x \,\}
+.
+$$
+If, instead, we apply Farkas's lemma to $\Delta$, i.e.,
+\begin{verbatim}
+D := [n] -> { [1, 1 - n] : n >= 2 };
+CD := coefficients D;
+CD;
+\end{verbatim}
+we obtain
+\begin{verbatim}
+{ rat: coefficients[[c_cst, c_n] -> [i2, i3]] : i3 <= c_n and
+ i3 <= c_cst + 2c_n + i2 }
+\end{verbatim}
+The pure-parametric constraints valid for $\Delta$,
+\begin{verbatim}
+P := { [a,b] -> [] }(D);
+CP := coefficients P;
+CP;
+\end{verbatim}
+are
+\begin{verbatim}
+{ rat: coefficients[[c_cst, c_n] -> []] : c_n >= 0 and 2c_n >= -c_cst }
+\end{verbatim}
+Negating these coefficients and intersecting with \verb+CD+,
+\begin{verbatim}
+NCP := { rat: coefficients[[a,b] -> []]
+ -> coefficients[[-a,-b] -> []] }(CP);
+CK := wrap((unwrap CD) * (dom (unwrap NCP)));
+CK;
+\end{verbatim}
+we obtain
+\begin{verbatim}
+{ rat: [[c_cst, c_n] -> [i2, i3]] : i3 <= c_n and
+ i3 <= c_cst + 2c_n + i2 and c_n <= 0 and 2c_n <= -c_cst }
+\end{verbatim}
+The approximation for $k\,\Delta$,
+\begin{verbatim}
+K := solutions CK;
+K;
+\end{verbatim}
+is then
+\begin{verbatim}
+[n] -> { rat: [i0, i1] : i1 <= -i0 and i0 >= 1 and i1 <= 2 - n - i0 }
+\end{verbatim}
+Finally, the computed approximation for $R^+$,
+\begin{verbatim}
+T := unwrap({ [dx,dy] -> [[x,y] -> [x+dx,y+dy]] }(K));
+R := [n] -> { [x,y] -> [x+1,y+1-n] : n >= 2 };
+T := T * ((dom R) -> (ran R));
+T;
+\end{verbatim}
+is
+\begin{verbatim}
+[n] -> { [x, y] -> [o0, o1] : o1 <= x + y - o0 and
+ o0 >= 1 + x and o1 <= 2 - n + x + y - o0 and n >= 2 }
+\end{verbatim}
+\end{example}
+
+Existentially quantified variables can be handled by
+classifying them into variables that are uniquely
+determined by the parameters, variables that are independent
+of the parameters and others. The first set can be treated
+as parameters and the second as variables. Constraints involving
+the other existentially quantified variables are removed.
+
+\begin{example}
+Consider the relation
+$$
+R =
+n \to \{\, x \to y \mid \exists \, \alpha_0, \alpha_1: 7\alpha_0 = -2 + n \wedge 5\alpha_1 = -1 - x + y \wedge y \ge 6 + x \,\}
+.
+$$
+The difference set of this relation is
+$$
+\Delta = \Delta \, R =
+n \to \{\, x \mid \exists \, \alpha_0, \alpha_1: 7\alpha_0 = -2 + n \wedge 5\alpha_1 = -1 + x \wedge x \ge 6 \,\}
+.
+$$
+The existentially quantified variables can be defined in terms
+of the parameters and variables as
+$$
+\alpha_0 = \floor{\frac{-2 + n}7}
+\qquad
+\text{and}
+\qquad
+\alpha_1 = \floor{\frac{-1 + x}5}
+.
+$$
+$\alpha_0$ can therefore be treated as a parameter,
+while $\alpha_1$ can be treated as a variable.
+This in turn means that $7\alpha_0 = -2 + n$ can be treated as
+a purely parametric constraint, while the other two constraints are
+non-parametric.
+The corresponding $Q$~\eqref{eq:transitive:Q} is therefore
+$$
+\begin{aligned}
+n \to \{\, (x,z) \to (y,w) \mid
+\exists\, \alpha_0, \alpha_1, k, f : {} &
+k \ge 1 \wedge
+y = x + f \wedge
+w = z + k \wedge {} \\
+&
+7\alpha_0 = -2 + n \wedge
+5\alpha_1 = -k + x \wedge
+x \ge 6 k
+\,\}
+.
+\end{aligned}
+$$
+Projecting out the final coordinates encoding the length of the paths,
+results in the exact transitive closure
+$$
+R^+ =
+n \to \{\, x \to y \mid \exists \, \alpha_0, \alpha_1: 7\alpha_1 = -2 + n \wedge 6\alpha_0 \ge -x + y \wedge 5\alpha_0 \le -1 - x + y \,\}
+.
+$$
+\end{example}
+
+The fact that we ignore some impure constraints clearly leads
+to a loss of accuracy. In some cases, some of this loss can be recovered
+by not considering the parameters in a special way.
+That is, instead of considering the set
+$$
+\Delta = \diff R =
+\vec s \mapsto
+\{\, \vec \delta \in \Z^{d} \mid \exists \vec x \to \vec y \in R :
+\vec \delta = \vec y - \vec x
+\,\}
+$$
+we consider the set
+$$
+\Delta' = \diff R' =
+\{\, \vec \delta \in \Z^{n+d} \mid \exists
+(\vec s, \vec x) \to (\vec s, \vec y) \in R' :
+\vec \delta = (\vec s - \vec s, \vec y - \vec x)
+\,\}
+.
+$$
+The first $n$ coordinates of every element in $\Delta'$ are zero.
+Projecting out these zero coordinates from $\Delta'$ is equivalent
+to projecting out the parameters in $\Delta$.
+The result is obviously a superset of $\Delta$, but all its constraints
+are of type \eqref{eq:transitive:non-parametric} and they can therefore
+all be used in the construction of $Q_i$.
+
+\begin{example}
+Consider the relation
+$$
+% [n] -> { [x, y] -> [1 + x, 1 - n + y] | n >= 2 }
+R = n \to \{\, (x, y) \to (1 + x, 1 - n + y) \mid n \ge 2 \,\}
+.
+$$
+We have
+$$
+\diff R = n \to \{\, (1, 1 - n) \mid n \ge 2 \,\}
+$$
+and so, by treating the parameters in a special way, we obtain
+the following approximation for $R^+$:
+$$
+n \to \{\, (x, y) \to (x', y') \mid n \ge 2 \wedge y' \le 1 - n + y \wedge x' \ge 1 + x \,\}
+.
+$$
+If we consider instead
+$$
+R' = \{\, (n, x, y) \to (n, 1 + x, 1 - n + y) \mid n \ge 2 \,\}
+$$
+then
+$$
+\diff R' = \{\, (0, 1, y) \mid y \le -1 \,\}
+$$
+and we obtain the approximation
+$$
+n \to \{\, (x, y) \to (x', y') \mid n \ge 2 \wedge x' \ge 1 + x \wedge y' \le x + y - x' \,\}
+.
+$$
+If we consider both $\diff R$ and $\diff R'$, then we obtain
+$$
+n \to \{\, (x, y) \to (x', y') \mid n \ge 2 \wedge y' \le 1 - n + y \wedge x' \ge 1 + x \wedge y' \le x + y - x' \,\}
+.
+$$
+Note, however, that this is not the most accurate affine approximation that
+can be obtained. That would be
+$$
+n \to \{\, (x, y) \to (x', y') \mid y' \le 2 - n + x + y - x' \wedge n \ge 2 \wedge x' \ge 1 + x \,\}
+.
+$$
+\end{example}
+
+\subsection{Checking Exactness}
+
+The approximation $T$ for the transitive closure $R^+$ can be obtained
+by projecting out the parameter $k$ from the approximation $K$
+\eqref{eq:transitive:approx} of the power $R^k$.
+Since $K$ is an overapproximation of $R^k$, $T$ will also be an
+overapproximation of $R^+$.
+To check whether the results are exact, we need to consider two
+cases depending on whether $R$ is {\em cyclic}, where $R$ is defined
+to be cyclic if $R^+$ maps any element to itself, i.e.,
+$R^+ \cap \identity \ne \emptyset$.
+If $R$ is acyclic, then the inductive definition of
+\eqref{eq:transitive:inductive} is equivalent to its completion,
+i.e.,
+$$
+R^+ = R \cup \left(R \circ R^+\right)
+$$
+is a defining property.
+Since $T$ is known to be an overapproximation, we only need to check
+whether
+$$
+T \subseteq R \cup \left(R \circ T\right)
+.
+$$
+This is essentially Theorem~5 of \shortciteN{Kelly1996closure}.
+The only difference is that they only consider lexicographically
+forward relations, a special case of acyclic relations.
+
+If, on the other hand, $R$ is cyclic, then we have to resort
+to checking whether the approximation $K$ of the power is exact.
+Note that $T$ may be exact even if $K$ is not exact, so the check
+is sound, but incomplete.
+To check exactness of the power, we simply need to check
+\eqref{eq:transitive:power}. Since again $K$ is known
+to be an overapproximation, we only need to check whether
+$$
+\begin{aligned}
+K'|_{y_{d+1} - x_{d+1} = 1} & \subseteq R'
+\\
+K'|_{y_{d+1} - x_{d+1} \ge 2} & \subseteq R' \circ K'|_{y_{d+1} - x_{d+1} \ge 1}
+,
+\end{aligned}
+$$
+where $R' = \{\, \vec x' \to \vec y' \mid \vec x \to \vec y \in R
+\wedge y_{d+1} - x_{d+1} = 1\,\}$, i.e., $R$ extended with path
+lengths equal to 1.
+
+All that remains is to explain how to check the cyclicity of $R$.
+Note that the exactness on the power is always sound, even
+in the acyclic case, so we only need to be careful that we find
+all cyclic cases. Now, if $R$ is cyclic, i.e.,
+$R^+ \cap \identity \ne \emptyset$, then, since $T$ is
+an overapproximation of $R^+$, also
+$T \cap \identity \ne \emptyset$. This in turn means
+that $\Delta \, K'$ contains a point whose first $d$ coordinates
+are zero and whose final coordinate is positive.
+In the implementation we currently perform this test on $P'$ instead of $K'$.
+Note that if $R^+$ is acyclic and $T$ is not, then the approximation
+is clearly not exact and the approximation of the power $K$
+will not be exact either.
+
+\subsection{Decomposing $R$ into strongly connected components}
+
+If the input relation $R$ is a union of several basic relations
+that can be partially ordered
+then the accuracy of the approximation may be improved by computing
+an approximation of each strongly connected components separately.
+For example, if $R = R_1 \cup R_2$ and $R_1 \circ R_2 = \emptyset$,
+then we know that any path that passes through $R_2$ cannot later
+pass through $R_1$, i.e.,
+\begin{equation}
+\label{eq:transitive:components}
+R^+ = R_1^+ \cup R_2^+ \cup \left(R_2^+ \circ R_1^+\right)
+.
+\end{equation}
+We can therefore compute (approximations of) transitive closures
+of $R_1$ and $R_2$ separately.
+Note, however, that the condition $R_1 \circ R_2 = \emptyset$
+is actually too strong.
+If $R_1 \circ R_2$ is a subset of $R_2 \circ R_1$
+then we can reorder the segments
+in any path that moves through both $R_1$ and $R_2$ to
+first move through $R_1$ and then through $R_2$.
+
+This idea can be generalized to relations that are unions
+of more than two basic relations by constructing the
+strongly connected components in the graph with as vertices
+the basic relations and an edge between two basic relations
+$R_i$ and $R_j$ if $R_i$ needs to follow $R_j$ in some paths.
+That is, there is an edge from $R_i$ to $R_j$ iff
+\begin{equation}
+\label{eq:transitive:edge}
+R_i \circ R_j
+\not\subseteq
+R_j \circ R_i
+.
+\end{equation}
+The components can be obtained from the graph by applying
+Tarjan's algorithm \shortcite{Tarjan1972}.
+
+In practice, we compute the (extended) powers $K_i'$ of each component
+separately and then compose them as in \eqref{eq:transitive:decompose}.
+Note, however, that in this case the order in which we apply them is
+important and should correspond to a topological ordering of the
+strongly connected components. Simply applying Tarjan's
+algorithm will produce topologically sorted strongly connected components.
+The graph on which Tarjan's algorithm is applied is constructed on-the-fly.
+That is, whenever the algorithm checks if there is an edge between
+two vertices, we evaluate \eqref{eq:transitive:edge}.
+The exactness check is performed on each component separately.
+If the approximation turns out to be inexact for any of the components,
+then the entire result is marked inexact and the exactness check
+is skipped on the components that still need to be handled.
+
+It should be noted that \eqref{eq:transitive:components}
+is only valid for exact transitive closures.
+If overapproximations are computed in the right hand side, then the result will
+still be an overapproximation of the left hand side, but this result
+may not be transitively closed. If we only separate components based
+on the condition $R_i \circ R_j = \emptyset$, then there is no problem,
+as this condition will still hold on the computed approximations
+of the transitive closures. If, however, we have exploited
+\eqref{eq:transitive:edge} during the decomposition and if the
+result turns out not to be exact, then we check whether
+the result is transitively closed. If not, we recompute
+the transitive closure, skipping the decomposition.
+Note that testing for transitive closedness on the result may
+be fairly expensive, so we may want to make this check
+configurable.
+
+\begin{figure}
+\begin{center}
+\begin{tikzpicture}[x=0.5cm,y=0.5cm,>=stealth,shorten >=1pt]
+\foreach \x in {1,...,10}{
+ \foreach \y in {1,...,10}{
+ \draw[->] (\x,\y) -- (\x,\y+1);
+ }
+}
+\foreach \x in {1,...,20}{
+ \foreach \y in {5,...,15}{
+ \draw[->] (\x,\y) -- (\x+1,\y);
+ }
+}
+\end{tikzpicture}
+\end{center}
+\caption{The relation from \autoref{ex:closure4}}
+\label{f:closure4}
+\end{figure}
+\begin{example}
+\label{ex:closure4}
+Consider the relation in example {\tt closure4} that comes with
+the Omega calculator~\shortcite{Omega_calc}, $R = R_1 \cup R_2$,
+with
+$$
+\begin{aligned}
+R_1 & = \{\, (x,y) \to (x,y+1) \mid 1 \le x,y \le 10 \,\}
+\\
+R_2 & = \{\, (x,y) \to (x+1,y) \mid 1 \le x \le 20 \wedge 5 \le y \le 15 \,\}
+.
+\end{aligned}
+$$
+This relation is shown graphically in \autoref{f:closure4}.
+We have
+$$
+\begin{aligned}
+R_1 \circ R_2 &=
+\{\, (x,y) \to (x+1,y+1) \mid 1 \le x \le 9 \wedge 5 \le y \le 10 \,\}
+\\
+R_2 \circ R_1 &=
+\{\, (x,y) \to (x+1,y+1) \mid 1 \le x \le 10 \wedge 4 \le y \le 10 \,\}
+.
+\end{aligned}
+$$
+Clearly, $R_1 \circ R_2 \subseteq R_2 \circ R_1$ and so
+$$
+\left(
+R_1 \cup R_2
+\right)^+
+=
+\left(R_2^+ \circ R_1^+\right)
+\cup R_1^+
+\cup R_2^+
+.
+$$
+\end{example}
+
+\begin{figure}
+\newcounter{n}
+\newcounter{t1}
+\newcounter{t2}
+\newcounter{t3}
+\newcounter{t4}
+\begin{center}
+\begin{tikzpicture}[>=stealth,shorten >=1pt]
+\setcounter{n}{7}
+\foreach \i in {1,...,\value{n}}{
+ \foreach \j in {1,...,\value{n}}{
+ \setcounter{t1}{2 * \j - 4 - \i + 1}
+ \setcounter{t2}{\value{n} - 3 - \i + 1}
+ \setcounter{t3}{2 * \i - 1 - \j + 1}
+ \setcounter{t4}{\value{n} - \j + 1}
+ \ifnum\value{t1}>0\ifnum\value{t2}>0
+ \ifnum\value{t3}>0\ifnum\value{t4}>0
+ \draw[thick,->] (\i,\j) to[out=20] (\i+3,\j);
+ \fi\fi\fi\fi
+ \setcounter{t1}{2 * \j - 1 - \i + 1}
+ \setcounter{t2}{\value{n} - \i + 1}
+ \setcounter{t3}{2 * \i - 4 - \j + 1}
+ \setcounter{t4}{\value{n} - 3 - \j + 1}
+ \ifnum\value{t1}>0\ifnum\value{t2}>0
+ \ifnum\value{t3}>0\ifnum\value{t4}>0
+ \draw[thick,->] (\i,\j) to[in=-20,out=20] (\i,\j+3);
+ \fi\fi\fi\fi
+ \setcounter{t1}{2 * \j - 1 - \i + 1}
+ \setcounter{t2}{\value{n} - 1 - \i + 1}
+ \setcounter{t3}{2 * \i - 1 - \j + 1}
+ \setcounter{t4}{\value{n} - 1 - \j + 1}
+ \ifnum\value{t1}>0\ifnum\value{t2}>0
+ \ifnum\value{t3}>0\ifnum\value{t4}>0
+ \draw[thick,->] (\i,\j) to (\i+1,\j+1);
+ \fi\fi\fi\fi
+ }
+}
+\end{tikzpicture}
+\end{center}
+\caption{The relation from \autoref{ex:decomposition}}
+\label{f:decomposition}
+\end{figure}
+\begin{example}
+\label{ex:decomposition}
+Consider the relation on the right of \shortciteN[Figure~2]{Beletska2009},
+reproduced in \autoref{f:decomposition}.
+The relation can be described as $R = R_1 \cup R_2 \cup R_3$,
+with
+$$
+\begin{aligned}
+R_1 &= n \mapsto \{\, (i,j) \to (i+3,j) \mid
+i \le 2 j - 4 \wedge
+i \le n - 3 \wedge
+j \le 2 i - 1 \wedge
+j \le n \,\}
+\\
+R_2 &= n \mapsto \{\, (i,j) \to (i,j+3) \mid
+i \le 2 j - 1 \wedge
+i \le n \wedge
+j \le 2 i - 4 \wedge
+j \le n - 3 \,\}
+\\
+R_3 &= n \mapsto \{\, (i,j) \to (i+1,j+1) \mid
+i \le 2 j - 1 \wedge
+i \le n - 1 \wedge
+j \le 2 i - 1 \wedge
+j \le n - 1\,\}
+.
+\end{aligned}
+$$
+The figure shows this relation for $n = 7$.
+Both
+$R_3 \circ R_1 \subseteq R_1 \circ R_3$
+and
+$R_3 \circ R_2 \subseteq R_2 \circ R_3$,
+which the reader can verify using the {\tt iscc} calculator:
+\begin{verbatim}
+R1 := [n] -> { [i,j] -> [i+3,j] : i <= 2 j - 4 and i <= n - 3 and
+ j <= 2 i - 1 and j <= n };
+R2 := [n] -> { [i,j] -> [i,j+3] : i <= 2 j - 1 and i <= n and
+ j <= 2 i - 4 and j <= n - 3 };
+R3 := [n] -> { [i,j] -> [i+1,j+1] : i <= 2 j - 1 and i <= n - 1 and
+ j <= 2 i - 1 and j <= n - 1 };
+(R1 . R3) - (R3 . R1);
+(R2 . R3) - (R3 . R2);
+\end{verbatim}
+$R_3$ can therefore be moved forward in any path.
+For the other two basic relations, we have both
+$R_2 \circ R_1 \not\subseteq R_1 \circ R_2$
+and
+$R_1 \circ R_2 \not\subseteq R_2 \circ R_1$
+and so $R_1$ and $R_2$ form a strongly connected component.
+By computing the power of $R_3$ and $R_1 \cup R_2$ separately
+and composing the results, the power of $R$ can be computed exactly
+using \eqref{eq:transitive:singleton}.
+As explained by \shortciteN{Beletska2009}, applying the same formula
+to $R$ directly, without a decomposition, would result in
+an overapproximation of the power.
+\end{example}
+
+\subsection{Partitioning the domains and ranges of $R$}
+
+The algorithm of \autoref{s:power} assumes that the input relation $R$
+can be treated as a union of translations.
+This is a reasonable assumption if $R$ maps elements of a given
+abstract domain to the same domain.
+However, if $R$ is a union of relations that map between different
+domains, then this assumption no longer holds.
+In particular, when an entire dependence graph is encoded
+in a single relation, as is done by, e.g.,
+\shortciteN[Section~6.1]{Barthou2000MSE}, then it does not make
+sense to look at differences between iterations of different domains.
+Now, arguably, a modified Floyd-Warshall algorithm should
+be applied to the dependence graph, as advocated by
+\shortciteN{Kelly1996closure}, with the transitive closure operation
+only being applied to relations from a given domain to itself.
+However, it is also possible to detect disjoint domains and ranges
+and to apply Floyd-Warshall internally.
+
+\LinesNumbered
+\begin{algorithm}
+\caption{The modified Floyd-Warshall algorithm of
+\protect\shortciteN{Kelly1996closure}}
+\label{a:Floyd}
+\SetKwInput{Input}{Input}
+\SetKwInput{Output}{Output}
+\Input{Relations $R_{pq}$, $0 \le p, q < n$}
+\Output{Updated relations $R_{pq}$ such that each relation
+$R_{pq}$ contains all indirect paths from $p$ to $q$ in the input graph}
+%
+\BlankLine
+\SetAlgoVlined
+\DontPrintSemicolon
+%
+\For{$r \in [0, n-1]$}{
+ $R_{rr} \coloneqq R_{rr}^+$ \nllabel{l:Floyd:closure}\;
+ \For{$p \in [0, n-1]$}{
+ \For{$q \in [0, n-1]$}{
+ \If{$p \ne r$ or $q \ne r$}{
+ $R_{pq} \coloneqq R_{pq} \cup \left(R_{rq} \circ R_{pr}\right)
+ \cup \left(R_{rq} \circ R_{rr} \circ R_{pr}\right)$
+ \nllabel{l:Floyd:update}
+ }
+ }
+ }
+}
+\end{algorithm}
+
+Let the input relation $R$ be a union of $m$ basic relations $R_i$.
+Let $D_{2i}$ be the domains of $R_i$ and $D_{2i+1}$ the ranges of $R_i$.
+The first step is to group overlapping $D_j$ until a partition is
+obtained. If the resulting partition consists of a single part,
+then we continue with the algorithm of \autoref{s:power}.
+Otherwise, we apply Floyd-Warshall on the graph with as vertices
+the parts of the partition and as edges the $R_i$ attached to
+the appropriate pairs of vertices.
+In particular, let there be $n$ parts $P_k$ in the partition.
+We construct $n^2$ relations
+$$
+R_{pq} \coloneqq \bigcup_{i \text{ s.t. } \domain R_i \subseteq P_p \wedge
+ \range R_i \subseteq P_q} R_i
+,
+$$
+apply \autoref{a:Floyd} and return the union of all resulting
+$R_{pq}$ as the transitive closure of $R$.
+Each iteration of the $r$-loop in \autoref{a:Floyd} updates
+all relations $R_{pq}$ to include paths that go from $p$ to $r$,
+possibly stay there for a while, and then go from $r$ to $q$.
+Note that paths that ``stay in $r$'' include all paths that
+pass through earlier vertices since $R_{rr}$ itself has been updated
+accordingly in previous iterations of the outer loop.
+In principle, it would be sufficient to use the $R_{pr}$
+and $R_{rq}$ computed in the previous iteration of the
+$r$-loop in Line~\ref{l:Floyd:update}.
+However, from an implementation perspective, it is easier
+to allow either or both of these to have been updated
+in the same iteration of the $r$-loop.
+This may result in duplicate paths, but these can usually
+be removed by coalescing (\autoref{s:coalescing}) the result of the union
+in Line~\ref{l:Floyd:update}, which should be done in any case.
+The transitive closure in Line~\ref{l:Floyd:closure}
+is performed using a recursive call. This recursive call
+includes the partitioning step, but the resulting partition will
+usually be a singleton.
+The result of the recursive call will either be exact or an
+overapproximation. The final result of Floyd-Warshall is therefore
+also exact or an overapproximation.
+
+\begin{figure}
+\begin{center}
+\begin{tikzpicture}[x=1cm,y=1cm,>=stealth,shorten >=3pt]
+\foreach \x/\y in {0/0,1/1,3/2} {
+ \fill (\x,\y) circle (2pt);
+}
+\foreach \x/\y in {0/1,2/2,3/3} {
+ \draw (\x,\y) circle (2pt);
+}
+\draw[->] (0,0) -- (0,1);
+\draw[->] (0,1) -- (1,1);
+\draw[->] (2,2) -- (3,2);
+\draw[->] (3,2) -- (3,3);
+\draw[->,dashed] (2,2) -- (3,3);
+\draw[->,dotted] (0,0) -- (1,1);
+\end{tikzpicture}
+\end{center}
+\caption{The relation (solid arrows) on the right of Figure~1 of
+\protect\shortciteN{Beletska2009} and its transitive closure}
+\label{f:COCOA:1}
+\end{figure}
+\begin{example}
+Consider the relation on the right of Figure~1 of
+\shortciteN{Beletska2009},
+reproduced in \autoref{f:COCOA:1}.
+This relation can be described as
+$$
+\begin{aligned}
+\{\, (x, y) \to (x_2, y_2) \mid {} & (3y = 2x \wedge x_2 = x \wedge 3y_2 = 3 + 2x \wedge x \ge 0 \wedge x \le 3) \vee {} \\
+& (x_2 = 1 + x \wedge y_2 = y \wedge x \ge 0 \wedge 3y \ge 2 + 2x \wedge x \le 2 \wedge 3y \le 3 + 2x) \,\}
+.
+\end{aligned}
+$$
+Note that the domain of the upward relation overlaps with the range
+of the rightward relation and vice versa, but that the domain
+of neither relation overlaps with its own range or the domain of
+the other relation.
+The domains and ranges can therefore be partitioned into two parts,
+$P_0$ and $P_1$, shown as the white and black dots in \autoref{f:COCOA:1},
+respectively.
+Initially, we have
+$$
+\begin{aligned}
+R_{00} & = \emptyset
+\\
+R_{01} & =
+\{\, (x, y) \to (x+1, y) \mid
+(x \ge 0 \wedge 3y \ge 2 + 2x \wedge x \le 2 \wedge 3y \le 3 + 2x) \,\}
+\\
+R_{10} & =
+\{\, (x, y) \to (x_2, y_2) \mid (3y = 2x \wedge x_2 = x \wedge 3y_2 = 3 + 2x \wedge x \ge 0 \wedge x \le 3) \,\}
+\\
+R_{11} & = \emptyset
+.
+\end{aligned}
+$$
+In the first iteration, $R_{00}$ remains the same ($\emptyset^+ = \emptyset$).
+$R_{01}$ and $R_{10}$ are therefore also unaffected, but
+$R_{11}$ is updated to include $R_{01} \circ R_{10}$, i.e.,
+the dashed arrow in the figure.
+This new $R_{11}$ is obviously transitively closed, so it is not
+changed in the second iteration and it does not have an effect
+on $R_{01}$ and $R_{10}$. However, $R_{00}$ is updated to
+include $R_{10} \circ R_{01}$, i.e., the dotted arrow in the figure.
+The transitive closure of the original relation is then equal to
+$R_{00} \cup R_{01} \cup R_{10} \cup R_{11}$.
+\end{example}
+
+\subsection{Incremental Computation}
+\label{s:incremental}
+
+In some cases it is possible and useful to compute the transitive closure
+of union of basic relations incrementally. In particular,
+if $R$ is a union of $m$ basic maps,
+$$
+R = \bigcup_j R_j
+,
+$$
+then we can pick some $R_i$ and compute the transitive closure of $R$ as
+\begin{equation}
+\label{eq:transitive:incremental}
+R^+ = R_i^+ \cup
+\left(
+\bigcup_{j \ne i}
+R_i^* \circ R_j \circ R_i^*
+\right)^+
+.
+\end{equation}
+For this approach to be successful, it is crucial that each
+of the disjuncts in the argument of the second transitive
+closure in \eqref{eq:transitive:incremental} be representable
+as a single basic relation, i.e., without a union.
+If this condition holds, then by using \eqref{eq:transitive:incremental},
+the number of disjuncts in the argument of the transitive closure
+can be reduced by one.
+Now, $R_i^* = R_i^+ \cup \identity$, but in some cases it is possible
+to relax the constraints of $R_i^+$ to include part of the identity relation,
+say on domain $D$. We will use the notation
+${\cal C}(R_i,D) = R_i^+ \cup \identity_D$ to represent
+this relaxed version of $R^+$.
+\shortciteN{Kelly1996closure} use the notation $R_i^?$.
+${\cal C}(R_i,D)$ can be computed by allowing $k$ to attain
+the value $0$ in \eqref{eq:transitive:Q} and by using
+$$
+P \cap \left(D \to D\right)
+$$
+instead of \eqref{eq:transitive:approx}.
+Typically, $D$ will be a strict superset of both $\domain R_i$
+and $\range R_i$. We therefore need to check that domain
+and range of the transitive closure are part of ${\cal C}(R_i,D)$,
+i.e., the part that results from the paths of positive length ($k \ge 1$),
+are equal to the domain and range of $R_i$.
+If not, then the incremental approach cannot be applied for
+the given choice of $R_i$ and $D$.
+
+In order to be able to replace $R^*$ by ${\cal C}(R_i,D)$
+in \eqref{eq:transitive:incremental}, $D$ should be chosen
+to include both $\domain R$ and $\range R$, i.e., such
+that $\identity_D \circ R_j \circ \identity_D = R_j$ for all $j\ne i$.
+\shortciteN{Kelly1996closure} say that they use
+$D = \domain R_i \cup \range R_i$, but presumably they mean that
+they use $D = \domain R \cup \range R$.
+Now, this expression of $D$ contains a union, so it not directly usable.
+\shortciteN{Kelly1996closure} do not explain how they avoid this union.
+Apparently, in their implementation,
+they are using the convex hull of $\domain R \cup \range R$
+or at least an approximation of this convex hull.
+We use the simple hull (\autoref{s:simple hull}) of $\domain R \cup \range R$.
+
+It is also possible to use a domain $D$ that does {\em not\/}
+include $\domain R \cup \range R$, but then we have to
+compose with ${\cal C}(R_i,D)$ more selectively.
+In particular, if we have
+\begin{equation}
+\label{eq:transitive:right}
+\text{for each $j \ne i$ either }
+\domain R_j \subseteq D \text{ or } \domain R_j \cap \range R_i = \emptyset
+\end{equation}
+and, similarly,
+\begin{equation}
+\label{eq:transitive:left}
+\text{for each $j \ne i$ either }
+\range R_j \subseteq D \text{ or } \range R_j \cap \domain R_i = \emptyset
+\end{equation}
+then we can refine \eqref{eq:transitive:incremental} to
+$$
+R_i^+ \cup
+\left(
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \subseteq D $\\
+ $\scriptstyle\range R_j \subseteq D$}}
+{\cal C} \circ R_j \circ {\cal C}
+\right)
+\cup
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \cap \range R_i = \emptyset$\\
+ $\scriptstyle\range R_j \subseteq D$}}
+\!\!\!\!\!
+{\cal C} \circ R_j
+\right)
+\cup
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \subseteq D $\\
+ $\scriptstyle\range R_j \cap \domain R_i = \emptyset$}}
+\!\!\!\!\!
+R_j \circ {\cal C}
+\right)
+\cup
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \cap \range R_i = \emptyset$\\
+ $\scriptstyle\range R_j \cap \domain R_i = \emptyset$}}
+\!\!\!\!\!
+R_j
+\right)
+\right)^+
+.
+$$
+If only property~\eqref{eq:transitive:right} holds,
+we can use
+$$
+R_i^+ \cup
+\left(
+\left(
+R_i^+ \cup \identity
+\right)
+\circ
+\left(
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \subseteq D $}}
+R_j \circ {\cal C}
+\right)
+\cup
+\left(
+\bigcup_{\shortstack{$\scriptstyle\domain R_j \cap \range R_i = \emptyset$}}
+\!\!\!\!\!
+R_j
+\right)
+\right)^+
+\right)
+,
+$$
+while if only property~\eqref{eq:transitive:left} holds,
+we can use
+$$
+R_i^+ \cup
+\left(
+\left(
+\left(
+\bigcup_{\shortstack{$\scriptstyle\range R_j \subseteq D $}}
+{\cal C} \circ R_j
+\right)
+\cup
+\left(
+\bigcup_{\shortstack{$\scriptstyle\range R_j \cap \domain R_i = \emptyset$}}
+\!\!\!\!\!
+R_j
+\right)
+\right)^+
+\circ
+\left(
+R_i^+ \cup \identity
+\right)
+\right)
+.
+$$
+
+It should be noted that if we want the result of the incremental
+approach to be transitively closed, then we can only apply it
+if all of the transitive closure operations involved are exact.
+If, say, the second transitive closure in \eqref{eq:transitive:incremental}
+contains extra elements, then the result does not necessarily contain
+the composition of these extra elements with powers of $R_i$.
+
+\subsection{An {\tt Omega}-like implementation}
+
+While the main algorithm of \shortciteN{Kelly1996closure} is
+designed to compute and underapproximation of the transitive closure,
+the authors mention that they could also compute overapproximations.
+In this section, we describe our implementation of an algorithm
+that is based on their ideas.
+Note that the {\tt Omega} library computes underapproximations
+\shortcite[Section 6.4]{Omega_lib}.
+
+The main tool is Equation~(2) of \shortciteN{Kelly1996closure}.
+The input relation $R$ is first overapproximated by a ``d-form'' relation
+$$
+\{\, \vec i \to \vec j \mid \exists \vec \alpha :
+\vec L \le \vec j - \vec i \le \vec U
+\wedge
+(\forall p : j_p - i_p = M_p \alpha_p)
+\,\}
+,
+$$
+where $p$ ranges over the dimensions and $\vec L$, $\vec U$ and
+$\vec M$ are constant integer vectors. The elements of $\vec U$
+may be $\infty$, meaning that there is no upper bound corresponding
+to that element, and similarly for $\vec L$.
+Such an overapproximation can be obtained by computing strides,
+lower and upper bounds on the difference set $\Delta \, R$.
+The transitive closure of such a ``d-form'' relation is
+\begin{equation}
+\label{eq:omega}
+\{\, \vec i \to \vec j \mid \exists \vec \alpha, k :
+k \ge 1 \wedge
+k \, \vec L \le \vec j - \vec i \le k \, \vec U
+\wedge
+(\forall p : j_p - i_p = M_p \alpha_p)
+\,\}
+.
+\end{equation}
+The domain and range of this transitive closure are then
+intersected with those of the input relation.
+This is a special case of the algorithm in \autoref{s:power}.
+
+In their algorithm for computing lower bounds, the authors
+use the above algorithm as a substep on the disjuncts in the relation.
+At the end, they say
+\begin{quote}
+If an upper bound is required, it can be calculated in a manner
+similar to that of a single conjunct [sic] relation.
+\end{quote}
+Presumably, the authors mean that a ``d-form'' approximation
+of the whole input relation should be used.
+However, the accuracy can be improved by also trying to
+apply the incremental technique from the same paper,
+which is explained in more detail in \autoref{s:incremental}.
+In this case, ${\cal C}(R_i,D)$ can be obtained by
+allowing the value zero for $k$ in \eqref{eq:omega},
+i.e., by computing
+$$
+\{\, \vec i \to \vec j \mid \exists \vec \alpha, k :
+k \ge 0 \wedge
+k \, \vec L \le \vec j - \vec i \le k \, \vec U
+\wedge
+(\forall p : j_p - i_p = M_p \alpha_p)
+\,\}
+.
+$$
+In our implementation we take as $D$ the simple hull
+(\autoref{s:simple hull}) of $\domain R \cup \range R$.
+To determine whether it is safe to use ${\cal C}(R_i,D)$,
+we check the following conditions, as proposed by
+\shortciteN{Kelly1996closure}:
+${\cal C}(R_i,D) - R_i^+$ is not a union and for each $j \ne i$
+the condition
+$$
+\left({\cal C}(R_i,D) - R_i^+\right)
+\circ
+R_j
+\circ
+\left({\cal C}(R_i,D) - R_i^+\right)
+=
+R_j
+$$
+holds.
diff --git a/polly/lib/External/isl/doc/isl.bib b/polly/lib/External/isl/doc/isl.bib
new file mode 100644
index 00000000000..cfe8081e56b
--- /dev/null
+++ b/polly/lib/External/isl/doc/isl.bib
@@ -0,0 +1,313 @@
+@inproceedings{Kelly1996closure,
+ author = {Wayne Kelly and
+ William Pugh and
+ Evan Rosser and
+ Tatiana Shpeisman},
+ title = {Transitive Closure of Infinite Graphs and Its Applications},
+ pages = {126-140},
+ editor = {Chua-Huang Huang and
+ P. Sadayappan and
+ Utpal Banerjee and
+ David Gelernter and
+ Alexandru Nicolau and
+ David A. Padua},
+ booktitle = {Languages and Compilers for Parallel Computing, 8th International
+ Workshop, LCPC'95, Columbus, Ohio, USA, August 10-12, 1995,
+ Proceedings},
+ publisher = {Springer},
+ series = {Lecture Notes in Computer Science},
+ volume = {1033},
+ year = {1996},
+ isbn = {3-540-60765-X},
+}
+
+@inproceedings{Beletska2009,
+ author = {Beletska, Anna and Barthou, Denis and Bielecki, Wlodzimierz and Cohen, Albert},
+ title = {Computing the Transitive Closure of a Union of Affine Integer Tuple Relations},
+ booktitle = {COCOA '09: Proceedings of the 3rd International Conference on Combinatorial Optimization and Applications},
+ year = {2009},
+ isbn = {978-3-642-02025-4},
+ pages = {98--109},
+ location = {Huangshan, China},
+ doi = {10.1007/978-3-642-02026-1_9},
+ publisher = {Springer-Verlag},
+ address = {Berlin, Heidelberg},
+}
+
+@book{Schrijver1986,
+ author = "Schrijver, Alexander",
+ title = "Theory of Linear and Integer Programming",
+ publisher = "John Wiley \& Sons",
+ year = 1986
+}
+
+@article{Tarjan1972,
+ author = {Tarjan, Robert},
+ journal = {SIAM Journal on Computing},
+ number = {2},
+ pages = {146--160},
+ publisher = {SIAM},
+ title = {Depth-First Search and Linear Graph Algorithms},
+ volume = {1},
+ year = {1972}
+}
+
+@TechReport{ Omega_calc,
+ author = "Wayne Kelly and Vadim Maslov and William Pugh and Evan Rosser and Tatiana Shpeisman and Dave Wonnacott",
+ title = "The {Omega} Calculator and Library",
+ month = nov,
+ institution = "University of Maryland",
+ year = 1996
+}
+
+@TechReport{ Omega_lib,
+ author = "Wayne Kelly and Vadim Maslov and William Pugh and Evan Rosser and Tatiana Shpeisman and Dave Wonnacott",
+ title = "The {Omega} Library",
+ month = nov,
+ institution = "University of Maryland",
+ year = 1996
+}
+
+@unpublished{Verdoolaege2009isl,
+ author = "Verdoolaege, Sven",
+ title = "An integer set library for program analysis",
+ note = "Advances in the Theory of Integer Linear Optimization and its Extensions,AMS 2009 Spring Western Section Meeting, San Francisco, California, 25-26 April 2009",
+ month = Apr,
+ year = "2009",
+ url = "https://lirias.kuleuven.be/handle/123456789/228373",
+}
+
+@article{Barthou2000MSE,
+ author = {Barthou, Denis and Cohen, Albert and Collard, Jean-Fran\c{c}ois},
+ title = {Maximal Static Expansion},
+ journal = {Int. J. Parallel Program.},
+ volume = {28},
+ number = {3},
+ year = {2000},
+ issn = {0885-7458},
+ pages = {213--243},
+ doi = {10.1023/A:1007500431910},
+ publisher = {Kluwer Academic Publishers},
+ address = {Norwell, MA, USA},
+}
+
+@article{ Feautrier88parametric,
+ author = "P. Feautrier",
+ title = "Parametric Integer Programming",
+ journal = "RAIRO Recherche Op\'erationnelle",
+ volume = "22",
+ number = "3",
+ pages = "243--268",
+ year = "1988",
+}
+
+@Article{ Fea91,
+ author = {Feautrier, P.},
+ title = {Dataflow analysis of array and scalar references},
+ journal = {International Journal of Parallel Programming},
+ year = {1991},
+ OPTkey = {},
+ volume = {20},
+ number = {1},
+ OPTmonth = {},
+ pages = {23--53},
+ OPTnote = {},
+ OPTannote = {},
+}
+
+@INPROCEEDINGS{BouletRe98,
+ AUTHOR = {Pierre Boulet and Xavier Redon},
+ TITLE = {Communication Pre-evaluation in {HPF}},
+ BOOKTITLE = {EUROPAR'98},
+ PAGES = {263--272},
+ YEAR = 1998,
+ VOLUME = 1470,
+ series = {Lecture Notes in Computer Science},
+ PUBLISHER = {Springer-Verlag, Berlin},
+ ABSTRACT = { Parallel computers are difficult to program efficiently. We believe
+ that a good way to help programmers write efficient programs is to
+ provide them with tools that show them how their programs behave on
+ a parallel computer. Data distribution is the major performance
+ factor of data-parallel programs and so automatic data layout for
+ HPF programs has been studied by many researchers recently. The
+ communication volume induced by a data distribution is a good
+ estimator of the efficiency of this data distribution.
+
+ We present here a symbolic method to compute the communication
+ volume generated by a given data distribution during the program
+ writing phase (before compilation). We stay machine-independent to
+ assure portability. Our goal is to help the programmer understand
+ the data movements its program generates and thus find a good data
+ distribution. Our method is based on parametric polyhedral
+ computations. It can be applied to a large class of regular codes.},
+}
+
+@INPROCEEDINGS {Verdoolaege2005experiences,
+ AUTHOR = "Verdoolaege, Sven and Beyls, Kristof and Bruynooghe, Maurice and Catthoor, Francky",
+ TITLE = {{E}xperiences with enumeration of integer projections of parametric polytopes},
+ BOOKTITLE = {{P}roceedings of 14th {I}nternational {C}onference on {C}ompiler {C}onstruction, {E}dinburgh, {S}cotland},
+ YEAR = {2005},
+ EDITOR = {Bodik, R.},
+ VOLUME = 3443,
+ pages = "91-105",
+ series = "Lecture Notes in Computer Science",
+ publisher = "Springer-Verlag",
+ address = "Berlin",
+ doi = "10.1007/b107108",
+}
+
+@article{Detlefs2005simplify,
+ author = {David Detlefs and Greg Nelson and James B. Saxe},
+ title = {Simplify: a theorem prover for program checking},
+ journal = {J. ACM},
+ volume = {52},
+ number = {3},
+ year = {2005},
+ issn = {0004-5411},
+ pages = {365--473},
+ doi = {10.1145/1066100.1066102},
+ publisher = {ACM},
+ address = {New York, NY, USA},
+ }
+
+@phdthesis{Nelson1980phd,
+ author = {Charles Gregory Nelson},
+ title = {Techniques for program verification},
+ year = {1980},
+ order_no = {AAI8011683},
+ school = {Stanford University},
+ address = {Stanford, CA, USA},
+ }
+
+@article{Woods2003short,
+ year = 2003,
+ Journal = "J. Amer. Math. Soc.",
+ volume = 16,
+ pages = "957--979",
+ month = apr,
+ title = {{Short rational generating functions for lattice point
+ problems}},
+ author = {Alexander Barvinok and Kevin Woods},
+}
+
+@misc{barvinok-0.22,
+ author = {Sven Verdoolaege},
+ title = {{\texttt{barvinok}}, version 0.22},
+ howpublished = {Available from \url{http://freshmeat.net/projects/barvinok/}},
+ year = 2006
+}
+
+@inproceedings{DeLoera2004Three,
+ title = "Three Kinds of Integer Programming Algorithms based on Barvinok's Rational Functions",
+ author = "De Loera, J. A. and D. Haws and R. Hemmecke and P. Huggins and R. Yoshida",
+ booktitle = "Integer Programming and Combinatorial Optimization: 10th International IPCO Conference",
+ year = "2004",
+ month = jan,
+ series = "Lecture Notes in Computer Science",
+ Volume = 3064,
+ Pages = "244-255",
+}
+
+@TechReport{Feautrier02,
+ author = {P. Feautrier and J. Collard and C. Bastoul},
+ title = {Solving systems of affine (in)equalities},
+ institution = {PRiSM, Versailles University},
+ year = 2002
+}
+
+@article{ Feautrier92multi,
+ author = "Paul Feautrier",
+ title = "Some Efficient Solutions to the Affine Scheduling Problem. {P}art {II}. Multidimensional Time",
+ journal = "International Journal of Parallel Programming",
+ volume = "21",
+ number = "6",
+ pages = "389--420",
+ year = "1992",
+ month = dec,
+ url = "citeseer.nj.nec.com/article/feautrier92some.html",
+}
+
+@misc{Bygde2010licentiate,
+ author = {Stefan Bygde},
+ title = {Static {WCET} Analysis based on Abstract Interpretation and Counting of Elements},
+ month = {March},
+ year = {2010},
+ howpublished = {Licentiate thesis},
+ publisher = {M{\"{a}}lardalen University Press},
+ url = {http://www.mrtc.mdh.se/index.php?choice=publications&id=2144},
+}
+
+@phdthesis{Meister2004PhD,
+ title = {Stating and Manipulating Periodicity in the Polytope Model. Applications to Program Analysis and Optimization},
+ author= {Beno\^it Meister},
+ school = {Universit\'e Louis Pasteur},
+ month = Dec,
+ year = {2004},
+}
+
+@inproceedings{Meister2008,
+ author = {Beno\^it Meister and Sven Verdoolaege},
+ title = {Polynomial Approximations in the Polytope Model: Bringing the Power
+ of Quasi-Polynomials to the Masses},
+ year = {2008},
+ booktitle = {Digest of the 6th Workshop on Optimization for DSP and Embedded Systems, ODES-6},
+ editor = "Jagadeesh Sankaran and Vander Aa, Tom",
+ month = apr,
+}
+
+@misc{Galea2009personal,
+ author = "Fran\c{c}ois Galea",
+ title = "personal communication",
+ year = 2009,
+ month = nov,
+}
+
+@misc{PPL,
+ author = "R. Bagnara and P. M. Hill and E. Zaffanella",
+ title = "The {Parma Polyhedra Library}",
+ howpublished = {\url{http://www.cs.unipr.it/ppl/}},
+}
+
+@TECHREPORT{Cook1991implementation,
+AUTHOR={William Cook and Thomas Rutherford and Herbert E. Scarf and David F. Shallcross},
+TITLE={An Implementation of the Generalized Basis Reduction Algorithm for Integer Programming},
+YEAR=1991,
+MONTH=Aug,
+INSTITUTION={Cowles Foundation, Yale University},
+TYPE={Cowles Foundation Discussion Papers},
+NOTE={available at \url{http://ideas.repec.org/p/cwl/cwldpp/990.html}},
+NUMBER={990},
+}
+
+ @article{Karr1976affine,
+author={ Michael Karr},
+title={ Affine Relationships Among Variables of a Program },
+journal={Acta Informatica},
+Volume={6},
+pages={133-151},
+year={1976},
+publisher={Springer-Verlag},
+ignore={ },
+}
+
+@PhdThesis{Verhaegh1995PhD,
+ title = "Multidimensional Periodic Scheduling",
+ author = "Wim F. J. Verhaegh",
+ school = "Technische Universiteit Eindhoven",
+ year = 1995,
+}
+
+@INPROCEEDINGS{Seghir2006minimizing,
+ AUTHOR = "Rachid Seghir and Vincent Loechner",
+ TITLE = {Memory Optimization by Counting Points in Integer Transformations of Parametric Polytopes},
+ BOOKTITLE = {{P}roceedings of the {I}nternational {C}onference on {C}ompilers, {A}rchitectures, and {S}ynthesis for {E}mbedded Systems, CASES 2006, {S}eoul, {K}orea},
+ month = oct,
+ YEAR = {2006}
+}
+
+@misc{DeSmet2010personal,
+ author = "De Smet, Sven",
+ title = "personal communication",
+ year = 2010,
+ month = apr,
+}
diff --git a/polly/lib/External/isl/doc/manual.tex b/polly/lib/External/isl/doc/manual.tex
new file mode 100644
index 00000000000..91b3db0e640
--- /dev/null
+++ b/polly/lib/External/isl/doc/manual.tex
@@ -0,0 +1,75 @@
+\documentclass{report}
+\usepackage[plainpages=false,pdfpagelabels,breaklinks,pagebackref]{hyperref}
+\usepackage{amsmath}
+\usepackage{amssymb}
+\usepackage{txfonts}
+\usepackage{chicago}
+\usepackage{aliascnt}
+\usepackage{tikz}
+\usepackage{calc}
+\usepackage[ruled]{algorithm2e}
+\usetikzlibrary{matrix,fit,backgrounds,decorations.pathmorphing,positioning}
+\usepackage{listings}
+
+\lstset{basicstyle=\tt,flexiblecolumns=false}
+
+\def\vec#1{\mathchoice{\mbox{\boldmath$\displaystyle\bf#1$}}
+{\mbox{\boldmath$\textstyle\bf#1$}}
+{\mbox{\boldmath$\scriptstyle\bf#1$}}
+{\mbox{\boldmath$\scriptscriptstyle\bf#1$}}}
+
+\providecommand{\fract}[1]{\left\{#1\right\}}
+\providecommand{\floor}[1]{\left\lfloor#1\right\rfloor}
+\providecommand{\ceil}[1]{\left\lceil#1\right\rceil}
+\def\sp#1#2{\langle #1, #2 \rangle}
+\def\spv#1#2{\langle\vec #1,\vec #2\rangle}
+
+\newtheorem{theorem}{Theorem}
+\newaliascnt{example}{theorem}
+\newtheorem{example}[example]{Example}
+\newaliascnt{def}{theorem}
+\newtheorem{definition}[def]{Definition}
+\aliascntresetthe{example}
+\aliascntresetthe{def}
+\numberwithin{theorem}{section}
+\numberwithin{def}{section}
+\numberwithin{example}{section}
+
+\newcommand{\algocflineautorefname}{Algorithm}
+\newcommand{\exampleautorefname}{Example}
+\newcommand{\lstnumberautorefname}{Line}
+\renewcommand{\sectionautorefname}{Section}
+\renewcommand{\subsectionautorefname}{Section}
+
+\def\Z{\mathbb{Z}}
+\def\Q{\mathbb{Q}}
+
+\def\pdom{\mathop{\rm pdom}\nolimits}
+\def\domain{\mathop{\rm dom}\nolimits}
+\def\range{\mathop{\rm ran}\nolimits}
+\def\identity{\mathop{\rm Id}\nolimits}
+\def\diff{\mathop{\Delta}\nolimits}
+
+\providecommand{\floor}[1]{\left\lfloor#1\right\rfloor}
+
+\begin{document}
+
+\title{Integer Set Library: Manual\\
+\small Version: \input{version} }
+\author{Sven Verdoolaege}
+
+\maketitle
+\tableofcontents
+
+\chapter{User Manual}
+
+\input{user}
+
+\chapter{Implementation Details}
+
+\input{implementation}
+
+\bibliography{isl}
+\bibliographystyle{chicago}
+
+\end{document}
diff --git a/polly/lib/External/isl/doc/mypod2latex b/polly/lib/External/isl/doc/mypod2latex
new file mode 100755
index 00000000000..b11c0593d01
--- /dev/null
+++ b/polly/lib/External/isl/doc/mypod2latex
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use strict;
+use Pod::LaTeX;
+
+my ($in, $out) = @ARGV;
+
+my $parser = new Pod::LaTeX(
+ AddPreamble => 0,
+ AddPostamble => 0,
+ LevelNoNum => 5,
+ );
+
+$parser->parse_from_file($in, $out);
diff --git a/polly/lib/External/isl/doc/user.pod b/polly/lib/External/isl/doc/user.pod
new file mode 100644
index 00000000000..f5c0c4dfe42
--- /dev/null
+++ b/polly/lib/External/isl/doc/user.pod
@@ -0,0 +1,8039 @@
+=head1 Introduction
+
+C<isl> is a thread-safe C library for manipulating
+sets and relations of integer points bounded by affine constraints.
+The descriptions of the sets and relations may involve
+both parameters and existentially quantified variables.
+All computations are performed in exact integer arithmetic
+using C<GMP> or C<imath>.
+The C<isl> library offers functionality that is similar
+to that offered by the C<Omega> and C<Omega+> libraries,
+but the underlying algorithms are in most cases completely different.
+
+The library is by no means complete and some fairly basic
+functionality is still missing.
+Still, even in its current form, the library has been successfully
+used as a backend polyhedral library for the polyhedral
+scanner C<CLooG> and as part of an equivalence checker of
+static affine programs.
+For bug reports, feature requests and questions,
+visit the discussion group at
+L<http://groups.google.com/group/isl-development>.
+
+=head2 Backward Incompatible Changes
+
+=head3 Changes since isl-0.02
+
+=over
+
+=item * The old printing functions have been deprecated
+and replaced by C<isl_printer> functions, see L<Input and Output>.
+
+=item * Most functions related to dependence analysis have acquired
+an extra C<must> argument. To obtain the old behavior, this argument
+should be given the value 1. See L<Dependence Analysis>.
+
+=back
+
+=head3 Changes since isl-0.03
+
+=over
+
+=item * The function C<isl_pw_qpolynomial_fold_add> has been
+renamed to C<isl_pw_qpolynomial_fold_fold>.
+Similarly, C<isl_union_pw_qpolynomial_fold_add> has been
+renamed to C<isl_union_pw_qpolynomial_fold_fold>.
+
+=back
+
+=head3 Changes since isl-0.04
+
+=over
+
+=item * All header files have been renamed from C<isl_header.h>
+to C<isl/header.h>.
+
+=back
+
+=head3 Changes since isl-0.05
+
+=over
+
+=item * The functions C<isl_printer_print_basic_set> and
+C<isl_printer_print_basic_map> no longer print a newline.
+
+=item * The functions C<isl_flow_get_no_source>
+and C<isl_union_map_compute_flow> now return
+the accesses for which no source could be found instead of
+the iterations where those accesses occur.
+
+=item * The functions C<isl_basic_map_identity> and
+C<isl_map_identity> now take a B<map> space as input. An old call
+C<isl_map_identity(space)> can be rewritten to
+C<isl_map_identity(isl_space_map_from_set(space))>.
+
+=item * The function C<isl_map_power> no longer takes
+a parameter position as input. Instead, the exponent
+is now expressed as the domain of the resulting relation.
+
+=back
+
+=head3 Changes since isl-0.06
+
+=over
+
+=item * The format of C<isl_printer_print_qpolynomial>'s
+C<ISL_FORMAT_ISL> output has changed.
+Use C<ISL_FORMAT_C> to obtain the old output.
+
+=item * The C<*_fast_*> functions have been renamed to C<*_plain_*>.
+Some of the old names have been kept for backward compatibility,
+but they will be removed in the future.
+
+=back
+
+=head3 Changes since isl-0.07
+
+=over
+
+=item * The function C<isl_pw_aff_max> has been renamed to
+C<isl_pw_aff_union_max>.
+Similarly, the function C<isl_pw_aff_add> has been renamed to
+C<isl_pw_aff_union_add>.
+
+=item * The C<isl_dim> type has been renamed to C<isl_space>
+along with the associated functions.
+Some of the old names have been kept for backward compatibility,
+but they will be removed in the future.
+
+=item * Spaces of maps, sets and parameter domains are now
+treated differently. The distinction between map spaces and set spaces
+has always been made on a conceptual level, but proper use of such spaces
+was never checked. Furthermore, up until isl-0.07 there was no way
+of explicitly creating a parameter space. These can now be created
+directly using C<isl_space_params_alloc> or from other spaces using
+C<isl_space_params>.
+
+=item * The space in which C<isl_aff>, C<isl_pw_aff>, C<isl_qpolynomial>,
+C<isl_pw_qpolynomial>, C<isl_qpolynomial_fold> and C<isl_pw_qpolynomial_fold>
+objects live is now a map space
+instead of a set space. This means, for example, that the dimensions
+of the domain of an C<isl_aff> are now considered to be of type
+C<isl_dim_in> instead of C<isl_dim_set>. Extra functions have been
+added to obtain the domain space. Some of the constructors still
+take a domain space and have therefore been renamed.
+
+=item * The functions C<isl_equality_alloc> and C<isl_inequality_alloc>
+now take an C<isl_local_space> instead of an C<isl_space>.
+An C<isl_local_space> can be created from an C<isl_space>
+using C<isl_local_space_from_space>.
+
+=item * The C<isl_div> type has been removed. Functions that used
+to return an C<isl_div> now return an C<isl_aff>.
+Note that the space of an C<isl_aff> is that of relation.
+When replacing a call to C<isl_div_get_coefficient> by a call to
+C<isl_aff_get_coefficient> any C<isl_dim_set> argument needs
+to be replaced by C<isl_dim_in>.
+A call to C<isl_aff_from_div> can be replaced by a call
+to C<isl_aff_floor>.
+A call to C<isl_qpolynomial_div(div)> call be replaced by
+the nested call
+
+ isl_qpolynomial_from_aff(isl_aff_floor(div))
+
+The function C<isl_constraint_div> has also been renamed
+to C<isl_constraint_get_div>.
+
+=item * The C<nparam> argument has been removed from
+C<isl_map_read_from_str> and similar functions.
+When reading input in the original PolyLib format,
+the result will have no parameters.
+If parameters are expected, the caller may want to perform
+dimension manipulation on the result.
+
+=back
+
+=head3 Changes since isl-0.09
+
+=over
+
+=item * The C<schedule_split_parallel> option has been replaced
+by the C<schedule_split_scaled> option.
+
+=item * The first argument of C<isl_pw_aff_cond> is now
+an C<isl_pw_aff> instead of an C<isl_set>.
+A call C<isl_pw_aff_cond(a, b, c)> can be replaced by
+
+ isl_pw_aff_cond(isl_set_indicator_function(a), b, c)
+
+=back
+
+=head3 Changes since isl-0.10
+
+=over
+
+=item * The functions C<isl_set_dim_has_lower_bound> and
+C<isl_set_dim_has_upper_bound> have been renamed to
+C<isl_set_dim_has_any_lower_bound> and
+C<isl_set_dim_has_any_upper_bound>.
+The new C<isl_set_dim_has_lower_bound> and
+C<isl_set_dim_has_upper_bound> have slightly different meanings.
+
+=back
+
+=head3 Changes since isl-0.12
+
+=over
+
+=item * C<isl_int> has been replaced by C<isl_val>.
+Some of the old functions are still available in C<isl/deprecated/*.h>
+but they will be removed in the future.
+
+=item * The functions C<isl_pw_qpolynomial_eval>,
+C<isl_union_pw_qpolynomial_eval>, C<isl_pw_qpolynomial_fold_eval>
+and C<isl_union_pw_qpolynomial_fold_eval> have been changed to return
+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
+setting up coincidence constraints.
+The option C<schedule_outer_zero_distance> has accordingly been
+replaced by the option C<schedule_outer_coincidence>.
+
+=item * The function C<isl_vertex_get_expr> has been changed
+to return an C<isl_multi_aff> instead of a rational C<isl_basic_set>.
+The function C<isl_vertex_get_domain> has been changed to return
+a regular basic set, rather than a rational basic set.
+
+=back
+
+=head3 Changes since isl-0.14
+
+=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
+to compute the sum on the union of definition domains.
+The original behavior of C<isl_union_pw_multi_aff_add> was
+confused and is no longer available.
+
+=back
+
+=head1 License
+
+C<isl> is released under the MIT license.
+
+=over
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+=back
+
+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.
+
+=head1 Installation
+
+The source of C<isl> can be obtained either as a tarball
+or from the git repository. Both are available from
+L<http://freshmeat.net/projects/isl/>.
+The installation process depends on how you obtained
+the source.
+
+=head2 Installation from the git repository
+
+=over
+
+=item 1 Clone or update the repository
+
+The first time the source is obtained, you need to clone
+the repository.
+
+ git clone git://repo.or.cz/isl.git
+
+To obtain updates, you need to pull in the latest changes
+
+ git pull
+
+=item 2 Optionally get C<imath> submodule
+
+To build C<isl> with C<imath>, you need to obtain the C<imath>
+submodule by running in the git source tree of C<isl>
+
+ git submodule init
+ git submodule update
+
+This will fetch the required version of C<imath> in a subdirectory of C<isl>.
+
+=item 2 Generate C<configure>
+
+ ./autogen.sh
+
+=back
+
+After performing the above steps, continue
+with the L<Common installation instructions>.
+
+=head2 Common installation instructions
+
+=over
+
+=item 1 Obtain C<GMP>
+
+By default, building C<isl> requires C<GMP>, including its headers files.
+Your distribution may not provide these header files by default
+and you may need to install a package called C<gmp-devel> or something
+similar. Alternatively, C<GMP> can be built from
+source, available from L<http://gmplib.org/>.
+C<GMP> is not needed if you build C<isl> with C<imath>.
+
+=item 2 Configure
+
+C<isl> uses the standard C<autoconf> C<configure> script.
+To run it, just type
+
+ ./configure
+
+optionally followed by some configure options.
+A complete list of options can be obtained by running
+
+ ./configure --help
+
+Below we discuss some of the more common options.
+
+=over
+
+=item C<--prefix>
+
+Installation prefix for C<isl>
+
+=item C<--with-int=[gmp|imath]>
+
+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>.
+
+=item C<--with-gmp-prefix>
+
+Installation prefix for C<GMP> (architecture-independent files).
+
+=item C<--with-gmp-exec-prefix>
+
+Installation prefix for C<GMP> (architecture-dependent files).
+
+=back
+
+=item 3 Compile
+
+ make
+
+=item 4 Install (optional)
+
+ make install
+
+=back
+
+=head1 Integer Set Library
+
+=head2 Memory Management
+
+Since a high-level operation on isl objects usually involves
+several substeps and since the user is usually not interested in
+the intermediate results, most functions that return a new object
+will also release all the objects passed as arguments.
+If the user still wants to use one or more of these arguments
+after the function call, she should pass along a copy of the
+object rather than the object itself.
+The user is then responsible for making sure that the original
+object gets used somewhere else or is explicitly freed.
+
+The arguments and return values of all documented functions are
+annotated to make clear which arguments are released and which
+arguments are preserved. In particular, the following annotations
+are used
+
+=over
+
+=item C<__isl_give>
+
+C<__isl_give> means that a new object is returned.
+The user should make sure that the returned pointer is
+used exactly once as a value for an C<__isl_take> argument.
+In between, it can be used as a value for as many
+C<__isl_keep> arguments as the user likes.
+There is one exception, and that is the case where the
+pointer returned is C<NULL>. Is this case, the user
+is free to use it as an C<__isl_take> argument or not.
+When applied to a C<char *>, the returned pointer needs to be
+freed using C<free>.
+
+=item C<__isl_null>
+
+C<__isl_null> means that a C<NULL> value is returned.
+
+=item C<__isl_take>
+
+C<__isl_take> means that the object the argument points to
+is taken over by the function and may no longer be used
+by the user as an argument to any other function.
+The pointer value must be one returned by a function
+returning an C<__isl_give> pointer.
+If the user passes in a C<NULL> value, then this will
+be treated as an error in the sense that the function will
+not perform its usual operation. However, it will still
+make sure that all the other C<__isl_take> arguments
+are released.
+
+=item C<__isl_keep>
+
+C<__isl_keep> means that the function will only use the object
+temporarily. After the function has finished, the user
+can still use it as an argument to other functions.
+A C<NULL> value will be treated in the same way as
+a C<NULL> value for an C<__isl_take> argument.
+This annotation may also be used on return values of
+type C<const char *>, in which case the returned pointer should
+not be freed by the user and is only valid until the object
+from which it was derived is updated or freed.
+
+=back
+
+=head2 Initialization
+
+All manipulations of integer sets and relations occur within
+the context of an C<isl_ctx>.
+A given C<isl_ctx> can only be used within a single thread.
+All arguments of a function are required to have been allocated
+within the same context.
+There are currently no functions available for moving an object
+from one C<isl_ctx> to another C<isl_ctx>. This means that
+there is currently no way of safely moving an object from one
+thread to another, unless the whole C<isl_ctx> is moved.
+
+An C<isl_ctx> can be allocated using C<isl_ctx_alloc> and
+freed using C<isl_ctx_free>.
+All objects allocated within an C<isl_ctx> should be freed
+before the C<isl_ctx> itself is freed.
+
+ isl_ctx *isl_ctx_alloc();
+ void isl_ctx_free(isl_ctx *ctx);
+
+The user can impose a bound on the number of low-level I<operations>
+that can be performed by an C<isl_ctx>. This bound can be set and
+retrieved using the following functions. A bound of zero means that
+no bound is imposed. The number of operations performed can be
+reset using C<isl_ctx_reset_operations>. Note that the number
+of low-level operations needed to perform a high-level computation
+may differ significantly across different versions
+of C<isl>, but it should be the same across different platforms
+for the same version of C<isl>.
+
+Warning: This feature is experimental. C<isl> has good support to abort and
+bail out during the computation, but this feature may exercise error code paths
+that are normally not used that much. Consequently, it is not unlikely that
+hidden bugs will be exposed.
+
+ void isl_ctx_set_max_operations(isl_ctx *ctx,
+ unsigned long max_operations);
+ unsigned long isl_ctx_get_max_operations(isl_ctx *ctx);
+ void isl_ctx_reset_operations(isl_ctx *ctx);
+
+In order to be able to create an object in the same context
+as another object, most object types (described later in
+this document) provide a function to obtain the context
+in which the object was created.
+
+ #include <isl/val.h>
+ isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val);
+ isl_ctx *isl_multi_val_get_ctx(
+ __isl_keep isl_multi_val *mv);
+
+ #include <isl/id.h>
+ isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id);
+
+ #include <isl/local_space.h>
+ isl_ctx *isl_local_space_get_ctx(
+ __isl_keep isl_local_space *ls);
+
+ #include <isl/set.h>
+ isl_ctx *isl_set_list_get_ctx(
+ __isl_keep isl_set_list *list);
+
+ #include <isl/aff.h>
+ isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff);
+ isl_ctx *isl_multi_aff_get_ctx(
+ __isl_keep isl_multi_aff *maff);
+ isl_ctx *isl_pw_aff_get_ctx(__isl_keep isl_pw_aff *pa);
+ isl_ctx *isl_pw_multi_aff_get_ctx(
+ __isl_keep isl_pw_multi_aff *pma);
+ isl_ctx *isl_multi_pw_aff_get_ctx(
+ __isl_keep isl_multi_pw_aff *mpa);
+ isl_ctx *isl_union_pw_multi_aff_get_ctx(
+ __isl_keep isl_union_pw_multi_aff *upma);
+
+ #include <isl/id_to_ast_expr.h>
+ isl_ctx *isl_id_to_ast_expr_get_ctx(
+ __isl_keep id_to_ast_expr *id2expr);
+
+ #include <isl/point.h>
+ isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt);
+
+ #include <isl/vec.h>
+ isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec);
+
+ #include <isl/mat.h>
+ isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat);
+
+ #include <isl/vertices.h>
+ isl_ctx *isl_vertices_get_ctx(
+ __isl_keep isl_vertices *vertices);
+ isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex);
+ isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell);
+
+ #include <isl/flow.h>
+ isl_ctx *isl_restriction_get_ctx(
+ __isl_keep isl_restriction *restr);
+
+ #include <isl/schedule.h>
+ isl_ctx *isl_schedule_constraints_get_ctx(
+ __isl_keep isl_schedule_constraints *sc);
+
+ #include <isl/band.h>
+ isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band);
+
+ #include <isl/ast_build.h>
+ isl_ctx *isl_ast_build_get_ctx(
+ __isl_keep isl_ast_build *build);
+
+ #include <isl/ast.h>
+ isl_ctx *isl_ast_expr_get_ctx(
+ __isl_keep isl_ast_expr *expr);
+ isl_ctx *isl_ast_node_get_ctx(
+ __isl_keep isl_ast_node *node);
+
+=head2 Values
+
+An C<isl_val> represents an integer value, a rational value
+or one of three special values, infinity, negative infinity and NaN.
+Some predefined values can be created using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_zero(isl_ctx *ctx);
+ __isl_give isl_val *isl_val_one(isl_ctx *ctx);
+ __isl_give isl_val *isl_val_negone(isl_ctx *ctx);
+ __isl_give isl_val *isl_val_nan(isl_ctx *ctx);
+ __isl_give isl_val *isl_val_infty(isl_ctx *ctx);
+ __isl_give isl_val *isl_val_neginfty(isl_ctx *ctx);
+
+Specific integer values can be created using the following functions.
+
+ #include <isl/val.h>
+ __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, size_t size, const void *chunks);
+
+The function C<isl_val_int_from_chunks> constructs an C<isl_val>
+from the C<n> I<digits>, each consisting of C<size> bytes, stored at C<chunks>.
+The least significant digit is assumed to be stored first.
+
+Value objects can be copied and freed using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_copy(__isl_keep isl_val *v);
+ __isl_null isl_val *isl_val_free(__isl_take isl_val *v);
+
+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);
+ 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, void *chunks);
+
+C<isl_val_n_abs_num_chunks> returns the number of I<digits>
+of C<size> bytes needed to store the absolute value of the
+numerator of C<v>.
+C<isl_val_get_abs_num_chunks> stores these digits at C<chunks>,
+which is assumed to have been preallocated by the caller.
+The least significant digit is stored first.
+Note that C<isl_val_get_num_si>, C<isl_val_get_den_si>,
+C<isl_val_get_d>, C<isl_val_n_abs_num_chunks>
+and C<isl_val_get_abs_num_chunks> can only be applied to rational values.
+
+An C<isl_val> can be modified using the following function.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_set_si(__isl_take isl_val *v,
+ long i);
+
+The following unary properties are defined on C<isl_val>s.
+
+ #include <isl/val.h>
+ int isl_val_sgn(__isl_keep isl_val *v);
+ int isl_val_is_zero(__isl_keep isl_val *v);
+ int isl_val_is_one(__isl_keep isl_val *v);
+ int isl_val_is_negone(__isl_keep isl_val *v);
+ int isl_val_is_nonneg(__isl_keep isl_val *v);
+ int isl_val_is_nonpos(__isl_keep isl_val *v);
+ int isl_val_is_pos(__isl_keep isl_val *v);
+ int isl_val_is_neg(__isl_keep isl_val *v);
+ int isl_val_is_int(__isl_keep isl_val *v);
+ int isl_val_is_rat(__isl_keep isl_val *v);
+ int isl_val_is_nan(__isl_keep isl_val *v);
+ int isl_val_is_infty(__isl_keep isl_val *v);
+ int isl_val_is_neginfty(__isl_keep isl_val *v);
+
+Note that the sign of NaN is undefined.
+
+The following binary properties are defined on pairs of C<isl_val>s.
+
+ #include <isl/val.h>
+ int isl_val_lt(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_le(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_gt(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_ge(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_eq(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_ne(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+ int isl_val_abs_eq(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+
+The function C<isl_val_abs_eq> checks whether its two arguments
+are equal in absolute value.
+
+For integer C<isl_val>s we additionally have the following binary property.
+
+ #include <isl/val.h>
+ int isl_val_is_divisible_by(__isl_keep isl_val *v1,
+ __isl_keep isl_val *v2);
+
+An C<isl_val> can also be compared to an integer using the following
+function. The result is undefined for NaN.
+
+ #include <isl/val.h>
+ int isl_val_cmp_si(__isl_keep isl_val *v, long i);
+
+The following unary operations are available on C<isl_val>s.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_abs(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_neg(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_floor(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_ceil(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_trunc(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_inv(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
+
+The following binary operations are available on C<isl_val>s.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_min(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_max(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_add(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1,
+ unsigned long v2);
+ __isl_give isl_val *isl_val_sub(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1,
+ unsigned long v2);
+ __isl_give isl_val *isl_val_mul(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1,
+ unsigned long v2);
+ __isl_give isl_val *isl_val_div(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+
+On integer values, we additionally have the following operations.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
+ __isl_give isl_val *isl_val_mod(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ __isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
+ __isl_take isl_val *v2, __isl_give isl_val **x,
+ __isl_give isl_val **y);
+
+The function C<isl_val_gcdext> returns the greatest common divisor g
+of C<v1> and C<v2> as well as two integers C<*x> and C<*y> such
+that C<*x> * C<v1> + C<*y> * C<v2> = g.
+
+=head3 GMP specific functions
+
+These functions are only available if C<isl> has been compiled with C<GMP>
+support.
+
+Specific integer and rational values can be created from C<GMP> values using
+the following functions.
+
+ #include <isl/val_gmp.h>
+ __isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx,
+ mpz_t z);
+ __isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx,
+ const mpz_t n, const mpz_t d);
+
+The numerator and denominator of a rational value can be extracted as
+C<GMP> values using the following functions.
+
+ #include <isl/val_gmp.h>
+ int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z);
+ int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z);
+
+=head2 Sets and Relations
+
+C<isl> uses six types of objects for representing sets and relations,
+C<isl_basic_set>, C<isl_basic_map>, C<isl_set>, C<isl_map>,
+C<isl_union_set> and C<isl_union_map>.
+C<isl_basic_set> and C<isl_basic_map> represent sets and relations that
+can be described as a conjunction of affine constraints, while
+C<isl_set> and C<isl_map> represent unions of
+C<isl_basic_set>s and C<isl_basic_map>s, respectively.
+However, all C<isl_basic_set>s or C<isl_basic_map>s in the union need
+to live in the same space. C<isl_union_set>s and C<isl_union_map>s
+represent unions of C<isl_set>s or C<isl_map>s in I<different> spaces,
+where spaces are considered different if they have a different number
+of dimensions and/or different names (see L<"Spaces">).
+The difference between sets and relations (maps) is that sets have
+one set of variables, while relations have two sets of variables,
+input variables and output variables.
+
+=head2 Error Handling
+
+C<isl> supports different ways to react in case a runtime error is triggered.
+Runtime errors arise, e.g., if a function such as C<isl_map_intersect> is called
+with two maps that have incompatible spaces. There are three possible ways
+to react on error: to warn, to continue or to abort.
+
+The default behavior is to warn. In this mode, C<isl> prints a warning, stores
+the last error in the corresponding C<isl_ctx> and the function in which the
+error was triggered returns C<NULL>. An error does not corrupt internal state,
+such that isl can continue to be used. C<isl> also provides functions to
+read the last error and to reset the memory that stores the last error. The
+last error is only stored for information purposes. Its presence does not
+change the behavior of C<isl>. Hence, resetting an error is not required to
+continue to use isl, but only to observe new errors.
+
+ #include <isl/ctx.h>
+ enum isl_error isl_ctx_last_error(isl_ctx *ctx);
+ void isl_ctx_reset_error(isl_ctx *ctx);
+
+Another option is to continue on error. This is similar to warn on error mode,
+except that C<isl> does not print any warning. This allows a program to
+implement its own error reporting.
+
+The last option is to directly abort the execution of the program from within
+the isl library. This makes it obviously impossible to recover from an error,
+but it allows to directly spot the error location. By aborting on error,
+debuggers break at the location the error occurred and can provide a stack
+trace. Other tools that automatically provide stack traces on abort or that do
+not want to continue execution after an error was triggered may also prefer to
+abort on error.
+
+The on error behavior of isl can be specified by calling
+C<isl_options_set_on_error> or by setting the command line option
+C<--isl-on-error>. Valid arguments for the function call are
+C<ISL_ON_ERROR_WARN>, C<ISL_ON_ERROR_CONTINUE> and C<ISL_ON_ERROR_ABORT>. The
+choices for the command line option are C<warn>, C<continue> and C<abort>.
+It is also possible to query the current error mode.
+
+ #include <isl/options.h>
+ int isl_options_set_on_error(isl_ctx *ctx, int val);
+ int isl_options_get_on_error(isl_ctx *ctx);
+
+=head2 Identifiers
+
+Identifiers are used to identify both individual dimensions
+and tuples of dimensions. They consist of an optional name and an optional
+user pointer. The name and the user pointer cannot both be C<NULL>, however.
+Identifiers with the same name but different pointer values
+are considered to be distinct.
+Similarly, identifiers with different names but the same pointer value
+are also considered to be distinct.
+Equal identifiers are represented using the same object.
+Pairs of identifiers can therefore be tested for equality using the
+C<==> operator.
+Identifiers can be constructed, copied, freed, inspected and printed
+using the following functions.
+
+ #include <isl/id.h>
+ __isl_give isl_id *isl_id_alloc(isl_ctx *ctx,
+ __isl_keep const char *name, void *user);
+ __isl_give isl_id *isl_id_set_free_user(
+ __isl_take isl_id *id,
+ __isl_give void (*free_user)(void *user));
+ __isl_give isl_id *isl_id_copy(isl_id *id);
+ __isl_null isl_id *isl_id_free(__isl_take isl_id *id);
+
+ void *isl_id_get_user(__isl_keep isl_id *id);
+ __isl_keep const char *isl_id_get_name(__isl_keep isl_id *id);
+
+ __isl_give isl_printer *isl_printer_print_id(
+ __isl_take isl_printer *p, __isl_keep isl_id *id);
+
+The callback set by C<isl_id_set_free_user> is called on the user
+pointer when the last reference to the C<isl_id> is freed.
+Note that C<isl_id_get_name> returns a pointer to some internal
+data structure, so the result can only be used while the
+corresponding C<isl_id> is alive.
+
+=head2 Spaces
+
+Whenever a new set, relation or similar object is created from scratch,
+the space in which it lives needs to be specified using an C<isl_space>.
+Each space involves zero or more parameters and zero, one or two
+tuples of set or input/output dimensions. The parameters and dimensions
+are identified by an C<isl_dim_type> and a position.
+The type C<isl_dim_param> refers to parameters,
+the type C<isl_dim_set> refers to set dimensions (for spaces
+with a single tuple of dimensions) and the types C<isl_dim_in>
+and C<isl_dim_out> refer to input and output dimensions
+(for spaces with two tuples of dimensions).
+Local spaces (see L</"Local Spaces">) also contain dimensions
+of type C<isl_dim_div>.
+Note that parameters are only identified by their position within
+a given object. Across different objects, parameters are (usually)
+identified by their names or identifiers. Only unnamed parameters
+are identified by their positions across objects. The use of unnamed
+parameters is discouraged.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned n_in, unsigned n_out);
+ __isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx,
+ unsigned nparam);
+ __isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned dim);
+ __isl_give isl_space *isl_space_copy(__isl_keep isl_space *space);
+ __isl_null isl_space *isl_space_free(__isl_take isl_space *space);
+
+The space used for creating a parameter domain
+needs to be created using C<isl_space_params_alloc>.
+For other sets, the space
+needs to be created using C<isl_space_set_alloc>, while
+for a relation, the space
+needs to be created using C<isl_space_alloc>.
+
+To check whether a given space is that of a set or a map
+or whether it is a parameter space, use these functions:
+
+ #include <isl/space.h>
+ int isl_space_is_params(__isl_keep isl_space *space);
+ int isl_space_is_set(__isl_keep isl_space *space);
+ int isl_space_is_map(__isl_keep isl_space *space);
+
+Spaces can be compared using the following functions:
+
+ #include <isl/space.h>
+ int isl_space_is_equal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+ int isl_space_is_domain(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+ int isl_space_is_range(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+ int isl_space_tuple_is_equal(
+ __isl_keep isl_space *space1,
+ enum isl_dim_type type1,
+ __isl_keep isl_space *space2,
+ enum isl_dim_type type2);
+
+C<isl_space_is_domain> checks whether the first argument is equal
+to the domain of the second argument. This requires in particular that
+the first argument is a set space and that the second argument
+is a map space. C<isl_space_tuple_is_equal> checks whether the given
+tuples (C<isl_dim_in>, C<isl_dim_out> or C<isl_dim_set>) of the given
+spaces are the same. That is, it checks if they have the same
+identifier (if any), the same dimension and the same internal structure
+(if any).
+
+It is often useful to create objects that live in the
+same space as some other object. This can be accomplished
+by creating the new objects
+(see L</"Creating New Sets and Relations"> or
+L</"Functions">) based on the space
+of the original object.
+
+ #include <isl/set.h>
+ __isl_give isl_space *isl_basic_set_get_space(
+ __isl_keep isl_basic_set *bset);
+ __isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set);
+
+ #include <isl/union_set.h>
+ __isl_give isl_space *isl_union_set_get_space(
+ __isl_keep isl_union_set *uset);
+
+ #include <isl/map.h>
+ __isl_give isl_space *isl_basic_map_get_space(
+ __isl_keep isl_basic_map *bmap);
+ __isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_space *isl_union_map_get_space(
+ __isl_keep isl_union_map *umap);
+
+ #include <isl/constraint.h>
+ __isl_give isl_space *isl_constraint_get_space(
+ __isl_keep isl_constraint *constraint);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_space *isl_qpolynomial_get_domain_space(
+ __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_space(
+ __isl_keep isl_qpolynomial_fold *fold);
+ __isl_give isl_space *isl_pw_qpolynomial_get_domain_space(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+ __isl_give isl_space *isl_pw_qpolynomial_get_space(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+ __isl_give isl_space *isl_pw_qpolynomial_fold_get_domain_space(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_space *isl_pw_qpolynomial_fold_get_space(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_space *isl_union_pw_qpolynomial_get_space(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+ __isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+ #include <isl/val.h>
+ __isl_give isl_space *isl_multi_val_get_space(
+ __isl_keep isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_space *isl_aff_get_domain_space(
+ __isl_keep isl_aff *aff);
+ __isl_give isl_space *isl_aff_get_space(
+ __isl_keep isl_aff *aff);
+ __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_give isl_space *isl_multi_aff_get_domain_space(
+ __isl_keep isl_multi_aff *maff);
+ __isl_give isl_space *isl_multi_aff_get_space(
+ __isl_keep isl_multi_aff *maff);
+ __isl_give isl_space *isl_pw_multi_aff_get_domain_space(
+ __isl_keep isl_pw_multi_aff *pma);
+ __isl_give isl_space *isl_pw_multi_aff_get_space(
+ __isl_keep isl_pw_multi_aff *pma);
+ __isl_give isl_space *isl_union_pw_multi_aff_get_space(
+ __isl_keep isl_union_pw_multi_aff *upma);
+ __isl_give isl_space *isl_multi_pw_aff_get_domain_space(
+ __isl_keep isl_multi_pw_aff *mpa);
+ __isl_give isl_space *isl_multi_pw_aff_get_space(
+ __isl_keep isl_multi_pw_aff *mpa);
+
+ #include <isl/point.h>
+ __isl_give isl_space *isl_point_get_space(
+ __isl_keep isl_point *pnt);
+
+The number of dimensions of a given type of space
+may be read off from a space or an object that lives
+in a space using the following functions.
+In case of C<isl_space_dim>, type may be
+C<isl_dim_param>, C<isl_dim_in> (only for relations),
+C<isl_dim_out> (only for relations), C<isl_dim_set>
+(only for sets) or C<isl_dim_all>.
+
+ #include <isl/space.h>
+ unsigned isl_space_dim(__isl_keep isl_space *space,
+ enum isl_dim_type type);
+
+ #include <isl/local_space.h>
+ int isl_local_space_dim(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type);
+
+ #include <isl/set.h>
+ unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type);
+ unsigned isl_set_dim(__isl_keep isl_set *set,
+ enum isl_dim_type type);
+
+ #include <isl/union_set.h>
+ unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+ enum isl_dim_type type);
+
+ #include <isl/map.h>
+ unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type);
+ unsigned isl_map_dim(__isl_keep isl_map *map,
+ enum isl_dim_type type);
+
+ #include <isl/union_map.h>
+ unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type);
+
+ #include <isl/val.h>
+ unsigned isl_multi_val_dim(__isl_keep isl_multi_val *mv,
+ enum isl_dim_type type);
+
+ #include <isl/aff.h>
+ int isl_aff_dim(__isl_keep isl_aff *aff,
+ enum isl_dim_type type);
+ unsigned isl_multi_aff_dim(__isl_keep isl_multi_aff *maff,
+ enum isl_dim_type type);
+ unsigned isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff,
+ enum isl_dim_type type);
+ unsigned isl_pw_multi_aff_dim(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+ unsigned isl_multi_pw_aff_dim(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type);
+ unsigned isl_union_pw_multi_aff_dim(
+ __isl_keep isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type);
+
+ #include <isl/polynomial.h>
+ unsigned isl_union_pw_qpolynomial_dim(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type);
+ unsigned isl_union_pw_qpolynomial_fold_dim(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type);
+
+Note that an C<isl_union_set>, an C<isl_union_map>,
+an C<isl_union_pw_multi_aff>,
+an C<isl_union_pw_qpolynomial> and
+an C<isl_union_pw_qpolynomial_fold>
+only have parameters.
+
+The identifiers or names of the individual dimensions of spaces
+may be set or read off using the following functions on spaces
+or objects that live in spaces.
+These functions are mostly useful to obtain the identifiers, positions
+or names of the parameters. Identifiers of individual dimensions are
+essentially only useful for printing. They are ignored by all other
+operations and may not be preserved across those operations.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_set_dim_id(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ int isl_space_has_dim_id(__isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_space_get_dim_id(
+ __isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_space *isl_space_set_dim_name(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, unsigned pos,
+ __isl_keep const char *name);
+ int isl_space_has_dim_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos);
+ __isl_keep const char *isl_space_get_dim_name(
+ __isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_set_dim_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ int isl_local_space_has_dim_id(
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_local_space_get_dim_id(
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_local_space *isl_local_space_set_dim_name(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, const char *s);
+ int isl_local_space_has_dim_name(
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+ const char *isl_local_space_get_dim_name(
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/constraint.h>
+ const char *isl_constraint_get_dim_name(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/set.h>
+ __isl_give isl_id *isl_basic_set_get_dim_id(
+ __isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_set *isl_set_set_dim_id(
+ __isl_take isl_set *set, enum isl_dim_type type,
+ unsigned pos, __isl_take isl_id *id);
+ int isl_set_has_dim_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_set_get_dim_id(
+ __isl_keep isl_set *set, enum isl_dim_type type,
+ unsigned pos);
+ const char *isl_basic_set_get_dim_name(
+ __isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos);
+ int isl_set_has_dim_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+ const char *isl_set_get_dim_name(
+ __isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_set_dim_id(
+ __isl_take isl_map *map, enum isl_dim_type type,
+ unsigned pos, __isl_take isl_id *id);
+ int isl_basic_map_has_dim_id(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+ int isl_map_has_dim_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_map_get_dim_id(
+ __isl_keep isl_map *map, enum isl_dim_type type,
+ unsigned pos);
+ __isl_give isl_id *isl_union_map_get_dim_id(
+ __isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned pos);
+ const char *isl_basic_map_get_dim_name(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+ int isl_map_has_dim_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+ const char *isl_map_get_dim_name(
+ __isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_set_dim_id(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ __isl_give isl_id *isl_multi_val_get_dim_id(
+ __isl_keep isl_multi_val *mv,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_multi_val *isl_multi_val_set_dim_name(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_set_dim_id(
+ __isl_take isl_aff *aff, enum isl_dim_type type,
+ unsigned pos, __isl_take isl_id *id);
+ __isl_give isl_multi_aff *isl_multi_aff_set_dim_id(
+ __isl_take isl_multi_aff *maff,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ __isl_give isl_pw_aff *isl_pw_aff_set_dim_id(
+ __isl_take isl_pw_aff *pma,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_set_dim_id(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
+ __isl_give isl_id *isl_multi_aff_get_dim_id(
+ __isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type, unsigned pos);
+ int isl_pw_aff_has_dim_id(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_pw_aff_get_dim_id(
+ __isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_pw_multi_aff_get_dim_id(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_multi_pw_aff_get_dim_id(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_aff *isl_aff_set_dim_name(
+ __isl_take isl_aff *aff, enum isl_dim_type type,
+ unsigned pos, const char *s);
+ __isl_give isl_multi_aff *isl_multi_aff_set_dim_name(
+ __isl_take isl_multi_aff *maff,
+ enum isl_dim_type type, unsigned pos, const char *s);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_set_dim_name(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned pos, const char *s);
+ const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned pos);
+ const char *isl_pw_aff_get_dim_name(
+ __isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+ const char *isl_pw_multi_aff_get_dim_name(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned pos);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_set_dim_name(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_set_dim_name(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+
+Note that C<isl_space_get_name> returns a pointer to some internal
+data structure, so the result can only be used while the
+corresponding C<isl_space> is alive.
+Also note that every function that operates on two sets or relations
+requires that both arguments have the same parameters. This also
+means that if one of the arguments has named parameters, then the
+other needs to have named parameters too and the names need to match.
+Pairs of C<isl_set>, C<isl_map>, C<isl_union_set> and/or C<isl_union_map>
+arguments may have different parameters (as long as they are named),
+in which case the result will have as parameters the union of the parameters of
+the arguments.
+
+Given the identifier or name of a dimension (typically a parameter),
+its position can be obtained from the following functions.
+
+ #include <isl/space.h>
+ int isl_space_find_dim_by_id(__isl_keep isl_space *space,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_space_find_dim_by_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/local_space.h>
+ int isl_local_space_find_dim_by_name(
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/val.h>
+ int isl_multi_val_find_dim_by_id(
+ __isl_keep isl_multi_val *mv,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_multi_val_find_dim_by_name(
+ __isl_keep isl_multi_val *mv,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/set.h>
+ int isl_set_find_dim_by_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_set_find_dim_by_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/map.h>
+ int isl_map_find_dim_by_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_basic_map_find_dim_by_name(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, const char *name);
+ int isl_map_find_dim_by_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, const char *name);
+ int isl_union_map_find_dim_by_name(
+ __isl_keep isl_union_map *umap,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/aff.h>
+ int isl_multi_aff_find_dim_by_id(
+ __isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_multi_pw_aff_find_dim_by_id(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, const char *name);
+ int isl_multi_aff_find_dim_by_name(
+ __isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type, const char *name);
+ int isl_pw_aff_find_dim_by_name(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, const char *name);
+ int isl_multi_pw_aff_find_dim_by_name(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, const char *name);
+ int isl_pw_multi_aff_find_dim_by_name(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type, const char *name);
+ int isl_union_pw_multi_aff_find_dim_by_name(
+ __isl_keep isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type, const char *name);
+
+ #include <isl/polynomial.h>
+ int isl_pw_qpolynomial_find_dim_by_name(
+ __isl_keep isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, const char *name);
+ int isl_pw_qpolynomial_fold_find_dim_by_name(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, const char *name);
+ int isl_union_pw_qpolynomial_find_dim_by_name(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type, const char *name);
+ int isl_union_pw_qpolynomial_fold_find_dim_by_name(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type, const char *name);
+
+The identifiers or names of entire spaces may be set or read off
+using the following functions.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_set_tuple_id(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_space *isl_space_reset_tuple_id(
+ __isl_take isl_space *space, enum isl_dim_type type);
+ int isl_space_has_tuple_id(__isl_keep isl_space *space,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_space_get_tuple_id(
+ __isl_keep isl_space *space, enum isl_dim_type type);
+ __isl_give isl_space *isl_space_set_tuple_name(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, const char *s);
+ int isl_space_has_tuple_name(__isl_keep isl_space *space,
+ enum isl_dim_type type);
+ const char *isl_space_get_tuple_name(__isl_keep isl_space *space,
+ enum isl_dim_type type);
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_set_tuple_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, __isl_take isl_id *id);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_set_tuple_id(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_id *id);
+ __isl_give isl_set *isl_set_set_tuple_id(
+ __isl_take isl_set *set, __isl_take isl_id *id);
+ __isl_give isl_set *isl_set_reset_tuple_id(
+ __isl_take isl_set *set);
+ int isl_set_has_tuple_id(__isl_keep isl_set *set);
+ __isl_give isl_id *isl_set_get_tuple_id(
+ __isl_keep isl_set *set);
+ __isl_give isl_basic_set *isl_basic_set_set_tuple_name(
+ __isl_take isl_basic_set *set, const char *s);
+ __isl_give isl_set *isl_set_set_tuple_name(
+ __isl_take isl_set *set, const char *s);
+ const char *isl_basic_set_get_tuple_name(
+ __isl_keep isl_basic_set *bset);
+ int isl_set_has_tuple_name(__isl_keep isl_set *set);
+ const char *isl_set_get_tuple_name(
+ __isl_keep isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_set_tuple_id(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_map *isl_map_set_tuple_id(
+ __isl_take isl_map *map, enum isl_dim_type type,
+ __isl_take isl_id *id);
+ __isl_give isl_map *isl_map_reset_tuple_id(
+ __isl_take isl_map *map, enum isl_dim_type type);
+ int isl_map_has_tuple_id(__isl_keep isl_map *map,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_map_get_tuple_id(
+ __isl_keep isl_map *map, enum isl_dim_type type);
+ __isl_give isl_map *isl_map_set_tuple_name(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, const char *s);
+ const char *isl_basic_map_get_tuple_name(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type);
+ __isl_give isl_basic_map *isl_basic_map_set_tuple_name(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, const char *s);
+ int isl_map_has_tuple_name(__isl_keep isl_map *map,
+ enum isl_dim_type type);
+ const char *isl_map_get_tuple_name(
+ __isl_keep isl_map *map,
+ enum isl_dim_type type);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_set_tuple_id(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_multi_val *isl_multi_val_reset_tuple_id(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type);
+ int isl_multi_val_has_tuple_id(__isl_keep isl_multi_val *mv,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_multi_val_get_tuple_id(
+ __isl_keep isl_multi_val *mv,
+ enum isl_dim_type type);
+ __isl_give isl_multi_val *isl_multi_val_set_tuple_name(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, const char *s);
+ const char *isl_multi_val_get_tuple_name(
+ __isl_keep isl_multi_val *mv,
+ enum isl_dim_type type);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_set_tuple_id(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_multi_aff *isl_multi_aff_set_tuple_id(
+ __isl_take isl_multi_aff *maff,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_pw_aff *isl_pw_aff_set_tuple_id(
+ __isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_tuple_id(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_multi_aff *isl_multi_aff_reset_tuple_id(
+ __isl_take isl_multi_aff *ma,
+ enum isl_dim_type type);
+ __isl_give isl_pw_aff *isl_pw_aff_reset_tuple_id(
+ __isl_take isl_pw_aff *pa,
+ enum isl_dim_type type);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_reset_tuple_id(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_reset_tuple_id(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+ int isl_multi_aff_has_tuple_id(__isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_multi_aff_get_tuple_id(
+ __isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type);
+ int isl_pw_aff_has_tuple_id(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_pw_aff_get_tuple_id(
+ __isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type);
+ int isl_pw_multi_aff_has_tuple_id(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_pw_multi_aff_get_tuple_id(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+ int isl_multi_pw_aff_has_tuple_id(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_multi_pw_aff_get_tuple_id(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type);
+ __isl_give isl_multi_aff *isl_multi_aff_set_tuple_name(
+ __isl_take isl_multi_aff *maff,
+ enum isl_dim_type type, const char *s);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_set_tuple_name(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, const char *s);
+ const char *isl_multi_aff_get_tuple_name(
+ __isl_keep isl_multi_aff *multi,
+ enum isl_dim_type type);
+ int isl_pw_multi_aff_has_tuple_name(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+ const char *isl_pw_multi_aff_get_tuple_name(
+ __isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+
+The C<type> argument needs to be one of C<isl_dim_in>, C<isl_dim_out>
+or C<isl_dim_set>. As with C<isl_space_get_name>,
+the C<isl_space_get_tuple_name> function returns a pointer to some internal
+data structure.
+Binary operations require the corresponding spaces of their arguments
+to have the same name.
+
+To keep the names of all parameters and tuples, but reset the user pointers
+of all the corresponding identifiers, use the following function.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_reset_user(
+ __isl_take isl_space *space);
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_set_reset_user(
+ __isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_reset_user(
+ __isl_take isl_map *map);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_reset_user(
+ __isl_take isl_union_set *uset);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_reset_user(
+ __isl_take isl_union_map *umap);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_reset_user(
+ __isl_take isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_reset_user(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_reset_user(
+ __isl_take isl_multi_pw_aff *mpa);
+
+Spaces can be nested. In particular, the domain of a set or
+the domain or range of a relation can be a nested relation.
+This process is also called I<wrapping>.
+The functions for detecting, constructing and deconstructing
+such nested spaces can be found in the wrapping properties
+of L</"Unary Properties">, the wrapping operations
+of L</"Unary Operations"> and the Cartesian product operations
+of L</"Basic Operations">.
+
+Spaces can be created from other spaces
+using the functions described in L</"Unary Operations">
+and L</"Binary Operations">.
+
+=head2 Local Spaces
+
+A local space is essentially a space with
+zero or more existentially quantified variables.
+The local space of various objects can be obtained
+using the following functions.
+
+ #include <isl/constraint.h>
+ __isl_give isl_local_space *isl_constraint_get_local_space(
+ __isl_keep isl_constraint *constraint);
+
+ #include <isl/set.h>
+ __isl_give isl_local_space *isl_basic_set_get_local_space(
+ __isl_keep isl_basic_set *bset);
+
+ #include <isl/map.h>
+ __isl_give isl_local_space *isl_basic_map_get_local_space(
+ __isl_keep isl_basic_map *bmap);
+
+ #include <isl/aff.h>
+ __isl_give isl_local_space *isl_aff_get_domain_local_space(
+ __isl_keep isl_aff *aff);
+ __isl_give isl_local_space *isl_aff_get_local_space(
+ __isl_keep isl_aff *aff);
+
+A new local space can be created from a space using
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_from_space(
+ __isl_take isl_space *space);
+
+They can be inspected, modified, copied and freed using the following functions.
+
+ #include <isl/local_space.h>
+ int isl_local_space_is_params(
+ __isl_keep isl_local_space *ls);
+ int isl_local_space_is_set(__isl_keep isl_local_space *ls);
+ __isl_give isl_space *isl_local_space_get_space(
+ __isl_keep isl_local_space *ls);
+ __isl_give isl_aff *isl_local_space_get_div(
+ __isl_keep isl_local_space *ls, int pos);
+ __isl_give isl_local_space *isl_local_space_copy(
+ __isl_keep isl_local_space *ls);
+ __isl_null isl_local_space *isl_local_space_free(
+ __isl_take isl_local_space *ls);
+
+Note that C<isl_local_space_get_div> can only be used on local spaces
+of sets.
+
+Two local spaces can be compared using
+
+ int isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
+ __isl_keep isl_local_space *ls2);
+
+Local spaces can be created from other local spaces
+using the functions described in L</"Unary Operations">
+and L</"Binary Operations">.
+
+=head2 Creating New Sets and Relations
+
+C<isl> has functions for creating some standard sets and relations.
+
+=over
+
+=item * Empty sets and relations
+
+ __isl_give isl_basic_set *isl_basic_set_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_basic_map *isl_basic_map_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_set *isl_set_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_map *isl_map_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_union_set *isl_union_set_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_union_map *isl_union_map_empty(
+ __isl_take isl_space *space);
+
+For C<isl_union_set>s and C<isl_union_map>s, the space
+is only used to specify the parameters.
+
+=item * Universe sets and relations
+
+ __isl_give isl_basic_set *isl_basic_set_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_basic_map *isl_basic_map_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_set *isl_set_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_map *isl_map_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_union_set *isl_union_set_universe(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_universe(
+ __isl_take isl_union_map *umap);
+
+The sets and relations constructed by the functions above
+contain all integer values, while those constructed by the
+functions below only contain non-negative values.
+
+ __isl_give isl_basic_set *isl_basic_set_nat_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_basic_map *isl_basic_map_nat_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_set *isl_set_nat_universe(
+ __isl_take isl_space *space);
+ __isl_give isl_map *isl_map_nat_universe(
+ __isl_take isl_space *space);
+
+=item * Identity relations
+
+ __isl_give isl_basic_map *isl_basic_map_identity(
+ __isl_take isl_space *space);
+ __isl_give isl_map *isl_map_identity(
+ __isl_take isl_space *space);
+
+The number of input and output dimensions in C<space> needs
+to be the same.
+
+=item * Lexicographic order
+
+ __isl_give isl_map *isl_map_lex_lt(
+ __isl_take isl_space *set_space);
+ __isl_give isl_map *isl_map_lex_le(
+ __isl_take isl_space *set_space);
+ __isl_give isl_map *isl_map_lex_gt(
+ __isl_take isl_space *set_space);
+ __isl_give isl_map *isl_map_lex_ge(
+ __isl_take isl_space *set_space);
+ __isl_give isl_map *isl_map_lex_lt_first(
+ __isl_take isl_space *space, unsigned n);
+ __isl_give isl_map *isl_map_lex_le_first(
+ __isl_take isl_space *space, unsigned n);
+ __isl_give isl_map *isl_map_lex_gt_first(
+ __isl_take isl_space *space, unsigned n);
+ __isl_give isl_map *isl_map_lex_ge_first(
+ __isl_take isl_space *space, unsigned n);
+
+The first four functions take a space for a B<set>
+and return relations that express that the elements in the domain
+are lexicographically less
+(C<isl_map_lex_lt>), less or equal (C<isl_map_lex_le>),
+greater (C<isl_map_lex_gt>) or greater or equal (C<isl_map_lex_ge>)
+than the elements in the range.
+The last four functions take a space for a map
+and return relations that express that the first C<n> dimensions
+in the domain are lexicographically less
+(C<isl_map_lex_lt_first>), less or equal (C<isl_map_lex_le_first>),
+greater (C<isl_map_lex_gt_first>) or greater or equal (C<isl_map_lex_ge_first>)
+than the first C<n> dimensions in the range.
+
+=back
+
+A basic set or relation can be converted to a set or relation
+using the following functions.
+
+ __isl_give isl_set *isl_set_from_basic_set(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_map *isl_map_from_basic_map(
+ __isl_take isl_basic_map *bmap);
+
+Sets and relations can be converted to union sets and relations
+using the following functions.
+
+ __isl_give isl_union_set *isl_union_set_from_basic_set(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_union_map *isl_union_map_from_basic_map(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_union_set *isl_union_set_from_set(
+ __isl_take isl_set *set);
+ __isl_give isl_union_map *isl_union_map_from_map(
+ __isl_take isl_map *map);
+
+The inverse conversions below can only be used if the input
+union set or relation is known to contain elements in exactly one
+space.
+
+ __isl_give isl_set *isl_set_from_union_set(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_map *isl_map_from_union_map(
+ __isl_take isl_union_map *umap);
+
+Sets and relations can be copied and freed again using the following
+functions.
+
+ __isl_give isl_basic_set *isl_basic_set_copy(
+ __isl_keep isl_basic_set *bset);
+ __isl_give isl_set *isl_set_copy(__isl_keep isl_set *set);
+ __isl_give isl_union_set *isl_union_set_copy(
+ __isl_keep isl_union_set *uset);
+ __isl_give isl_basic_map *isl_basic_map_copy(
+ __isl_keep isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_copy(__isl_keep isl_map *map);
+ __isl_give isl_union_map *isl_union_map_copy(
+ __isl_keep isl_union_map *umap);
+ __isl_null isl_basic_set *isl_basic_set_free(
+ __isl_take isl_basic_set *bset);
+ __isl_null isl_set *isl_set_free(__isl_take isl_set *set);
+ __isl_null isl_union_set *isl_union_set_free(
+ __isl_take isl_union_set *uset);
+ __isl_null isl_basic_map *isl_basic_map_free(
+ __isl_take isl_basic_map *bmap);
+ __isl_null isl_map *isl_map_free(__isl_take isl_map *map);
+ __isl_null isl_union_map *isl_union_map_free(
+ __isl_take isl_union_map *umap);
+
+Other sets and relations can be constructed by starting
+from a universe set or relation, adding equality and/or
+inequality constraints and then projecting out the
+existentially quantified variables, if any.
+Constraints can be constructed, manipulated and
+added to (or removed from) (basic) sets and relations
+using the following functions.
+
+ #include <isl/constraint.h>
+ __isl_give isl_constraint *isl_equality_alloc(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_constraint *isl_inequality_alloc(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_constraint *isl_constraint_set_constant_si(
+ __isl_take isl_constraint *constraint, int v);
+ __isl_give isl_constraint *isl_constraint_set_constant_val(
+ __isl_take isl_constraint *constraint,
+ __isl_take isl_val *v);
+ __isl_give isl_constraint *isl_constraint_set_coefficient_si(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, int v);
+ __isl_give isl_constraint *
+ isl_constraint_set_coefficient_val(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos,
+ __isl_take isl_val *v);
+ __isl_give isl_basic_map *isl_basic_map_add_constraint(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_constraint *constraint);
+ __isl_give isl_basic_set *isl_basic_set_add_constraint(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_constraint *constraint);
+ __isl_give isl_map *isl_map_add_constraint(
+ __isl_take isl_map *map,
+ __isl_take isl_constraint *constraint);
+ __isl_give isl_set *isl_set_add_constraint(
+ __isl_take isl_set *set,
+ __isl_take isl_constraint *constraint);
+ __isl_give isl_basic_set *isl_basic_set_drop_constraint(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_constraint *constraint);
+
+For example, to create a set containing the even integers
+between 10 and 42, you would use the following code.
+
+ isl_space *space;
+ isl_local_space *ls;
+ isl_constraint *c;
+ isl_basic_set *bset;
+
+ space = isl_space_set_alloc(ctx, 0, 2);
+ bset = isl_basic_set_universe(isl_space_copy(space));
+ ls = isl_local_space_from_space(space);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
+ c = isl_constraint_set_coefficient_si(c, isl_dim_set, 1, 2);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_inequality_alloc(isl_local_space_copy(ls));
+ c = isl_constraint_set_constant_si(c, -10);
+ c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, 1);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_inequality_alloc(ls);
+ c = isl_constraint_set_constant_si(c, 42);
+ c = isl_constraint_set_coefficient_si(c, isl_dim_set, 0, -1);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 1);
+
+Or, alternatively,
+
+ isl_basic_set *bset;
+ bset = isl_basic_set_read_from_str(ctx,
+ "{[i] : exists (a : i = 2a and i >= 10 and i <= 42)}");
+
+A basic set or relation can also be constructed from two matrices
+describing the equalities and the inequalities.
+
+ __isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
+ __isl_take isl_space *space,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq,
+ enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4);
+ __isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
+ __isl_take isl_space *space,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq,
+ enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+
+The C<isl_dim_type> arguments indicate the order in which
+different kinds of variables appear in the input matrices
+and should be a permutation of C<isl_dim_cst>, C<isl_dim_param>,
+C<isl_dim_set> and C<isl_dim_div> for sets and
+of C<isl_dim_cst>, C<isl_dim_param>,
+C<isl_dim_in>, C<isl_dim_out> and C<isl_dim_div> for relations.
+
+A (basic or union) set or relation can also be constructed from a
+(union) (piecewise) (multiple) affine expression
+or a list of affine expressions
+(See L</"Functions">).
+
+ __isl_give isl_basic_map *isl_basic_map_from_aff(
+ __isl_take isl_aff *aff);
+ __isl_give isl_map *isl_map_from_aff(
+ __isl_take isl_aff *aff);
+ __isl_give isl_set *isl_set_from_pw_aff(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_map *isl_map_from_pw_aff(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_basic_map *isl_basic_map_from_aff_list(
+ __isl_take isl_space *domain_space,
+ __isl_take isl_aff_list *list);
+ __isl_give isl_basic_map *isl_basic_map_from_multi_aff(
+ __isl_take isl_multi_aff *maff)
+ __isl_give isl_map *isl_map_from_multi_aff(
+ __isl_take isl_multi_aff *maff)
+ __isl_give isl_set *isl_set_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_map *isl_map_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+ __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_union_map *
+ isl_union_map_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+The C<domain_space> argument describes the domain of the resulting
+basic relation. It is required because the C<list> may consist
+of zero affine expressions.
+
+=head2 Inspecting Sets and Relations
+
+Usually, the user should not have to care about the actual constraints
+of the sets and maps, but should instead apply the abstract operations
+explained in the following sections.
+Occasionally, however, it may be required to inspect the individual
+coefficients of the constraints. This section explains how to do so.
+In these cases, it may also be useful to have C<isl> compute
+an explicit representation of the existentially quantified variables.
+
+ __isl_give isl_set *isl_set_compute_divs(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_compute_divs(
+ __isl_take isl_map *map);
+ __isl_give isl_union_set *isl_union_set_compute_divs(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_compute_divs(
+ __isl_take isl_union_map *umap);
+
+This explicit representation defines the existentially quantified
+variables as integer divisions of the other variables, possibly
+including earlier existentially quantified variables.
+An explicitly represented existentially quantified variable therefore
+has a unique value when the values of the other variables are known.
+If, furthermore, the same existentials, i.e., existentials
+with the same explicit representations, should appear in the
+same order in each of the disjuncts of a set or map, then the user should call
+either of the following functions.
+
+ __isl_give isl_set *isl_set_align_divs(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_align_divs(
+ __isl_take isl_map *map);
+
+Alternatively, the existentially quantified variables can be removed
+using the following functions, which compute an overapproximation.
+
+ __isl_give isl_basic_set *isl_basic_set_remove_divs(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_map *isl_basic_map_remove_divs(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_set_remove_divs(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_remove_divs(
+ __isl_take isl_map *map);
+
+It is also possible to only remove those divs that are defined
+in terms of a given range of dimensions or only those for which
+no explicit representation is known.
+
+ __isl_give isl_basic_set *
+ isl_basic_set_remove_divs_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_basic_map *
+ isl_basic_map_remove_divs_involving_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_set *isl_set_remove_divs_involving_dims(
+ __isl_take isl_set *set, enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_map *isl_map_remove_divs_involving_dims(
+ __isl_take isl_map *map, enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+ __isl_give isl_basic_set *
+ isl_basic_set_remove_unknown_divs(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_remove_unknown_divs(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_remove_unknown_divs(
+ __isl_take isl_map *map);
+
+To iterate over all the sets or maps in a union set or map, use
+
+ int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
+ int (*fn)(__isl_take isl_set *set, void *user),
+ void *user);
+ int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
+ int (*fn)(__isl_take isl_map *map, void *user),
+ void *user);
+
+The number of sets or maps in a union set or map can be obtained
+from
+
+ int isl_union_set_n_set(__isl_keep isl_union_set *uset);
+ int isl_union_map_n_map(__isl_keep isl_union_map *umap);
+
+To extract the set or map in a given space from a union, use
+
+ __isl_give isl_set *isl_union_set_extract_set(
+ __isl_keep isl_union_set *uset,
+ __isl_take isl_space *space);
+ __isl_give isl_map *isl_union_map_extract_map(
+ __isl_keep isl_union_map *umap,
+ __isl_take isl_space *space);
+
+To iterate over all the basic sets or maps in a set or map, use
+
+ int isl_set_foreach_basic_set(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_basic_set *bset, void *user),
+ void *user);
+ int isl_map_foreach_basic_map(__isl_keep isl_map *map,
+ int (*fn)(__isl_take isl_basic_map *bmap, void *user),
+ void *user);
+
+The callback function C<fn> should return 0 if successful and
+-1 if an error occurs. In the latter case, or if any other error
+occurs, the above functions will return -1.
+
+It should be noted that C<isl> does not guarantee that
+the basic sets or maps passed to C<fn> are disjoint.
+If this is required, then the user should call one of
+the following functions first.
+
+ __isl_give isl_set *isl_set_make_disjoint(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_make_disjoint(
+ __isl_take isl_map *map);
+
+The number of basic sets in a set can be obtained
+or the number of basic maps in a map can be obtained
+from
+
+ #include <isl/set.h>
+ int isl_set_n_basic_set(__isl_keep isl_set *set);
+
+ #include <isl/map.h>
+ int isl_map_n_basic_map(__isl_keep isl_map *map);
+
+To iterate over the constraints of a basic set or map, use
+
+ #include <isl/constraint.h>
+
+ int isl_basic_set_n_constraint(
+ __isl_keep isl_basic_set *bset);
+ int isl_basic_set_foreach_constraint(
+ __isl_keep isl_basic_set *bset,
+ int (*fn)(__isl_take isl_constraint *c, void *user),
+ void *user);
+ int isl_basic_map_n_constraint(
+ __isl_keep isl_basic_map *bmap);
+ int isl_basic_map_foreach_constraint(
+ __isl_keep isl_basic_map *bmap,
+ int (*fn)(__isl_take isl_constraint *c, void *user),
+ void *user);
+ __isl_null isl_constraint *isl_constraint_free(
+ __isl_take isl_constraint *c);
+
+Again, the callback function C<fn> should return 0 if successful and
+-1 if an error occurs. In the latter case, or if any other error
+occurs, the above functions will return -1.
+The constraint C<c> represents either an equality or an inequality.
+Use the following function to find out whether a constraint
+represents an equality. If not, it represents an inequality.
+
+ int isl_constraint_is_equality(
+ __isl_keep isl_constraint *constraint);
+
+It is also possible to obtain a list of constraints from a basic
+map or set
+
+ #include <isl/constraint.h>
+ __isl_give isl_constraint_list *
+ isl_basic_map_get_constraint_list(
+ __isl_keep isl_basic_map *bmap);
+ __isl_give isl_constraint_list *
+ isl_basic_set_get_constraint_list(
+ __isl_keep isl_basic_set *bset);
+
+These functions require that all existentially quantified variables
+have an explicit representation.
+The returned list can be manipulated using the functions in L<"Lists">.
+
+The coefficients of the constraints can be inspected using
+the following functions.
+
+ int isl_constraint_is_lower_bound(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+ int isl_constraint_is_upper_bound(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_val *isl_constraint_get_constant_val(
+ __isl_keep isl_constraint *constraint);
+ __isl_give isl_val *isl_constraint_get_coefficient_val(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, int pos);
+
+The explicit representations of the existentially quantified
+variables can be inspected using the following function.
+Note that the user is only allowed to use this function
+if the inspected set or map is the result of a call
+to C<isl_set_compute_divs> or C<isl_map_compute_divs>.
+The existentially quantified variable is equal to the floor
+of the returned affine expression. The affine expression
+itself can be inspected using the functions in
+L</"Functions">.
+
+ __isl_give isl_aff *isl_constraint_get_div(
+ __isl_keep isl_constraint *constraint, int pos);
+
+To obtain the constraints of a basic set or map in matrix
+form, use the following functions.
+
+ __isl_give isl_mat *isl_basic_set_equalities_matrix(
+ __isl_keep isl_basic_set *bset,
+ enum isl_dim_type c1, enum isl_dim_type c2,
+ enum isl_dim_type c3, enum isl_dim_type c4);
+ __isl_give isl_mat *isl_basic_set_inequalities_matrix(
+ __isl_keep isl_basic_set *bset,
+ enum isl_dim_type c1, enum isl_dim_type c2,
+ enum isl_dim_type c3, enum isl_dim_type c4);
+ __isl_give isl_mat *isl_basic_map_equalities_matrix(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+ __isl_give isl_mat *isl_basic_map_inequalities_matrix(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+
+The C<isl_dim_type> arguments dictate the order in which
+different kinds of variables appear in the resulting matrix.
+For set inputs, they should be a permutation of
+C<isl_dim_cst>, C<isl_dim_param>, C<isl_dim_set> and C<isl_dim_div>.
+For map inputs, they should be a permutation of
+C<isl_dim_cst>, C<isl_dim_param>,
+C<isl_dim_in>, C<isl_dim_out> and C<isl_dim_div>.
+
+=head2 Points
+
+Points are elements of a set. They can be used to construct
+simple sets (boxes) or they can be used to represent the
+individual elements of a set.
+The zero point (the origin) can be created using
+
+ __isl_give isl_point *isl_point_zero(__isl_take isl_space *space);
+
+The coordinates of a point can be inspected, set and changed
+using
+
+ __isl_give isl_val *isl_point_get_coordinate_val(
+ __isl_keep isl_point *pnt,
+ enum isl_dim_type type, int pos);
+ __isl_give isl_point *isl_point_set_coordinate_val(
+ __isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos,
+ __isl_take isl_val *v);
+
+ __isl_give isl_point *isl_point_add_ui(
+ __isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val);
+ __isl_give isl_point *isl_point_sub_ui(
+ __isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val);
+
+Points can be copied or freed using
+
+ __isl_give isl_point *isl_point_copy(
+ __isl_keep isl_point *pnt);
+ void isl_point_free(__isl_take isl_point *pnt);
+
+A singleton set can be created from a point using
+
+ __isl_give isl_basic_set *isl_basic_set_from_point(
+ __isl_take isl_point *pnt);
+ __isl_give isl_set *isl_set_from_point(
+ __isl_take isl_point *pnt);
+
+and a box can be created from two opposite extremal points using
+
+ __isl_give isl_basic_set *isl_basic_set_box_from_points(
+ __isl_take isl_point *pnt1,
+ __isl_take isl_point *pnt2);
+ __isl_give isl_set *isl_set_box_from_points(
+ __isl_take isl_point *pnt1,
+ __isl_take isl_point *pnt2);
+
+All elements of a B<bounded> (union) set can be enumerated using
+the following functions.
+
+ int isl_set_foreach_point(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_point *pnt, void *user),
+ void *user);
+ int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
+ int (*fn)(__isl_take isl_point *pnt, void *user),
+ void *user);
+
+The function C<fn> is called for each integer point in
+C<set> with as second argument the last argument of
+the C<isl_set_foreach_point> call. The function C<fn>
+should return C<0> on success and C<-1> on failure.
+In the latter case, C<isl_set_foreach_point> will stop
+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
+
+ __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);
+
+If C<set> does not contain any (integer) points, then the
+resulting point will be ``void'', a property that can be
+tested using
+
+ int isl_point_is_void(__isl_keep isl_point *pnt);
+
+=head2 Functions
+
+Besides sets and relation, C<isl> also supports various types of functions.
+Each of these types is derived from the value type (see L</"Values">)
+or from one of two primitive function types
+through the application of zero or more type constructors.
+We first describe the primitive type and then we describe
+the types derived from these primitive types.
+
+=head3 Primitive Functions
+
+C<isl> support two primitive function types, quasi-affine
+expressions and quasipolynomials.
+A quasi-affine expression is defined either over a parameter
+space or over a set and is composed of integer constants,
+parameters and set variables, addition, subtraction and
+integer division by an integer constant.
+For example, the quasi-affine expression
+
+ [n] -> { [x] -> [2*floor((4 n + x)/9] }
+
+maps C<x> to C<2*floor((4 n + x)/9>.
+A quasipolynomial is a polynomial expression in quasi-affine
+expression. That is, it additionally allows for multiplication.
+Note, though, that it is not allowed to construct an integer
+division of an expression involving multiplications.
+Here is an example of a quasipolynomial that is not
+quasi-affine expression
+
+ [n] -> { [x] -> (n*floor((4 n + x)/9) }
+
+Note that the external representations of quasi-affine expressions
+and quasipolynomials are different. Quasi-affine expressions
+use a notation with square brackets just like binary relations,
+while quasipolynomials do not. This might change at some point.
+
+If a primitive function is defined over a parameter space,
+then the space of the function itself is that of a set.
+If it is defined over a set, then the space of the function
+is that of a relation. In both cases, the set space (or
+the output space) is single-dimensional, anonymous and unstructured.
+To create functions with multiple dimensions or with other kinds
+of set or output spaces, use multiple expressions
+(see L</"Multiple Expressions">).
+
+=over
+
+=item * Quasi-affine Expressions
+
+Besides the expressions described above, a quasi-affine
+expression can also be set to NaN. Such expressions
+typically represent a failure to represent a result
+as a quasi-affine expression.
+
+The zero quasi affine expression or the quasi affine expression
+that is equal to a given value or
+a specified dimension on a given domain can be created using
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_zero_on_domain(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_aff *isl_aff_val_on_domain(
+ __isl_take isl_local_space *ls,
+ __isl_take isl_val *val);
+ __isl_give isl_aff *isl_aff_var_on_domain(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_aff *isl_aff_nan_on_domain(
+ __isl_take isl_local_space *ls);
+
+Quasi affine expressions can be copied and freed using
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_copy(
+ __isl_keep isl_aff *aff);
+ __isl_null isl_aff *isl_aff_free(
+ __isl_take isl_aff *aff);
+
+A (rational) bound on a dimension can be extracted from an C<isl_constraint>
+using the following function. The constraint is required to have
+a non-zero coefficient for the specified dimension.
+
+ #include <isl/constraint.h>
+ __isl_give isl_aff *isl_constraint_get_bound(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, int pos);
+
+The entire affine expression of the constraint can also be extracted
+using the following function.
+
+ #include <isl/constraint.h>
+ __isl_give isl_aff *isl_constraint_get_aff(
+ __isl_keep isl_constraint *constraint);
+
+Conversely, an equality constraint equating
+the affine expression to zero or an inequality constraint enforcing
+the affine expression to be non-negative, can be constructed using
+
+ __isl_give isl_constraint *isl_equality_from_aff(
+ __isl_take isl_aff *aff);
+ __isl_give isl_constraint *isl_inequality_from_aff(
+ __isl_take isl_aff *aff);
+
+The coefficients and the integer divisions of an affine expression
+can be inspected using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_val *isl_aff_get_constant_val(
+ __isl_keep isl_aff *aff);
+ __isl_give isl_val *isl_aff_get_coefficient_val(
+ __isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos);
+ int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos);
+ __isl_give isl_val *isl_aff_get_denominator_val(
+ __isl_keep isl_aff *aff);
+ __isl_give isl_aff *isl_aff_get_div(
+ __isl_keep isl_aff *aff, int pos);
+
+They can be modified using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_set_constant_si(
+ __isl_take isl_aff *aff, int v);
+ __isl_give isl_aff *isl_aff_set_constant_val(
+ __isl_take isl_aff *aff, __isl_take isl_val *v);
+ __isl_give isl_aff *isl_aff_set_coefficient_si(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v);
+ __isl_give isl_aff *isl_aff_set_coefficient_val(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos,
+ __isl_take isl_val *v);
+
+ __isl_give isl_aff *isl_aff_add_constant_si(
+ __isl_take isl_aff *aff, int v);
+ __isl_give isl_aff *isl_aff_add_constant_val(
+ __isl_take isl_aff *aff, __isl_take isl_val *v);
+ __isl_give isl_aff *isl_aff_add_constant_num_si(
+ __isl_take isl_aff *aff, int v);
+ __isl_give isl_aff *isl_aff_add_coefficient_si(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v);
+ __isl_give isl_aff *isl_aff_add_coefficient_val(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos,
+ __isl_take isl_val *v);
+
+Note that C<isl_aff_set_constant_si> and C<isl_aff_set_coefficient_si>
+set the I<numerator> of the constant or coefficient, while
+C<isl_aff_set_constant_val> and C<isl_aff_set_coefficient_val> set
+the constant or coefficient as a whole.
+The C<add_constant> and C<add_coefficient> functions add an integer
+or rational value to
+the possibly rational constant or coefficient.
+The C<add_constant_num> functions add an integer value to
+the numerator.
+
+=item * Quasipolynomials
+
+Some simple quasipolynomials can be created using the following functions.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(
+ __isl_take isl_space *domain);
+ __isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(
+ __isl_take isl_space *domain);
+ __isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(
+ __isl_take isl_space *domain);
+ __isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(
+ __isl_take isl_space *domain);
+ __isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(
+ __isl_take isl_space *domain);
+ __isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
+ __isl_take isl_space *domain,
+ __isl_take isl_val *val);
+ __isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(
+ __isl_take isl_space *domain,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_qpolynomial *isl_qpolynomial_from_aff(
+ __isl_take isl_aff *aff);
+
+Recall that the space in which a quasipolynomial lives is a map space
+with a one-dimensional range. The C<domain> argument in some of
+the functions above corresponds to the domain of this map space.
+
+Quasipolynomials can be copied and freed again using the following
+functions.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_copy(
+ __isl_keep isl_qpolynomial *qp);
+ __isl_null isl_qpolynomial *isl_qpolynomial_free(
+ __isl_take isl_qpolynomial *qp);
+
+The constant term of a quasipolynomial can be extracted using
+
+ __isl_give isl_val *isl_qpolynomial_get_constant_val(
+ __isl_keep isl_qpolynomial *qp);
+
+To iterate over all terms in a quasipolynomial,
+use
+
+ int isl_qpolynomial_foreach_term(
+ __isl_keep isl_qpolynomial *qp,
+ int (*fn)(__isl_take isl_term *term,
+ void *user), void *user);
+
+The terms themselves can be inspected and freed using
+these functions
+
+ unsigned isl_term_dim(__isl_keep isl_term *term,
+ enum isl_dim_type type);
+ __isl_give isl_val *isl_term_get_coefficient_val(
+ __isl_keep isl_term *term);
+ int isl_term_get_exp(__isl_keep isl_term *term,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_aff *isl_term_get_div(
+ __isl_keep isl_term *term, unsigned pos);
+ void isl_term_free(__isl_take isl_term *term);
+
+Each term is a product of parameters, set variables and
+integer divisions. The function C<isl_term_get_exp>
+returns the exponent of a given dimensions in the given term.
+
+=back
+
+=head3 Reductions
+
+A reduction represents a maximum or a minimum of its
+base expressions.
+The only reduction type defined by C<isl> is
+C<isl_qpolynomial_fold>.
+
+There are currently no functions to directly create such
+objects, but they do appear in the piecewise quasipolynomial
+reductions returned by the C<isl_pw_qpolynomial_bound> function.
+See
+L</"Bounds on Piecewise Quasipolynomials and Piecewise Quasipolynomial Reductions">.
+
+Reductions can be copied and freed using
+the following functions.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial_fold *
+ isl_qpolynomial_fold_copy(
+ __isl_keep isl_qpolynomial_fold *fold);
+ void isl_qpolynomial_fold_free(
+ __isl_take isl_qpolynomial_fold *fold);
+
+To iterate over all quasipolynomials in a reduction, use
+
+ int isl_qpolynomial_fold_foreach_qpolynomial(
+ __isl_keep isl_qpolynomial_fold *fold,
+ int (*fn)(__isl_take isl_qpolynomial *qp,
+ void *user), void *user);
+
+=head3 Multiple Expressions
+
+A multiple expression represents a sequence of zero or
+more base expressions, all defined on the same domain space.
+The domain space of the multiple expression is the same
+as that of the base expressions, but the range space
+can be any space. In case the base expressions have
+a set space, the corresponding multiple expression
+also has a set space.
+Objects of the value type do not have an associated space.
+The space of a multiple value is therefore always a set space.
+
+The multiple expression types defined by C<isl>
+are C<isl_multi_val>, C<isl_multi_aff> and C<isl_multi_pw_aff>.
+
+A multiple expression with the value zero for
+each output (or set) dimension can be created
+using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_zero(
+ __isl_take isl_space *space);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_zero(
+ __isl_take isl_space *space);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_zero(
+ __isl_take isl_space *space);
+
+An identity function can be created using the following
+functions. The space needs to be that of a relation
+with the same number of input and output dimensions.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_identity(
+ __isl_take isl_space *space);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
+ __isl_take isl_space *space);
+
+A function that performs a projection on a universe
+relation or set can be created using the following functions.
+See also the corresponding
+projection operations in L</"Unary Operations">.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_domain_map(
+ __isl_take isl_space *space);
+ __isl_give isl_multi_aff *isl_multi_aff_range_map(
+ __isl_take isl_space *space);
+ __isl_give isl_multi_aff *isl_multi_aff_project_out_map(
+ __isl_take isl_space *space,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+A multiple expression can be created from a single
+base expression using the following functions.
+The space of the created multiple expression is the same
+as that of the base expression.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_from_aff(
+ __isl_take isl_aff *aff);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff(
+ __isl_take isl_pw_aff *pa);
+
+A multiple expression can be created from a list
+of base expression in a specified space.
+The domain of this space needs to be the same
+as the domains of the base expressions in the list.
+If the base expressions have a set space (or no associated space),
+then this space also needs to be a set space.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_from_val_list(
+ __isl_take isl_space *space,
+ __isl_take isl_val_list *list);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_from_aff_list(
+ __isl_take isl_space *space,
+ __isl_take isl_aff_list *list);
+
+As a convenience, a multiple piecewise expression can
+also be created from a multiple expression.
+Each piecewise expression in the result has a single
+universe cell.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+
+A multiple quasi-affine expression can be created from
+a multiple value with a given domain space using the following
+function.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *
+ isl_multi_aff_multi_val_on_space(
+ __isl_take isl_space *space,
+ __isl_take isl_multi_val *mv);
+
+Multiple expressions can be copied and freed using
+the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_copy(
+ __isl_keep isl_multi_val *mv);
+ __isl_null isl_multi_val *isl_multi_val_free(
+ __isl_take isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_copy(
+ __isl_keep isl_multi_aff *maff);
+ __isl_null isl_multi_aff *isl_multi_aff_free(
+ __isl_take isl_multi_aff *maff);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_copy(
+ __isl_keep isl_multi_pw_aff *mpa);
+ __isl_null isl_multi_pw_aff *isl_multi_pw_aff_free(
+ __isl_take isl_multi_pw_aff *mpa);
+
+The base expression at a given position of a multiple
+expression can be extracted using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_multi_val_get_val(
+ __isl_keep isl_multi_val *mv, int pos);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_multi_aff_get_aff(
+ __isl_keep isl_multi_aff *multi, int pos);
+ __isl_give isl_pw_aff *isl_multi_pw_aff_get_pw_aff(
+ __isl_keep isl_multi_pw_aff *mpa, int pos);
+
+It can be replaced using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_set_val(
+ __isl_take isl_multi_val *mv, int pos,
+ __isl_take isl_val *val);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_set_aff(
+ __isl_take isl_multi_aff *multi, int pos,
+ __isl_take isl_aff *aff);
+
+=head3 Piecewise Expressions
+
+A piecewise expression is an expression that is described
+using zero or more base expression defined over the same
+number of cells in the domain space of the base expressions.
+All base expressions are defined over the same
+domain space and the cells are disjoint.
+The space of a piecewise expression is the same as
+that of the base expressions.
+If the union of the cells is a strict subset of the domain
+space, then the value of the piecewise expression outside
+this union is different for types derived from quasi-affine
+expressions and those derived from quasipolynomials.
+Piecewise expressions derived from quasi-affine expressions
+are considered to be undefined outside the union of their cells.
+Piecewise expressions derived from quasipolynomials
+are considered to be zero outside the union of their cells.
+
+Piecewise quasipolynomials are mainly used by the C<barvinok>
+library for representing the number of elements in a parametric set or map.
+For example, the piecewise quasipolynomial
+
+ [n] -> { [x] -> ((1 + n) - x) : x <= n and x >= 0 }
+
+represents the number of points in the map
+
+ [n] -> { [x] -> [y] : x,y >= 0 and 0 <= x + y <= n }
+
+The piecewise expression types defined by C<isl>
+are C<isl_pw_aff>, C<isl_pw_multi_aff>,
+C<isl_pw_qpolynomial> and C<isl_pw_qpolynomial_fold>.
+
+A piecewise expression with no cells can be created using
+the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_empty(
+ __isl_take isl_space *space);
+
+A piecewise expression with a single universe cell can be
+created using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_from_aff(
+ __isl_take isl_aff *aff);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_from_qpolynomial(
+ __isl_take isl_qpolynomial *qp);
+
+A piecewise expression with a single specified cell can be
+created using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_alloc(
+ __isl_take isl_set *set, __isl_take isl_aff *aff);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_alloc(
+ __isl_take isl_set *set,
+ __isl_take isl_multi_aff *maff);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc(
+ __isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp);
+
+The following convenience functions first create a base expression and
+then create a piecewise expression over a universe domain.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_pw_aff *isl_pw_aff_var_on_domain(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(
+ __isl_take isl_space *space);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
+ __isl_take isl_space *space);
+ __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);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero(
+ __isl_take isl_space *space);
+
+The following convenience functions first create a base expression and
+then create a piecewise expression over a given domain.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_val_on_domain(
+ __isl_take isl_set *domain,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_set *domain,
+ __isl_take isl_multi_val *mv);
+
+As a convenience, a piecewise multiple expression can
+also be created from a piecewise expression.
+Each multiple expression in the result is derived
+from the corresponding base expression.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
+ __isl_take isl_pw_aff *pa);
+
+Similarly, a piecewise quasipolynomial can be
+created from a piecewise quasi-affine expression using
+the following function.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_from_pw_aff(
+ __isl_take isl_pw_aff *pwaff);
+
+Piecewise expressions can be copied and freed using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_copy(
+ __isl_keep isl_pw_aff *pwaff);
+ __isl_null isl_pw_aff *isl_pw_aff_free(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_copy(
+ __isl_keep isl_pw_multi_aff *pma);
+ __isl_null isl_pw_multi_aff *isl_pw_multi_aff_free(
+ __isl_take isl_pw_multi_aff *pma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+ __isl_null isl_pw_qpolynomial *isl_pw_qpolynomial_free(
+ __isl_take isl_pw_qpolynomial *pwqp);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_copy(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+ __isl_null isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_free(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+
+To iterate over the different cells of a piecewise expression,
+use the following functions.
+
+ #include <isl/aff.h>
+ int isl_pw_aff_is_empty(__isl_keep isl_pw_aff *pwaff);
+ int isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
+ int isl_pw_aff_foreach_piece(__isl_keep isl_pw_aff *pwaff,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_aff *aff,
+ void *user), void *user);
+ int isl_pw_multi_aff_foreach_piece(
+ __isl_keep isl_pw_multi_aff *pma,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_multi_aff *maff,
+ void *user), void *user);
+
+ #include <isl/polynomial.h>
+ int isl_pw_qpolynomial_foreach_piece(
+ __isl_keep isl_pw_qpolynomial *pwqp,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp,
+ void *user), void *user);
+ int isl_pw_qpolynomial_foreach_lifted_piece(
+ __isl_keep isl_pw_qpolynomial *pwqp,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp,
+ void *user), void *user);
+ int isl_pw_qpolynomial_fold_foreach_piece(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold,
+ void *user), void *user);
+ int isl_pw_qpolynomial_fold_foreach_lifted_piece(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ int (*fn)(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold,
+ void *user), void *user);
+
+As usual, the function C<fn> should return C<0> on success
+and C<-1> on failure. The difference between
+C<isl_pw_qpolynomial_foreach_piece> and
+C<isl_pw_qpolynomial_foreach_lifted_piece> is that
+C<isl_pw_qpolynomial_foreach_lifted_piece> will first
+compute unique representations for all existentially quantified
+variables and then turn these existentially quantified variables
+into extra set variables, adapting the associated quasipolynomial
+accordingly. This means that the C<set> passed to C<fn>
+will not have any existentially quantified variables, but that
+the dimensions of the sets may be different for different
+invocations of C<fn>.
+Similarly for C<isl_pw_qpolynomial_fold_foreach_piece>
+and C<isl_pw_qpolynomial_fold_foreach_lifted_piece>.
+
+A piecewise expression consisting of the expressions at a given
+position of a piecewise multiple expression can be extracted
+using the following function.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
+ __isl_keep isl_pw_multi_aff *pma, int pos);
+
+These expressions can be replaced using the following function.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
+ __isl_take isl_pw_multi_aff *pma, unsigned pos,
+ __isl_take isl_pw_aff *pa);
+
+Note that there is a difference between C<isl_multi_pw_aff> and
+C<isl_pw_multi_aff> objects. The first is a sequence of piecewise
+affine expressions, while the second is a piecewise sequence
+of affine expressions. In particular, each of the piecewise
+affine expressions in an C<isl_multi_pw_aff> may have a different
+domain, while all multiple expressions associated to a cell
+in an C<isl_pw_multi_aff> have the same domain.
+It is possible to convert between the two, but when converting
+an C<isl_multi_pw_aff> to an C<isl_pw_multi_aff>, the domain
+of the result is the intersection of the domains of the input.
+The reverse conversion is exact.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+
+=head3 Union Expressions
+
+A union expression collects base expressions defined
+over different domains. The space of a union expression
+is that of the shared parameter space.
+
+The union expression types defined by C<isl>
+are C<isl_union_pw_multi_aff>, C<isl_union_pw_qpolynomial> and
+C<isl_union_pw_qpolynomial_fold>.
+
+An empty union expression can be created using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_empty(
+ __isl_take isl_space *space);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_zero(
+ __isl_take isl_space *space);
+
+A union expression containing a single base expression
+can be created using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_from_pw_qpolynomial(
+ __isl_take isl_pw_qpolynomial *pwqp);
+
+The following function creates a base expression on each
+of the sets in the union set and collects the results.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_multi_val *mv);
+
+A base expression can be added to a union expression using
+the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_add_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_pw_multi_aff *pma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_add_pw_qpolynomial(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_pw_qpolynomial *pwqp);
+
+Union expressions can be copied and freed using
+the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_copy(
+ __isl_keep isl_union_pw_multi_aff *upma);
+ __isl_null isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_free(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_copy(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+ __isl_null isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_free(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_copy(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+ __isl_null isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_free(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+
+To iterate over the base expressions in a union expression,
+use the following functions.
+
+ #include <isl/aff.h>
+ int isl_union_pw_multi_aff_foreach_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma,
+ int (*fn)(__isl_take isl_pw_multi_aff *pma,
+ void *user), void *user);
+
+ #include <isl/polynomial.h>
+ int isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ int (*fn)(__isl_take isl_pw_qpolynomial *pwqp,
+ void *user), void *user);
+ int isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf,
+ int (*fn)(__isl_take isl_pw_qpolynomial_fold *pwf,
+ void *user), void *user);
+
+To extract the base expression in a given space from a union, use
+the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_multi_aff *
+ isl_union_pw_multi_aff_extract_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma,
+ __isl_take isl_space *space);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_union_pw_qpolynomial_extract_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_space *space);
+
+=head2 Input and Output
+
+For set and relation,
+C<isl> supports its own input/output format, which is similar
+to the C<Omega> format, but also supports the C<PolyLib> format
+in some cases.
+For other object types, typically only an C<isl> format is supported.
+
+=head3 C<isl> format
+
+The C<isl> format is similar to that of C<Omega>, but has a different
+syntax for describing the parameters and allows for the definition
+of an existentially quantified variable as the integer division
+of an affine expression.
+For example, the set of integers C<i> between C<0> and C<n>
+such that C<i % 10 <= 6> can be described as
+
+ [n] -> { [i] : exists (a = [i/10] : 0 <= i and i <= n and
+ i - 10 a <= 6) }
+
+A set or relation can have several disjuncts, separated
+by the keyword C<or>. Each disjunct is either a conjunction
+of constraints or a projection (C<exists>) of a conjunction
+of constraints. The constraints are separated by the keyword
+C<and>.
+
+=head3 C<PolyLib> format
+
+If the represented set is a union, then the first line
+contains a single number representing the number of disjuncts.
+Otherwise, a line containing the number C<1> is optional.
+
+Each disjunct is represented by a matrix of constraints.
+The first line contains two numbers representing
+the number of rows and columns,
+where the number of rows is equal to the number of constraints
+and the number of columns is equal to two plus the number of variables.
+The following lines contain the actual rows of the constraint matrix.
+In each row, the first column indicates whether the constraint
+is an equality (C<0>) or inequality (C<1>). The final column
+corresponds to the constant term.
+
+If the set is parametric, then the coefficients of the parameters
+appear in the last columns before the constant column.
+The coefficients of any existentially quantified variables appear
+between those of the set variables and those of the parameters.
+
+=head3 Extended C<PolyLib> format
+
+The extended C<PolyLib> format is nearly identical to the
+C<PolyLib> format. The only difference is that the line
+containing the number of rows and columns of a constraint matrix
+also contains four additional numbers:
+the number of output dimensions, the number of input dimensions,
+the number of local dimensions (i.e., the number of existentially
+quantified variables) and the number of parameters.
+For sets, the number of ``output'' dimensions is equal
+to the number of set dimensions, while the number of ``input''
+dimensions is zero.
+
+=head3 Input
+
+Objects can be read from input using the following functions.
+
+ #include <isl/val.h>
+ __isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx,
+ const char *str);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_basic_set *isl_basic_set_read_from_str(
+ isl_ctx *ctx, const char *str);
+ __isl_give isl_set *isl_set_read_from_file(isl_ctx *ctx,
+ FILE *input);
+ __isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx,
+ const char *str);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_basic_map *isl_basic_map_read_from_str(
+ isl_ctx *ctx, const char *str);
+ __isl_give isl_map *isl_map_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx,
+ const char *str);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_union_set *isl_union_set_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_union_map *isl_union_map_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
+ __isl_give isl_multi_aff *isl_multi_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
+ __isl_give isl_pw_aff *isl_pw_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(
+ 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_multi_aff *
+ isl_union_pw_multi_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+For sets and relations,
+the input format is autodetected and may be either the C<PolyLib> format
+or the C<isl> format.
+
+=head3 Output
+
+Before anything can be printed, an C<isl_printer> needs to
+be created.
+
+ __isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx,
+ FILE *file);
+ __isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx);
+ __isl_null isl_printer *isl_printer_free(
+ __isl_take isl_printer *printer);
+ __isl_give char *isl_printer_get_str(
+ __isl_keep isl_printer *printer);
+
+The printer can be inspected using the following functions.
+
+ FILE *isl_printer_get_file(
+ __isl_keep isl_printer *printer);
+ int isl_printer_get_output_format(
+ __isl_keep isl_printer *p);
+
+The behavior of the printer can be modified in various ways
+
+ __isl_give isl_printer *isl_printer_set_output_format(
+ __isl_take isl_printer *p, int output_format);
+ __isl_give isl_printer *isl_printer_set_indent(
+ __isl_take isl_printer *p, int indent);
+ __isl_give isl_printer *isl_printer_set_indent_prefix(
+ __isl_take isl_printer *p, const char *prefix);
+ __isl_give isl_printer *isl_printer_indent(
+ __isl_take isl_printer *p, int indent);
+ __isl_give isl_printer *isl_printer_set_prefix(
+ __isl_take isl_printer *p, const char *prefix);
+ __isl_give isl_printer *isl_printer_set_suffix(
+ __isl_take isl_printer *p, const char *suffix);
+
+The C<output_format> may be either C<ISL_FORMAT_ISL>, C<ISL_FORMAT_OMEGA>,
+C<ISL_FORMAT_POLYLIB>, C<ISL_FORMAT_EXT_POLYLIB> or C<ISL_FORMAT_LATEX>
+and defaults to C<ISL_FORMAT_ISL>.
+Each line in the output is prefixed by C<indent_prefix>,
+indented by C<indent> (set by C<isl_printer_set_indent>) spaces
+(default: 0), prefixed by C<prefix> and suffixed by C<suffix>.
+In the C<PolyLib> format output,
+the coefficients of the existentially quantified variables
+appear between those of the set variables and those
+of the parameters.
+The function C<isl_printer_indent> increases the indentation
+by the specified amount (which may be negative).
+
+To actually print something, use
+
+ #include <isl/printer.h>
+ __isl_give isl_printer *isl_printer_print_double(
+ __isl_take isl_printer *p, double d);
+
+ #include <isl/val.h>
+ __isl_give isl_printer *isl_printer_print_val(
+ __isl_take isl_printer *p, __isl_keep isl_val *v);
+
+ #include <isl/set.h>
+ __isl_give isl_printer *isl_printer_print_basic_set(
+ __isl_take isl_printer *printer,
+ __isl_keep isl_basic_set *bset);
+ __isl_give isl_printer *isl_printer_print_set(
+ __isl_take isl_printer *printer,
+ __isl_keep isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_printer *isl_printer_print_basic_map(
+ __isl_take isl_printer *printer,
+ __isl_keep isl_basic_map *bmap);
+ __isl_give isl_printer *isl_printer_print_map(
+ __isl_take isl_printer *printer,
+ __isl_keep isl_map *map);
+
+ #include <isl/union_set.h>
+ __isl_give isl_printer *isl_printer_print_union_set(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_set *uset);
+
+ #include <isl/union_map.h>
+ __isl_give isl_printer *isl_printer_print_union_map(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_map *umap);
+
+ #include <isl/val.h>
+ __isl_give isl_printer *isl_printer_print_multi_val(
+ __isl_take isl_printer *p,
+ __isl_keep isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_printer *isl_printer_print_aff(
+ __isl_take isl_printer *p, __isl_keep isl_aff *aff);
+ __isl_give isl_printer *isl_printer_print_multi_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_multi_aff *maff);
+ __isl_give isl_printer *isl_printer_print_pw_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_pw_aff *pwaff);
+ __isl_give isl_printer *isl_printer_print_pw_multi_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_pw_multi_aff *pma);
+ __isl_give isl_printer *isl_printer_print_multi_pw_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_multi_pw_aff *mpa);
+ __isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_multi_aff *upma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_printer *isl_printer_print_qpolynomial(
+ __isl_take isl_printer *p,
+ __isl_keep isl_qpolynomial *qp);
+ __isl_give isl_printer *isl_printer_print_pw_qpolynomial(
+ __isl_take isl_printer *p,
+ __isl_keep isl_pw_qpolynomial *pwqp);
+ __isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+
+ __isl_give isl_printer *
+ isl_printer_print_pw_qpolynomial_fold(
+ __isl_take isl_printer *p,
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_printer *
+ isl_printer_print_union_pw_qpolynomial_fold(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+For C<isl_printer_print_qpolynomial>,
+C<isl_printer_print_pw_qpolynomial> and
+C<isl_printer_print_pw_qpolynomial_fold>,
+the output format of the printer
+needs to be set to either C<ISL_FORMAT_ISL> or C<ISL_FORMAT_C>.
+For C<isl_printer_print_union_pw_qpolynomial> and
+C<isl_printer_print_union_pw_qpolynomial_fold>, only C<ISL_FORMAT_ISL>
+is supported.
+In case of printing in C<ISL_FORMAT_C>, the user may want
+to set the names of all dimensions first.
+
+When called on a file printer, the following function flushes
+the file. When called on a string printer, the buffer is cleared.
+
+ __isl_give isl_printer *isl_printer_flush(
+ __isl_take isl_printer *p);
+
+Alternatively, a string representation can be obtained
+directly using the following functions, which always print
+in isl format.
+
+ #include <isl/space.h>
+ __isl_give char *isl_space_to_str(
+ __isl_keep isl_space *space);
+
+ #include <isl/val.h>
+ __isl_give char *isl_val_to_str(__isl_keep isl_val *v);
+ __isl_give char *isl_multi_val_to_str(
+ __isl_keep isl_multi_val *mv);
+
+ #include <isl/set.h>
+ __isl_give char *isl_set_to_str(
+ __isl_keep isl_set *set);
+
+ #include <isl/union_set.h>
+ __isl_give char *isl_union_set_to_str(
+ __isl_keep isl_union_set *uset);
+
+ #include <isl/map.h>
+ __isl_give char *isl_map_to_str(
+ __isl_keep isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give char *isl_union_map_to_str(
+ __isl_keep isl_union_map *umap);
+
+ #include <isl/aff.h>
+ __isl_give char *isl_multi_aff_to_str(
+ __isl_keep isl_multi_aff *aff);
+ __isl_give char *isl_union_pw_multi_aff_to_str(
+ __isl_keep isl_union_pw_multi_aff *upma);
+
+=head2 Properties
+
+=head3 Unary Properties
+
+=over
+
+=item * Emptiness
+
+The following functions test whether the given set or relation
+contains any integer points. The ``plain'' variants do not perform
+any computations, but simply check if the given set or relation
+is already known to be empty.
+
+ int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset);
+ int isl_basic_set_is_empty(__isl_keep isl_basic_set *bset);
+ int isl_set_plain_is_empty(__isl_keep isl_set *set);
+ int isl_set_is_empty(__isl_keep isl_set *set);
+ int isl_union_set_is_empty(__isl_keep isl_union_set *uset);
+ int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap);
+ int isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap);
+ int isl_map_plain_is_empty(__isl_keep isl_map *map);
+ int isl_map_is_empty(__isl_keep isl_map *map);
+ int isl_union_map_is_empty(__isl_keep isl_union_map *umap);
+
+=item * Universality
+
+ int isl_basic_set_is_universe(__isl_keep isl_basic_set *bset);
+ int isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap);
+ int isl_set_plain_is_universe(__isl_keep isl_set *set);
+
+=item * Single-valuedness
+
+ #include <isl/set.h>
+ int isl_set_is_singleton(__isl_keep isl_set *set);
+
+ #include <isl/map.h>
+ int isl_basic_map_is_single_valued(
+ __isl_keep isl_basic_map *bmap);
+ int isl_map_plain_is_single_valued(
+ __isl_keep isl_map *map);
+ int isl_map_is_single_valued(__isl_keep isl_map *map);
+
+ #include <isl/union_map.h>
+ int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap);
+
+=item * Injectivity
+
+ int isl_map_plain_is_injective(__isl_keep isl_map *map);
+ int isl_map_is_injective(__isl_keep isl_map *map);
+ int isl_union_map_plain_is_injective(
+ __isl_keep isl_union_map *umap);
+ int isl_union_map_is_injective(
+ __isl_keep isl_union_map *umap);
+
+=item * Bijectivity
+
+ int isl_map_is_bijective(__isl_keep isl_map *map);
+ int isl_union_map_is_bijective(__isl_keep isl_union_map *umap);
+
+=item * Position
+
+ __isl_give isl_val *
+ isl_basic_map_plain_get_val_if_fixed(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_val *isl_set_plain_get_val_if_fixed(
+ __isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+ __isl_give isl_val *isl_map_plain_get_val_if_fixed(
+ __isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+
+If the set or relation obviously lies on a hyperplane where the given dimension
+has a fixed value, then return that value.
+Otherwise return NaN.
+
+=item * Stride
+
+ int isl_set_dim_residue_class_val(
+ __isl_keep isl_set *set,
+ int pos, __isl_give isl_val **modulo,
+ __isl_give isl_val **residue);
+
+Check if the values of the given set dimension are equal to a fixed
+value modulo some integer value. If so, assign the modulo to C<*modulo>
+and the fixed value to C<*residue>. If the given dimension attains only
+a single value, then assign C<0> to C<*modulo> and the fixed value to
+C<*residue>.
+If the dimension does not attain only a single value and if no modulo
+can be found then assign C<1> to C<*modulo> and C<1> to C<*residue>.
+
+=item * Dependence
+
+To check whether the description of a set, relation or function depends
+on one or more given dimensions,
+the following functions can be used.
+
+ #include <isl/constraint.h>
+ int isl_constraint_involves_dims(
+ __isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/set.h>
+ int isl_basic_set_involves_dims(
+ __isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ int isl_set_involves_dims(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/map.h>
+ int isl_basic_map_involves_dims(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ int isl_map_involves_dims(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/union_map.h>
+ int isl_union_map_involves_dims(
+ __isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/aff.h>
+ int isl_aff_involves_dims(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ int isl_pw_aff_involves_dims(__isl_keep isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ int isl_multi_aff_involves_dims(
+ __isl_keep isl_multi_aff *ma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ int isl_multi_pw_aff_involves_dims(
+ __isl_keep isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+Similarly, the following functions can be used to check whether
+a given dimension is involved in any lower or upper bound.
+
+ #include <isl/set.h>
+ int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+ int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+
+Note that these functions return true even if there is a bound on
+the dimension on only some of the basic sets of C<set>.
+To check if they have a bound for all of the basic sets in C<set>,
+use the following functions instead.
+
+ #include <isl/set.h>
+ int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+ int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+
+=item * Space
+
+To check whether a set is a parameter domain, use this function:
+
+ int isl_set_is_params(__isl_keep isl_set *set);
+ int isl_union_set_is_params(
+ __isl_keep isl_union_set *uset);
+
+=item * Wrapping
+
+The following functions check whether the space of the given
+(basic) set or relation range is a wrapped relation.
+
+ #include <isl/space.h>
+ int isl_space_is_wrapping(
+ __isl_keep isl_space *space);
+ int isl_space_domain_is_wrapping(
+ __isl_keep isl_space *space);
+ int isl_space_range_is_wrapping(
+ __isl_keep isl_space *space);
+
+ #include <isl/set.h>
+ int isl_basic_set_is_wrapping(
+ __isl_keep isl_basic_set *bset);
+ int isl_set_is_wrapping(__isl_keep isl_set *set);
+
+ #include <isl/map.h>
+ int isl_map_domain_is_wrapping(
+ __isl_keep isl_map *map);
+ int isl_map_range_is_wrapping(
+ __isl_keep isl_map *map);
+
+ #include <isl/val.h>
+ int isl_multi_val_range_is_wrapping(
+ __isl_keep isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ int isl_multi_aff_range_is_wrapping(
+ __isl_keep isl_multi_aff *ma);
+ int isl_multi_pw_aff_range_is_wrapping(
+ __isl_keep isl_multi_pw_aff *mpa);
+
+The input to C<isl_space_is_wrapping> should
+be the space of a set, while that of
+C<isl_space_domain_is_wrapping> and
+C<isl_space_range_is_wrapping> should be the space of a relation.
+
+=item * Internal Product
+
+ int isl_basic_map_can_zip(
+ __isl_keep isl_basic_map *bmap);
+ int isl_map_can_zip(__isl_keep isl_map *map);
+
+Check whether the product of domain and range of the given relation
+can be computed,
+i.e., whether both domain and range are nested relations.
+
+=item * Currying
+
+ int isl_basic_map_can_curry(
+ __isl_keep isl_basic_map *bmap);
+ int isl_map_can_curry(__isl_keep isl_map *map);
+
+Check whether the domain of the (basic) relation is a wrapped relation.
+
+ int isl_basic_map_can_uncurry(
+ __isl_keep isl_basic_map *bmap);
+ int isl_map_can_uncurry(__isl_keep isl_map *map);
+
+Check whether the range of the (basic) relation is a wrapped relation.
+
+=item * Special Values
+
+ #include <isl/aff.h>
+ int isl_aff_is_cst(__isl_keep isl_aff *aff);
+ int isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff);
+
+Check whether the given expression is a constant.
+
+ #include <isl/aff.h>
+ int isl_aff_is_nan(__isl_keep isl_aff *aff);
+ int isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa);
+
+Check whether the given expression is equal to or involves NaN.
+
+ #include <isl/aff.h>
+ int isl_aff_plain_is_zero(__isl_keep isl_aff *aff);
+
+Check whether the affine expression is obviously zero.
+
+=back
+
+=head3 Binary Properties
+
+=over
+
+=item * Equality
+
+The following functions check whether two objects
+represent the same set, relation or function.
+The C<plain> variants only return true if the objects
+are obviously the same. That is, they may return false
+even if the objects are the same, but they will never
+return true if the objects are not the same.
+
+ #include <isl/set.h>
+ int isl_basic_set_plain_is_equal(
+ __isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+ int isl_set_plain_is_equal(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ int isl_set_is_equal(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+
+ #include <isl/map.h>
+ int isl_basic_map_is_equal(
+ __isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+ int isl_map_is_equal(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2);
+ int isl_map_plain_is_equal(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2);
+
+ #include <isl/union_set.h>
+ int isl_union_set_is_equal(
+ __isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+
+ #include <isl/union_map.h>
+ int isl_union_map_is_equal(
+ __isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+
+ #include <isl/aff.h>
+ int isl_aff_plain_is_equal(__isl_keep isl_aff *aff1,
+ __isl_keep isl_aff *aff2);
+ int isl_multi_aff_plain_is_equal(
+ __isl_keep isl_multi_aff *maff1,
+ __isl_keep isl_multi_aff *maff2);
+ int isl_pw_aff_plain_is_equal(
+ __isl_keep isl_pw_aff *pwaff1,
+ __isl_keep isl_pw_aff *pwaff2);
+ int isl_pw_multi_aff_plain_is_equal(
+ __isl_keep isl_pw_multi_aff *pma1,
+ __isl_keep isl_pw_multi_aff *pma2);
+ int isl_multi_pw_aff_plain_is_equal(
+ __isl_keep isl_multi_pw_aff *mpa1,
+ __isl_keep isl_multi_pw_aff *mpa2);
+ int isl_multi_pw_aff_is_equal(
+ __isl_keep isl_multi_pw_aff *mpa1,
+ __isl_keep isl_multi_pw_aff *mpa2);
+ int isl_union_pw_multi_aff_plain_is_equal(
+ __isl_keep isl_union_pw_multi_aff *upma1,
+ __isl_keep isl_union_pw_multi_aff *upma2);
+
+ #include <isl/polynomial.h>
+ int isl_union_pw_qpolynomial_plain_is_equal(
+ __isl_keep isl_union_pw_qpolynomial *upwqp1,
+ __isl_keep isl_union_pw_qpolynomial *upwqp2);
+ int isl_union_pw_qpolynomial_fold_plain_is_equal(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf1,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf2);
+
+=item * Disjointness
+
+ int isl_basic_set_is_disjoint(
+ __isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+ int isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ int isl_set_is_disjoint(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ int isl_basic_map_is_disjoint(
+ __isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+ int isl_map_is_disjoint(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2);
+
+=item * Subset
+
+ int isl_basic_set_is_subset(
+ __isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+ int isl_set_is_subset(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ int isl_set_is_strict_subset(
+ __isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ int isl_union_set_is_subset(
+ __isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+ int isl_union_set_is_strict_subset(
+ __isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+ int isl_basic_map_is_subset(
+ __isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+ int isl_basic_map_is_strict_subset(
+ __isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+ int isl_map_is_subset(
+ __isl_keep isl_map *map1,
+ __isl_keep isl_map *map2);
+ int isl_map_is_strict_subset(
+ __isl_keep isl_map *map1,
+ __isl_keep isl_map *map2);
+ int isl_union_map_is_subset(
+ __isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+ int isl_union_map_is_strict_subset(
+ __isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+
+Check whether the first argument is a (strict) subset of the
+second argument.
+
+=item * Order
+
+Every comparison function returns a negative value if the first
+argument is considered smaller than the second, a positive value
+if the first argument is considered greater and zero if the two
+constraints are considered the same by the comparison criterion.
+
+ #include <isl/constraint.h>
+ int isl_constraint_plain_cmp(
+ __isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2);
+
+This function is useful for sorting C<isl_constraint>s.
+The order depends on the internal representation of the inputs.
+The order is fixed over different calls to the function (assuming
+the internal representation of the inputs has not changed), but may
+change over different versions of C<isl>.
+
+ #include <isl/constraint.h>
+ int isl_constraint_cmp_last_non_zero(
+ __isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2);
+
+This function can be used to sort constraints that live in the same
+local space. Constraints that involve ``earlier'' dimensions or
+that have a smaller coefficient for the shared latest dimension
+are considered smaller than other constraints.
+This function only defines a B<partial> order.
+
+ #include <isl/set.h>
+ int isl_set_plain_cmp(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+
+This function is useful for sorting C<isl_set>s.
+The order depends on the internal representation of the inputs.
+The order is fixed over different calls to the function (assuming
+the internal representation of the inputs has not changed), but may
+change over different versions of C<isl>.
+
+ #include <isl/aff.h>
+ int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
+ __isl_keep isl_pw_aff *pa2);
+
+The function C<isl_pw_aff_plain_cmp> can be used to sort
+C<isl_pw_aff>s. The order is not strictly defined.
+The current order sorts expressions that only involve
+earlier dimensions before those that involve later dimensions.
+
+=back
+
+=head2 Unary Operations
+
+=over
+
+=item * Complement
+
+ __isl_give isl_set *isl_set_complement(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_complement(
+ __isl_take isl_map *map);
+
+=item * Inverse map
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_reverse(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_reverse(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_reverse(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_reverse(
+ __isl_take isl_union_map *umap);
+
+=item * Projection
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_domain(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_range(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_params(
+ __isl_take isl_space *space);
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_domain(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_local_space *isl_local_space_range(
+ __isl_take isl_local_space *ls);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_project_out(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_basic_set *isl_basic_set_params(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_params(__isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_project_out(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_basic_set *isl_basic_map_domain(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_set *isl_basic_map_range(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_map_params(__isl_take isl_map *map);
+ __isl_give isl_set *isl_map_domain(
+ __isl_take isl_map *bmap);
+ __isl_give isl_set *isl_map_range(
+ __isl_take isl_map *map);
+
+ #include <isl/union_set.h>
+ __isl_give isl_set *isl_union_set_params(
+ __isl_take isl_union_set *uset);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_project_out(
+ __isl_take isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_set *isl_union_map_params(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_set *isl_union_map_domain(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_set *isl_union_map_range(
+ __isl_take isl_union_map *umap);
+
+The function C<isl_union_map_project_out> can only project out
+parameters.
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_project_domain_on_params(
+ __isl_take isl_aff *aff);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_project_domain_on_params(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_set *isl_pw_aff_domain(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_set *isl_pw_multi_aff_domain(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_set *isl_multi_pw_aff_domain(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_set *isl_union_pw_multi_aff_domain(
+ __isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_set *isl_pw_aff_params(
+ __isl_take isl_pw_aff *pwa);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *
+ isl_qpolynomial_project_domain_on_params(
+ __isl_take isl_qpolynomial *qp);
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_project_domain_on_params(
+ __isl_take isl_pw_qpolynomial *pwqp);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_project_domain_on_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_set *isl_pw_qpolynomial_domain(
+ __isl_take isl_pw_qpolynomial *pwqp);
+ __isl_give isl_union_set *isl_union_pw_qpolynomial_fold_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+ __isl_give isl_union_set *isl_union_pw_qpolynomial_domain(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_domain_map(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_range_map(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_set_wrapped_domain_map(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_map *isl_basic_map_domain_map(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_map *isl_basic_map_range_map(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map);
+ __isl_give isl_map *isl_map_range_map(__isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_domain_map(
+ __isl_take isl_union_map *umap);
+ __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(
+ __isl_take isl_union_set *uset);
+
+The functions above construct a (basic, regular or union) relation
+that maps (a wrapped version of) the input relation to its domain or range.
+C<isl_set_wrapped_domain_map> maps the input set to the domain
+of its wrapped relation.
+
+=item * Elimination
+
+ __isl_give isl_basic_set *isl_basic_set_eliminate(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_set *isl_set_eliminate(
+ __isl_take isl_set *set, enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_basic_map *isl_basic_map_eliminate(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_map *isl_map_eliminate(
+ __isl_take isl_map *map, enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+Eliminate the coefficients for the given dimensions from the constraints,
+without removing the dimensions.
+
+=item * Constructing a set from a parameter domain
+
+A zero-dimensional space or (basic) set can be constructed
+on a given parameter domain using the following functions.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_set_from_params(
+ __isl_take isl_space *space);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_from_params(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_from_params(
+ __isl_take isl_set *set);
+
+=item * Constructing a relation from a set
+
+Create a relation with the given set as domain or range.
+The range or domain of the created relation is a zero-dimensional
+flat anonymous space.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_from_domain(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_from_range(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_map_from_set(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_map_from_domain_and_range(
+ __isl_take isl_space *domain,
+ __isl_take isl_space *range);
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_from_domain(
+ __isl_take isl_local_space *ls);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_from_domain(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_from_range(
+ __isl_take isl_set *set);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_from_range(
+ __isl_take isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_from_range(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_pw_aff *isl_pw_aff_from_range(
+ __isl_take isl_pw_aff *pwa);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_range(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_domain(
+ __isl_take isl_union_set *uset);
+
+=item * Slicing
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_fix_si(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_basic_set *isl_basic_set_fix_val(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *v);
+ __isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_set *isl_set_fix_val(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *v);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_fix_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_basic_map *isl_basic_map_fix_val(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *v);
+ __isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_map *isl_map_fix_val(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *v);
+
+ #include <isl/aff.h>
+ __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);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_fix_val(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned n,
+ __isl_take isl_val *v);
+
+Intersect the set, relation or function domain
+with the hyperplane where the given
+dimension has the fixed given value.
+
+ __isl_give isl_basic_map *isl_basic_map_lower_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_basic_map *isl_basic_map_upper_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_set *isl_set_lower_bound_si(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_set *isl_set_lower_bound_val(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *value);
+ __isl_give isl_map *isl_map_lower_bound_si(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_set *isl_set_upper_bound_si(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+ __isl_give isl_set *isl_set_upper_bound_val(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_val *value);
+ __isl_give isl_map *isl_map_upper_bound_si(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+
+Intersect the set or relation with the half-space where the given
+dimension has a value bounded by the fixed given integer value.
+
+ __isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_basic_map *isl_basic_map_equate(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+
+Intersect the set or relation with the hyperplane where the given
+dimensions are equal to each other.
+
+ __isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+
+Intersect the relation with the hyperplane where the given
+dimensions have opposite values.
+
+ __isl_give isl_map *isl_map_order_le(
+ __isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_basic_map *isl_basic_map_order_ge(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_map *isl_map_order_ge(
+ __isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_basic_map *isl_basic_map_order_gt(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+ __isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2);
+
+Intersect the relation with the half-space where the given
+dimensions satisfy the given ordering.
+
+=item * Locus
+
+ #include <isl/aff.h>
+ __isl_give isl_basic_set *isl_aff_zero_basic_set(
+ __isl_take isl_aff *aff);
+ __isl_give isl_basic_set *isl_aff_neg_basic_set(
+ __isl_take isl_aff *aff);
+ __isl_give isl_set *isl_pw_aff_nonneg_set(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_set *isl_pw_aff_zero_set(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_set *isl_pw_aff_non_zero_set(
+ __isl_take isl_pw_aff *pwaff);
+
+The function C<isl_aff_neg_basic_set> returns a basic set
+containing those elements in the domain space
+of C<aff> where C<aff> is negative.
+The function C<isl_pw_aff_nonneg_set> returns a set
+containing those elements in the domain
+of C<pwaff> where C<pwaff> is non-negative.
+
+=item * Identity
+
+ __isl_give isl_map *isl_set_identity(
+ __isl_take isl_set *set);
+ __isl_give isl_union_map *isl_union_set_identity(
+ __isl_take isl_union_set *uset);
+
+Construct an identity relation on the given (union) set.
+
+=item * Function Extraction
+
+A piecewise quasi affine expression that is equal to 1 on a set
+and 0 outside the set can be created using the following function.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_set_indicator_function(
+ __isl_take isl_set *set);
+
+A piecewise multiple quasi affine expression can be extracted
+from an C<isl_set> or C<isl_map>, provided the C<isl_set> is a singleton
+and the C<isl_map> is single-valued.
+In case of a conversion from an C<isl_union_map>
+to an C<isl_union_pw_multi_aff>, these properties need to hold
+in each domain space.
+
+ __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_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_union_set(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_union_map(
+ __isl_take isl_union_map *umap);
+
+=item * Deltas
+
+ __isl_give isl_basic_set *isl_basic_map_deltas(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_map_deltas(__isl_take isl_map *map);
+ __isl_give isl_union_set *isl_union_map_deltas(
+ __isl_take isl_union_map *umap);
+
+These functions return a (basic) set containing the differences
+between image elements and corresponding domain elements in the input.
+
+ __isl_give isl_basic_map *isl_basic_map_deltas_map(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_deltas_map(
+ __isl_take isl_map *map);
+ __isl_give isl_union_map *isl_union_map_deltas_map(
+ __isl_take isl_union_map *umap);
+
+The functions above construct a (basic, regular or union) relation
+that maps (a wrapped version of) the input relation to its delta set.
+
+=item * Coalescing
+
+Simplify the representation of a set, relation or functions by trying
+to combine pairs of basic sets or relations into a single
+basic set or relation.
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_set_coalesce(__isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_coalesce(__isl_take isl_map *map);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_coalesce(
+ __isl_take isl_union_set *uset);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_coalesce(
+ __isl_take isl_union_map *umap);
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_coalesce(
+ __isl_take isl_pw_aff *pwqp);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_coalesce(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_coalesce(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_coalesce(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_coalesce(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_coalesce(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+
+One of the methods for combining pairs of basic sets or relations
+can result in coefficients that are much larger than those that appear
+in the constraints of the input. By default, the coefficients are
+not allowed to grow larger, but this can be changed by unsetting
+the following option.
+
+ int isl_options_set_coalesce_bounded_wrapping(
+ isl_ctx *ctx, int val);
+ int isl_options_get_coalesce_bounded_wrapping(
+ isl_ctx *ctx);
+
+=item * Detecting equalities
+
+ __isl_give isl_basic_set *isl_basic_set_detect_equalities(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_map *isl_basic_map_detect_equalities(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_set_detect_equalities(
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_detect_equalities(
+ __isl_take isl_map *map);
+ __isl_give isl_union_set *isl_union_set_detect_equalities(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_detect_equalities(
+ __isl_take isl_union_map *umap);
+
+Simplify the representation of a set or relation by detecting implicit
+equalities.
+
+=item * Removing redundant constraints
+
+ __isl_give isl_basic_set *isl_basic_set_remove_redundancies(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_remove_redundancies(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_map *isl_basic_map_remove_redundancies(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_remove_redundancies(
+ __isl_take isl_map *map);
+
+=item * Convex hull
+
+ __isl_give isl_basic_set *isl_set_convex_hull(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_map *isl_map_convex_hull(
+ __isl_take isl_map *map);
+
+If the input set or relation has any existentially quantified
+variables, then the result of these operations is currently undefined.
+
+=item * Simple hull
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *
+ isl_set_unshifted_simple_hull(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_set *isl_set_simple_hull(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_set *
+ isl_set_unshifted_simple_hull_from_set_list(
+ __isl_take isl_set *set,
+ __isl_take isl_set_list *list);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *
+ isl_map_unshifted_simple_hull(
+ __isl_take isl_map *map);
+ __isl_give isl_basic_map *isl_map_simple_hull(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_simple_hull(
+ __isl_take isl_union_map *umap);
+
+These functions compute a single basic set or relation
+that contains the whole input set or relation.
+In particular, the output is described by translates
+of the constraints describing the basic sets or relations in the input.
+In case of C<isl_set_unshifted_simple_hull>, only the original
+constraints are used, without any translation.
+In case of C<isl_set_unshifted_simple_hull_from_set_list>, the
+constraints are taken from the elements of the second argument.
+
+=begin latex
+
+(See \autoref{s:simple hull}.)
+
+=end latex
+
+=item * Affine hull
+
+ __isl_give isl_basic_set *isl_basic_set_affine_hull(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_set *isl_set_affine_hull(
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_affine_hull(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_basic_map *isl_basic_map_affine_hull(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_map *isl_map_affine_hull(
+ __isl_take isl_map *map);
+ __isl_give isl_union_map *isl_union_map_affine_hull(
+ __isl_take isl_union_map *umap);
+
+In case of union sets and relations, the affine hull is computed
+per space.
+
+=item * Polyhedral hull
+
+ __isl_give isl_basic_set *isl_set_polyhedral_hull(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_map *isl_map_polyhedral_hull(
+ __isl_take isl_map *map);
+ __isl_give isl_union_set *isl_union_set_polyhedral_hull(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_polyhedral_hull(
+ __isl_take isl_union_map *umap);
+
+These functions compute a single basic set or relation
+not involving any existentially quantified variables
+that contains the whole input set or relation.
+In case of union sets and relations, the polyhedral hull is computed
+per space.
+
+=item * Other approximations
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *
+ isl_basic_set_drop_constraints_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_basic_set *
+ isl_basic_set_drop_constraints_not_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_set *
+ isl_set_drop_constraints_involving_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+ #include <isl/map.h>
+ __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_map *
+ isl_map_drop_constraints_involving_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+These functions drop any constraints (not) involving the specified dimensions.
+Note that the result depends on the representation of the input.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
+ __isl_take isl_pw_qpolynomial *pwqp, int sign);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_to_polynomial(
+ __isl_take isl_union_pw_qpolynomial *upwqp, int sign);
+
+Approximate each quasipolynomial by a polynomial. If C<sign> is positive,
+the polynomial will be an overapproximation. If C<sign> is negative,
+it will be an underapproximation. If C<sign> is zero, the approximation
+will lie somewhere in between.
+
+=item * Feasibility
+
+ __isl_give isl_basic_set *isl_basic_set_sample(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_set *isl_set_sample(
+ __isl_take isl_set *set);
+ __isl_give isl_basic_map *isl_basic_map_sample(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_map *isl_map_sample(
+ __isl_take isl_map *map);
+
+If the input (basic) set or relation is non-empty, then return
+a singleton subset of the input. Otherwise, return an empty set.
+
+=item * Optimization
+
+ #include <isl/ilp.h>
+ __isl_give isl_val *isl_basic_set_max_val(
+ __isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj);
+ __isl_give isl_val *isl_set_min_val(
+ __isl_keep isl_set *set,
+ __isl_keep isl_aff *obj);
+ __isl_give isl_val *isl_set_max_val(
+ __isl_keep isl_set *set,
+ __isl_keep isl_aff *obj);
+
+Compute the minimum or maximum of the integer affine expression C<obj>
+over the points in C<set>, returning the result in C<opt>.
+The result is C<NULL> in case of an error, the optimal value in case
+there is one, negative infinity or infinity if the problem is unbounded and
+NaN if the problem is empty.
+
+=item * Parametric optimization
+
+ __isl_give isl_pw_aff *isl_set_dim_min(
+ __isl_take isl_set *set, int pos);
+ __isl_give isl_pw_aff *isl_set_dim_max(
+ __isl_take isl_set *set, int pos);
+ __isl_give isl_pw_aff *isl_map_dim_max(
+ __isl_take isl_map *map, int pos);
+
+Compute the minimum or maximum of the given set or output dimension
+as a function of the parameters (and input dimensions), but independently
+of the other set or output dimensions.
+For lexicographic optimization, see L<"Lexicographic Optimization">.
+
+=item * Dual
+
+The following functions compute either the set of (rational) coefficient
+values of valid constraints for the given set or the set of (rational)
+values satisfying the constraints with coefficients from the given set.
+Internally, these two sets of functions perform essentially the
+same operations, except that the set of coefficients is assumed to
+be a cone, while the set of values may be any polyhedron.
+The current implementation is based on the Farkas lemma and
+Fourier-Motzkin elimination, but this may change or be made optional
+in future. In particular, future implementations may use different
+dualization algorithms or skip the elimination step.
+
+ __isl_give isl_basic_set *isl_basic_set_coefficients(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_set *isl_set_coefficients(
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_coefficients(
+ __isl_take isl_union_set *bset);
+ __isl_give isl_basic_set *isl_basic_set_solutions(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_set *isl_set_solutions(
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_solutions(
+ __isl_take isl_union_set *bset);
+
+=item * Power
+
+ __isl_give isl_map *isl_map_fixed_power_val(
+ __isl_take isl_map *map,
+ __isl_take isl_val *exp);
+ __isl_give isl_union_map *
+ isl_union_map_fixed_power_val(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_val *exp);
+
+Compute the given power of C<map>, where C<exp> is assumed to be non-zero.
+If the exponent C<exp> is negative, then the -C<exp> th power of the inverse
+of C<map> is computed.
+
+ __isl_give isl_map *isl_map_power(__isl_take isl_map *map,
+ int *exact);
+ __isl_give isl_union_map *isl_union_map_power(
+ __isl_take isl_union_map *umap, int *exact);
+
+Compute a parametric representation for all positive powers I<k> of C<map>.
+The result maps I<k> to a nested relation corresponding to the
+I<k>th power of C<map>.
+The result may be an overapproximation. If the result is known to be exact,
+then C<*exact> is set to C<1>.
+
+=item * Transitive closure
+
+ __isl_give isl_map *isl_map_transitive_closure(
+ __isl_take isl_map *map, int *exact);
+ __isl_give isl_union_map *isl_union_map_transitive_closure(
+ __isl_take isl_union_map *umap, int *exact);
+
+Compute the transitive closure of C<map>.
+The result may be an overapproximation. If the result is known to be exact,
+then C<*exact> is set to C<1>.
+
+=item * Reaching path lengths
+
+ __isl_give isl_map *isl_map_reaching_path_lengths(
+ __isl_take isl_map *map, int *exact);
+
+Compute a relation that maps each element in the range of C<map>
+to the lengths of all paths composed of edges in C<map> that
+end up in the given element.
+The result may be an overapproximation. If the result is known to be exact,
+then C<*exact> is set to C<1>.
+To compute the I<maximal> path length, the resulting relation
+should be postprocessed by C<isl_map_lexmax>.
+In particular, if the input relation is a dependence relation
+(mapping sources to sinks), then the maximal path length corresponds
+to the free schedule.
+Note, however, that C<isl_map_lexmax> expects the maximum to be
+finite, so if the path lengths are unbounded (possibly due to
+the overapproximation), then you will get an error message.
+
+=item * Wrapping
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_wrap(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_unwrap(
+ __isl_take isl_space *space);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_map *isl_basic_set_unwrap(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_map *isl_set_unwrap(
+ __isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_set *isl_basic_map_wrap(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_map_wrap(
+ __isl_take isl_map *map);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_map *isl_union_set_unwrap(
+ __isl_take isl_union_set *uset);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_set *isl_union_map_wrap(
+ __isl_take isl_union_map *umap);
+
+The input to C<isl_space_unwrap> should
+be the space of a set, while that of
+C<isl_space_wrap> should be the space of a relation.
+Conversely, the output of C<isl_space_unwrap> is the space
+of a relation, while that of C<isl_space_wrap> is the space of a set.
+
+=item * Flattening
+
+Remove any internal structure of domain (and range) of the given
+set or relation. If there is any such internal structure in the input,
+then the name of the space is also removed.
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *
+ isl_local_space_flatten_domain(
+ __isl_take isl_local_space *ls);
+ __isl_give isl_local_space *
+ isl_local_space_flatten_range(
+ __isl_take isl_local_space *ls);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_flatten(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_flatten(
+ __isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_flatten_domain(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_map *isl_basic_map_flatten_range(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_flatten_range(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_flatten_domain(
+ __isl_take isl_map *map);
+ __isl_give isl_basic_map *isl_basic_map_flatten(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_flatten(
+ __isl_take isl_map *map);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_flatten_range(
+ __isl_take isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_aff *isl_multi_aff_flatten_range(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_flatten_range(
+ __isl_take isl_multi_pw_aff *mpa);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_set_flatten_map(
+ __isl_take isl_set *set);
+
+The function above constructs a relation
+that maps the input set to a flattened version of the set.
+
+=item * Lifting
+
+Lift the input set to a space with extra dimensions corresponding
+to the existentially quantified variables in the input.
+In particular, the result lives in a wrapped map where the domain
+is the original space and the range corresponds to the original
+existentially quantified variables.
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_lift(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_lift(
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_lift(
+ __isl_take isl_union_set *uset);
+
+Given a local space that contains the existentially quantified
+variables of a set, a basic relation that, when applied to
+a basic set, has essentially the same effect as C<isl_basic_set_lift>,
+can be constructed using the following function.
+
+ #include <isl/local_space.h>
+ __isl_give isl_basic_map *isl_local_space_lifting(
+ __isl_take isl_local_space *ls);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_lift(
+ __isl_take isl_multi_aff *maff,
+ __isl_give isl_local_space **ls);
+
+If the C<ls> argument of C<isl_multi_aff_lift> is not C<NULL>,
+then it is assigned the local space that lies at the basis of
+the lifting applied.
+
+=item * Internal Product
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_zip(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_zip(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_zip(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_zip(
+ __isl_take isl_union_map *umap);
+
+Given a relation with nested relations for domain and range,
+interchange the range of the domain with the domain of the range.
+
+=item * Currying
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_curry(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_uncurry(
+ __isl_take isl_space *space);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_curry(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_basic_map *isl_basic_map_uncurry(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_curry(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_uncurry(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_curry(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *isl_union_map_uncurry(
+ __isl_take isl_union_map *umap);
+
+Given a relation with a nested relation for domain,
+the C<curry> functions
+move the range of the nested relation out of the domain
+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.
+
+=item * Aligning parameters
+
+Change the order of the parameters of the given set, relation
+or function
+such that the first parameters match those of C<model>.
+This may involve the introduction of extra parameters.
+All parameters need to be named.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_align_params(
+ __isl_take isl_space *space1,
+ __isl_take isl_space *space2)
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_align_params(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_space *model);
+ __isl_give isl_set *isl_set_align_params(
+ __isl_take isl_set *set,
+ __isl_take isl_space *model);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_align_params(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_space *model);
+ __isl_give isl_map *isl_map_align_params(
+ __isl_take isl_map *map,
+ __isl_take isl_space *model);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_align_params(
+ __isl_take isl_multi_val *mv,
+ __isl_take isl_space *model);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_align_params(
+ __isl_take isl_aff *aff,
+ __isl_take isl_space *model);
+ __isl_give isl_multi_aff *isl_multi_aff_align_params(
+ __isl_take isl_multi_aff *multi,
+ __isl_take isl_space *model);
+ __isl_give isl_pw_aff *isl_pw_aff_align_params(
+ __isl_take isl_pw_aff *pwaff,
+ __isl_take isl_space *model);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_align_params(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_space *model);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_align_params(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_space *model);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_align_params(
+ __isl_take isl_qpolynomial *qp,
+ __isl_take isl_space *model);
+
+=item * Unary Arithmethic Operations
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_neg(
+ __isl_take isl_aff *aff);
+ __isl_give isl_pw_aff *isl_pw_aff_neg(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_aff *isl_aff_ceil(
+ __isl_take isl_aff *aff);
+ __isl_give isl_pw_aff *isl_pw_aff_ceil(
+ __isl_take isl_pw_aff *pwaff);
+ __isl_give isl_aff *isl_aff_floor(
+ __isl_take isl_aff *aff);
+ __isl_give isl_multi_aff *isl_multi_aff_floor(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_pw_aff *isl_pw_aff_floor(
+ __isl_take isl_pw_aff *pwaff);
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_list_min(
+ __isl_take isl_pw_aff_list *list);
+ __isl_give isl_pw_aff *isl_pw_aff_list_max(
+ __isl_take isl_pw_aff_list *list);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_neg(
+ __isl_take isl_qpolynomial *qp);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_neg(
+ __isl_take isl_pw_qpolynomial *pwqp);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_neg(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+ __isl_give isl_qpolynomial *isl_qpolynomial_pow(
+ __isl_take isl_qpolynomial *qp,
+ unsigned exponent);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ unsigned exponent);
+
+=item * Evaluation
+
+The following functions evaluate a function in a point.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_val *isl_pw_qpolynomial_eval(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_point *pnt);
+ __isl_give isl_val *isl_pw_qpolynomial_fold_eval(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_point *pnt);
+ __isl_give isl_val *isl_union_pw_qpolynomial_eval(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_point *pnt);
+ __isl_give isl_val *isl_union_pw_qpolynomial_fold_eval(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_point *pnt);
+
+=item * Dimension manipulation
+
+It is usually not advisable to directly change the (input or output)
+space of a set or a relation as this removes the name and the internal
+structure of the space. However, the functions below can be useful
+to add new parameters, assuming
+C<isl_set_align_params> and C<isl_map_align_params>
+are not sufficient.
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_add_dims(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_space *isl_space_insert_dims(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+ __isl_give isl_space *isl_space_drop_dims(
+ __isl_take isl_space *space,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_space *isl_space_move_dims(
+ __isl_take isl_space *space,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_add_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_local_space *isl_local_space_insert_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_local_space *isl_local_space_drop_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_add_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_set *isl_set_add_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_basic_set *isl_basic_set_insert_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos,
+ unsigned n);
+ __isl_give isl_set *isl_set_insert_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+ __isl_give isl_basic_set *isl_basic_set_move_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+ __isl_give isl_set *isl_set_move_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_add_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_basic_map *isl_basic_map_insert_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos,
+ unsigned n);
+ __isl_give isl_map *isl_map_insert_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+ __isl_give isl_basic_map *isl_basic_map_move_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+ __isl_give isl_map *isl_map_move_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_insert_dims(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_multi_val *isl_multi_val_add_dims(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_multi_val *isl_multi_val_drop_dims(
+ __isl_take isl_multi_val *mv,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_insert_dims(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_multi_aff *isl_multi_aff_insert_dims(
+ __isl_take isl_multi_aff *ma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_pw_aff *isl_pw_aff_insert_dims(
+ __isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_insert_dims(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_aff *isl_aff_add_dims(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_multi_aff *isl_multi_aff_add_dims(
+ __isl_take isl_multi_aff *ma,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_pw_aff *isl_pw_aff_add_dims(
+ __isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_add_dims(
+ __isl_take isl_multi_pw_aff *mpa,
+ enum isl_dim_type type, unsigned n);
+ __isl_give isl_aff *isl_aff_drop_dims(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_multi_aff *isl_multi_aff_drop_dims(
+ __isl_take isl_multi_aff *maff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_pw_aff *isl_pw_aff_drop_dims(
+ __isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_drop_dims(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_aff *isl_aff_move_dims(
+ __isl_take isl_aff *aff,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+ __isl_give isl_multi_aff *isl_multi_aff_move_dims(
+ __isl_take isl_multi_aff *ma,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+ __isl_give isl_pw_aff *isl_pw_aff_move_dims(
+ __isl_take isl_pw_aff *pa,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_move_dims(
+ __isl_take isl_multi_pw_aff *pma,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos,
+ unsigned n);
+
+=back
+
+=head2 Binary Operations
+
+The two arguments of a binary operation not only need to live
+in the same C<isl_ctx>, they currently also need to have
+the same (number of) parameters.
+
+=head3 Basic Operations
+
+=over
+
+=item * Intersection
+
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_intersect(
+ __isl_take isl_local_space *ls1,
+ __isl_take isl_local_space *ls2);
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_intersect_params(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+ __isl_give isl_basic_set *isl_basic_set_intersect(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+ __isl_give isl_basic_set *isl_basic_set_list_intersect(
+ __isl_take struct isl_basic_set_list *list);
+ __isl_give isl_set *isl_set_intersect_params(
+ __isl_take isl_set *set,
+ __isl_take isl_set *params);
+ __isl_give isl_set *isl_set_intersect(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_intersect_domain(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_map *isl_basic_map_intersect_range(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_basic_map *isl_basic_map_intersect(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_map *isl_map_intersect_params(
+ __isl_take isl_map *map,
+ __isl_take isl_set *params);
+ __isl_give isl_map *isl_map_intersect_domain(
+ __isl_take isl_map *map,
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_intersect_range(
+ __isl_take isl_map *map,
+ __isl_take isl_set *set);
+ __isl_give isl_map *isl_map_intersect(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_intersect_params(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_intersect(
+ __isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_intersect_params(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_set *set);
+ __isl_give isl_union_map *isl_union_map_intersect_domain(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_intersect_range(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_intersect(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_intersect_domain(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_intersect_domain(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_set *domain);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_domain(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_intersect_domain(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_pw_aff *isl_pw_aff_intersect_params(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_intersect_params(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_set *set);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_params(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_intersect_params(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_set *set);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_intersect_domain(
+ __isl_take isl_pw_qpolynomial *pwpq,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_intersect_domain(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_intersect_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_intersect_params(
+ __isl_take isl_pw_qpolynomial *pwpq,
+ __isl_take isl_set *set);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_intersect_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_intersect_params(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_intersect_params(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_set *set);
+
+The second argument to the C<_params> functions needs to be
+a parametric (basic) set. For the other functions, a parametric set
+for either argument is only allowed if the other argument is
+a parametric set as well.
+The list passed to C<isl_basic_set_list_intersect> needs to have
+at least one element and all elements need to live in the same space.
+
+=item * Union
+
+ __isl_give isl_set *isl_basic_set_union(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+ __isl_give isl_map *isl_basic_map_union(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_set *isl_set_union(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+ __isl_give isl_map *isl_map_union(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_union_set *isl_union_set_union(
+ __isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+ __isl_give isl_union_map *isl_union_map_union(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+
+=item * Set difference
+
+ __isl_give isl_set *isl_set_subtract(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+ __isl_give isl_map *isl_map_subtract(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_map *isl_map_subtract_domain(
+ __isl_take isl_map *map,
+ __isl_take isl_set *dom);
+ __isl_give isl_map *isl_map_subtract_range(
+ __isl_take isl_map *map,
+ __isl_take isl_set *dom);
+ __isl_give isl_union_set *isl_union_set_subtract(
+ __isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+ __isl_give isl_union_map *isl_union_map_subtract(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+ __isl_give isl_union_map *isl_union_map_subtract_domain(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *dom);
+ __isl_give isl_union_map *isl_union_map_subtract_range(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *dom);
+
+=item * Application
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_join(
+ __isl_take isl_space *left,
+ __isl_take isl_space *right);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_set *isl_basic_set_apply(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_set *isl_set_apply(
+ __isl_take isl_set *set,
+ __isl_take isl_map *map);
+ __isl_give isl_union_set *isl_union_set_apply(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_map *umap);
+ __isl_give isl_basic_map *isl_basic_map_apply_domain(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_basic_map *isl_basic_map_apply_range(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_map *isl_map_apply_domain(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_map *isl_map_apply_range(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_apply_domain(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+ __isl_give isl_union_map *isl_union_map_apply_range(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_set_apply_pw_qpolynomial_fold(
+ __isl_take isl_set *set,
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_map_apply_pw_qpolynomial_fold(
+ __isl_take isl_map *map,
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_set_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ int *tight);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_map_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ int *tight);
+
+The functions taking a map
+compose the given map with the given piecewise quasipolynomial reduction.
+That is, compute a bound (of the same type as C<pwf> or C<upwf> itself)
+over all elements in the intersection of the range of the map
+and the domain of the piecewise quasipolynomial reduction
+as a function of an element in the domain of the map.
+The functions taking a set compute a bound over all elements in the
+intersection of the set and the domain of the
+piecewise quasipolynomial reduction.
+
+=item * Preimage
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *
+ isl_basic_set_preimage_multi_aff(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_set *isl_set_preimage_multi_aff(
+ __isl_take isl_set *set,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_set *isl_set_preimage_pw_multi_aff(
+ __isl_take isl_set *set,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_set *isl_set_preimage_multi_pw_aff(
+ __isl_take isl_set *set,
+ __isl_take isl_multi_pw_aff *mpa);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *
+ isl_union_set_preimage_multi_aff(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_union_set *
+ isl_union_set_preimage_pw_multi_aff(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_union_set *
+ isl_union_set_preimage_union_pw_multi_aff(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_multi_aff *upma);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *
+ isl_basic_map_preimage_domain_multi_aff(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_map *isl_map_preimage_domain_multi_aff(
+ __isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_map *isl_map_preimage_range_multi_aff(
+ __isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_map *
+ isl_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_map *map,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_map *
+ isl_map_preimage_range_pw_multi_aff(
+ __isl_take isl_map *map,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_map *
+ isl_map_preimage_domain_multi_pw_aff(
+ __isl_take isl_map *map,
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_basic_map *
+ isl_basic_map_preimage_range_multi_aff(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_multi_aff *ma);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *
+ isl_union_map_preimage_domain_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_union_map *
+ isl_union_map_preimage_range_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_union_map *
+ isl_union_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_union_map *
+ isl_union_map_preimage_range_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_union_map *
+ isl_union_map_preimage_domain_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_union_map *
+ isl_union_map_preimage_range_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma);
+
+These functions compute the preimage of the given set or map domain/range under
+the given function. In other words, the expression is plugged
+into the set description or into the domain/range of the map.
+
+=item * Pullback
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_pullback_aff(
+ __isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ __isl_give isl_aff *isl_aff_pullback_multi_aff(
+ __isl_take isl_aff *aff,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_aff(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_multi_aff *ma);
+ __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_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+ __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_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_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);
+ __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_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);
+
+These functions precompose the first expression by the second function.
+In other words, the second function is plugged
+into the first expression.
+
+=item * Locus
+
+ #include <isl/aff.h>
+ __isl_give isl_basic_set *isl_aff_le_basic_set(
+ __isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ __isl_give isl_basic_set *isl_aff_ge_basic_set(
+ __isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ __isl_give isl_set *isl_pw_aff_eq_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_set *isl_pw_aff_ne_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_set *isl_pw_aff_le_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_set *isl_pw_aff_lt_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_set *isl_pw_aff_ge_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_set *isl_pw_aff_gt_set(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+
+ __isl_give isl_set *isl_multi_aff_lex_le_set(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+ __isl_give isl_set *isl_multi_aff_lex_ge_set(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+
+ __isl_give isl_set *isl_pw_aff_list_eq_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+ __isl_give isl_set *isl_pw_aff_list_ne_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+ __isl_give isl_set *isl_pw_aff_list_le_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+ __isl_give isl_set *isl_pw_aff_list_lt_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+ __isl_give isl_set *isl_pw_aff_list_ge_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+ __isl_give isl_set *isl_pw_aff_list_gt_set(
+ __isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+
+The function C<isl_aff_ge_basic_set> returns a basic set
+containing those elements in the shared space
+of C<aff1> and C<aff2> where C<aff1> is greater than or equal to C<aff2>.
+The function C<isl_pw_aff_ge_set> returns a set
+containing those elements in the shared domain
+of C<pwaff1> and C<pwaff2> where C<pwaff1> is
+greater than or equal to C<pwaff2>.
+The function C<isl_multi_aff_lex_le_set> returns a set
+containing those elements in the shared domain space
+where C<ma1> is lexicographically smaller than or
+equal to C<ma2>.
+The functions operating on C<isl_pw_aff_list> apply the corresponding
+C<isl_pw_aff> function to each pair of elements in the two lists.
+
+=item * Cartesian Product
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_product(
+ __isl_take isl_space *space1,
+ __isl_take isl_space *space2);
+ __isl_give isl_space *isl_space_domain_product(
+ __isl_take isl_space *space1,
+ __isl_take isl_space *space2);
+ __isl_give isl_space *isl_space_range_product(
+ __isl_take isl_space *space1,
+ __isl_take isl_space *space2);
+
+The functions
+C<isl_space_product>, C<isl_space_domain_product>
+and C<isl_space_range_product> take pairs or relation spaces and
+produce a single relations space, where either the domain, the range
+or both domain and range are wrapped spaces of relations between
+the domains and/or ranges of the input spaces.
+If the product is only constructed over the domain or the range
+then the ranges or the domains of the inputs should be the same.
+The function C<isl_space_product> also accepts a pair of set spaces,
+in which case it returns a wrapped space of a relation between the
+two input spaces.
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_set_product(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_domain_product(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_basic_map *isl_basic_map_range_product(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_basic_map *isl_basic_map_product(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_map *isl_map_domain_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_map *isl_map_range_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_map *isl_map_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_product(
+ __isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+
+ #include <isl/union_map.h>
+ __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_range_product(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+ __isl_give isl_union_map *isl_union_map_product(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_range_product(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
+ __isl_give isl_multi_val *isl_multi_val_product(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_range_product(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+ __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_pw_aff *
+ isl_multi_pw_aff_range_product(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_product(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __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_give isl_pw_multi_aff *isl_pw_multi_aff_product(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+
+The above functions compute the cross product of the given
+sets, relations or functions. The domains and ranges of the results
+are wrapped maps between domains and ranges of the inputs.
+To obtain a ``flat'' product, use the following functions
+instead.
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_flat_product(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+ __isl_give isl_set *isl_set_flat_product(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_flat_range_product(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_map *isl_map_flat_domain_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_map *isl_map_flat_range_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+ __isl_give isl_basic_map *isl_basic_map_flat_product(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+ __isl_give isl_map *isl_map_flat_product(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *
+ isl_union_map_flat_range_product(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_flat_range_product(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_aff *mv2);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_flat_range_product(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+ __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_give isl_multi_pw_aff *
+ isl_multi_pw_aff_flat_range_product(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __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);
+
+ #include <isl/space.h>
+ __isl_give isl_space *isl_space_factor_domain(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_factor_range(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_domain_factor_domain(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_domain_factor_range(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_range_factor_domain(
+ __isl_take isl_space *space);
+ __isl_give isl_space *isl_space_range_factor_range(
+ __isl_take isl_space *space);
+
+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
+from the result using the following functions.
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_map_factor_domain(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_factor_range(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_domain_factor_domain(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_domain_factor_range(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_range_factor_domain(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_range_factor_range(
+ __isl_take isl_map *map);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_factor_domain(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *isl_union_map_factor_range(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *
+ isl_union_map_domain_factor_domain(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *
+ isl_union_map_domain_factor_range(
+ __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_range_factor_domain(
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_val *
+ isl_multi_val_range_factor_range(
+ __isl_take isl_multi_val *mv);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *
+ isl_multi_aff_range_factor_domain(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_aff *
+ isl_multi_aff_range_factor_range(
+ __isl_take isl_multi_aff *ma);
+ __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);
+
+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.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_range_splice(
+ __isl_take isl_multi_val *mv1, unsigned pos,
+ __isl_take isl_multi_val *mv2);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_range_splice(
+ __isl_take isl_multi_aff *ma1, unsigned pos,
+ __isl_take isl_multi_aff *ma2);
+ __isl_give isl_multi_aff *isl_multi_aff_splice(
+ __isl_take isl_multi_aff *ma1,
+ unsigned in_pos, unsigned out_pos,
+ __isl_take isl_multi_aff *ma2);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_range_splice(
+ __isl_take isl_multi_pw_aff *mpa1, unsigned pos,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_splice(
+ __isl_take isl_multi_pw_aff *mpa1,
+ unsigned in_pos, unsigned out_pos,
+ __isl_take isl_multi_pw_aff *mpa2);
+
+=item * Simplification
+
+When applied to a set or relation,
+the gist operation returns a set or relation that has the
+same intersection with the context as the input set or relation.
+Any implicit equality in the intersection is made explicit in the result,
+while all inequalities that are redundant with respect to the intersection
+are removed.
+In case of union sets and relations, the gist operation is performed
+per space.
+
+When applied to a function,
+the gist operation applies the set gist operation to each of
+the cells in the domain of the input piecewise expression.
+The context is also exploited
+to simplify the expression associated to each cell.
+
+ #include <isl/set.h>
+ __isl_give isl_basic_set *isl_basic_set_gist(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *context);
+ __isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
+ __isl_take isl_set *context);
+ __isl_give isl_set *isl_set_gist_params(
+ __isl_take isl_set *set,
+ __isl_take isl_set *context);
+
+ #include <isl/map.h>
+ __isl_give isl_basic_map *isl_basic_map_gist(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_map *context);
+ __isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+ __isl_take isl_map *context);
+ __isl_give isl_map *isl_map_gist_params(
+ __isl_take isl_map *map,
+ __isl_take isl_set *context);
+ __isl_give isl_map *isl_map_gist_domain(
+ __isl_take isl_map *map,
+ __isl_take isl_set *context);
+ __isl_give isl_map *isl_map_gist_range(
+ __isl_take isl_map *map,
+ __isl_take isl_set *context);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_gist(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_set *context);
+ __isl_give isl_union_set *isl_union_set_gist_params(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_set *set);
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *isl_union_map_gist(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_map *context);
+ __isl_give isl_union_map *isl_union_map_gist_params(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_set *set);
+ __isl_give isl_union_map *isl_union_map_gist_domain(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_map *isl_union_map_gist_range(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_set *uset);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_gist_params(
+ __isl_take isl_aff *aff,
+ __isl_take isl_set *context);
+ __isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
+ __isl_take isl_set *context);
+ __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,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_aff *isl_pw_aff_gist_params(
+ __isl_take isl_pw_aff *pwaff,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_aff *isl_pw_aff_gist(
+ __isl_take isl_pw_aff *pwaff,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist_params(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_set *set);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_set *set);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist_params(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_set *set);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_gist_params(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_set *context);
+ __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);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
+ __isl_take isl_qpolynomial *qp,
+ __isl_take isl_set *context);
+ __isl_give isl_qpolynomial *isl_qpolynomial_gist(
+ __isl_take isl_qpolynomial *qp,
+ __isl_take isl_set *context);
+ __isl_give isl_qpolynomial_fold *
+ isl_qpolynomial_fold_gist_params(
+ __isl_take isl_qpolynomial_fold *fold,
+ __isl_take isl_set *context);
+ __isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
+ __isl_take isl_qpolynomial_fold *fold,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist_params(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_gist(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_set *context);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_gist_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_set *context);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_gist_params(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_set *context);
+ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_gist(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_union_set *context);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_gist(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *context);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_gist_params(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_set *context);
+
+=item * Binary Arithmethic Operations
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_add(
+ __isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ __isl_give isl_multi_aff *isl_multi_aff_add(
+ __isl_take isl_multi_aff *maff1,
+ __isl_take isl_multi_aff *maff2);
+ __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_multi_aff *isl_pw_multi_aff_add(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+ __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_pw_aff *isl_pw_aff_min(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_pw_aff *isl_pw_aff_max(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_aff *isl_aff_sub(
+ __isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ __isl_give isl_multi_aff *isl_multi_aff_sub(
+ __isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+ __isl_give isl_pw_aff *isl_pw_aff_sub(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_sub(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+
+C<isl_aff_sub> subtracts the second argument from the first.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_add(
+ __isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_disjoint(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2);
+ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_add(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+ __isl_give isl_qpolynomial *isl_qpolynomial_sub(
+ __isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sub(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_sub(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+ __isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fold(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_fold(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf1,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf2);
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_union_add(
+ __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+ __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_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);
+ __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);
+
+The function C<isl_pw_aff_union_max> computes a piecewise quasi-affine
+expression with a domain that is the union of those of C<pwaff1> and
+C<pwaff2> and such that on each cell, the quasi-affine expression is
+the maximum of those of C<pwaff1> and C<pwaff2>. If only one of
+C<pwaff1> or C<pwaff2> is defined on a given cell, then the
+associated expression is the defined one.
+This in contrast to the C<isl_pw_aff_max> function, which is
+only defined on the shared definition domain of the arguments.
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_add_val(
+ __isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+ __isl_give isl_multi_val *isl_multi_val_mod_val(
+ __isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+ __isl_give isl_multi_val *isl_multi_val_scale_val(
+ __isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+ __isl_give isl_multi_val *isl_multi_val_scale_down_val(
+ __isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+
+ #include <isl/aff.h>
+ __isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *mod);
+ __isl_give isl_pw_aff *isl_pw_aff_mod_val(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_val *mod);
+ __isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v);
+ __isl_give isl_multi_aff *isl_multi_aff_scale_val(
+ __isl_take isl_multi_aff *ma,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_aff *isl_pw_aff_scale_val(
+ __isl_take isl_pw_aff *pa, __isl_take isl_val *v);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_scale_val(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_val(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_scale_val(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_val *val);
+ __isl_give isl_aff *isl_aff_scale_down_ui(
+ __isl_take isl_aff *aff, unsigned f);
+ __isl_give isl_aff *isl_aff_scale_down_val(
+ __isl_take isl_aff *aff, __isl_take isl_val *v);
+ __isl_give isl_multi_aff *isl_multi_aff_scale_down_val(
+ __isl_take isl_multi_aff *ma,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_aff *isl_pw_aff_scale_down_val(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_val *f);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_scale_down_val(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_val(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_scale_down_val(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_val *val);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
+ __isl_take isl_qpolynomial *qp,
+ __isl_take isl_val *v);
+ __isl_give isl_qpolynomial_fold *
+ isl_qpolynomial_fold_scale_val(
+ __isl_take isl_qpolynomial_fold *fold,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_scale_val(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_scale_val(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_scale_val(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_scale_val(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_val *v);
+ __isl_give isl_qpolynomial *
+ isl_qpolynomial_scale_down_val(
+ __isl_take isl_qpolynomial *qp,
+ __isl_take isl_val *v);
+ __isl_give isl_qpolynomial_fold *
+ isl_qpolynomial_fold_scale_down_val(
+ __isl_take isl_qpolynomial_fold *fold,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_scale_down_val(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_val *v);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_scale_down_val(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_scale_down_val(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_scale_down_val(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_val *v);
+
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_scale_multi_val(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
+ __isl_give isl_multi_val *
+ isl_multi_val_scale_down_multi_val(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_scale_multi_val(
+ __isl_take isl_multi_aff *ma,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_scale_multi_val(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_scale_multi_val(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_multi_val *mv);
+ __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_give isl_multi_aff *
+ isl_multi_aff_scale_down_multi_val(
+ __isl_take isl_multi_aff *ma,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_scale_down_multi_val(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_multi_val *mv);
+
+C<isl_multi_aff_scale_multi_val> scales the elements of C<ma>
+by the corresponding elements of C<mv>.
+
+ #include <isl/aff.h>
+ __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_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_give isl_pw_aff *isl_pw_aff_tdiv_q(
+ __isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+ __isl_give isl_pw_aff *isl_pw_aff_tdiv_r(
+ __isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+
+When multiplying two affine expressions, at least one of the two needs
+to be a constant. Similarly, when dividing an affine expression by another,
+the second expression needs to be a constant.
+C<isl_pw_aff_tdiv_q> computes the quotient of an integer division with
+rounding towards zero. C<isl_pw_aff_tdiv_r> computes the corresponding
+remainder.
+
+ #include <isl/polynomial.h>
+ __isl_give isl_qpolynomial *isl_qpolynomial_mul(
+ __isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+ __isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+ __isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+
+=back
+
+=head3 Lexicographic Optimization
+
+Given a (basic) set C<set> (or C<bset>) and a zero-dimensional domain C<dom>,
+the following functions
+compute a set that contains the lexicographic minimum or maximum
+of the elements in C<set> (or C<bset>) for those values of the parameters
+that satisfy C<dom>.
+If C<empty> is not C<NULL>, then C<*empty> is assigned a set
+that contains the parameter values in C<dom> for which C<set> (or C<bset>)
+has no elements.
+In other words, the union of the parameter values
+for which the result is non-empty and of C<*empty>
+is equal to C<dom>.
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_basic_set_partial_lexmin(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_set *isl_basic_set_partial_lexmax(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_set *isl_set_partial_lexmin(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_set *isl_set_partial_lexmax(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+
+Given a (basic) set C<set> (or C<bset>), the following functions simply
+return a set containing the lexicographic minimum or maximum
+of the elements in C<set> (or C<bset>).
+In case of union sets, the optimum is computed per space.
+
+ #include <isl/set.h>
+ __isl_give isl_set *isl_basic_set_lexmin(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_basic_set_lexmax(
+ __isl_take isl_basic_set *bset);
+ __isl_give isl_set *isl_set_lexmin(
+ __isl_take isl_set *set);
+ __isl_give isl_set *isl_set_lexmax(
+ __isl_take isl_set *set);
+ __isl_give isl_union_set *isl_union_set_lexmin(
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_set *isl_union_set_lexmax(
+ __isl_take isl_union_set *uset);
+
+Given a (basic) relation C<map> (or C<bmap>) and a domain C<dom>,
+the following functions
+compute a relation that maps each element of C<dom>
+to the single lexicographic minimum or maximum
+of the elements that are associated to that same
+element in C<map> (or C<bmap>).
+If C<empty> is not C<NULL>, then C<*empty> is assigned a set
+that contains the elements in C<dom> that do not map
+to any elements in C<map> (or C<bmap>).
+In other words, the union of the domain of the result and of C<*empty>
+is equal to C<dom>.
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_basic_map_partial_lexmax(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_map *isl_basic_map_partial_lexmin(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_map *isl_map_partial_lexmax(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_map *isl_map_partial_lexmin(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+
+Given a (basic) map C<map> (or C<bmap>), the following functions simply
+return a map mapping each element in the domain of
+C<map> (or C<bmap>) to the lexicographic minimum or maximum
+of all elements associated to that element.
+In case of union relations, the optimum is computed per space.
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_basic_map_lexmin(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_basic_map_lexmax(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_map *isl_map_lexmin(
+ __isl_take isl_map *map);
+ __isl_give isl_map *isl_map_lexmax(
+ __isl_take isl_map *map);
+ __isl_give isl_union_map *isl_union_map_lexmin(
+ __isl_take isl_union_map *umap);
+ __isl_give isl_union_map *isl_union_map_lexmax(
+ __isl_take isl_union_map *umap);
+
+The following functions return their result in the form of
+a piecewise multi-affine expression,
+but are otherwise equivalent to the corresponding functions
+returning a basic set or relation.
+
+ #include <isl/set.h>
+ __isl_give isl_pw_multi_aff *
+ isl_basic_set_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_pw_multi_aff *
+ isl_basic_set_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_pw_multi_aff *isl_set_lexmin_pw_multi_aff(
+ __isl_take isl_set *set);
+ __isl_give isl_pw_multi_aff *isl_set_lexmax_pw_multi_aff(
+ __isl_take isl_set *set);
+
+ #include <isl/map.h>
+ __isl_give isl_pw_multi_aff *
+ isl_basic_map_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap);
+ __isl_give isl_pw_multi_aff *
+ isl_basic_map_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_pw_multi_aff *
+ isl_basic_map_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+ __isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
+ __isl_take isl_map *map);
+ __isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
+ __isl_take isl_map *map);
+
+The following functions return the lexicographic minimum or maximum
+on the shared domain of the inputs and the single defined function
+on those parts of the domain where only a single function is defined.
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+
+=head2 Ternary Operations
+
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_cond(
+ __isl_take isl_pw_aff *cond,
+ __isl_take isl_pw_aff *pwaff_true,
+ __isl_take isl_pw_aff *pwaff_false);
+
+The function C<isl_pw_aff_cond> performs a conditional operator
+and returns an expression that is equal to C<pwaff_true>
+for elements where C<cond> is non-zero and equal to C<pwaff_false> for elements
+where C<cond> is zero.
+
+=head2 Lists
+
+Lists are defined over several element types, including
+C<isl_val>, C<isl_id>, C<isl_aff>, C<isl_pw_aff>, C<isl_constraint>,
+C<isl_basic_set>, C<isl_set>, C<isl_ast_expr> and C<isl_ast_node>.
+Here we take lists of C<isl_set>s as an example.
+Lists can be created, copied, modified and freed using the following functions.
+
+ #include <isl/set.h>
+ __isl_give isl_set_list *isl_set_list_from_set(
+ __isl_take isl_set *el);
+ __isl_give isl_set_list *isl_set_list_alloc(
+ isl_ctx *ctx, int n);
+ __isl_give isl_set_list *isl_set_list_copy(
+ __isl_keep isl_set_list *list);
+ __isl_give isl_set_list *isl_set_list_insert(
+ __isl_take isl_set_list *list, unsigned pos,
+ __isl_take isl_set *el);
+ __isl_give isl_set_list *isl_set_list_add(
+ __isl_take isl_set_list *list,
+ __isl_take isl_set *el);
+ __isl_give isl_set_list *isl_set_list_drop(
+ __isl_take isl_set_list *list,
+ unsigned first, unsigned n);
+ __isl_give isl_set_list *isl_set_list_set_set(
+ __isl_take isl_set_list *list, int index,
+ __isl_take isl_set *set);
+ __isl_give isl_set_list *isl_set_list_concat(
+ __isl_take isl_set_list *list1,
+ __isl_take isl_set_list *list2);
+ __isl_give isl_set_list *isl_set_list_sort(
+ __isl_take isl_set_list *list,
+ int (*cmp)(__isl_keep isl_set *a,
+ __isl_keep isl_set *b, void *user),
+ void *user);
+ __isl_null isl_set_list *isl_set_list_free(
+ __isl_take isl_set_list *list);
+
+C<isl_set_list_alloc> creates an empty list with a capacity for
+C<n> elements. C<isl_set_list_from_set> creates a list with a single
+element.
+
+Lists can be inspected using the following functions.
+
+ #include <isl/set.h>
+ int isl_set_list_n_set(__isl_keep isl_set_list *list);
+ __isl_give isl_set *isl_set_list_get_set(
+ __isl_keep isl_set_list *list, int index);
+ int isl_set_list_foreach(__isl_keep isl_set_list *list,
+ int (*fn)(__isl_take isl_set *el, void *user),
+ void *user);
+ int isl_set_list_foreach_scc(__isl_keep isl_set_list *list,
+ int (*follows)(__isl_keep isl_set *a,
+ __isl_keep isl_set *b, void *user),
+ void *follows_user
+ int (*fn)(__isl_take isl_set *el, void *user),
+ void *fn_user);
+
+The function C<isl_set_list_foreach_scc> calls C<fn> on each of the
+strongly connected components of the graph with as vertices the elements
+of C<list> and a directed edge from vertex C<b> to vertex C<a>
+iff C<follows(a, b)> returns C<1>. The callbacks C<follows> and C<fn>
+should return C<-1> on error.
+
+Lists can be printed using
+
+ #include <isl/set.h>
+ __isl_give isl_printer *isl_printer_print_set_list(
+ __isl_take isl_printer *p,
+ __isl_keep isl_set_list *list);
+
+=head2 Associative arrays
+
+Associative arrays map isl objects of a specific type to isl objects
+of some (other) specific type. They are defined for several pairs
+of types, including (C<isl_map>, C<isl_basic_set>),
+(C<isl_id>, C<isl_ast_expr>) and.
+(C<isl_id>, C<isl_pw_aff>).
+Here, we take associative arrays that map C<isl_id>s to C<isl_ast_expr>s
+as an example.
+
+Associative arrays can be created, copied and freed using
+the following functions.
+
+ #include <isl/id_to_ast_expr.h>
+ __isl_give id_to_ast_expr *isl_id_to_ast_expr_alloc(
+ isl_ctx *ctx, int min_size);
+ __isl_give id_to_ast_expr *isl_id_to_ast_expr_copy(
+ __isl_keep id_to_ast_expr *id2expr);
+ __isl_null id_to_ast_expr *isl_id_to_ast_expr_free(
+ __isl_take id_to_ast_expr *id2expr);
+
+The C<min_size> argument to C<isl_id_to_ast_expr_alloc> can be used
+to specify the expected size of the associative array.
+The associative array will be grown automatically as needed.
+
+Associative arrays can be inspected using the following functions.
+
+ #include <isl/id_to_ast_expr.h>
+ int isl_id_to_ast_expr_has(
+ __isl_keep id_to_ast_expr *id2expr,
+ __isl_keep isl_id *key);
+ __isl_give isl_ast_expr *isl_id_to_ast_expr_get(
+ __isl_keep id_to_ast_expr *id2expr,
+ __isl_take isl_id *key);
+ int isl_id_to_ast_expr_foreach(
+ __isl_keep id_to_ast_expr *id2expr,
+ int (*fn)(__isl_take isl_id *key,
+ __isl_take isl_ast_expr *val, void *user),
+ void *user);
+
+They can be modified using the following function.
+
+ #include <isl/id_to_ast_expr.h>
+ __isl_give id_to_ast_expr *isl_id_to_ast_expr_set(
+ __isl_take id_to_ast_expr *id2expr,
+ __isl_take isl_id *key,
+ __isl_take isl_ast_expr *val);
+ __isl_give id_to_ast_expr *isl_id_to_ast_expr_drop(
+ __isl_take id_to_ast_expr *id2expr,
+ __isl_take isl_id *key);
+
+Associative arrays can be printed using the following function.
+
+ #include <isl/id_to_ast_expr.h>
+ __isl_give isl_printer *isl_printer_print_id_to_ast_expr(
+ __isl_take isl_printer *p,
+ __isl_keep id_to_ast_expr *id2expr);
+
+=head2 Vectors
+
+Vectors can be created, copied and freed using the following functions.
+
+ #include <isl/vec.h>
+ __isl_give isl_vec *isl_vec_alloc(isl_ctx *ctx,
+ unsigned size);
+ __isl_give isl_vec *isl_vec_copy(__isl_keep isl_vec *vec);
+ __isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec);
+
+Note that the elements of a newly created vector may have arbitrary values.
+The elements can be changed and inspected using the following functions.
+
+ int isl_vec_size(__isl_keep isl_vec *vec);
+ __isl_give isl_val *isl_vec_get_element_val(
+ __isl_keep isl_vec *vec, int pos);
+ __isl_give isl_vec *isl_vec_set_element_si(
+ __isl_take isl_vec *vec, int pos, int v);
+ __isl_give isl_vec *isl_vec_set_element_val(
+ __isl_take isl_vec *vec, int pos,
+ __isl_take isl_val *v);
+ __isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec,
+ int v);
+ __isl_give isl_vec *isl_vec_set_val(
+ __isl_take isl_vec *vec, __isl_take isl_val *v);
+ int isl_vec_cmp_element(__isl_keep isl_vec *vec1,
+ __isl_keep isl_vec *vec2, int pos);
+
+C<isl_vec_get_element> will return a negative value if anything went wrong.
+In that case, the value of C<*v> is undefined.
+
+The following function can be used to concatenate two vectors.
+
+ __isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
+ __isl_take isl_vec *vec2);
+
+=head2 Matrices
+
+Matrices can be created, copied and freed using the following functions.
+
+ #include <isl/mat.h>
+ __isl_give isl_mat *isl_mat_alloc(isl_ctx *ctx,
+ unsigned n_row, unsigned n_col);
+ __isl_give isl_mat *isl_mat_copy(__isl_keep isl_mat *mat);
+ __isl_null isl_mat *isl_mat_free(__isl_take isl_mat *mat);
+
+Note that the elements of a newly created matrix may have arbitrary values.
+The elements can be changed and inspected using the following functions.
+
+ int isl_mat_rows(__isl_keep isl_mat *mat);
+ int isl_mat_cols(__isl_keep isl_mat *mat);
+ __isl_give isl_val *isl_mat_get_element_val(
+ __isl_keep isl_mat *mat, int row, int col);
+ __isl_give isl_mat *isl_mat_set_element_si(__isl_take isl_mat *mat,
+ int row, int col, int v);
+ __isl_give isl_mat *isl_mat_set_element_val(
+ __isl_take isl_mat *mat, int row, int col,
+ __isl_take isl_val *v);
+
+C<isl_mat_get_element> will return a negative value if anything went wrong.
+In that case, the value of C<*v> is undefined.
+
+The following function can be used to compute the (right) inverse
+of a matrix, i.e., a matrix such that the product of the original
+and the inverse (in that order) is a multiple of the identity matrix.
+The input matrix is assumed to be of full row-rank.
+
+ __isl_give isl_mat *isl_mat_right_inverse(__isl_take isl_mat *mat);
+
+The following function can be used to compute the (right) kernel
+(or null space) of a matrix, i.e., a matrix such that the product of
+the original and the kernel (in that order) is the zero matrix.
+
+ __isl_give isl_mat *isl_mat_right_kernel(__isl_take isl_mat *mat);
+
+=head2 Bounds on Piecewise Quasipolynomials and Piecewise Quasipolynomial Reductions
+
+The following functions determine
+an upper or lower bound on a quasipolynomial over its domain.
+
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_bound(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_fold type, int *tight);
+
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_bound(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_fold type, int *tight);
+
+The C<type> argument may be either C<isl_fold_min> or C<isl_fold_max>.
+If C<tight> is not C<NULL>, then C<*tight> is set to C<1>
+is the returned bound is known be tight, i.e., for each value
+of the parameters there is at least
+one element in the domain that reaches the bound.
+If the domain of C<pwqp> is not wrapping, then the bound is computed
+over all elements in that domain and the result has a purely parametric
+domain. If the domain of C<pwqp> is wrapping, then the bound is
+computed over the range of the wrapped relation. The domain of the
+wrapped relation becomes the domain of the result.
+
+=head2 Parametric Vertex Enumeration
+
+The parametric vertex enumeration described in this section
+is mainly intended to be used internally and by the C<barvinok>
+library.
+
+ #include <isl/vertices.h>
+ __isl_give isl_vertices *isl_basic_set_compute_vertices(
+ __isl_keep isl_basic_set *bset);
+
+The function C<isl_basic_set_compute_vertices> performs the
+actual computation of the parametric vertices and the chamber
+decomposition and store the result in an C<isl_vertices> object.
+This information can be queried by either iterating over all
+the vertices or iterating over all the chambers or cells
+and then iterating over all vertices that are active on the chamber.
+
+ int isl_vertices_foreach_vertex(
+ __isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user),
+ void *user);
+
+ int isl_vertices_foreach_cell(
+ __isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_cell *cell, void *user),
+ void *user);
+ int isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user),
+ void *user);
+
+Other operations that can be performed on an C<isl_vertices> object are
+the following.
+
+ int isl_vertices_get_n_vertices(
+ __isl_keep isl_vertices *vertices);
+ void isl_vertices_free(__isl_take isl_vertices *vertices);
+
+Vertices can be inspected and destroyed using the following functions.
+
+ int isl_vertex_get_id(__isl_keep isl_vertex *vertex);
+ __isl_give isl_basic_set *isl_vertex_get_domain(
+ __isl_keep isl_vertex *vertex);
+ __isl_give isl_multi_aff *isl_vertex_get_expr(
+ __isl_keep isl_vertex *vertex);
+ void isl_vertex_free(__isl_take isl_vertex *vertex);
+
+C<isl_vertex_get_expr> returns a multiple quasi-affine expression
+describing the vertex in terms of the parameters,
+while C<isl_vertex_get_domain> returns the activity domain
+of the vertex.
+
+Chambers can be inspected and destroyed using the following functions.
+
+ __isl_give isl_basic_set *isl_cell_get_domain(
+ __isl_keep isl_cell *cell);
+ void isl_cell_free(__isl_take isl_cell *cell);
+
+=head1 Polyhedral Compilation Library
+
+This section collects functionality in C<isl> that has been specifically
+designed for use during polyhedral compilation.
+
+=head2 Dependence Analysis
+
+C<isl> contains specialized functionality for performing
+array dataflow analysis. That is, given a I<sink> access relation
+and a collection of possible I<source> access relations,
+C<isl> can compute relations that describe
+for each iteration of the sink access, which iteration
+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 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>
+accesses, then there will be a dependence from the last
+I<must> access B<and> from any I<may> access that follows
+this last I<must> access.
+In particular, if I<all> sources are I<may> accesses,
+then memory based dependence analysis is performed.
+If, on the other hand, all sources are I<must> accesses,
+then value based dependence analysis is performed.
+
+ #include <isl/flow.h>
+
+ typedef int (*isl_access_level_before)(void *first, void *second);
+
+ __isl_give isl_access_info *isl_access_info_alloc(
+ __isl_take isl_map *sink,
+ void *sink_user, isl_access_level_before fn,
+ int max_source);
+ __isl_give isl_access_info *isl_access_info_add_source(
+ __isl_take isl_access_info *acc,
+ __isl_take isl_map *source, int must,
+ void *source_user);
+ __isl_null isl_access_info *isl_access_info_free(
+ __isl_take isl_access_info *acc);
+
+ __isl_give isl_flow *isl_access_info_compute_flow(
+ __isl_take isl_access_info *acc);
+
+ int isl_flow_foreach(__isl_keep isl_flow *deps,
+ int (*fn)(__isl_take isl_map *dep, int must,
+ void *dep_user, void *user),
+ void *user);
+ __isl_give isl_map *isl_flow_get_no_source(
+ __isl_keep isl_flow *deps, int must);
+ void isl_flow_free(__isl_take isl_flow *deps);
+
+The function C<isl_access_info_compute_flow> performs the actual
+dependence analysis. The other functions are used to construct
+the input for this function or to read off the output.
+
+The input is collected in an C<isl_access_info>, which can
+be created through a call to C<isl_access_info_alloc>.
+The arguments to this functions are the sink access relation
+C<sink>, a token C<sink_user> used to identify the sink
+access to the user, a callback function for specifying the
+relative order of source and sink accesses, and the number
+of source access relations that will be added.
+The callback function has type C<int (*)(void *first, void *second)>.
+The function is called with two user supplied tokens identifying
+either a source or the sink and it should return the shared nesting
+level and the relative order of the two accesses.
+In particular, let I<n> be the number of loops shared by
+the two accesses. If C<first> precedes C<second> textually,
+then the function should return I<2 * n + 1>; otherwise,
+it should return I<2 * n>.
+The sources can be added to the C<isl_access_info> by performing
+(at most) C<max_source> calls to C<isl_access_info_add_source>.
+C<must> indicates whether the source is a I<must> access
+or a I<may> access. Note that a multi-valued access relation
+should only be marked I<must> if every iteration in the domain
+of the relation accesses I<all> elements in its image.
+The C<source_user> token is again used to identify
+the source access. The range of the source access relation
+C<source> should have the same dimension as the range
+of the sink access relation.
+The C<isl_access_info_free> function should usually not be
+called explicitly, because it is called implicitly by
+C<isl_access_info_compute_flow>.
+
+The result of the dependence analysis is collected in an
+C<isl_flow>. There may be elements of
+the sink access for which no preceding source access could be
+found or for which all preceding sources are I<may> accesses.
+The relations containing these elements can be obtained through
+calls to C<isl_flow_get_no_source>, the first with C<must> set
+and the second with C<must> unset.
+In the case of standard flow dependence analysis,
+with the sink a read and the sources I<must> writes,
+the first relation corresponds to the reads from uninitialized
+array elements and the second relation is empty.
+The actual flow dependences can be extracted using
+C<isl_flow_foreach>. This function will call the user-specified
+callback function C<fn> for each B<non-empty> dependence between
+a source and the sink. The callback function is called
+with four arguments, the actual flow dependence relation
+mapping source iterations to sink iterations, a boolean that
+indicates whether it is a I<must> or I<may> dependence, a token
+identifying the source and an additional C<void *> with value
+equal to the third argument of the C<isl_flow_foreach> call.
+A dependence is marked I<must> if it originates from a I<must>
+source and if it is not followed by any I<may> sources.
+
+After finishing with an C<isl_flow>, the user should call
+C<isl_flow_free> to free all associated memory.
+
+A higher-level interface to dependence analysis is provided
+by the following function.
+
+ #include <isl/flow.h>
+
+ 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,
+ __isl_take isl_union_map *schedule,
+ __isl_give isl_union_map **must_dep,
+ __isl_give isl_union_map **may_dep,
+ __isl_give isl_union_map **must_no_source,
+ __isl_give isl_union_map **may_no_source);
+
+The arrays are identified by the tuple names of the ranges
+of the accesses. The iteration domains by the tuple names
+of the domains of the accesses and of the schedule.
+The relative order of the iteration domains is given by the
+schedule. The relations returned through C<must_no_source>
+and C<may_no_source> are subsets of C<sink>.
+Any of C<must_dep>, C<may_dep>, C<must_no_source>
+or C<may_no_source> may be C<NULL>, but a C<NULL> value for
+any of the other arguments is treated as an error.
+
+=head3 Interaction with Dependence Analysis
+
+During the dependence analysis, we frequently need to perform
+the following operation. Given a relation between sink iterations
+and potential source iterations from a particular source domain,
+what is the last potential source iteration corresponding to each
+sink iteration. It can sometimes be convenient to adjust
+the set of potential source iterations before or after each such operation.
+The prototypical example is fuzzy array dataflow analysis,
+where we need to analyze if, based on data-dependent constraints,
+the sink iteration can ever be executed without one or more of
+the corresponding potential source iterations being executed.
+If so, we can introduce extra parameters and select an unknown
+but fixed source iteration from the potential source iterations.
+To be able to perform such manipulations, C<isl> provides the following
+function.
+
+ #include <isl/flow.h>
+
+ typedef __isl_give isl_restriction *(*isl_access_restrict)(
+ __isl_keep isl_map *source_map,
+ __isl_keep isl_set *sink, void *source_user,
+ void *user);
+ __isl_give isl_access_info *isl_access_info_set_restrict(
+ __isl_take isl_access_info *acc,
+ isl_access_restrict fn, void *user);
+
+The function C<isl_access_info_set_restrict> should be called
+before calling C<isl_access_info_compute_flow> and registers a callback function
+that will be called any time C<isl> is about to compute the last
+potential source. The first argument is the (reverse) proto-dependence,
+mapping sink iterations to potential source iterations.
+The second argument represents the sink iterations for which
+we want to compute the last source iteration.
+The third argument is the token corresponding to the source
+and the final argument is the token passed to C<isl_access_info_set_restrict>.
+The callback is expected to return a restriction on either the input or
+the output of the operation computing the last potential source.
+If the input needs to be restricted then restrictions are needed
+for both the source and the sink iterations. The sink iterations
+and the potential source iterations will be intersected with these sets.
+If the output needs to be restricted then only a restriction on the source
+iterations is required.
+If any error occurs, the callback should return C<NULL>.
+An C<isl_restriction> object can be created, freed and inspected
+using the following functions.
+
+ #include <isl/flow.h>
+
+ __isl_give isl_restriction *isl_restriction_input(
+ __isl_take isl_set *source_restr,
+ __isl_take isl_set *sink_restr);
+ __isl_give isl_restriction *isl_restriction_output(
+ __isl_take isl_set *source_restr);
+ __isl_give isl_restriction *isl_restriction_none(
+ __isl_take isl_map *source_map);
+ __isl_give isl_restriction *isl_restriction_empty(
+ __isl_take isl_map *source_map);
+ __isl_null isl_restriction *isl_restriction_free(
+ __isl_take isl_restriction *restr);
+
+C<isl_restriction_none> and C<isl_restriction_empty> are special
+cases of C<isl_restriction_input>. C<isl_restriction_none>
+is essentially equivalent to
+
+ isl_restriction_input(isl_set_universe(
+ isl_space_range(isl_map_get_space(source_map))),
+ isl_set_universe(
+ isl_space_domain(isl_map_get_space(source_map))));
+
+whereas C<isl_restriction_empty> is essentially equivalent to
+
+ isl_restriction_input(isl_set_empty(
+ isl_space_range(isl_map_get_space(source_map))),
+ isl_set_universe(
+ isl_space_domain(isl_map_get_space(source_map))));
+
+=head2 Scheduling
+
+B<The functionality described in this section is fairly new
+and may be subject to change.>
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *
+ isl_schedule_constraints_compute_schedule(
+ __isl_take isl_schedule_constraints *sc);
+ __isl_null isl_schedule *isl_schedule_free(
+ __isl_take isl_schedule *sched);
+
+The function C<isl_schedule_constraints_compute_schedule> can be
+used to compute a schedule that satisfies the given schedule constraints.
+These schedule constraints include the iteration domain for which
+a schedule should be computed and dependences between pairs of
+iterations. In particular, these dependences include
+I<validity> dependences and I<proximity> dependences.
+By default, the algorithm used to construct the schedule is similar
+to that of C<Pluto>.
+Alternatively, Feautrier's multi-dimensional scheduling algorithm can
+be selected.
+The generated schedule respects all validity dependences.
+That is, all dependence distances over these dependences in the
+scheduled space are lexicographically positive.
+The default algorithm tries to ensure that the dependence distances
+over coincidence constraints are zero and to minimize the
+dependence distances over proximity dependences.
+Moreover, it tries to obtain sequences (bands) of schedule dimensions
+for groups of domains where the dependence distances over validity
+dependences have only non-negative values.
+When using Feautrier's algorithm, the coincidence and proximity constraints
+are only taken into account during the extension to a
+full-dimensional schedule.
+
+An C<isl_schedule_constraints> object can be constructed
+and manipulated using the following functions.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_copy(
+ __isl_keep isl_schedule_constraints *sc);
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_on_domain(
+ __isl_take isl_union_set *domain);
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_set_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *validity);
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_set_coincidence(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *coincidence);
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_set_proximity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *proximity);
+ __isl_give isl_schedule_constraints *
+ isl_schedule_constraints_set_conditional_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *condition,
+ __isl_take isl_union_map *validity);
+ __isl_null isl_schedule_constraints *
+ isl_schedule_constraints_free(
+ __isl_take isl_schedule_constraints *sc);
+
+The initial C<isl_schedule_constraints> object created by
+C<isl_schedule_constraints_on_domain> does not impose any constraints.
+That is, it has an empty set of dependences.
+The function C<isl_schedule_constraints_set_validity> replaces the
+validity dependences, mapping domain elements I<i> to domain
+elements that should be scheduled after I<i>.
+The function C<isl_schedule_constraints_set_coincidence> replaces the
+coincidence dependences, mapping domain elements I<i> to domain
+elements that should be scheduled together with I<I>, if possible.
+The function C<isl_schedule_constraints_set_proximity> replaces the
+proximity dependences, mapping domain elements I<i> to domain
+elements that should be scheduled either before I<I>
+or as early as possible after I<i>.
+
+The function C<isl_schedule_constraints_set_conditional_validity>
+replaces the conditional validity constraints.
+A conditional validity constraint is only imposed when any of the corresponding
+conditions is satisfied, i.e., when any of them is non-zero.
+That is, the scheduler ensures that within each band if the dependence
+distances over the condition constraints are not all zero
+then all corresponding conditional validity constraints are respected.
+A conditional validity constraint corresponds to a condition
+if the two are adjacent, i.e., if the domain of one relation intersect
+the range of the other relation.
+The typical use case of conditional validity constraints is
+to allow order constraints between live ranges to be violated
+as long as the live ranges themselves are local to the band.
+To allow more fine-grained control over which conditions correspond
+to which conditional validity constraints, the domains and ranges
+of these relations may include I<tags>. That is, the domains and
+ranges of those relation may themselves be wrapped relations
+where the iteration domain appears in the domain of those wrapped relations
+and the range of the wrapped relations can be arbitrarily chosen
+by the user. Conditions and conditional validity constraints are only
+considered adjacent to each other if the entire wrapped relation matches.
+In particular, a relation with a tag will never be considered adjacent
+to a relation without a tag.
+
+The following function computes a schedule directly from
+an iteration domain and validity and proximity dependences
+and is implemented in terms of the functions described above.
+The use of C<isl_union_set_compute_schedule> is discouraged.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_union_set_compute_schedule(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_union_map *validity,
+ __isl_take isl_union_map *proximity);
+
+A mapping from the domains to the scheduled space can be obtained
+from an C<isl_schedule> using the following function.
+
+ __isl_give isl_union_map *isl_schedule_get_map(
+ __isl_keep isl_schedule *sched);
+
+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);
+
+A representation of the schedule as a forest of bands can be obtained
+using the following function.
+
+ __isl_give isl_band_list *isl_schedule_get_band_forest(
+ __isl_keep isl_schedule *schedule);
+
+The individual bands can be visited in depth-first post-order
+using the following function.
+
+ #include <isl/schedule.h>
+ int isl_schedule_foreach_band(
+ __isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_band *band, void *user),
+ void *user);
+
+The list can be manipulated as explained in L<"Lists">.
+The bands inside the list can be copied and freed using the following
+functions.
+
+ #include <isl/band.h>
+ __isl_give isl_band *isl_band_copy(
+ __isl_keep isl_band *band);
+ __isl_null isl_band *isl_band_free(
+ __isl_take isl_band *band);
+
+Each band contains zero or more scheduling dimensions.
+These are referred to as the members of the band.
+The section of the schedule that corresponds to the band is
+referred to as the partial schedule of the band.
+For those nodes that participate in a band, the outer scheduling
+dimensions form the prefix schedule, while the inner scheduling
+dimensions form the suffix schedule.
+That is, if we take a cut of the band forest, then the union of
+the concatenations of the prefix, partial and suffix schedules of
+each band in the cut is equal to the entire schedule (modulo
+some possible padding at the end with zero scheduling dimensions).
+The properties of a band can be inspected using the following functions.
+
+ #include <isl/band.h>
+ int isl_band_has_children(__isl_keep isl_band *band);
+ __isl_give isl_band_list *isl_band_get_children(
+ __isl_keep isl_band *band);
+
+ __isl_give isl_union_map *isl_band_get_prefix_schedule(
+ __isl_keep isl_band *band);
+ __isl_give isl_union_map *isl_band_get_partial_schedule(
+ __isl_keep isl_band *band);
+ __isl_give isl_union_map *isl_band_get_suffix_schedule(
+ __isl_keep isl_band *band);
+
+ int isl_band_n_member(__isl_keep isl_band *band);
+ int isl_band_member_is_coincident(
+ __isl_keep isl_band *band, int pos);
+
+ int isl_band_list_foreach_band(
+ __isl_keep isl_band_list *list,
+ int (*fn)(__isl_keep isl_band *band, void *user),
+ void *user);
+
+Note that a scheduling dimension is considered to be ``coincident''
+if it satisfies the coincidence constraints within its band.
+That is, if the dependence distances of the coincidence
+constraints are all zero in that direction (for fixed
+iterations of outer bands).
+Like C<isl_schedule_foreach_band>,
+the function C<isl_band_list_foreach_band> calls C<fn> on the bands
+in depth-first post-order.
+
+A band can be tiled using the following function.
+
+ #include <isl/band.h>
+ int isl_band_tile(__isl_keep isl_band *band,
+ __isl_take isl_vec *sizes);
+
+ int isl_options_set_tile_scale_tile_loops(isl_ctx *ctx,
+ int val);
+ int isl_options_get_tile_scale_tile_loops(isl_ctx *ctx);
+ int isl_options_set_tile_shift_point_loops(isl_ctx *ctx,
+ int val);
+ int isl_options_get_tile_shift_point_loops(isl_ctx *ctx);
+
+The C<isl_band_tile> function tiles the band using the given tile sizes
+inside its schedule.
+A new child band is created to represent the point loops and it is
+inserted between the modified band and its children.
+The C<tile_scale_tile_loops> option specifies whether the tile
+loops iterators should be scaled by the tile sizes.
+If the C<tile_shift_point_loops> option is set, then the point loops
+are shifted to start at zero.
+
+A band can be split into two nested bands using the following function.
+
+ int isl_band_split(__isl_keep isl_band *band, int pos);
+
+The resulting outer band contains the first C<pos> dimensions of C<band>
+while the inner band contains the remaining dimensions.
+
+A representation of the band can be printed using
+
+ #include <isl/band.h>
+ __isl_give isl_printer *isl_printer_print_band(
+ __isl_take isl_printer *p,
+ __isl_keep isl_band *band);
+
+=head3 Options
+
+ #include <isl/schedule.h>
+ int isl_options_set_schedule_max_coefficient(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_max_coefficient(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_max_constant_term(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_max_constant_term(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_fuse(isl_ctx *ctx, int val);
+ int isl_options_get_schedule_fuse(isl_ctx *ctx);
+ int isl_options_set_schedule_maximize_band_depth(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_maximize_band_depth(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_outer_coincidence(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_outer_coincidence(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_split_scaled(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_split_scaled(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_algorithm(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_algorithm(
+ isl_ctx *ctx);
+ int isl_options_set_schedule_separate_components(
+ isl_ctx *ctx, int val);
+ int isl_options_get_schedule_separate_components(
+ isl_ctx *ctx);
+
+=over
+
+=item * schedule_max_coefficient
+
+This option enforces that the coefficients for variable and parameter
+dimensions in the calculated schedule are not larger than the specified value.
+This option can significantly increase the speed of the scheduling calculation
+and may also prevent fusing of unrelated dimensions. A value of -1 means that
+this option does not introduce bounds on the variable or parameter
+coefficients.
+
+=item * schedule_max_constant_term
+
+This option enforces that the constant coefficients in the calculated schedule
+are not larger than the maximal constant term. This option can significantly
+increase the speed of the scheduling calculation and may also prevent fusing of
+unrelated dimensions. A value of -1 means that this option does not introduce
+bounds on the constant coefficients.
+
+=item * schedule_fuse
+
+This option controls the level of fusion.
+If this option is set to C<ISL_SCHEDULE_FUSE_MIN>, then loops in the
+resulting schedule will be distributed as much as possible.
+If this option is set to C<ISL_SCHEDULE_FUSE_MAX>, then C<isl> will
+try to fuse loops in the resulting schedule.
+
+=item * schedule_maximize_band_depth
+
+If this option is set, we do not split bands at the point
+where we detect splitting is necessary. Instead, we
+backtrack and split bands as early as possible. This
+reduces the number of splits and maximizes the width of
+the bands. Wider bands give more possibilities for tiling.
+Note that if the C<schedule_fuse> option is set to C<ISL_SCHEDULE_FUSE_MIN>,
+then bands will be split as early as possible, even if there is no need.
+The C<schedule_maximize_band_depth> option therefore has no effect in this case.
+
+=item * schedule_outer_coincidence
+
+If this option is set, then we try to construct schedules
+where the outermost scheduling dimension in each band
+satisfies the coincidence constraints.
+
+=item * schedule_split_scaled
+
+If this option is set, then we try to construct schedules in which the
+constant term is split off from the linear part if the linear parts of
+the scheduling rows for all nodes in the graphs have a common non-trivial
+divisor.
+The constant term is then placed in a separate band and the linear
+part is reduced.
+
+=item * schedule_algorithm
+
+Selects the scheduling algorithm to be used.
+Available scheduling algorithms are C<ISL_SCHEDULE_ALGORITHM_ISL>
+and C<ISL_SCHEDULE_ALGORITHM_FEAUTRIER>.
+
+=item * schedule_separate_components
+
+If at any point the dependence graph contains any (weakly connected) components,
+then these components are scheduled separately.
+If this option is not set, then some iterations of the domains
+in these components may be scheduled together.
+If this option is set, then the components are given consecutive
+schedules.
+
+=back
+
+=head2 AST Generation
+
+This section describes the C<isl> functionality for generating
+ASTs that visit all the elements
+in a domain in an order specified by a schedule.
+In particular, given a C<isl_union_map>, an AST is generated
+that visits all the elements in the domain of the C<isl_union_map>
+according to the lexicographic order of the corresponding image
+element(s). If the range of the C<isl_union_map> consists of
+elements in more than one space, then each of these spaces is handled
+separately in an arbitrary order.
+It should be noted that the image elements only specify the I<order>
+in which the corresponding domain elements should be visited.
+No direct relation between the image elements and the loop iterators
+in the generated AST should be assumed.
+
+Each AST is generated within a build. The initial build
+simply specifies the constraints on the parameters (if any)
+and can be created, inspected, copied and freed using the following functions.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *isl_ast_build_from_context(
+ __isl_take isl_set *set);
+ __isl_give isl_ast_build *isl_ast_build_copy(
+ __isl_keep isl_ast_build *build);
+ __isl_null isl_ast_build *isl_ast_build_free(
+ __isl_take isl_ast_build *build);
+
+The C<set> argument is usually a parameter set with zero or more parameters.
+More C<isl_ast_build> functions are described in L</"Nested AST Generation">
+and L</"Fine-grained Control over AST Generation">.
+Finally, the AST itself can be constructed using the following
+function.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_union_map *schedule);
+
+=head3 Inspecting the AST
+
+The basic properties of an AST node can be obtained as follows.
+
+ #include <isl/ast.h>
+ enum isl_ast_node_type isl_ast_node_get_type(
+ __isl_keep isl_ast_node *node);
+
+The type of an AST node is one of
+C<isl_ast_node_for>,
+C<isl_ast_node_if>,
+C<isl_ast_node_block> or
+C<isl_ast_node_user>.
+An C<isl_ast_node_for> represents a for node.
+An C<isl_ast_node_if> represents an if node.
+An C<isl_ast_node_block> represents a compound node.
+An C<isl_ast_node_user> represents an expression statement.
+An expression statement typically corresponds to a domain element, i.e.,
+one of the elements that is visited by the AST.
+
+Each type of node has its own additional properties.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_expr *isl_ast_node_for_get_init(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_node *isl_ast_node_for_get_body(
+ __isl_keep isl_ast_node *node);
+ int isl_ast_node_for_is_degenerate(
+ __isl_keep isl_ast_node *node);
+
+An C<isl_ast_for> is considered degenerate if it is known to execute
+exactly once.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_node *isl_ast_node_if_get_then(
+ __isl_keep isl_ast_node *node);
+ int isl_ast_node_if_has_else(
+ __isl_keep isl_ast_node *node);
+ __isl_give isl_ast_node *isl_ast_node_if_get_else(
+ __isl_keep isl_ast_node *node);
+
+ __isl_give isl_ast_node_list *
+ isl_ast_node_block_get_children(
+ __isl_keep isl_ast_node *node);
+
+ __isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+ __isl_keep isl_ast_node *node);
+
+Each of the returned C<isl_ast_expr>s can in turn be inspected using
+the following functions.
+
+ #include <isl/ast.h>
+ enum isl_ast_expr_type isl_ast_expr_get_type(
+ __isl_keep isl_ast_expr *expr);
+
+The type of an AST expression is one of
+C<isl_ast_expr_op>,
+C<isl_ast_expr_id> or
+C<isl_ast_expr_int>.
+An C<isl_ast_expr_op> represents the result of an operation.
+An C<isl_ast_expr_id> represents an identifier.
+An C<isl_ast_expr_int> represents an integer value.
+
+Each type of expression has its own additional properties.
+
+ #include <isl/ast.h>
+ enum isl_ast_op_type isl_ast_expr_get_op_type(
+ __isl_keep isl_ast_expr *expr);
+ int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+ __isl_give isl_ast_expr *isl_ast_expr_get_op_arg(
+ __isl_keep isl_ast_expr *expr, int pos);
+ int isl_ast_node_foreach_ast_op_type(
+ __isl_keep isl_ast_node *node,
+ int (*fn)(enum isl_ast_op_type type, void *user),
+ void *user);
+
+C<isl_ast_expr_get_op_type> returns the type of the operation
+performed. C<isl_ast_expr_get_op_n_arg> returns the number of
+arguments. C<isl_ast_expr_get_op_arg> returns the specified
+argument.
+C<isl_ast_node_foreach_ast_op_type> calls C<fn> for each distinct
+C<isl_ast_op_type> that appears in C<node>.
+The operation type is one of the following.
+
+=over
+
+=item C<isl_ast_op_and>
+
+Logical I<and> of two arguments.
+Both arguments can be evaluated.
+
+=item C<isl_ast_op_and_then>
+
+Logical I<and> of two arguments.
+The second argument can only be evaluated if the first evaluates to true.
+
+=item C<isl_ast_op_or>
+
+Logical I<or> of two arguments.
+Both arguments can be evaluated.
+
+=item C<isl_ast_op_or_else>
+
+Logical I<or> of two arguments.
+The second argument can only be evaluated if the first evaluates to false.
+
+=item C<isl_ast_op_max>
+
+Maximum of two or more arguments.
+
+=item C<isl_ast_op_min>
+
+Minimum of two or more arguments.
+
+=item C<isl_ast_op_minus>
+
+Change sign.
+
+=item C<isl_ast_op_add>
+
+Sum of two arguments.
+
+=item C<isl_ast_op_sub>
+
+Difference of two arguments.
+
+=item C<isl_ast_op_mul>
+
+Product of two arguments.
+
+=item C<isl_ast_op_div>
+
+Exact division. That is, the result is known to be an integer.
+
+=item C<isl_ast_op_fdiv_q>
+
+Result of integer division, rounded towards negative
+infinity.
+
+=item C<isl_ast_op_pdiv_q>
+
+Result of integer division, where dividend is known to be non-negative.
+
+=item C<isl_ast_op_pdiv_r>
+
+Remainder of integer division, where dividend is known to be non-negative.
+
+=item C<isl_ast_op_zdiv_r>
+
+Equal to zero iff the remainder on integer division is zero.
+
+=item C<isl_ast_op_cond>
+
+Conditional operator defined on three arguments.
+If the first argument evaluates to true, then the result
+is equal to the second argument. Otherwise, the result
+is equal to the third argument.
+The second and third argument may only be evaluated if
+the first argument evaluates to true and false, respectively.
+Corresponds to C<a ? b : c> in C.
+
+=item C<isl_ast_op_select>
+
+Conditional operator defined on three arguments.
+If the first argument evaluates to true, then the result
+is equal to the second argument. Otherwise, the result
+is equal to the third argument.
+The second and third argument may be evaluated independently
+of the value of the first argument.
+Corresponds to C<a * b + (1 - a) * c> in C.
+
+=item C<isl_ast_op_eq>
+
+Equality relation.
+
+=item C<isl_ast_op_le>
+
+Less than or equal relation.
+
+=item C<isl_ast_op_lt>
+
+Less than relation.
+
+=item C<isl_ast_op_ge>
+
+Greater than or equal relation.
+
+=item C<isl_ast_op_gt>
+
+Greater than relation.
+
+=item C<isl_ast_op_call>
+
+A function call.
+The number of arguments of the C<isl_ast_expr> is one more than
+the number of arguments in the function call, the first argument
+representing the function being called.
+
+=item C<isl_ast_op_access>
+
+An array access.
+The number of arguments of the C<isl_ast_expr> is one more than
+the number of index expressions in the array access, the first argument
+representing the array being accessed.
+
+=item C<isl_ast_op_member>
+
+A member access.
+This operation has two arguments, a structure and the name of
+the member of the structure being accessed.
+
+=back
+
+ #include <isl/ast.h>
+ __isl_give isl_id *isl_ast_expr_get_id(
+ __isl_keep isl_ast_expr *expr);
+
+Return the identifier represented by the AST expression.
+
+ #include <isl/ast.h>
+ __isl_give isl_val *isl_ast_expr_get_val(
+ __isl_keep isl_ast_expr *expr);
+
+Return the integer represented by the AST expression.
+
+=head3 Properties of ASTs
+
+ #include <isl/ast.h>
+ int isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
+ __isl_keep isl_ast_expr *expr2);
+
+Check if two C<isl_ast_expr>s are equal to each other.
+
+=head3 Manipulating and printing the AST
+
+AST nodes can be copied and freed using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_node *isl_ast_node_copy(
+ __isl_keep isl_ast_node *node);
+ __isl_null isl_ast_node *isl_ast_node_free(
+ __isl_take isl_ast_node *node);
+
+AST expressions can be copied and freed using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_expr_copy(
+ __isl_keep isl_ast_expr *expr);
+ __isl_null isl_ast_expr *isl_ast_expr_free(
+ __isl_take isl_ast_expr *expr);
+
+New AST expressions can be created either directly or within
+the context of an C<isl_ast_build>.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_expr_from_val(
+ __isl_take isl_val *v);
+ __isl_give isl_ast_expr *isl_ast_expr_from_id(
+ __isl_take isl_id *id);
+ __isl_give isl_ast_expr *isl_ast_expr_neg(
+ __isl_take isl_ast_expr *expr);
+ __isl_give isl_ast_expr *isl_ast_expr_address_of(
+ __isl_take isl_ast_expr *expr);
+ __isl_give isl_ast_expr *isl_ast_expr_add(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_sub(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_mul(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_div(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_and(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+ __isl_give isl_ast_expr *isl_ast_expr_or(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+ __isl_give isl_ast_expr *isl_ast_expr_eq(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_le(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_lt(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_ge(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_gt(
+ __isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+ __isl_give isl_ast_expr *isl_ast_expr_access(
+ __isl_take isl_ast_expr *array,
+ __isl_take isl_ast_expr_list *indices);
+
+The function C<isl_ast_expr_address_of> can be applied to an
+C<isl_ast_expr> of type C<isl_ast_op_access> only. It is meant
+to represent the address of the C<isl_ast_expr_access>.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_pw_aff *pa);
+ __isl_give isl_ast_expr *
+ isl_ast_build_access_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_ast_expr *
+ isl_ast_build_access_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_ast_expr *
+ isl_ast_build_call_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_ast_expr *
+ isl_ast_build_call_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build,
+ __isl_take isl_multi_pw_aff *mpa);
+
+The domains of C<pa>, C<mpa> and C<pma> should correspond
+to the schedule space of C<build>.
+The tuple id of C<mpa> or C<pma> is used as the array being accessed or
+the function being called.
+If the accessed space is a nested relation, then it is taken
+to represent an access of the member specified by the range
+of this nested relation of the structure specified by the domain
+of the nested relation.
+
+The following functions can be used to modify an C<isl_ast_expr>.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_expr_set_op_arg(
+ __isl_take isl_ast_expr *expr, int pos,
+ __isl_take isl_ast_expr *arg);
+
+Replace the argument of C<expr> at position C<pos> by C<arg>.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
+ __isl_take isl_ast_expr *expr,
+ __isl_take isl_id_to_ast_expr *id2expr);
+
+The function C<isl_ast_expr_substitute_ids> replaces the
+subexpressions of C<expr> of type C<isl_ast_expr_id>
+by the corresponding expression in C<id2expr>, if there is any.
+
+
+User specified data can be attached to an C<isl_ast_node> and obtained
+from the same C<isl_ast_node> using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_node *isl_ast_node_set_annotation(
+ __isl_take isl_ast_node *node,
+ __isl_take isl_id *annotation);
+ __isl_give isl_id *isl_ast_node_get_annotation(
+ __isl_keep isl_ast_node *node);
+
+Basic printing can be performed using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_printer *isl_printer_print_ast_expr(
+ __isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr);
+ __isl_give isl_printer *isl_printer_print_ast_node(
+ __isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node);
+ __isl_give char *isl_ast_expr_to_str(
+ __isl_keep isl_ast_expr *expr);
+
+More advanced printing can be performed using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_printer *isl_ast_op_type_print_macro(
+ enum isl_ast_op_type type,
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_ast_node_print_macros(
+ __isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_ast_node_print(
+ __isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+ __isl_give isl_printer *isl_ast_node_for_print(
+ __isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+ __isl_give isl_printer *isl_ast_node_if_print(
+ __isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+
+While printing an C<isl_ast_node> in C<ISL_FORMAT_C>,
+C<isl> may print out an AST that makes use of macros such
+as C<floord>, C<min> and C<max>.
+C<isl_ast_op_type_print_macro> prints out the macro
+corresponding to a specific C<isl_ast_op_type>.
+C<isl_ast_node_print_macros> scans the C<isl_ast_node>
+for expressions where these macros would be used and prints
+out the required macro definitions.
+Essentially, C<isl_ast_node_print_macros> calls
+C<isl_ast_node_foreach_ast_op_type> with C<isl_ast_op_type_print_macro>
+as function argument.
+C<isl_ast_node_print>, C<isl_ast_node_for_print> and
+C<isl_ast_node_if_print> print an C<isl_ast_node>
+in C<ISL_FORMAT_C>, but allow for some extra control
+through an C<isl_ast_print_options> object.
+This object can be created using the following functions.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_print_options *
+ isl_ast_print_options_alloc(isl_ctx *ctx);
+ __isl_give isl_ast_print_options *
+ isl_ast_print_options_copy(
+ __isl_keep isl_ast_print_options *options);
+ __isl_null isl_ast_print_options *
+ isl_ast_print_options_free(
+ __isl_take isl_ast_print_options *options);
+
+ __isl_give isl_ast_print_options *
+ isl_ast_print_options_set_print_user(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_user)(
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user);
+ __isl_give isl_ast_print_options *
+ isl_ast_print_options_set_print_for(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_for)(
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user);
+
+The callback set by C<isl_ast_print_options_set_print_user>
+is called whenever a node of type C<isl_ast_node_user> needs to
+be printed.
+The callback set by C<isl_ast_print_options_set_print_for>
+is called whenever a node of type C<isl_ast_node_for> needs to
+be printed.
+Note that C<isl_ast_node_for_print> will I<not> call the
+callback set by C<isl_ast_print_options_set_print_for> on the node
+on which C<isl_ast_node_for_print> is called, but only on nested
+nodes of type C<isl_ast_node_for>. It is therefore safe to
+call C<isl_ast_node_for_print> from within the callback set by
+C<isl_ast_print_options_set_print_for>.
+
+The following option determines the type to be used for iterators
+while printing the AST.
+
+ int isl_options_set_ast_iterator_type(
+ isl_ctx *ctx, const char *val);
+ const char *isl_options_get_ast_iterator_type(
+ isl_ctx *ctx);
+
+The AST printer only prints body nodes as blocks if these
+blocks cannot be safely omitted.
+For example, a C<for> node with one body node will not be
+surrounded with braces in C<ISL_FORMAT_C>.
+A block will always be printed by setting the following option.
+
+ int isl_options_set_ast_always_print_block(isl_ctx *ctx,
+ int val);
+ int isl_options_get_ast_always_print_block(isl_ctx *ctx);
+
+=head3 Options
+
+ #include <isl/ast_build.h>
+ int isl_options_set_ast_build_atomic_upper_bound(
+ isl_ctx *ctx, int val);
+ int isl_options_get_ast_build_atomic_upper_bound(
+ isl_ctx *ctx);
+ int isl_options_set_ast_build_prefer_pdiv(isl_ctx *ctx,
+ int val);
+ int isl_options_get_ast_build_prefer_pdiv(isl_ctx *ctx);
+ int isl_options_set_ast_build_exploit_nested_bounds(
+ isl_ctx *ctx, int val);
+ int isl_options_get_ast_build_exploit_nested_bounds(
+ isl_ctx *ctx);
+ int isl_options_set_ast_build_group_coscheduled(
+ isl_ctx *ctx, int val);
+ int isl_options_get_ast_build_group_coscheduled(
+ isl_ctx *ctx);
+ int isl_options_set_ast_build_scale_strides(
+ isl_ctx *ctx, int val);
+ int isl_options_get_ast_build_scale_strides(
+ isl_ctx *ctx);
+ int isl_options_set_ast_build_allow_else(isl_ctx *ctx,
+ int val);
+ int isl_options_get_ast_build_allow_else(isl_ctx *ctx);
+ int isl_options_set_ast_build_allow_or(isl_ctx *ctx,
+ int val);
+ int isl_options_get_ast_build_allow_or(isl_ctx *ctx);
+
+=over
+
+=item * ast_build_atomic_upper_bound
+
+Generate loop upper bounds that consist of the current loop iterator,
+an operator and an expression not involving the iterator.
+If this option is not set, then the current loop iterator may appear
+several times in the upper bound.
+For example, when this option is turned off, AST generation
+for the schedule
+
+ [n] -> { A[i] -> [i] : 0 <= i <= 100, n }
+
+produces
+
+ for (int c0 = 0; c0 <= 100 && n >= c0; c0 += 1)
+ A(c0);
+
+When the option is turned on, the following AST is generated
+
+ for (int c0 = 0; c0 <= min(100, n); c0 += 1)
+ A(c0);
+
+=item * ast_build_prefer_pdiv
+
+If this option is turned off, then the AST generation will
+produce ASTs that may only contain C<isl_ast_op_fdiv_q>
+operators, but no C<isl_ast_op_pdiv_q> or
+C<isl_ast_op_pdiv_r> operators.
+If this options is turned on, then C<isl> will try to convert
+some of the C<isl_ast_op_fdiv_q> operators to (expressions containing)
+C<isl_ast_op_pdiv_q> or C<isl_ast_op_pdiv_r> operators.
+
+=item * ast_build_exploit_nested_bounds
+
+Simplify conditions based on bounds of nested for loops.
+In particular, remove conditions that are implied by the fact
+that one or more nested loops have at least one iteration,
+meaning that the upper bound is at least as large as the lower bound.
+For example, when this option is turned off, AST generation
+for the schedule
+
+ [N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and
+ 0 <= j <= M }
+
+produces
+
+ if (M >= 0)
+ for (int c0 = 0; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ A(c0, c1);
+
+When the option is turned on, the following AST is generated
+
+ for (int c0 = 0; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ A(c0, c1);
+
+=item * ast_build_group_coscheduled
+
+If two domain elements are assigned the same schedule point, then
+they may be executed in any order and they may even appear in different
+loops. If this options is set, then the AST generator will make
+sure that coscheduled domain elements do not appear in separate parts
+of the AST. This is useful in case of nested AST generation
+if the outer AST generation is given only part of a schedule
+and the inner AST generation should handle the domains that are
+coscheduled by this initial part of the schedule together.
+For example if an AST is generated for a schedule
+
+ { A[i] -> [0]; B[i] -> [0] }
+
+then the C<isl_ast_build_set_create_leaf> callback described
+below may get called twice, once for each domain.
+Setting this option ensures that the callback is only called once
+on both domains together.
+
+=item * ast_build_separation_bounds
+
+This option specifies which bounds to use during separation.
+If this option is set to C<ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT>
+then all (possibly implicit) bounds on the current dimension will
+be used during separation.
+If this option is set to C<ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT>
+then only those bounds that are explicitly available will
+be used during separation.
+
+=item * ast_build_scale_strides
+
+This option specifies whether the AST generator is allowed
+to scale down iterators of strided loops.
+
+=item * ast_build_allow_else
+
+This option specifies whether the AST generator is allowed
+to construct if statements with else branches.
+
+=item * ast_build_allow_or
+
+This option specifies whether the AST generator is allowed
+to construct if conditions with disjunctions.
+
+=back
+
+=head3 Fine-grained Control over AST Generation
+
+Besides specifying the constraints on the parameters,
+an C<isl_ast_build> object can be used to control
+various aspects of the AST generation process.
+The most prominent way of control is through ``options'',
+which can be set using the following function.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_options(
+ __isl_take isl_ast_build *control,
+ __isl_take isl_union_map *options);
+
+The options are encoded in an C<isl_union_map>.
+The domain of this union relation refers to the schedule domain,
+i.e., the range of the schedule passed to C<isl_ast_build_ast_from_schedule>.
+In the case of nested AST generation (see L</"Nested AST Generation">),
+the domain of C<options> should refer to the extra piece of the schedule.
+That is, it should be equal to the range of the wrapped relation in the
+range of the schedule.
+The range of the options can consist of elements in one or more spaces,
+the names of which determine the effect of the option.
+The values of the range typically also refer to the schedule dimension
+to which the option applies. In case of nested AST generation
+(see L</"Nested AST Generation">), these values refer to the position
+of the schedule dimension within the innermost AST generation.
+The constraints on the domain elements of
+the option should only refer to this dimension and earlier dimensions.
+We consider the following spaces.
+
+=over
+
+=item C<separation_class>
+
+This space is a wrapped relation between two one dimensional spaces.
+The input space represents the schedule dimension to which the option
+applies and the output space represents the separation class.
+While constructing a loop corresponding to the specified schedule
+dimension(s), the AST generator will try to generate separate loops
+for domain elements that are assigned different classes.
+If only some of the elements are assigned a class, then those elements
+that are not assigned any class will be treated as belonging to a class
+that is separate from the explicitly assigned classes.
+The typical use case for this option is to separate full tiles from
+partial tiles.
+The other options, described below, are applied after the separation
+into classes.
+
+As an example, consider the separation into full and partial tiles
+of a tiling of a triangular domain.
+Take, for example, the domain
+
+ { A[i,j] : 0 <= i,j and i + j <= 100 }
+
+and a tiling into tiles of 10 by 10. The input to the AST generator
+is then the schedule
+
+ { A[i,j] -> [([i/10]),[j/10],i,j] : 0 <= i,j and
+ i + j <= 100 }
+
+Without any options, the following AST is generated
+
+ for (int c0 = 0; c0 <= 10; c0 += 1)
+ for (int c1 = 0; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(10 * c1 + 9, -c2 + 100);
+ c3 += 1)
+ A(c2, c3);
+
+Separation into full and partial tiles can be obtained by assigning
+a class, say C<0>, to the full tiles. The full tiles are represented by those
+values of the first and second schedule dimensions for which there are
+values of the third and fourth dimensions to cover an entire tile.
+That is, we need to specify the following option
+
+ { [a,b,c,d] -> separation_class[[0]->[0]] :
+ exists b': 0 <= 10a,10b' and
+ 10a+9+10b'+9 <= 100;
+ [a,b,c,d] -> separation_class[[1]->[0]] :
+ 0 <= 10a,10b and 10a+9+10b+9 <= 100 }
+
+which simplifies to
+
+ { [a, b, c, d] -> separation_class[[1] -> [0]] :
+ a >= 0 and b >= 0 and b <= 8 - a;
+ [a, b, c, d] -> separation_class[[0] -> [0]] :
+ a >= 0 and a <= 8 }
+
+With this option, the generated AST is as follows
+
+ {
+ for (int c0 = 0; c0 <= 8; c0 += 1) {
+ for (int c1 = 0; c1 <= -c0 + 8; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= 10 * c0 + 9; c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= 10 * c1 + 9; c3 += 1)
+ A(c2, c3);
+ for (int c1 = -c0 + 9; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(-c2 + 100, 10 * c1 + 9);
+ c3 += 1)
+ A(c2, c3);
+ }
+ for (int c0 = 9; c0 <= 10; c0 += 1)
+ for (int c1 = 0; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0;
+ c2 <= min(-10 * c1 + 100, 10 * c0 + 9);
+ c2 += 1)
+ for (int c3 = 10 * c1;
+ c3 <= min(10 * c1 + 9, -c2 + 100);
+ c3 += 1)
+ A(c2, c3);
+ }
+
+=item C<separate>
+
+This is a single-dimensional space representing the schedule dimension(s)
+to which ``separation'' should be applied. Separation tries to split
+a loop into several pieces if this can avoid the generation of guards
+inside the loop.
+See also the C<atomic> option.
+
+=item C<atomic>
+
+This is a single-dimensional space representing the schedule dimension(s)
+for which the domains should be considered ``atomic''. That is, the
+AST generator will make sure that any given domain space will only appear
+in a single loop at the specified level.
+
+Consider the following schedule
+
+ { a[i] -> [i] : 0 <= i < 10;
+ b[i] -> [i+1] : 0 <= i < 10 }
+
+If the following option is specified
+
+ { [i] -> separate[x] }
+
+then the following AST will be generated
+
+ {
+ a(0);
+ for (int c0 = 1; c0 <= 9; c0 += 1) {
+ a(c0);
+ b(c0 - 1);
+ }
+ b(9);
+ }
+
+If, on the other hand, the following option is specified
+
+ { [i] -> atomic[x] }
+
+then the following AST will be generated
+
+ for (int c0 = 0; c0 <= 10; c0 += 1) {
+ if (c0 <= 9)
+ a(c0);
+ if (c0 >= 1)
+ b(c0 - 1);
+ }
+
+If neither C<atomic> nor C<separate> is specified, then the AST generator
+may produce either of these two results or some intermediate form.
+
+=item C<unroll>
+
+This is a single-dimensional space representing the schedule dimension(s)
+that should be I<completely> unrolled.
+To obtain a partial unrolling, the user should apply an additional
+strip-mining to the schedule and fully unroll the inner loop.
+
+=back
+
+Additional control is available through the following functions.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_iterators(
+ __isl_take isl_ast_build *control,
+ __isl_take isl_id_list *iterators);
+
+The function C<isl_ast_build_set_iterators> allows the user to
+specify a list of iterator C<isl_id>s to be used as iterators.
+If the input schedule is injective, then
+the number of elements in this list should be as large as the dimension
+of the schedule space, but no direct correspondence should be assumed
+between dimensions and elements.
+If the input schedule is not injective, then an additional number
+of C<isl_id>s equal to the largest dimension of the input domains
+may be required.
+If the number of provided C<isl_id>s is insufficient, then additional
+names are automatically generated.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_create_leaf(
+ __isl_take isl_ast_build *control,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_build *build,
+ void *user), void *user);
+
+The
+C<isl_ast_build_set_create_leaf> function allows for the
+specification of a callback that should be called whenever the AST
+generator arrives at an element of the schedule domain.
+The callback should return an AST node that should be inserted
+at the corresponding position of the AST. The default action (when
+the callback is not set) is to continue generating parts of the AST to scan
+all the domain elements associated to the schedule domain element
+and to insert user nodes, ``calling'' the domain element, for each of them.
+The C<build> argument contains the current state of the C<isl_ast_build>.
+To ease nested AST generation (see L</"Nested AST Generation">),
+all control information that is
+specific to the current AST generation such as the options and
+the callbacks has been removed from this C<isl_ast_build>.
+The callback would typically return the result of a nested
+AST generation or a
+user defined node created using the following function.
+
+ #include <isl/ast.h>
+ __isl_give isl_ast_node *isl_ast_node_alloc_user(
+ __isl_take isl_ast_expr *expr);
+
+ #include <isl/ast_build.h>
+ __isl_give isl_ast_build *
+ isl_ast_build_set_at_each_domain(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+ __isl_give isl_ast_build *
+ isl_ast_build_set_before_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_id *(*fn)(
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+ __isl_give isl_ast_build *
+ isl_ast_build_set_after_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build,
+ void *user), void *user);
+
+The callback set by C<isl_ast_build_set_at_each_domain> will
+be called for each domain AST node.
+The callbacks set by C<isl_ast_build_set_before_each_for>
+and C<isl_ast_build_set_after_each_for> will be called
+for each for AST node. The first will be called in depth-first
+pre-order, while the second will be called in depth-first post-order.
+Since C<isl_ast_build_set_before_each_for> is called before the for
+node is actually constructed, it is only passed an C<isl_ast_build>.
+The returned C<isl_id> will be added as an annotation (using
+C<isl_ast_node_set_annotation>) to the constructed for node.
+In particular, if the user has also specified an C<after_each_for>
+callback, then the annotation can be retrieved from the node passed to
+that callback using C<isl_ast_node_get_annotation>.
+All callbacks should C<NULL> on failure.
+The given C<isl_ast_build> can be used to create new
+C<isl_ast_expr> objects using C<isl_ast_build_expr_from_pw_aff>
+or C<isl_ast_build_call_from_pw_multi_aff>.
+
+=head3 Nested AST Generation
+
+C<isl> allows the user to create an AST within the context
+of another AST. These nested ASTs are created using the
+same C<isl_ast_build_ast_from_schedule> function that is used to create the
+outer AST. The C<build> argument should be an C<isl_ast_build>
+passed to a callback set by
+C<isl_ast_build_set_create_leaf>.
+The space of the range of the C<schedule> argument should refer
+to this build. In particular, the space should be a wrapped
+relation and the domain of this wrapped relation should be the
+same as that of the range of the schedule returned by
+C<isl_ast_build_get_schedule> below.
+In practice, the new schedule is typically
+created by calling C<isl_union_map_range_product> on the old schedule
+and some extra piece of the schedule.
+The space of the schedule domain is also available from
+the C<isl_ast_build>.
+
+ #include <isl/ast_build.h>
+ __isl_give isl_union_map *isl_ast_build_get_schedule(
+ __isl_keep isl_ast_build *build);
+ __isl_give isl_space *isl_ast_build_get_schedule_space(
+ __isl_keep isl_ast_build *build);
+ __isl_give isl_ast_build *isl_ast_build_restrict(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_set *set);
+
+The C<isl_ast_build_get_schedule> function returns a (partial)
+schedule for the domains elements for which part of the AST still needs to
+be generated in the current build.
+In particular, the domain elements are mapped to those iterations of the loops
+enclosing the current point of the AST generation inside which
+the domain elements are executed.
+No direct correspondence between
+the input schedule and this schedule should be assumed.
+The space obtained from C<isl_ast_build_get_schedule_space> can be used
+to create a set for C<isl_ast_build_restrict> to intersect
+with the current build. In particular, the set passed to
+C<isl_ast_build_restrict> can have additional parameters.
+The ids of the set dimensions in the space returned by
+C<isl_ast_build_get_schedule_space> correspond to the
+iterators of the already generated loops.
+The user should not rely on the ids of the output dimensions
+of the relations in the union relation returned by
+C<isl_ast_build_get_schedule> having any particular value.
+
+=head1 Applications
+
+Although C<isl> is mainly meant to be used as a library,
+it also contains some basic applications that use some
+of the functionality of C<isl>.
+The input may be specified in either the L<isl format>
+or the L<PolyLib format>.
+
+=head2 C<isl_polyhedron_sample>
+
+C<isl_polyhedron_sample> takes a polyhedron as input and prints
+an integer element of the polyhedron, if there is any.
+The first column in the output is the denominator and is always
+equal to 1. If the polyhedron contains no integer points,
+then a vector of length zero is printed.
+
+=head2 C<isl_pip>
+
+C<isl_pip> takes the same input as the C<example> program
+from the C<piplib> distribution, i.e., a set of constraints
+on the parameters, a line containing only -1 and finally a set
+of constraints on a parametric polyhedron.
+The coefficients of the parameters appear in the last columns
+(but before the final constant column).
+The output is the lexicographic minimum of the parametric polyhedron.
+As C<isl> currently does not have its own output format, the output
+is just a dump of the internal state.
+
+=head2 C<isl_polyhedron_minimize>
+
+C<isl_polyhedron_minimize> computes the minimum of some linear
+or affine objective function over the integer points in a polyhedron.
+If an affine objective function
+is given, then the constant should appear in the last column.
+
+=head2 C<isl_polytope_scan>
+
+Given a polytope, C<isl_polytope_scan> prints
+all integer points in the polytope.
+
+=head2 C<isl_codegen>
+
+Given a schedule, a context set and an options relation,
+C<isl_codegen> prints out an AST that scans the domain elements
+of the schedule in the order of their image(s) taking into account
+the constraints in the context set.
diff --git a/polly/lib/External/isl/gitversion.h b/polly/lib/External/isl/gitversion.h
new file mode 100644
index 00000000000..3e4cb24fff3
--- /dev/null
+++ b/polly/lib/External/isl/gitversion.h
@@ -0,0 +1 @@
+#define GIT_HEAD_ID "UNKNOWN"
diff --git a/polly/lib/External/isl/imath/ChangeLog b/polly/lib/External/isl/imath/ChangeLog
new file mode 100644
index 00000000000..5222475d084
--- /dev/null
+++ b/polly/lib/External/isl/imath/ChangeLog
@@ -0,0 +1,377 @@
+1.0.1
+ First released version.
+
+1.0.2
+ Fixed a bug in mp_int_div() which would yield incorrect quotients
+ when the divisor was very close in value to a prefix of the
+ dividend. This is now fixed, and there are regression tests in
+ the tests directory.
+
+ Added recursive multiplication and squaring (Karatsuba-Ofman) for
+ large input values. Integrated these with the existing code for
+ exponentiation, too. See the code for s_kmul() and s_ksqr() in
+ imath.c. Tests added and verified against GNU bc.
+
+ Added documentation on mp_get_multiply_threshold() and the reason
+ why it exists.
+
+1.0.3
+ Fixed a couple of bugs in pi.c that were causing incorrect values
+ to be computed for > 30 digits or so. Added a pi-computation test
+ to the default test suite (make test), checked against a static
+ file computed by bc (set scale=1024, compute 4 * atan(1)). Added
+ command line option to specify output radix for pi.
+
+ Cleaned up a sign-related bug in mp_int_gcd(), which would cause
+ the sign of gcd(0, x) to be incorrect when x < 0. Test cases
+ added for future regression.
+
+ Fixed a bug in s_reduce() which would give incorrect results for
+ powers of 2 in certain circumstances. Added tests to drive this
+ case for future regression.
+
+ Added mp_int_exptmod_evalue() and mp_int_exptmod_bvalue() to make
+ it easier to work with small bases and small exponents.
+
+ Set default recursive multiplication threshold to 50 digits, since
+ this seems to work best for the platforms I've tested so far.
+
+ Added iprime.h and iprime.c to the distribution.
+
+1.0.4
+ Added `findsizes.pl' to the distribution.
+
+ Revised the type declarations in imath.h to use 32/64 bit
+ operations where the "long long" type is supported.
+
+ Fixed a sign-related bug in mp_int_invmod().
+
+ Fixed several small bugs related to shifting which affect the use
+ of 32-bit digits. Many architectures cannot shift by 32 bits at a
+ time (e.g., MIPS), so I split each of these cases into two shifts
+ of half the size, which should scale properly for both the smaller
+ and larger cases.
+
+ Fixed several arithmetic issues with 32-bit digits that arose due
+ to missing type-casts on the right-hand sides of assignments.
+
+ Fixed s_print() and s_print_buf() to handle the sizes of digits
+ transparently.
+
+1.0.5
+ Updated the Makefile to include the _GNU_SOURCE macro. For many
+ GCC systems, this is necessary to get the correct definition of
+ the ULLONG_MAX macro in <limits.h>. Also, you may now build with
+ the make option DEBUG=Y to enable debugging, e.g.:
+
+ make DEBUG=Y imtest
+
+ By default, the Makefile builds with the optimizer enabled.
+
+ Cleaned up the definitions triggered by USE_LONG_LONG in imath.h,
+ and added an #error instruction in case the build is unable to
+ find a definition of ULLONG_MAX or ULONG_LONG_MAX in <limits.h>.
+ Also added the mp_int_to_unsigned(), mp_int_read_unsigned(), and
+ mp_int_unsigned_len() prototypes.
+
+ Fixed a bug in s_qmul() [imath.c:2493] that would grow the value
+ being multiplied even if there was room in the existing digits to
+ hold the result. This was driving an (apparent) bug in the more
+ general mp_int_read_binary() routine. Added the routines
+ mentioned in the previous paragraph, and factored some common
+ code out into a static s_tobin().
+
+ Added reset_registers() to imdrover.{h,c}. Added new test
+ driver functions test_to_uns() and test_read_uns(). Renamed
+ test_read_bin to test_read_binary().
+
+ Silenced a sign-related warning in pi.c (related to printf).
+
+ Added many new test vectors to tests/conv.t, including the
+ original bug proof-of-concept from Tom Wu, and a series of new
+ tests for the unsigned conversion routines.
+
+ Updated `doc.txt' to reflect the changes described above.
+
+1.0.6
+ Updated copyright notices, added LICENSE file explaining the
+ license I am using. This is basically the BSD license, so
+ you should have no trouble incorporating this code into other
+ open source projects.
+
+ No new functionality in this release.
+
+1.0.7
+ The mp_int_invmod(a, m, c) function would compute a negative value
+ for c when given a < 0. I added some code to insure that the value
+ returned is always the least non-negative member of the congruence
+ class, if the inverse exists. A test for this was added to invmod.t.
+
+1.0.8
+ Fixed a small buffer-overrun in s_qmul(). Because it only
+ allocates an extra digit if it absolutely has to, the test for
+ whether it needs to carry a shift out into the "spare" digit had
+ to be written carefully; I missed a subtlety, which is now
+ fixed. Along the way, I fixed a minor performance-related bug in
+ the same routine.
+
+ Added mp_int_error_string(), which converts mp_result values
+ into descriptive strings. These are statically allocated, so
+ you don't have to free them.
+
+ This version also adds an "examples" subdirectory. Currently,
+ there is only one program there, but I will add more examples as
+ time permits me. You have to read the source to understand them
+ anyway, so I won't explain them here.
+
+1.1.0
+ Added imrat.h and imrat.c, containing routines for rational number
+ arithmetic at arbitrary precision. Added support to the test driver,
+ in imath.c and included various tests in the tests/ subdirectory.
+
+ Fixed a sign-of-zero bug in mp_int_mul(). Tests added to mul.t to
+ regress this fix.
+
+1.1.2
+ Fixed a bug with leading zeroes after the decimal point in the
+ mp_rat_read_decimal() function (imrat.c). Along the way, I also
+ found a sign-related bug, in which -0.5 would be treated as if it
+ were positive, because the sign of zero is implicitly positive,
+ and the denominator is treated as unsigned always.
+
+ Thanks to Eric Silva for pointing out the leading zeroes bug.
+ The solution isn't the most efficient possible.
+
+1.1.3
+ Rewrote mp_int_to_decimal() to support new rounding modes. The
+ modes are documented in doc.txt. Some of the code sucked anyway,
+ so I rewrote pretty much the entire function.
+
+ Added new rounding mode constants.
+
+1.1.4
+ Added mixed rational/integer operations:
+ mp_rat_add_int, mp_rat_sub_int, mp_rat_mul_int, mp_rat_div_int
+ Added rational exponentiation (with integer exponents):
+ mp_rat_expt
+
+ Tests for same were added to the tests/ subdirectory.
+
+1.1.5
+ Added mp_rat_read_cdecimal() and mp_rat_read_ustring()
+ Updated the input.c example.
+
+1.1.6
+ Fixed a bug in mp_int_read_cstring() which would read the string
+ "-0" with incorrect sign (MP_NEG instead of MP_ZPOS). This would
+ violate an invariant that zero is always signed with positives.
+
+ Added some tests to tests/neg.t to catch this case.
+
+1.1.7
+ Fixed a bug in s_udiv(), internal to imath.c, which caused
+ division to fail in some corner cases masked by the use of long
+ long as a word type. As a result, s_udiv() has now been wholly
+ rewritten. I also fixed a few lingering buffer-length errors in
+ s_kmul(), and added a "const" qualifier to the input buffers for
+ the mp_int_read_string() and mp_int_read_cstring() functions,
+ and their analogs in imrat.c.
+
+1.1.8
+ Added mp_int_alloc() and mp_int_free().
+
+1.1.9
+ Added mp_rat_alloc() and mp_rat_free(). Fixed a couple of minor
+ bugs in the doc.txt file. Added mp_int_sqrt() to imath.{h,c} and
+ doc.txt.
+
+1.2
+ Dropped bugfix component of revision number. Fixed rsakey.c
+ example program to be complete and work faster.
+
+1.3
+ Replaced findsizes.pl with findsizes.py. Fixed two bugs in the
+ rsakey tool that were leading to incorrect output.
+
+1.4
+ Fixed a bug in mp_int_alloc(), it was not returning NULL when out
+ of memory, but rather failing in assert() instead. Also, updated
+ the documentation to have better language about the return values
+ in various error conditions.
+
+1.5
+ Changed the API for rational rounding. Removed the two functions
+ mp_rat_set_rounding() and mp_rat_get_rounding(), along with the
+ round_output global variable. Redefined the MP_ROUND_* constants
+ as an enumeration type (mp_round_mode). Added a new parameter to
+ the mp_rat_to_decimal() function to accept a rounding mode. Unit
+ tests and doc.txt updated suitably.
+
+ This release also incorporates a small patch submitted by Jonathan
+ Shapiro to support compilation in C++.
+
+1.6
+ Defined default_precision and multiply_threshold to be constant
+ and static. If IMATH_TEST is defined at compile time, these are
+ made global, and can be modified by the caller (the imtimer tool
+ makes use of this ability, for example).
+
+ Implemented a single-digit optimization suggested by J. Shapiro.
+ Documentation updated.
+
+1.7
+ Fixed a subtle casting problem in the use of the ctype macros that
+ would permit negative signed character values to produce illogical
+ behaviour in some configurations (e.g., NetBSD). Removed a dead
+ "return" statement.
+
+ Added the -pedantic switch for gcc, to get more aggressive
+ warnings; to permit the nonstandard "long long" type to still be
+ used, I also added -Wno-long-long when building with long long
+ enabled (the standard configuration).
+
+ Fixed a bug found by the Samba team running Valgrind on the
+ Heimdal project, and reported by Love Hörnquist Âstrand: One of
+ the intermediate values used during modular exponentiation could
+ be overflowed during recursive multiplication. Fixed by taking a
+ more conservative approach to buffer sizing.
+
+ Added a "contrib" subdirectory, whose first entry is a Makefile
+ to build IMath with the MSVC++ "nmake" program, contributed by
+ Matus Horvath.
+
+1.8
+ Fixed a bug in s_udiv() affecting the computation of quotient
+ digits. Thanks to Love Âstrand for isolating this bug. Also in
+ this release, defining USELLONG=Y or USELLONG=N on the command
+ line for make will switch support for the "long long" data type on
+ or off without having to edit the Makefile. The default is still
+ to permit use of "long long", even though the type is not standard
+ ANSI C90.
+
+1.9
+ Increased the number of small primes used for primality testing to
+ 100 from 32. Removed an unwanted #define from imath.c, left over
+ from testing; added "static" to the declaration of the s_embar()
+ internal function since it is not used outside imath.c. Reduced
+ the quantity of feedback generated by rsakey.c during the prime
+ finding stage of key generation.
+
+1.10
+ All primes less than 1000 are now used in iprime.c for preliminary
+ testing of prime candidates. Removed declaration of s_pad() from
+ rsakey.c example. Added imcalc.c example.
+
+ Beginning with this release, defining the DEBUG preprocessor macro
+ when compiling imath.c causes all the normally-static helper
+ functions to be exported. This makes it easier to troubleshoot
+ bugs in the back end functions without manually editing the source
+ till you have found where the bug actually is.
+
+ Fixed a memory leak in the test driver (imtest.c) where the input
+ buffers allocated for test specs were not released before being
+ released. No impact on the core routines, but nevertheless not a
+ good thing.
+
+ Fixed several uninitialized memory reads and one subtle read past
+ the end of a buffer in s_kmul(), found during a run of Purify.
+ Thanks to Love Hörnquist Âstrand for finding this one, and
+ providing a good test case so I could isolate the problem. Also
+ fixed a buglet in s_kmul(), in which free() was being called
+ instead of s_free(), which would break if you provided a custom
+ version of s_alloc() and s_free() for your application.
+
+1.11
+ Those functions which take int parameters to supply one or more of
+ the arithmetic values of the function have been converted to use a
+ typedef "mp_small". This is defined in imath.h, along with some
+ supporting macros.
+
+ Added mp_int_to_uint() and mp_int_lcm() in imath.{h,c}, based on a
+ patch contributed by Hal Finkel. Added LCM tests as as well as
+ some more GCD tests in tests/lcm.t and tests/gcd.t
+
+ Also at Hal Finkel's request, added mp_int_root() to compute the
+ integer nth root, i.e., \lfloor a^{1/b}\rfloor; replaced the old
+ mp_int_sqrt() function with a call to mp_int_root() via a macro.
+ The new implementation is probably slightly less efficient for
+ square roots, but more general. Added tests/root.t and moved the
+ sqrt tests there, also.
+
+1.12
+ Added a new global constant MP_MINERR which is the value of the
+ smallest error code defined by IMath itself. This can be used by
+ clients who wish to define and use additional error codes, so that
+ those codes will not conflict with the existing set.
+
+ Extended the imcalc example to include memory.
+
+ Fixed a bug in mp_int_add() in which -1 + 1 = -0 (the sign of zero
+ was recorded incorrectly). Added tests to the regression suite
+ for this fix.
+
+1.13
+ Cosmetic change -- updated all the files with my new web address.
+
+ Fixed a buglet caught by Love Hörnquist Âstrand using the LLVM
+ static checker tools, in which a mp_int_copy() failure would be
+ silently ignored and cause an extra copy to be generated.
+
+ Fixed a bug in the testing suite while building on MinGW. The pi
+ generation tests compare to static files and these tests fail if
+ CR/LF is output instead of just LF. The test script now strips
+ all CR and LF from the output and compares to files lacking them.
+ Reported by Chris Cole <cjcole@gmail.com>.
+
+1.14
+ Instead of using the preprocessor to delete "static", the static
+ definitions in imath.c now use an explicit STATIC macro, that is
+ made null when DEBUG is defined. This avoids a subtle problem
+ with static variables defined inside functions (although no bugs
+ actually arose from it).
+
+ Fixed a bug in s_udiv() while building on MinGW. When building
+ with short type digits, the routine was incorrectly discarding
+ overflow when computing the next quotient digit.
+ Reported by Paul DeMarco <pdemarco@ppg.com>.
+
+1.15
+ Fixed a bug in the definition of MP_DIGIT_MAX that caused errors
+ when IMath is built under 64-bit Linux. Reported by
+ Klaus Stengel <klaus.stengel@informatik.stud.uni-erlangen.de>.
+
+ Unpacked the macro definitions in imath.c a bit, to make them more
+ readable.
+
+ Added mp_int_expt_full() by request of Andrea Barberio
+ <insomniac@slackware.it>.
+
+1.16
+ Fixed a bug in mp_int_to_uint() which was causing incorrect MP_RANGE
+ errors during small integer conversion.
+ Reported by Andrea Barberio <insomniac@slackware.it>
+
+ Added mp_int_compare_uvalue().
+ Added some new testing hooks in imtest.c, new unit tests.
+
+ Made some code style changes that do not affect functionality.
+
+1.17
+ Fixed a bug in mp_int_swap() where mpz_t structures using their single
+ field as storage would not get swapped correctly.
+ Reported by Andres Navarro <canavarro82@gmail.com>
+
+ Added regression test for this and some hooks for future
+ regressions in the tests/test.sh script.
+
+1.18
+ Made mp_int_rat() use mp_int_init() to initialize numerator and
+ denominator instead of mp_int_init_size().
+ Some minor code cleanup inside the testing code (imdrover.c).
+
+ Fixed an off-by-one bug in s_udiv() which could cause the quotient
+ guessing loop to spin. Reported by Andres Navarro. Added
+ triggering example to div.t as a regression test.
+
+1.19
+ Fix signedness error in compile. Reported by Paweł Sikora.
diff --git a/polly/lib/External/isl/imath/LICENSE b/polly/lib/External/isl/imath/LICENSE
new file mode 100644
index 00000000000..087fb612583
--- /dev/null
+++ b/polly/lib/External/isl/imath/LICENSE
@@ -0,0 +1,20 @@
+IMath is Copyright © 2002-2009 Michael J. Fromberger
+You may use it subject to the following Licensing Terms:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/polly/lib/External/isl/imath/README.md b/polly/lib/External/isl/imath/README.md
new file mode 100644
index 00000000000..637467177d0
--- /dev/null
+++ b/polly/lib/External/isl/imath/README.md
@@ -0,0 +1,106 @@
+IMath
+=====
+
+Arbitrary precision integer and rational arithmetic library.
+
+IMath is an open-source ANSI C arbitrary precision integer and rational
+arithmetic library.
+
+IMath is copyright &copy; 2002-2009 Michael J. Fromberger.
+
+> Permission is hereby granted, free of charge, to any person obtaining a copy
+> of this software and associated documentation files (the "Software"), to deal
+> in the Software without restriction, including without limitation the rights
+> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+> copies of the Software, and to permit persons to whom the Software is
+> furnished to do so, subject to the following conditions:
+>
+> The above copyright notice and this permission notice shall be included in
+> all copies or substantial portions of the Software.
+>
+> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+> SOFTWARE.
+
+
+About IMath
+-----------
+
+IMath is a library written in portable ANSI C that allows you to perform
+arithmetic on integers and rational numbers of arbitrary precision. While many
+programming languages, including Java, Perl, and Python provide arbitrary
+precision numbers as a standard library or language feature, C does not.
+
+IMath was designed to be small, self-contained, easy to understand and use, and
+as portable as possible across various platforms. The API is simple, and the
+code should be comparatively easy to modify or extend. Simplicity and
+portability are useful goals for some applications&#8212;however, IMath does
+not attempt to break performance records. If you need the fastest possible
+implementation, you might consider some other libraries, such as GNU MP (GMP),
+MIRACL, or the bignum library from OpenSSL.
+
+Programming with IMath
+----------------------
+
+Detailed descriptions of the IMath API can be found in `doc.txt`. However, the
+following is a brief synopsis of how to get started with some simple tasks.
+
+To do basic integer arithmetic, you must declare variables of type `mpz_t` in
+your program, and call the functions defined in `imath.h` to operate on them.
+Here is a simple example that reads one base-10 integer from the command line,
+multiplies it by another (fixed) value, and prints the result to the standard
+output in base-10 notation:
+
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include "imath.h"
+
+ int main(int argc, char *argv[])
+ {
+ mpz_t a, b;
+ char *buf;
+ int len;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: testprogram <integer>\n");
+ return 1;
+ }
+
+ /* Initialize a new zero-valued mpz_t structure */
+ mp_int_init(&a);
+
+ /* Initialize a new mpz_t with a small integer value */
+ mp_int_init_value(&b, 25101);
+
+ /* Read a string value in the specified radix */
+ mp_int_read_string(&a, 10, argv[1]);
+
+ /* Multiply the two together... */
+ mp_int_mul(&a, &b, &a);
+
+ /* Print out the result */
+ len = mp_int_string_len(&a, 10);
+ buf = calloc(len, sizeof(*buf));
+ mp_int_to_string(&a, 10, buf, len);
+ printf("result = %s\n", buf);
+ free(buf);
+
+ /* Release memory occupied by mpz_t structures when finished */
+ mp_int_clear(&b);
+ mp_int_clear(&a);
+
+ return 0;
+ }
+
+This simple example program does not do any error checking, but all the IMath
+API functions return an `mp_result` value which can be used to detect various
+problems like range errors, running out of memory, and undefined results.
+
+The IMath API also supports operations on arbitrary precision rational numbers.
+The functions for creating and manipulating rational values (type `mpq_t`) are
+defined in `imrat.h`, so that you need only include them in your project if you
+wish to.
diff --git a/polly/lib/External/isl/imath/bintest.c b/polly/lib/External/isl/imath/bintest.c
new file mode 100644
index 00000000000..bec34945da2
--- /dev/null
+++ b/polly/lib/External/isl/imath/bintest.c
@@ -0,0 +1,106 @@
+/*
+ Name: bintest.c
+ Purpose: Test driver for binary input/output formats from IMath.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "imath.h"
+
+int main(int argc, char *argv[])
+{
+ unsigned char buf[512];
+ mpz_t v, w;
+ mp_result res;
+ int len;
+
+ if(argc < 2 || argv[1][0] == '\0') {
+ fprintf(stderr, "Usage: bintest <value>\n");
+ return 1;
+ }
+
+ mp_int_init(&v);
+ mp_int_init(&w);
+ res = mp_int_read_string(&v, 10, argv[1]);
+ printf("Result code from mp_int_read_string() = %d (%s)\n",
+ res, mp_error_string(res));
+
+ len = mp_int_binary_len(&v);
+ printf("%d bytes needed to write this value in 2's complement.\n", len);
+
+ res = mp_int_to_binary(&v, buf, sizeof(buf));
+ printf("Result code from mp_int_to_binary() = %d (%s)\n",
+ res, mp_error_string(res));
+ if(res == MP_OK) {
+ int ix;
+
+ for(ix = 0; ix < (len - 1); ++ix)
+ printf("%d.", buf[ix]);
+
+ printf("%d\n", buf[ix]);
+ } else {
+ return 1;
+ }
+
+ /* Try converting back... */
+ res = mp_int_read_binary(&w, buf, len);
+ printf("Result code from mp_int_read_binary() = %d (%s)\n",
+ res, mp_error_string(res));
+ if(res == MP_OK) {
+ mp_int_to_string(&w, 10, (char *) buf, sizeof(buf));
+
+ printf("[%s]\n\n", buf);
+ }
+
+ len = mp_int_unsigned_len(&v);
+ printf("%d bytes needed to write this value as unsigned.\n", len);
+
+ res = mp_int_to_unsigned(&v, buf, sizeof(buf));
+ printf("Result code from mp_int_to_unsigned() = %d\n", res);
+ if(res == MP_OK) {
+ int ix;
+
+ for(ix = 0; ix < (len - 1); ++ix)
+ printf("%d.", buf[ix]);
+
+ printf("%d\n", buf[ix]);
+ } else {
+ return 1;
+ }
+
+ res = mp_int_read_unsigned(&w, buf, len);
+ printf("Result code from mp_int_read_unsigned() = %d (%s)\n",
+ res, mp_error_string(res));
+ if(res == MP_OK) {
+ mp_int_to_string(&w, 10, (char *) buf, sizeof(buf));
+
+ printf("[%s]\n\n", buf);
+ }
+
+ mp_int_clear(&v);
+ mp_int_clear(&w);
+ return 0;
+}
diff --git a/polly/lib/External/isl/imath/bug-swap.c b/polly/lib/External/isl/imath/bug-swap.c
new file mode 100644
index 00000000000..c9adca9f928
--- /dev/null
+++ b/polly/lib/External/isl/imath/bug-swap.c
@@ -0,0 +1,25 @@
+/* Regression test for mp_int_swap() bug on self-stored values. */
+#include <stdio.h>
+#include "imath.h"
+
+int main(int argc, char* argv[]) {
+ mpz_t a, b;
+ int result;
+
+ mp_int_init_value(&a, 1);
+ mp_int_init_value(&b, 16);
+
+ mp_int_swap(&a, &b);
+ result = (a.digits == &(a.single) &&
+ b.digits == &(b.single) &&
+ a.digits[0] == 16 &&
+ b.digits[0] == 1);
+
+ printf("REGRESSION: mp_int_swap() on self-stored values: %s\n",
+ result ? "OK" : "FAILED");
+
+ mp_int_clear(&b);
+ mp_int_clear(&a);
+ return !result;
+}
+
diff --git a/polly/lib/External/isl/imath/contrib/Makefile.msvc b/polly/lib/External/isl/imath/contrib/Makefile.msvc
new file mode 100644
index 00000000000..0eb24fb352a
--- /dev/null
+++ b/polly/lib/External/isl/imath/contrib/Makefile.msvc
@@ -0,0 +1,84 @@
+##
+## Name: Makefile.msvc
+## Purpose: Makefile for IMath library and associated tools
+## for Microsoft Visual Studio 2005
+## Author: Matus Horvath <matus.horvath@nextra.sk>
+##
+## Copyright (C) 2006 Matus Horvath. Permission has been granted to use,
+## modify, and redistribute this file according to the terms of the IMath
+## license.
+##
+## Usage: nmake /f Makefile.msvc
+##
+
+# --- begin configuration section ---
+
+## Settings for Microsoft Windows systems using nmake.
+## To build with debugging, add DEBUG=Y on the "nmake" command line.
+CC=cl.exe
+LD=link.exe
+CFLAGS=$(CFLAGS) -nologo -I. -D_CRT_SECURE_NO_DEPRECATE $(DCFLAGS)
+LDFLAGS=$(LDFLAGS) -nologo $(DLDFLAGS)
+LIBS=$(DLIBS)
+
+!if "$(DEBUG)" == "Y"
+DCFLAGS=-ZI -Od -DDEBUG=1 -DTRACEABLE_FREE=1
+DLDFLAGS=-DEBUG
+#DLIBS=-lefence
+!else
+DCFLAGS=-O2 -Ob2
+DLDFLAGS=
+#DLIBS=
+!endif
+
+## Visual Studio C/C++ 2005 compiler supports "long long" 64-bit type.
+CFLAGS=$(CFLAGS) -DUSE_LONG_LONG
+
+# --- end of configuration section ---
+TARGETS=imtest.exe pi.exe bintest.exe findprime.exe
+HDRS=imath.h imrat.h iprime.h imdrover.h rsamath.h
+SRCS=$(HDRS:.h=.c) $(TARGETS:.exe=.c)
+OBJS=$(SRCS:.c=.obj)
+EXAMPLES=input.exe basecvt.exe rounding.exe
+
+.c.obj:
+ $(CC) $(CFLAGS) -c $<
+
+all: objs examples test
+
+objs: $(OBJS)
+
+# Because Visual Studio does not permit Unix shell syntax, you will
+# have to run the tests manually once the "test" target is built.
+test: imtest.exe pi.exe
+# @ echo ""
+# @ echo "Running tests, you should not see any 'FAILED' lines here."
+# @ echo "If you do, please see doc.txt for how to report a bug."
+# @ echo ""
+# (cd tests && ./test.sh)
+
+$(EXAMPLES): imath.obj imrat.obj iprime.obj examples/$*.obj
+ @move $*.obj examples/$*.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+examples: $(EXAMPLES)
+
+imtest.exe: imtest.obj imath.obj imrat.obj imdrover.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+pi.exe: pi.obj imath.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+findprime.exe: findprime.obj imath.obj iprime.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+rtest.exe: rtest.obj imath.obj rsamath.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+bintest.exe: imath.obj bintest.obj
+ $(LD) $(LDFLAGS) -out:$@ $** $(LIBS)
+
+clean:
+ del /q /f *.exe *.obj examples\*.obj
+
+# End of Makefile.msvc
diff --git a/polly/lib/External/isl/imath/contrib/README b/polly/lib/External/isl/imath/contrib/README
new file mode 100644
index 00000000000..b699944123b
--- /dev/null
+++ b/polly/lib/External/isl/imath/contrib/README
@@ -0,0 +1,3 @@
+The files in this directory have been contributed to the IMath project
+by other authors.
+
diff --git a/polly/lib/External/isl/imath/divide.txt b/polly/lib/External/isl/imath/divide.txt
new file mode 100644
index 00000000000..41092b3a606
--- /dev/null
+++ b/polly/lib/External/isl/imath/divide.txt
@@ -0,0 +1,43 @@
+Algorithm for Arbitrary Precision Unsigned Division
+
+Inputs:
+ A = [a1 ... an] -- array representation
+ B = [b1 ... bm]
+ ai, bi \in {0,..radix}
+
+Preconditions:
+ n >= m
+
+Outputs:
+ Q, R satisfying A = QB + R with 0 <= R < B.
+
+let Q = [], j = n, i = 1, skip = 0 in
+ while j > 0 do
+ if B > A[j,..j + i + 1] then
+ decrement j
+ increment i
+ increment skip
+ if skip > 1 then
+ Q.append(0)
+ else
+ let pfx = A[j] in
+ if pfx < bm and j > 1 then
+ pfx := pfx * radix + A[j - 1]
+
+ q := pfx div bm
+ if q >= radix then
+ if q > radix then
+ q = radix
+ else
+ q := 1
+
+ let t = B * q in
+ while t > A[j,..j + i + 1] do
+ t := t - B
+ decrement q
+
+ Q.append(q)
+ skip := 0
+ end
+
+ result Q, A
diff --git a/polly/lib/External/isl/imath/doc.txt b/polly/lib/External/isl/imath/doc.txt
new file mode 100644
index 00000000000..12f7ee62e55
--- /dev/null
+++ b/polly/lib/External/isl/imath/doc.txt
@@ -0,0 +1,820 @@
+Name: doc.txt
+Purpose: User documentation for IMath library
+Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+--- Installation:
+
+1. Edit Makefile to select compiler and options. The default uses gcc. If you
+ are building under MacOS 10.1.x, you will need to change CC to 'cc' instead
+ of 'gcc', but otherwise you can use the default GCC settings.
+
+ By default, the Makefile assumes you can use the "long long" integer type,
+ even though it is not standard in ANSI C90. You can control this by setting
+ the USELLONG variable in your make command line. Setting USELLONG=Y enables
+ "long long"; USELLONG=N disables it. The default is Y.
+
+ If the built-in types do not work for your particular platform, you can try
+ to find suitable integer type sizes by running the Python program
+ `findsizes.py'. This requires a Python interpreter, version 2.4.x or later.
+
+2. Type 'make' or 'make test' to build the test driver and run the unit tests.
+ None of these should fail. If they do, see below for how you can report
+ bugs.
+
+ To build with debugging enabled (and optimization disabled), run make
+ DEBUG=Y. This sets the preprocessor macro DEBUG to 1, and several other
+ things (see Makefile for details).
+
+To use the library in your code, include "imath.h" wherever you intend to use
+the library's routines. The integer library is just a single source file, so
+you can compile it into your project in whatever way makes sense. If you wish
+to use rational arithmetic, you will also need to include "imrat.h".
+
+--- Background:
+
+The basic types defined by the imath library are mpz_t, an arbitrary precision
+signed integer, and mpq_t, an arbitrary precision signed rational number. The
+type mp_int is a pointer to an mpz_t, and mp_rat is a pointer to an mpq_t.
+
+Most of the functions in the imath library return a value of type mp_result.
+This is a signed integer type which can be used to convey status information
+and also return small values. Any negative value is considered to be a status
+message. The following constants are defined for processing these:
+
+ MP_OK operation successful, all is well (= 0)
+ MP_FALSE boolean false (= MP_OK)
+ MP_TRUE boolean true
+ MP_MEMORY out of memory
+ MP_RANGE parameter out of range
+ MP_UNDEF result is undefined (e.g., division by zero)
+ MP_TRUNC output value was truncated
+ MP_BADARG an invalid parameter was passed
+
+If you obtain a zero or negative value of an mp_result, you can use the
+mp_int_error_string() routine to obtain a pointer to a brief human readable
+string describing the error. These strings are statically allocated, so they
+need not be freed by the caller; the same strings are re-used from call to
+call.
+
+Unless otherwise noted, it is legal to use the same parameter for both inputs
+and output with most of the functions in this library. For example, you can
+add a number to itself and replace the original by writing:
+
+ mp_int_add(a, a, a); /* a = a + a */
+
+Any cases in which this is not legal will be noted in the function summaries
+below (if you discover that this is not so, please report it as a bug; I will
+fix either the function or the documentation :)
+
+--- The IMath API
+
+Each of the API functions is documented here. The general format of the
+entries is:
+
+return_type function_name(parameters ...)
+ English description.
+
+Unless otherwise noted, any API function that returns mp_result may be expected
+to return MP_OK, MP_BADARG, or MP_MEMORY. Other return values should be
+documented in the description. Please let me know if you discover this is not
+the case.
+
+The following macros are defined in "imath.h", to define the sizes of the
+various data types used in the library:
+
+ MP_DIGIT_BIT : the number of bits in a single mpz_t digit.
+ MP_WORD_BIT : the number of bits in a mpz_t word.
+ MP_SMALL_MIN : the minimum value representable by an mp_small.
+ MP_SMALL_MAX : the maximum value representable by an mp_small.
+ MP_USMALL_MIN : the minimum value representable by an mp_usmall.
+ MP_USMALL_MAX : the maximum value representable by an mp_usmall.
+ MP_MIN_RADIX : the minimum radix accepted for base conversion.
+ MP_MAX_RADIX : the maximum radix accepted for base conversion.
+
+An mp_int must be initialized before use. This may be accomplished using the
+following functions:
+
+mp_result mp_int_init(mp_int z);
+ Initializes z with a default precision, sets the value to zero. This
+ function cannot fail unless z is NULL.
+
+mp_int mp_int_alloc();
+ Dynamically allocates an mpz_t, initializes it to the value zero, and
+ returns a pointer to it. Returns NULL in case of error (the only
+ error possible is MP_MEMORY in this case).
+
+mp_result mp_int_init_size(mp_int z, mp_size prec);
+ Initializes z with at least prec digits of storage, sets the value to
+ zero. If prec is zero, the default size is used, defined in imath.h
+ as MP_DEFAULT_PREC. The size is rounded up to the nearest word
+ boundary.
+
+mp_result mp_int_init_copy(mp_int z, mp_int old);
+ Initializes z to be a copy of an already-initialized mp_int in old.
+ They do not share storage.
+
+mp_result mp_int_init_value(mp_int z, mp_small value);
+ Initializes z with default precision and sets its value to the value
+ of the supplied integer.
+
+To copy one mp_int to another, use:
+
+mp_result mp_int_copy(mp_int a, mp_int c);
+ Copies the value of a into c. Does not allocate new memory unless a
+ has more significant digits than c has room for.
+
+When you are finished with an mp_int, you must free the memory it uses:
+
+void mp_int_clear(mp_int z);
+ Releases the storage used by z.
+
+void mp_int_free(mp_int z);
+ Releases the storage used by z, and frees the mpz_t structure z
+ points to. This should only be used for values allocated by
+ mp_int_alloc().
+
+To set an mp_int, which has already been initialized, to a small integer value,
+use the following:
+
+mp_result mp_int_set_value(mp_int z, mp_small value);
+ Sets the value of z to the value of the supplied integer.
+
+By default, an mp_int is initialized with a certain minimum amount of storage
+for digits. This storage is expanded automatically as needed.
+
+- The arithmetic functions are:
+
+int mp_int_is_odd(mp_int z);
+ Returns true if z is an odd integer (z = 1 (mod 2))
+ [currently implemented as a macro]
+
+int mp_int_is_even(mp_int z);
+ Returns true if z is an even integer (z = 0 (mod 2))
+ [currently implemented as a macro]
+
+void mp_int_zero(mp_int z);
+ Sets z to zero.
+
+mp_result mp_int_abs(mp_int a, mp_int c);
+ Sets c to the absolute value of a.
+ If a < 0, c = -a, else c = a.
+
+mp_result mp_int_neg(mp_int a, mp_int c);
+ Sets c to be the additive inverse of a, c = -a.
+
+mp_result mp_int_add(mp_int a, mp_int b, mp_int c);
+ Computes c = a + b.
+
+mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c);
+ Computes c = a + value, where value is a small integer.
+
+mp_result mp_int_sub(mp_int a, mp_int b, mp_int c);
+ Computes c = a - b.
+
+mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c);
+ Computes c = a - value, where value is a small integer.
+
+mp_result mp_int_mul(mp_int a, mp_int b, mp_int c);
+ Computes c = a * b
+
+mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c);
+ Computes c = a * value, where value is a small integer.
+
+mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);
+ Computes c = a * 2^p2, where p2 >= 0.
+
+mp_result mp_int_sqr(mp_int a, mp_int c);
+ Computes c = a * a. Faster than using mp_int_mul(a, a, c).
+
+mp_result mp_int_root(mp_int a, mp_small b, mp_int c);
+ Computes c = floor(a^{1/b}). Returns MP_UNDEF if the root is
+ undefined, i.e., if a < 0 and b is even. Uses Newton's method to
+ obtain the root.
+
+mp_result mp_int_sqrt(mp_int a, mp_int c);
+ Computes c = floor(sqrt(a)) if a >= 0. Returns MP_UNDEF if
+ a < 0.
+ [currently implemented as a macro]
+
+mp_result mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r);
+ Computes q, r such that a = bq + r and 0 <= r < b.
+
+ Pass NULL for q or r if you don't need its value. Detects and
+ handles division by powers of two in an efficient manner. Returns
+ MP_UNDEF if b = 0. If both q and r point to the same non-NULL
+ location, their values on output will be arbitrary (usually
+ incorrect).
+
+mp_result mp_int_div_value(mp_int a, mp_small v, mp_int q, mp_small *r);
+ Computes q, r such that a = qv + r and 0 <= r < v, where v is a small
+ integer. Pass NULL for q or r if you don't need its value.
+
+mp_result mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r);
+ Computes q, r such that a = q * 2^p2 + r. This is a special case for
+ division by powers of two that is much more efficient than using the
+ regular division algorithm. Note that mp_int_div() will
+ automatically handle this case if b = 2^k for some k >= 0;
+ mp_int_div_pow2() is for when you have only the exponent, not the
+ expanded value.
+
+mp_result mp_int_mod(mp_int a, mp_int m, mp_int c);
+ Computes the least non-negative residue of a (mod m), and assigns the
+ result to c.
+
+mp_result mp_int_mod_value(mp_int a, mp_int value, mp_small *r);
+ Computes the least non-negative residue of a (mod value), where value
+ is a small integer, and assigns the result to r.
+
+mp_result mp_int_expt(mp_int a, mp_small b, mp_int c);
+ Raises a to the b power, and assigns the result to c. It is an error
+ if b < 0.
+
+mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c);
+ Raises a to the b power, and assigns the result to c. It is an error
+ if b < 0.
+
+mp_result mp_int_expt_full(mp_int a, mp_int b, mp_int c);
+ Raises a to the b power, and assigns the result to c. It is an error
+ if b < 0.
+
+- Comparison functions:
+
+Unless otherwise specified, comparison between values x and y returns a value <
+0 if x is less than y, = 0 if x is equal to y, and > 0 if x is greater than y.
+
+int mp_int_compare(mp_int a, mp_int b);
+ Signed comparison of a and b.
+
+int mp_int_compare_unsigned(mp_int a, mp_int b);
+ Unsigned (magnitude) comparison of a and b. The signs of a and b are
+ not modified.
+
+int mp_int_compare_zero(mp_int z);
+ Compare z to zero.
+
+int mp_int_compare_value(mp_int z, mp_small value);
+int mp_int_compare_uvalue(mp_int z, mp_usmall value);
+ Compare z to small signed (value) or unsigned (uvalue) integer value.
+
+int mp_int_divisible_value(mp_int a, mp_small v);
+ Returns true (nonzero) if a is divisible by small integer v,
+ otherwise false (zero)
+
+int mp_int_is_pow2(mp_int z);
+ Returns k >= 0 such that z = 2^k, if such a k exists; otherwise a
+ value < 0 is returned.
+
+- Other useful functions:
+
+mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c);
+ Efficiently computes c = a^b (mod m).
+ Returns MP_UNDEF if m = 0; returns MP_RANGE if b < 0.
+
+mp_result mp_int_exptmod_evalue(mp_int a, mp_small v, mp_int m, mp_int c);
+ Efficiently computes c = a^v (mod m).
+mp_result mp_int_exptmod_bvalue(mp_small v, mp_int b, mp_int m, mp_int c);
+ Efficiently computes c = v^b (mod m).
+
+ Note: These routines use Barrett's algorithm for modular reduction.
+ It is widely held (probably correctly) that using Peter Montgomery's
+ multiplication algorithm would make this operation faster; but that
+ algorithm has the restriction that a and m must be coprime, so I have
+ not implemented it here.
+
+mp_result mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu,
+ mp_int c);
+ Efficiently computes c = a^b (mod m), given a precomputed reduction
+ constant mu, as defined for Barrett's modular reduction algorithm.
+ Returns MP_UNDEF if m = 0; returns MP_RANGE if b < 0.
+
+mp_result mp_int_redux_const(mp_int m, mp_int c);
+ Computes reduction constant mu for Barrett reduction by modulus m,
+ stores the result in c.
+
+mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c);
+ Computes the modular inverse of a (mod m), if it exists, and assigns
+ the result to c. Returns the least non-negative representative of
+ the congruence class (mod m) containing this inverse. Returns
+ MP_UNDEF if the inverse does not exist; returns MP_RANGE if a = 0 or
+ m <= 0.
+
+mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c);
+ Compute the greatest common divisor if a and b, and assign the result
+ to c. Returns MP_UNDEF if the GCD is not defined (e.g., if a = 0 and
+ b = 0).
+
+mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, mp_int x, mp_int y);
+ Compute the greatest common divisor of a and b, and assign the result
+ to c. Also computes x and y satisfying Bezout's identity, namely (a,
+ b) = ax + by. Returns MP_UNDEF if the GCD is not defined (e.g., if a
+ = b = 0).
+
+mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c)
+ Compute the least common multiple of a and b, and assign the result
+ to c. Returns MP_UNDEF if the LCM is not defined (e.g., if a = 0 and
+ b = 0).
+
+- Conversion of values:
+
+mp_result mp_int_to_int(mp_int z, mp_small *out);
+ Convert z to an int type, if it is representable as such. Returns
+ MP_RANGE if z cannot be represented as an value of type mp_small. If
+ out is NULL no value is stored, but the return value will still be
+ correct.
+
+mp_result mp_int_to_uint(mp_int z, mp_usmall *out);
+ Convert z to an unsigned int type, if it is representable as such.
+ Returns MP_RANGE if z cannot be represented as a value of type
+ mp_usmall. If out is NULL no value is stored, but the return value
+ will still be correct.
+
+mp_result mp_int_to_string(mp_int z, mp_size radix, char *str, int limit);
+ Convert z to a zero-terminated string of characters in the given
+ radix, writing at most 'limit' characters including the terminating
+ NUL value. A leading '-' is used to indicate a negative value.
+
+ Returns MP_RANGE if radix < MP_MIN_RADIX or radix > MP_MAX_RADIX.
+ Returns MP_TRUNC if limit is too small to write out all of z.
+
+mp_result mp_int_string_len(mp_int z, mp_size radix);
+ Return the minimum number of characters required to represent z as a
+ zero-terminated string of characters in the given radix. May
+ over-estimate (but generally will not).
+
+ Returns MP_RANGE if radix < MP_MIN_RADIX or radix > MP_MAX_RADIX.
+
+mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);
+mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
+ char **end);
+ Read a string of ASCII digits in the specified radix from the
+ zero-terminated string provided, and assign z to the corresponding
+ value. For radices greater than 10, the ASCII letters 'A' .. 'Z' or
+ 'a' .. 'z' are used. Letters are interpreted without respect to
+ case.
+
+ Leading whitespace is ignored, and a leading '+' or '-' is
+ interpreted as a sign flag. Processing stops when ASCII NUL or any
+ character which is out of range for a digit in the given radix is
+ encountered.
+
+ If the whole string was processed, MP_OK is returned; otherwise,
+ MP_TRUNC is returned.
+
+ Returns MP_RANGE if radix < MP_MIN_RADIX or radix > MP_MAX_RADIX.
+
+ With mp_int_read_cstring(), if end is not NULL, the target pointer is
+ set to point to the first unconsumed character of the input string
+ (the NUL byte, if the whole string was consumed). This emulates the
+ behavior of the standard C strtol() function.
+
+mp_result mp_int_count_bits(mp_int z);
+ Returns the number of significant bits in z.
+
+mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
+ Convert z to 2's complement binary, writing at most 'limit' bytes
+ into the given buffer. Returns MP_TRUNC if the buffer limit was too
+ small to contain the whole value. If this occurs, the contents of
+ buf will be effectively garbage, as the function uses the buffer as
+ scratch space.
+
+ The binary representation of z is in base-256 with digits ordered
+ from most significant to least significant (network byte ordering).
+ The high-order bit of the first byte is set for negative values,
+ clear for non-negative values.
+
+ As a result, non-negative values will be padded with a leading zero
+ byte if the high-order byte of the base-256 magnitude is set. This
+ extra byte is accounted for by the mp_int_binary_len() function
+ described below.
+
+mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);
+ Read a 2's complement binary value into z, where the length of the
+ buffer is given as 'len'. The contents of 'buf' may be overwritten
+ during processing, although they will be restored when the function
+ returns.
+
+mp_result mp_int_binary_len(mp_int z);
+ Return the number of bytes required to represent z in 2's complement
+ binary.
+
+mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
+ Convert |z| to unsigned binary, writing at most 'limit' bytes into
+ the given buffer. The sign of z is ignored, but z is not modified.
+ Returns MP_TRUNC if the buffer limit was too small to contain the
+ whole value. If this occurs, the contents of buf will be effectively
+ garbage, as the function uses the buffer as scratch space during
+ conversion.
+
+ The binary representation of z is in base-256 with digits ordered
+ from most significant to least significant (network byte ordering).
+
+mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
+ Read an unsigned binary value into z, where the length of the buffer
+ is given as 'len'. The contents of 'buf' will not be modified during
+ processing.
+
+mp_result mp_int_unsigned_len(mp_int z);
+ Return the number of bytes required to represent z as an unsigned
+ binary value using mp_int_to_unsigned().
+
+- Other functions:
+
+Ordinarily, integer multiplication and squaring are done using the simple
+quadratic "schoolbook" algorithm. However, for sufficiently large values,
+there is a more efficient algorithm usually attributed to Karatsuba and Ofman
+that is usually faster. See Knuth Vol. 2 for more details about how this
+algorithm works.
+
+The breakpoint between the "normal" and the recursive algorithm is controlled
+by a static constant "multiply_threshold" defined in imath.c, which contains
+the number of significant digits below which the standard algorithm should be
+used. This is initialized to the value of the compile-time constant
+MP_MULT_THRESH from imath.h. If you wish to be able to modify this value at
+runtime, compile imath.c with IMATH_TEST defined true in the preprocessor, and
+declare
+
+ extern mp_size multiply_threshold;
+
+When IMATH_TEST is defined, this variable is defined as a mutable global, and
+can be changed. Otherwise, it is defined as an immutable static constant. The
+`imtimer' program and the `findthreshold.py' script (Python) can help you find
+a suitable value for MP_MULT_THRESH for your particular platform.
+
+const char *mp_int_error_string(mp_result res);
+ Return a pointer to a brief string describing 'res'. These strings
+ are defined as a constant array in `imath.c', if you wish to change
+ them for your application.
+
+--- Rational Arithmetic:
+
+mp_result mp_rat_init(mp_rat r);
+ Initialize a new zero-valued rational number in r.
+
+mp_result mp_rat_reduce(mp_rat r);
+ Reduce a rational to canonical form.
+ Removes common factors from the numerator and denomenator and makes
+ the denomenator positive.
+
+mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec);
+ As mp_rat_init(), but specifies the number of long digits of
+ precision for numerator (n_prec) and denominator (d_prec). Use this
+ if you wish to preallocate storage for operations of known output
+ size.
+
+mp_result mp_rat_init_copy(mp_rat r, mp_rat old);
+ As mp_rat_init(), but initializes a copy of an existing rational
+ value.
+
+mp_result mp_rat_set_value(mp_rat r, mp_small numer, mp_small denom);
+ Set the value of the given rational to a ratio specified as ordinary
+ signed integers (denom != 0). Returns MP_UNDEF if denom = 0.
+
+void mp_rat_clear(mp_rat r);
+ Release the memory occupied by the given rational number.
+
+mp_result mp_rat_numer(mp_rat r, mp_int z);
+ Extract the numerator of r as an mp_int, and store it in z.
+
+mp_result mp_rat_denom(mp_rat r, mp_int z);
+ Extract the denominator of r as an mp_int, and store it in z.
+
+mp_sign mp_rat_sign(mp_rat r);
+ Return the sign of the rational number. Note that an mpq_t
+ is always stored so that the sign of the numerator is the
+ correct sign of the whole value.
+
+mp_result mp_rat_copy(mp_rat a, mp_rat c);
+ Copy a to c. Avoids unnecessary allocations.
+
+void mp_rat_zero(mp_rat r);
+ Set r to have the value zero (canonical with denominator 1).
+
+mp_result mp_rat_abs(mp_rat a, mp_rat c);
+ Set c to the absolute value of a.
+
+mp_result mp_rat_neg(mp_rat a, mp_rat c);
+ Set c to the negative (additive inverse) of a.
+
+mp_result mp_rat_recip(mp_rat a, mp_rat c);
+ Take the reciprocal of a and store it in c, if defined.
+ Returns MP_UNDEF if a/c = 0.
+
+mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c);
+ Add a + b and store the result in c.
+
+mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c);
+ Subtract a - b and store the result in c.
+
+mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c);
+ Multiply a * b and store the result in c.
+
+mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c);
+ Divide a / b, if possible, and store the result in c.
+ Returns MP_UNDEF if b = 0.
+
+mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c);
+ Add a + b and store the result in c. Note: b is an integer.
+
+mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c);
+ Subtract a - b and store the result in c. Note: b is an integer.
+
+mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c);
+ Multiply a * b and store the result in c. Note: b is an integer.
+
+mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c);
+ Divide a / b, if possible, and store the result in c.
+ Note: b is an integer.
+ Returns MP_UNDEF if b = 0.
+
+mp_result mp_rat_expt(mp_rat a, mp_small b, mp_rat c);
+ Raise a to the b power, where b >= 0, and store the result in c.
+
+int mp_rat_compare(mp_rat a, mp_rat b);
+ Full signed comparison of rational values.
+
+int mp_rat_compare_unsigned(mp_rat a, mp_rat b);
+ Compare the absolute values of a and b.
+
+int mp_rat_compare_zero(mp_rat r);
+ Compare r to zero.
+
+int mp_rat_compare_value(mp_rat r, mp_small n, mp_small d);
+ Compare r to the ratio n/d.
+
+int mp_rat_is_integer(mp_rat r);
+ Returns true if r can be represented by an integer (i.e.,
+ its denominator is one).
+
+mp_result mp_rat_to_ints(mp_rat r, mp_small *num, mp_small *den);
+ If it is possible to do so, extract the numerator and the denominator
+ of r as regular (signed) integers. Returns MP_RANGE if either cannot
+ be so represented.
+
+mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit);
+ Convert the value of r to a string of the format "n/d" with n and d
+ in the specified radix, writing no more than "limit" bytes of data to
+ the given output buffer. Includes sign flag.
+
+mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec,
+ mp_round_mode rmode, char *str, int limit);
+ Convert the value of r to a string in decimal-point notation with the
+ specified radix, writing no more than "limit" bytes of data to the
+ given output buffer. Generates "prec" digits of precision.
+
+ Values numbers may be rounded when they are being converted for
+ output as a decimal value. There are four rounding modes currently
+ supported:
+
+ MP_ROUND_DOWN
+ Truncates the value toward zero.
+ Example: 12.009 to 2dp becomes 12.00
+
+ MP_ROUND_UP
+ Rounds the value away from zero:
+ Example: 12.001 to 2dp becomes 12.01, but
+ 12.000 to 2dp remains 12.00
+
+ MP_ROUND_HALF_DOWN
+ Rounds the value to nearest digit, half goes toward zero.
+ Example: 12.005 to 2dp becomes 12.00, but
+ 12.006 to 2dp becomes 12.01
+
+ MP_ROUND_HALF_UP
+ Rounds the value to nearest digit, half rounds upward.
+ Example: 12.005 to 2dp becomes 12.01, but
+ 12.004 to 2dp becomes 12.00
+
+mp_result mp_rat_string_len(mp_rat r, mp_size radix);
+ Return the length of buffer required to convert r using the
+ mp_rat_to_string() function. May over-estimate slightly.
+
+mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec);
+ Return the length of buffer required to convert r using the
+ mp_rat_to_decimal() function. May over-estimate slightly.
+
+mp_result mp_rat_read_string(mp_rat r, mp_size radix, char *str);
+ Read a zero-terminated string in the format "n/d" (including sign
+ flag), and replace the value of r with it.
+
+mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, char *str, char **end);
+ Like mp_rat_read_string(), but with a similar interface to the
+ strtoul() library function. Used as the back end for the
+ mp_rat_read_string() function. Returns MP_UNDEF if the denominator
+ read has value zero.
+
+mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, char *str, char **end);
+ A "universal" reader. Capable of reading plain integers, rational
+ number written in a/b notation, and decimal values in z.f format.
+ The end parameter works as for mp_int_read_cstring().
+
+mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, char *str);
+ A wrapper around mp_rat_read_cdecimal(), which discards the resulting
+ end pointer.
+
+mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, char *str, char **end);
+ Read a zero-terminated string in the format "z.f" (including sign
+ flag), and replace r with its value. If end is not NULL, a pointer
+ to the first unconsumed character of the string is returned.
+
+--- Representation Details
+
+ NOTE: You do not need to read this section to use IMath. This is provided
+ for the benefit of developers wishing to extend or modify the
+ internals of the library.
+
+IMath uses a signed magnitude representation for arbitrary precision integers.
+The magnitude is represented as an array of radix-R digits in increasing order
+of significance; the value of R is chosen to be half the size of the largest
+available unsigned integer type, so typically 16 or 32 bits. Digits are
+represented as mp_digit, which must be an unsigned integral type.
+
+Digit arrays are allocated using malloc(3) and realloc(3). Because this can be
+an expensive operation, the library takes pains to avoid allocation as much as
+possible. For this reason, the mpz_t structure distinguishes between how many
+digits are allocated and how many digits are actually consumed by the
+representation. The fields of an mpz_t are:
+
+ mp_digit single; /* single-digit value (see note) */
+ mp_digit *digits; /* array of digits */
+ mp_size alloc; /* how many digits are allocated */
+ mp_size used; /* how many digits are in use */
+ mp_sign sign; /* the sign of the value */
+
+The elements of "digits" at indices less than "used" are the significant
+figures of the value; the elements at indices greater than or equal to "used"
+are undefined (and may contain garbage). At all times, "used" must be at least
+1 and at most "alloc".
+
+To avoid interaction with the memory allocator, single-digit values are stored
+directly in the mpz_t structure, in the .single field. The semantics of access
+are the same as the more general case.
+
+The number of digits allocated for an mpz_t is referred to in the library
+documentation as its "precision". Operations that affect an mpz_t cause
+precision to increase as needed. In any case, all allocations are measured in
+digits, and rounded up to the nearest mp_word boundary. There is a default
+minimum precision stored as a static constant default_precision (imath.c); its
+value is set to MP_DEFAULT_PREC (imath.h). If the preprocessor symbol
+IMATH_TEST is defined, this value becomes global and modifiable.
+
+Note that the allocated size of an mpz_t can only grow; the library never
+reallocates in order to decrease the size. A simple way to do so explicitly is
+to use mp_int_init_copy(), as in:
+
+ mpz_t big, new;
+
+ /* ... */
+ mp_int_init_copy(&new, &big);
+ mp_int_swap(&new, &big);
+ mp_int_clear(&new);
+
+The value of "sign" is 0 for positive values and zero, 1 for negative values.
+Constants MP_ZPOS and MP_NEG are defined for these; no other sign values are
+used.
+
+If you are adding to this library, you should be careful to preserve the
+convention that inputs and outputs can overlap, as described above. So, for
+example, mp_int_add(a, a, a) is legal. Often, this means you must maintain one
+or more temporary mpz_t structures for intermediate values. The private macros
+SETUP(E, C) and TEMP(K) can be used to enforce a conventional structure like
+this:
+
+ {
+ mpz_t temp[NUM_TEMPS]; /* declare how many you need here */
+ int last = 0; /* number of in-use temps */
+ mp_result res; /* used for checking results */
+ ...
+
+ /* Initialization phase */
+ SETUP(mp_int_init(TEMP(0)), last);
+ SETUP(mp_int_init_copy(TEMP(1), x), last);
+ ...
+ SETUP(mp_int_init_value(TEMP(7), 3), last);
+
+ /* Work phase */
+ ...
+
+ CLEANUP:
+ while(--last >= 0)
+ mp_int_clear(TEMP(last));
+
+ return res;
+ }
+
+The names "temp" and "res" are fixed -- the SETUP and TEMP macros assume they
+exist. TEMP(k) returns a pointer to the kth entry of temp. This structure
+insures that even if a failure occurs during the "initialization phase", no
+memory is leaked.
+
+"Small" integer values are represented by the types mp_small and mp_usmall,
+which are mapped to appropriately-sized types on the host system. The default
+for mp_small is "long" and the default for mp_usmall is "unsigned long". You
+may change these, provided you insure that mp_small is signed and mp_usmall is
+unsigned. You will also need to adjust the size macros:
+
+ MP_SMALL_MIN, MP_SMALL_MAX
+ MP_USMALL_MIN, MP_USMALL_MAX
+
+... which are defined in <imath.h>, if you change these.
+
+Rational numbers are represented using a pair of arbitrary precision integers,
+with the convention that the sign of the numerator is the sign of the rational
+value, and that the result of any rational operation is always represented in
+lowest terms. The canonical representation for rational zero is 0/1. See
+"imrat.h".
+
+--- Testing and Reporting of Bugs:
+
+Test vectors are included in the 'tests' subdirectory of the imath
+distribution. When you run 'make test', it builds the imtest program and runs
+all available test vectors. If any tests fail, you will get a line like this:
+
+ x y FAILED v
+
+Here, x is the line number of the test which failed, y is index of the test
+within the file, and v is the value(s) actually computed. The name of the file
+is printed at the beginning of each test, so you can find out what test vector
+failed by executing the following (with x, y, and v replaced by the above
+values, and where "foo.t" is the name of the test file that was being processed
+at the time):
+
+ % tail +x tests/foo.t | head -1
+
+None of the tests should fail [but see Note 2]; if any do, it probably
+indicates a bug in the library (or at the very least, some assumption I made
+which I shouldn't have). Please send a bug report to the address below, which
+includes the FAILED test line above, as well as the output of the above 'tail'
+command (so I know what inputs caused the failure).
+
+If you build with the preprocessor symbol DEBUG defined as a positive integer,
+you will have access to several things:
+
+ 1. The static functions defined in imath.c are made globally visible so that
+ you can call them from a test driver.
+
+ 2. The s_print() and s_print_buf() routines are defined; these make it easier
+ to dump the contents of an mpz_t to text.
+
+ 3. If DEBUG > 1, the digit allocators (s_alloc, s_realloc) fill all new
+ buffers with the value 0xDEADBEEF, or as much of it as will fit in a digit,
+ so that you can more easily catch uninitialized reads in the debugger.
+
+--- Notes:
+
+1. You can generally use the same variables for both input and output. One
+ exception is that you may not use the same variable for both the quotient
+ and the remainder of mp_int_div().
+
+2. Many of the tests for this library were written under the assumption that
+ the mp_small type is 32 bits or more. If you compile with a smaller type,
+ you may see MP_RANGE errors in some of the tests that otherwise pass (due to
+ conversion failures). Also, the pi generator (pi.c) will not work correctly
+ if mp_small is too short, as its algorithm for arc tangent is fairly
+ simple-minded.
+
+--- Contacts:
+
+The IMath library was written by
+Michael J. Fromberger <http://spinning-yarns.org/michael/>
+
+If you discover any bugs or testing failures, please send e-mail to
+the following address:
+
+ <michael.j.fromberger@gmail.com>
+
+Please be sure to include, with any bug report, a complete description of what
+goes wrong, and if possible, a test vector for imtest or a minimal test program
+that will demonstrate the bug on your system. Please also let me know what
+hardware, operating system, and compiler you're using.
+
+--- Acknowledgements:
+
+The algorithms used in this library came from Vol. 2 of Donald Knuth's "The Art
+of Computer Programming" (Seminumerical Algorithms). Thanks to Nelson Bolyard,
+Bryan Olson, Tom St. Denis, Tushar Udeshi, and Eric Silva for excellent
+feedback on earlier versions of this code. Special thanks to Jonathan Shapiro
+for some very helpful design advice, as well as feedback and some clever ideas
+for improving performance in some common use cases.
+
+--- License and Disclaimers:
+
+IMath is Copyright 2002-2009 Michael J. Fromberger
+You may use it subject to the following Licensing Terms:
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/polly/lib/External/isl/imath/examples/basecvt.c b/polly/lib/External/isl/imath/examples/basecvt.c
new file mode 100644
index 00000000000..c067be904f1
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/basecvt.c
@@ -0,0 +1,121 @@
+/*
+ Name: basecvt.c
+ Purpose: Convert integers and rationals from one base to another.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+ Info: $Id: basecvt.c 635 2008-01-08 18:19:40Z sting $
+
+ Copyright (C) 2004-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "imath.h"
+#include "imrat.h"
+
+int main(int argc, char *argv[])
+{
+ mp_size in_rdx, out_rdx;
+ mpq_t value;
+ mp_result res;
+ int ix;
+
+ if(argc < 4) {
+ fprintf(stderr, "Usage: basecvt <ibase> <obase> <values>+\n");
+ return 1;
+ }
+
+ in_rdx = atoi(argv[1]);
+ out_rdx = atoi(argv[2]);
+
+ if(in_rdx < MP_MIN_RADIX || in_rdx > MP_MAX_RADIX) {
+ fprintf(stderr,
+ "basecvt: input radix %u not allowed (minimum %u, "
+ "maximum %u)\n", in_rdx, MP_MIN_RADIX, MP_MAX_RADIX);
+ return 3;
+ }
+ if(out_rdx < MP_MIN_RADIX || out_rdx > MP_MAX_RADIX) {
+ fprintf(stderr,
+ "basecvt: output radix %u not allowed (minimum %u, "
+ "maximum %u)\n", out_rdx, MP_MIN_RADIX, MP_MAX_RADIX);
+ return 3;
+ }
+
+ if((res = mp_rat_init(&value)) != MP_OK) {
+ fprintf(stderr, "basecvt: out of memory\n");
+ return 2;
+ }
+
+ for(ix = 3; ix < argc; ++ix) {
+ char *buf, *endp = NULL;
+ mp_result len;
+ int is_int;
+
+ if((res = mp_rat_read_ustring(&value, in_rdx, argv[ix], &endp)) != MP_OK &&
+ res != MP_TRUNC) {
+ fprintf(stderr, "basecvt: error reading argument %d: %s\n", ix,
+ mp_error_string(res));
+ break;
+ }
+ else if(*endp != '\0') {
+ fprintf(stderr, "basecvt: argument %d contains '%s' not in base %u\n",
+ ix, endp, in_rdx);
+ continue;
+ }
+
+ if((is_int = mp_rat_is_integer(&value)) != 0) {
+ len = mp_int_string_len(MP_NUMER_P(&value), out_rdx);
+ }
+ else {
+ len = mp_rat_string_len(&value, out_rdx);
+ }
+
+ if((buf = malloc(len)) == NULL) {
+ fprintf(stderr, "basecvt: out of memory\n");
+ break;
+ }
+
+ if(is_int) {
+ res = mp_int_to_string(MP_NUMER_P(&value), out_rdx, buf, len);
+ }
+ else {
+ res = mp_rat_to_string(&value, out_rdx, buf, len);
+ }
+
+ if(res != MP_OK) {
+ fprintf(stderr, "basecvt: error converting argument %d: %s\n", ix,
+ mp_error_string(res));
+ free(buf);
+ break;
+ }
+
+ printf("%s\n", buf);
+ free(buf);
+ }
+
+ mp_rat_clear(&value);
+
+ return (res != MP_OK);
+}
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/examples/findprime.c b/polly/lib/External/isl/imath/examples/findprime.c
new file mode 100644
index 00000000000..070f14194d9
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/findprime.c
@@ -0,0 +1,72 @@
+/*
+ Name: findprime.c
+ Purpose: Find probable primes.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+ Info: $Id: findprime.c 635 2008-01-08 18:19:40Z sting $
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Notes:
+ Find the first prime number in sequence starting from the given value.
+ Demonstrates the use of mp_int_find_prime().
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "iprime.h"
+
+int main(int argc, char *argv[])
+{
+ char buf[4096];
+ mpz_t seed;
+ mp_result res;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s <start-value>\n", argv[0]);
+ return 1;
+ }
+
+ mp_int_init(&seed);
+ if((res = mp_int_read_string(&seed, 10, argv[1])) != MP_OK) {
+ fprintf(stderr, "%s: error reading `%s': %d\n",
+ argv[0], argv[1], res);
+ return 2;
+ }
+
+ if(mp_int_compare_value(&seed, 131) <= 0) {
+ fprintf(stderr, "%s: please enter a start value > 131\n",
+ argv[0]);
+ return 1;
+ }
+
+ if((res = mp_int_find_prime(&seed)) != MP_TRUE) {
+ fprintf(stderr, "%s: error finding prime: %d\n",
+ argv[0], res);
+ return 2;
+ }
+
+ mp_int_to_string(&seed, 10, buf, sizeof(buf));
+ printf("=> %s\n", buf);
+
+ mp_int_clear(&seed);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/imath/examples/imcalc.c b/polly/lib/External/isl/imath/examples/imcalc.c
new file mode 100644
index 00000000000..97f0dc5affb
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/imcalc.c
@@ -0,0 +1,1471 @@
+/*
+ Name: imcalc.c
+ Purpose: Simple RPN calculator based on IMath library.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ This is a very simplistic RPN calculator that will let you test the features
+ of the IMath built-in functions.
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <unistd.h>
+
+#include "imath.h"
+#include "imrat.h"
+#include "iprime.h"
+
+/* A cstate_t represents a stack of operands; numeric operands are pushed on
+ the stack, and commands cause them to be consumed in various ways.
+ */
+typedef struct {
+ /* Operand stack */
+ mp_int *elts;
+ mp_size alloc; /* number of slots available */
+ mp_size used; /* number of slots free */
+
+ /* Named variables */
+ mp_int *mem; /* named memory slots */
+ char **names; /* names of memory slots */
+ mp_size mslots; /* number of memory slots */
+ mp_size mused; /* number of used memories */
+
+ /* I/O components */
+ FILE *ifp; /* input file handle */
+ char *ibuf; /* input scratch buffer */
+ int buflen; /* size of scratch buffer */
+} cstate_t;
+
+/* {{{ State function prototypes */
+
+static mp_result state_init(cstate_t *sp, mp_size n_elts);
+static void state_clear(cstate_t *sp);
+static void stack_flush(cstate_t *sp);
+static mp_result stack_push(cstate_t *sp, mp_int elt);
+static mp_result stack_pop(cstate_t *sp);
+static mp_result mem_insert(cstate_t *sp, const char *name, mp_int value);
+static mp_result mem_recall(cstate_t *sp, const char *name, mp_int value);
+static mp_result mem_clear(cstate_t *sp);
+
+/* }}} */
+
+/* {{{ Calculation function prototypes */
+
+typedef mp_result (*op_func)(cstate_t *);
+
+static mp_result cf_abs(cstate_t *sp);
+static mp_result cf_neg(cstate_t *sp);
+static mp_result cf_add(cstate_t *sp);
+static mp_result cf_sub(cstate_t *sp);
+static mp_result cf_mul(cstate_t *sp);
+static mp_result cf_divmod(cstate_t *sp);
+static mp_result cf_div(cstate_t *sp);
+static mp_result cf_mod(cstate_t *sp);
+static mp_result cf_expt(cstate_t *sp);
+static mp_result cf_exptmod(cstate_t *sp);
+static mp_result cf_square(cstate_t *sp);
+static mp_result cf_invmod(cstate_t *sp);
+static mp_result cf_gcd(cstate_t *sp);
+static mp_result cf_xgcd(cstate_t *sp);
+static mp_result cf_sqrt(cstate_t *sp);
+static mp_result cf_root(cstate_t *sp);
+static mp_result cf_cmplt(cstate_t *sp);
+static mp_result cf_cmpgt(cstate_t *sp);
+static mp_result cf_cmple(cstate_t *sp);
+static mp_result cf_cmpge(cstate_t *sp);
+static mp_result cf_cmpeq(cstate_t *sp);
+static mp_result cf_cmpne(cstate_t *sp);
+static mp_result cf_inc(cstate_t *sp);
+static mp_result cf_dec(cstate_t *sp);
+static mp_result cf_fact(cstate_t *sp);
+static mp_result cf_pprint(cstate_t *sp);
+static mp_result cf_print(cstate_t *sp);
+static mp_result cf_pstack(cstate_t *sp);
+static mp_result cf_clstk(cstate_t *sp);
+static mp_result cf_pop(cstate_t *sp);
+static mp_result cf_dup(cstate_t *sp);
+static mp_result cf_copy(cstate_t *sp);
+static mp_result cf_swap(cstate_t *sp);
+static mp_result cf_rot(cstate_t *sp);
+static mp_result cf_pick(cstate_t *sp);
+static mp_result cf_setr(cstate_t *sp);
+static mp_result cf_setbin(cstate_t *sp);
+static mp_result cf_help(cstate_t *sp);
+static mp_result cf_store(cstate_t *sp);
+static mp_result cf_recall(cstate_t *sp);
+static mp_result cf_cmem(cstate_t *sp);
+static mp_result cf_pmem(cstate_t *sp);
+static mp_result cf_qrecall(cstate_t *sp);
+
+/* }}} */
+
+/* {{{ Built-in operator records, g_ops[] */
+
+typedef struct {
+ char *name; /* The name of the operator. */
+ int stack_size; /* Number of stack arguments required. */
+ op_func handler; /* Function implementing operation. */
+ char *descript; /* Human-readable description. */
+} calcop_t;
+
+static calcop_t g_ops[] = {
+ { "abs", 1, cf_abs, "x -- |x|" },
+ { "neg", 1, cf_neg, "x -- (-x)" },
+ { "+", 2, cf_add, "x y -- (x+y)" },
+ { "add", 2, cf_add, "x y -- (x+y)" },
+ { "-", 2, cf_sub, "x y -- (x-y)" },
+ { "sub", 2, cf_sub, "x y -- (x-y)" },
+ { "*", 2, cf_mul, "x y -- (x*y)" },
+ { "mul", 2, cf_mul, "x y -- (x*y)" },
+ { "/", 2, cf_divmod, "x y -- q r ; x = yq + r, 0 <= r < y" },
+ { "//", 2, cf_div, "x y -- (x div y)" },
+ { "div", 2, cf_div, "x y -- (x div y)" },
+ { "%", 2, cf_mod, "x y -- (x mod y)" },
+ { "mod", 2, cf_mod, "x y -- (x mod y)" },
+ { "^", 2, cf_expt, "x y -- (x^y)" },
+ { "expt", 2, cf_expt, "x y -- (x^y)" },
+ { "^^", 3, cf_exptmod, "x y m -- (x^y mod m)" },
+ { "emod", 3, cf_exptmod, "x y m -- (x^y mod m)" },
+ { "sqr", 1, cf_square, "x -- (x*x)" },
+ { "inv", 2, cf_invmod, "x m -- (1/x mod m)" },
+ { "gcd", 2, cf_gcd, "x y -- gcd(x, y)" },
+ { "xgcd", 2, cf_xgcd, "x y -- g u v ; g = ux + vy" },
+ { "sqrt", 1, cf_sqrt, "x -- floor(sqrt(x))" },
+ { "root", 2, cf_root, "x y -- floor(x^{1/y}) ; y > 0" },
+ { "<", 2, cf_cmplt, "x y -- (x<y)" },
+ { ">", 2, cf_cmpgt, "x y -- (x>y)" },
+ { "<=", 2, cf_cmple, "x y -- (x<=y)" },
+ { ">=", 2, cf_cmpge, "x y -- (x>=y)" },
+ { "=", 2, cf_cmpeq, "x y -- (x=y)" },
+ { "<>", 2, cf_cmpne, "x y -- (x<>y)" },
+ { "inc", 1, cf_inc, "x -- (x+1)" },
+ { "dec", 1, cf_dec, "x -- (x-1)" },
+ { "!", 1, cf_fact, "x -- x!" },
+ { "fact", 1, cf_fact, "x -- x!" },
+
+ { ".", 1, cf_pprint, "x -- ; print x in current output mode" },
+ { ";", 1, cf_print, "x -- x ; print x in current output mode" },
+ { "?", 0, cf_pstack, "-- ; print stack" },
+ { "cls", 0, cf_clstk, "... -- ; clear stack" },
+ { "$", 1, cf_pop, "x --" },
+ { "drop", 1, cf_pop, "x --" },
+ { "dup", 1, cf_dup, "x -- x x" },
+ { "copy", 2, cf_copy, "vn ... v1 v0 n -- vn ... v0 vn ... v0" },
+ { "swap", 2, cf_swap, "x y -- y x" },
+ { "rot", 3, cf_rot, "a b c -- b c a" },
+ { "pick", 2, cf_pick, "... v2 v1 v0 n -- ... v2 v1 v0 vn" },
+
+ { ">>", 1, cf_store, "x -- ; save in named variable" },
+ { "<<", 0, cf_recall, "-- x ; recall from named variable" },
+ { "clm", 0, cf_cmem, "-- ; clear memory" },
+ { "??", 0, cf_pmem, "-- ; print memory" },
+
+ { "out", 1, cf_setr, "r -- ; set output radix to r" },
+ { "bin", 0, cf_setbin, "-- ; set output format to binary" },
+ { "help", 0, cf_help, "-- ; print help message" },
+
+ /* This is the end-marker, but it is also used to catch implicit
+ variable lookups from memory.
+ */
+ { NULL, 0, cf_qrecall, "-- x ; recall from named variable" },
+};
+
+/* }}} */
+
+#define BUFFER_SIZE 16384 /* max. length of input values, in chars */
+
+/* Token types from the primitive lexical analyzer */
+typedef enum { t_eof, t_symbol, t_number, t_error } token_t;
+
+/* {{{ Helper functions */
+
+static token_t next_token(FILE *ifp, char *buf, int size);
+static mp_result read_number(char *buf, mp_int *out);
+static int find_command(cstate_t *ops);
+static void print_value(mp_int v);
+static mp_result run_file(FILE *ifp, cstate_t *op_state);
+
+/* }}} */
+
+/* Error code used internally to signal input problems. */
+static mp_result MP_INPUT;
+
+static int g_output_radix = 10; /* output radix */
+static FILE *g_output_file = NULL;
+
+int main(int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+
+ int opt, errs = 0;
+ FILE *ifp;
+
+ cstate_t op_state;
+ mp_result res;
+
+ MP_INPUT = MP_MINERR - 1;
+
+ g_output_file = stdout;
+ while((opt = getopt(argc, argv, "ho:")) != EOF) {
+ switch(opt) {
+ case 'h':
+ fprintf(stderr,
+ "Usage: imcalc [-h] [-o <output>] input*\n\n"
+ "Options:\n"
+ " -h : display this help message.\n"
+ " -o <output> : send output to file.\n\n"
+
+ "If no input files are given, the standard input is read. The\n"
+ "special file name \"-\" is interpreted to mean the standard input.\n"
+ "Output goes to standard output unless \"-o\" is used.\n\n");
+ return 0;
+
+ case 'o':
+ if((g_output_file = fopen(optarg, "wt")) == NULL) {
+ fprintf(stderr, "Unable to open \"%s\" for writing: %s\n",
+ optarg, strerror(errno));
+ return 1;
+ }
+ break;
+
+ default:
+ fprintf(stderr,
+ "Usage: imcalc [-h] [-o <output>] input*\n"
+ " [use \"imcalc -h\" to get help]\n\n");
+ return 1;
+ }
+ }
+
+ if((res = state_init(&op_state, 1)) != MP_OK) {
+ fprintf(stderr, "Error: state_init: %s\n",
+ mp_error_string(res));
+ return 1;
+ }
+
+ if(optind < argc) {
+ int ix;
+
+ for(ix = optind; ix < argc; ++ix) {
+ if(strcmp(argv[ix], "-") == 0)
+ ifp = stdin;
+ else if((ifp = fopen(argv[optind], "rt")) == NULL) {
+ fprintf(stderr, "Unable to open \"%s\" for reading: %s\n",
+ argv[optind], strerror(errno));
+ return 1;
+ }
+
+ if(run_file(ifp, &op_state) != MP_OK)
+ ++errs;
+ }
+
+ state_clear(&op_state);
+ return errs > 0;
+ }
+ else {
+ int rv = 1 - (run_file(stdin, &op_state) == MP_OK);
+ state_clear(&op_state);
+ return rv;
+ }
+}
+
+/* {{{ next_token(*ifp, *buf, size) */
+
+static token_t next_token(FILE *ifp, char *buf, int size)
+{
+ int ch, pos = 0;
+ token_t res;
+
+ assert(buf != NULL && size > 0);
+
+ while((ch = fgetc(ifp)) != EOF && isspace(ch))
+ /* empty */;
+
+ if(ch == EOF) {
+ buf[0] = '\0';
+ return t_eof;
+ }
+
+ if(ch == '-') {
+ int next = fgetc(ifp);
+ if(next == EOF || !isdigit(next))
+ res = t_symbol;
+ else
+ res = t_number;
+ ungetc(next, ifp);
+ }
+ else if(isdigit(ch) || ch == '#')
+ res = t_number;
+ else
+ res = t_symbol;
+
+ buf[pos++] = ch;
+ while((ch = fgetc(ifp)) != EOF) {
+ if((res == t_number && ispunct(ch) && ch != '-') ||
+ (res == t_symbol && isdigit(ch)) ||
+ isspace(ch)) {
+ ungetc(ch, ifp);
+ break;
+ }
+ else if(pos + 1 >= size) {
+ res = t_error;
+ break;
+ }
+ buf[pos++] = ch;
+ }
+
+ buf[pos] = '\0';
+ return res;
+}
+
+/* }}} */
+
+/* {{{ read_number(*buf, *out) */
+
+static mp_result read_number(char *buf, mp_int *out)
+{
+ int radix = 10, pos = 0;
+ mp_result res;
+ mp_int value;
+
+ assert(buf != NULL && out != NULL);
+
+ if(buf[pos] == '#') {
+ switch(buf[1]) {
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ default:
+ return MP_BADARG;
+ }
+
+ pos += 2;
+ }
+
+ if((value = mp_int_alloc()) == NULL) {
+ *out = NULL;
+ return MP_MEMORY;
+ }
+
+ if((res = mp_int_read_string(value, radix, buf + pos)) != MP_OK) {
+ mp_int_free(value);
+ *out = NULL;
+ return res;
+ }
+
+ *out = value;
+ return res;
+}
+
+/* }}} */
+
+/* {{{ find_command(*buf) */
+
+static int find_command(cstate_t *op)
+{
+ int ix, jx;
+ char *buf = op->ibuf;
+
+ /* First, try to find the command by name */
+ for(ix = 0; g_ops[ix].name != NULL; ++ix) {
+ if(strcasecmp(buf, g_ops[ix].name) == 0)
+ return ix;
+ }
+
+ /* If we don't find the command, try a variable lookup */
+ for(jx = 0; jx < op->mused; ++jx) {
+ if(strcmp(buf, op->names[jx]) == 0)
+ return ix; /* sentinel */
+ }
+
+ /* If variable lookup fails, report command not found */
+ return -1;
+}
+
+/* }}} */
+
+/* {{{ print_value(v) */
+
+static void print_value(mp_int v)
+{
+ if(g_output_radix == 0) {
+ mp_result len = mp_int_binary_len(v);
+ unsigned char *buf = malloc(len);
+ int ix;
+
+ if(buf != NULL) {
+ mp_int_to_binary(v, buf, len);
+ for(ix = 0; ix < len - 1; ++ix) {
+ fprintf(g_output_file, "%02x.", buf[ix]);
+ }
+ fprintf(g_output_file, "%02x\n", buf[ix]);
+ free(buf);
+ }
+ else
+ fprintf(g_output_file, "<insufficient memory to print>\n");
+ }
+ else {
+ mp_result len = mp_int_string_len(v, g_output_radix);
+ char *buf = malloc(len);
+
+ if(buf != NULL) {
+ mp_int_to_string(v, g_output_radix, buf, len);
+ fputs(buf, g_output_file);
+ fputc('\n', g_output_file);
+ free(buf);
+ }
+ else
+ fprintf(g_output_file, "<insufficient memory to print>\n");
+ }
+}
+
+/* }}} */
+
+/* {{{ run_file(*ifp, *op_state) */
+
+static mp_result run_file(FILE *ifp, cstate_t *op_state)
+{
+ mp_result res = MP_OK;
+ token_t next;
+
+ op_state->ifp = ifp;
+ while((next = next_token(ifp, op_state->ibuf, op_state->buflen)) != t_eof) {
+ mp_int value = NULL;
+ int cpos;
+
+ switch(next) {
+ case t_number:
+ if((res = read_number(op_state->ibuf, &value)) != MP_OK)
+ fprintf(stderr, "error: invalid number syntax: %s\n", op_state->ibuf);
+ else if((res = stack_push(op_state, value)) != MP_OK)
+ goto EXIT;
+ break;
+ case t_symbol:
+ if((cpos = find_command(op_state)) < 0)
+ fprintf(stderr, "error: command not understood: %s\n", op_state->ibuf);
+ else if(op_state->used < g_ops[cpos].stack_size) {
+ fprintf(stderr, "error: not enough arguments (have %d, want %d)\n",
+ op_state->used, g_ops[cpos].stack_size);
+ }
+ else if((res = (g_ops[cpos].handler)(op_state)) != MP_OK) {
+ if(res == MP_INPUT)
+ fprintf(stderr, "error: incorrect input format\n");
+ else
+ fprintf(stderr, "error: %s\n", mp_error_string(res));
+ }
+ break;
+ default:
+ fprintf(stderr, "error: invalid input token: %s\n", op_state->ibuf);
+ res = MP_BADARG;
+ goto EXIT;
+ }
+ }
+
+ EXIT:
+ return res;
+}
+
+/* }}} */
+
+/* {{{ state_init(*sp, n_elts) */
+
+static mp_result state_init(cstate_t *sp, mp_size n_elts)
+{
+ int ix;
+
+ assert(sp != NULL && n_elts > 0);
+
+ if((sp->elts = malloc(n_elts * sizeof(*(sp->elts)))) == NULL)
+ return MP_MEMORY;
+ if((sp->mem = malloc(n_elts * sizeof(*(sp->mem)))) == NULL) {
+ free(sp->elts);
+ return MP_MEMORY;
+ }
+ if((sp->names = malloc(n_elts * sizeof(*(sp->names)))) == NULL) {
+ free(sp->mem);
+ free(sp->elts);
+ return MP_MEMORY;
+ }
+ if((sp->ibuf = malloc(BUFFER_SIZE * sizeof(char))) == NULL) {
+ free(sp->names);
+ free(sp->mem);
+ free(sp->elts);
+ return MP_MEMORY;
+ }
+
+ for(ix = 0; ix < n_elts; ++ix) {
+ sp->elts[ix] = NULL;
+ sp->mem[ix] = NULL;
+ sp->names[ix] = NULL;
+ }
+
+ sp->alloc = n_elts;
+ sp->used = 0;
+ sp->mslots = n_elts;
+ sp->mused = 0;
+ sp->buflen = BUFFER_SIZE;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ state_clear(*sp) */
+
+static void state_clear(cstate_t *sp)
+{
+ assert(sp != NULL);
+
+ if(sp->elts != NULL) {
+ int ix;
+
+ for(ix = 0; ix < sp->used; ++ix) {
+ mp_int_clear(sp->elts[ix]);
+ sp->elts[ix] = NULL;
+ }
+
+ free(sp->elts);
+ sp->elts = NULL;
+ sp->alloc = 0;
+ sp->used = 0;
+ }
+ if(sp->mem != NULL) {
+ int ix;
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ mp_int_free(sp->mem[ix]);
+ sp->mem[ix] = NULL;
+ free(sp->names[ix]);
+ sp->names[ix] = NULL;
+ }
+
+ free(sp->mem);
+ sp->mem = NULL;
+ free(sp->names);
+ sp->names = NULL;
+
+ sp->mslots = 0;
+ sp->mused = 0;
+ }
+ if(sp->ibuf != NULL) {
+ free(sp->ibuf);
+ sp->buflen = 0;
+ }
+ if(sp->ifp != NULL) {
+ fclose(sp->ifp);
+ sp->ifp = NULL;
+ }
+}
+
+/* }}} */
+
+/* {{{ stack_flush(*sp) */
+
+static void stack_flush(cstate_t *sp)
+{
+ int ix;
+
+ assert(sp != NULL && sp->elts != NULL);
+
+ for(ix = 0; ix < sp->used; ++ix) {
+ mp_int_clear(sp->elts[ix]);
+ sp->elts[ix] = NULL;
+ }
+
+ sp->used = 0;
+}
+
+/* }}} */
+
+/* {{{ stack_push(*sp, elt) */
+
+static mp_result stack_push(cstate_t *sp, mp_int elt)
+{
+ if(sp->used >= sp->alloc) {
+ mp_size nsize = 2 * sp->alloc;
+ mp_int *tmp;
+ int ix;
+
+ if((tmp = malloc(nsize * sizeof(*(sp->elts)))) == NULL)
+ return MP_MEMORY;
+
+ for(ix = 0; ix < sp->used; ++ix)
+ tmp[ix] = sp->elts[ix];
+
+ free(sp->elts);
+ sp->elts = tmp;
+ sp->alloc = nsize;
+ }
+
+ sp->elts[sp->used++] = elt;
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ stack_pop(*sp) */
+
+static mp_result stack_pop(cstate_t *sp)
+{
+ assert(sp != NULL && sp->elts != NULL);
+
+ if(sp->used == 0)
+ return MP_UNDEF;
+
+ sp->used -= 1;
+ mp_int_clear(sp->elts[sp->used]);
+ sp->elts[sp->used] = NULL;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mem_insert(*sp, *name, value) */
+
+static mp_result mem_insert(cstate_t *sp, const char *name, mp_int value)
+{
+ int ix;
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ if(strcmp(name, sp->names[ix]) == 0)
+ break;
+ }
+
+ /* Two cases:
+ ix < sp->mused ==> replacing existing entry.
+ otherwise ==> adding new entry, may need to grow dictionary.
+ */
+ if(ix < sp->mused) {
+ mp_int_free(sp->mem[ix]); /* fall through to the end */
+ }
+ else {
+ if(sp->mused >= sp->mslots) {
+ mp_size nsize = 2 * sp->mslots;
+ mp_int *tz;
+ char **tc;
+ int jx;
+
+ if((tz = malloc(nsize * sizeof(*(sp->mem)))) == NULL)
+ return MP_MEMORY;
+ if((tc = malloc(nsize * sizeof(*(sp->names)))) == NULL) {
+ free(tz);
+ return MP_MEMORY;
+ }
+
+ for(jx = 0; jx < sp->mused; ++jx) {
+ tz[jx] = sp->mem[jx];
+ tc[jx] = sp->names[jx];
+ }
+
+ free(sp->mem);
+ sp->mem = tz;
+ free(sp->names);
+ sp->names = tc;
+
+ sp->mslots = nsize;
+ }
+
+ sp->mused += 1;
+ sp->names[ix] = malloc(1 + strlen(name));
+ strcpy(sp->names[ix], name);
+ }
+
+ sp->mem[ix] = mp_int_alloc();
+ return mp_int_copy(value, sp->mem[ix]);
+}
+
+/* }}} */
+
+/* {{{ mem_recall(*sp, *name, value) */
+
+static mp_result mem_recall(cstate_t *sp, const char *name, mp_int value)
+{
+ int ix;
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ if(strcmp(name, sp->names[ix]) == 0) {
+ return mp_int_copy(sp->mem[ix], value);
+ }
+ }
+
+ return MP_UNDEF; /* not found */
+}
+
+/* }}} */
+
+/* {{{ mem_clear(*sp) */
+
+static mp_result mem_clear(cstate_t *sp)
+{
+ int ix;
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ mp_int_free(sp->mem[ix]);
+ free(sp->names[ix]);
+ }
+ sp->mused = 0;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_abs(sp) */
+
+static mp_result cf_abs(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_abs(a, a);
+}
+
+/* }}} */
+
+/* {{{ cf_neg(sp) */
+
+static mp_result cf_neg(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_neg(a, a);
+}
+
+/* }}} */
+
+/* {{{ cf_add(sp) */
+
+static mp_result cf_add(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_add(a, b, a);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_sub(sp) */
+
+static mp_result cf_sub(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_sub(a, b, a);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_mul(sp) */
+
+static mp_result cf_mul(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_mul(a, b, a);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_divmod(sp) */
+
+static mp_result cf_divmod(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+
+ return mp_int_div(a, b, a, b);
+}
+
+/* }}} */
+
+/* {{{ cf_div(sp) */
+
+static mp_result cf_div(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_div(a, b, a, NULL);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_mod(sp) */
+
+static mp_result cf_mod(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_mod(a, b, a);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_expt(sp) */
+
+static mp_result cf_expt(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+ mp_small bval;
+
+ if((res = mp_int_to_int(b, &bval)) != MP_OK)
+ return res;
+
+ stack_pop(sp);
+ return mp_int_expt(a, bval, a);
+}
+
+/* }}} */
+
+/* {{{ cf_exptmod(sp) */
+
+static mp_result cf_exptmod(cstate_t *sp)
+{
+ mp_int m = sp->elts[sp->used - 1];
+ mp_int b = sp->elts[sp->used - 2];
+ mp_int a = sp->elts[sp->used - 3];
+ mp_result res = mp_int_exptmod(a, b, m, a);
+
+ if(res == MP_OK) {
+ stack_pop(sp);
+ stack_pop(sp);
+ }
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_square(sp) */
+
+static mp_result cf_square(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_sqr(a, a);
+}
+
+/* }}} */
+
+/* {{{ cf_invmod(sp) */
+
+static mp_result cf_invmod(cstate_t *sp)
+{
+ mp_int m = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_invmod(a, m, a);
+
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_gcd(sp) */
+
+static mp_result cf_gcd(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res = mp_int_gcd(a, b, a);
+
+ if(res == MP_OK)
+ stack_pop(sp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_xgcd(sp) */
+
+static mp_result cf_xgcd(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_int t;
+ mp_result res;
+
+ if((t = mp_int_alloc()) == NULL)
+ return MP_MEMORY;
+ if((res = mp_int_egcd(a, b, a, b, t)) != MP_OK) {
+ mp_int_free(t);
+ return res;
+ }
+
+ if((res = stack_push(sp, t)) != MP_OK)
+ mp_int_free(t);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_sqrt(sp) */
+
+static mp_result cf_sqrt(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_sqrt(a, a);
+}
+
+/* }}} */
+
+/* {{{ cf_root(sp) */
+
+static mp_result cf_root(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 2];
+ mp_int bp = sp->elts[sp->used - 1];
+ mp_small b;
+ mp_result res;
+
+ if((res = mp_int_to_int(bp, &b)) != MP_OK)
+ return res;
+
+ stack_pop(sp);
+ return mp_int_root(a, b, a);
+}
+
+/* }}} */
+
+/* {{{ cf_cmplt(sp) */
+
+static mp_result cf_cmplt(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) < 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_cmpgt(sp) */
+
+static mp_result cf_cmpgt(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) > 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_cmple(sp) */
+
+static mp_result cf_cmple(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) <= 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_cmpge(sp) */
+
+static mp_result cf_cmpge(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) >= 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_cmpeq(sp) */
+
+static mp_result cf_cmpeq(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) == 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_cmpne(sp) */
+
+static mp_result cf_cmpne(cstate_t *sp)
+{
+ mp_int b = sp->elts[sp->used - 1];
+ mp_int a = sp->elts[sp->used - 2];
+ mp_result res;
+
+ res = mp_int_set_value(a, (mp_int_compare(a, b) != 0));
+ stack_pop(sp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_inc(sp) */
+
+static mp_result cf_inc(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_add_value(a, 1, a);
+}
+
+/* }}} */
+
+/* {{{ cf_dec(sp) */
+
+static mp_result cf_dec(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+
+ return mp_int_sub_value(a, 1, a);
+}
+
+/* }}} */
+
+/* {{{ cf_fact(sp) */
+
+static mp_result cf_fact(cstate_t *sp)
+{
+ mpz_t tmp;
+ mp_int x = sp->elts[sp->used - 1];
+ mp_result res = MP_OK;
+
+ if (mp_int_compare_zero(x) < 0)
+ return MP_UNDEF;
+
+ (void) mp_int_init_value(&tmp, 1);
+
+ while (mp_int_compare_value(x, 1) > 0) {
+ if ((res = mp_int_mul(&tmp, x, &tmp)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_sub_value(x, 1, x)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ res = mp_int_copy(&tmp, x);
+
+ CLEANUP:
+ mp_int_clear(&tmp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_pprint(sp) */
+
+static mp_result cf_pprint(cstate_t *sp)
+{
+ print_value(sp->elts[sp->used - 1]);
+ stack_pop(sp);
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_print(sp) */
+
+static mp_result cf_print(cstate_t *sp)
+{
+ print_value(sp->elts[sp->used - 1]);
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_pstack(sp) */
+
+static mp_result cf_pstack(cstate_t *sp)
+{
+ int ix;
+
+ if(sp->used == 0) {
+ fprintf(g_output_file, "<stack empty>\n");
+ }
+ else {
+ for(ix = 0; ix < sp->used; ++ix) {
+ fprintf(g_output_file, "%2d: ", ix);
+ print_value(sp->elts[sp->used - 1 - ix]);
+ }
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_clstk(sp) */
+
+static mp_result cf_clstk(cstate_t *sp)
+{
+ stack_flush(sp);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_pop(sp) */
+
+static mp_result cf_pop(cstate_t *sp)
+{
+ return stack_pop(sp);
+}
+
+/* }}} */
+
+/* {{{ cf_dup(sp) */
+
+static mp_result cf_dup(cstate_t *sp)
+{
+ mp_int cp = mp_int_alloc();
+ mp_result res;
+
+ if(cp == NULL)
+ return MP_MEMORY;
+
+ if((res = mp_int_copy(sp->elts[sp->used - 1], cp)) != MP_OK) {
+ mp_int_free(cp);
+ return res;
+ }
+
+ if((res = stack_push(sp, cp)) != MP_OK)
+ mp_int_free(cp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ cf_copy(sp) */
+
+static mp_result cf_copy(cstate_t *sp)
+{
+ mp_int n = sp->elts[sp->used - 1];
+ mp_result res;
+ mp_small ncopy;
+ int ix;
+
+ if((res = mp_int_to_int(n, &ncopy)) != MP_OK)
+ return res;
+
+ if(ncopy < 1 || ncopy >= sp->used)
+ return MP_RANGE;
+
+ stack_pop(sp);
+
+ for(ix = 0; ix < ncopy; ++ix) {
+ mp_int old = sp->elts[sp->used - ncopy];
+ mp_int new = mp_int_alloc();
+
+ if(new == NULL)
+ return MP_MEMORY;
+
+ if((res = mp_int_copy(old, new)) != MP_OK) {
+ mp_int_free(new);
+ return res;
+ }
+ if((res = stack_push(sp, new)) != MP_OK)
+ return res;
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_swap(sp) */
+
+static mp_result cf_swap(cstate_t *sp)
+{
+ mp_int t = sp->elts[sp->used - 1];
+
+ sp->elts[sp->used - 1] = sp->elts[sp->used - 2];
+ sp->elts[sp->used - 2] = t;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_rot(sp) */
+
+static mp_result cf_rot(cstate_t *sp)
+{
+ mp_int t = sp->elts[sp->used - 3];
+
+ sp->elts[sp->used - 3] = sp->elts[sp->used - 2];
+ sp->elts[sp->used - 2] = sp->elts[sp->used - 1];
+ sp->elts[sp->used - 1] = t;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_pick(sp) */
+
+static mp_result cf_pick(cstate_t *sp)
+{
+ mp_int n = sp->elts[sp->used - 1];
+ mp_result res;
+ mp_small pos = 0;
+
+ if((res = mp_int_to_int(n, &pos)) != MP_OK)
+ return res;
+
+ if(pos < 0 || pos >= sp->used - 1)
+ return MP_RANGE;
+
+ return mp_int_copy(sp->elts[sp->used - 2 - pos], n);
+}
+
+/* }}} */
+
+/* {{{ cf_setr(sp) */
+
+static mp_result cf_setr(cstate_t *sp)
+{
+ mp_int a = sp->elts[sp->used - 1];
+ mp_result res;
+ mp_small rdx = 0;
+
+ if((res = mp_int_to_int(a, &rdx)) != MP_OK)
+ return res;
+
+ if(rdx < MP_MIN_RADIX || rdx > MP_MAX_RADIX)
+ return MP_RANGE;
+
+ g_output_radix = rdx;
+ stack_pop(sp);
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_setbin(sp) */
+
+static mp_result cf_setbin(cstate_t *sp)
+{
+ g_output_radix = 0;
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_help(sp) */
+
+static mp_result cf_help(cstate_t *sp)
+{
+ int ix, maxlen = 10; /* minimum width */
+
+ for(ix = 0; g_ops[ix].name != NULL; ++ix) {
+ int len = strlen(g_ops[ix].name);
+
+ if(len > maxlen)
+ maxlen = len;
+ }
+
+ fprintf(stderr, "Operators understood:\n");
+ for(ix = 0; g_ops[ix].name != NULL; ++ix) {
+ int len = strlen(g_ops[ix].name);
+
+ fputs(g_ops[ix].name, stderr);
+ while(len++ <= maxlen)
+ fputc(' ', stderr);
+
+ fprintf(stderr, "%s\n", g_ops[ix].descript);
+ }
+ fputc('\n', stderr);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_store(*sp) */
+
+static mp_result cf_store(cstate_t *sp)
+{
+ mp_result res;
+
+ if(next_token(sp->ifp, sp->ibuf, sp->buflen) != t_symbol)
+ return MP_INPUT;
+
+ if((res = mem_insert(sp, sp->ibuf, sp->elts[sp->used - 1])) != MP_OK)
+ return res;
+
+ return stack_pop(sp);
+}
+
+/* }}} */
+
+/* {{{ cf_recall(*sp) */
+
+static mp_result cf_recall(cstate_t *sp)
+{
+ mp_result res;
+ mp_int val;
+
+ if(next_token(sp->ifp, sp->ibuf, sp->buflen) != t_symbol)
+ return MP_INPUT;
+
+ if((val = mp_int_alloc()) == NULL)
+ return MP_MEMORY;
+ if((res = mem_recall(sp, sp->ibuf, val)) != MP_OK) {
+ mp_int_free(val);
+ return res;
+ }
+
+ return stack_push(sp, val);
+}
+
+/* }}} */
+
+/* {{{ cf_cmem(*sp) */
+
+static mp_result cf_cmem(cstate_t *sp)
+{
+ return mem_clear(sp);
+}
+
+/* }}} */
+
+/* {{{ cf_pmem(*sp) */
+
+static mp_result cf_pmem(cstate_t *sp)
+{
+ int ix, max_len = 0;
+
+ if(sp->mused == 0) {
+ fprintf(g_output_file, "<memory empty>\n");
+ return MP_OK;
+ }
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ int ln = strlen(sp->names[ix]);
+
+ if(ln > max_len)
+ max_len = ln;
+ }
+
+ max_len += 1; /* allow for a padding space */
+
+ for(ix = 0; ix < sp->mused; ++ix) {
+ int ln = strlen(sp->names[ix]);
+
+ fprintf(g_output_file, "%s:", sp->names[ix]);
+
+ while(ln++ < max_len)
+ fputc(' ', g_output_file);
+
+ print_value(sp->mem[ix]);
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ cf_qrecall(*sp) */
+
+static mp_result cf_qrecall(cstate_t *sp)
+{
+ mp_result res;
+ mp_int val;
+
+ if((val = mp_int_alloc()) == NULL)
+ return MP_MEMORY;
+
+ if((res = mem_recall(sp, sp->ibuf, val)) != MP_OK) {
+ mp_int_free(val);
+ return res;
+ }
+
+ return stack_push(sp, val);
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/examples/input.c b/polly/lib/External/isl/imath/examples/input.c
new file mode 100644
index 00000000000..6997c3e9321
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/input.c
@@ -0,0 +1,120 @@
+/*
+ input.c
+
+ Demonstrates basic input and output of arbitrary precision integers using
+ IMath.
+
+ by Michael J. Fromberger <http://spinning-yarns.org/michael/>
+ Copyright (C) 2003-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "imrat.h"
+
+int main(int argc, char *argv[])
+{
+ mp_size radix = 10; /* Default output radix */
+ mpq_t value;
+ mp_result res;
+ char *endp;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: input <value> [output-base]\n");
+ return 1;
+ }
+ if(argc > 2) {
+ if((radix = atoi(argv[2])) < MP_MIN_RADIX ||
+ (radix > MP_MAX_RADIX)) {
+ fprintf(stderr, "Error: Specified radix is out of range (%d)\n",
+ radix);
+ return 1;
+ }
+ }
+
+ /* Initialize a new value, initially zero; illustrates how to check
+ for errors (e.g., out of memory) and display a message. */
+ if((res = mp_rat_init(&value)) != MP_OK) {
+ fprintf(stderr, "Error in mp_rat_init(): %s\n",
+ mp_error_string(res));
+ return 1;
+ }
+
+ /* Read value in base 10 */
+ if((res = mp_rat_read_ustring(&value, 0, argv[1], &endp)) != MP_OK) {
+ fprintf(stderr, "Error in mp_rat_read_ustring(): %s\n",
+ mp_error_string(res));
+
+ if(res == MP_TRUNC)
+ fprintf(stderr, " -- remaining input is: %s\n", endp);
+
+ mp_rat_clear(&value);
+ return 1;
+ }
+
+ printf("Here is your value in base %d\n", radix);
+ {
+ mp_result buf_size, res;
+ char *obuf;
+
+ if(mp_rat_is_integer(&value)) {
+ /* Allocate a buffer big enough to hold the given value, including
+ sign and zero terminator. */
+ buf_size = mp_int_string_len(MP_NUMER_P(&value), radix);
+ obuf = malloc(buf_size);
+
+ /* Convert the value to a string in the desired radix. */
+ if((res = mp_int_to_string(MP_NUMER_P(&value), radix,
+ obuf, buf_size)) != MP_OK) {
+ fprintf(stderr, "Converstion to base %d failed: %s\n",
+ radix, mp_error_string(res));
+ mp_rat_clear(&value);
+ return 1;
+ }
+ }
+ else {
+ /* Allocate a buffer big enough to hold the given value, including
+ sign and zero terminator. */
+ buf_size = mp_rat_string_len(&value, radix);
+ obuf = malloc(buf_size);
+
+ /* Convert the value to a string in the desired radix. */
+ if((res = mp_rat_to_string(&value, radix, obuf, buf_size)) != MP_OK) {
+ fprintf(stderr, "Conversion to base %d failed: %s\n",
+ radix, mp_error_string(res));
+ mp_rat_clear(&value);
+ return 1;
+ }
+ }
+ fputs(obuf, stdout);
+ fputc('\n', stdout);
+ free(obuf);
+ }
+
+ /* When you are done with a value, it must be "cleared" to release
+ the memory it occupies */
+ mp_rat_clear(&value);
+ return 0;
+}
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/examples/randprime.c b/polly/lib/External/isl/imath/examples/randprime.c
new file mode 100644
index 00000000000..84ccdc98c98
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/randprime.c
@@ -0,0 +1,261 @@
+/*
+ Name: randprime.c
+ Purpose: Generate a probable prime at random.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Usage: randprime [-s] <bits> [<outfile>]
+
+ Generate a randomly-chosen probable prime having <bits> significant bits, and
+ write it to the specified output file or to the standard output. If the "-s"
+ option is given, a prime p is chosen such that (p - 1) / 2 is also prime.
+
+ A prime is obtained by reading random bits from /dev/random, setting the
+ low-order bit, and testing for primality. If the first candidate is not
+ prime, successive odd candidates are tried until a probable prime is found.
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <unistd.h>
+
+#include "imath.h"
+#include "iprime.h"
+
+/* Load the specified buffer with random bytes */
+int randomize(unsigned char *buf, size_t len);
+
+/* Overwrite the specified value with n_bits random bits */
+mp_result mp_int_randomize(mp_int a, mp_size n_bits);
+
+/* Find a prime starting from the given odd seed */
+mp_result find_prime(mp_int seed, FILE *fb);
+mp_result find_strong_prime(mp_int seed, FILE *fb);
+
+typedef mp_result (*find_f)(mp_int, FILE *);
+
+int main(int argc, char *argv[])
+{
+ int opt, modbits;
+ FILE *ofp = stdout;
+ mp_result res;
+ find_f find_func = find_prime;
+ char tag = 'p';
+ mpz_t value;
+
+ /* Process command-line arguments */
+ while((opt = getopt(argc, argv, "s")) != EOF) {
+ switch(opt) {
+ case 's':
+ find_func = find_strong_prime;
+ tag = 'P';
+ break;
+ default:
+ fprintf(stderr, "Usage: randprime [-s] <bits> [<outfile>]\n");
+ return 1;
+ }
+ }
+
+ if(optind >= argc) {
+ fprintf(stderr, "Error: You must specify the number of significant bits.\n");
+ fprintf(stderr, "Usage: randprime [-s] <bits> [<outfile>]\n");
+ return 1;
+ }
+ modbits = (int) strtol(argv[optind++], NULL, 0);
+ if(modbits < CHAR_BIT) {
+ fprintf(stderr, "Error: Invalid value for number of significant bits.\n");
+ return 1;
+ }
+ if(modbits % 2 == 1)
+ ++modbits;
+
+ /* Check if output file is specified */
+ if(optind < argc) {
+ if((ofp = fopen(argv[optind], "wt")) == NULL) {
+ fprintf(stderr, "Error: Unable to open output file for writing.\n"
+ " - Filename: %s\n"
+ " - Error: %s\n", argv[optind], strerror(errno));
+ return 1;
+ }
+ }
+
+ mp_int_init(&value);
+ if ((res = mp_int_randomize(&value, modbits - 1)) != MP_OK) {
+ fprintf(stderr, "Error: Unable to generate random start value.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ fprintf(stderr, "%c: ", tag);
+ find_func(&value, stderr);
+ fputc('\n', stderr);
+
+ /* Write the completed value to the specified output file */
+ {
+ int len;
+ char *obuf;
+
+ len = mp_int_string_len(&value, 10);
+ obuf = malloc(len);
+ mp_int_to_string(&value, 10, obuf, len);
+ fputs(obuf, ofp);
+ fputc('\n', ofp);
+
+ free(obuf);
+ }
+
+ EXIT:
+ fclose(ofp);
+ mp_int_clear(&value);
+ return 0;
+}
+
+/* {{{ randomize(buf, len) */
+
+int randomize(unsigned char *buf, size_t len)
+{
+ FILE *rnd = fopen("/dev/random", "rb");
+ size_t nr;
+
+ if(rnd == NULL)
+ return -1;
+
+ nr = fread(buf, sizeof(*buf), len, rnd);
+ fclose(rnd);
+
+ return (int) nr;
+}
+
+/* }}} */
+
+/* {{{ mp_int_randomize(a, n_bits) */
+
+mp_result mp_int_randomize(mp_int a, mp_size n_bits)
+{
+ mp_size n_bytes = (n_bits + CHAR_BIT - 1) / CHAR_BIT;
+ unsigned char *buf;
+ mp_result res = MP_OK;
+
+ if((buf = malloc(n_bytes)) == NULL)
+ return MP_MEMORY;
+
+ if(randomize(buf, n_bytes) != n_bytes) {
+ res = MP_TRUNC;
+ goto CLEANUP;
+ }
+
+ /* Clear bits beyond the number requested */
+ if(n_bits % CHAR_BIT != 0) {
+ unsigned char b_mask = (1 << (n_bits % CHAR_BIT)) - 1;
+ unsigned char t_mask = (1 << (n_bits % CHAR_BIT)) >> 1;
+
+ buf[0] &= b_mask;
+ buf[0] |= t_mask;
+ }
+
+ /* Set low-order bit to insure value is odd */
+ buf[n_bytes - 1] |= 1;
+
+ res = mp_int_read_unsigned(a, buf, n_bytes);
+
+ CLEANUP:
+ memset(buf, 0, n_bytes);
+ free(buf);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ find_prime(seed, fb) */
+
+mp_result find_prime(mp_int seed, FILE *fb)
+{
+ mp_result res;
+ int count = 0;
+
+ if(mp_int_is_even(seed))
+ if((res = mp_int_add_value(seed, 1, seed)) != MP_OK)
+ return res;
+
+ while((res = mp_int_is_prime(seed)) == MP_FALSE) {
+ ++count;
+
+ if(fb != NULL && (count % 50) == 0)
+ fputc('.', fb);
+
+ if((res = mp_int_add_value(seed, 2, seed)) != MP_OK)
+ return res;
+ }
+
+ if(res == MP_TRUE && fb != NULL)
+ fputc('+', fb);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ find_strong_prime(seed, fb) */
+
+mp_result find_strong_prime(mp_int seed, FILE *fb)
+{
+ mp_result res;
+ mpz_t t;
+
+ mp_int_init(&t);
+ for(;;) {
+ if ((res = find_prime(seed, fb)) != MP_TRUE)
+ break;
+ if ((res = mp_int_copy(seed, &t)) != MP_OK)
+ break;
+
+ if ((res = mp_int_mul_pow2(&t, 1, &t)) != MP_OK ||
+ (res = mp_int_add_value(&t, 1, &t)) != MP_OK)
+ break;
+
+ if ((res = mp_int_is_prime(&t)) == MP_TRUE) {
+ if (fb != NULL)
+ fputc('!', fb);
+
+ res = mp_int_copy(&t, seed);
+ break;
+ }
+ else if (res != MP_FALSE)
+ break;
+
+ if (fb != NULL)
+ fputc('x', fb);
+ if ((res = mp_int_add_value(seed, 2, seed)) != MP_OK)
+ break;
+ }
+
+ mp_int_clear(&t);
+ return res;
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/examples/rounding.c b/polly/lib/External/isl/imath/examples/rounding.c
new file mode 100644
index 00000000000..674b2bd39a4
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/rounding.c
@@ -0,0 +1,83 @@
+/*
+ Name: rounding.c
+ Purpose: Demonstrates rounding modes.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Bugs: The rounding mode can only be specified by value, not name.
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "imath.h"
+#include "imrat.h"
+
+int main(int argc, char *argv[])
+{
+ mp_result mode, len, res = 0;
+ mp_size prec, radix;
+ mpq_t value;
+ char *buf;
+
+ if(argc < 5) {
+ fprintf(stderr, "Usage: rounding <mode> <precision> <radix> <value>\n");
+ return 1;
+ }
+
+ if((res = mp_rat_init(&value)) != MP_OK) {
+ fprintf(stderr, "Error initializing: %s\n", mp_error_string(res));
+ return 2;
+ }
+
+ mode = atoi(argv[1]);
+ prec = atoi(argv[2]);
+ radix = atoi(argv[3]);
+
+ printf("Rounding mode: %d\n"
+ "Precision: %u digits\n"
+ "Radix: %u\n"
+ "Input string: \"%s\"\n", mode, prec, radix, argv[4]);
+
+ if((res = mp_rat_read_decimal(&value, radix, argv[4])) != MP_OK) {
+ fprintf(stderr, "Error reading input string: %s\n",
+ mp_error_string(res));
+ goto CLEANUP;
+ }
+
+ len = mp_rat_decimal_len(&value, radix, prec);
+ buf = malloc(len);
+
+ if((res = mp_rat_to_decimal(&value, radix, prec, mode, buf, len)) != MP_OK)
+ fprintf(stderr, "Error converting output: %s\n",
+ mp_error_string(res));
+
+ printf("Result string: \"%s\"\n", buf);
+ free(buf);
+
+ CLEANUP:
+ mp_rat_clear(&value);
+ return res;
+}
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/examples/rsakey.c b/polly/lib/External/isl/imath/examples/rsakey.c
new file mode 100644
index 00000000000..34190fa414f
--- /dev/null
+++ b/polly/lib/External/isl/imath/examples/rsakey.c
@@ -0,0 +1,325 @@
+/*
+ Name: rsakey.c
+ Purpose: Generate keys for the RSA cryptosystem.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Usage: rsakey [-e <expt>] <modbits> [<outfile>]
+
+ Generates an RSA key pair with a modulus having <modbits> significant bits,
+ and writes it to the specified output file, or to the standard output. The
+ -e option allows the user to specify an encryption exponent; otherwise, an
+ encryption exponent is chosen at random.
+
+ Primes p and q are obtained by reading random bits from /dev/random, setting
+ the low-order bit, and testing for primality. If the first candidate is not
+ prime, successive odd candidates are tried until a probable prime is found.
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+
+#include <unistd.h>
+
+#include "imath.h"
+#include "iprime.h"
+
+typedef struct {
+ mpz_t p;
+ mpz_t q;
+ mpz_t n;
+ mpz_t e;
+ mpz_t d;
+} rsa_key;
+
+/* Load the specified buffer with random bytes */
+int randomize(unsigned char *buf, size_t len);
+
+/* Overwrite the specified value with n_bits random bits */
+mp_result mp_int_randomize(mp_int a, mp_size n_bits);
+
+/* Find a prime starting from the given odd seed */
+mp_result find_prime(mp_int seed, FILE *fb);
+
+/* Initialize/destroy an rsa_key structure */
+mp_result rsa_key_init(rsa_key *kp);
+void rsa_key_clear(rsa_key *kp);
+void rsa_key_write(rsa_key *kp, FILE *ofp);
+
+int main(int argc, char *argv[])
+{
+ int opt, modbits;
+ FILE *ofp = stdout;
+ char *expt = NULL;
+ rsa_key the_key;
+ mp_result res;
+
+ /* Process command-line arguments */
+ while((opt = getopt(argc, argv, "e:")) != EOF) {
+ switch(opt) {
+ case 'e':
+ expt = optarg;
+ break;
+ default:
+ fprintf(stderr, "Usage: rsakey [-e <expt>] <modbits> [<outfile>]\n");
+ return 1;
+ }
+ }
+
+ if(optind >= argc) {
+ fprintf(stderr, "Error: You must specify the number of modulus bits.\n");
+ fprintf(stderr, "Usage: rsakey [-e <expt>] <modbits> [<outfile>]\n");
+ return 1;
+ }
+ modbits = (int) strtol(argv[optind++], NULL, 0);
+ if(modbits < CHAR_BIT) {
+ fprintf(stderr, "Error: Invalid value for number of modulus bits.\n");
+ return 1;
+ }
+ if(modbits % 2 == 1)
+ ++modbits;
+
+ /* Check if output file is specified */
+ if(optind < argc) {
+ if((ofp = fopen(argv[optind], "wt")) == NULL) {
+ fprintf(stderr, "Error: Unable to open output file for writing.\n"
+ " - Filename: %s\n"
+ " - Error: %s\n", argv[optind], strerror(errno));
+ return 1;
+ }
+ }
+
+ if((res = rsa_key_init(&the_key)) != MP_OK) {
+ fprintf(stderr, "Error initializing RSA key structure:\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ return 1;
+ }
+
+ /* If specified, try to load the key exponent */
+ if(expt != NULL) {
+ if((res = mp_int_read_string(&(the_key.e), 10, expt)) != MP_OK) {
+ fprintf(stderr, "Error: Invalid value for encryption exponent.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ }
+
+ if((res = mp_int_randomize(&(the_key.p), (modbits / 2))) != MP_OK) {
+ fprintf(stderr, "Error: Unable to randomize first prime.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ fprintf(stderr, "p: ");
+ find_prime(&(the_key.p), stderr);
+
+ if((res = mp_int_randomize(&(the_key.q), (modbits / 2))) != MP_OK) {
+ fprintf(stderr, "Error: Unable to randomize second prime.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ fprintf(stderr, "\nq: ");
+ find_prime(&(the_key.q), stderr);
+ fputc('\n', stderr);
+
+ /* Temporarily, the key's "n" field will be (p - 1) * (q - 1) for
+ purposes of computing the decryption exponent.
+ */
+ mp_int_mul(&(the_key.p), &(the_key.q), &(the_key.n));
+ mp_int_sub(&(the_key.n), &(the_key.p), &(the_key.n));
+ mp_int_sub(&(the_key.n), &(the_key.q), &(the_key.n));
+ mp_int_add_value(&(the_key.n), 1, &(the_key.n));
+
+ if(expt == NULL &&
+ (res = mp_int_randomize(&(the_key.e), (modbits / 2))) != MP_OK) {
+ fprintf(stderr, "Error: Unable to randomize encryption exponent.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ while((res = mp_int_invmod(&(the_key.e), &(the_key.n),
+ &(the_key.d))) != MP_OK) {
+ if(expt != NULL) {
+ fprintf(stderr, "Error: Unable to compute decryption exponent.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ if((res = mp_int_randomize(&(the_key.e), (modbits / 2))) != MP_OK) {
+ fprintf(stderr, "Error: Unable to re-randomize encryption exponent.\n"
+ " - %s (%d)\n", mp_error_string(res), res);
+ goto EXIT;
+ }
+ }
+
+ /* Recompute the real modulus, now that exponents are done. */
+ mp_int_mul(&(the_key.p), &(the_key.q), &(the_key.n));
+
+ /* Write completed key to the specified output file */
+ rsa_key_write(&the_key, ofp);
+
+ EXIT:
+ fclose(ofp);
+ rsa_key_clear(&the_key);
+ return 0;
+}
+
+/* {{{ randomize(buf, len) */
+
+int randomize(unsigned char *buf, size_t len)
+{
+ FILE *rnd = fopen("/dev/random", "rb");
+ size_t nr;
+
+ if(rnd == NULL)
+ return -1;
+
+ nr = fread(buf, sizeof(*buf), len, rnd);
+ fclose(rnd);
+
+ return (int) nr;
+}
+
+/* }}} */
+
+/* {{{ mp_int_randomize(a, n_bits) */
+
+mp_result mp_int_randomize(mp_int a, mp_size n_bits)
+{
+ mp_size n_bytes = (n_bits + CHAR_BIT - 1) / CHAR_BIT;
+ unsigned char *buf;
+ mp_result res = MP_OK;
+
+ if((buf = malloc(n_bytes)) == NULL)
+ return MP_MEMORY;
+
+ if(randomize(buf, n_bytes) != n_bytes) {
+ res = MP_TRUNC;
+ goto CLEANUP;
+ }
+
+ /* Clear bits beyond the number requested */
+ if(n_bits % CHAR_BIT != 0) {
+ unsigned char b_mask = (1 << (n_bits % CHAR_BIT)) - 1;
+ unsigned char t_mask = (1 << (n_bits % CHAR_BIT)) >> 1;
+
+ buf[0] &= b_mask;
+ buf[0] |= t_mask;
+ }
+
+ /* Set low-order bit to insure value is odd */
+ buf[n_bytes - 1] |= 1;
+
+ res = mp_int_read_unsigned(a, buf, n_bytes);
+
+ CLEANUP:
+ memset(buf, 0, n_bytes);
+ free(buf);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ find_prime(seed, fb) */
+
+mp_result find_prime(mp_int seed, FILE *fb)
+{
+ mp_result res;
+ int count = 0;
+
+ if(mp_int_is_even(seed))
+ if((res = mp_int_add_value(seed, 1, seed)) != MP_OK)
+ return res;
+
+ while((res = mp_int_is_prime(seed)) == MP_FALSE) {
+ ++count;
+
+ if(fb != NULL && (count % 50) == 0)
+ fputc('.', fb);
+
+ if((res = mp_int_add_value(seed, 2, seed)) != MP_OK)
+ return res;
+ }
+
+ if(res == MP_TRUE && fb != NULL)
+ fputc('+', fb);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ rsa_key_init(kp) */
+
+mp_result rsa_key_init(rsa_key *kp)
+{
+ mp_int_init(&(kp->p));
+ mp_int_init(&(kp->q));
+ mp_int_init(&(kp->n));
+ mp_int_init(&(kp->e));
+ mp_int_init(&(kp->d));
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ rsa_key_clear(kp) */
+
+void rsa_key_clear(rsa_key *kp)
+{
+ mp_int_clear(&(kp->p));
+ mp_int_clear(&(kp->q));
+ mp_int_clear(&(kp->n));
+ mp_int_clear(&(kp->e));
+ mp_int_clear(&(kp->d));
+}
+
+/* }}} */
+
+/* {{{ rsa_key_write(kp, ofp) */
+
+void rsa_key_write(rsa_key *kp, FILE *ofp)
+{
+ int len;
+ char *obuf;
+
+ len = mp_int_string_len(&(kp->n), 10);
+ obuf = malloc(len);
+ mp_int_to_string(&(kp->p), 10, obuf, len);
+ fprintf(ofp, "p = %s\n", obuf);
+ mp_int_to_string(&(kp->q), 10, obuf, len);
+ fprintf(ofp, "q = %s\n", obuf);
+ mp_int_to_string(&(kp->e), 10, obuf, len);
+ fprintf(ofp, "e = %s\n", obuf);
+ mp_int_to_string(&(kp->d), 10, obuf, len);
+ fprintf(ofp, "d = %s\n", obuf);
+ mp_int_to_string(&(kp->n), 10, obuf, len);
+ fprintf(ofp, "n = %s\n", obuf);
+
+ free(obuf);
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/findsizes.py b/polly/lib/External/isl/imath/findsizes.py
new file mode 100755
index 00000000000..fc270b38761
--- /dev/null
+++ b/polly/lib/External/isl/imath/findsizes.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+##
+## Name: findsizes.py
+## Purpose: Find acceptable digit and word types for IMath.
+## Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+##
+## Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+##
+## Permission is hereby granted, free of charge, to any person obtaining a
+## copy of this software and associated documentation files (the "Software"),
+## to deal in the Software without restriction, including without limitation
+## the rights to use, copy, modify, merge, publish, distribute, sublicense,
+## and/or sell copies of the Software, and to permit persons to whom the
+## Software is furnished to do so, subject to the following conditions:
+##
+## The above copyright notice and this permission notice shall be included in
+## all copies or substantial portions of the Software.
+##
+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+## THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+## DEALINGS IN THE SOFTWARE.
+##
+import getopt, os, re, subprocess, sys, tempfile
+
+# These are the type names to test for suitability. If your compiler
+# does not support "long long", e.g., it is strict ANSI C90, then you
+# should remove "long long" from this list.
+try_types = [ "unsigned %s" % s for s in
+ ("char", "short", "int", "long", "long long") ]
+
+def main(args):
+ """Scan the Makefile to find appropriate compiler settings, and then
+ compile a test program to emit the sizes of the various types that are
+ considered candidates. The -L (--nolonglong) command line option disables
+ the use of the"long long" type, which is not standard ANSI C90; by default,
+ "long long" is considered.
+ """
+ try:
+ opts, args = getopt.getopt(args, 'L', ('nolonglong',))
+ except getopt.GetoptError, e:
+ print >> sys.stderr, "Usage: findsizes.py [-L/--nolonglong]"
+ sys.exit(1)
+
+ for opt, arg in opts:
+ if opt in ('-L', '--nolonglong'):
+ try:
+ try_types.pop(try_types.index("unsigned long long"))
+ except ValueError: pass
+
+ vars = get_make_info()
+ sizes = get_type_sizes(try_types, vars.get('CC', 'cc'),
+ vars.get('CFLAGS', '').split())
+
+ stypes = sorted(sizes.keys(), key = lambda k: sizes[k], reverse = True)
+ word_type = stypes[0]
+ for t in stypes[1:]:
+ if sizes[t] <= sizes[word_type] / 2:
+ digit_type = t
+ break
+ else:
+ print >> sys.stderr, "Unable to find a compatible digit type."
+ sys.exit(1)
+
+ print "typedef %-20s mp_word; /* %d bytes */\n" \
+ "typedef %-20s mp_digit; /* %d bytes */" % \
+ (word_type, sizes[word_type], digit_type, sizes[digit_type])
+
+def get_type_sizes(types, cc, cflags = ()):
+ """Return a dictionary mapping the names of the specified types to
+ their sizes in bytes, based on the output of the C compiler whose
+ path and arguments are given.
+ """
+ fd, tpath = tempfile.mkstemp(suffix = '.c')
+ fp = os.fdopen(fd, 'r+')
+ fp.seek(0)
+
+ fp.write("#include <stdio.h>\n\nint main(void)\n{\n")
+ for t in types:
+ fp.write(' printf("%%lu\\t%%s\\n", (unsigned long) sizeof(%s), '
+ '\"%s\");\n' % (t, t))
+ fp.write('\n return 0;\n}\n')
+ fp.close()
+
+ print >> sys.stderr, \
+ "Compiler: %s\n" \
+ "Flags: %s\n" \
+ "Source: %s\n" % (cc, ' '.join(cflags), tpath)
+
+ cmd = [cc] + list(cflags) + [tpath]
+ if subprocess.call(cmd) <> 0:
+ raise ValueError("Error while running '%s'" % ' '.join(cmd))
+
+ os.unlink(tpath)
+ if not os.path.isfile('a.out'):
+ raise ValueError("No executable a.out found")
+
+ result = subprocess.Popen(['./a.out'],
+ stdout = subprocess.PIPE).communicate()[0]
+
+ out = {}
+ for line in result.split('\n'):
+ if line.strip() == '':
+ continue
+ size, type = re.split(r'\s+', line, 1)
+ out[type] = int(size)
+
+ os.unlink("a.out")
+ return out
+
+def sub_make_vars(input, vars):
+ """Perform Make style variable substitution in the given input
+ string, using vars as a dictionary of variables to substitute.
+ """
+ def frep(m):
+ try:
+ return vars[m.group(1).strip()]
+ except KeyError:
+ return ' '
+
+ expr = re.compile(r'\$\((\s*\w+\s*)\)')
+ out = input
+ while True:
+ next = expr.sub(frep, out)
+ if next == out:
+ break
+ out = next
+
+ return out
+
+def get_make_info(target = None, makefile = None, makepath = "make",
+ defs = ()):
+ """Extract a listing of all of the variables defined by Make.
+ Returns a dictionary mapping variable names to their string
+ values.
+
+ Optional arguments:
+ target -- the name of the target to request that Make build.
+ makefile -- the path to the Makefile.
+ makepath -- the path to the make executable.
+ defs -- a sequence of strings, additional make arguments.
+ """
+ cmd = [makepath]
+ if defs:
+ cmd.extend(defs)
+ cmd.extend(("-p", "-n"))
+ if makefile is not None:
+ cmd.extend(["-f", makefile])
+ if target is not None:
+ cmd.append(target)
+
+ output = subprocess.Popen(cmd,
+ stdout = subprocess.PIPE,
+ stderr = subprocess.PIPE).communicate()[0]
+ vrule = re.compile(r'^(\w+)\s*=\s*(.*)$')
+
+ vars = {}
+ for line in output.split('\n'):
+ m = vrule.match(line)
+ if m:
+ vars[m.group(1)] = m.group(2)
+
+ for key, val in vars.iteritems():
+ vars[key] = sub_make_vars(val, vars)
+
+ return vars
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
+
+# Here there be dragons
diff --git a/polly/lib/External/isl/imath/findthreshold.py b/polly/lib/External/isl/imath/findthreshold.py
new file mode 100755
index 00000000000..daf3de6580b
--- /dev/null
+++ b/polly/lib/External/isl/imath/findthreshold.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+##
+## Name: findthreshold.py
+## Purpose: Find a good threshold for recursive multiplication.
+## Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+## Info: $Id: findthreshold.py 456 2006-08-16 14:24:06Z sting $
+##
+## This tool computes some timing statistics to help you select a suitable
+## recursive multiplication breakpoint. It uses the imtimer tool to run a
+## series of tests varying precision and breakpoint, and prints out a summary
+## of the "best" values for each category. Each summary line contains the
+## following fields, tab-separated:
+##
+## prec -- the precision of the operands (in digits).
+## thresh -- the threshold for recursive multiplication (digits).
+## trec -- total time using recursive algorithm (sec).
+## tnorm -- total time without recursive algorithm (sec).
+## ratio -- speedup (ratio of tnorm/trec).
+##
+## You are responsible for reading and interpreting the resulting table to
+## obtain a useful value for your workload. Change the value of MP_MULT_THRESH
+## in imath.h once you have a satisfactory result.
+##
+import math, os, random, sys, time
+
+def get_timing_stats(num_tests, precision, threshold, seed = None):
+ """Obtain timing statistics for multiplication.
+
+ num_tests -- number of tests to run.
+ precision -- number of digits per operand.
+ threshold -- threshold in digits for recursive multiply.
+ seed -- random seed; if None, the clock is used.
+
+ Returns a tuple of (seed, bits, time) where seed is the random seed used,
+ bits is the number of bits per operand, and time is a float giving the
+ total time taken for the test run.
+ """
+ if seed is None:
+ seed = int(time.time())
+
+ line = os.popen('./imtimer -mn -p %d -t %d -s %d %d' %
+ (precision, threshold, seed, num_tests), 'r').readline()
+
+ count, prec, bits, thresh, status = line.strip().split('\t')
+ kind, total, unit = status.split()
+
+ return seed, int(bits), float(total)
+
+def check_binary(name):
+ if not os.path.exists(name):
+ os.system('make %s' % name)
+ if not os.path.exists(name):
+ raise ValueError("Unable to build %s" % name)
+ elif not os.path.isfile(name):
+ raise ValueError("Path exists with wrong type")
+
+def compute_stats():
+ check_binary('imtimer')
+ seed = int(time.time())
+
+ print >> sys.stderr, "Computing timer statistics (this may take a while)"
+ stats = {}
+ for prec in (32, 40, 64, 80, 128, 150, 256, 384, 512, 600, 768, 1024):
+ sys.stderr.write('%-4d ' % prec)
+ stats[prec] = (None, 1000000., 0.)
+
+ for thresh in xrange(16, 65, 2):
+ s, b, t = get_timing_stats(1000, prec, thresh, seed)
+ sp, bp, tp = get_timing_stats(1000, prec, prec + 1, seed)
+
+ if t < stats[prec][1]:
+ stats[prec] = (thresh, t, tp)
+ sys.stderr.write('+')
+ else:
+ sys.stderr.write('.')
+ sys.stderr.write('\n')
+
+ return list((p, h, t, tp) for p, (h, t, tp) in stats.iteritems())
+
+if __name__ == "__main__":
+ stats = compute_stats()
+ stats.sort(key = lambda s: s[3]/s[2])
+ for prec, thresh, trec, tnorm in stats:
+ print "%d\t%d\t%.3f\t%.3f\t%.4f" % (prec, thresh, trec, tnorm,
+ tnorm / trec)
+
+ print
+
+# Here there be dragons
diff --git a/polly/lib/External/isl/imath/gmp_compat.c b/polly/lib/External/isl/imath/gmp_compat.c
new file mode 100644
index 00000000000..5d89b3097da
--- /dev/null
+++ b/polly/lib/External/isl/imath/gmp_compat.c
@@ -0,0 +1,861 @@
+/*
+ Name: gmp_compat.c
+ Purpose: Provide GMP compatiable routines for imath library
+ Author: David Peixotto
+
+ Copyright (c) 2012 Qualcomm Innovation Center, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+#include "gmp_compat.h"
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <string.h>
+
+#ifdef NDEBUG
+#define CHECK(res) (res)
+#else
+#define CHECK(res) assert(((res) == MP_OK) && "expected MP_OK")
+#endif
+
+/*************************************************************************
+ *
+ * Functions with direct translations
+ *
+ *************************************************************************/
+/* gmp: mpq_clear */
+void GMPQAPI(clear)(mp_rat x) {
+ mp_rat_clear(x);
+}
+
+/* gmp: mpq_cmp */
+int GMPQAPI(cmp)(mp_rat op1, mp_rat op2) {
+ return mp_rat_compare(op1, op2);
+}
+
+/* gmp: mpq_init */
+void GMPQAPI(init)(mp_rat x) {
+ CHECK(mp_rat_init(x));
+}
+
+/* gmp: mpq_mul */
+void GMPQAPI(mul)(mp_rat product, mp_rat multiplier, mp_rat multiplicand) {
+ CHECK(mp_rat_mul(multiplier, multiplicand, product));
+}
+
+/* gmp: mpq_set*/
+void GMPQAPI(set)(mp_rat rop, mp_rat op) {
+ CHECK(mp_rat_copy(op, rop));
+}
+
+/* gmp: mpz_abs */
+void GMPZAPI(abs)(mp_int rop, mp_int op) {
+ CHECK(mp_int_abs(op, rop));
+}
+
+/* gmp: mpz_add */
+void GMPZAPI(add)(mp_int rop, mp_int op1, mp_int op2) {
+ CHECK(mp_int_add(op1, op2, rop));
+}
+
+/* gmp: mpz_clear */
+void GMPZAPI(clear)(mp_int x) {
+ mp_int_clear(x);
+}
+
+/* gmp: mpz_cmp_si */
+int GMPZAPI(cmp_si)(mp_int op1, long op2) {
+ return mp_int_compare_value(op1, op2);
+}
+
+/* gmp: mpz_cmpabs */
+int GMPZAPI(cmpabs)(mp_int op1, mp_int op2) {
+ return mp_int_compare_unsigned(op1, op2);
+}
+
+/* gmp: mpz_cmp */
+int GMPZAPI(cmp)(mp_int op1, mp_int op2) {
+ return mp_int_compare(op1, op2);
+}
+
+/* gmp: mpz_init */
+void GMPZAPI(init)(mp_int x) {
+ CHECK(mp_int_init(x));
+}
+
+/* gmp: mpz_mul */
+void GMPZAPI(mul)(mp_int rop, mp_int op1, mp_int op2) {
+ CHECK(mp_int_mul(op1, op2, rop));
+}
+
+/* gmp: mpz_neg */
+void GMPZAPI(neg)(mp_int rop, mp_int op) {
+ CHECK(mp_int_neg(op, rop));
+}
+
+/* gmp: mpz_set_si */
+void GMPZAPI(set_si)(mp_int rop, long op) {
+ CHECK(mp_int_set_value(rop, op));
+}
+
+/* gmp: mpz_set */
+void GMPZAPI(set)(mp_int rop, mp_int op) {
+ CHECK(mp_int_copy(op, rop));
+}
+
+/* gmp: mpz_sub */
+void GMPZAPI(sub)(mp_int rop, mp_int op1, mp_int op2) {
+ CHECK(mp_int_sub(op1, op2, rop));
+}
+
+/* gmp: mpz_swap */
+void GMPZAPI(swap)(mp_int rop1, mp_int rop2) {
+ mp_int_swap(rop1, rop2);
+}
+
+/* gmp: mpq_sgn */
+int GMPQAPI(sgn)(mp_rat op) {
+ return mp_rat_compare_zero(op);
+}
+
+/* gmp: mpz_sgn */
+int GMPZAPI(sgn)(mp_int op) {
+ return mp_int_compare_zero(op);
+}
+
+/* gmp: mpq_set_ui */
+void GMPQAPI(set_ui)(mp_rat rop, unsigned long op1, unsigned long op2) {
+ CHECK(mp_rat_set_uvalue(rop, op1, op2));
+}
+
+/* gmp: mpz_set_ui */
+void GMPZAPI(set_ui)(mp_int rop, unsigned long op) {
+ CHECK(mp_int_set_uvalue(rop, op));
+}
+
+/* gmp: mpq_den_ref */
+mp_int GMPQAPI(denref)(mp_rat op) {
+ return mp_rat_denom_ref(op);
+}
+
+/* gmp: mpq_num_ref */
+mp_int GMPQAPI(numref)(mp_rat op) {
+ return mp_rat_numer_ref(op);
+}
+
+/* gmp: mpq_canonicalize */
+void GMPQAPI(canonicalize)(mp_rat op) {
+ CHECK(mp_rat_reduce(op));
+}
+
+/*************************************************************************
+ *
+ * Functions that can be implemented as a combination of imath functions
+ *
+ *************************************************************************/
+/* gmp: mpz_addmul */
+/* gmp: rop = rop + (op1 * op2) */
+void GMPZAPI(addmul)(mp_int rop, mp_int op1, mp_int op2) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ mp_int_init(temp);
+
+ CHECK(mp_int_mul(op1, op2, temp));
+ CHECK(mp_int_add(rop, temp, rop));
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_divexact */
+/* gmp: only produces correct results when d divides n */
+void GMPZAPI(divexact)(mp_int q, mp_int n, mp_int d) {
+ CHECK(mp_int_div(n, d, q, NULL));
+}
+
+/* gmp: mpz_divisible_p */
+/* gmp: return 1 if d divides n, 0 otherwise */
+/* gmp: 0 is considered to divide 0*/
+int GMPZAPI(divisible_p)(mp_int n, mp_int d) {
+ /* variables to hold remainder */
+ mpz_t rz;
+ mp_int r = &rz;
+ int r_is_zero;
+
+ /* check for n = 0, d = 0 */
+ int n_is_zero = mp_int_compare_zero(n) == 0;
+ int d_is_zero = mp_int_compare_zero(d) == 0;
+ if (n_is_zero && d_is_zero)
+ return 1;
+
+ /* return true if remainder is 0 */
+ CHECK(mp_int_init(r));
+ CHECK(mp_int_div(n, d, NULL, r));
+ r_is_zero = mp_int_compare_zero(r) == 0;
+ mp_int_clear(r);
+
+ return r_is_zero;
+}
+
+/* gmp: mpz_submul */
+/* gmp: rop = rop - (op1 * op2) */
+void GMPZAPI(submul)(mp_int rop, mp_int op1, mp_int op2) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ mp_int_init(temp);
+
+ CHECK(mp_int_mul(op1, op2, temp));
+ CHECK(mp_int_sub(rop, temp, rop));
+
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_add_ui */
+void GMPZAPI(add_ui)(mp_int rop, mp_int op1, unsigned long op2) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ CHECK(mp_int_init_uvalue(temp, op2));
+
+ CHECK(mp_int_add(op1, temp, rop));
+
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_divexact_ui */
+/* gmp: only produces correct results when d divides n */
+void GMPZAPI(divexact_ui)(mp_int q, mp_int n, unsigned long d) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ CHECK(mp_int_init_uvalue(temp, d));
+
+ CHECK(mp_int_div(n, temp, q, NULL));
+
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_mul_ui */
+void GMPZAPI(mul_ui)(mp_int rop, mp_int op1, unsigned long op2) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ CHECK(mp_int_init_uvalue(temp, op2));
+
+ CHECK(mp_int_mul(op1, temp, rop));
+
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_pow_ui */
+/* gmp: 0^0 = 1 */
+void GMPZAPI(pow_ui)(mp_int rop, mp_int base, unsigned long exp) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+
+ /* check for 0^0 */
+ if (exp == 0 && mp_int_compare_zero(base) == 0) {
+ CHECK(mp_int_set_value(rop, 1));
+ return;
+ }
+
+ /* rop = base^exp */
+ CHECK(mp_int_init_uvalue(temp, exp));
+ CHECK(mp_int_expt_full(base, temp, rop));
+ mp_int_clear(temp);
+}
+
+/* gmp: mpz_sub_ui */
+void GMPZAPI(sub_ui)(mp_int rop, mp_int op1, unsigned long op2) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ CHECK(mp_int_init_uvalue(temp, op2));
+
+ CHECK(mp_int_sub(op1, temp, rop));
+
+ mp_int_clear(temp);
+}
+
+/*************************************************************************
+ *
+ * Functions with different behavior in corner cases
+ *
+ *************************************************************************/
+
+/* gmp: mpz_gcd */
+void GMPZAPI(gcd)(mp_int rop, mp_int op1, mp_int op2) {
+ int op1_is_zero = mp_int_compare_zero(op1) == 0;
+ int op2_is_zero = mp_int_compare_zero(op2) == 0;
+
+ if (op1_is_zero && op2_is_zero) {
+ mp_int_zero(rop);
+ return;
+ }
+
+ CHECK(mp_int_gcd(op1, op2, rop));
+}
+
+/* gmp: mpz_get_str */
+char* GMPZAPI(get_str)(char *str, int radix, mp_int op) {
+ int i, r, len;
+
+ /* Support negative radix like gmp */
+ r = radix;
+ if (r < 0)
+ r = -r;
+
+ /* Compute the length of the string needed to hold the int */
+ len = mp_int_string_len(op, r);
+ if (str == NULL) {
+ str = malloc(len);
+ }
+
+ /* Convert to string using imath function */
+ CHECK(mp_int_to_string(op, r, str, len));
+
+ /* Change case to match gmp */
+ for (i = 0; i < len; i++)
+ if (radix < 0)
+ str[i] = toupper(str[i]);
+ else
+ str[i] = tolower(str[i]);
+ return str;
+}
+
+/* gmp: mpq_get_str */
+char* GMPQAPI(get_str)(char *str, int radix, mp_rat op) {
+ int i, r, len;
+
+ /* Only print numerator if it is a whole number */
+ if (mp_int_compare_value(mp_rat_denom_ref(op), 1) == 0)
+ return GMPZAPI(get_str)(str, radix, mp_rat_numer_ref(op));
+
+ /* Support negative radix like gmp */
+ r = radix;
+ if (r < 0)
+ r = -r;
+
+ /* Compute the length of the string needed to hold the int */
+ len = mp_rat_string_len(op, r);
+ if (str == NULL) {
+ str = malloc(len);
+ }
+
+ /* Convert to string using imath function */
+ CHECK(mp_rat_to_string(op, r, str, len));
+
+ /* Change case to match gmp */
+ for (i = 0; i < len; i++)
+ if (radix < 0)
+ str[i] = toupper(str[i]);
+ else
+ str[i] = tolower(str[i]);
+
+ return str;
+}
+
+/* gmp: mpz_set_str */
+int GMPZAPI(set_str)(mp_int rop, char *str, int base) {
+ mp_result res = mp_int_read_string(rop, base, str);
+ return ((res == MP_OK) ? 0 : -1);
+}
+
+/* gmp: mpq_set_str */
+int GMPQAPI(set_str)(mp_rat rop, char *s, int base) {
+ char *slash;
+ char *str;
+ mp_result resN;
+ mp_result resD;
+ int res = 0;
+
+ /* Copy string to temporary storage so we can modify it below */
+ str = malloc(strlen(s)+1);
+ strcpy(str, s);
+
+ /* Properly format the string as an int by terminating at the / */
+ slash = strchr(str, '/');
+ if (slash)
+ *slash = '\0';
+
+ /* Parse numerator */
+ resN = mp_int_read_string(mp_rat_numer_ref(rop), base, str);
+
+ /* Parse denomenator if given or set to 1 if not */
+ if (slash)
+ resD = mp_int_read_string(mp_rat_denom_ref(rop), base, slash+1);
+ else
+ resD = mp_int_set_uvalue(mp_rat_denom_ref(rop), 1);
+
+ /* Return failure if either parse failed */
+ if (resN != MP_OK || resD != MP_OK)
+ res = -1;
+
+ free(str);
+ return res;
+}
+
+static unsigned long get_long_bits(mp_int op) {
+ /* Deal with integer that does not fit into unsigned long. We want to grab
+ * the least significant digits that will fit into the long. Read the digits
+ * into the long starting at the most significant digit that fits into a
+ * long. The long is shifted over by MP_DIGIT_BIT before each digit is added.
+ * The shift is decomposed into two steps to follow the patten used in the
+ * rest of the imath library. The two step shift is used to accomedate
+ * architectures that don't deal well with 32-bit shifts. */
+ mp_size num_digits_in_long = sizeof(unsigned long) / sizeof(mp_digit);
+ mp_digit *digits = MP_DIGITS(op);
+ unsigned long out = 0;
+ int i;
+
+ for (i = num_digits_in_long - 1; i >= 0; i--) {
+ out <<= (MP_DIGIT_BIT/2);
+ out <<= (MP_DIGIT_BIT/2);
+ out |= digits[i];
+ }
+
+ return out;
+}
+
+/* gmp: mpz_get_ui */
+unsigned long GMPZAPI(get_ui)(mp_int op) {
+ unsigned long out;
+
+ /* Try a standard conversion that fits into an unsigned long */
+ mp_result res = mp_int_to_uint(op, &out);
+ if (res == MP_OK)
+ return out;
+
+ /* Abort the try if we don't have a range error in the conversion.
+ * The range error indicates that the value cannot fit into a long. */
+ CHECK(res == MP_RANGE ? MP_OK : MP_RANGE);
+ if (res != MP_RANGE)
+ return 0;
+
+ return get_long_bits(op);
+}
+
+/* gmp: mpz_get_si */
+long GMPZAPI(get_si)(mp_int op) {
+ long out;
+ unsigned long uout;
+ int long_msb;
+
+ /* Try a standard conversion that fits into a long */
+ mp_result res = mp_int_to_int(op, &out);
+ if (res == MP_OK)
+ return out;
+
+ /* Abort the try if we don't have a range error in the conversion.
+ * The range error indicates that the value cannot fit into a long. */
+ CHECK(res == MP_RANGE ? MP_OK : MP_RANGE);
+ if (res != MP_RANGE)
+ return 0;
+
+ /* get least significant bits into an unsigned long */
+ uout = get_long_bits(op);
+
+ /* clear the top bit */
+ long_msb = (sizeof(unsigned long) * 8) - 1;
+ uout &= (~(1UL << long_msb));
+
+ /* convert to negative if needed based on sign of op */
+ if (MP_SIGN(op) == MP_NEG)
+ uout = 0 - uout;
+
+ out = (long) uout;
+ return out;
+}
+
+/* gmp: mpz_lcm */
+void GMPZAPI(lcm)(mp_int rop, mp_int op1, mp_int op2) {
+ int op1_is_zero = mp_int_compare_zero(op1) == 0;
+ int op2_is_zero = mp_int_compare_zero(op2) == 0;
+
+ if (op1_is_zero || op2_is_zero) {
+ mp_int_zero(rop);
+ return;
+ }
+
+ CHECK(mp_int_lcm(op1, op2, rop));
+ CHECK(mp_int_abs(rop, rop));
+}
+
+/* gmp: mpz_mul_2exp */
+/* gmp: allow big values for op2 when op1 == 0 */
+void GMPZAPI(mul_2exp)(mp_int rop, mp_int op1, unsigned long op2) {
+ if (mp_int_compare_zero(op1) == 0)
+ mp_int_zero(rop);
+ else
+ CHECK(mp_int_mul_pow2(op1, op2, rop));
+}
+
+/*************************************************************************
+ *
+ * Functions needing expanded functionality
+ *
+ *************************************************************************/
+/* [Note]Overview of division implementation
+
+ All division operations (N / D) compute q and r such that
+
+ N = q * D + r, with 0 <= abs(r) < abs(d)
+
+ The q and r values are not uniquely specified by N and D. To specify which q
+ and r values should be used, GMP implements three different rounding modes
+ for integer division:
+
+ ceiling - round q twords +infinity, r has opposite sign as d
+ floor - round q twords -infinity, r has same sign as d
+ truncate - round q twords zero, r has same sign as n
+
+ The imath library only supports truncate as a rounding mode. We need to
+ implement the other rounding modes in terms of truncating division. We first
+ perform the division in trucate mode and then adjust q accordingly. Once we
+ know q, we can easily compute the correct r according the the formula above
+ by computing:
+
+ r = N - q * D
+
+ The main task is to compute q. We can compute the correct q from a trucated
+ version as follows.
+
+ For ceiling rounding mode, if q is less than 0 then the truncated rounding
+ mode is the same as the ceiling rounding mode. If q is greater than zero
+ then we need to round q up by one because the truncated version was rounded
+ down to zero. If q equals zero then check to see if the result of the
+ divison is positive. A positive result needs to increment q to one.
+
+ For floor rounding mode, if q is greater than 0 then the trucated rounding
+ mode is the same as the floor rounding mode. If q is less than zero then we
+ need to round q down by one because the trucated mode rounded q up by one
+ twords zero. If q is zero then we need to check to see if the result of the
+ division is negative. A negative result needs to decrement q to negative
+ one.
+ */
+
+/* gmp: mpz_cdiv_q */
+void GMPZAPI(cdiv_q)(mp_int q, mp_int n, mp_int d) {
+ mpz_t rz;
+ mp_int r = &rz;
+ int qsign, rsign, nsign, dsign;
+ CHECK(mp_int_init(r));
+
+ /* save signs before division because q can alias with n or d */
+ nsign = mp_int_compare_zero(n);
+ dsign = mp_int_compare_zero(d);
+
+ /* truncating division */
+ CHECK(mp_int_div(n, d, q, r));
+
+ /* see: [Note]Overview of division implementation */
+ qsign = mp_int_compare_zero(q);
+ rsign = mp_int_compare_zero(r);
+ if (qsign > 0) { /* q > 0 */
+ if (rsign != 0) { /* r != 0 */
+ CHECK(mp_int_add_value(q, 1, q));
+ }
+ }
+ else if (qsign == 0) { /* q == 0 */
+ if (rsign != 0) { /* r != 0 */
+ if ((nsign > 0 && dsign > 0) || (nsign < 0 && dsign < 0)) {
+ CHECK(mp_int_set_value(q, 1));
+ }
+ }
+ }
+ mp_int_clear(r);
+}
+
+/* gmp: mpz_fdiv_q */
+void GMPZAPI(fdiv_q)(mp_int q, mp_int n, mp_int d) {
+ mpz_t rz;
+ mp_int r = &rz;
+ int qsign, rsign, nsign, dsign;
+ CHECK(mp_int_init(r));
+
+ /* save signs before division because q can alias with n or d */
+ nsign = mp_int_compare_zero(n);
+ dsign = mp_int_compare_zero(d);
+
+ /* truncating division */
+ CHECK(mp_int_div(n, d, q, r));
+
+ /* see: [Note]Overview of division implementation */
+ qsign = mp_int_compare_zero(q);
+ rsign = mp_int_compare_zero(r);
+ if (qsign < 0) { /* q < 0 */
+ if (rsign != 0) { /* r != 0 */
+ CHECK(mp_int_sub_value(q, 1, q));
+ }
+ }
+ else if (qsign == 0) { /* q == 0 */
+ if (rsign != 0) { /* r != 0 */
+ if ((nsign < 0 && dsign > 0) || (nsign > 0 && dsign < 0)) {
+ CHECK(mp_int_set_value(q, -1));
+ }
+ }
+ }
+ mp_int_clear(r);
+}
+
+/* gmp: mpz_fdiv_r */
+void GMPZAPI(fdiv_r)(mp_int r, mp_int n, mp_int d) {
+ mpz_t qz;
+ mpz_t tempz;
+ mpz_t orig_dz;
+ mpz_t orig_nz;
+ mp_int q = &qz;
+ mp_int temp = &tempz;
+ mp_int orig_d = &orig_dz;
+ mp_int orig_n = &orig_nz;
+ CHECK(mp_int_init(q));
+ CHECK(mp_int_init(temp));
+ /* Make a copy of n in case n and d in case they overlap with q */
+ CHECK(mp_int_init_copy(orig_d, d));
+ CHECK(mp_int_init_copy(orig_n, n));
+
+ /* floor division */
+ GMPZAPI(fdiv_q)(q, n, d);
+
+ /* see: [Note]Overview of division implementation */
+ /* n = q * d + r ==> r = n - q * d */
+ mp_int_mul(q, orig_d, temp);
+ mp_int_sub(orig_n, temp, r);
+
+ mp_int_clear(q);
+ mp_int_clear(temp);
+ mp_int_clear(orig_d);
+ mp_int_clear(orig_n);
+}
+
+/* gmp: mpz_tdiv_q */
+void GMPZAPI(tdiv_q)(mp_int q, mp_int n, mp_int d) {
+ /* truncating division*/
+ CHECK(mp_int_div(n, d, q, NULL));
+}
+
+/* gmp: mpz_fdiv_q_ui */
+unsigned long GMPZAPI(fdiv_q_ui)(mp_int q, mp_int n, unsigned long d) {
+ mpz_t tempz;
+ mp_int temp = &tempz;
+ mpz_t rz;
+ mp_int r = &rz;
+ mpz_t orig_nz;
+ mp_int orig_n = &orig_nz;
+ unsigned long rl;
+ CHECK(mp_int_init_uvalue(temp, d));
+ CHECK(mp_int_init(r));
+ /* Make a copy of n in case n and q overlap */
+ CHECK(mp_int_init_copy(orig_n, n));
+
+ /* use floor division mode to compute q and r */
+ GMPZAPI(fdiv_q)(q, n, temp);
+ GMPZAPI(fdiv_r)(r, orig_n, temp);
+ CHECK(mp_int_to_uint(r, &rl));
+
+ mp_int_clear(temp);
+ mp_int_clear(r);
+ mp_int_clear(orig_n);
+
+ return rl;
+}
+
+/* gmp: mpz_export */
+void* GMPZAPI(export)(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, mp_int op) {
+ int i;
+ int num_used_bytes;
+ size_t num_words, num_missing_bytes;
+ unsigned char* dst;
+ unsigned char* src;
+
+ /* We do not have a complete implementation. Assert to ensure our
+ * restrictions are in place, We do not support big endian output, but do not
+ * check that native endian is little endian. */
+ assert(nails == 0 && "Do not support non-full words");
+ assert((endian == 0 || endian == -1) && "Do not support big endian");
+
+ /* The gmp API requires that order must be -1 or 1.
+ Not sure how gmp behaves when order is not 1 or -1, so force all non-one
+ values to -1 for now. */
+ if (order != 1) order = -1;
+
+ /* Test for zero */
+ if (mp_int_compare_zero(op) == 0) {
+ if (countp)
+ *countp = 0;
+ return rop;
+ }
+
+ /* Calculate how many words we need */
+ num_used_bytes = mp_int_unsigned_len(op);
+ num_words = (num_used_bytes + (size-1)) / size; /* ceil division */
+ assert(num_used_bytes > 0);
+
+ /* Check to see if we will have missing bytes in the last word.
+
+ Missing bytes can only occur when the size of words we output is
+ greater than the size of words used internally by imath. The number of
+ missing bytes is the number of bytes needed to fill out the last word. If
+ this number is greater than the size of a single mp_digit, then we need to
+ pad the word with extra zeros. Otherwise, the missing bytes can be filled
+ directly from the zeros in the last digit in the number.
+ */
+ num_missing_bytes = (size * num_words) - num_used_bytes;
+ assert(num_missing_bytes < size);
+
+ /* Allocate space for the result if needed */
+ if (rop == NULL) {
+ rop = malloc(num_words * size);
+ }
+
+ /* Initialize dst and src pointers */
+ dst = (unsigned char *)rop;
+ src = (unsigned char *)MP_DIGITS(op);
+
+ /* Most significant word first */
+ if (order == 1) {
+ size_t words_written = 0;
+ src += (num_words-1) * size;
+
+ /* Handle write of first word specially */
+ for (i = 0; i < size - num_missing_bytes; i++)
+ dst[i] = src[i];
+ for (; i < size; i++)
+ dst[i] = 0;
+ dst += size;
+ src -= size;
+ words_written++;
+
+ for (; words_written < num_words; words_written++) {
+ for (i = 0; i < size; i++)
+ dst[i] = src[i];
+ dst += size;
+ src -= size;
+ }
+ }
+ /* Least significant word first */
+ else {
+ size_t words_written = 0;
+ for (; words_written < num_words - 1; words_written++) {
+ for (i = 0; i < size; i++)
+ dst[i] = src[i];
+ dst += size;
+ src += size;
+ }
+
+ /* Handle write of last word specially */
+ for (i = 0; i < size - num_missing_bytes; i++)
+ dst[i] = src[i];
+
+ for (; i < size; i++)
+ dst[i] = 0;
+ }
+
+ if (countp)
+ *countp = num_words;
+ return rop;
+}
+
+/* gmp: mpz_import */
+void GMPZAPI(import)(mp_int rop, size_t count, int order, size_t size, int endian, size_t nails, const void* op) {
+ mpz_t tmpz;
+ mp_int tmp = &tmpz;
+ size_t total_size;
+ size_t num_digits;
+ const char *src;
+ char *dst;
+ int i;
+ if (count == 0 || op == NULL)
+ return;
+
+ /* We do not have a complete implementation. Assert to ensure our
+ * restrictions are in place, We do not support big endian output, but do not
+ * check that native endian is little endian. */
+ assert(nails == 0 && "Do not support non-full words");
+ assert((endian == 0 || endian == -1) && "Do not support big endian");
+
+ /* Compute number of needed digits by ceil division */
+ total_size = count * size;
+ num_digits = (total_size + sizeof(mp_digit) - 1) / sizeof(mp_digit);
+
+ /* Init temporary */
+ mp_int_init_size(tmp, num_digits);
+ for (i = 0; i < num_digits; i++)
+ tmp->digits[i] = 0;
+
+ /* Copy bytes */
+ src = (const char *) op;
+ dst = (char *)MP_DIGITS(tmp);
+
+ /* Most significant word is first */
+ if (order == 1) {
+ size_t word;
+ dst += (count - 1) * size;
+ for (word = 0; word < count; word++) {
+ for (i = 0; i < size; i++)
+ dst[i] = src[i];
+ dst -= size;
+ src += size;
+ }
+ }
+ /* Least significant word is first */
+ else {
+ size_t word;
+ for (word = 0; word < count; word++) {
+ for (i = 0; i < size; i++)
+ dst[i] = src[i];
+ dst += size;
+ src += size;
+ }
+ }
+ MP_USED(tmp) = num_digits;
+
+ /* Remove leading zeros from number */
+ {
+ mp_size uz_ = MP_USED(tmp);
+ mp_digit *dz_ = MP_DIGITS(tmp) + uz_ -1;
+ while (uz_ > 1 && (*dz_-- == 0))
+ --uz_;
+ MP_USED(tmp) = uz_;
+ }
+
+ /* Copy to destination */
+ mp_int_copy(tmp, rop);
+}
+
+/* gmp: mpz_sizeinbase */
+size_t GMPZAPI(sizeinbase)(mp_int op, int base) {
+ mp_result res;
+ size_t size;
+
+ /* If op == 0, return 1 */
+ if (mp_int_compare_zero(op) == 0)
+ return 1;
+
+ /* Compute string length in base */
+ res = mp_int_string_len(op, base);
+ CHECK((res > 0) == MP_OK);
+
+ /* Now adjust the final size by getting rid of string artifacts */
+ size = res;
+
+ /* subtract one for the null terminator */
+ size -= 1;
+
+ /* subtract one for the negative sign */
+ if (mp_int_compare_zero(op) < 0)
+ size -= 1;
+
+ return size;
+}
diff --git a/polly/lib/External/isl/imath/gmp_compat.h b/polly/lib/External/isl/imath/gmp_compat.h
new file mode 100644
index 00000000000..949e377e979
--- /dev/null
+++ b/polly/lib/External/isl/imath/gmp_compat.h
@@ -0,0 +1,229 @@
+/*
+ Name: gmp_compat.h
+ Purpose: Provide GMP compatiable routines for imath library
+ Author: David Peixotto
+
+ Copyright (c) 2012 Qualcomm Innovation Center, Inc. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef IMATH_GMP_COMPAT_H_
+#define IMATH_GMP_COMPAT_H_
+#include "imath.h"
+#include "imrat.h"
+#include <stddef.h>
+
+#define GMPZAPI(fun) impz_ ## fun
+#define GMPQAPI(fun) impq_ ## fun
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*************************************************************************
+ *
+ * Functions with direct translations
+ *
+ *************************************************************************/
+/* gmp: mpq_clear */
+void GMPQAPI(clear)(mp_rat x);
+
+/* gmp: mpq_cmp */
+int GMPQAPI(cmp)(mp_rat op1, mp_rat op2);
+
+/* gmp: mpq_init */
+void GMPQAPI(init)(mp_rat x);
+
+/* gmp: mpq_mul */
+void GMPQAPI(mul)(mp_rat product, mp_rat multiplier, mp_rat multiplicand);
+
+/* gmp: mpq_set */
+void GMPQAPI(set)(mp_rat rop, mp_rat op);
+
+/* gmp: mpz_abs */
+void GMPZAPI(abs)(mp_int rop, mp_int op);
+
+/* gmp: mpz_add */
+void GMPZAPI(add)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_clear */
+void GMPZAPI(clear)(mp_int x);
+
+/* gmp: mpz_cmp_si */
+int GMPZAPI(cmp_si)(mp_int op1, long op2);
+
+/* gmp: mpz_cmpabs */
+int GMPZAPI(cmpabs)(mp_int op1, mp_int op2);
+
+/* gmp: mpz_cmp */
+int GMPZAPI(cmp)(mp_int op1, mp_int op2);
+
+/* gmp: mpz_init */
+void GMPZAPI(init)(mp_int x);
+
+/* gmp: mpz_mul */
+void GMPZAPI(mul)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_neg */
+void GMPZAPI(neg)(mp_int rop, mp_int op);
+
+/* gmp: mpz_set_si */
+void GMPZAPI(set_si)(mp_int rop, long op);
+
+/* gmp: mpz_set */
+void GMPZAPI(set)(mp_int rop, mp_int op);
+
+/* gmp: mpz_sub */
+void GMPZAPI(sub)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_swap */
+void GMPZAPI(swap)(mp_int rop1, mp_int rop2);
+
+/* gmp: mpq_sgn */
+int GMPQAPI(sgn)(mp_rat op);
+
+/* gmp: mpz_sgn */
+int GMPZAPI(sgn)(mp_int op);
+
+/* gmp: mpq_set_ui */
+void GMPQAPI(set_ui)(mp_rat rop, unsigned long op1, unsigned long op2);
+
+/* gmp: mpz_set_ui */
+void GMPZAPI(set_ui)(mp_int rop, unsigned long op);
+
+/* gmp: mpq_den_ref */
+mp_int GMPQAPI(denref)(mp_rat op);
+
+/* gmp: mpq_num_ref */
+mp_int GMPQAPI(numref)(mp_rat op);
+
+/* gmp: mpq_canonicalize */
+void GMPQAPI(canonicalize)(mp_rat op);
+
+/*************************************************************************
+ *
+ * Functions that can be implemented as a combination of imath functions
+ *
+ *************************************************************************/
+/* gmp: mpz_addmul */
+void GMPZAPI(addmul)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_divexact */
+void GMPZAPI(divexact)(mp_int q, mp_int n, mp_int d);
+
+/* gmp: mpz_divisible_p */
+int GMPZAPI(divisible_p)(mp_int n, mp_int d);
+
+/* gmp: mpz_submul */
+void GMPZAPI(submul)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_add_ui */
+void GMPZAPI(add_ui)(mp_int rop, mp_int op1, unsigned long op2);
+
+/* gmp: mpz_divexact_ui */
+void GMPZAPI(divexact_ui)(mp_int q, mp_int n, unsigned long d);
+
+/* gmp: mpz_mul_ui */
+void GMPZAPI(mul_ui)(mp_int rop, mp_int op1, unsigned long op2);
+
+/* gmp: mpz_pow_ui */
+void GMPZAPI(pow_ui)(mp_int rop, mp_int base, unsigned long exp);
+
+/* gmp: mpz_sub_ui */
+void GMPZAPI(sub_ui)(mp_int rop, mp_int op1, unsigned long op2);
+
+/* gmp: mpz_fdiv_q_ui */
+unsigned long GMPZAPI(fdiv_q_ui)(mp_int q, mp_int n, unsigned long d);
+
+/* gmp: mpz_sizeinbase */
+size_t GMPZAPI(sizeinbase)(mp_int op, int base);
+
+/*************************************************************************
+ *
+ * Functions with different behavior in corner cases
+ *
+ *************************************************************************/
+/* gmp: mpz_gcd */
+/* gmp: When op1 = 0 and op2 = 0, return 0.*/
+void GMPZAPI(gcd)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_get_str */
+/* gmp: If str is NULL then allocate space using the default allocator. */
+char* GMPZAPI(get_str)(char *str, int radix, mp_int op);
+
+/* gmp: mpq_get_str */
+/* gmp: If str is NULL then allocate space using the default allocator. */
+/* gmp: If value is a whole number do not print denomenator. */
+/* TODO: Need to handle 0 values better. GMP prints 0/4 instead of 0.*/
+char* GMPQAPI(get_str)(char *str, int radix, mp_rat op);
+
+/* gmp: mpz_set_str */
+/* gmp: Allow and ignore spaces in string. */
+int GMPZAPI(set_str)(mp_int rop, char *str, int base);
+
+/* gmp: mpq_set_str */
+int GMPQAPI(set_str)(mp_rat rop, char *str, int base);
+
+/* gmp: mpz_get_ui */
+/* gmp: Return least significant bits if value is too big for a long. */
+unsigned long GMPZAPI(get_ui)(mp_int op);
+
+/* gmp: mpz_get_si */
+/* gmp: Return least significant bits if value is too bit for a long. */
+/* gmp: If value is too big for long, return the least significant
+ (8*sizeof(long)-1) bits from the op and set the sign bit according to
+ the sign of the op. */
+long GMPZAPI(get_si)(mp_int op);
+
+/* gmp: mpz_lcm */
+/* gmp: When op1 = 0 or op2 = 0, return 0.*/
+/* gmp: The resutl of lcm(a,b) is always positive. */
+void GMPZAPI(lcm)(mp_int rop, mp_int op1, mp_int op2);
+
+/* gmp: mpz_mul_2exp */
+/* gmp: allow big values for op2 when op1 == 0 */
+void GMPZAPI(mul_2exp)(mp_int rop, mp_int op1, unsigned long op2);
+
+/*************************************************************************
+ *
+ * Functions needing expanded functionality
+ *
+ *************************************************************************/
+/* gmp: mpz_cdiv_q */
+void GMPZAPI(cdiv_q)(mp_int q, mp_int n, mp_int d);
+
+/* gmp: mpz_fdiv_q */
+void GMPZAPI(fdiv_q)(mp_int q, mp_int n, mp_int d);
+
+/* gmp: mpz_fdiv_r */
+void GMPZAPI(fdiv_r)(mp_int r, mp_int n, mp_int d);
+
+/* gmp: mpz_tdiv_q */
+void GMPZAPI(tdiv_q)(mp_int q, mp_int n, mp_int d);
+
+/* gmp: mpz_export */
+void* GMPZAPI(export)(void *rop, size_t *countp, int order, size_t size, int endian, size_t nails, mp_int op);
+
+/* gmp: mpz_import */
+void GMPZAPI(import)(mp_int rop, size_t count, int order, size_t size, int endian, size_t nails, const void* op);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* end IMATH_GMP_COMPAT_H_ */
diff --git a/polly/lib/External/isl/imath/imath.c b/polly/lib/External/isl/imath/imath.c
new file mode 100644
index 00000000000..306678ec963
--- /dev/null
+++ b/polly/lib/External/isl/imath/imath.c
@@ -0,0 +1,3668 @@
+/*
+ Name: imath.c
+ Purpose: Arbitrary precision integer arithmetic routines.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include "imath.h"
+
+#if DEBUG
+#include <stdio.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <assert.h>
+
+#if DEBUG
+#define STATIC /* public */
+#else
+#define STATIC static
+#endif
+
+/* {{{ Constants */
+
+const mp_result MP_OK = 0; /* no error, all is well */
+const mp_result MP_FALSE = 0; /* boolean false */
+const mp_result MP_TRUE = -1; /* boolean true */
+const mp_result MP_MEMORY = -2; /* out of memory */
+const mp_result MP_RANGE = -3; /* argument out of range */
+const mp_result MP_UNDEF = -4; /* result undefined */
+const mp_result MP_TRUNC = -5; /* output truncated */
+const mp_result MP_BADARG = -6; /* invalid null argument */
+const mp_result MP_MINERR = -6;
+
+const mp_sign MP_NEG = 1; /* value is strictly negative */
+const mp_sign MP_ZPOS = 0; /* value is non-negative */
+
+STATIC const char *s_unknown_err = "unknown result code";
+STATIC const char *s_error_msg[] = {
+ "error code 0",
+ "boolean true",
+ "out of memory",
+ "argument out of range",
+ "result undefined",
+ "output truncated",
+ "invalid argument",
+ NULL
+};
+
+/* }}} */
+
+/* Argument checking macros
+ Use CHECK() where a return value is required; NRCHECK() elsewhere */
+#define CHECK(TEST) assert(TEST)
+#define NRCHECK(TEST) assert(TEST)
+
+/* {{{ Logarithm table for computing output sizes */
+
+/* The ith entry of this table gives the value of log_i(2).
+
+ An integer value n requires ceil(log_i(n)) digits to be represented
+ in base i. Since it is easy to compute lg(n), by counting bits, we
+ can compute log_i(n) = lg(n) * log_i(2).
+
+ The use of this table eliminates a dependency upon linkage against
+ the standard math libraries.
+
+ If MP_MAX_RADIX is increased, this table should be expanded too.
+ */
+STATIC const double s_log2[] = {
+ 0.000000000, 0.000000000, 1.000000000, 0.630929754, /* (D)(D) 2 3 */
+ 0.500000000, 0.430676558, 0.386852807, 0.356207187, /* 4 5 6 7 */
+ 0.333333333, 0.315464877, 0.301029996, 0.289064826, /* 8 9 10 11 */
+ 0.278942946, 0.270238154, 0.262649535, 0.255958025, /* 12 13 14 15 */
+ 0.250000000, 0.244650542, 0.239812467, 0.235408913, /* 16 17 18 19 */
+ 0.231378213, 0.227670249, 0.224243824, 0.221064729, /* 20 21 22 23 */
+ 0.218104292, 0.215338279, 0.212746054, 0.210309918, /* 24 25 26 27 */
+ 0.208014598, 0.205846832, 0.203795047, 0.201849087, /* 28 29 30 31 */
+ 0.200000000, 0.198239863, 0.196561632, 0.194959022, /* 32 33 34 35 */
+ 0.193426404, /* 36 */
+};
+
+/* }}} */
+/* {{{ Various macros */
+
+/* Return the number of digits needed to represent a static value */
+#define MP_VALUE_DIGITS(V) \
+((sizeof(V)+(sizeof(mp_digit)-1))/sizeof(mp_digit))
+
+/* Round precision P to nearest word boundary */
+#define ROUND_PREC(P) ((mp_size)(2*(((P)+1)/2)))
+
+/* Set array P of S digits to zero */
+#define ZERO(P, S) \
+do{ \
+ mp_size i__ = (S) * sizeof(mp_digit); \
+ mp_digit *p__ = (P); \
+ memset(p__, 0, i__); \
+} while(0)
+
+/* Copy S digits from array P to array Q */
+#define COPY(P, Q, S) \
+do{ \
+ mp_size i__ = (S) * sizeof(mp_digit); \
+ mp_digit *p__ = (P), *q__ = (Q); \
+ memcpy(q__, p__, i__); \
+} while(0)
+
+/* Reverse N elements of type T in array A */
+#define REV(T, A, N) \
+do{ \
+ T *u_ = (A), *v_ = u_ + (N) - 1; \
+ while (u_ < v_) { \
+ T xch = *u_; \
+ *u_++ = *v_; \
+ *v_-- = xch; \
+ } \
+} while(0)
+
+#define CLAMP(Z) \
+do{ \
+ mp_int z_ = (Z); \
+ mp_size uz_ = MP_USED(z_); \
+ mp_digit *dz_ = MP_DIGITS(z_) + uz_ -1; \
+ while (uz_ > 1 && (*dz_-- == 0)) \
+ --uz_; \
+ MP_USED(z_) = uz_; \
+} while(0)
+
+/* Select min/max. Do not provide expressions for which multiple
+ evaluation would be problematic, e.g. x++ */
+#define MIN(A, B) ((B)<(A)?(B):(A))
+#define MAX(A, B) ((B)>(A)?(B):(A))
+
+/* Exchange lvalues A and B of type T, e.g.
+ SWAP(int, x, y) where x and y are variables of type int. */
+#define SWAP(T, A, B) \
+do{ \
+ T t_ = (A); \
+ A = (B); \
+ B = t_; \
+} while(0)
+
+/* Used to set up and access simple temp stacks within functions. */
+#define DECLARE_TEMP(N) \
+ mpz_t temp[(N)]; \
+ int last__ = 0
+#define CLEANUP_TEMP() \
+ CLEANUP: \
+ while (--last__ >= 0) \
+ mp_int_clear(TEMP(last__))
+#define TEMP(K) (temp + (K))
+#define LAST_TEMP() TEMP(last__)
+#define SETUP(E) \
+do{ \
+ if ((res = (E)) != MP_OK) \
+ goto CLEANUP; \
+ ++(last__); \
+} while(0)
+
+/* Compare value to zero. */
+#define CMPZ(Z) \
+(((Z)->used==1&&(Z)->digits[0]==0)?0:((Z)->sign==MP_NEG)?-1:1)
+
+/* Multiply X by Y into Z, ignoring signs. Requires that Z have
+ enough storage preallocated to hold the result. */
+#define UMUL(X, Y, Z) \
+do{ \
+ mp_size ua_ = MP_USED(X), ub_ = MP_USED(Y); \
+ mp_size o_ = ua_ + ub_; \
+ ZERO(MP_DIGITS(Z), o_); \
+ (void) s_kmul(MP_DIGITS(X), MP_DIGITS(Y), MP_DIGITS(Z), ua_, ub_); \
+ MP_USED(Z) = o_; \
+ CLAMP(Z); \
+} while(0)
+
+/* Square X into Z. Requires that Z have enough storage to hold the
+ result. */
+#define USQR(X, Z) \
+do{ \
+ mp_size ua_ = MP_USED(X), o_ = ua_ + ua_; \
+ ZERO(MP_DIGITS(Z), o_); \
+ (void) s_ksqr(MP_DIGITS(X), MP_DIGITS(Z), ua_); \
+ MP_USED(Z) = o_; \
+ CLAMP(Z); \
+} while(0)
+
+#define UPPER_HALF(W) ((mp_word)((W) >> MP_DIGIT_BIT))
+#define LOWER_HALF(W) ((mp_digit)(W))
+#define HIGH_BIT_SET(W) ((W) >> (MP_WORD_BIT - 1))
+#define ADD_WILL_OVERFLOW(W, V) ((MP_WORD_MAX - (V)) < (W))
+
+/* }}} */
+/* {{{ Default configuration settings */
+
+/* Default number of digits allocated to a new mp_int */
+#if IMATH_TEST
+mp_size default_precision = MP_DEFAULT_PREC;
+#else
+STATIC const mp_size default_precision = MP_DEFAULT_PREC;
+#endif
+
+/* Minimum number of digits to invoke recursive multiply */
+#if IMATH_TEST
+mp_size multiply_threshold = MP_MULT_THRESH;
+#else
+STATIC const mp_size multiply_threshold = MP_MULT_THRESH;
+#endif
+
+/* }}} */
+
+/* Allocate a buffer of (at least) num digits, or return
+ NULL if that couldn't be done. */
+STATIC mp_digit *s_alloc(mp_size num);
+
+/* Release a buffer of digits allocated by s_alloc(). */
+STATIC void s_free(void *ptr);
+
+/* Insure that z has at least min digits allocated, resizing if
+ necessary. Returns true if successful, false if out of memory. */
+STATIC int s_pad(mp_int z, mp_size min);
+
+/* Fill in a "fake" mp_int on the stack with a given value */
+STATIC void s_fake(mp_int z, mp_small value, mp_digit vbuf[]);
+STATIC void s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[]);
+
+/* Compare two runs of digits of given length, returns <0, 0, >0 */
+STATIC int s_cdig(mp_digit *da, mp_digit *db, mp_size len);
+
+/* Pack the unsigned digits of v into array t */
+STATIC int s_uvpack(mp_usmall v, mp_digit t[]);
+
+/* Compare magnitudes of a and b, returns <0, 0, >0 */
+STATIC int s_ucmp(mp_int a, mp_int b);
+
+/* Compare magnitudes of a and v, returns <0, 0, >0 */
+STATIC int s_vcmp(mp_int a, mp_small v);
+STATIC int s_uvcmp(mp_int a, mp_usmall uv);
+
+/* Unsigned magnitude addition; assumes dc is big enough.
+ Carry out is returned (no memory allocated). */
+STATIC mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b);
+
+/* Unsigned magnitude subtraction. Assumes dc is big enough. */
+STATIC void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b);
+
+/* Unsigned recursive multiplication. Assumes dc is big enough. */
+STATIC int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b);
+
+/* Unsigned magnitude multiplication. Assumes dc is big enough. */
+STATIC void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b);
+
+/* Unsigned recursive squaring. Assumes dc is big enough. */
+STATIC int s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a);
+
+/* Unsigned magnitude squaring. Assumes dc is big enough. */
+STATIC void s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a);
+
+/* Single digit addition. Assumes a is big enough. */
+STATIC void s_dadd(mp_int a, mp_digit b);
+
+/* Single digit multiplication. Assumes a is big enough. */
+STATIC void s_dmul(mp_int a, mp_digit b);
+
+/* Single digit multiplication on buffers; assumes dc is big enough. */
+STATIC void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc,
+ mp_size size_a);
+
+/* Single digit division. Replaces a with the quotient,
+ returns the remainder. */
+STATIC mp_digit s_ddiv(mp_int a, mp_digit b);
+
+/* Quick division by a power of 2, replaces z (no allocation) */
+STATIC void s_qdiv(mp_int z, mp_size p2);
+
+/* Quick remainder by a power of 2, replaces z (no allocation) */
+STATIC void s_qmod(mp_int z, mp_size p2);
+
+/* Quick multiplication by a power of 2, replaces z.
+ Allocates if necessary; returns false in case this fails. */
+STATIC int s_qmul(mp_int z, mp_size p2);
+
+/* Quick subtraction from a power of 2, replaces z.
+ Allocates if necessary; returns false in case this fails. */
+STATIC int s_qsub(mp_int z, mp_size p2);
+
+/* Return maximum k such that 2^k divides z. */
+STATIC int s_dp2k(mp_int z);
+
+/* Return k >= 0 such that z = 2^k, or -1 if there is no such k. */
+STATIC int s_isp2(mp_int z);
+
+/* Set z to 2^k. May allocate; returns false in case this fails. */
+STATIC int s_2expt(mp_int z, mp_small k);
+
+/* Normalize a and b for division, returns normalization constant */
+STATIC int s_norm(mp_int a, mp_int b);
+
+/* Compute constant mu for Barrett reduction, given modulus m, result
+ replaces z, m is untouched. */
+STATIC mp_result s_brmu(mp_int z, mp_int m);
+
+/* Reduce a modulo m, using Barrett's algorithm. */
+STATIC int s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2);
+
+/* Modular exponentiation, using Barrett reduction */
+STATIC mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c);
+
+/* Unsigned magnitude division. Assumes |a| > |b|. Allocates temporaries;
+ overwrites a with quotient, b with remainder. */
+STATIC mp_result s_udiv_knuth(mp_int a, mp_int b);
+
+/* Compute the number of digits in radix r required to represent the given
+ value. Does not account for sign flags, terminators, etc. */
+STATIC int s_outlen(mp_int z, mp_size r);
+
+/* Guess how many digits of precision will be needed to represent a radix r
+ value of the specified number of digits. Returns a value guaranteed to be
+ no smaller than the actual number required. */
+STATIC mp_size s_inlen(int len, mp_size r);
+
+/* Convert a character to a digit value in radix r, or
+ -1 if out of range */
+STATIC int s_ch2val(char c, int r);
+
+/* Convert a digit value to a character */
+STATIC char s_val2ch(int v, int caps);
+
+/* Take 2's complement of a buffer in place */
+STATIC void s_2comp(unsigned char *buf, int len);
+
+/* Convert a value to binary, ignoring sign. On input, *limpos is the bound on
+ how many bytes should be written to buf; on output, *limpos is set to the
+ number of bytes actually written. */
+STATIC mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad);
+
+#if DEBUG
+/* Dump a representation of the mp_int to standard output */
+void s_print(char *tag, mp_int z);
+void s_print_buf(char *tag, mp_digit *buf, mp_size num);
+#endif
+
+/* {{{ mp_int_init(z) */
+
+mp_result mp_int_init(mp_int z)
+{
+ if (z == NULL)
+ return MP_BADARG;
+
+ z->single = 0;
+ z->digits = &(z->single);
+ z->alloc = 1;
+ z->used = 1;
+ z->sign = MP_ZPOS;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_alloc() */
+
+mp_int mp_int_alloc(void)
+{
+ mp_int out = malloc(sizeof(mpz_t));
+
+ if (out != NULL)
+ mp_int_init(out);
+
+ return out;
+}
+
+/* }}} */
+
+/* {{{ mp_int_init_size(z, prec) */
+
+mp_result mp_int_init_size(mp_int z, mp_size prec)
+{
+ CHECK(z != NULL);
+
+ if (prec == 0)
+ prec = default_precision;
+ else if (prec == 1)
+ return mp_int_init(z);
+ else
+ prec = (mp_size) ROUND_PREC(prec);
+
+ if ((MP_DIGITS(z) = s_alloc(prec)) == NULL)
+ return MP_MEMORY;
+
+ z->digits[0] = 0;
+ MP_USED(z) = 1;
+ MP_ALLOC(z) = prec;
+ MP_SIGN(z) = MP_ZPOS;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_init_copy(z, old) */
+
+mp_result mp_int_init_copy(mp_int z, mp_int old)
+{
+ mp_result res;
+ mp_size uold;
+
+ CHECK(z != NULL && old != NULL);
+
+ uold = MP_USED(old);
+ if (uold == 1) {
+ mp_int_init(z);
+ }
+ else {
+ mp_size target = MAX(uold, default_precision);
+
+ if ((res = mp_int_init_size(z, target)) != MP_OK)
+ return res;
+ }
+
+ MP_USED(z) = uold;
+ MP_SIGN(z) = MP_SIGN(old);
+ COPY(MP_DIGITS(old), MP_DIGITS(z), uold);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_init_value(z, value) */
+
+mp_result mp_int_init_value(mp_int z, mp_small value)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+ return mp_int_init_copy(z, &vtmp);
+}
+
+/* }}} */
+
+/* {{{ mp_int_init_uvalue(z, uvalue) */
+
+mp_result mp_int_init_uvalue(mp_int z, mp_usmall uvalue)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(uvalue)];
+
+ s_ufake(&vtmp, uvalue, vbuf);
+ return mp_int_init_copy(z, &vtmp);
+}
+
+/* }}} */
+
+/* {{{ mp_int_set_value(z, value) */
+
+mp_result mp_int_set_value(mp_int z, mp_small value)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+ return mp_int_copy(&vtmp, z);
+}
+
+/* }}} */
+
+/* {{{ mp_int_set_uvalue(z, value) */
+
+mp_result mp_int_set_uvalue(mp_int z, mp_usmall uvalue)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(uvalue)];
+
+ s_ufake(&vtmp, uvalue, vbuf);
+ return mp_int_copy(&vtmp, z);
+}
+
+/* }}} */
+
+/* {{{ mp_int_clear(z) */
+
+void mp_int_clear(mp_int z)
+{
+ if (z == NULL)
+ return;
+
+ if (MP_DIGITS(z) != NULL) {
+ if (MP_DIGITS(z) != &(z->single))
+ s_free(MP_DIGITS(z));
+
+ MP_DIGITS(z) = NULL;
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_int_free(z) */
+
+void mp_int_free(mp_int z)
+{
+ NRCHECK(z != NULL);
+
+ mp_int_clear(z);
+ free(z); /* note: NOT s_free() */
+}
+
+/* }}} */
+
+/* {{{ mp_int_copy(a, c) */
+
+mp_result mp_int_copy(mp_int a, mp_int c)
+{
+ CHECK(a != NULL && c != NULL);
+
+ if (a != c) {
+ mp_size ua = MP_USED(a);
+ mp_digit *da, *dc;
+
+ if (!s_pad(c, ua))
+ return MP_MEMORY;
+
+ da = MP_DIGITS(a); dc = MP_DIGITS(c);
+ COPY(da, dc, ua);
+
+ MP_USED(c) = ua;
+ MP_SIGN(c) = MP_SIGN(a);
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_swap(a, c) */
+
+void mp_int_swap(mp_int a, mp_int c)
+{
+ if (a != c) {
+ mpz_t tmp = *a;
+
+ *a = *c;
+ *c = tmp;
+
+ if (MP_DIGITS(a) == &(c->single))
+ MP_DIGITS(a) = &(a->single);
+ if (MP_DIGITS(c) == &(a->single))
+ MP_DIGITS(c) = &(c->single);
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_int_zero(z) */
+
+void mp_int_zero(mp_int z)
+{
+ NRCHECK(z != NULL);
+
+ z->digits[0] = 0;
+ MP_USED(z) = 1;
+ MP_SIGN(z) = MP_ZPOS;
+}
+
+/* }}} */
+
+/* {{{ mp_int_abs(a, c) */
+
+mp_result mp_int_abs(mp_int a, mp_int c)
+{
+ mp_result res;
+
+ CHECK(a != NULL && c != NULL);
+
+ if ((res = mp_int_copy(a, c)) != MP_OK)
+ return res;
+
+ MP_SIGN(c) = MP_ZPOS;
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_neg(a, c) */
+
+mp_result mp_int_neg(mp_int a, mp_int c)
+{
+ mp_result res;
+
+ CHECK(a != NULL && c != NULL);
+
+ if ((res = mp_int_copy(a, c)) != MP_OK)
+ return res;
+
+ if (CMPZ(c) != 0)
+ MP_SIGN(c) = 1 - MP_SIGN(a);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_add(a, b, c) */
+
+mp_result mp_int_add(mp_int a, mp_int b, mp_int c)
+{
+ mp_size ua, ub, uc, max;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+
+ ua = MP_USED(a); ub = MP_USED(b); uc = MP_USED(c);
+ max = MAX(ua, ub);
+
+ if (MP_SIGN(a) == MP_SIGN(b)) {
+ /* Same sign -- add magnitudes, preserve sign of addends */
+ mp_digit carry;
+
+ if (!s_pad(c, max))
+ return MP_MEMORY;
+
+ carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+ uc = max;
+
+ if (carry) {
+ if (!s_pad(c, max + 1))
+ return MP_MEMORY;
+
+ c->digits[max] = carry;
+ ++uc;
+ }
+
+ MP_USED(c) = uc;
+ MP_SIGN(c) = MP_SIGN(a);
+
+ }
+ else {
+ /* Different signs -- subtract magnitudes, preserve sign of greater */
+ mp_int x, y;
+ int cmp = s_ucmp(a, b); /* magnitude comparision, sign ignored */
+
+ /* Set x to max(a, b), y to min(a, b) to simplify later code.
+ A special case yields zero for equal magnitudes.
+ */
+ if (cmp == 0) {
+ mp_int_zero(c);
+ return MP_OK;
+ }
+ else if (cmp < 0) {
+ x = b; y = a;
+ }
+ else {
+ x = a; y = b;
+ }
+
+ if (!s_pad(c, MP_USED(x)))
+ return MP_MEMORY;
+
+ /* Subtract smaller from larger */
+ s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
+ MP_USED(c) = MP_USED(x);
+ CLAMP(c);
+
+ /* Give result the sign of the larger */
+ MP_SIGN(c) = MP_SIGN(x);
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_add_value(a, value, c) */
+
+mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+
+ return mp_int_add(a, &vtmp, c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_sub(a, b, c) */
+
+mp_result mp_int_sub(mp_int a, mp_int b, mp_int c)
+{
+ mp_size ua, ub, uc, max;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+
+ ua = MP_USED(a); ub = MP_USED(b); uc = MP_USED(c);
+ max = MAX(ua, ub);
+
+ if (MP_SIGN(a) != MP_SIGN(b)) {
+ /* Different signs -- add magnitudes and keep sign of a */
+ mp_digit carry;
+
+ if (!s_pad(c, max))
+ return MP_MEMORY;
+
+ carry = s_uadd(MP_DIGITS(a), MP_DIGITS(b), MP_DIGITS(c), ua, ub);
+ uc = max;
+
+ if (carry) {
+ if (!s_pad(c, max + 1))
+ return MP_MEMORY;
+
+ c->digits[max] = carry;
+ ++uc;
+ }
+
+ MP_USED(c) = uc;
+ MP_SIGN(c) = MP_SIGN(a);
+
+ }
+ else {
+ /* Same signs -- subtract magnitudes */
+ mp_int x, y;
+ mp_sign osign;
+ int cmp = s_ucmp(a, b);
+
+ if (!s_pad(c, max))
+ return MP_MEMORY;
+
+ if (cmp >= 0) {
+ x = a; y = b; osign = MP_ZPOS;
+ }
+ else {
+ x = b; y = a; osign = MP_NEG;
+ }
+
+ if (MP_SIGN(a) == MP_NEG && cmp != 0)
+ osign = 1 - osign;
+
+ s_usub(MP_DIGITS(x), MP_DIGITS(y), MP_DIGITS(c), MP_USED(x), MP_USED(y));
+ MP_USED(c) = MP_USED(x);
+ CLAMP(c);
+
+ MP_SIGN(c) = osign;
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_sub_value(a, value, c) */
+
+mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+
+ return mp_int_sub(a, &vtmp, c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_mul(a, b, c) */
+
+mp_result mp_int_mul(mp_int a, mp_int b, mp_int c)
+{
+ mp_digit *out;
+ mp_size osize, ua, ub, p = 0;
+ mp_sign osign;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+
+ /* If either input is zero, we can shortcut multiplication */
+ if (mp_int_compare_zero(a) == 0 || mp_int_compare_zero(b) == 0) {
+ mp_int_zero(c);
+ return MP_OK;
+ }
+
+ /* Output is positive if inputs have same sign, otherwise negative */
+ osign = (MP_SIGN(a) == MP_SIGN(b)) ? MP_ZPOS : MP_NEG;
+
+ /* If the output is not identical to any of the inputs, we'll write the
+ results directly; otherwise, allocate a temporary space. */
+ ua = MP_USED(a); ub = MP_USED(b);
+ osize = MAX(ua, ub);
+ osize = 4 * ((osize + 1) / 2);
+
+ if (c == a || c == b) {
+ p = ROUND_PREC(osize);
+ p = MAX(p, default_precision);
+
+ if ((out = s_alloc(p)) == NULL)
+ return MP_MEMORY;
+ }
+ else {
+ if (!s_pad(c, osize))
+ return MP_MEMORY;
+
+ out = MP_DIGITS(c);
+ }
+ ZERO(out, osize);
+
+ if (!s_kmul(MP_DIGITS(a), MP_DIGITS(b), out, ua, ub))
+ return MP_MEMORY;
+
+ /* If we allocated a new buffer, get rid of whatever memory c was already
+ using, and fix up its fields to reflect that.
+ */
+ if (out != MP_DIGITS(c)) {
+ if ((void *) MP_DIGITS(c) != (void *) c)
+ s_free(MP_DIGITS(c));
+ MP_DIGITS(c) = out;
+ MP_ALLOC(c) = p;
+ }
+
+ MP_USED(c) = osize; /* might not be true, but we'll fix it ... */
+ CLAMP(c); /* ... right here */
+ MP_SIGN(c) = osign;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_mul_value(a, value, c) */
+
+mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+
+ return mp_int_mul(a, &vtmp, c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_mul_pow2(a, p2, c) */
+
+mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c)
+{
+ mp_result res;
+ CHECK(a != NULL && c != NULL && p2 >= 0);
+
+ if ((res = mp_int_copy(a, c)) != MP_OK)
+ return res;
+
+ if (s_qmul(c, (mp_size) p2))
+ return MP_OK;
+ else
+ return MP_MEMORY;
+}
+
+/* }}} */
+
+/* {{{ mp_int_sqr(a, c) */
+
+mp_result mp_int_sqr(mp_int a, mp_int c)
+{
+ mp_digit *out;
+ mp_size osize, p = 0;
+
+ CHECK(a != NULL && c != NULL);
+
+ /* Get a temporary buffer big enough to hold the result */
+ osize = (mp_size) 4 * ((MP_USED(a) + 1) / 2);
+ if (a == c) {
+ p = ROUND_PREC(osize);
+ p = MAX(p, default_precision);
+
+ if ((out = s_alloc(p)) == NULL)
+ return MP_MEMORY;
+ }
+ else {
+ if (!s_pad(c, osize))
+ return MP_MEMORY;
+
+ out = MP_DIGITS(c);
+ }
+ ZERO(out, osize);
+
+ s_ksqr(MP_DIGITS(a), out, MP_USED(a));
+
+ /* Get rid of whatever memory c was already using, and fix up its fields to
+ reflect the new digit array it's using
+ */
+ if (out != MP_DIGITS(c)) {
+ if ((void *) MP_DIGITS(c) != (void *) c)
+ s_free(MP_DIGITS(c));
+ MP_DIGITS(c) = out;
+ MP_ALLOC(c) = p;
+ }
+
+ MP_USED(c) = osize; /* might not be true, but we'll fix it ... */
+ CLAMP(c); /* ... right here */
+ MP_SIGN(c) = MP_ZPOS;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_div(a, b, q, r) */
+
+mp_result mp_int_div(mp_int a, mp_int b, mp_int q, mp_int r)
+{
+ int cmp, lg;
+ mp_result res = MP_OK;
+ mp_int qout, rout;
+ mp_sign sa = MP_SIGN(a), sb = MP_SIGN(b);
+ DECLARE_TEMP(2);
+
+ CHECK(a != NULL && b != NULL && q != r);
+
+ if (CMPZ(b) == 0)
+ return MP_UNDEF;
+ else if ((cmp = s_ucmp(a, b)) < 0) {
+ /* If |a| < |b|, no division is required:
+ q = 0, r = a
+ */
+ if (r && (res = mp_int_copy(a, r)) != MP_OK)
+ return res;
+
+ if (q)
+ mp_int_zero(q);
+
+ return MP_OK;
+ }
+ else if (cmp == 0) {
+ /* If |a| = |b|, no division is required:
+ q = 1 or -1, r = 0
+ */
+ if (r)
+ mp_int_zero(r);
+
+ if (q) {
+ mp_int_zero(q);
+ q->digits[0] = 1;
+
+ if (sa != sb)
+ MP_SIGN(q) = MP_NEG;
+ }
+
+ return MP_OK;
+ }
+
+ /* When |a| > |b|, real division is required. We need someplace to store
+ quotient and remainder, but q and r are allowed to be NULL or to overlap
+ with the inputs.
+ */
+ if ((lg = s_isp2(b)) < 0) {
+ if (q && b != q) {
+ if ((res = mp_int_copy(a, q)) != MP_OK)
+ goto CLEANUP;
+ else
+ qout = q;
+ }
+ else {
+ qout = LAST_TEMP();
+ SETUP(mp_int_init_copy(LAST_TEMP(), a));
+ }
+
+ if (r && a != r) {
+ if ((res = mp_int_copy(b, r)) != MP_OK)
+ goto CLEANUP;
+ else
+ rout = r;
+ }
+ else {
+ rout = LAST_TEMP();
+ SETUP(mp_int_init_copy(LAST_TEMP(), b));
+ }
+
+ if ((res = s_udiv_knuth(qout, rout)) != MP_OK) goto CLEANUP;
+ }
+ else {
+ if (q && (res = mp_int_copy(a, q)) != MP_OK) goto CLEANUP;
+ if (r && (res = mp_int_copy(a, r)) != MP_OK) goto CLEANUP;
+
+ if (q) s_qdiv(q, (mp_size) lg); qout = q;
+ if (r) s_qmod(r, (mp_size) lg); rout = r;
+ }
+
+ /* Recompute signs for output */
+ if (rout) {
+ MP_SIGN(rout) = sa;
+ if (CMPZ(rout) == 0)
+ MP_SIGN(rout) = MP_ZPOS;
+ }
+ if (qout) {
+ MP_SIGN(qout) = (sa == sb) ? MP_ZPOS : MP_NEG;
+ if (CMPZ(qout) == 0)
+ MP_SIGN(qout) = MP_ZPOS;
+ }
+
+ if (q && (res = mp_int_copy(qout, q)) != MP_OK) goto CLEANUP;
+ if (r && (res = mp_int_copy(rout, r)) != MP_OK) goto CLEANUP;
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_mod(a, m, c) */
+
+mp_result mp_int_mod(mp_int a, mp_int m, mp_int c)
+{
+ mp_result res;
+ mpz_t tmp;
+ mp_int out;
+
+ if (m == c) {
+ mp_int_init(&tmp);
+ out = &tmp;
+ }
+ else {
+ out = c;
+ }
+
+ if ((res = mp_int_div(a, m, NULL, out)) != MP_OK)
+ goto CLEANUP;
+
+ if (CMPZ(out) < 0)
+ res = mp_int_add(out, m, c);
+ else
+ res = mp_int_copy(out, c);
+
+ CLEANUP:
+ if (out != c)
+ mp_int_clear(&tmp);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_div_value(a, value, q, r) */
+
+mp_result mp_int_div_value(mp_int a, mp_small value, mp_int q, mp_small *r)
+{
+ mpz_t vtmp, rtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+ mp_result res;
+
+ mp_int_init(&rtmp);
+ s_fake(&vtmp, value, vbuf);
+
+ if ((res = mp_int_div(a, &vtmp, q, &rtmp)) != MP_OK)
+ goto CLEANUP;
+
+ if (r)
+ (void) mp_int_to_int(&rtmp, r); /* can't fail */
+
+ CLEANUP:
+ mp_int_clear(&rtmp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_div_pow2(a, p2, q, r) */
+
+mp_result mp_int_div_pow2(mp_int a, mp_small p2, mp_int q, mp_int r)
+{
+ mp_result res = MP_OK;
+
+ CHECK(a != NULL && p2 >= 0 && q != r);
+
+ if (q != NULL && (res = mp_int_copy(a, q)) == MP_OK)
+ s_qdiv(q, (mp_size) p2);
+
+ if (res == MP_OK && r != NULL && (res = mp_int_copy(a, r)) == MP_OK)
+ s_qmod(r, (mp_size) p2);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_expt(a, b, c) */
+
+mp_result mp_int_expt(mp_int a, mp_small b, mp_int c)
+{
+ mpz_t t;
+ mp_result res;
+ unsigned int v = abs(b);
+
+ CHECK(c != NULL);
+ if (b < 0)
+ return MP_RANGE;
+
+ if ((res = mp_int_init_copy(&t, a)) != MP_OK)
+ return res;
+
+ (void) mp_int_set_value(c, 1);
+ while (v != 0) {
+ if (v & 1) {
+ if ((res = mp_int_mul(c, &t, c)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ v >>= 1;
+ if (v == 0) break;
+
+ if ((res = mp_int_sqr(&t, &t)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ CLEANUP:
+ mp_int_clear(&t);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_expt_value(a, b, c) */
+
+mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c)
+{
+ mpz_t t;
+ mp_result res;
+ unsigned int v = abs(b);
+
+ CHECK(c != NULL);
+ if (b < 0)
+ return MP_RANGE;
+
+ if ((res = mp_int_init_value(&t, a)) != MP_OK)
+ return res;
+
+ (void) mp_int_set_value(c, 1);
+ while (v != 0) {
+ if (v & 1) {
+ if ((res = mp_int_mul(c, &t, c)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ v >>= 1;
+ if (v == 0) break;
+
+ if ((res = mp_int_sqr(&t, &t)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ CLEANUP:
+ mp_int_clear(&t);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_expt_full(a, b, c) */
+
+mp_result mp_int_expt_full(mp_int a, mp_int b, mp_int c)
+{
+ mpz_t t;
+ mp_result res;
+ unsigned ix, jx;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+ if (MP_SIGN(b) == MP_NEG)
+ return MP_RANGE;
+
+ if ((res = mp_int_init_copy(&t, a)) != MP_OK)
+ return res;
+
+ (void) mp_int_set_value(c, 1);
+ for (ix = 0; ix < MP_USED(b); ++ix) {
+ mp_digit d = b->digits[ix];
+
+ for (jx = 0; jx < MP_DIGIT_BIT; ++jx) {
+ if (d & 1) {
+ if ((res = mp_int_mul(c, &t, c)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ d >>= 1;
+ if (d == 0 && ix + 1 == MP_USED(b))
+ break;
+ if ((res = mp_int_sqr(&t, &t)) != MP_OK)
+ goto CLEANUP;
+ }
+ }
+
+ CLEANUP:
+ mp_int_clear(&t);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_compare(a, b) */
+
+int mp_int_compare(mp_int a, mp_int b)
+{
+ mp_sign sa;
+
+ CHECK(a != NULL && b != NULL);
+
+ sa = MP_SIGN(a);
+ if (sa == MP_SIGN(b)) {
+ int cmp = s_ucmp(a, b);
+
+ /* If they're both zero or positive, the normal comparison applies; if both
+ negative, the sense is reversed. */
+ if (sa == MP_ZPOS)
+ return cmp;
+ else
+ return -cmp;
+
+ }
+ else {
+ if (sa == MP_ZPOS)
+ return 1;
+ else
+ return -1;
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_int_compare_unsigned(a, b) */
+
+int mp_int_compare_unsigned(mp_int a, mp_int b)
+{
+ NRCHECK(a != NULL && b != NULL);
+
+ return s_ucmp(a, b);
+}
+
+/* }}} */
+
+/* {{{ mp_int_compare_zero(z) */
+
+int mp_int_compare_zero(mp_int z)
+{
+ NRCHECK(z != NULL);
+
+ if (MP_USED(z) == 1 && z->digits[0] == 0)
+ return 0;
+ else if (MP_SIGN(z) == MP_ZPOS)
+ return 1;
+ else
+ return -1;
+}
+
+/* }}} */
+
+/* {{{ mp_int_compare_value(z, value) */
+
+int mp_int_compare_value(mp_int z, mp_small value)
+{
+ mp_sign vsign = (value < 0) ? MP_NEG : MP_ZPOS;
+ int cmp;
+
+ CHECK(z != NULL);
+
+ if (vsign == MP_SIGN(z)) {
+ cmp = s_vcmp(z, value);
+
+ return (vsign == MP_ZPOS) ? cmp : -cmp;
+ }
+ else {
+ return (value < 0) ? 1 : -1;
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_int_compare_uvalue(z, uv) */
+
+int mp_int_compare_uvalue(mp_int z, mp_usmall uv)
+{
+ CHECK(z != NULL);
+
+ if (MP_SIGN(z) == MP_NEG)
+ return -1;
+ else
+ return s_uvcmp(z, uv);
+}
+
+/* }}} */
+
+/* {{{ mp_int_exptmod(a, b, m, c) */
+
+mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m, mp_int c)
+{
+ mp_result res;
+ mp_size um;
+ mp_int s;
+ DECLARE_TEMP(3);
+
+ CHECK(a != NULL && b != NULL && c != NULL && m != NULL);
+
+ /* Zero moduli and negative exponents are not considered. */
+ if (CMPZ(m) == 0)
+ return MP_UNDEF;
+ if (CMPZ(b) < 0)
+ return MP_RANGE;
+
+ um = MP_USED(m);
+ SETUP(mp_int_init_size(TEMP(0), 2 * um));
+ SETUP(mp_int_init_size(TEMP(1), 2 * um));
+
+ if (c == b || c == m) {
+ SETUP(mp_int_init_size(TEMP(2), 2 * um));
+ s = TEMP(2);
+ }
+ else {
+ s = c;
+ }
+
+ if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK) goto CLEANUP;
+
+ if ((res = s_brmu(TEMP(1), m)) != MP_OK) goto CLEANUP;
+
+ if ((res = s_embar(TEMP(0), b, m, TEMP(1), s)) != MP_OK)
+ goto CLEANUP;
+
+ res = mp_int_copy(s, c);
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_exptmod_evalue(a, value, m, c) */
+
+mp_result mp_int_exptmod_evalue(mp_int a, mp_small value, mp_int m, mp_int c)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+
+ return mp_int_exptmod(a, &vtmp, m, c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_exptmod_bvalue(v, b, m, c) */
+
+mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b,
+ mp_int m, mp_int c)
+{
+ mpz_t vtmp;
+ mp_digit vbuf[MP_VALUE_DIGITS(value)];
+
+ s_fake(&vtmp, value, vbuf);
+
+ return mp_int_exptmod(&vtmp, b, m, c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_exptmod_known(a, b, m, mu, c) */
+
+mp_result mp_int_exptmod_known(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
+{
+ mp_result res;
+ mp_size um;
+ mp_int s;
+ DECLARE_TEMP(2);
+
+ CHECK(a && b && m && c);
+
+ /* Zero moduli and negative exponents are not considered. */
+ if (CMPZ(m) == 0)
+ return MP_UNDEF;
+ if (CMPZ(b) < 0)
+ return MP_RANGE;
+
+ um = MP_USED(m);
+ SETUP(mp_int_init_size(TEMP(0), 2 * um));
+
+ if (c == b || c == m) {
+ SETUP(mp_int_init_size(TEMP(1), 2 * um));
+ s = TEMP(1);
+ }
+ else {
+ s = c;
+ }
+
+ if ((res = mp_int_mod(a, m, TEMP(0))) != MP_OK) goto CLEANUP;
+
+ if ((res = s_embar(TEMP(0), b, m, mu, s)) != MP_OK)
+ goto CLEANUP;
+
+ res = mp_int_copy(s, c);
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_redux_const(m, c) */
+
+mp_result mp_int_redux_const(mp_int m, mp_int c)
+{
+ CHECK(m != NULL && c != NULL && m != c);
+
+ return s_brmu(c, m);
+}
+
+/* }}} */
+
+/* {{{ mp_int_invmod(a, m, c) */
+
+mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c)
+{
+ mp_result res;
+ mp_sign sa;
+ DECLARE_TEMP(2);
+
+ CHECK(a != NULL && m != NULL && c != NULL);
+
+ if (CMPZ(a) == 0 || CMPZ(m) <= 0)
+ return MP_RANGE;
+
+ sa = MP_SIGN(a); /* need this for the result later */
+
+ for (last__ = 0; last__ < 2; ++last__)
+ mp_int_init(LAST_TEMP());
+
+ if ((res = mp_int_egcd(a, m, TEMP(0), TEMP(1), NULL)) != MP_OK)
+ goto CLEANUP;
+
+ if (mp_int_compare_value(TEMP(0), 1) != 0) {
+ res = MP_UNDEF;
+ goto CLEANUP;
+ }
+
+ /* It is first necessary to constrain the value to the proper range */
+ if ((res = mp_int_mod(TEMP(1), m, TEMP(1))) != MP_OK)
+ goto CLEANUP;
+
+ /* Now, if 'a' was originally negative, the value we have is actually the
+ magnitude of the negative representative; to get the positive value we
+ have to subtract from the modulus. Otherwise, the value is okay as it
+ stands.
+ */
+ if (sa == MP_NEG)
+ res = mp_int_sub(m, TEMP(1), c);
+ else
+ res = mp_int_copy(TEMP(1), c);
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_gcd(a, b, c) */
+
+/* Binary GCD algorithm due to Josef Stein, 1961 */
+mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c)
+{
+ int ca, cb, k = 0;
+ mpz_t u, v, t;
+ mp_result res;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+
+ ca = CMPZ(a);
+ cb = CMPZ(b);
+ if (ca == 0 && cb == 0)
+ return MP_UNDEF;
+ else if (ca == 0)
+ return mp_int_abs(b, c);
+ else if (cb == 0)
+ return mp_int_abs(a, c);
+
+ mp_int_init(&t);
+ if ((res = mp_int_init_copy(&u, a)) != MP_OK)
+ goto U;
+ if ((res = mp_int_init_copy(&v, b)) != MP_OK)
+ goto V;
+
+ MP_SIGN(&u) = MP_ZPOS; MP_SIGN(&v) = MP_ZPOS;
+
+ { /* Divide out common factors of 2 from u and v */
+ int div2_u = s_dp2k(&u), div2_v = s_dp2k(&v);
+
+ k = MIN(div2_u, div2_v);
+ s_qdiv(&u, (mp_size) k);
+ s_qdiv(&v, (mp_size) k);
+ }
+
+ if (mp_int_is_odd(&u)) {
+ if ((res = mp_int_neg(&v, &t)) != MP_OK)
+ goto CLEANUP;
+ }
+ else {
+ if ((res = mp_int_copy(&u, &t)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ for (;;) {
+ s_qdiv(&t, s_dp2k(&t));
+
+ if (CMPZ(&t) > 0) {
+ if ((res = mp_int_copy(&t, &u)) != MP_OK)
+ goto CLEANUP;
+ }
+ else {
+ if ((res = mp_int_neg(&t, &v)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ if ((res = mp_int_sub(&u, &v, &t)) != MP_OK)
+ goto CLEANUP;
+
+ if (CMPZ(&t) == 0)
+ break;
+ }
+
+ if ((res = mp_int_abs(&u, c)) != MP_OK)
+ goto CLEANUP;
+ if (!s_qmul(c, (mp_size) k))
+ res = MP_MEMORY;
+
+ CLEANUP:
+ mp_int_clear(&v);
+ V: mp_int_clear(&u);
+ U: mp_int_clear(&t);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_egcd(a, b, c, x, y) */
+
+/* This is the binary GCD algorithm again, but this time we keep track of the
+ elementary matrix operations as we go, so we can get values x and y
+ satisfying c = ax + by.
+ */
+mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c,
+ mp_int x, mp_int y)
+{
+ int k, ca, cb;
+ mp_result res;
+ DECLARE_TEMP(8);
+
+ CHECK(a != NULL && b != NULL && c != NULL &&
+ (x != NULL || y != NULL));
+
+ ca = CMPZ(a);
+ cb = CMPZ(b);
+ if (ca == 0 && cb == 0)
+ return MP_UNDEF;
+ else if (ca == 0) {
+ if ((res = mp_int_abs(b, c)) != MP_OK) return res;
+ mp_int_zero(x); (void) mp_int_set_value(y, 1); return MP_OK;
+ }
+ else if (cb == 0) {
+ if ((res = mp_int_abs(a, c)) != MP_OK) return res;
+ (void) mp_int_set_value(x, 1); mp_int_zero(y); return MP_OK;
+ }
+
+ /* Initialize temporaries:
+ A:0, B:1, C:2, D:3, u:4, v:5, ou:6, ov:7 */
+ for (last__ = 0; last__ < 4; ++last__)
+ mp_int_init(LAST_TEMP());
+ TEMP(0)->digits[0] = 1;
+ TEMP(3)->digits[0] = 1;
+
+ SETUP(mp_int_init_copy(TEMP(4), a));
+ SETUP(mp_int_init_copy(TEMP(5), b));
+
+ /* We will work with absolute values here */
+ MP_SIGN(TEMP(4)) = MP_ZPOS;
+ MP_SIGN(TEMP(5)) = MP_ZPOS;
+
+ { /* Divide out common factors of 2 from u and v */
+ int div2_u = s_dp2k(TEMP(4)), div2_v = s_dp2k(TEMP(5));
+
+ k = MIN(div2_u, div2_v);
+ s_qdiv(TEMP(4), k);
+ s_qdiv(TEMP(5), k);
+ }
+
+ SETUP(mp_int_init_copy(TEMP(6), TEMP(4)));
+ SETUP(mp_int_init_copy(TEMP(7), TEMP(5)));
+
+ for (;;) {
+ while (mp_int_is_even(TEMP(4))) {
+ s_qdiv(TEMP(4), 1);
+
+ if (mp_int_is_odd(TEMP(0)) || mp_int_is_odd(TEMP(1))) {
+ if ((res = mp_int_add(TEMP(0), TEMP(7), TEMP(0))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(1), TEMP(6), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+ }
+
+ s_qdiv(TEMP(0), 1);
+ s_qdiv(TEMP(1), 1);
+ }
+
+ while (mp_int_is_even(TEMP(5))) {
+ s_qdiv(TEMP(5), 1);
+
+ if (mp_int_is_odd(TEMP(2)) || mp_int_is_odd(TEMP(3))) {
+ if ((res = mp_int_add(TEMP(2), TEMP(7), TEMP(2))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(3), TEMP(6), TEMP(3))) != MP_OK)
+ goto CLEANUP;
+ }
+
+ s_qdiv(TEMP(2), 1);
+ s_qdiv(TEMP(3), 1);
+ }
+
+ if (mp_int_compare(TEMP(4), TEMP(5)) >= 0) {
+ if ((res = mp_int_sub(TEMP(4), TEMP(5), TEMP(4))) != MP_OK) goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(0), TEMP(2), TEMP(0))) != MP_OK) goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(1), TEMP(3), TEMP(1))) != MP_OK) goto CLEANUP;
+ }
+ else {
+ if ((res = mp_int_sub(TEMP(5), TEMP(4), TEMP(5))) != MP_OK) goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK) goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(3), TEMP(1), TEMP(3))) != MP_OK) goto CLEANUP;
+ }
+
+ if (CMPZ(TEMP(4)) == 0) {
+ if (x && (res = mp_int_copy(TEMP(2), x)) != MP_OK) goto CLEANUP;
+ if (y && (res = mp_int_copy(TEMP(3), y)) != MP_OK) goto CLEANUP;
+ if (c) {
+ if (!s_qmul(TEMP(5), k)) {
+ res = MP_MEMORY;
+ goto CLEANUP;
+ }
+
+ res = mp_int_copy(TEMP(5), c);
+ }
+
+ break;
+ }
+ }
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_lcm(a, b, c) */
+
+mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c)
+{
+ mpz_t lcm;
+ mp_result res;
+
+ CHECK(a != NULL && b != NULL && c != NULL);
+
+ /* Since a * b = gcd(a, b) * lcm(a, b), we can compute
+ lcm(a, b) = (a / gcd(a, b)) * b.
+
+ This formulation insures everything works even if the input
+ variables share space.
+ */
+ if ((res = mp_int_init(&lcm)) != MP_OK)
+ return res;
+ if ((res = mp_int_gcd(a, b, &lcm)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_div(a, &lcm, &lcm, NULL)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_mul(&lcm, b, &lcm)) != MP_OK)
+ goto CLEANUP;
+
+ res = mp_int_copy(&lcm, c);
+
+ CLEANUP:
+ mp_int_clear(&lcm);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_divisible_value(a, v) */
+
+int mp_int_divisible_value(mp_int a, mp_small v)
+{
+ mp_small rem = 0;
+
+ if (mp_int_div_value(a, v, NULL, &rem) != MP_OK)
+ return 0;
+
+ return rem == 0;
+}
+
+/* }}} */
+
+/* {{{ mp_int_is_pow2(z) */
+
+int mp_int_is_pow2(mp_int z)
+{
+ CHECK(z != NULL);
+
+ return s_isp2(z);
+}
+
+/* }}} */
+
+/* {{{ mp_int_root(a, b, c) */
+
+/* Implementation of Newton's root finding method, based loosely on a patch
+ contributed by Hal Finkel <half@halssoftware.com>
+ modified by M. J. Fromberger.
+ */
+mp_result mp_int_root(mp_int a, mp_small b, mp_int c)
+{
+ mp_result res = MP_OK;
+ int flips = 0;
+ DECLARE_TEMP(5);
+
+ CHECK(a != NULL && c != NULL && b > 0);
+
+ if (b == 1) {
+ return mp_int_copy(a, c);
+ }
+ if (MP_SIGN(a) == MP_NEG) {
+ if (b % 2 == 0)
+ return MP_UNDEF; /* root does not exist for negative a with even b */
+ else
+ flips = 1;
+ }
+
+ SETUP(mp_int_init_copy(LAST_TEMP(), a));
+ SETUP(mp_int_init_copy(LAST_TEMP(), a));
+ SETUP(mp_int_init(LAST_TEMP()));
+ SETUP(mp_int_init(LAST_TEMP()));
+ SETUP(mp_int_init(LAST_TEMP()));
+
+ (void) mp_int_abs(TEMP(0), TEMP(0));
+ (void) mp_int_abs(TEMP(1), TEMP(1));
+
+ for (;;) {
+ if ((res = mp_int_expt(TEMP(1), b, TEMP(2))) != MP_OK)
+ goto CLEANUP;
+
+ if (mp_int_compare_unsigned(TEMP(2), TEMP(0)) <= 0)
+ break;
+
+ if ((res = mp_int_sub(TEMP(2), TEMP(0), TEMP(2))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_expt(TEMP(1), b - 1, TEMP(3))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_mul_value(TEMP(3), b, TEMP(3))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_div(TEMP(2), TEMP(3), TEMP(4), NULL)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_sub(TEMP(1), TEMP(4), TEMP(4))) != MP_OK)
+ goto CLEANUP;
+
+ if (mp_int_compare_unsigned(TEMP(1), TEMP(4)) == 0) {
+ if ((res = mp_int_sub_value(TEMP(4), 1, TEMP(4))) != MP_OK)
+ goto CLEANUP;
+ }
+ if ((res = mp_int_copy(TEMP(4), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+ }
+
+ if ((res = mp_int_copy(TEMP(1), c)) != MP_OK)
+ goto CLEANUP;
+
+ /* If the original value of a was negative, flip the output sign. */
+ if (flips)
+ (void) mp_int_neg(c, c); /* cannot fail */
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_to_int(z, *out) */
+
+mp_result mp_int_to_int(mp_int z, mp_small *out)
+{
+ mp_usmall uv = 0;
+ mp_size uz;
+ mp_digit *dz;
+ mp_sign sz;
+
+ CHECK(z != NULL);
+
+ /* Make sure the value is representable as a small integer */
+ sz = MP_SIGN(z);
+ if ((sz == MP_ZPOS && mp_int_compare_value(z, MP_SMALL_MAX) > 0) ||
+ mp_int_compare_value(z, MP_SMALL_MIN) < 0)
+ return MP_RANGE;
+
+ uz = MP_USED(z);
+ dz = MP_DIGITS(z) + uz - 1;
+
+ while (uz > 0) {
+ uv <<= MP_DIGIT_BIT/2;
+ uv = (uv << (MP_DIGIT_BIT/2)) | *dz--;
+ --uz;
+ }
+
+ if (out)
+ *out = (sz == MP_NEG) ? -(mp_small)uv : (mp_small)uv;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_to_uint(z, *out) */
+
+mp_result mp_int_to_uint(mp_int z, mp_usmall *out)
+{
+ mp_usmall uv = 0;
+ mp_size uz;
+ mp_digit *dz;
+ mp_sign sz;
+
+ CHECK(z != NULL);
+
+ /* Make sure the value is representable as an unsigned small integer */
+ sz = MP_SIGN(z);
+ if (sz == MP_NEG || mp_int_compare_uvalue(z, MP_USMALL_MAX) > 0)
+ return MP_RANGE;
+
+ uz = MP_USED(z);
+ dz = MP_DIGITS(z) + uz - 1;
+
+ while (uz > 0) {
+ uv <<= MP_DIGIT_BIT/2;
+ uv = (uv << (MP_DIGIT_BIT/2)) | *dz--;
+ --uz;
+ }
+
+ if (out)
+ *out = uv;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_to_string(z, radix, str, limit) */
+
+mp_result mp_int_to_string(mp_int z, mp_size radix,
+ char *str, int limit)
+{
+ mp_result res;
+ int cmp = 0;
+
+ CHECK(z != NULL && str != NULL && limit >= 2);
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+ return MP_RANGE;
+
+ if (CMPZ(z) == 0) {
+ *str++ = s_val2ch(0, 1);
+ }
+ else {
+ mpz_t tmp;
+ char *h, *t;
+
+ if ((res = mp_int_init_copy(&tmp, z)) != MP_OK)
+ return res;
+
+ if (MP_SIGN(z) == MP_NEG) {
+ *str++ = '-';
+ --limit;
+ }
+ h = str;
+
+ /* Generate digits in reverse order until finished or limit reached */
+ for (/* */; limit > 0; --limit) {
+ mp_digit d;
+
+ if ((cmp = CMPZ(&tmp)) == 0)
+ break;
+
+ d = s_ddiv(&tmp, (mp_digit)radix);
+ *str++ = s_val2ch(d, 1);
+ }
+ t = str - 1;
+
+ /* Put digits back in correct output order */
+ while (h < t) {
+ char tc = *h;
+ *h++ = *t;
+ *t-- = tc;
+ }
+
+ mp_int_clear(&tmp);
+ }
+
+ *str = '\0';
+ if (cmp == 0)
+ return MP_OK;
+ else
+ return MP_TRUNC;
+}
+
+/* }}} */
+
+/* {{{ mp_int_string_len(z, radix) */
+
+mp_result mp_int_string_len(mp_int z, mp_size radix)
+{
+ int len;
+
+ CHECK(z != NULL);
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+ return MP_RANGE;
+
+ len = s_outlen(z, radix) + 1; /* for terminator */
+
+ /* Allow for sign marker on negatives */
+ if (MP_SIGN(z) == MP_NEG)
+ len += 1;
+
+ return len;
+}
+
+/* }}} */
+
+/* {{{ mp_int_read_string(z, radix, *str) */
+
+/* Read zero-terminated string into z */
+mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str)
+{
+ return mp_int_read_cstring(z, radix, str, NULL);
+}
+
+/* }}} */
+
+/* {{{ mp_int_read_cstring(z, radix, *str, **end) */
+
+mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str, char **end)
+{
+ int ch;
+
+ CHECK(z != NULL && str != NULL);
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+ return MP_RANGE;
+
+ /* Skip leading whitespace */
+ while (isspace((int)*str))
+ ++str;
+
+ /* Handle leading sign tag (+/-, positive default) */
+ switch (*str) {
+ case '-':
+ MP_SIGN(z) = MP_NEG;
+ ++str;
+ break;
+ case '+':
+ ++str; /* fallthrough */
+ default:
+ MP_SIGN(z) = MP_ZPOS;
+ break;
+ }
+
+ /* Skip leading zeroes */
+ while ((ch = s_ch2val(*str, radix)) == 0)
+ ++str;
+
+ /* Make sure there is enough space for the value */
+ if (!s_pad(z, s_inlen(strlen(str), radix)))
+ return MP_MEMORY;
+
+ MP_USED(z) = 1; z->digits[0] = 0;
+
+ while (*str != '\0' && ((ch = s_ch2val(*str, radix)) >= 0)) {
+ s_dmul(z, (mp_digit)radix);
+ s_dadd(z, (mp_digit)ch);
+ ++str;
+ }
+
+ CLAMP(z);
+
+ /* Override sign for zero, even if negative specified. */
+ if (CMPZ(z) == 0)
+ MP_SIGN(z) = MP_ZPOS;
+
+ if (end != NULL)
+ *end = (char *)str;
+
+ /* Return a truncation error if the string has unprocessed characters
+ remaining, so the caller can tell if the whole string was done */
+ if (*str != '\0')
+ return MP_TRUNC;
+ else
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_count_bits(z) */
+
+mp_result mp_int_count_bits(mp_int z)
+{
+ mp_size nbits = 0, uz;
+ mp_digit d;
+
+ CHECK(z != NULL);
+
+ uz = MP_USED(z);
+ if (uz == 1 && z->digits[0] == 0)
+ return 1;
+
+ --uz;
+ nbits = uz * MP_DIGIT_BIT;
+ d = z->digits[uz];
+
+ while (d != 0) {
+ d >>= 1;
+ ++nbits;
+ }
+
+ return nbits;
+}
+
+/* }}} */
+
+/* {{{ mp_int_to_binary(z, buf, limit) */
+
+mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit)
+{
+ static const int PAD_FOR_2C = 1;
+
+ mp_result res;
+ int limpos = limit;
+
+ CHECK(z != NULL && buf != NULL);
+
+ res = s_tobin(z, buf, &limpos, PAD_FOR_2C);
+
+ if (MP_SIGN(z) == MP_NEG)
+ s_2comp(buf, limpos);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_int_read_binary(z, buf, len) */
+
+mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len)
+{
+ mp_size need, i;
+ unsigned char *tmp;
+ mp_digit *dz;
+
+ CHECK(z != NULL && buf != NULL && len > 0);
+
+ /* Figure out how many digits are needed to represent this value */
+ need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+ if (!s_pad(z, need))
+ return MP_MEMORY;
+
+ mp_int_zero(z);
+
+ /* If the high-order bit is set, take the 2's complement before reading the
+ value (it will be restored afterward) */
+ if (buf[0] >> (CHAR_BIT - 1)) {
+ MP_SIGN(z) = MP_NEG;
+ s_2comp(buf, len);
+ }
+
+ dz = MP_DIGITS(z);
+ for (tmp = buf, i = len; i > 0; --i, ++tmp) {
+ s_qmul(z, (mp_size) CHAR_BIT);
+ *dz |= *tmp;
+ }
+
+ /* Restore 2's complement if we took it before */
+ if (MP_SIGN(z) == MP_NEG)
+ s_2comp(buf, len);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_binary_len(z) */
+
+mp_result mp_int_binary_len(mp_int z)
+{
+ mp_result res = mp_int_count_bits(z);
+ int bytes = mp_int_unsigned_len(z);
+
+ if (res <= 0)
+ return res;
+
+ bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+
+ /* If the highest-order bit falls exactly on a byte boundary, we need to pad
+ with an extra byte so that the sign will be read correctly when reading it
+ back in. */
+ if (bytes * CHAR_BIT == res)
+ ++bytes;
+
+ return bytes;
+}
+
+/* }}} */
+
+/* {{{ mp_int_to_unsigned(z, buf, limit) */
+
+mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit)
+{
+ static const int NO_PADDING = 0;
+
+ CHECK(z != NULL && buf != NULL);
+
+ return s_tobin(z, buf, &limit, NO_PADDING);
+}
+
+/* }}} */
+
+/* {{{ mp_int_read_unsigned(z, buf, len) */
+
+mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len)
+{
+ mp_size need, i;
+ unsigned char *tmp;
+
+ CHECK(z != NULL && buf != NULL && len > 0);
+
+ /* Figure out how many digits are needed to represent this value */
+ need = ((len * CHAR_BIT) + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT;
+ if (!s_pad(z, need))
+ return MP_MEMORY;
+
+ mp_int_zero(z);
+
+ for (tmp = buf, i = len; i > 0; --i, ++tmp) {
+ (void) s_qmul(z, CHAR_BIT);
+ *MP_DIGITS(z) |= *tmp;
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_int_unsigned_len(z) */
+
+mp_result mp_int_unsigned_len(mp_int z)
+{
+ mp_result res = mp_int_count_bits(z);
+ int bytes;
+
+ if (res <= 0)
+ return res;
+
+ bytes = (res + (CHAR_BIT - 1)) / CHAR_BIT;
+
+ return bytes;
+}
+
+/* }}} */
+
+/* {{{ mp_error_string(res) */
+
+const char *mp_error_string(mp_result res)
+{
+ int ix;
+ if (res > 0)
+ return s_unknown_err;
+
+ res = -res;
+ for (ix = 0; ix < res && s_error_msg[ix] != NULL; ++ix)
+ ;
+
+ if (s_error_msg[ix] != NULL)
+ return s_error_msg[ix];
+ else
+ return s_unknown_err;
+}
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* Private functions for internal use. These make assumptions. */
+
+/* {{{ s_alloc(num) */
+
+STATIC mp_digit *s_alloc(mp_size num)
+{
+ mp_digit *out = malloc(num * sizeof(mp_digit));
+
+ assert(out != NULL); /* for debugging */
+#if DEBUG > 1
+ {
+ mp_digit v = (mp_digit) 0xdeadbeef;
+ int ix;
+
+ for (ix = 0; ix < num; ++ix)
+ out[ix] = v;
+ }
+#endif
+
+ return out;
+}
+
+/* }}} */
+
+/* {{{ s_realloc(old, osize, nsize) */
+
+STATIC mp_digit *s_realloc(mp_digit *old, mp_size osize, mp_size nsize)
+{
+#if DEBUG > 1
+ mp_digit *new = s_alloc(nsize);
+ int ix;
+
+ for (ix = 0; ix < nsize; ++ix)
+ new[ix] = (mp_digit) 0xdeadbeef;
+
+ memcpy(new, old, osize * sizeof(mp_digit));
+#else
+ mp_digit *new = realloc(old, nsize * sizeof(mp_digit));
+
+ assert(new != NULL); /* for debugging */
+#endif
+ return new;
+}
+
+/* }}} */
+
+/* {{{ s_free(ptr) */
+
+STATIC void s_free(void *ptr)
+{
+ free(ptr);
+}
+
+/* }}} */
+
+/* {{{ s_pad(z, min) */
+
+STATIC int s_pad(mp_int z, mp_size min)
+{
+ if (MP_ALLOC(z) < min) {
+ mp_size nsize = ROUND_PREC(min);
+ mp_digit *tmp;
+
+ if ((void *)z->digits == (void *)z) {
+ if ((tmp = s_alloc(nsize)) == NULL)
+ return 0;
+
+ COPY(MP_DIGITS(z), tmp, MP_USED(z));
+ }
+ else if ((tmp = s_realloc(MP_DIGITS(z), MP_ALLOC(z), nsize)) == NULL)
+ return 0;
+
+ MP_DIGITS(z) = tmp;
+ MP_ALLOC(z) = nsize;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_fake(z, value, vbuf[]) */
+
+/* Note: This will not work correctly when value == MP_SMALL_MIN */
+STATIC void s_fake(mp_int z, mp_small value, mp_digit vbuf[])
+{
+ mp_usmall uv = (mp_usmall) (value < 0) ? -value : value;
+ s_ufake(z, uv, vbuf);
+ if (value < 0)
+ z->sign = MP_NEG;
+}
+
+/* }}} */
+
+/* {{{ s_ufake(z, value, vbuf[]) */
+
+STATIC void s_ufake(mp_int z, mp_usmall value, mp_digit vbuf[])
+{
+ mp_size ndig = (mp_size) s_uvpack(value, vbuf);
+
+ z->used = ndig;
+ z->alloc = MP_VALUE_DIGITS(value);
+ z->sign = MP_ZPOS;
+ z->digits = vbuf;
+}
+
+/* }}} */
+
+/* {{{ s_cdig(da, db, len) */
+
+STATIC int s_cdig(mp_digit *da, mp_digit *db, mp_size len)
+{
+ mp_digit *dat = da + len - 1, *dbt = db + len - 1;
+
+ for (/* */; len != 0; --len, --dat, --dbt) {
+ if (*dat > *dbt)
+ return 1;
+ else if (*dat < *dbt)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* }}} */
+
+/* {{{ s_uvpack(uv, t[]) */
+
+STATIC int s_uvpack(mp_usmall uv, mp_digit t[])
+{
+ int ndig = 0;
+
+ if (uv == 0)
+ t[ndig++] = 0;
+ else {
+ while (uv != 0) {
+ t[ndig++] = (mp_digit) uv;
+ uv >>= MP_DIGIT_BIT/2;
+ uv >>= MP_DIGIT_BIT/2;
+ }
+ }
+
+ return ndig;
+}
+
+/* }}} */
+
+/* {{{ s_ucmp(a, b) */
+
+STATIC int s_ucmp(mp_int a, mp_int b)
+{
+ mp_size ua = MP_USED(a), ub = MP_USED(b);
+
+ if (ua > ub)
+ return 1;
+ else if (ub > ua)
+ return -1;
+ else
+ return s_cdig(MP_DIGITS(a), MP_DIGITS(b), ua);
+}
+
+/* }}} */
+
+/* {{{ s_vcmp(a, v) */
+
+STATIC int s_vcmp(mp_int a, mp_small v)
+{
+ mp_usmall uv = (mp_usmall) (v < 0) ? -v : v;
+ return s_uvcmp(a, uv);
+}
+
+/* }}} */
+
+/* {{{ s_uvcmp(a, v) */
+
+STATIC int s_uvcmp(mp_int a, mp_usmall uv)
+{
+ mpz_t vtmp;
+ mp_digit vdig[MP_VALUE_DIGITS(uv)];
+
+ s_ufake(&vtmp, uv, vdig);
+ return s_ucmp(a, &vtmp);
+}
+
+/* }}} */
+
+/* {{{ s_uadd(da, db, dc, size_a, size_b) */
+
+STATIC mp_digit s_uadd(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b)
+{
+ mp_size pos;
+ mp_word w = 0;
+
+ /* Insure that da is the longer of the two to simplify later code */
+ if (size_b > size_a) {
+ SWAP(mp_digit *, da, db);
+ SWAP(mp_size, size_a, size_b);
+ }
+
+ /* Add corresponding digits until the shorter number runs out */
+ for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc) {
+ w = w + (mp_word) *da + (mp_word) *db;
+ *dc = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ }
+
+ /* Propagate carries as far as necessary */
+ for (/* */; pos < size_a; ++pos, ++da, ++dc) {
+ w = w + *da;
+
+ *dc = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ }
+
+ /* Return carry out */
+ return (mp_digit)w;
+}
+
+/* }}} */
+
+/* {{{ s_usub(da, db, dc, size_a, size_b) */
+
+STATIC void s_usub(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b)
+{
+ mp_size pos;
+ mp_word w = 0;
+
+ /* We assume that |a| >= |b| so this should definitely hold */
+ assert(size_a >= size_b);
+
+ /* Subtract corresponding digits and propagate borrow */
+ for (pos = 0; pos < size_b; ++pos, ++da, ++db, ++dc) {
+ w = ((mp_word)MP_DIGIT_MAX + 1 + /* MP_RADIX */
+ (mp_word)*da) - w - (mp_word)*db;
+
+ *dc = LOWER_HALF(w);
+ w = (UPPER_HALF(w) == 0);
+ }
+
+ /* Finish the subtraction for remaining upper digits of da */
+ for (/* */; pos < size_a; ++pos, ++da, ++dc) {
+ w = ((mp_word)MP_DIGIT_MAX + 1 + /* MP_RADIX */
+ (mp_word)*da) - w;
+
+ *dc = LOWER_HALF(w);
+ w = (UPPER_HALF(w) == 0);
+ }
+
+ /* If there is a borrow out at the end, it violates the precondition */
+ assert(w == 0);
+}
+
+/* }}} */
+
+/* {{{ s_kmul(da, db, dc, size_a, size_b) */
+
+STATIC int s_kmul(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b)
+{
+ mp_size bot_size;
+
+ /* Make sure b is the smaller of the two input values */
+ if (size_b > size_a) {
+ SWAP(mp_digit *, da, db);
+ SWAP(mp_size, size_a, size_b);
+ }
+
+ /* Insure that the bottom is the larger half in an odd-length split; the code
+ below relies on this being true.
+ */
+ bot_size = (size_a + 1) / 2;
+
+ /* If the values are big enough to bother with recursion, use the Karatsuba
+ algorithm to compute the product; otherwise use the normal multiplication
+ algorithm
+ */
+ if (multiply_threshold &&
+ size_a >= multiply_threshold &&
+ size_b > bot_size) {
+
+ mp_digit *t1, *t2, *t3, carry;
+
+ mp_digit *a_top = da + bot_size;
+ mp_digit *b_top = db + bot_size;
+
+ mp_size at_size = size_a - bot_size;
+ mp_size bt_size = size_b - bot_size;
+ mp_size buf_size = 2 * bot_size;
+
+ /* Do a single allocation for all three temporary buffers needed; each
+ buffer must be big enough to hold the product of two bottom halves, and
+ one buffer needs space for the completed product; twice the space is
+ plenty.
+ */
+ if ((t1 = s_alloc(4 * buf_size)) == NULL) return 0;
+ t2 = t1 + buf_size;
+ t3 = t2 + buf_size;
+ ZERO(t1, 4 * buf_size);
+
+ /* t1 and t2 are initially used as temporaries to compute the inner product
+ (a1 + a0)(b1 + b0) = a1b1 + a1b0 + a0b1 + a0b0
+ */
+ carry = s_uadd(da, a_top, t1, bot_size, at_size); /* t1 = a1 + a0 */
+ t1[bot_size] = carry;
+
+ carry = s_uadd(db, b_top, t2, bot_size, bt_size); /* t2 = b1 + b0 */
+ t2[bot_size] = carry;
+
+ (void) s_kmul(t1, t2, t3, bot_size + 1, bot_size + 1); /* t3 = t1 * t2 */
+
+ /* Now we'll get t1 = a0b0 and t2 = a1b1, and subtract them out so that
+ we're left with only the pieces we want: t3 = a1b0 + a0b1
+ */
+ ZERO(t1, buf_size);
+ ZERO(t2, buf_size);
+ (void) s_kmul(da, db, t1, bot_size, bot_size); /* t1 = a0 * b0 */
+ (void) s_kmul(a_top, b_top, t2, at_size, bt_size); /* t2 = a1 * b1 */
+
+ /* Subtract out t1 and t2 to get the inner product */
+ s_usub(t3, t1, t3, buf_size + 2, buf_size);
+ s_usub(t3, t2, t3, buf_size + 2, buf_size);
+
+ /* Assemble the output value */
+ COPY(t1, dc, buf_size);
+ carry = s_uadd(t3, dc + bot_size, dc + bot_size,
+ buf_size + 1, buf_size);
+ assert(carry == 0);
+
+ carry = s_uadd(t2, dc + 2*bot_size, dc + 2*bot_size,
+ buf_size, buf_size);
+ assert(carry == 0);
+
+ s_free(t1); /* note t2 and t3 are just internal pointers to t1 */
+ }
+ else {
+ s_umul(da, db, dc, size_a, size_b);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_umul(da, db, dc, size_a, size_b) */
+
+STATIC void s_umul(mp_digit *da, mp_digit *db, mp_digit *dc,
+ mp_size size_a, mp_size size_b)
+{
+ mp_size a, b;
+ mp_word w;
+
+ for (a = 0; a < size_a; ++a, ++dc, ++da) {
+ mp_digit *dct = dc;
+ mp_digit *dbt = db;
+
+ if (*da == 0)
+ continue;
+
+ w = 0;
+ for (b = 0; b < size_b; ++b, ++dbt, ++dct) {
+ w = (mp_word)*da * (mp_word)*dbt + w + (mp_word)*dct;
+
+ *dct = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ }
+
+ *dct = (mp_digit)w;
+ }
+}
+
+/* }}} */
+
+/* {{{ s_ksqr(da, dc, size_a) */
+
+STATIC int s_ksqr(mp_digit *da, mp_digit *dc, mp_size size_a)
+{
+ if (multiply_threshold && size_a > multiply_threshold) {
+ mp_size bot_size = (size_a + 1) / 2;
+ mp_digit *a_top = da + bot_size;
+ mp_digit *t1, *t2, *t3, carry;
+ mp_size at_size = size_a - bot_size;
+ mp_size buf_size = 2 * bot_size;
+
+ if ((t1 = s_alloc(4 * buf_size)) == NULL) return 0;
+ t2 = t1 + buf_size;
+ t3 = t2 + buf_size;
+ ZERO(t1, 4 * buf_size);
+
+ (void) s_ksqr(da, t1, bot_size); /* t1 = a0 ^ 2 */
+ (void) s_ksqr(a_top, t2, at_size); /* t2 = a1 ^ 2 */
+
+ (void) s_kmul(da, a_top, t3, bot_size, at_size); /* t3 = a0 * a1 */
+
+ /* Quick multiply t3 by 2, shifting left (can't overflow) */
+ {
+ int i, top = bot_size + at_size;
+ mp_word w, save = 0;
+
+ for (i = 0; i < top; ++i) {
+ w = t3[i];
+ w = (w << 1) | save;
+ t3[i] = LOWER_HALF(w);
+ save = UPPER_HALF(w);
+ }
+ t3[i] = LOWER_HALF(save);
+ }
+
+ /* Assemble the output value */
+ COPY(t1, dc, 2 * bot_size);
+ carry = s_uadd(t3, dc + bot_size, dc + bot_size,
+ buf_size + 1, buf_size);
+ assert(carry == 0);
+
+ carry = s_uadd(t2, dc + 2*bot_size, dc + 2*bot_size,
+ buf_size, buf_size);
+ assert(carry == 0);
+
+ s_free(t1); /* note that t2 and t2 are internal pointers only */
+
+ }
+ else {
+ s_usqr(da, dc, size_a);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_usqr(da, dc, size_a) */
+
+STATIC void s_usqr(mp_digit *da, mp_digit *dc, mp_size size_a)
+{
+ mp_size i, j;
+ mp_word w;
+
+ for (i = 0; i < size_a; ++i, dc += 2, ++da) {
+ mp_digit *dct = dc, *dat = da;
+
+ if (*da == 0)
+ continue;
+
+ /* Take care of the first digit, no rollover */
+ w = (mp_word)*dat * (mp_word)*dat + (mp_word)*dct;
+ *dct = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ ++dat; ++dct;
+
+ for (j = i + 1; j < size_a; ++j, ++dat, ++dct) {
+ mp_word t = (mp_word)*da * (mp_word)*dat;
+ mp_word u = w + (mp_word)*dct, ov = 0;
+
+ /* Check if doubling t will overflow a word */
+ if (HIGH_BIT_SET(t))
+ ov = 1;
+
+ w = t + t;
+
+ /* Check if adding u to w will overflow a word */
+ if (ADD_WILL_OVERFLOW(w, u))
+ ov = 1;
+
+ w += u;
+
+ *dct = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ if (ov) {
+ w += MP_DIGIT_MAX; /* MP_RADIX */
+ ++w;
+ }
+ }
+
+ w = w + *dct;
+ *dct = (mp_digit)w;
+ while ((w = UPPER_HALF(w)) != 0) {
+ ++dct; w = w + *dct;
+ *dct = LOWER_HALF(w);
+ }
+
+ assert(w == 0);
+ }
+}
+
+/* }}} */
+
+/* {{{ s_dadd(a, b) */
+
+STATIC void s_dadd(mp_int a, mp_digit b)
+{
+ mp_word w = 0;
+ mp_digit *da = MP_DIGITS(a);
+ mp_size ua = MP_USED(a);
+
+ w = (mp_word)*da + b;
+ *da++ = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+
+ for (ua -= 1; ua > 0; --ua, ++da) {
+ w = (mp_word)*da + w;
+
+ *da = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ }
+
+ if (w) {
+ *da = (mp_digit)w;
+ MP_USED(a) += 1;
+ }
+}
+
+/* }}} */
+
+/* {{{ s_dmul(a, b) */
+
+STATIC void s_dmul(mp_int a, mp_digit b)
+{
+ mp_word w = 0;
+ mp_digit *da = MP_DIGITS(a);
+ mp_size ua = MP_USED(a);
+
+ while (ua > 0) {
+ w = (mp_word)*da * b + w;
+ *da++ = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ --ua;
+ }
+
+ if (w) {
+ *da = (mp_digit)w;
+ MP_USED(a) += 1;
+ }
+}
+
+/* }}} */
+
+/* {{{ s_dbmul(da, b, dc, size_a) */
+
+STATIC void s_dbmul(mp_digit *da, mp_digit b, mp_digit *dc, mp_size size_a)
+{
+ mp_word w = 0;
+
+ while (size_a > 0) {
+ w = (mp_word)*da++ * (mp_word)b + w;
+
+ *dc++ = LOWER_HALF(w);
+ w = UPPER_HALF(w);
+ --size_a;
+ }
+
+ if (w)
+ *dc = LOWER_HALF(w);
+}
+
+/* }}} */
+
+/* {{{ s_ddiv(da, d, dc, size_a) */
+
+STATIC mp_digit s_ddiv(mp_int a, mp_digit b)
+{
+ mp_word w = 0, qdigit;
+ mp_size ua = MP_USED(a);
+ mp_digit *da = MP_DIGITS(a) + ua - 1;
+
+ for (/* */; ua > 0; --ua, --da) {
+ w = (w << MP_DIGIT_BIT) | *da;
+
+ if (w >= b) {
+ qdigit = w / b;
+ w = w % b;
+ }
+ else {
+ qdigit = 0;
+ }
+
+ *da = (mp_digit)qdigit;
+ }
+
+ CLAMP(a);
+ return (mp_digit)w;
+}
+
+/* }}} */
+
+/* {{{ s_qdiv(z, p2) */
+
+STATIC void s_qdiv(mp_int z, mp_size p2)
+{
+ mp_size ndig = p2 / MP_DIGIT_BIT, nbits = p2 % MP_DIGIT_BIT;
+ mp_size uz = MP_USED(z);
+
+ if (ndig) {
+ mp_size mark;
+ mp_digit *to, *from;
+
+ if (ndig >= uz) {
+ mp_int_zero(z);
+ return;
+ }
+
+ to = MP_DIGITS(z); from = to + ndig;
+
+ for (mark = ndig; mark < uz; ++mark)
+ *to++ = *from++;
+
+ MP_USED(z) = uz - ndig;
+ }
+
+ if (nbits) {
+ mp_digit d = 0, *dz, save;
+ mp_size up = MP_DIGIT_BIT - nbits;
+
+ uz = MP_USED(z);
+ dz = MP_DIGITS(z) + uz - 1;
+
+ for (/* */; uz > 0; --uz, --dz) {
+ save = *dz;
+
+ *dz = (*dz >> nbits) | (d << up);
+ d = save;
+ }
+
+ CLAMP(z);
+ }
+
+ if (MP_USED(z) == 1 && z->digits[0] == 0)
+ MP_SIGN(z) = MP_ZPOS;
+}
+
+/* }}} */
+
+/* {{{ s_qmod(z, p2) */
+
+STATIC void s_qmod(mp_int z, mp_size p2)
+{
+ mp_size start = p2 / MP_DIGIT_BIT + 1, rest = p2 % MP_DIGIT_BIT;
+ mp_size uz = MP_USED(z);
+ mp_digit mask = (1 << rest) - 1;
+
+ if (start <= uz) {
+ MP_USED(z) = start;
+ z->digits[start - 1] &= mask;
+ CLAMP(z);
+ }
+}
+
+/* }}} */
+
+/* {{{ s_qmul(z, p2) */
+
+STATIC int s_qmul(mp_int z, mp_size p2)
+{
+ mp_size uz, need, rest, extra, i;
+ mp_digit *from, *to, d;
+
+ if (p2 == 0)
+ return 1;
+
+ uz = MP_USED(z);
+ need = p2 / MP_DIGIT_BIT; rest = p2 % MP_DIGIT_BIT;
+
+ /* Figure out if we need an extra digit at the top end; this occurs if the
+ topmost `rest' bits of the high-order digit of z are not zero, meaning
+ they will be shifted off the end if not preserved */
+ extra = 0;
+ if (rest != 0) {
+ mp_digit *dz = MP_DIGITS(z) + uz - 1;
+
+ if ((*dz >> (MP_DIGIT_BIT - rest)) != 0)
+ extra = 1;
+ }
+
+ if (!s_pad(z, uz + need + extra))
+ return 0;
+
+ /* If we need to shift by whole digits, do that in one pass, then
+ to back and shift by partial digits.
+ */
+ if (need > 0) {
+ from = MP_DIGITS(z) + uz - 1;
+ to = from + need;
+
+ for (i = 0; i < uz; ++i)
+ *to-- = *from--;
+
+ ZERO(MP_DIGITS(z), need);
+ uz += need;
+ }
+
+ if (rest) {
+ d = 0;
+ for (i = need, from = MP_DIGITS(z) + need; i < uz; ++i, ++from) {
+ mp_digit save = *from;
+
+ *from = (*from << rest) | (d >> (MP_DIGIT_BIT - rest));
+ d = save;
+ }
+
+ d >>= (MP_DIGIT_BIT - rest);
+ if (d != 0) {
+ *from = d;
+ uz += extra;
+ }
+ }
+
+ MP_USED(z) = uz;
+ CLAMP(z);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_qsub(z, p2) */
+
+/* Compute z = 2^p2 - |z|; requires that 2^p2 >= |z|
+ The sign of the result is always zero/positive.
+ */
+STATIC int s_qsub(mp_int z, mp_size p2)
+{
+ mp_digit hi = (1 << (p2 % MP_DIGIT_BIT)), *zp;
+ mp_size tdig = (p2 / MP_DIGIT_BIT), pos;
+ mp_word w = 0;
+
+ if (!s_pad(z, tdig + 1))
+ return 0;
+
+ for (pos = 0, zp = MP_DIGITS(z); pos < tdig; ++pos, ++zp) {
+ w = ((mp_word) MP_DIGIT_MAX + 1) - w - (mp_word)*zp;
+
+ *zp = LOWER_HALF(w);
+ w = UPPER_HALF(w) ? 0 : 1;
+ }
+
+ w = ((mp_word) MP_DIGIT_MAX + 1 + hi) - w - (mp_word)*zp;
+ *zp = LOWER_HALF(w);
+
+ assert(UPPER_HALF(w) != 0); /* no borrow out should be possible */
+
+ MP_SIGN(z) = MP_ZPOS;
+ CLAMP(z);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_dp2k(z) */
+
+STATIC int s_dp2k(mp_int z)
+{
+ int k = 0;
+ mp_digit *dp = MP_DIGITS(z), d;
+
+ if (MP_USED(z) == 1 && *dp == 0)
+ return 1;
+
+ while (*dp == 0) {
+ k += MP_DIGIT_BIT;
+ ++dp;
+ }
+
+ d = *dp;
+ while ((d & 1) == 0) {
+ d >>= 1;
+ ++k;
+ }
+
+ return k;
+}
+
+/* }}} */
+
+/* {{{ s_isp2(z) */
+
+STATIC int s_isp2(mp_int z)
+{
+ mp_size uz = MP_USED(z), k = 0;
+ mp_digit *dz = MP_DIGITS(z), d;
+
+ while (uz > 1) {
+ if (*dz++ != 0)
+ return -1;
+ k += MP_DIGIT_BIT;
+ --uz;
+ }
+
+ d = *dz;
+ while (d > 1) {
+ if (d & 1)
+ return -1;
+ ++k; d >>= 1;
+ }
+
+ return (int) k;
+}
+
+/* }}} */
+
+/* {{{ s_2expt(z, k) */
+
+STATIC int s_2expt(mp_int z, mp_small k)
+{
+ mp_size ndig, rest;
+ mp_digit *dz;
+
+ ndig = (k + MP_DIGIT_BIT) / MP_DIGIT_BIT;
+ rest = k % MP_DIGIT_BIT;
+
+ if (!s_pad(z, ndig))
+ return 0;
+
+ dz = MP_DIGITS(z);
+ ZERO(dz, ndig);
+ *(dz + ndig - 1) = (1 << rest);
+ MP_USED(z) = ndig;
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_norm(a, b) */
+
+STATIC int s_norm(mp_int a, mp_int b)
+{
+ mp_digit d = b->digits[MP_USED(b) - 1];
+ int k = 0;
+
+ while (d < (mp_digit) (1 << (MP_DIGIT_BIT - 1))) { /* d < (MP_RADIX / 2) */
+ d <<= 1;
+ ++k;
+ }
+
+ /* These multiplications can't fail */
+ if (k != 0) {
+ (void) s_qmul(a, (mp_size) k);
+ (void) s_qmul(b, (mp_size) k);
+ }
+
+ return k;
+}
+
+/* }}} */
+
+/* {{{ s_brmu(z, m) */
+
+STATIC mp_result s_brmu(mp_int z, mp_int m)
+{
+ mp_size um = MP_USED(m) * 2;
+
+ if (!s_pad(z, um))
+ return MP_MEMORY;
+
+ s_2expt(z, MP_DIGIT_BIT * um);
+ return mp_int_div(z, m, z, NULL);
+}
+
+/* }}} */
+
+/* {{{ s_reduce(x, m, mu, q1, q2) */
+
+STATIC int s_reduce(mp_int x, mp_int m, mp_int mu, mp_int q1, mp_int q2)
+{
+ mp_size um = MP_USED(m), umb_p1, umb_m1;
+
+ umb_p1 = (um + 1) * MP_DIGIT_BIT;
+ umb_m1 = (um - 1) * MP_DIGIT_BIT;
+
+ if (mp_int_copy(x, q1) != MP_OK)
+ return 0;
+
+ /* Compute q2 = floor((floor(x / b^(k-1)) * mu) / b^(k+1)) */
+ s_qdiv(q1, umb_m1);
+ UMUL(q1, mu, q2);
+ s_qdiv(q2, umb_p1);
+
+ /* Set x = x mod b^(k+1) */
+ s_qmod(x, umb_p1);
+
+ /* Now, q is a guess for the quotient a / m.
+ Compute x - q * m mod b^(k+1), replacing x. This may be off
+ by a factor of 2m, but no more than that.
+ */
+ UMUL(q2, m, q1);
+ s_qmod(q1, umb_p1);
+ (void) mp_int_sub(x, q1, x); /* can't fail */
+
+ /* The result may be < 0; if it is, add b^(k+1) to pin it in the proper
+ range. */
+ if ((CMPZ(x) < 0) && !s_qsub(x, umb_p1))
+ return 0;
+
+ /* If x > m, we need to back it off until it is in range. This will be
+ required at most twice. */
+ if (mp_int_compare(x, m) >= 0) {
+ (void) mp_int_sub(x, m, x);
+ if (mp_int_compare(x, m) >= 0)
+ (void) mp_int_sub(x, m, x);
+ }
+
+ /* At this point, x has been properly reduced. */
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ s_embar(a, b, m, mu, c) */
+
+/* Perform modular exponentiation using Barrett's method, where mu is the
+ reduction constant for m. Assumes a < m, b > 0. */
+STATIC mp_result s_embar(mp_int a, mp_int b, mp_int m, mp_int mu, mp_int c)
+{
+ mp_digit *db, *dbt, umu, d;
+ mp_result res;
+ DECLARE_TEMP(3);
+
+ umu = MP_USED(mu); db = MP_DIGITS(b); dbt = db + MP_USED(b) - 1;
+
+ while (last__ < 3) {
+ SETUP(mp_int_init_size(LAST_TEMP(), 4 * umu));
+ ZERO(MP_DIGITS(TEMP(last__ - 1)), MP_ALLOC(TEMP(last__ - 1)));
+ }
+
+ (void) mp_int_set_value(c, 1);
+
+ /* Take care of low-order digits */
+ while (db < dbt) {
+ int i;
+
+ for (d = *db, i = MP_DIGIT_BIT; i > 0; --i, d >>= 1) {
+ if (d & 1) {
+ /* The use of a second temporary avoids allocation */
+ UMUL(c, a, TEMP(0));
+ if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) {
+ res = MP_MEMORY; goto CLEANUP;
+ }
+ mp_int_copy(TEMP(0), c);
+ }
+
+
+ USQR(a, TEMP(0));
+ assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
+ if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) {
+ res = MP_MEMORY; goto CLEANUP;
+ }
+ assert(MP_SIGN(TEMP(0)) == MP_ZPOS);
+ mp_int_copy(TEMP(0), a);
+ }
+
+ ++db;
+ }
+
+ /* Take care of highest-order digit */
+ d = *dbt;
+ for (;;) {
+ if (d & 1) {
+ UMUL(c, a, TEMP(0));
+ if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) {
+ res = MP_MEMORY; goto CLEANUP;
+ }
+ mp_int_copy(TEMP(0), c);
+ }
+
+ d >>= 1;
+ if (!d) break;
+
+ USQR(a, TEMP(0));
+ if (!s_reduce(TEMP(0), m, mu, TEMP(1), TEMP(2))) {
+ res = MP_MEMORY; goto CLEANUP;
+ }
+ (void) mp_int_copy(TEMP(0), a);
+ }
+
+ CLEANUP_TEMP();
+ return res;
+}
+
+/* }}} */
+
+#if 0
+/* {{{ s_udiv(a, b) */
+/* The s_udiv function produces incorrect results. For example, with test
+ div:11141460315522012760862883825:48318382095:0,230584300062375935
+ commenting out the function for now and using s_udiv_knuth instead.
+ STATIC mp_result s_udiv(mp_int a, mp_int b);
+*/
+
+/* Precondition: a >= b and b > 0
+ Postcondition: a' = a / b, b' = a % b
+ */
+STATIC mp_result s_udiv(mp_int a, mp_int b)
+{
+ mpz_t q, r, t;
+ mp_size ua, ub, qpos = 0;
+ mp_digit *da, btop;
+ mp_result res = MP_OK;
+ int k, skip = 0;
+
+ /* Force signs to positive */
+ MP_SIGN(a) = MP_ZPOS;
+ MP_SIGN(b) = MP_ZPOS;
+
+ /* Normalize, per Knuth */
+ k = s_norm(a, b);
+
+ ua = MP_USED(a); ub = MP_USED(b); btop = b->digits[ub - 1];
+ if ((res = mp_int_init_size(&q, ua)) != MP_OK) return res;
+ if ((res = mp_int_init_size(&t, ua + 1)) != MP_OK) goto CLEANUP;
+
+ da = MP_DIGITS(a);
+ r.digits = da + ua - 1; /* The contents of r are shared with a */
+ r.used = 1;
+ r.sign = MP_ZPOS;
+ r.alloc = MP_ALLOC(a);
+ ZERO(t.digits, t.alloc);
+
+ /* Solve for quotient digits, store in q.digits in reverse order */
+ while (r.digits >= da) {
+ assert(qpos <= q.alloc);
+
+ if (s_ucmp(b, &r) > 0) {
+ r.digits -= 1;
+ r.used += 1;
+
+ if (++skip > 1 && qpos > 0)
+ q.digits[qpos++] = 0;
+
+ CLAMP(&r);
+ }
+ else {
+ mp_word pfx = r.digits[r.used - 1];
+ mp_word qdigit;
+
+ if (r.used > 1 && pfx < btop) {
+ pfx <<= MP_DIGIT_BIT / 2;
+ pfx <<= MP_DIGIT_BIT / 2;
+ pfx |= r.digits[r.used - 2];
+ }
+
+ qdigit = pfx / btop;
+ if (qdigit > MP_DIGIT_MAX) {
+ qdigit = MP_DIGIT_MAX;
+ }
+
+ s_dbmul(MP_DIGITS(b), (mp_digit) qdigit, t.digits, ub);
+ t.used = ub + 1; CLAMP(&t);
+ while (s_ucmp(&t, &r) > 0) {
+ --qdigit;
+ (void) mp_int_sub(&t, b, &t); /* cannot fail */
+ }
+
+ s_usub(r.digits, t.digits, r.digits, r.used, t.used);
+ CLAMP(&r);
+
+ q.digits[qpos++] = (mp_digit) qdigit;
+ ZERO(t.digits, t.used);
+ skip = 0;
+ }
+ }
+
+ /* Put quotient digits in the correct order, and discard extra zeroes */
+ q.used = qpos;
+ REV(mp_digit, q.digits, qpos);
+ CLAMP(&q);
+
+ /* Denormalize the remainder */
+ CLAMP(a);
+ if (k != 0)
+ s_qdiv(a, k);
+
+ mp_int_copy(a, b); /* ok: 0 <= r < b */
+ mp_int_copy(&q, a); /* ok: q <= a */
+
+ mp_int_clear(&t);
+ CLEANUP:
+ mp_int_clear(&q);
+ return res;
+}
+
+/* }}} */
+#endif
+
+/* Division of nonnegative integers
+
+ This function implements division algorithm for unsigned multi-precision
+ integers. The algorithm is based on Algorithm D from Knuth's "The Art of
+ Computer Programming", 3rd ed. 1998, pg 272-273.
+
+ We diverge from Knuth's algorithm in that we do not perform the subtraction
+ from the remainder until we have determined that we have the correct
+ quotient digit. This makes our algorithm less efficient that Knuth because
+ we might have to perform multiple multiplication and comparison steps before
+ the subtraction. The advantage is that it is easy to implement and ensure
+ correctness without worrying about underflow from the subtraction.
+
+ inputs: u a n+m digit integer in base b (b is 2^MP_DIGIT_BIT)
+ v a n digit integer in base b (b is 2^MP_DIGIT_BIT)
+ n >= 1
+ m >= 0
+ outputs: u / v stored in u
+ u % v stored in v
+ */
+STATIC mp_result s_udiv_knuth(mp_int u, mp_int v) {
+ mpz_t q, r, t;
+ mp_result
+ res = MP_OK;
+ int k,j;
+ mp_size m,n;
+
+ /* Force signs to positive */
+ MP_SIGN(u) = MP_ZPOS;
+ MP_SIGN(v) = MP_ZPOS;
+
+ /* Use simple division algorithm when v is only one digit long */
+ if (MP_USED(v) == 1) {
+ mp_digit d, rem;
+ d = v->digits[0];
+ rem = s_ddiv(u, d);
+ mp_int_set_value(v, rem);
+ return MP_OK;
+ }
+
+ /************************************************************/
+ /* Algorithm D */
+ /************************************************************/
+ /* The n and m variables are defined as used by Knuth.
+ u is an n digit number with digits u_{n-1}..u_0.
+ v is an n+m digit number with digits from v_{m+n-1}..v_0.
+ We require that n > 1 and m >= 0 */
+ n = MP_USED(v);
+ m = MP_USED(u) - n;
+ assert(n > 1);
+ assert(m >= 0);
+
+ /************************************************************/
+ /* D1: Normalize.
+ The normalization step provides the necessary condition for Theorem B,
+ which states that the quotient estimate for q_j, call it qhat
+
+ qhat = u_{j+n}u_{j+n-1} / v_{n-1}
+
+ is bounded by
+
+ qhat - 2 <= q_j <= qhat.
+
+ That is, qhat is always greater than the actual quotient digit q,
+ and it is never more than two larger than the actual quotient digit. */
+ k = s_norm(u, v);
+
+ /* Extend size of u by one if needed.
+
+ The algorithm begins with a value of u that has one more digit of input.
+ The normalization step sets u_{m+n}..u_0 = 2^k * u_{m+n-1}..u_0. If the
+ multiplication did not increase the number of digits of u, we need to add
+ a leading zero here.
+ */
+ if (k == 0 || MP_USED(u) != m + n + 1) {
+ if (!s_pad(u, m+n+1))
+ return MP_MEMORY;
+ u->digits[m+n] = 0;
+ u->used = m+n+1;
+ }
+
+ /* Add a leading 0 to v.
+
+ The multiplication in step D4 multiplies qhat * 0v_{n-1}..v_0. We need to
+ add the leading zero to v here to ensure that the multiplication will
+ produce the full n+1 digit result. */
+ if (!s_pad(v, n+1)) return MP_MEMORY; v->digits[n] = 0;
+
+ /* Initialize temporary variables q and t.
+ q allocates space for m+1 digits to store the quotient digits
+ t allocates space for n+1 digits to hold the result of q_j*v */
+ if ((res = mp_int_init_size(&q, m + 1)) != MP_OK) return res;
+ if ((res = mp_int_init_size(&t, n + 1)) != MP_OK) goto CLEANUP;
+
+ /************************************************************/
+ /* D2: Initialize j */
+ j = m;
+ r.digits = MP_DIGITS(u) + j; /* The contents of r are shared with u */
+ r.used = n + 1;
+ r.sign = MP_ZPOS;
+ r.alloc = MP_ALLOC(u);
+ ZERO(t.digits, t.alloc);
+
+ /* Calculate the m+1 digits of the quotient result */
+ for (; j >= 0; j--) {
+ /************************************************************/
+ /* D3: Calculate q' */
+ /* r->digits is aligned to position j of the number u */
+ mp_word pfx, qhat;
+ pfx = r.digits[n];
+ pfx <<= MP_DIGIT_BIT / 2;
+ pfx <<= MP_DIGIT_BIT / 2;
+ pfx |= r.digits[n-1]; /* pfx = u_{j+n}{j+n-1} */
+
+ qhat = pfx / v->digits[n-1];
+ /* Check to see if qhat > b, and decrease qhat if so.
+ Theorem B guarantess that qhat is at most 2 larger than the
+ actual value, so it is possible that qhat is greater than
+ the maximum value that will fit in a digit */
+ if (qhat > MP_DIGIT_MAX)
+ qhat = MP_DIGIT_MAX;
+
+ /************************************************************/
+ /* D4,D5,D6: Multiply qhat * v and test for a correct value of q
+
+ We proceed a bit different than the way described by Knuth. This way is
+ simpler but less efficent. Instead of doing the multiply and subtract
+ then checking for underflow, we first do the multiply of qhat * v and
+ see if it is larger than the current remainder r. If it is larger, we
+ decrease qhat by one and try again. We may need to decrease qhat one
+ more time before we get a value that is smaller than r.
+
+ This way is less efficent than Knuth becuase we do more multiplies, but
+ we do not need to worry about underflow this way. */
+ /* t = qhat * v */
+ s_dbmul(MP_DIGITS(v), (mp_digit) qhat, t.digits, n+1); t.used = n + 1;
+ CLAMP(&t);
+
+ /* Clamp r for the comparison. Comparisons do not like leading zeros. */
+ CLAMP(&r);
+ if (s_ucmp(&t, &r) > 0) { /* would the remainder be negative? */
+ qhat -= 1; /* try a smaller q */
+ s_dbmul(MP_DIGITS(v), (mp_digit) qhat, t.digits, n+1);
+ t.used = n + 1; CLAMP(&t);
+ if (s_ucmp(&t, &r) > 0) { /* would the remainder be negative? */
+ assert(qhat > 0);
+ qhat -= 1; /* try a smaller q */
+ s_dbmul(MP_DIGITS(v), (mp_digit) qhat, t.digits, n+1);
+ t.used = n + 1; CLAMP(&t);
+ }
+ assert(s_ucmp(&t, &r) <= 0 && "The mathematics failed us.");
+ }
+ /* Unclamp r. The D algorithm expects r = u_{j+n}..u_j to always be n+1
+ digits long. */
+ r.used = n + 1;
+
+ /************************************************************/
+ /* D4: Multiply and subtract */
+ /* note: The multiply was completed above so we only need to subtract here.
+ **/
+ s_usub(r.digits, t.digits, r.digits, r.used, t.used);
+
+ /************************************************************/
+ /* D5: Test remainder */
+ /* note: Not needed because we always check that qhat is the correct value
+ * before performing the subtract. */
+ q.digits[j] = qhat;
+
+ /************************************************************/
+ /* D6: Add back */
+ /* note: Not needed because we always check that qhat is the correct value
+ * before performing the subtract. */
+
+ /************************************************************/
+ /* D7: Loop on j */
+ r.digits--;
+ ZERO(t.digits, t.alloc);
+ }
+
+ /* Get rid of leading zeros in q */
+ q.used = m + 1;
+ CLAMP(&q);
+
+ /* Denormalize the remainder */
+ CLAMP(u); /* use u here because the r.digits pointer is off-by-one */
+ if (k != 0)
+ s_qdiv(u, k);
+
+ mp_int_copy(u, v); /* ok: 0 <= r < v */
+ mp_int_copy(&q, u); /* ok: q <= u */
+
+ mp_int_clear(&t);
+ CLEANUP:
+ mp_int_clear(&q);
+ return res;
+}
+
+/* {{{ s_outlen(z, r) */
+
+STATIC int s_outlen(mp_int z, mp_size r)
+{
+ mp_result bits;
+ double raw;
+
+ assert(r >= MP_MIN_RADIX && r <= MP_MAX_RADIX);
+
+ bits = mp_int_count_bits(z);
+ raw = (double)bits * s_log2[r];
+
+ return (int)(raw + 0.999999);
+}
+
+/* }}} */
+
+/* {{{ s_inlen(len, r) */
+
+STATIC mp_size s_inlen(int len, mp_size r)
+{
+ double raw = (double)len / s_log2[r];
+ mp_size bits = (mp_size)(raw + 0.5);
+
+ return (mp_size)((bits + (MP_DIGIT_BIT - 1)) / MP_DIGIT_BIT) + 1;
+}
+
+/* }}} */
+
+/* {{{ s_ch2val(c, r) */
+
+STATIC int s_ch2val(char c, int r)
+{
+ int out;
+
+ if (isdigit((unsigned char) c))
+ out = c - '0';
+ else if (r > 10 && isalpha((unsigned char) c))
+ out = toupper(c) - 'A' + 10;
+ else
+ return -1;
+
+ return (out >= r) ? -1 : out;
+}
+
+/* }}} */
+
+/* {{{ s_val2ch(v, caps) */
+
+STATIC char s_val2ch(int v, int caps)
+{
+ assert(v >= 0);
+
+ if (v < 10)
+ return v + '0';
+ else {
+ char out = (v - 10) + 'a';
+
+ if (caps)
+ return toupper(out);
+ else
+ return out;
+ }
+}
+
+/* }}} */
+
+/* {{{ s_2comp(buf, len) */
+
+STATIC void s_2comp(unsigned char *buf, int len)
+{
+ int i;
+ unsigned short s = 1;
+
+ for (i = len - 1; i >= 0; --i) {
+ unsigned char c = ~buf[i];
+
+ s = c + s;
+ c = s & UCHAR_MAX;
+ s >>= CHAR_BIT;
+
+ buf[i] = c;
+ }
+
+ /* last carry out is ignored */
+}
+
+/* }}} */
+
+/* {{{ s_tobin(z, buf, *limpos) */
+
+STATIC mp_result s_tobin(mp_int z, unsigned char *buf, int *limpos, int pad)
+{
+ mp_size uz;
+ mp_digit *dz;
+ int pos = 0, limit = *limpos;
+
+ uz = MP_USED(z); dz = MP_DIGITS(z);
+ while (uz > 0 && pos < limit) {
+ mp_digit d = *dz++;
+ int i;
+
+ for (i = sizeof(mp_digit); i > 0 && pos < limit; --i) {
+ buf[pos++] = (unsigned char)d;
+ d >>= CHAR_BIT;
+
+ /* Don't write leading zeroes */
+ if (d == 0 && uz == 1)
+ i = 0; /* exit loop without signaling truncation */
+ }
+
+ /* Detect truncation (loop exited with pos >= limit) */
+ if (i > 0) break;
+
+ --uz;
+ }
+
+ if (pad != 0 && (buf[pos - 1] >> (CHAR_BIT - 1))) {
+ if (pos < limit)
+ buf[pos++] = 0;
+ else
+ uz = 1;
+ }
+
+ /* Digits are in reverse order, fix that */
+ REV(unsigned char, buf, pos);
+
+ /* Return the number of bytes actually written */
+ *limpos = pos;
+
+ return (uz == 0) ? MP_OK : MP_TRUNC;
+}
+
+/* }}} */
+
+/* {{{ s_print(tag, z) */
+
+#if DEBUG
+void s_print(char *tag, mp_int z)
+{
+ int i;
+
+ fprintf(stderr, "%s: %c ", tag,
+ (MP_SIGN(z) == MP_NEG) ? '-' : '+');
+
+ for (i = MP_USED(z) - 1; i >= 0; --i)
+ fprintf(stderr, "%0*X", (int)(MP_DIGIT_BIT / 4), z->digits[i]);
+
+ fputc('\n', stderr);
+
+}
+
+void s_print_buf(char *tag, mp_digit *buf, mp_size num)
+{
+ int i;
+
+ fprintf(stderr, "%s: ", tag);
+
+ for (i = num - 1; i >= 0; --i)
+ fprintf(stderr, "%0*X", (int)(MP_DIGIT_BIT / 4), buf[i]);
+
+ fputc('\n', stderr);
+}
+#endif
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/imath.h b/polly/lib/External/isl/imath/imath.h
new file mode 100644
index 00000000000..a9f5e408a48
--- /dev/null
+++ b/polly/lib/External/isl/imath/imath.h
@@ -0,0 +1,232 @@
+/*
+ Name: imath.h
+ Purpose: Arbitrary precision integer arithmetic routines.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef IMATH_H_
+#define IMATH_H_
+
+#include <stdint.h>
+#include <limits.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned char mp_sign;
+typedef unsigned int mp_size;
+typedef int mp_result;
+typedef long mp_small; /* must be a signed type */
+typedef unsigned long mp_usmall; /* must be an unsigned type */
+
+/* Force building with uint64_t so that the library builds consistently
+ * whether we build from the makefile or by embedding imath in another project.
+ */
+#undef USE_64BIT_WORDS
+#define USE_64BIT_WORDS
+#ifdef USE_64BIT_WORDS
+typedef uint32_t mp_digit;
+typedef uint64_t mp_word;
+#else
+typedef uint16_t mp_digit;
+typedef uint32_t mp_word;
+#endif
+
+typedef struct mpz {
+ mp_digit single;
+ mp_digit *digits;
+ mp_size alloc;
+ mp_size used;
+ mp_sign sign;
+} mpz_t, *mp_int;
+
+#define MP_DIGITS(Z) ((Z)->digits)
+#define MP_ALLOC(Z) ((Z)->alloc)
+#define MP_USED(Z) ((Z)->used)
+#define MP_SIGN(Z) ((Z)->sign)
+
+extern const mp_result MP_OK;
+extern const mp_result MP_FALSE;
+extern const mp_result MP_TRUE;
+extern const mp_result MP_MEMORY;
+extern const mp_result MP_RANGE;
+extern const mp_result MP_UNDEF;
+extern const mp_result MP_TRUNC;
+extern const mp_result MP_BADARG;
+extern const mp_result MP_MINERR;
+
+#define MP_DIGIT_BIT (sizeof(mp_digit) * CHAR_BIT)
+#define MP_WORD_BIT (sizeof(mp_word) * CHAR_BIT)
+#define MP_SMALL_MIN LONG_MIN
+#define MP_SMALL_MAX LONG_MAX
+#define MP_USMALL_MIN ULONG_MIN
+#define MP_USMALL_MAX ULONG_MAX
+
+#ifdef USE_64BIT_WORDS
+# define MP_DIGIT_MAX (UINT32_MAX * UINT64_C(1))
+# define MP_WORD_MAX (UINT64_MAX)
+#else
+# define MP_DIGIT_MAX (UINT16_MAX * 1UL)
+# define MP_WORD_MAX (UINT32_MAX * 1UL)
+#endif
+
+#define MP_MIN_RADIX 2
+#define MP_MAX_RADIX 36
+
+/* Values with fewer than this many significant digits use the standard
+ multiplication algorithm; otherwise, a recursive algorithm is used.
+ Choose a value to suit your platform.
+ */
+#define MP_MULT_THRESH 22
+
+#define MP_DEFAULT_PREC 8 /* default memory allocation, in digits */
+
+extern const mp_sign MP_NEG;
+extern const mp_sign MP_ZPOS;
+
+#define mp_int_is_odd(Z) ((Z)->digits[0] & 1)
+#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
+
+mp_result mp_int_init(mp_int z);
+mp_int mp_int_alloc(void);
+mp_result mp_int_init_size(mp_int z, mp_size prec);
+mp_result mp_int_init_copy(mp_int z, mp_int old);
+mp_result mp_int_init_value(mp_int z, mp_small value);
+mp_result mp_int_init_uvalue(mp_int z, mp_usmall uvalue);
+mp_result mp_int_set_value(mp_int z, mp_small value);
+mp_result mp_int_set_uvalue(mp_int z, mp_usmall uvalue);
+void mp_int_clear(mp_int z);
+void mp_int_free(mp_int z);
+
+mp_result mp_int_copy(mp_int a, mp_int c); /* c = a */
+void mp_int_swap(mp_int a, mp_int c); /* swap a, c */
+void mp_int_zero(mp_int z); /* z = 0 */
+mp_result mp_int_abs(mp_int a, mp_int c); /* c = |a| */
+mp_result mp_int_neg(mp_int a, mp_int c); /* c = -a */
+mp_result mp_int_add(mp_int a, mp_int b, mp_int c); /* c = a + b */
+mp_result mp_int_add_value(mp_int a, mp_small value, mp_int c);
+mp_result mp_int_sub(mp_int a, mp_int b, mp_int c); /* c = a - b */
+mp_result mp_int_sub_value(mp_int a, mp_small value, mp_int c);
+mp_result mp_int_mul(mp_int a, mp_int b, mp_int c); /* c = a * b */
+mp_result mp_int_mul_value(mp_int a, mp_small value, mp_int c);
+mp_result mp_int_mul_pow2(mp_int a, mp_small p2, mp_int c);
+mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
+mp_result mp_int_div(mp_int a, mp_int b, /* q = a / b */
+ mp_int q, mp_int r); /* r = a % b */
+mp_result mp_int_div_value(mp_int a, mp_small value, /* q = a / value */
+ mp_int q, mp_small *r); /* r = a % value */
+mp_result mp_int_div_pow2(mp_int a, mp_small p2, /* q = a / 2^p2 */
+ mp_int q, mp_int r); /* r = q % 2^p2 */
+mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */
+#define mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
+mp_result mp_int_expt(mp_int a, mp_small b, mp_int c); /* c = a^b */
+mp_result mp_int_expt_value(mp_small a, mp_small b, mp_int c); /* c = a^b */
+mp_result mp_int_expt_full(mp_int a, mp_int b, mp_int c); /* c = a^b */
+
+int mp_int_compare(mp_int a, mp_int b); /* a <=> b */
+int mp_int_compare_unsigned(mp_int a, mp_int b); /* |a| <=> |b| */
+int mp_int_compare_zero(mp_int z); /* a <=> 0 */
+int mp_int_compare_value(mp_int z, mp_small v); /* a <=> v */
+int mp_int_compare_uvalue(mp_int z, mp_usmall uv); /* a <=> uv */
+
+/* Returns true if v|a, false otherwise (including errors) */
+int mp_int_divisible_value(mp_int a, mp_small v);
+
+/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
+int mp_int_is_pow2(mp_int z);
+
+mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
+ mp_int c); /* c = a^b (mod m) */
+mp_result mp_int_exptmod_evalue(mp_int a, mp_small value,
+ mp_int m, mp_int c); /* c = a^v (mod m) */
+mp_result mp_int_exptmod_bvalue(mp_small value, mp_int b,
+ mp_int m, mp_int c); /* c = v^b (mod m) */
+mp_result mp_int_exptmod_known(mp_int a, mp_int b,
+ mp_int m, mp_int mu,
+ mp_int c); /* c = a^b (mod m) */
+mp_result mp_int_redux_const(mp_int m, mp_int c);
+
+mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */
+
+mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */
+
+mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */
+ mp_int x, mp_int y); /* c = ax + by */
+
+mp_result mp_int_lcm(mp_int a, mp_int b, mp_int c); /* c = lcm(a, b) */
+
+mp_result mp_int_root(mp_int a, mp_small b, mp_int c); /* c = floor(a^{1/b}) */
+#define mp_int_sqrt(a, c) mp_int_root(a, 2, c) /* c = floor(sqrt(a)) */
+
+/* Convert to a small int, if representable; else MP_RANGE */
+mp_result mp_int_to_int(mp_int z, mp_small *out);
+mp_result mp_int_to_uint(mp_int z, mp_usmall *out);
+
+/* Convert to nul-terminated string with the specified radix, writing at
+ most limit characters including the nul terminator */
+mp_result mp_int_to_string(mp_int z, mp_size radix,
+ char *str, int limit);
+
+/* Return the number of characters required to represent
+ z in the given radix. May over-estimate. */
+mp_result mp_int_string_len(mp_int z, mp_size radix);
+
+/* Read zero-terminated string into z */
+mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);
+mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
+ char **end);
+
+/* Return the number of significant bits in z */
+mp_result mp_int_count_bits(mp_int z);
+
+/* Convert z to two's complement binary, writing at most limit bytes */
+mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
+
+/* Read a two's complement binary value into z from the given buffer */
+mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);
+
+/* Return the number of bytes required to represent z in binary. */
+mp_result mp_int_binary_len(mp_int z);
+
+/* Convert z to unsigned binary, writing at most limit bytes */
+mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
+
+/* Read an unsigned binary value into z from the given buffer */
+mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
+
+/* Return the number of bytes required to represent z as unsigned output */
+mp_result mp_int_unsigned_len(mp_int z);
+
+/* Return a statically allocated string describing error code res */
+const char *mp_error_string(mp_result res);
+
+#if DEBUG
+void s_print(char *tag, mp_int z);
+void s_print_buf(char *tag, mp_digit *buf, mp_size num);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* end IMATH_H_ */
diff --git a/polly/lib/External/isl/imath/imdrover.c b/polly/lib/External/isl/imath/imdrover.c
new file mode 100644
index 00000000000..be0de16cc8f
--- /dev/null
+++ b/polly/lib/External/isl/imath/imdrover.c
@@ -0,0 +1,1780 @@
+/*
+ Name: imdrover.c
+ Purpose: Keeper of the hordes of testing code.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "imdrover.h"
+#include "imath.h"
+#include "imrat.h"
+
+/* Globals visible from outside this file */
+mp_result imath_errno;
+char *imath_errmsg;
+
+/* Set imath_errno and return failure from a test. */
+#define FAIL(E) return (imath_errno = (E), 0)
+
+/* Check that an expression X yields the expected mp_result value V. */
+#define VCHECK(X, V) \
+do { \
+ mp_result res_; \
+ if ((res_ = (X)) != (V)) { \
+ FAIL(res_); \
+ } \
+} while(0)
+#define CHECK(X) VCHECK(X, MP_OK)
+#define ECHECK(X) VCHECK(X, expect)
+#define ACHECK(X) \
+do { \
+ if (!(X)) { \
+ FAIL(MP_BADARG); \
+ } \
+} while(0)
+
+#define OUTPUT_LIMIT 2048
+#define NUM_REGS 16
+#define OTHER_ERROR -1024
+
+static char g_output[OUTPUT_LIMIT];
+static mpz_t g_zreg[NUM_REGS];
+static mpq_t g_qreg[NUM_REGS];
+static unsigned char g_bin1[OUTPUT_LIMIT];
+static unsigned char g_bin2[OUTPUT_LIMIT];
+
+extern void trim_line(char *line); /* borrowed from imtest.c */
+
+/* Read in a string with radix tags */
+static mp_result read_int_value(mp_int z, char *str);
+static mp_result read_rat_value(mp_rat q, char *str);
+
+/* Read in a string with radix tags, as a long (not an mp_int) */
+static int read_long(long *z, char *str);
+
+/* Parse the input and output values and fill in pointers to the
+ registers containing them. Returns true if all is well, false
+ in case of error. Caller allocates in/out to correct sizes. */
+static int parse_int_values(testspec_t* t, mp_int *in, mp_int *out,
+ mp_result *rval);
+static int parse_rat_values(testspec_t* t, mp_rat *in, mp_rat *out,
+ mp_result *rval);
+
+/* Parse a result code name and return the corresponding result
+ code */
+static int parse_result_code(char *str, mp_result *code);
+
+/* Read in a dot-delimited binary sequence to the given buffer, and
+ return the number of bytes read. Returns < 0 in case of a syntax
+ error. Records no more than limit bytes. */
+static int parse_binary(char *str, unsigned char *buf, int limit);
+
+/* Clean up registers (called from atexit()) */
+static void done_testing(void);
+
+/*------------------------------------------------------------------------*/
+/* Utility subroutines for writing tests (explained above) */
+
+/* {{{ read_int_value(z, str) */
+
+static mp_result read_int_value(mp_int z, char *str)
+{
+ int radix = 10;
+
+ if(*str == '#') {
+ ++str;
+ switch(*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return MP_RANGE;
+ }
+ ++str;
+ }
+
+ return mp_int_read_string(z, radix, str);
+}
+
+/* }}} */
+
+/* {{{ read_rat_value(q, str) */
+
+static mp_result read_rat_value(mp_rat q, char *str)
+{
+ int radix = 10;
+
+ if(*str == '#') {
+ ++str;
+ switch(*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return MP_RANGE;
+ }
+ ++str;
+ }
+
+ if(*str == '@')
+ return mp_rat_read_decimal(q, radix, str + 1);
+ else
+ return mp_rat_read_string(q, radix, str);
+}
+
+/* }}} */
+
+/* {{{ read_long(z, str) */
+
+static int read_long(long *z, char *str)
+{
+ char *end;
+ int radix = 10;
+
+ if (*str == '#') {
+ ++str;
+ switch (*str) {
+ case 'x': case 'X':
+ radix = 16;
+ break;
+ case 'd': case 'D':
+ radix = 10;
+ break;
+ case 'o': case 'O':
+ radix = 8;
+ break;
+ case 'b': case 'B':
+ radix = 2;
+ break;
+ default:
+ return 0;
+ }
+ ++str;
+ }
+
+ *z = strtol(str, &end, radix);
+ return (end != str && *end == '\0');
+}
+
+/* }}} */
+
+/* {{{ parse_int_values(t, in, out) */
+
+static int parse_int_values(testspec_t* t, mp_int* in, mp_int* out,
+ mp_result* rval)
+{
+ int i, pos = 0;
+ char *str;
+
+ if (rval != NULL)
+ *rval = MP_OK; /* default */
+
+ if (in != NULL) {
+ for (i = 0; i < t->num_inputs; ++i) {
+ str = t->input[i];
+
+ trim_line(str);
+
+ if (*str == '=') {
+ int k = abs(atoi(str + 1)) - 1;
+
+ if (k < 0 || k >= i) {
+ fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = in[k];
+ }
+ else {
+ mp_int reg = g_zreg + pos++; /* grab next free register */
+
+ if (read_int_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid input value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = reg;
+ }
+ }
+ }
+
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_int reg = g_zreg + pos++;
+
+ str = t->output[i];
+
+ trim_line(str);
+
+ if (strcmp(str, "?") == 0)
+ mp_int_zero(reg);
+ else if (*str == '$') {
+ mp_result code;
+
+ if (!parse_result_code(str, &code)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else if(rval == NULL) {
+ fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else
+ *rval = code;
+
+ /* Provide a dummy value for the corresponding output */
+ mp_int_zero(reg);
+ }
+ else if (out != NULL && read_int_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid output value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ if (out != NULL)
+ out[i] = reg;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_rat_values(t, in, out) */
+
+static int parse_rat_values(testspec_t* t, mp_rat *in, mp_rat *out,
+ mp_result *rval)
+{
+ int i, pos = 0;
+ char *str;
+
+ if (rval != NULL)
+ *rval = MP_OK; /* default */
+
+ if (in != NULL) {
+ for (i = 0; i < t->num_inputs; ++i) {
+ str = t->input[i];
+
+ trim_line(str);
+
+ if (*str == '=') {
+ int k = abs(atoi(str + 1)) - 1;
+
+ if (k < 0 || k >= i) {
+ fprintf(stderr, "Line %d: Invalid input back-reference [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = in[k];
+ }
+ else {
+ mp_rat reg = g_qreg + pos++; /* grab next free register */
+
+ if (read_rat_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid input value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ in[i] = reg;
+ }
+ }
+ }
+
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_rat reg = g_qreg + pos++;
+
+ str = t->output[i];
+
+ trim_line(str);
+
+ if (strcmp(str, "?") == 0)
+ mp_rat_zero(reg);
+ else if (*str == '$') {
+ mp_result code;
+
+ if (!parse_result_code(str, &code)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else if (rval == NULL) {
+ fprintf(stderr, "Line %d: Result code not permitted here [%s]\n",
+ t->line, str);
+ return 0;
+ }
+ else
+ *rval = code;
+
+ /* Provide a dummy value for the corresponding output */
+ mp_rat_zero(reg);
+ }
+ else if (out != NULL && read_rat_value(reg, str) != MP_OK) {
+ fprintf(stderr, "Line %d: Invalid output value [%s]\n",
+ t->line, str);
+ return 0;
+ }
+
+ if (out != NULL)
+ out[i] = reg;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_result_code(str, *code) */
+
+static int parse_result_code(char *str, mp_result *code)
+{
+ if (str[0] == '$') {
+ if (str[1] == '#') {
+ long v;
+
+ if (!read_long(&v, str + 2))
+ return 0;
+
+ *code = (mp_result) v;
+ }
+ else if (strcmp(str + 1, "MP_OK") == 0 ||
+ strcmp(str + 1, "MP_FALSE") == 0)
+ *code = MP_OK;
+ else if (strcmp(str + 1, "MP_TRUE") == 0)
+ *code = MP_TRUE;
+ else if (strcmp(str + 1, "MP_MEMORY") == 0)
+ *code = MP_MEMORY;
+ else if (strcmp(str + 1, "MP_RANGE") == 0)
+ *code = MP_RANGE;
+ else if (strcmp(str + 1, "MP_UNDEF") == 0)
+ *code = MP_UNDEF;
+ else if (strcmp(str + 1, "MP_TRUNC") == 0)
+ *code = MP_TRUNC;
+ else if (strcmp(str + 1, "MP_ROUND_UP") == 0)
+ *code = MP_ROUND_UP;
+ else if (strcmp(str + 1, "MP_ROUND_DOWN") == 0)
+ *code = MP_ROUND_DOWN;
+ else if (strcmp(str + 1, "MP_ROUND_HALF_UP") == 0)
+ *code = MP_ROUND_HALF_UP;
+ else if (strcmp(str + 1, "MP_ROUND_HALF_DOWN") == 0)
+ *code = MP_ROUND_HALF_DOWN;
+ else
+ return 0;
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ parse_binary(str, buf, limit) */
+
+static int parse_binary(char *str, unsigned char *buf, int limit)
+{
+ int pos = 0;
+ char *tok;
+
+ trim_line(str);
+
+ for (tok = strtok(str, ".");
+ tok != NULL && pos < limit;
+ tok = strtok(NULL, ".")) {
+ long v;
+
+ if (!read_long(&v, tok) || v > UCHAR_MAX || v < 0)
+ return -1;
+
+ buf[pos++] = (unsigned char)v;
+ }
+
+ return pos;
+}
+
+/* }}} */
+
+/* {{{ done_testing() */
+
+static void done_testing(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ mp_int_clear(g_zreg + i);
+ mp_rat_clear(g_qreg + i);
+ }
+}
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* Global functions visible to callers outside this file */
+
+/* {{{ init_testing() */
+
+void init_testing(void)
+{
+ static int is_done = 0;
+ int i;
+
+ if (is_done)
+ return;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ assert(mp_int_init(g_zreg + i) == MP_OK);
+ assert(mp_rat_init(g_qreg + i) == MP_OK);
+ }
+
+ imath_errmsg = g_output;
+
+ assert(atexit(done_testing) == 0);
+ is_done = 1;
+}
+
+/* }}} */
+
+/* {{{ reset_registers() */
+
+void reset_registers(void)
+{
+ int i;
+
+ for (i = 0; i < NUM_REGS; ++i) {
+ mp_int_zero(g_zreg + i);
+ mp_rat_zero(g_qreg + i);
+ }
+}
+
+/* }}} */
+
+int test_init(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_small v;
+ mp_usmall uv;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "initu") == 0) {
+ CHECK(mp_int_to_uint(in[1], &uv));
+ ECHECK(mp_int_init_uvalue(in[0], uv));
+ }
+ else { /* initv */
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_init_value(in[0], v));
+ }
+
+
+ if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
+ mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+int test_set(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_small v;
+ mp_usmall uv;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "setu") == 0) {
+ CHECK(mp_int_to_uint(in[1], &uv));
+ ECHECK(mp_int_set_uvalue(in[0], uv));
+ }
+ else { /* setv */
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_set_value(in[0], v));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[0], out[0]) != 0) {
+ mp_int_to_string(in[0], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* {{{ test_neg(t, ofp) */
+
+int test_neg(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_neg(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_abs(t, ofp) */
+
+int test_abs(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_abs(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_add(t, ofp) */
+
+int test_add(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "addv") == 0) {
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_add_value(in[0], v, in[2]));
+ }
+ else {
+ ECHECK(mp_int_add(in[0], in[1], in[2]));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sub(t, ofp) */
+
+int test_sub(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ if (strcmp(t->code, "subv") == 0) {
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_sub_value(in[0], v, in[2]));
+ }
+ else {
+ ECHECK(mp_int_sub(in[0], in[1], in[2]));
+ }
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mul(t, ofp) */
+
+int test_mul(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_mul(in[0], in[1], in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mulp2(t, ofp) */
+
+int test_mulp2(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small p2;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &p2));
+ ECHECK(mp_int_mul_pow2(in[0], p2, in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mulv(t, ofp) */
+
+int test_mulv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_mul_value(in[0], v, in[2]));
+
+ if(expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sqr(t, ofp) */
+
+int test_sqr(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_sqr(in[0], in[1]));
+
+ if(expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_div(t, ofp) */
+
+int test_div(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[2];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_div(in[0], in[1], in[2], in[3]));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0))) {
+ int len;
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_divp2(t, ofp) */
+
+int test_divp2(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[2];
+ mp_result expect;
+ mp_small p2;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &p2));
+ ECHECK(mp_int_div_pow2(in[0], p2, in[2], in[3]));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0))) {
+ int len;
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_divv(t, ofp) */
+
+int test_divv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[2];
+ mp_result expect;
+ mp_small v, rem, orem;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ CHECK(mp_int_to_int(out[1], &orem));
+ ECHECK(mp_int_div_value(in[0], v, in[2], &rem));
+
+ if (expect == MP_OK &&
+ ((mp_int_compare(in[2], out[0]) != 0) || (rem != orem))) {
+ char *str;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + strlen(g_output);
+ *str++ = ',';
+ sprintf(str, "%ld", rem);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_expt(t, ofp) */
+
+int test_expt(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small pow;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &pow));
+ ECHECK(mp_int_expt(in[0], pow, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptv(t, ofp) */
+
+int test_exptv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+ mp_small a, b;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[0], &a));
+ CHECK(mp_int_to_int(in[1], &b));
+ ECHECK(mp_int_expt_value(a, b, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptf(t, ofp) */
+
+int test_exptf(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_expt_full(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_mod(t, ofp) */
+
+int test_mod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_mod(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_gcd(t, ofp) */
+
+int test_gcd(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_gcd(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_egcd(t, ofp) */
+
+int test_egcd(testspec_t* t, FILE* ofp)
+{
+ mp_int in[5], out[3], t1 = g_zreg + 8, t2 = g_zreg + 9;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_egcd(in[0], in[1], in[2], in[3], in[4]));
+
+ /* If we got an error we expected, return success immediately */
+ if(expect != MP_OK)
+ return 1;
+
+ if ((mp_int_compare(in[2], out[0]) != 0) ||
+ (mp_int_compare(in[3], out[1]) != 0) ||
+ (mp_int_compare(in[4], out[2]) != 0)) {
+ int len, len2;
+ char *str;
+
+ /* Failure might occur because the tester computed x and y in a different
+ way than we did. Verify that the results are correct before reporting
+ an error. */
+ mp_int_mul(in[3], in[0], t1);
+ mp_int_mul(in[4], in[1], t2);
+ mp_int_add(t1, t2, t2);
+ if (mp_int_compare(t2, in[2]) == 0)
+ return 1;
+
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ str = g_output + (len = strlen(g_output));
+ *str++ = ',';
+ mp_int_to_string(in[3], 10, str, OUTPUT_LIMIT - (len + 1));
+ str = str + (len2 = strlen(str));
+ *str++ = ',';
+ mp_int_to_string(in[4], 10, str, OUTPUT_LIMIT - (len + len2 + 2));
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_lcm(t, ofp) */
+
+int test_lcm(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_lcm(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_sqrt(t, ofp) */
+
+int test_sqrt(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_sqrt(in[0], in[1]));
+
+ if (expect == MP_OK && mp_int_compare(in[1], out[0]) != 0) {
+ mp_int_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_root(t, ofp) */
+
+int test_root(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_root(in[0], v, in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_invmod(t, ofp) */
+
+int test_invmod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_invmod(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_int_compare(in[2], out[0]) != 0) {
+ mp_int_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod(t, ofp) */
+
+int test_exptmod(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_exptmod(in[0], in[1], in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod_ev(t, ofp) */
+
+int test_exptmod_ev(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[1], &v));
+ ECHECK(mp_int_exptmod_evalue(in[0], v, in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_exptmod_bv(t, ofp) */
+
+int test_exptmod_bv(testspec_t* t, FILE* ofp)
+{
+ mp_int in[4], out[1];
+ mp_result expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ CHECK(mp_int_to_int(in[0], &v));
+ ECHECK(mp_int_exptmod_bvalue(v, in[1], in[2], in[3]));
+
+ if (expect == MP_OK && mp_int_compare(in[3], out[0]) != 0) {
+ mp_int_to_string(in[3], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_comp(t, ofp) */
+
+int test_comp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare(in[0], in[1])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_ucomp(t, ofp) */
+
+int test_ucomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare_unsigned(in[0], in[1])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_zcomp(t, ofp) */
+
+int test_zcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ mp_result res, expect;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ if ((res = mp_int_compare_zero(in[0])) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_vcomp(t, ofp) */
+
+int test_vcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+ mp_small v;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ v = atoi(t->input[1]);
+ if ((res = mp_int_compare_value(in[0], v)) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_uvcomp(t, ofp) */
+
+int test_uvcomp(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_result res, expect;
+ mp_usmall v;
+
+ ACHECK(parse_int_values(t, in, NULL, &expect));
+
+ v = strtoul(t->input[1], NULL, 0);
+ if ((res = mp_int_compare_uvalue(in[0], v)) != expect) {
+ sprintf(g_output, "Incorrect comparison result (want %d, got %d)",
+ expect, res);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_tostr(t, ofp) */
+
+int test_tostr(testspec_t* t, FILE* ofp)
+{
+ mp_int in[2];
+ mp_small radix;
+ mp_result len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+ ACHECK(mp_int_to_int(in[1], &radix) == MP_OK);
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX)
+ FAIL(MP_RANGE);
+
+ trim_line(t->output[0]);
+ len = mp_int_string_len(in[0], radix);
+
+ CHECK(mp_int_to_string(in[0], radix, g_output, len));
+
+ if(strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_tobin(t, ofp) */
+
+int test_tobin(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ int test_len, out_len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+
+ trim_line(t->output[0]);
+ if((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ if((test_len = mp_int_binary_len(in[0])) != out_len) {
+ sprintf(g_output, "Output lengths do not match (want %d, got %d)",
+ test_len, out_len);
+ FAIL(OTHER_ERROR);
+ }
+
+ CHECK(mp_int_to_binary(in[0], g_bin2, sizeof(g_bin2)));
+
+ if (memcmp(g_bin1, g_bin2, test_len) != 0) {
+ int pos = 0, i;
+
+ for(i = 0; i < test_len - 1; ++i)
+ pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
+
+ sprintf(g_output + pos, "%d", g_bin2[i]);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_int(t, ofp) */
+
+int test_to_int(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1], out[1];
+ mp_small v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_to_int(in[0], &v));
+
+ if (expect == MP_OK && mp_int_compare_value(out[0], v) != 0) {
+ sprintf(g_output, "Incorrect value (got %ld)", v);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_uint(t, ofp) */
+
+int test_to_uint(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1], out[1];
+ mp_usmall v;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+ ECHECK(mp_int_to_uint(in[0], &v));
+
+ if (expect == MP_OK && mp_int_compare_uvalue(out[0], v) != 0) {
+ sprintf(g_output, "Incorrect value (got %lu)", v);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_read_binary(t, ofp) */
+
+int test_read_binary(testspec_t* t, FILE* ofp)
+{
+ mp_int out[1], in = g_zreg + 1;
+ int in_len;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, NULL, out, &expect));
+
+ trim_line(t->input[0]);
+ if((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ ECHECK(mp_int_read_binary(in, g_bin1, in_len));
+
+ if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
+ mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_to_uns(t, ofp) */
+
+int test_to_uns(testspec_t* t, FILE* ofp)
+{
+ mp_int in[1];
+ int test_len, out_len;
+
+ ACHECK(parse_int_values(t, in, NULL, NULL));
+
+ trim_line(t->output[0]);
+ if((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ if((test_len = mp_int_unsigned_len(in[0])) != out_len) {
+ sprintf(g_output, "Output lengths do not match (want %d, got %d)",
+ test_len, out_len);
+ FAIL(OTHER_ERROR);
+ }
+
+ CHECK(mp_int_to_unsigned(in[0], g_bin2, sizeof(g_bin2)));
+
+ if (memcmp(g_bin1, g_bin2, test_len) != 0) {
+ int pos = 0, i;
+
+ for(i = 0; i < test_len - 1; ++i)
+ pos += sprintf(g_output + pos, "%d.", g_bin2[i]);
+
+ sprintf(g_output + pos, "%d", g_bin2[i]);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_read_uns(t, ofp) */
+
+int test_read_uns(testspec_t* t, FILE* ofp)
+{
+ mp_int out[1], in = g_zreg + 1;
+ int in_len;
+ mp_result expect;
+
+ ACHECK(parse_int_values(t, NULL, out, &expect));
+
+ trim_line(t->input[0]);
+ if((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0)
+ FAIL(MP_BADARG);
+
+ ECHECK(mp_int_read_unsigned(in, g_bin1, in_len));
+
+ if (expect == MP_OK && mp_int_compare(in, out[0]) != 0) {
+ mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_meta(t, ofp) */
+
+int test_meta(testspec_t* t, FILE* ofp)
+{
+ mp_int *in = NULL, *out = NULL;
+ int i, j;
+ mp_result expect;
+
+ if (t->num_inputs > 0)
+ in = calloc(t->num_inputs, sizeof(mp_int));
+ if (t->num_outputs > 0)
+ out = calloc(t->num_outputs, sizeof(mp_int));
+
+ ACHECK(parse_int_values(t, in, out, &expect));
+
+ fprintf(ofp, "Test '%s' defined at line %d\n",
+ t->code, t->line);
+ fprintf(ofp, "Expected result: %d\n", expect);
+ fprintf(ofp, "Input values: %d\n", t->num_inputs);
+ for (i = 0; i < t->num_inputs; ++i) {
+ mp_int_to_string(in[i], 10, g_output, OUTPUT_LIMIT);
+
+ fprintf(ofp, " %2d.) %s", i + 1, g_output);
+
+ for (j = i - 1; j >= 0; --j)
+ if (in[j] == in[i]) {
+ fprintf(ofp, " (=> %d)", j + 1);
+ break;
+ }
+
+ fputc('\n', ofp);
+ }
+ fprintf(ofp, "Output values: %d\n", t->num_outputs);
+ for (i = 0; i < t->num_outputs; ++i) {
+ mp_int_to_string(out[i], 10, g_output, OUTPUT_LIMIT);
+
+ fprintf(ofp, " %2d.) %s\n", i + 1, g_output);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qneg(t, ofp) */
+
+int test_qneg(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_neg(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qrecip(t, ofp) */
+
+int test_qrecip(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_recip(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qabs(t, ofp) */
+
+int test_qabs(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_abs(in[0], in[1]));
+
+ if (expect == MP_OK && mp_rat_compare(in[1], out[0]) != 0) {
+ mp_rat_to_string(in[1], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qadd(t, ofp) */
+
+int test_qadd(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_add(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qsub(t, ofp) */
+
+int test_qsub(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_sub(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qmul(t, ofp) */
+
+int test_qmul(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_mul(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qdiv(t, ofp) */
+
+int test_qdiv(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+ ECHECK(mp_rat_div(in[0], in[1], in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qaddz(t, ofp) */
+
+int test_qaddz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qaddz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_add_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qsubz(t, ofp) */
+
+int test_qsubz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qsubz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_sub_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qmulz(t, ofp) */
+
+int test_qmulz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qmulz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_mul_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qdivz(t, ofp) */
+
+int test_qdivz(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qdivz)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ ECHECK(mp_rat_div_int(in[0], MP_NUMER_P(in[1]), in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qexpt(t, ofp) */
+
+int test_qexpt(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[3], out[1];
+ mp_result expect;
+ mp_small power;
+
+ ACHECK(parse_rat_values(t, in, out, &expect));
+
+ if (!mp_rat_is_integer(in[1])) {
+ fprintf(stderr, "Line %d: Second argument must be an integer (test_qexpt)\n",
+ t->line);
+ FAIL(MP_BADARG);
+ }
+
+ CHECK(mp_int_to_int(MP_NUMER_P(in[1]), &power));
+ ECHECK(mp_rat_expt(in[0], power, in[2]));
+
+ if (expect == MP_OK && mp_rat_compare(in[2], out[0]) != 0) {
+ mp_rat_to_string(in[2], 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qtostr(t, ofp) */
+
+int test_qtostr(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[2];
+ long radix;
+ mp_result len;
+
+ ACHECK(parse_rat_values(t, in, NULL, NULL));
+ trim_line(t->input[1]);
+ ACHECK(read_long(&radix, t->input[1]));
+
+ if (radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) {
+ fprintf(stderr, "Line %d: Radix %ld out of range\n",
+ t->line, radix);
+ FAIL(MP_RANGE);
+ }
+
+ trim_line(t->output[0]);
+ len = mp_rat_string_len(in[0], radix);
+
+ CHECK(mp_rat_to_string(in[0], radix, g_output, len));
+
+ if (strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qtodec(t, ofp) */
+
+int test_qtodec(testspec_t* t, FILE* ofp)
+{
+ mp_rat in[4];
+ long radix, prec, m;
+ mp_round_mode rmode;
+ mp_result res, expect = MP_OK, len;
+
+ ACHECK(parse_rat_values(t, in, NULL, NULL));
+
+ if (t->output[0][0] == '$' && !parse_result_code(t->output[0], &expect)) {
+ fprintf(stderr, "Line %d: Invalid result code [%s]\n",
+ t->line, t->output[0]);
+ FAIL(OTHER_ERROR);
+ }
+
+ trim_line(t->input[1]);
+ trim_line(t->input[2]);
+ trim_line(t->input[3]);
+ ACHECK(read_long(&radix, t->input[1]));
+ ACHECK(read_long(&prec, t->input[2]));
+ ACHECK(read_long(&m, t->input[3]));
+ rmode = (mp_round_mode) m;
+
+ if (prec < 0) {
+ fprintf(stderr, "Line %d: Precision %ld out of range\n",
+ t->line, prec);
+ FAIL(MP_RANGE);
+ }
+
+ trim_line(t->output[0]);
+ len = mp_rat_decimal_len(in[0], radix, prec);
+ ECHECK((res = mp_rat_to_decimal(in[0], radix, prec, rmode, g_output, len)));
+
+ if (res == MP_OK && strcmp(t->output[0], g_output) != 0)
+ FAIL(OTHER_ERROR);
+
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ test_qrdec(t, ofp) */
+
+int test_qrdec(testspec_t* t, FILE* ofp)
+{
+ mp_rat out[1], reg = g_qreg + 1;
+ long radix;
+ mp_result expect;
+
+ ACHECK(parse_rat_values(t, NULL, out, &expect));
+ trim_line(t->input[1]);
+ ACHECK(read_long(&radix, t->input[1]));
+
+ ECHECK(mp_rat_read_decimal(reg, radix, t->input[0]));
+ if (expect == MP_OK &&
+ mp_rat_compare(reg, out[0]) != 0) {
+ mp_rat_to_string(reg, 10, g_output, OUTPUT_LIMIT);
+ FAIL(OTHER_ERROR);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/imdrover.h b/polly/lib/External/isl/imath/imdrover.h
new file mode 100644
index 00000000000..df74d2b6700
--- /dev/null
+++ b/polly/lib/External/isl/imath/imdrover.h
@@ -0,0 +1,106 @@
+/*
+ Name: imdrover.h
+ Purpose: Keeper of the hordes of testing code.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef IMDROVER_H_
+#define IMDROVER_H_
+
+#include <stdio.h>
+
+typedef struct {
+ int line;
+ char *code;
+ int num_inputs;
+ char **input;
+ int num_outputs;
+ char **output;
+} testspec_t;
+
+typedef int (*test_f)(testspec_t *, FILE *);
+
+/* Call this once at the outset to set up test registers */
+void init_testing(void);
+void reset_registers(void);
+
+/* Integer tests, and general */
+int test_init(testspec_t* t, FILE* ofp);
+int test_set(testspec_t* t, FILE* ofp);
+int test_neg(testspec_t* t, FILE* ofp);
+int test_abs(testspec_t* t, FILE* ofp);
+int test_add(testspec_t* t, FILE* ofp);
+int test_sub(testspec_t* t, FILE* ofp);
+int test_mul(testspec_t* t, FILE* ofp);
+int test_mulp2(testspec_t* t, FILE* ofp);
+int test_mulv(testspec_t* t, FILE* ofp);
+int test_sqr(testspec_t* t, FILE* ofp);
+int test_div(testspec_t* t, FILE* ofp);
+int test_divp2(testspec_t* t, FILE* ofp);
+int test_divv(testspec_t* t, FILE* ofp);
+int test_expt(testspec_t* t, FILE* ofp);
+int test_exptv(testspec_t* t, FILE* ofp);
+int test_exptf(testspec_t* t, FILE* ofp);
+int test_mod(testspec_t* t, FILE* ofp);
+int test_gcd(testspec_t* t, FILE* ofp);
+int test_egcd(testspec_t* t, FILE* ofp);
+int test_lcm(testspec_t* t, FILE* ofp);
+int test_sqrt(testspec_t* t, FILE* ofp);
+int test_root(testspec_t* t, FILE* ofp);
+int test_invmod(testspec_t* t, FILE* ofp);
+int test_exptmod(testspec_t* t, FILE* ofp);
+int test_exptmod_ev(testspec_t* t, FILE* ofp);
+int test_exptmod_bv(testspec_t* t, FILE* ofp);
+int test_comp(testspec_t* t, FILE* ofp);
+int test_ucomp(testspec_t* t, FILE* ofp);
+int test_zcomp(testspec_t* t, FILE* ofp);
+int test_vcomp(testspec_t* t, FILE* ofp);
+int test_uvcomp(testspec_t* t, FILE* ofp);
+int test_tostr(testspec_t* t, FILE* ofp);
+int test_tobin(testspec_t* t, FILE* ofp);
+int test_to_int(testspec_t* t, FILE* ofp);
+int test_to_uint(testspec_t* t, FILE* ofp);
+int test_read_binary(testspec_t* t, FILE* ofp);
+int test_to_uns(testspec_t* t, FILE* ofp);
+int test_read_uns(testspec_t* t, FILE* ofp);
+int test_meta(testspec_t* t, FILE* ofp);
+
+/* Rational tests */
+int test_qneg(testspec_t* t, FILE* ofp);
+int test_qrecip(testspec_t* t, FILE* ofp);
+int test_qabs(testspec_t* t, FILE* ofp);
+int test_qadd(testspec_t* t, FILE* ofp);
+int test_qsub(testspec_t* t, FILE* ofp);
+int test_qmul(testspec_t* t, FILE* ofp);
+int test_qdiv(testspec_t* t, FILE* ofp);
+int test_qdiv(testspec_t* t, FILE* ofp);
+int test_qaddz(testspec_t* t, FILE* ofp);
+int test_qsubz(testspec_t* t, FILE* ofp);
+int test_qmulz(testspec_t* t, FILE* ofp);
+int test_qdivz(testspec_t* t, FILE* ofp);
+int test_qexpt(testspec_t* t, FILE* ofp);
+int test_qtostr(testspec_t* t, FILE* ofp);
+int test_qtodec(testspec_t* t, FILE* ofp);
+int test_qrdec(testspec_t* t, FILE* ofp);
+
+#endif /* IMDROVER_H_ */
diff --git a/polly/lib/External/isl/imath/imrat.c b/polly/lib/External/isl/imath/imrat.c
new file mode 100644
index 00000000000..c6e9cde003e
--- /dev/null
+++ b/polly/lib/External/isl/imath/imrat.c
@@ -0,0 +1,1141 @@
+/*
+ Name: imrat.c
+ Purpose: Arbitrary precision rational arithmetic routines.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include "imrat.h"
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+/* {{{ Useful macros */
+
+#define TEMP(K) (temp + (K))
+#define SETUP(E, C) \
+do{if((res = (E)) != MP_OK) goto CLEANUP; ++(C);}while(0)
+
+/* Argument checking:
+ Use CHECK() where a return value is required; NRCHECK() elsewhere */
+#define CHECK(TEST) assert(TEST)
+#define NRCHECK(TEST) assert(TEST)
+
+/* }}} */
+
+/* Reduce the given rational, in place, to lowest terms and canonical form.
+ Zero is represented as 0/1, one as 1/1. Signs are adjusted so that the sign
+ of the numerator is definitive. */
+static mp_result s_rat_reduce(mp_rat r);
+
+/* Common code for addition and subtraction operations on rationals. */
+static mp_result s_rat_combine(mp_rat a, mp_rat b, mp_rat c,
+ mp_result (*comb_f)(mp_int, mp_int, mp_int));
+
+/* {{{ mp_rat_init(r) */
+
+mp_result mp_rat_init(mp_rat r)
+{
+ mp_result res;
+
+ if ((res = mp_int_init(MP_NUMER_P(r))) != MP_OK)
+ return res;
+ if ((res = mp_int_init(MP_DENOM_P(r))) != MP_OK) {
+ mp_int_clear(MP_NUMER_P(r));
+ return res;
+ }
+
+ return mp_int_set_value(MP_DENOM_P(r), 1);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_alloc() */
+
+mp_rat mp_rat_alloc(void)
+{
+ mp_rat out = malloc(sizeof(*out));
+
+ if (out != NULL) {
+ if (mp_rat_init(out) != MP_OK) {
+ free(out);
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_reduce(r) */
+
+mp_result mp_rat_reduce(mp_rat r) {
+ return s_rat_reduce(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_init_size(r, n_prec, d_prec) */
+
+mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec)
+{
+ mp_result res;
+
+ if ((res = mp_int_init_size(MP_NUMER_P(r), n_prec)) != MP_OK)
+ return res;
+ if ((res = mp_int_init_size(MP_DENOM_P(r), d_prec)) != MP_OK) {
+ mp_int_clear(MP_NUMER_P(r));
+ return res;
+ }
+
+ return mp_int_set_value(MP_DENOM_P(r), 1);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_init_copy(r, old) */
+
+mp_result mp_rat_init_copy(mp_rat r, mp_rat old)
+{
+ mp_result res;
+
+ if ((res = mp_int_init_copy(MP_NUMER_P(r), MP_NUMER_P(old))) != MP_OK)
+ return res;
+ if ((res = mp_int_init_copy(MP_DENOM_P(r), MP_DENOM_P(old))) != MP_OK)
+ mp_int_clear(MP_NUMER_P(r));
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_set_value(r, numer, denom) */
+
+mp_result mp_rat_set_value(mp_rat r, mp_small numer, mp_small denom)
+{
+ mp_result res;
+
+ if (denom == 0)
+ return MP_UNDEF;
+
+ if ((res = mp_int_set_value(MP_NUMER_P(r), numer)) != MP_OK)
+ return res;
+ if ((res = mp_int_set_value(MP_DENOM_P(r), denom)) != MP_OK)
+ return res;
+
+ return s_rat_reduce(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_set_uvalue(r, numer, denom) */
+
+mp_result mp_rat_set_uvalue(mp_rat r, mp_usmall numer, mp_usmall denom)
+{
+ mp_result res;
+
+ if (denom == 0)
+ return MP_UNDEF;
+
+ if ((res = mp_int_set_uvalue(MP_NUMER_P(r), numer)) != MP_OK)
+ return res;
+ if ((res = mp_int_set_uvalue(MP_DENOM_P(r), denom)) != MP_OK)
+ return res;
+
+ return s_rat_reduce(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_clear(r) */
+
+void mp_rat_clear(mp_rat r)
+{
+ mp_int_clear(MP_NUMER_P(r));
+ mp_int_clear(MP_DENOM_P(r));
+
+}
+
+/* }}} */
+
+/* {{{ mp_rat_free(r) */
+
+void mp_rat_free(mp_rat r)
+{
+ NRCHECK(r != NULL);
+
+ if (r->num.digits != NULL)
+ mp_rat_clear(r);
+
+ free(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_numer(r, z) */
+
+mp_result mp_rat_numer(mp_rat r, mp_int z)
+{
+ return mp_int_copy(MP_NUMER_P(r), z);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_numer_ref(r) */
+
+mp_int mp_rat_numer_ref(mp_rat r)
+{
+ return MP_NUMER_P(r);
+}
+
+/* }}} */
+
+
+/* {{{ mp_rat_denom(r, z) */
+
+mp_result mp_rat_denom(mp_rat r, mp_int z)
+{
+ return mp_int_copy(MP_DENOM_P(r), z);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_denom_ref(r) */
+
+mp_int mp_rat_denom_ref(mp_rat r)
+{
+ return MP_DENOM_P(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_sign(r) */
+
+mp_sign mp_rat_sign(mp_rat r)
+{
+ return MP_SIGN(MP_NUMER_P(r));
+}
+
+/* }}} */
+
+/* {{{ mp_rat_copy(a, c) */
+
+mp_result mp_rat_copy(mp_rat a, mp_rat c)
+{
+ mp_result res;
+
+ if ((res = mp_int_copy(MP_NUMER_P(a), MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ res = mp_int_copy(MP_DENOM_P(a), MP_DENOM_P(c));
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_zero(r) */
+
+void mp_rat_zero(mp_rat r)
+{
+ mp_int_zero(MP_NUMER_P(r));
+ mp_int_set_value(MP_DENOM_P(r), 1);
+
+}
+
+/* }}} */
+
+/* {{{ mp_rat_abs(a, c) */
+
+mp_result mp_rat_abs(mp_rat a, mp_rat c)
+{
+ mp_result res;
+
+ if ((res = mp_int_abs(MP_NUMER_P(a), MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ res = mp_int_abs(MP_DENOM_P(a), MP_DENOM_P(c));
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_neg(a, c) */
+
+mp_result mp_rat_neg(mp_rat a, mp_rat c)
+{
+ mp_result res;
+
+ if ((res = mp_int_neg(MP_NUMER_P(a), MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ res = mp_int_copy(MP_DENOM_P(a), MP_DENOM_P(c));
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_recip(a, c) */
+
+mp_result mp_rat_recip(mp_rat a, mp_rat c)
+{
+ mp_result res;
+
+ if (mp_rat_compare_zero(a) == 0)
+ return MP_UNDEF;
+
+ if ((res = mp_rat_copy(a, c)) != MP_OK)
+ return res;
+
+ mp_int_swap(MP_NUMER_P(c), MP_DENOM_P(c));
+
+ /* Restore the signs of the swapped elements */
+ {
+ mp_sign tmp = MP_SIGN(MP_NUMER_P(c));
+
+ MP_SIGN(MP_NUMER_P(c)) = MP_SIGN(MP_DENOM_P(c));
+ MP_SIGN(MP_DENOM_P(c)) = tmp;
+ }
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_add(a, b, c) */
+
+mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c)
+{
+ return s_rat_combine(a, b, c, mp_int_add);
+
+}
+
+/* }}} */
+
+/* {{{ mp_rat_sub(a, b, c) */
+
+mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c)
+{
+ return s_rat_combine(a, b, c, mp_int_sub);
+
+}
+
+/* }}} */
+
+/* {{{ mp_rat_mul(a, b, c) */
+
+mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c)
+{
+ mp_result res;
+
+ if ((res = mp_int_mul(MP_NUMER_P(a), MP_NUMER_P(b), MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ if (mp_int_compare_zero(MP_NUMER_P(c)) != 0) {
+ if ((res = mp_int_mul(MP_DENOM_P(a), MP_DENOM_P(b), MP_DENOM_P(c))) != MP_OK)
+ return res;
+ }
+
+ return s_rat_reduce(c);
+}
+
+/* }}} */
+
+/* {{{ mp_int_div(a, b, c) */
+
+mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c)
+{
+ mp_result res = MP_OK;
+
+ if (mp_rat_compare_zero(b) == 0)
+ return MP_UNDEF;
+
+ if (c == a || c == b) {
+ mpz_t tmp;
+
+ if ((res = mp_int_init(&tmp)) != MP_OK) return res;
+ if ((res = mp_int_mul(MP_NUMER_P(a), MP_DENOM_P(b), &tmp)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_mul(MP_DENOM_P(a), MP_NUMER_P(b), MP_DENOM_P(c))) != MP_OK)
+ goto CLEANUP;
+ res = mp_int_copy(&tmp, MP_NUMER_P(c));
+
+ CLEANUP:
+ mp_int_clear(&tmp);
+ }
+ else {
+ if ((res = mp_int_mul(MP_NUMER_P(a), MP_DENOM_P(b), MP_NUMER_P(c))) != MP_OK)
+ return res;
+ if ((res = mp_int_mul(MP_DENOM_P(a), MP_NUMER_P(b), MP_DENOM_P(c))) != MP_OK)
+ return res;
+ }
+
+ if (res != MP_OK)
+ return res;
+ else
+ return s_rat_reduce(c);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_add_int(a, b, c) */
+
+mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c)
+{
+ mpz_t tmp;
+ mp_result res;
+
+ if ((res = mp_int_init_copy(&tmp, b)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_mul(&tmp, MP_DENOM_P(a), &tmp)) != MP_OK)
+ goto CLEANUP;
+
+ if ((res = mp_rat_copy(a, c)) != MP_OK)
+ goto CLEANUP;
+
+ if ((res = mp_int_add(MP_NUMER_P(c), &tmp, MP_NUMER_P(c))) != MP_OK)
+ goto CLEANUP;
+
+ res = s_rat_reduce(c);
+
+ CLEANUP:
+ mp_int_clear(&tmp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_sub_int(a, b, c) */
+
+mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c)
+{
+ mpz_t tmp;
+ mp_result res;
+
+ if ((res = mp_int_init_copy(&tmp, b)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_mul(&tmp, MP_DENOM_P(a), &tmp)) != MP_OK)
+ goto CLEANUP;
+
+ if ((res = mp_rat_copy(a, c)) != MP_OK)
+ goto CLEANUP;
+
+ if ((res = mp_int_sub(MP_NUMER_P(c), &tmp, MP_NUMER_P(c))) != MP_OK)
+ goto CLEANUP;
+
+ res = s_rat_reduce(c);
+
+ CLEANUP:
+ mp_int_clear(&tmp);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_mul_int(a, b, c) */
+
+mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c)
+{
+ mp_result res;
+
+ if ((res = mp_rat_copy(a, c)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_mul(MP_NUMER_P(c), b, MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ return s_rat_reduce(c);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_div_int(a, b, c) */
+
+mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c)
+{
+ mp_result res;
+
+ if (mp_int_compare_zero(b) == 0)
+ return MP_UNDEF;
+
+ if ((res = mp_rat_copy(a, c)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_mul(MP_DENOM_P(c), b, MP_DENOM_P(c))) != MP_OK)
+ return res;
+
+ return s_rat_reduce(c);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_expt(a, b, c) */
+
+mp_result mp_rat_expt(mp_rat a, mp_small b, mp_rat c)
+{
+ mp_result res;
+
+ /* Special cases for easy powers. */
+ if (b == 0)
+ return mp_rat_set_value(c, 1, 1);
+ else if(b == 1)
+ return mp_rat_copy(a, c);
+
+ /* Since rationals are always stored in lowest terms, it is not necessary to
+ reduce again when raising to an integer power. */
+ if ((res = mp_int_expt(MP_NUMER_P(a), b, MP_NUMER_P(c))) != MP_OK)
+ return res;
+
+ return mp_int_expt(MP_DENOM_P(a), b, MP_DENOM_P(c));
+}
+
+/* }}} */
+
+/* {{{ mp_rat_compare(a, b) */
+
+int mp_rat_compare(mp_rat a, mp_rat b)
+{
+ /* Quick check for opposite signs. Works because the sign of the numerator
+ is always definitive. */
+ if (MP_SIGN(MP_NUMER_P(a)) != MP_SIGN(MP_NUMER_P(b))) {
+ if (MP_SIGN(MP_NUMER_P(a)) == MP_ZPOS)
+ return 1;
+ else
+ return -1;
+ }
+ else {
+ /* Compare absolute magnitudes; if both are positive, the answer stands,
+ otherwise it needs to be reflected about zero. */
+ int cmp = mp_rat_compare_unsigned(a, b);
+
+ if (MP_SIGN(MP_NUMER_P(a)) == MP_ZPOS)
+ return cmp;
+ else
+ return -cmp;
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_rat_compare_unsigned(a, b) */
+
+int mp_rat_compare_unsigned(mp_rat a, mp_rat b)
+{
+ /* If the denominators are equal, we can quickly compare numerators without
+ multiplying. Otherwise, we actually have to do some work. */
+ if (mp_int_compare_unsigned(MP_DENOM_P(a), MP_DENOM_P(b)) == 0)
+ return mp_int_compare_unsigned(MP_NUMER_P(a), MP_NUMER_P(b));
+
+ else {
+ mpz_t temp[2];
+ mp_result res;
+ int cmp = INT_MAX, last = 0;
+
+ /* t0 = num(a) * den(b), t1 = num(b) * den(a) */
+ SETUP(mp_int_init_copy(TEMP(last), MP_NUMER_P(a)), last);
+ SETUP(mp_int_init_copy(TEMP(last), MP_NUMER_P(b)), last);
+
+ if ((res = mp_int_mul(TEMP(0), MP_DENOM_P(b), TEMP(0))) != MP_OK ||
+ (res = mp_int_mul(TEMP(1), MP_DENOM_P(a), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+
+ cmp = mp_int_compare_unsigned(TEMP(0), TEMP(1));
+
+ CLEANUP:
+ while (--last >= 0)
+ mp_int_clear(TEMP(last));
+
+ return cmp;
+ }
+}
+
+/* }}} */
+
+/* {{{ mp_rat_compare_zero(r) */
+
+int mp_rat_compare_zero(mp_rat r)
+{
+ return mp_int_compare_zero(MP_NUMER_P(r));
+}
+
+/* }}} */
+
+/* {{{ mp_rat_compare_value(r, n, d) */
+
+int mp_rat_compare_value(mp_rat r, mp_small n, mp_small d)
+{
+ mpq_t tmp;
+ mp_result res;
+ int out = INT_MAX;
+
+ if ((res = mp_rat_init(&tmp)) != MP_OK)
+ return out;
+ if ((res = mp_rat_set_value(&tmp, n, d)) != MP_OK)
+ goto CLEANUP;
+
+ out = mp_rat_compare(r, &tmp);
+
+ CLEANUP:
+ mp_rat_clear(&tmp);
+ return out;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_is_integer(r) */
+
+int mp_rat_is_integer(mp_rat r)
+{
+ return (mp_int_compare_value(MP_DENOM_P(r), 1) == 0);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_to_ints(r, *num, *den) */
+
+mp_result mp_rat_to_ints(mp_rat r, mp_small *num, mp_small *den)
+{
+ mp_result res;
+
+ if ((res = mp_int_to_int(MP_NUMER_P(r), num)) != MP_OK)
+ return res;
+
+ res = mp_int_to_int(MP_DENOM_P(r), den);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_to_string(r, radix, *str, limit) */
+
+mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit)
+{
+ char *start;
+ int len;
+ mp_result res;
+
+ /* Write the numerator. The sign of the rational number is written by the
+ underlying integer implementation. */
+ if ((res = mp_int_to_string(MP_NUMER_P(r), radix, str, limit)) != MP_OK)
+ return res;
+
+ /* If the value is zero, don't bother writing any denominator */
+ if (mp_int_compare_zero(MP_NUMER_P(r)) == 0)
+ return MP_OK;
+
+ /* Locate the end of the numerator, and make sure we are not going to exceed
+ the limit by writing a slash. */
+ len = strlen(str);
+ start = str + len;
+ limit -= len;
+ if(limit == 0)
+ return MP_TRUNC;
+
+ *start++ = '/';
+ limit -= 1;
+
+ res = mp_int_to_string(MP_DENOM_P(r), radix, start, limit);
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_to_decimal(r, radix, prec, *str, limit) */
+mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec,
+ mp_round_mode round, char *str, int limit)
+{
+ mpz_t temp[3];
+ mp_result res;
+ char *start = str;
+ int len, lead_0, left = limit, last = 0;
+
+ SETUP(mp_int_init_copy(TEMP(last), MP_NUMER_P(r)), last);
+ SETUP(mp_int_init(TEMP(last)), last);
+ SETUP(mp_int_init(TEMP(last)), last);
+
+ /* Get the unsigned integer part by dividing denominator into the absolute
+ value of the numerator. */
+ mp_int_abs(TEMP(0), TEMP(0));
+ if ((res = mp_int_div(TEMP(0), MP_DENOM_P(r), TEMP(0), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+
+ /* Now: T0 = integer portion, unsigned;
+ T1 = remainder, from which fractional part is computed. */
+
+ /* Count up leading zeroes after the radix point. */
+ for (lead_0 = 0; lead_0 < prec && mp_int_compare(TEMP(1), MP_DENOM_P(r)) < 0;
+ ++lead_0) {
+ if ((res = mp_int_mul_value(TEMP(1), radix, TEMP(1))) != MP_OK)
+ goto CLEANUP;
+ }
+
+ /* Multiply remainder by a power of the radix sufficient to get the right
+ number of significant figures. */
+ if (prec > lead_0) {
+ if ((res = mp_int_expt_value(radix, prec - lead_0, TEMP(2))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_mul(TEMP(1), TEMP(2), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+ }
+ if ((res = mp_int_div(TEMP(1), MP_DENOM_P(r), TEMP(1), TEMP(2))) != MP_OK)
+ goto CLEANUP;
+
+ /* Now: T1 = significant digits of fractional part;
+ T2 = leftovers, to use for rounding.
+
+ At this point, what we do depends on the rounding mode. The default is
+ MP_ROUND_DOWN, for which everything is as it should be already.
+ */
+ switch (round) {
+ int cmp;
+
+ case MP_ROUND_UP:
+ if (mp_int_compare_zero(TEMP(2)) != 0) {
+ if (prec == 0)
+ res = mp_int_add_value(TEMP(0), 1, TEMP(0));
+ else
+ res = mp_int_add_value(TEMP(1), 1, TEMP(1));
+ }
+ break;
+
+ case MP_ROUND_HALF_UP:
+ case MP_ROUND_HALF_DOWN:
+ if ((res = mp_int_mul_pow2(TEMP(2), 1, TEMP(2))) != MP_OK)
+ goto CLEANUP;
+
+ cmp = mp_int_compare(TEMP(2), MP_DENOM_P(r));
+
+ if (round == MP_ROUND_HALF_UP)
+ cmp += 1;
+
+ if (cmp > 0) {
+ if (prec == 0)
+ res = mp_int_add_value(TEMP(0), 1, TEMP(0));
+ else
+ res = mp_int_add_value(TEMP(1), 1, TEMP(1));
+ }
+ break;
+
+ case MP_ROUND_DOWN:
+ break; /* No action required */
+
+ default:
+ return MP_BADARG; /* Invalid rounding specifier */
+ }
+
+ /* The sign of the output should be the sign of the numerator, but if all the
+ displayed digits will be zero due to the precision, a negative shouldn't
+ be shown. */
+ if (MP_SIGN(MP_NUMER_P(r)) == MP_NEG &&
+ (mp_int_compare_zero(TEMP(0)) != 0 ||
+ mp_int_compare_zero(TEMP(1)) != 0)) {
+ *start++ = '-';
+ left -= 1;
+ }
+
+ if ((res = mp_int_to_string(TEMP(0), radix, start, left)) != MP_OK)
+ goto CLEANUP;
+
+ len = strlen(start);
+ start += len;
+ left -= len;
+
+ if (prec == 0)
+ goto CLEANUP;
+
+ *start++ = '.';
+ left -= 1;
+
+ if (left < prec + 1) {
+ res = MP_TRUNC;
+ goto CLEANUP;
+ }
+
+ memset(start, '0', lead_0 - 1);
+ left -= lead_0;
+ start += lead_0 - 1;
+
+ res = mp_int_to_string(TEMP(1), radix, start, left);
+
+ CLEANUP:
+ while (--last >= 0)
+ mp_int_clear(TEMP(last));
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_string_len(r, radix) */
+
+mp_result mp_rat_string_len(mp_rat r, mp_size radix)
+{
+ mp_result n_len, d_len = 0;
+
+ n_len = mp_int_string_len(MP_NUMER_P(r), radix);
+
+ if (mp_int_compare_zero(MP_NUMER_P(r)) != 0)
+ d_len = mp_int_string_len(MP_DENOM_P(r), radix);
+
+ /* Though simplistic, this formula is correct. Space for the sign flag is
+ included in n_len, and the space for the NUL that is counted in n_len
+ counts for the separator here. The space for the NUL counted in d_len
+ counts for the final terminator here. */
+
+ return n_len + d_len;
+
+}
+
+/* }}} */
+
+/* {{{ mp_rat_decimal_len(r, radix, prec) */
+
+mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec)
+{
+ int z_len, f_len;
+
+ z_len = mp_int_string_len(MP_NUMER_P(r), radix);
+
+ if (prec == 0)
+ f_len = 1; /* terminator only */
+ else
+ f_len = 1 + prec + 1; /* decimal point, digits, terminator */
+
+ return z_len + f_len;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_read_string(r, radix, *str) */
+
+mp_result mp_rat_read_string(mp_rat r, mp_size radix, const char *str)
+{
+ return mp_rat_read_cstring(r, radix, str, NULL);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_read_cstring(r, radix, *str, **end) */
+
+mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, const char *str,
+ char **end)
+{
+ mp_result res;
+ char *endp;
+
+ if ((res = mp_int_read_cstring(MP_NUMER_P(r), radix, str, &endp)) != MP_OK &&
+ (res != MP_TRUNC))
+ return res;
+
+ /* Skip whitespace between numerator and (possible) separator */
+ while (isspace((unsigned char) *endp))
+ ++endp;
+
+ /* If there is no separator, we will stop reading at this point. */
+ if (*endp != '/') {
+ mp_int_set_value(MP_DENOM_P(r), 1);
+ if (end != NULL)
+ *end = endp;
+ return res;
+ }
+
+ ++endp; /* skip separator */
+ if ((res = mp_int_read_cstring(MP_DENOM_P(r), radix, endp, end)) != MP_OK)
+ return res;
+
+ /* Make sure the value is well-defined */
+ if (mp_int_compare_zero(MP_DENOM_P(r)) == 0)
+ return MP_UNDEF;
+
+ /* Reduce to lowest terms */
+ return s_rat_reduce(r);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_read_ustring(r, radix, *str, **end) */
+
+/* Read a string and figure out what format it's in. The radix may be supplied
+ as zero to use "default" behaviour.
+
+ This function will accept either a/b notation or decimal notation.
+ */
+mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, const char *str,
+ char **end)
+{
+ char *endp;
+ mp_result res;
+
+ if (radix == 0)
+ radix = 10; /* default to decimal input */
+
+ if ((res = mp_rat_read_cstring(r, radix, str, &endp)) != MP_OK) {
+ if (res == MP_TRUNC) {
+ if (*endp == '.')
+ res = mp_rat_read_cdecimal(r, radix, str, &endp);
+ }
+ else
+ return res;
+ }
+
+ if (end != NULL)
+ *end = endp;
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ mp_rat_read_decimal(r, radix, *str) */
+
+mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, const char *str)
+{
+ return mp_rat_read_cdecimal(r, radix, str, NULL);
+}
+
+/* }}} */
+
+/* {{{ mp_rat_read_cdecimal(r, radix, *str, **end) */
+
+mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, const char *str,
+ char **end)
+{
+ mp_result res;
+ mp_sign osign;
+ char *endp;
+
+ while (isspace((unsigned char) *str))
+ ++str;
+
+ switch (*str) {
+ case '-':
+ osign = MP_NEG;
+ break;
+ default:
+ osign = MP_ZPOS;
+ }
+
+ if ((res = mp_int_read_cstring(MP_NUMER_P(r), radix, str, &endp)) != MP_OK &&
+ (res != MP_TRUNC))
+ return res;
+
+ /* This needs to be here. */
+ (void) mp_int_set_value(MP_DENOM_P(r), 1);
+
+ if (*endp != '.') {
+ if (end != NULL)
+ *end = endp;
+ return res;
+ }
+
+ /* If the character following the decimal point is whitespace or a sign flag,
+ we will consider this a truncated value. This special case is because
+ mp_int_read_string() will consider whitespace or sign flags to be valid
+ starting characters for a value, and we do not want them following the
+ decimal point.
+
+ Once we have done this check, it is safe to read in the value of the
+ fractional piece as a regular old integer.
+ */
+ ++endp;
+ if (*endp == '\0') {
+ if (end != NULL)
+ *end = endp;
+ return MP_OK;
+ }
+ else if(isspace((unsigned char) *endp) || *endp == '-' || *endp == '+') {
+ return MP_TRUNC;
+ }
+ else {
+ mpz_t frac;
+ mp_result save_res;
+ char *save = endp;
+ int num_lz = 0;
+
+ /* Make a temporary to hold the part after the decimal point. */
+ if ((res = mp_int_init(&frac)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_read_cstring(&frac, radix, endp, &endp)) != MP_OK &&
+ (res != MP_TRUNC))
+ goto CLEANUP;
+
+ /* Save this response for later. */
+ save_res = res;
+
+ if (mp_int_compare_zero(&frac) == 0)
+ goto FINISHED;
+
+ /* Discard trailing zeroes (somewhat inefficiently) */
+ while (mp_int_divisible_value(&frac, radix))
+ if ((res = mp_int_div_value(&frac, radix, &frac, NULL)) != MP_OK)
+ goto CLEANUP;
+
+ /* Count leading zeros after the decimal point */
+ while (save[num_lz] == '0')
+ ++num_lz;
+
+ /* Find the least power of the radix that is at least as large as the
+ significant value of the fractional part, ignoring leading zeroes. */
+ (void) mp_int_set_value(MP_DENOM_P(r), radix);
+
+ while (mp_int_compare(MP_DENOM_P(r), &frac) < 0) {
+ if ((res = mp_int_mul_value(MP_DENOM_P(r), radix, MP_DENOM_P(r))) != MP_OK)
+ goto CLEANUP;
+ }
+
+ /* Also shift by enough to account for leading zeroes */
+ while (num_lz > 0) {
+ if ((res = mp_int_mul_value(MP_DENOM_P(r), radix, MP_DENOM_P(r))) != MP_OK)
+ goto CLEANUP;
+
+ --num_lz;
+ }
+
+ /* Having found this power, shift the numerator leftward that many, digits,
+ and add the nonzero significant digits of the fractional part to get the
+ result. */
+ if ((res = mp_int_mul(MP_NUMER_P(r), MP_DENOM_P(r), MP_NUMER_P(r))) != MP_OK)
+ goto CLEANUP;
+
+ { /* This addition needs to be unsigned. */
+ MP_SIGN(MP_NUMER_P(r)) = MP_ZPOS;
+ if ((res = mp_int_add(MP_NUMER_P(r), &frac, MP_NUMER_P(r))) != MP_OK)
+ goto CLEANUP;
+
+ MP_SIGN(MP_NUMER_P(r)) = osign;
+ }
+ if ((res = s_rat_reduce(r)) != MP_OK)
+ goto CLEANUP;
+
+ /* At this point, what we return depends on whether reading the fractional
+ part was truncated or not. That information is saved from when we
+ called mp_int_read_string() above. */
+ FINISHED:
+ res = save_res;
+ if (end != NULL)
+ *end = endp;
+
+ CLEANUP:
+ mp_int_clear(&frac);
+
+ return res;
+ }
+}
+
+/* }}} */
+
+/* Private functions for internal use. Make unchecked assumptions about format
+ and validity of inputs. */
+
+/* {{{ s_rat_reduce(r) */
+
+static mp_result s_rat_reduce(mp_rat r)
+{
+ mpz_t gcd;
+ mp_result res = MP_OK;
+
+ if (mp_int_compare_zero(MP_NUMER_P(r)) == 0) {
+ mp_int_set_value(MP_DENOM_P(r), 1);
+ return MP_OK;
+ }
+
+ /* If the greatest common divisor of the numerator and denominator is greater
+ than 1, divide it out. */
+ if ((res = mp_int_init(&gcd)) != MP_OK)
+ return res;
+
+ if ((res = mp_int_gcd(MP_NUMER_P(r), MP_DENOM_P(r), &gcd)) != MP_OK)
+ goto CLEANUP;
+
+ if (mp_int_compare_value(&gcd, 1) != 0) {
+ if ((res = mp_int_div(MP_NUMER_P(r), &gcd, MP_NUMER_P(r), NULL)) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_div(MP_DENOM_P(r), &gcd, MP_DENOM_P(r), NULL)) != MP_OK)
+ goto CLEANUP;
+ }
+
+ /* Fix up the signs of numerator and denominator */
+ if (MP_SIGN(MP_NUMER_P(r)) == MP_SIGN(MP_DENOM_P(r)))
+ MP_SIGN(MP_NUMER_P(r)) = MP_SIGN(MP_DENOM_P(r)) = MP_ZPOS;
+ else {
+ MP_SIGN(MP_NUMER_P(r)) = MP_NEG;
+ MP_SIGN(MP_DENOM_P(r)) = MP_ZPOS;
+ }
+
+ CLEANUP:
+ mp_int_clear(&gcd);
+
+ return res;
+}
+
+/* }}} */
+
+/* {{{ s_rat_combine(a, b, c, comb_f) */
+
+static mp_result s_rat_combine(mp_rat a, mp_rat b, mp_rat c,
+ mp_result (*comb_f)(mp_int, mp_int, mp_int))
+{
+ mp_result res;
+
+ /* Shortcut when denominators are already common */
+ if (mp_int_compare(MP_DENOM_P(a), MP_DENOM_P(b)) == 0) {
+ if ((res = (comb_f)(MP_NUMER_P(a), MP_NUMER_P(b), MP_NUMER_P(c))) != MP_OK)
+ return res;
+ if ((res = mp_int_copy(MP_DENOM_P(a), MP_DENOM_P(c))) != MP_OK)
+ return res;
+
+ return s_rat_reduce(c);
+ }
+ else {
+ mpz_t temp[2];
+ int last = 0;
+
+ SETUP(mp_int_init_copy(TEMP(last), MP_NUMER_P(a)), last);
+ SETUP(mp_int_init_copy(TEMP(last), MP_NUMER_P(b)), last);
+
+ if ((res = mp_int_mul(TEMP(0), MP_DENOM_P(b), TEMP(0))) != MP_OK)
+ goto CLEANUP;
+ if ((res = mp_int_mul(TEMP(1), MP_DENOM_P(a), TEMP(1))) != MP_OK)
+ goto CLEANUP;
+ if ((res = (comb_f)(TEMP(0), TEMP(1), MP_NUMER_P(c))) != MP_OK)
+ goto CLEANUP;
+
+ res = mp_int_mul(MP_DENOM_P(a), MP_DENOM_P(b), MP_DENOM_P(c));
+
+ CLEANUP:
+ while (--last >= 0)
+ mp_int_clear(TEMP(last));
+
+ if (res == MP_OK)
+ return s_rat_reduce(c);
+ else
+ return res;
+ }
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/imrat.h b/polly/lib/External/isl/imath/imrat.h
new file mode 100644
index 00000000000..a3678a23922
--- /dev/null
+++ b/polly/lib/External/isl/imath/imrat.h
@@ -0,0 +1,124 @@
+/*
+ Name: imrat.h
+ Purpose: Arbitrary precision rational arithmetic routines.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2007 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef IMRAT_H_
+#define IMRAT_H_
+
+#include "imath.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct mpq {
+ mpz_t num; /* Numerator */
+ mpz_t den; /* Denominator, <> 0 */
+} mpq_t, *mp_rat;
+
+#define MP_NUMER_P(Q) (&((Q)->num)) /* Pointer to numerator */
+#define MP_DENOM_P(Q) (&((Q)->den)) /* Pointer to denominator */
+
+/* Rounding constants */
+typedef enum {
+ MP_ROUND_DOWN,
+ MP_ROUND_HALF_UP,
+ MP_ROUND_UP,
+ MP_ROUND_HALF_DOWN
+} mp_round_mode;
+
+mp_result mp_rat_init(mp_rat r);
+mp_rat mp_rat_alloc(void);
+mp_result mp_rat_reduce(mp_rat r);
+mp_result mp_rat_init_size(mp_rat r, mp_size n_prec, mp_size d_prec);
+mp_result mp_rat_init_copy(mp_rat r, mp_rat old);
+mp_result mp_rat_set_value(mp_rat r, mp_small numer, mp_small denom);
+mp_result mp_rat_set_uvalue(mp_rat r, mp_usmall numer, mp_usmall denom);
+void mp_rat_clear(mp_rat r);
+void mp_rat_free(mp_rat r);
+mp_result mp_rat_numer(mp_rat r, mp_int z); /* z = num(r) */
+mp_int mp_rat_numer_ref(mp_rat r); /* &num(r) */
+mp_result mp_rat_denom(mp_rat r, mp_int z); /* z = den(r) */
+mp_int mp_rat_denom_ref(mp_rat r); /* &den(r) */
+mp_sign mp_rat_sign(mp_rat r);
+
+mp_result mp_rat_copy(mp_rat a, mp_rat c); /* c = a */
+void mp_rat_zero(mp_rat r); /* r = 0 */
+mp_result mp_rat_abs(mp_rat a, mp_rat c); /* c = |a| */
+mp_result mp_rat_neg(mp_rat a, mp_rat c); /* c = -a */
+mp_result mp_rat_recip(mp_rat a, mp_rat c); /* c = 1 / a */
+mp_result mp_rat_add(mp_rat a, mp_rat b, mp_rat c); /* c = a + b */
+mp_result mp_rat_sub(mp_rat a, mp_rat b, mp_rat c); /* c = a - b */
+mp_result mp_rat_mul(mp_rat a, mp_rat b, mp_rat c); /* c = a * b */
+mp_result mp_rat_div(mp_rat a, mp_rat b, mp_rat c); /* c = a / b */
+
+mp_result mp_rat_add_int(mp_rat a, mp_int b, mp_rat c); /* c = a + b */
+mp_result mp_rat_sub_int(mp_rat a, mp_int b, mp_rat c); /* c = a - b */
+mp_result mp_rat_mul_int(mp_rat a, mp_int b, mp_rat c); /* c = a * b */
+mp_result mp_rat_div_int(mp_rat a, mp_int b, mp_rat c); /* c = a / b */
+mp_result mp_rat_expt(mp_rat a, mp_small b, mp_rat c); /* c = a ^ b */
+
+int mp_rat_compare(mp_rat a, mp_rat b); /* a <=> b */
+int mp_rat_compare_unsigned(mp_rat a, mp_rat b); /* |a| <=> |b| */
+int mp_rat_compare_zero(mp_rat r); /* r <=> 0 */
+int mp_rat_compare_value(mp_rat r, mp_small n, mp_small d); /* r <=> n/d */
+int mp_rat_is_integer(mp_rat r);
+
+/* Convert to integers, if representable (returns MP_RANGE if not). */
+mp_result mp_rat_to_ints(mp_rat r, mp_small *num, mp_small *den);
+
+/* Convert to nul-terminated string with the specified radix, writing
+ at most limit characters including the nul terminator. */
+mp_result mp_rat_to_string(mp_rat r, mp_size radix, char *str, int limit);
+
+/* Convert to decimal format in the specified radix and precision,
+ writing at most limit characters including a nul terminator. */
+mp_result mp_rat_to_decimal(mp_rat r, mp_size radix, mp_size prec,
+ mp_round_mode round, char *str, int limit);
+
+/* Return the number of characters required to represent r in the given
+ radix. May over-estimate. */
+mp_result mp_rat_string_len(mp_rat r, mp_size radix);
+
+/* Return the number of characters required to represent r in decimal
+ format with the given radix and precision. May over-estimate. */
+mp_result mp_rat_decimal_len(mp_rat r, mp_size radix, mp_size prec);
+
+/* Read zero-terminated string into r */
+mp_result mp_rat_read_string(mp_rat r, mp_size radix, const char *str);
+mp_result mp_rat_read_cstring(mp_rat r, mp_size radix, const char *str,
+ char **end);
+mp_result mp_rat_read_ustring(mp_rat r, mp_size radix, const char *str,
+ char **end);
+
+/* Read zero-terminated string in decimal format into r */
+mp_result mp_rat_read_decimal(mp_rat r, mp_size radix, const char *str);
+mp_result mp_rat_read_cdecimal(mp_rat r, mp_size radix, const char *str,
+ char **end);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* IMRAT_H_ */
diff --git a/polly/lib/External/isl/imath/imtest.c b/polly/lib/External/isl/imath/imtest.c
new file mode 100644
index 00000000000..804034f51e6
--- /dev/null
+++ b/polly/lib/External/isl/imath/imtest.c
@@ -0,0 +1,474 @@
+/*
+ Name: imtest.c
+ Purpose: Test driver for imath library.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+
+ Reads tests from input files or standard input, and runs them. Tests have
+ the form:
+
+ code:inputs:outputs
+
+ The 'code' is a string identifying the test to be performed. The inputs and
+ outputs are comma-separated sequences of values. The format of each input
+ is:
+
+ 1005 number in decimal notation (signs ok)
+ #x-C0E number in hexadecimal notation
+ #b1011 number in binary notation
+ #o37750 number in octal notation
+ =k use register k for this input
+
+ For rational tests, the following syntax is also legal:
+ @5.33 use decimal notation (for rationals only)
+ may be combined with radix notation, e.g. #x@A0.5C
+
+ Each output is a string representing the value to which the corresponding
+ result is compared in order to pass the test. By default, tests are expected
+ to succeed (i.e., return MP_OK). To specify an alternate return value, use
+ the notation $RESULT, where RESULT is the name of an error (e.g., MP_MEMORY,
+ MP_UNDEF, etc.) or a numeric result denoted $#number (e.g., $#-5).
+
+ Results are written to standard output in the following formats:
+
+ line<tab>number<tab>result<eoln>
+ line<tab>number<tab>result<tab>message<eoln>
+
+ The number is the number of the test in the input (starting from 1). The
+ result is a textual description of the result code returned by the operation
+ being tested.
+
+ Note: There is currently a fixed limit on the length of lines by this test
+ ---- driver. You can increase it if you wish, but the code doesn't check;
+ lines over the length are truncated (split).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "imath.h"
+#include "imdrover.h"
+
+#ifdef LINE_MAX
+#undef LINE_MAX
+#endif
+
+#define LINE_MAX 4096
+
+typedef struct {
+ char *code;
+ int num_inputs;
+ int num_outputs;
+ test_f call;
+} test_t;
+
+test_t g_tests[] = { /* What it does... */
+ { "initu", 2, 1, test_init}, /* r0 = uv(r1) */
+ { "initv", 2, 1, test_init}, /* r0 = v(r1) */
+ { "setu", 2, 1, test_set}, /* r0 = uv(r1) */
+ { "setv", 2, 1, test_set}, /* r0 = v(r1) */
+ { "neg", 2, 1, test_neg }, /* r1 = -r0 */
+ { "abs", 2, 1, test_abs }, /* r1 = |r0| */
+ { "add", 3, 1, test_add }, /* r3 = r1 + r2 */
+ { "addv", 3, 1, test_add }, /* r3 = r1 + v(r2) */
+ { "sub", 3, 1, test_sub }, /* r3 = r1 - r2 */
+ { "subv", 3, 1, test_sub }, /* r3 = r1 - v(r2) */
+ { "mul", 3, 1, test_mul }, /* r3 = r1 * r2 */
+ { "mulp2", 3, 1, test_mulp2 }, /* r3 = r1 * 2^v(r2) */
+ { "mulv", 3, 1, test_mulv }, /* r3 = r1 * v(r2) */
+ { "sqr", 2, 1, test_sqr }, /* r2 = r1 * r1 */
+ { "div", 4, 2, test_div }, /* r2 = r1 / r2, r3 = r1 % r2 */
+ { "divp2", 4, 2, test_divp2 }, /* r2 = r1 / 2^v(r2),r3 = r1 % 2^v(r2)*/
+ { "divv", 3, 2, test_divv }, /* r2 = r1 / v(r2), r3 = r1 % v(r2) */
+ { "expt", 3, 1, test_expt }, /* r3 = r1 ^ v(r2) */
+ { "exptv", 3, 1, test_exptv }, /* r3 = v(r1) ^ v(r2) */
+ { "exptf", 3, 1, test_exptf }, /* r3 = r1 ^ r2 */
+ { "mod", 3, 1, test_mod }, /* r3 = r1 % r2 */
+ { "gcd", 3, 1, test_gcd }, /* r3 = gcd(r1, r2) */
+ { "egcd", 5, 3, test_egcd }, /* r3 = gcd(r1, r2) = r1*r4 + r2*r5 */
+ { "lcm", 3, 1, test_lcm }, /* r3 = lcm(r1, r2) */
+ { "sqrt", 2, 1, test_sqrt }, /* r2 = sqrt(r1) */
+ { "root", 3, 1, test_root }, /* r3 = r1^(1/v(r2)) */
+ { "invmod", 3, 1, test_invmod }, /* r3 = r1^-1 mod r2 */
+ { "emod", 4, 1, test_exptmod }, /* r4 = r1^r2 mod r3 */
+ { "emodev", 4, 1, test_exptmod_ev }, /* r4 = r1^v(r2) mod r3 */
+ { "emodbv", 4, 1, test_exptmod_bv }, /* r4 = v(r1)^r2 mod r3 */
+ { "cmp", 2, 1, test_comp }, /* rtn = compare(r1, r2) */
+ { "cmpu", 2, 1, test_ucomp }, /* rtn = compare(|r1|, |r2|) */
+ { "cmpz", 1, 1, test_zcomp }, /* rtn = compare(r1, 0) */
+ { "cmpv", 2, 1, test_vcomp }, /* rtn = compare(r1, v(r2)) */
+ { "cmpuv", 2, 1, test_uvcomp }, /* rtn = compare(r1, v(r2)) */
+ { "tostr", 2, 1, test_tostr }, /* r1: value, r2: radix, o1: result */
+ { "tobin", 1, 1, test_tobin }, /* r1: value, o1: result binary */
+ { "readbin", 1, 1, test_read_binary },/* r1: 2's comp, o1: result value */
+ { "to-uns", 1, 1, test_to_uns }, /* r1: value, o1: result binary */
+ { "readuns", 1, 1, test_read_uns }, /* r1: unsigned, o1: result value */
+ { "to-int", 1, 1, test_to_int }, /* r1: value, o1: result */
+ { "to-uint", 1, 1, test_to_uint }, /* r1: value, o1: result */
+ { "meta", -1, -1, test_meta },
+ { "qneg", 2, 1, test_qneg }, /* r2 = -r1 */
+ { "qrecip", 2, 1, test_qrecip }, /* r2 = 1 / r1 */
+ { "qabs", 2, 1, test_qabs }, /* r2 = |r1| */
+ { "qadd", 3, 1, test_qadd }, /* r3 = r1 + r2 */
+ { "qsub", 3, 1, test_qsub }, /* r3 = r1 - r2 */
+ { "qmul", 3, 1, test_qmul }, /* r3 = r1 * r2 */
+ { "qdiv", 3, 1, test_qdiv }, /* r3 = r1 / r2 */
+ { "qaddz", 3, 1, test_qaddz }, /* r3 = r1 + r2 */
+ { "qsubz", 3, 1, test_qsubz }, /* r3 = r1 - r2 */
+ { "qmulz", 3, 1, test_qmulz }, /* r3 = r1 * r2 */
+ { "qdivz", 3, 1, test_qdivz }, /* r3 = r1 / r2 */
+ { "qexpt", 3, 1, test_qexpt }, /* r3 = r1 ^ v(r2) */
+ { "qtostr", 2, 1, test_qtostr }, /* r1: value, r2: radix; o1: result */
+ { "qtodec", 4, 1, test_qtodec }, /* r1: val, r2: rdx, r3: prec,
+ r4: rounding mode; o1: res */
+ { "qrdec", 2, 1, test_qrdec }, /* r1: dec, r2: rdx; o1: result value */
+ { NULL, 0, 0, NULL } /* end of list marker */
+};
+
+char g_line[LINE_MAX];
+
+extern mp_result imath_errno;
+extern char *imath_errmsg;
+
+const char *g_imath_strerr[] = {
+ "MP_OK", "MP_TRUE", "MP_MEMORY", "MP_RANGE",
+ "MP_UNDEF", "MP_TRUNC", "MP_BADARG"
+};
+
+int process_file(FILE *ifp, FILE *ofp);
+int read_line(FILE *ifp, char *line, int limit);
+void trim_line(char *line);
+int is_blank(char *line);
+int parse_line(char *line, testspec_t *t);
+int count_fields(char *line, int delim);
+void parse_fields(char *line, int delim, char **start);
+int run_test(int test_num, testspec_t *t, FILE *ofp);
+void free_test(testspec_t *t);
+int find_test(char *code, test_t *info);
+char *error_string(mp_result res);
+
+int main(int argc, char *argv[])
+{
+ int exit_status = 0;
+
+ init_testing();
+
+ if (argc == 1) {
+ process_file(stdin, stdout);
+ }
+ else {
+ FILE *ifp;
+ int i;
+
+ for (i = 1; i < argc; ++i) {
+ if (strcmp(argv[i], "-") == 0) {
+ ifp = stdin;
+ printf("# [stdin]\n");
+ }
+ else if ((ifp = fopen(argv[i], "r")) == NULL) {
+ fprintf(stderr, "Cannot open '%s': %s\n",
+ argv[i], strerror(errno));
+ return 1;
+ }
+ else {
+ printf("# %s\n", argv[i]);
+ }
+
+ if (process_file(ifp, stdout) != 0)
+ exit_status = 1;
+
+ fclose(ifp);
+ }
+ }
+ return exit_status;
+}
+
+/* {{{ process_file(ifp, ofp) */
+
+int process_file(FILE *ifp, FILE *ofp)
+{
+ int res, line_num, test_num = 0, num_failed = 0, num_bogus = 0;
+ clock_t start, finish;
+ testspec_t t;
+
+ start = clock();
+ while ((line_num = read_line(ifp, g_line, LINE_MAX)) != 0) {
+ if (parse_line(g_line, &t)) {
+ t.line = line_num;
+ if ((res = run_test(++test_num, &t, ofp)) < 0)
+ ++num_bogus;
+ else if (!res)
+ ++num_failed;
+
+ free_test(&t);
+ }
+ else {
+ fprintf(stderr, "Line %d: Incorrect input syntax.\n", line_num);
+ }
+ }
+ finish = clock();
+
+ fprintf(ofp, "# %d tests: %d passed, %d failed, %d errors. (%.2f seconds)\n",
+ test_num, (test_num - num_failed - num_bogus), num_failed, num_bogus,
+ ((double)(finish - start) / CLOCKS_PER_SEC));
+
+ return num_failed;
+}
+
+/* }}} */
+
+/* {{{ read_line(ifp, line, limit) */
+
+int read_line(FILE *ifp, char *line, int limit)
+{
+ static FILE *current_fp = NULL;
+ static int current_line = 0;
+
+ if (ifp != current_fp) {
+ current_fp = ifp;
+ current_line = 0;
+ }
+
+ do {
+ if (fgets(line, limit, ifp) == NULL)
+ return 0;
+
+ ++current_line;
+ } while (is_blank(line));
+
+ trim_line(line);
+ return current_line;
+}
+
+/* }}} */
+
+/* {{{ trim_line(line) */
+
+void trim_line(char *line)
+{
+ int len;
+ char *fnw = line;
+
+ /* Remove leading whitespace */
+ while (isspace((unsigned char) *fnw))
+ ++fnw;
+
+ len = strlen(fnw);
+ memmove(line, fnw, len);
+
+ /* Remove trailing whitespace (including linefeeds) */
+ fnw = line + len - 1;
+ while (fnw >= line && isspace((unsigned char) *fnw))
+ *fnw-- = '\0';
+}
+
+/* }}} */
+
+/* {{{ is_blank(line) */
+
+int is_blank(char *line)
+{
+ while (*line && *line != '#' && isspace((unsigned char) *line))
+ ++line;
+
+ return *line == '\0' || *line == '#';
+}
+
+/* }}} */
+
+/* {{{ parse_line(line, t) */
+
+int parse_line(char *line, testspec_t *t)
+{
+ char *code_brk, *in_brk;
+ int num_fields;
+
+ if ((code_brk = strchr(line, ':')) == NULL)
+ return 0;
+ if ((in_brk = strchr(code_brk + 1, ':')) == NULL)
+ return 0;
+
+ *code_brk = '\0';
+ t->code = line;
+ *in_brk = '\0';
+
+ num_fields = count_fields(code_brk + 1, ',');
+ t->num_inputs = num_fields;
+
+ num_fields = count_fields(in_brk + 1, ',');
+ t->num_outputs = num_fields;
+
+ if (t->num_inputs > 0) {
+ t->input = calloc(t->num_inputs, sizeof(char *));
+ parse_fields(code_brk + 1, ',', t->input);
+ }
+ if (t->num_outputs > 0) {
+ t->output = calloc(t->num_outputs, sizeof(char *));
+ parse_fields(in_brk + 1, ',', t->output);
+ }
+ return 1;
+}
+
+/* }}} */
+
+/* {{{ count_fields(line, delim) */
+
+int count_fields(char *line, int delim)
+{
+ int count = 1;
+
+ if (*line == '\0')
+ return 0;
+
+ while (*line) {
+ if (*line == (char)delim && *(line+1) != '\0')
+ ++count;
+ ++line;
+ }
+ return count;
+}
+
+/* }}} */
+
+/* {{{ parse_fields(line, delim, start) */
+
+void parse_fields(char *line, int delim, char **start)
+{
+ int pos = 0;
+
+ start[pos++] = line;
+ while ((line = strchr(line, delim)) != NULL) {
+ *line++ = '\0';
+ start[pos++] = line;
+ }
+}
+
+/* }}} */
+
+/* {{{ run_test(test_num, t, ofp) */
+
+int run_test(int test_num, testspec_t *t, FILE *ofp)
+{
+ test_t info;
+
+ /* Look up and reality check test parameters */
+ if (find_test(t->code, &info) < 0) {
+ fprintf(stderr, "Line %d: Test code '%s' is unknown.\n",
+ t->line, t->code);
+ return -1;
+ }
+ else {
+ int errs = 0;
+
+ if (info.num_inputs >= 0 && t->num_inputs != info.num_inputs) {
+ fprintf(stderr,
+ "Line %d: Wrong number of inputs to %s (want %d, have %d)\n",
+ t->line, t->code, info.num_inputs, t->num_inputs);
+ ++errs;
+ }
+ if (info.num_outputs >= 0 && t->num_outputs != info.num_outputs) {
+ fprintf(stderr,
+ "Line %d: Wrong number of outputs to %s (want %d, have %d)\n",
+ t->line, t->code, info.num_outputs, t->num_outputs);
+ ++errs;
+ }
+ if (errs) {
+ fprintf(stderr, "Line %d: %d error(s), skipping this test.\n",
+ t->line, errs);
+ return -1;
+ }
+ }
+
+ /* If return value is true, just print a generic OK message;
+ otherwise, it is assumed that imath_errno has been set to
+ a value indicating the problem. */
+ if ((info.call)(t, ofp)) {
+ fprintf(ofp, "%d\t%d\tOK\n", t->line, test_num);
+ return 1;
+ }
+ else if(imath_errno >= MP_BADARG) {
+ fprintf(ofp, "%d\t%d\t%s\n",
+ t->line, test_num, error_string(imath_errno));
+ }
+ else {
+ fprintf(ofp, "%d\t%d\tFAILED\t%s\n",
+ t->line, test_num, imath_errmsg);
+ }
+ return 0;
+}
+
+/* }}} */
+
+/* {{{ find_test(code, info) */
+
+int find_test(char *code, test_t *info)
+{
+ int i = 0;
+
+ while (g_tests[i].code != NULL) {
+ if (strcmp(g_tests[i].code, code) == 0) {
+ *info = g_tests[i];
+ return i;
+ }
+ ++i;
+ }
+ return -1;
+}
+
+/* }}} */
+
+/* {{{ free_test(*t) */
+
+void free_test(testspec_t *t)
+{
+ assert(t != NULL);
+
+ if (t->input != NULL) {
+ free(t->input);
+ t->input = NULL;
+ }
+ if (t->output != NULL) {
+ free(t->output);
+ t->output = NULL;
+ }
+}
+
+/* }}} */
+
+/* {{{ error_string(res) */
+
+char *error_string(mp_result res)
+{
+ int v = abs(res);
+
+ return (char *)g_imath_strerr[v];
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/imtimer.c b/polly/lib/External/isl/imath/imtimer.c
new file mode 100644
index 00000000000..f5a0ecf5641
--- /dev/null
+++ b/polly/lib/External/isl/imath/imtimer.c
@@ -0,0 +1,259 @@
+/*
+ Name: imtimer.c
+ Purpose: Timing tests for the imath library.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+
+#include <unistd.h>
+
+#include "imath.h"
+
+extern mp_size multiply_threshold; /* global in imath.c */
+extern mp_size default_precision; /* global in imath.c */
+
+double clocks_to_seconds(clock_t start, clock_t end);
+double get_multiply_time(int nt, int prec);
+double get_exptmod_time(int nt, int prec);
+mp_int alloc_values(int nt, int prec);
+void randomize_values(mp_int values, int nt, int prec);
+void release_values(mp_int values, int nt);
+void mp_int_random(mp_int z, int prec);
+
+const int g_mul_factor = 1000;
+
+int main(int argc, char *argv[])
+{
+ int do_mul = 0, do_exp = 0, do_header = 1;
+ int num_tests, precision = default_precision, opt;
+ unsigned int seed = (unsigned int) time(NULL);
+
+ while ((opt = getopt(argc, argv, "ehmnp:s:t:")) != EOF) {
+ switch (opt) {
+ case 'e':
+ do_exp = 1;
+ break;
+ case 'm':
+ do_mul = 1;
+ break;
+ case 'n':
+ do_header = 0;
+ break;
+ case 'p':
+ precision = atoi(optarg);
+ break;
+ case 's':
+ seed = atoi(optarg);
+ break;
+ case 't':
+ multiply_threshold = (mp_size) atoi(optarg);
+ break;
+ default:
+ fprintf(stderr, "Usage: imtimer [options] <num-tests>\n\n"
+ "Options understood:\n"
+ " -e -- test modular exponentiation speed.\n"
+ " -h -- display this help message.\n"
+ " -m -- test multiplication speed.\n"
+ " -n -- no header line.\n"
+ " -p <dig> -- use values with <dig> digits.\n"
+ " -s <rnd> -- set random seed to <rnd>.\n"
+ " -t <dig> -- set recursion threshold to <dig> digits.\n\n");
+ return (opt != 'h');
+ }
+ }
+
+ if (optind >= argc) {
+ fprintf(stderr, "Usage: imtimer [options] <num-tests>\n"
+ "[use \"imtimer -h\" for help with options]\n\n");
+ return 1;
+ }
+ else
+ num_tests = atoi(argv[optind]);
+
+ srand(seed);
+
+ if (num_tests <= 0) {
+ fprintf(stderr, "You must request at least one test.\n");
+ return 1;
+ }
+ if (precision <= 0) {
+ fprintf(stderr, "Precision must be positive.\n");
+ return 1;
+ }
+
+ if (do_header)
+ printf("NUM\tPREC\tBITS\tREC\tRESULT\n");
+ printf("%d\t%d\t%d\t%u", num_tests, precision,
+ (int) (precision * MP_DIGIT_BIT),
+ multiply_threshold);
+
+ if (do_mul) {
+ double m_time = get_multiply_time(num_tests, precision);
+
+ printf("\tMUL %.3f %.3f", m_time, m_time / num_tests);
+ }
+
+ if (do_exp) {
+ double e_time = get_exptmod_time(num_tests, precision);
+
+ printf("\tEXP %.3f %.3f", e_time, e_time / num_tests);
+ }
+ fputc('\n', stdout);
+ fflush(stdout);
+
+ return 0;
+}
+
+/* {{{ clocks_to_seconds(start, end) */
+
+double clocks_to_seconds(clock_t start, clock_t end)
+{
+ return (double)(end - start) / CLOCKS_PER_SEC;
+}
+
+/* }}} */
+
+/* {{{ alloc_values(nt, prec) */
+
+mp_int alloc_values(int nt, int prec)
+{
+ mp_int out = malloc(nt * sizeof(mpz_t));
+ int i;
+
+ if (out == NULL)
+ return NULL;
+
+ for (i = 0; i < nt; ++i) {
+ if (mp_int_init_size(out + i, prec) != MP_OK) {
+ while (--i >= 0)
+ mp_int_clear(out + i);
+ return NULL;
+ }
+ }
+
+ return out;
+}
+
+/* }}} */
+
+/* {{{ randomize_values(values, nt, prec) */
+
+void randomize_values(mp_int values, int nt, int prec)
+{
+ int i;
+
+ for (i = 0; i < nt; ++i)
+ mp_int_random(values + i, prec);
+}
+
+/* }}} */
+
+/* {{{ release_values(values, nt) */
+
+void release_values(mp_int values, int nt)
+{
+ int i;
+
+ for (i = 0; i < nt; ++i)
+ mp_int_clear(values + i);
+
+ free(values);
+}
+
+/* }}} */
+
+/* {{{ get_multiply_time(nt, prec) */
+
+double get_multiply_time(int nt, int prec)
+{
+ clock_t start, end;
+ mp_int values;
+ int i;
+
+ if ((values = alloc_values(3, prec)) == NULL)
+ return 0.0;
+ randomize_values(values, 2, prec);
+
+ start = clock();
+ for (i = 0; i < nt; ++i)
+ mp_int_mul(values, values + 1, values + 2);
+ end = clock();
+
+ release_values(values, 3);
+
+ return clocks_to_seconds(start, end);
+}
+
+/* }}} */
+
+/* {{{ get_exptmod_time(nt, prec) */
+
+double get_exptmod_time(int nt, int prec)
+{
+ clock_t start, end;
+ mp_int values;
+ int i;
+
+ if ((values = alloc_values(4, prec)) == NULL)
+ return 0.0;
+ randomize_values(values, 3, prec);
+
+ start = clock();
+ for (i = 0; i < nt; ++i)
+ mp_int_exptmod(values, values + 1, values + 2, values + 3);
+ end = clock();
+
+ release_values(values, 4);
+
+ return clocks_to_seconds(start, end);
+}
+
+/* }}} */
+
+/* {{{ mp_int_random(z, prec) */
+
+void mp_int_random(mp_int z, int prec)
+{
+ int i;
+
+ if (prec > MP_ALLOC(z))
+ prec = MP_ALLOC(z);
+
+ for (i = 0; i < prec; ++i) {
+ mp_digit d = 0;
+ int j;
+
+ for (j = 0; j < sizeof(d); ++j)
+ d = (d << CHAR_BIT) | (rand() & UCHAR_MAX);
+
+ z->digits[i] = d;
+ }
+ MP_USED(z) = prec;
+}
+
+/* }}} */
diff --git a/polly/lib/External/isl/imath/iprime.c b/polly/lib/External/isl/imath/iprime.c
new file mode 100644
index 00000000000..864eadbac94
--- /dev/null
+++ b/polly/lib/External/isl/imath/iprime.c
@@ -0,0 +1,116 @@
+/*
+ Name: iprime.c
+ Purpose: Pseudoprimality testing routines
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include "iprime.h"
+#include <stdlib.h>
+
+static int s_ptab_size = 168;
+static int s_ptab[] = {
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
+ 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107,
+ 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181,
+ 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263,
+ 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433,
+ 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521,
+ 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613,
+ 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
+ 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
+ 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887,
+ 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997
+};
+
+/* {{{ mp_int_is_prime(z) */
+
+/* Test whether z is likely to be prime:
+ MP_TRUE means it is probably prime
+ MP_FALSE means it is definitely composite
+ */
+mp_result mp_int_is_prime(mp_int z)
+{
+ int i;
+ mp_small rem;
+ mp_result res;
+
+ /* First check for divisibility by small primes; this eliminates a large
+ number of composite candidates quickly
+ */
+ for(i = 0; i < s_ptab_size; ++i) {
+ if((res = mp_int_div_value(z, s_ptab[i], NULL, &rem)) != MP_OK)
+ return res;
+
+ if(rem == 0)
+ return MP_FALSE;
+ }
+
+ /* Now try Fermat's test for several prime witnesses (since we now know from
+ the above that z is not a multiple of any of them)
+ */
+ {
+ mpz_t tmp;
+
+ if((res = mp_int_init(&tmp)) != MP_OK) return res;
+
+ for(i = 0; i < 10 && i < s_ptab_size; ++i) {
+ if((res = mp_int_exptmod_bvalue(s_ptab[i], z, z, &tmp)) != MP_OK)
+ return res;
+
+ if(mp_int_compare_value(&tmp, s_ptab[i]) != 0) {
+ mp_int_clear(&tmp);
+ return MP_FALSE;
+ }
+ }
+
+ mp_int_clear(&tmp);
+ }
+
+ return MP_TRUE;
+}
+
+/* }}} */
+
+/* {{{ mp_int_find_prime(z) */
+
+/* Find the first apparent prime in ascending order from z */
+mp_result mp_int_find_prime(mp_int z)
+{
+ mp_result res;
+
+ if(mp_int_is_even(z) && ((res = mp_int_add_value(z, 1, z)) != MP_OK))
+ return res;
+
+ while((res = mp_int_is_prime(z)) == MP_FALSE) {
+ if((res = mp_int_add_value(z, 2, z)) != MP_OK)
+ break;
+
+ }
+
+ return res;
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/iprime.h b/polly/lib/External/isl/imath/iprime.h
new file mode 100644
index 00000000000..03ea8f9d3cd
--- /dev/null
+++ b/polly/lib/External/isl/imath/iprime.h
@@ -0,0 +1,48 @@
+/*
+ Name: iprime.h
+ Purpose: Pseudoprimality testing routines
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef IPRIME_H_
+#define IPRIME_H_
+
+#include "imath.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Test whether z is likely to be prime
+ MP_YES means it is probably prime
+ MP_NO means it is definitely composite
+ */
+mp_result mp_int_is_prime(mp_int z);
+
+/* Find the first apparent prime in ascending order from z */
+mp_result mp_int_find_prime(mp_int z);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* IPRIME_H_ */
diff --git a/polly/lib/External/isl/imath/pi.c b/polly/lib/External/isl/imath/pi.c
new file mode 100644
index 00000000000..e1d46487b30
--- /dev/null
+++ b/polly/lib/External/isl/imath/pi.c
@@ -0,0 +1,177 @@
+/*
+ Name: pi.c
+ Purpose: Computes digits of the physical constant pi.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Notes:
+ Uses Machin's formula, which should be suitable for a few thousand digits.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "imath.h"
+
+int g_radix = 10; /* use this radix for output */
+
+mp_result arctan(mp_small radix, mp_small mul, mp_small x,
+ mp_small prec, mp_int sum);
+
+char g_buf[4096];
+
+int main(int argc, char *argv[])
+{
+ mp_result res;
+ mpz_t sum1, sum2;
+ int ndigits, out = 0;
+ clock_t start, end;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s <num-digits> [<radix>]\n", argv[0]);
+ return 1;
+ }
+
+ if((ndigits = abs(atoi(argv[1]))) == 0) {
+ fprintf(stderr, "%s: you must request at least 1 digit\n", argv[0]);
+ return 1;
+ } else if(ndigits > MP_DIGIT_MAX) {
+ fprintf(stderr, "%s: you may request at most %u digits\n",
+ argv[0], (unsigned int)MP_DIGIT_MAX);
+ return 1;
+ }
+
+ if(argc > 2) {
+ int radix = atoi(argv[2]);
+
+ if(radix < MP_MIN_RADIX || radix > MP_MAX_RADIX) {
+ fprintf(stderr, "%s: you may only specify a radix between %d and %d\n",
+ argv[0], MP_MIN_RADIX, MP_MAX_RADIX);
+ return 1;
+ }
+ g_radix = radix;
+ }
+
+ mp_int_init(&sum1); mp_int_init(&sum2);
+ start = clock();
+
+ /* sum1 = 16 * arctan(1/5) */
+ if((res = arctan(g_radix, 16, 5, ndigits, &sum1)) != MP_OK) {
+ fprintf(stderr, "%s: error computing arctan: %d\n", argv[0], res);
+ out = 1; goto CLEANUP;
+ }
+
+ /* sum2 = 4 * arctan(1/239) */
+ if((res = arctan(g_radix, 4, 239, ndigits, &sum2)) != MP_OK) {
+ fprintf(stderr, "%s: error computing arctan: %d\n", argv[0], res);
+ out = 1; goto CLEANUP;
+ }
+
+ /* pi = sum1 - sum2 */
+ if((res = mp_int_sub(&sum1, &sum2, &sum1)) != MP_OK) {
+ fprintf(stderr, "%s: error computing pi: %d\n", argv[0], res);
+ out = 1; goto CLEANUP;
+ }
+ end = clock();
+
+ mp_int_to_string(&sum1, g_radix, g_buf, sizeof(g_buf));
+ printf("%c.%s\n", g_buf[0], g_buf + 1);
+
+ fprintf(stderr, "Computation took %.2f sec.\n",
+ (double)(end - start) / CLOCKS_PER_SEC);
+
+ CLEANUP:
+ mp_int_clear(&sum1);
+ mp_int_clear(&sum2);
+
+ return out;
+}
+
+/* {{{ arctan(radix, mul, x, prec, sum) */
+
+/*
+ Compute mul * atan(1/x) to prec digits of precision, and store the
+ result in sum.
+
+ Computes atan(1/x) using the formula:
+
+ 1 1 1 1
+ atan(1/x) = --- - ---- + ---- - ---- + ...
+ x 3x^3 5x^5 7x^7
+
+ */
+mp_result arctan(mp_small radix, mp_small mul, mp_small x,
+ mp_small prec, mp_int sum)
+{
+ mpz_t t, v;
+ mp_result res;
+ mp_small rem, sign = 1, coeff = 1;
+
+ mp_int_init(&t);
+ mp_int_init(&v);
+ ++prec;
+
+ /* Compute mul * radix^prec * x
+ The initial multiplication by x saves a special case in the loop for
+ the first term of the series.
+ */
+ if((res = mp_int_expt_value(radix, prec, &t)) != MP_OK ||
+ (res = mp_int_mul_value(&t, mul, &t)) != MP_OK ||
+ (res = mp_int_mul_value(&t, x, &t)) != MP_OK)
+ goto CLEANUP;
+
+ x *= x; /* assumes x <= sqrt(MP_SMALL_MAX) */
+ mp_int_zero(sum);
+
+ do {
+ if((res = mp_int_div_value(&t, x, &t, &rem)) != MP_OK)
+ goto CLEANUP;
+
+ if((res = mp_int_div_value(&t, coeff, &v, &rem)) != MP_OK)
+ goto CLEANUP;
+
+ /* Add or subtract the result depending on the current sign (1 = add) */
+ if(sign > 0)
+ res = mp_int_add(sum, &v, sum);
+ else
+ res = mp_int_sub(sum, &v, sum);
+
+ if(res != MP_OK) goto CLEANUP;
+ sign = -sign;
+ coeff += 2;
+
+ } while(mp_int_compare_zero(&t) != 0);
+
+ res = mp_int_div_value(sum, radix, sum, NULL);
+
+ CLEANUP:
+ mp_int_clear(&v);
+ mp_int_clear(&t);
+
+ return res;
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/rsamath.c b/polly/lib/External/isl/imath/rsamath.c
new file mode 100644
index 00000000000..ff9aa1898bb
--- /dev/null
+++ b/polly/lib/External/isl/imath/rsamath.c
@@ -0,0 +1,203 @@
+/*
+ Name: rsamath.c
+ Purpose: Implements part of PKCS#1, v. 2.1, June 14, 2002 (RSA Labs)
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include "rsamath.h"
+
+#include <string.h>
+#include <limits.h>
+
+static mp_result s_rsa_transform(mp_int msg, mp_int exp,
+ mp_int mod, mp_int out);
+
+/* {{{ rsa_i2osp(z, out, len) */
+
+/* Convert integer to octet string, per PKCS#1 v.2.1 */
+mp_result rsa_i2osp(mp_int z, unsigned char *out, int len)
+{
+ int excess_len = mp_int_binary_len(z);
+
+ if(excess_len < len)
+ return MP_RANGE;
+
+ memset(out, 0, len);
+
+ excess_len -= len;
+ mp_int_to_binary(z, out + excess_len, len);
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ rsa_os2ip(z, in, len) */
+
+/* Convert octet string to integer, per PKCS#1 v.2.1 */
+mp_result rsa_os2ip(mp_int z, unsigned char *in, int len)
+{
+ return mp_int_read_binary(z, in, len);
+}
+
+/* }}} */
+
+/* {{{ rsa_rsaep(msg, exp, mod, cipher) */
+
+/* Primitive RSA encryption operation */
+mp_result rsa_rsaep(mp_int msg, mp_int exp, mp_int mod, mp_int cipher)
+{
+ return s_rsa_transform(msg, exp, mod, cipher);
+}
+
+/* }}} */
+
+/* {{{ rsa_rsadp(cipher, exp, mod, msg) */
+
+/* Primitive RSA decryption operation */
+mp_result rsa_rsadp(mp_int cipher, mp_int exp, mp_int mod, mp_int msg)
+{
+ return s_rsa_transform(cipher, exp, mod, msg);
+}
+
+/* }}} */
+
+/* {{{ rsa_rsasp(msg, exp, mod, signature) */
+
+/* Primitive RSA signing operation */
+mp_result rsa_rsasp(mp_int msg, mp_int exp, mp_int mod, mp_int signature)
+{
+ return s_rsa_transform(msg, exp, mod, signature);
+}
+
+/* }}} */
+
+/* {{{ rsa_rsavp(signature, exp, mod, msg) */
+
+/* Primitive RSA verification operation */
+mp_result rsa_rsavp(mp_int signature, mp_int exp, mp_int mod, mp_int msg)
+{
+ return s_rsa_transform(signature, exp, mod, msg);
+}
+
+/* }}} */
+
+/* {{{ rsa_max_message_len(mod) */
+
+/* Compute the maximum length in bytes a message can have using PKCS#1
+ v.1.5 encoding with the given modulus */
+int rsa_max_message_len(mp_int mod)
+{
+ int num_bits = mp_int_count_bits(mod);
+ int num_bytes = num_bits / CHAR_BIT;
+
+ if(num_bytes < 11)
+ return 0; /* at least eleven bytes are required for padding */
+ else
+ return num_bytes - 11;
+}
+
+/* }}} */
+
+/* {{{ rsa_pkcs1v15_encode(buf, msg_len, buf_len, tag, filler) */
+
+mp_result rsa_pkcs1v15_encode(unsigned char *buf, int msg_len,
+ int buf_len, int tag, random_f filler)
+{
+ int pad_len, msg_start;
+
+ /* Make sure there is enough space for the encoded output */
+ if(msg_len > (buf_len - 11))
+ return MP_RANGE;
+
+ msg_start = buf_len - msg_len;
+ pad_len = msg_start - 3;
+
+ /* Move message to top of buffer -- these might overlap, so we rely
+ on the semantics of memmove() here */
+ memmove(buf + msg_start, buf, msg_len);
+
+ /* Set initial bytes as required by the specification */
+ buf[0] = 0x00;
+ buf[1] = (unsigned char)tag;
+
+ /* Fill with random padding. We'll just assume the filler function
+ does the right thing and only writes the requested number of
+ nonzero bytes */
+ (filler)(buf + 2, pad_len);
+
+ /* Write separator between pad and message body */
+ buf[msg_start - 1] = 0x00;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ rsa_pkcs1v15_decode(buf, buf_len, *msg_len) */
+
+mp_result rsa_pkcs1v15_decode(unsigned char *buf, int buf_len,
+ int tag, int *msg_len)
+{
+ int pad_len = 0, data_len, data_start, i;
+
+ /* Make sure the buffer is syntactically valid */
+ if(buf_len < 11 || buf[0] != 0x00 || buf[1] != (unsigned char)tag)
+ return MP_UNDEF;
+
+ /* Figure out how many bytes of random padding there are */
+ i = 2;
+ while(buf[i++] != '\0')
+ ++pad_len;
+
+ data_start = i;
+ data_len = buf_len - data_start;
+
+ /* Shift the message to the front of the buffer */
+ memmove(buf, buf + data_start, data_len);
+
+ /* Zero out the rest of the buffer */
+ memset(buf + data_len, 0, pad_len + 3);
+
+ *msg_len = data_len;
+
+ return MP_OK;
+}
+
+/* }}} */
+
+/* {{{ s_rsa_transform(msg, exp, mod, out) */
+
+static mp_result s_rsa_transform(mp_int msg, mp_int exp,
+ mp_int mod, mp_int out)
+{
+ if(mp_int_compare_zero(msg) < 0 ||
+ mp_int_compare(msg, mod) >= 0)
+ return MP_RANGE;
+
+ return mp_int_exptmod(msg, exp, mod, out);
+}
+
+/* }}} */
+
+/* Here there be dragons */
diff --git a/polly/lib/External/isl/imath/rsamath.h b/polly/lib/External/isl/imath/rsamath.h
new file mode 100644
index 00000000000..01ebedebaaf
--- /dev/null
+++ b/polly/lib/External/isl/imath/rsamath.h
@@ -0,0 +1,94 @@
+/*
+ Name: rsamath.h
+ Purpose: Implements part of PKCS#1, v. 2.1, June 14, 2002 (RSA Labs)
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#ifndef RSAMATH_H_
+#define RSAMATH_H_
+
+#include "imath.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function to fill a buffer with nonzero random bytes */
+typedef void (*random_f)(unsigned char *, int);
+
+/* Convert integer to octet string, per PKCS#1 v.2.1 */
+mp_result rsa_i2osp(mp_int z, unsigned char *out, int len);
+
+/* Convert octet string to integer, per PKCS#1 v.2.1 */
+mp_result rsa_os2ip(mp_int z, unsigned char *in, int len);
+
+/* The following operations assume that you have converted your keys
+ and message data into mp_int values somehow. */
+
+/* Primitive RSA encryption operation */
+mp_result rsa_rsaep(mp_int msg, mp_int exp, mp_int mod, mp_int cipher);
+
+/* Primitive RSA decryption operation */
+mp_result rsa_rsadp(mp_int cipher, mp_int exp, mp_int mod, mp_int msg);
+
+/* Primitive RSA signing operation */
+mp_result rsa_rsasp(mp_int msg, mp_int exp, mp_int mod, mp_int signature);
+
+/* Primitive RSA verification operation */
+mp_result rsa_rsavp(mp_int signature, mp_int exp, mp_int mod, mp_int msg);
+
+/* Compute the maximum length in bytes a message can have using PKCS#1
+ v.1.5 encoding with the given modulus */
+int rsa_max_message_len(mp_int mod);
+
+/* Encode a raw message per PKCS#1 v.1.5
+ buf - the buffer containing the message
+ msg_len - the length in bytes of the message
+ buf_len - the size in bytes of the buffer
+ tag - the message tag (nonzero byte)
+ filler - function to generate pseudorandom nonzero padding
+
+ On input, the message is in the first msg_len bytes of the buffer;
+ on output, the contents of the buffer are replaced by the padded
+ message. If there is not enough room, MP_RANGE is returned.
+ */
+mp_result rsa_pkcs1v15_encode(unsigned char *buf, int msg_len,
+ int buf_len, int tag, random_f filler);
+
+/* Decode a PKCS#1 v.1.5 message back to its raw form
+ buf - the buffer containing the encoded message
+ buf_len - the length in bytes of the buffer
+ tag - the expected message tag (nonzero byte)
+ msg_len - on output, receives the length of the message content
+
+ On output, the message is packed into the first msg_len bytes of
+ the buffer, and the rest of the buffer is zeroed. If the buffer is
+ not of the correct form, MP_UNDEF is returned and msg_len is undefined.
+ */
+mp_result rsa_pkcs1v15_decode(unsigned char *buf, int buf_len,
+ int tag, int *msg_len);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* end RSAMATH_H_ */
diff --git a/polly/lib/External/isl/imath/rtest.c b/polly/lib/External/isl/imath/rtest.c
new file mode 100644
index 00000000000..12c55207296
--- /dev/null
+++ b/polly/lib/External/isl/imath/rtest.c
@@ -0,0 +1,124 @@
+/*
+ Name: rtest.c
+ Purpose: Test routines for RSA implementation.
+ Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+
+ Copyright (C) 2002-2008 Michael J. Fromberger, All Rights Reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <time.h>
+
+#include "rsamath.h"
+
+void random_fill(unsigned char *buf, int len);
+void print_buf(unsigned char *buf, int len, int brk, FILE *ofp);
+
+int main(int argc, char *argv[])
+{
+ int buf_len, msg_len, i;
+ unsigned char *buf;
+ mp_result res;
+
+ if(argc < 3) {
+ fprintf(stderr, "Usage: %s <bufsize> <msglen>\n", argv[0]);
+ return 1;
+ }
+
+ srand((unsigned int)time(NULL));
+
+ if((buf_len = atoi(argv[1])) <= 0) {
+ fprintf(stderr, "Buffer length must be positive, not %d\n", buf_len);
+ return 2;
+ }
+ if((msg_len = atoi(argv[2])) <= 0) {
+ fprintf(stderr, "Message length must be positive, not %d\n", msg_len);
+ return 2;
+ }
+ if(msg_len > buf_len)
+ msg_len = buf_len;
+
+ buf = calloc(buf_len, sizeof(*buf));
+ for(i = 0; i < msg_len; ++i)
+ buf[i] = i + 1;
+
+ printf("Buffer size: %d bytes\n"
+ "Message len: %d bytes\n\n", buf_len, msg_len);
+
+ printf("Message:\n");
+ print_buf(buf, msg_len, 16, stdout);
+ fputc('\n', stdout);
+
+ if((res = rsa_pkcs1v15_encode(buf, msg_len, buf_len, 2, random_fill)) != MP_OK) {
+ printf("Error from encoding function: %d\n", res);
+ free(buf);
+ return 1;
+ }
+ printf("Encoded message:\n");
+ print_buf(buf, buf_len, 16, stdout);
+ fputc('\n', stdout);
+
+ msg_len = -1; /* make decoder fill this in */
+ if((res = rsa_pkcs1v15_decode(buf, buf_len, 2, &msg_len)) != MP_OK) {
+ printf("Error from decoding function: %d\n", res);
+ free(buf);
+ return 1;
+ }
+ printf("Decoded message (%d bytes):\n", msg_len);
+ print_buf(buf, msg_len, 16, stdout);
+ fputc('\n', stdout);
+
+ free(buf);
+ return 0;
+}
+
+void random_fill(unsigned char *buf, int len)
+{
+ int i;
+
+ for(i = 0; i < len; ++i) {
+ unsigned char c = 0;
+
+ while(c == 0)
+ c = (unsigned char)rand();
+
+ buf[i] = c;
+ }
+}
+
+void print_buf(unsigned char *buf, int len, int brk, FILE *ofp)
+{
+ int i;
+
+ for(i = 0; i < len; ++i) {
+ fprintf(ofp, "%02X", buf[i]);
+
+ if((i + 1) % brk == 0)
+ fputc('\n', ofp);
+ else
+ fputc(' ', ofp);
+ }
+ if(i % brk)
+ fputc('\n', ofp);
+}
diff --git a/polly/lib/External/isl/imath/tests/add.t b/polly/lib/External/isl/imath/tests/add.t
new file mode 100644
index 00000000000..546aa673884
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/add.t
@@ -0,0 +1,848 @@
+# Addition tests
+
+add:0,0,0:0
+add:0,0,=1:0
+add:1,=1,=1:2
+add:1,-1,0:0
+add:-1,1,0:0
+add:-1,1,=1:0
+
+add:103427990038,909510006269847,0:909613434259885
+add:128593002,-9007199254740992,0:-9007199126147990
+add:-65537,70000,0:4463
+add:-1000000,-6543210,0:-7543210
+add:#x29C932F25E6CEF8046FA,#x-29C932F25E6CEF8046FA,0:0
+add:2,#x7FFFFFFFF,0:#x800000001
+add:95031018,=1,=1:190062036
+add:#x-176E7F8018D6BA4B550AB36AAAFDC78A9,#x186DAD2485A41B18AAF5EF17922D7E5F1F,=1:#x16F6C52C8416AF73F5A543E0E77DA1E676
+add:-628443782411312,-301652218193016,=2:-930096000604328
+add:13731535,499104,0:14230639
+add:46496,0,0:46496
+add:85658949,0,0:85658949
+add:3,86618070,0:86618073
+add:-364,0,0:-364
+add:916376,71094297,0:72010673
+add:-76,-48988,0:-49064
+add:7,98029,293800191852111:98036
+add:213,0,0:213
+add:116992,19352187,=1:19469179
+add:-54334706,-2638935,0:-56973641
+add:4210,4441,0:8651
+add:2470,-1654142,0:-1651672
+add:-32608,76896,0:44288
+add:598200,65918574,0:66516774
+add:-524863149,95573,0:-524767576
+add:4,6856995,0:6856999
+add:86710327,16209386,0:102919713
+add:31,-24,0:7
+add:5895523,9915789381,0:9921684904
+add:41557511,310172,0:41867683
+add:-6714,923,0:-5791
+add:466232157,987,0:466233144
+add:5919,-63,0:5856
+add:929994,66871,0:996865
+add:23,391,0:414
+add:751,-25255,0:-24504
+add:-282292,-1608,0:-283900
+add:0,-4119448990,0:-4119448990
+add:69248,-64165,0:5083
+add:816106,580,0:816686
+add:15171,219806,0:234977
+add:945180,-585066,0:360114
+add:27052,6664636892,0:6664663944
+add:-481622,-578,0:-482200
+add:926,-81,0:845
+add:-4084,62941238721,=1:62941234637
+add:888598,6601,0:895199
+add:-61,143796,0:143735
+add:408006264,51,0:408006315
+add:-582073,-6752,0:-588825
+add:88194084,595557600,0:683751684
+add:4963532385,72932,0:4963605317
+add:37370180,708428344,0:745798524
+add:638718578,-94054,0:638624524
+add:12603892606,194259,0:12604086865
+add:9812049,8843056,0:18655105
+add:-156093,-3718156523,0:-3718312616
+add:12264,949557843298,0:949557855562
+add:338742,9139,0:347881
+add:48848,-6268099,0:-6219251
+add:3653,981782890584,0:981782894237
+add:608763646,38233135026,0:38841898672
+add:-17063,-4811,0:-21874
+add:63244008,-380818980,0:-317574972
+add:624559862947,21088,0:624559884035
+add:-268795562,74755169,0:-194040393
+add:368827930,56987680,0:425815610
+add:142,-838643130506,0:-838643130364
+add:848909,137303147,0:138152056
+add:6682221270,4495632518460,0:4502314739730
+add:163999538727,754668,0:164000293395
+add:570098317,1230642588,0:1800740905
+add:814302609847,295465,0:814302905312
+add:61148411120,462527703,0:61610938823
+add:979075368979,64243429,0:979139612408
+add:8280601099859,431312,0:8280601531171
+add:29662,3920844058249,0:3920844087911
+add:381765363,6285,0:381771648
+add:6038301700102,167589011428,0:6205890711530
+add:-6720,50309,0:43589
+add:92070025383,8403955,0:92078429338
+add:9057100,9331,0:9066431
+add:46997620390,2556790331006,0:2603787951396
+add:9853238961850,760016661497,0:10613255623347
+add:642786326083,4994197649,0:647780523732
+add:60934395,192791945290,0:192852879685
+add:1304866806,9628566351206,0:9629871218012
+add:-537871392295,1691988267,0:-536179404028
+add:73595697641,63790,0:73595761431
+add:87798124384590,168308169,0:87798292692759
+add:77155772837617,993653875,0:77156766491492
+add:691109994727,83820903066409,0:84512013061136
+add:2012749349577,1194,0:2012749350771
+add:3909606,1258809350,0:1262718956
+add:5961027295,-191014,0:5960836281
+add:-9155782013,84622,0:-9155697391
+add:-7211667,-624806193439,0:-624813405106
+add:1754076,931310,0:2685386
+add:53288031910288,1866366148,0:53289898276436
+add:767503182,-78473238204,0:-77705735022
+add:-89763935864,-14028568280297,0:-14118332216161
+add:454616605,67243118209653,0:67243572826258
+add:674985,745910,0:1420895
+add:9182866281585,-7492901984,0:9175373379601
+add:8427973625,2948084578162,0:2956512551787
+add:89366530,96670928089,0:96760294619
+add:62255464298256,1694823,0:62255465993079
+add:5268676160308,-93499502334390,0:-88230826174082
+add:7165346,-12994330060,0:-12987164714
+add:73330752719,904668539586,0:977999292305
+add:8007349,88617667386,0:88625674735
+add:951867792,807329,0:952675121
+add:645715109491016,58609052382,0:645773718543398
+add:2037750169321,85113205892,0:2122863375213
+add:6585250,76715488825566,0:76715495410816
+add:4585299,4140224,0:8725523
+add:20194080,7047624,0:27241704
+add:786913195,5197776759303,0:5198563672498
+add:751261814658086,65539188,0:751261880197274
+add:-6325172443258,2171993016413249,0:2165667843969991
+add:3947284565,-78726628505,0:-74779343940
+add:-71699817835206,40239308204,0:-71659578527002
+add:53023714,-82553833053558,0:-82553780029844
+add:2808131187169,890250230608190,0:893058361795359
+add:4783795579,-953360022706,0:-948576227127
+add:22326520,59606609543578,0:59606631870098
+add:37110988189,2635629530529,0:2672740518718
+add:5415787,65557975919,0:65563391706
+add:687495904,-3296642739961554,0:-3296642052465650
+add:72930835789,43382168425705304,0:43382241356541093
+add:-995003864534,61722341747,0:-933281522787
+add:74285863538462,4701124896071184,0:4775410759609646
+add:-7259432400758987,917110091938734,0:-6342322308820253
+add:83640964028613,28436773,0:83640992465386
+add:12798300129,42764089830,0:55562389959
+add:907689161228474,9984041726746,0:917673202955220
+add:88648450941,-92224182312398621,0:-92224093663947680
+add:3423736794,992566059450,0:995989796244
+add:26095203,84516699542499712,0:84516699568594915
+add:-664955461457,34154013,0:-664921307444
+add:17408598155,57614703283466656,0:57614720692064811
+add:734135582143613,8386599520,0:734143968743133
+add:75433328059753089,3411724102,0:75433331471477191
+add:-5780056339,370823068636155,0:370817288579816
+add:747133022687630,743183409891560,0:1490316432579190
+add:1351023965,562216806411,0:563567830376
+add:8923051674,5453380084794,0:5462303136468
+add:244571930,-51111880145,0:-50867308215
+add:-41136584383913485,2817501078,0:-41136581566412407
+add:-8079768063523410,441741295522855156,0:433661527459331746
+add:599579537585,1505732756139,0:2105312293724
+add:6728375739,634744472,0:7363120211
+add:163686368,10797029513119,0:10797193199487
+add:38258778569482,81136715091,0:38339915284573
+add:89311393409893347,6487334114,0:89311399897227461
+add:4413952309911,-335091846,0:4413617218065
+add:-8490298221703,906197882389719833,0:906189392091498130
+add:547446627581960679,4111395072,0:547446631693355751
+add:-147199257725737,358585065185151457,0:358437865927425720
+add:733104781218,1305401890,0:734410183108
+add:66789232493812823,152353542633642764,0:219142775127455587
+add:91447917877257,890149399042107596,0:890240846959984853
+add:67840659340,45844535119015296,0:45844602959674636
+add:31351681435877221,-442068622969770457,0:-410716941533893236
+add:8505522087730720965,162001047045127445,0:8667523134775848410
+add:90408836865703,91766097115,0:90500602962818
+add:8278725919,-6565975065136635,0:-6565966786410716
+add:778195404262806210,9985183887639111776,0:10763379291901917986
+add:6696810212664216,312304914759219,0:7009115127423435
+add:3557735824865,584593215289536,0:588150951114401
+add:-49412044681,29956396329782239,0:29956346917737558
+add:11923449620,7765655187,0:19689104807
+add:1724176067,-67142223866,0:-65418047799
+add:525722978624,57023088377443306,0:57023614100421930
+add:726936921764427,3077076587081089,0:3804013508845516
+add:1790333591126,-91682335574328992,0:-91680545240737866
+add:-1112879092907469823,1867817571215,0:-1112877225089898608
+add:-8476115918476,3323398534004,0:-5152717384472
+add:83059391773,-65273298074046515729,0:-65273297990987123956
+add:2211388311050688,-245146603838894173,0:-242935215527843485
+add:585851683392336,3975804417513631370,0:3976390269197023706
+add:139186663640090,15082756961,0:139201746397051
+add:-48189710801086,-33546258184494787728,0:-33546306374205588814
+add:-100779556817445,-1522038785339961,0:-1622818342157406
+add:4885512159295669,480294778789866559,0:485180290949162228
+add:-557882003905193311,20195805293900,0:-557861808099899411
+add:154553862612072,9109218823125727072,0:9109373376988339144
+add:1483847515783086714,78233016786768531473,0:79716864302551618187
+add:632462956668123,-2951738540674650223,0:-2951106077717982100
+add:-60943119399848141,74036520715371,0:-60869082879132770
+add:-7905328383508507808,-207334403231,0:-7905328590842911039
+add:-376183968178,-862976187364,0:-1239160155542
+add:918327139068056021,-685922087142,0:918326453145968879
+add:-9846497109055054870,6775447579440637,0:-9839721661475614233
+add:-84073521083215,71309976692297262369,0:71309892618776179154
+add:-373011272994268095955,4157479098221637,0:-373007115515169874318
+add:49271774069573022576,378613526495506818344,0:427885300565079840920
+add:-5376376953931357562,7508833770175817,0:-5368868120161181745
+add:-23778714258598355551,-7185005392000393507,0:-30963719650598749058
+add:801031622749,53000130414840,0:53801162037589
+add:-970929952514676169,64017648311761173049,0:63046718359246496880
+add:444961381148474,-368409783275279249,0:-367964821894130775
+add:39999239040508219266,38054215870372108,0:40037293256378591374
+add:-712118755181107,21931036897383483,0:21218918142202376
+add:-646755675748528169,609844920243318603442,0:609198164567570075273
+add:171013028884891673,11967223547227113703,0:12138236576112005376
+add:90483783429450285931,8758299165450368514304,0:8848782948879818800235
+add:54722600417344222188,6655544009320,0:54722607072888231508
+add:7059355949487975,15428043300387,0:7074783992788362
+add:63718799432141668051,-1777818839779748621,0:61940980592361919430
+add:-811965656585153,-92999475442666083,0:-93811441099251236
+add:-480943344691207768,38637964026264,0:-480904706727181504
+add:87346474969320,11671605416687563,0:11758951891656883
+add:-144193490776783,320317203586930,0:176123712810147
+add:637224429856480,90100814693140,0:727325244549620
+add:1117448757980,20116238466569324081,0:20116239584018082061
+add:2134662653354031124,57535080216036041491,0:59669742869390072615
+add:-699305697439351543,-1322846377107844464831,0:-1323545682805283816374
+add:-287368527913803,559967333864139,0:272598805950336
+add:-4524131005300321178256,648090525452193270713,0:-3876040479848127907543
+add:983197813618615290581,-555223968315003163,0:982642589650300287418
+add:47595018158554,554354123612822084175,0:554354171207840242729
+add:76492304934567739056067,-17570682458452839171696,0:58921622476114899884371
+add:605579840932458751,5118917191828845481095,0:5119522771669777939846
+add:-77276783972774282464,97578221184517253974,0:20301437211742971510
+add:-55779468870779406,3628329199924803907,0:3572549731054024501
+add:-6810396240935929656,45581601665257956989667,0:45574791269017021060011
+add:-643395735022469,95994342321649,0:-547401392700820
+add:59033016804296,90010200392865311,0:90069233409669607
+add:412262412571713009,44652839425446643811,0:45065101838018356820
+add:-996242836885840433689,9932141967639296363784,0:8935899130753455930095
+add:-187591416585869366840,4868774783363997420,0:-182722641802505369420
+add:786124638558627932,120825949339625517416,0:121612073978184145348
+add:683056931297141410,13435555169749,0:683070366852311159
+add:78591895387046935416982,-3863271218201597391326,0:74728624168845338025656
+add:-581639737241844,59732569151616229,0:59150929414374385
+add:63839107438860260,-57936899988162199911626,0:-57936836149054761051366
+add:90241348579070434,4025779803051070287,0:4116021151630140721
+add:-29146551546957649,500543832007704775744,0:500514685456157818095
+add:40152296103662954,30632073318077007293876,0:30632113470373110956830
+add:46052697297460594549965,-2523434189144367108,0:46050173863271450182857
+add:-908472766655304200,503910242160770655137,0:503001769394115350937
+add:35664754770405781576262,-52328200879455304,0:35664702442204902120958
+add:536193847189289,2055159240163985839,0:2055695434011175128
+add:5692763430774180,559128387745059,0:6251891818519239
+add:962044518204007,36941484559411981897006,0:36941485521456500101013
+add:1778825689878630,1752252372363744,0:3531078062242374
+add:94533959067668939155652,7370593466294273268440,0:101904552533963212424092
+add:-79278320169999633,98078807455225677,0:18800487285226044
+add:97932568071091044410,45504699679270344940,0:143437267750361389350
+add:81602336599709335,277692040888807344679270,0:277692122491143944388605
+add:-8416111605414512356,-71387336643361802215,0:-79803448248776314571
+add:-4364114737364980,5713751339100810207300,0:5713746974986072842320
+add:-2248544818568852,-95216575446860643106235,0:-95216577695405461675087
+add:-86464737497345750915,-9340577567832336397746,0:-9427042305329682148661
+add:7285517444194103327524171,-178398693192528240,0:7285517265795410134995931
+add:745600294808335954574,3590181147179066146,0:749190475955515020720
+add:9465688117779501171539,38370364609588339408116,0:47836052727367840579655
+add:780056864215481439157498,-7015580969512485,0:780056857199900469645013
+add:978681982436757227400,2684547366513014,0:978684666984123740414
+add:-1128116293278100017914825,5548079193241448,0:-1128116287730020824673377
+add:69069382482494805,-40368676133739445253204,0:-40368607064356962758399
+add:1068908356897083556495,92975661850341635306516,0:94044570207238718863011
+add:2045728645356266,6732676856163053,0:8778405501519319
+add:986371258787059591145109,24417303396801332,0:986371283204362987946441
+add:5107392493993300358729,-8580635176929229687,0:5098811858816371129042
+add:1173219044247994941,150432915362745448142,0:151606134406993443083
+add:289209848265652909988,896527174701053128584035,0:896816384549318781494023
+add:7576209306830869,321093885120988771790,0:321101461330295602659
+add:-1998078850553780901,-491302474398583183312,0:-493300553249136964213
+add:48578611214917968888328,-9724795578642180430323005,0:-9676216967427262461434677
+add:-89125038112802690868952,106876489286063867,0:-89124931236313404805085
+add:71163583246605175,94315599279060581,0:165479182525665756
+add:-37978975375912768223,-83894091589588085332,0:-121873066965500853555
+add:26160354602260154641,82502519980721475,0:26242857122240876116
+add:6721445506562724498613,3849322132330485045442724,0:3856043577837047769941337
+add:-49599516930241019167,940046744572738518062,0:890447227642497498895
+add:309633233963607626456,431010776584765161668698,0:431320409818728769295154
+add:5437528458768789581061,98535318335138080471,0:5536063777103927661532
+add:441952255932531337132635419,-457951493790545402320,0:441951797981037546587233099
+add:4234090565000592983852,141452209542036221,0:4234232017210135020073
+add:444877202793878855,-818932236535168281886543304,0:-818932236090291079092664449
+add:8735279390159786014911,74528121661502104489,0:8809807511821288119400
+add:329585339951820135507,3209925326812978905481,0:3539510666764799040988
+add:7513147727765550283468497,18340872039691020224,0:7513166068637589974488721
+add:22672336765411635852057,112360311181155228061,0:22784697076592791080118
+add:94840923157956010314,-890963292023167606621709508,0:-890963197182244448665699194
+add:-42743124461511984041,-154189486799725890635958009,0:-154189529542850352147942050
+add:4642096435824001337488,1075739791472186776,0:4643172175615473524264
+add:9072122446151456250370,459465421414955099,0:9072581911572871205469
+add:1208103563782991690,37264807069479596362,0:38472910633262588052
+add:-35229676312313275613641079,7831519567525205386506558,0:-27398156744788070227134521
+add:-14914636592325904561,238892654922757390,0:-14675743937403147171
+add:70036479094753932788537196,3638698354298942306,0:70036482733452287087479502
+add:2026475183691718009207221,-51818547306091257831,0:2026423365144411917949390
+add:934591237413188471704,9583576351426447252706,0:10518167588839635724410
+add:19623165243467693921345120,713164237953453844732059938,0:732787403196921538653405058
+add:-330423131007863591790334,483122548819491409819,0:-329940008459044100380515
+add:186655649790428913672547335,45905196004697591848,0:186655695695624918370139183
+add:61575494850989411781745,510771432997312770825568,0:572346927848302182607313
+add:701715172953878317016084611,82176271434782371131,0:701715255130149751798455742
+add:37317170353550823267505484,-281915644115285990142,0:37316888437906707981515342
+add:782147829078599149413,406441493949770755536,0:1188589323028369904949
+add:8750933869512603353560747,4845145469101036864410189,0:13596079338613640217970936
+add:82771556090809260029854,417868176867358634531479,0:500639732958167894561333
+add:-60327848305676142893255531,45186448696277654715,0:-60327803119227446615600816
+add:559238168466621140605667,3086402973187970627177143386,0:3086962211356437248317749053
+add:1487217856230533992619184307,88533139618452902103,0:1487217944763673611072086410
+add:74032714774552791328773,-743497205088178750354447330,0:-743423172373404197563118557
+add:87529301918640055328531949,833538436278390237794218,0:88362840354918445566326167
+add:1134893809082711064119381650,835345147684508177653,0:1134894644427858748627559303
+add:-31083560926993891097159,-6452398931722666743775,0:-37535959858716557840934
+add:-494187214625328255573121,-433316980223823483512168,0:-927504194849151739085289
+add:390091842128606730764553615,7074602388637593045951,0:390098916730995368357599566
+add:14996900382322823366993947,155575881895992530106696,0:15152476264218815897100643
+add:256981179582607852185710064,960124902340809507842,0:256982139707510192995217906
+add:606337739205468757142681,34431354430278402333959617,0:35037692169483871091102298
+add:820809632172159862547216787,-4720961905066758420386939975,0:-3900152272894598557839723188
+add:33254605052680847119352168342,-42458830987973889052675953,0:33212146221692873230299492389
+add:1921909649929948589227,650119220435441127155469,0:652041130085371075744696
+add:36032029451816652021799919065,991948874284797761534223740,0:37023978326101449783334142805
+add:17509423061776720551599,561537726801446789470435708,0:561555236224508566190987307
+add:432435308982641288577,2579972583113864486802769,0:2580405018422847128091346
+add:5533541961594197125465685605,-5341574108952093824178502732,0:191967852642103301287182873
+add:29253784634468015940995,66868085704232379455942,0:96121870338700395396937
+add:5840836104812160960058403235,7254794739433874655672505,0:5848090899551594834714075740
+add:-986437670276537865472,-7254530387088660530975,0:-8240968057365198396447
+add:5936378029743262858909,5646361873410369432412,0:11582739903153632291321
+add:9309474173188449211471238,71622847426463521178458,0:9381097020614912732649696
+add:7395866525419579894252,6054211177368524226173,0:13450077702788104120425
+add:418754431137708178806,4581969489771092325887396,0:4582388244202230034066202
+add:427267592272679033207846,-1335344313633491261520271375,0:-1334917046041218582487063529
+add:633189097535167096544295,8453789539859471176551,0:641642887075026567720846
+add:5272319792173353341707102,391850306244460524900101084,0:397122626036633878241808186
+add:65825860390007189905183231257,931471994606023293002971,0:65826791862001795928476234228
+add:-176921811706712109725453309153,51104838980538411694813294,0:-176870706867731571313758495859
+add:76672856213061308993625,-29636580685314230414049903200,0:-29636504012458017352740909575
+add:674452402018255228121289278,67008875737626760336005690,0:741461277755881988457294968
+add:8541968162357356479415070453,-80758853802904365328480678550,0:-72216885640547008849065608097
+add:63670327126030699390525,647239453527002086941714828140,0:647239517197329212972414218665
+add:23827968287407694016891491732,5687322786770428586659139842628,0:5711150755057836280676031334360
+add:-56934084938034523477449,6919565043762938954102,0:-50014519894271584523347
+add:-812505002549423792769451177170,-468614098924848220068202,0:-812505471163522717617671245372
+add:67104776285167776356142,210831864020377644772737617440,0:210831931125153929940513973582
+add:5824940449668378359986211,-64180395015735031445899448907,0:-64174570075285363067539462696
+add:983409682982426617028179979,163969833630884765202234246,0:1147379516613311382230414225
+add:6210538420073191557435,-31054053390220409528967600423,0:-31054047179681989455776042988
+add:469516153781193420842788,1496796321887102771420,0:471012950103080523614208
+add:33979356884336447134582,91638986223658016683623403,0:91672965580542353130757985
+add:-32260848074913901984307362359,-2672012528351544629126598,0:-32263520087442253528936488957
+add:-8417639463674910047939048993449,80120124562574727803706174,0:-8417559343550347473211245287275
+add:775695772679005684017516,-3020790629041979619689982869,0:-3020014933269300614005965353
+add:975852258680635035690012,83046701463562128390834533268,0:83047677315820809025870223280
+add:8781861863169257626949530,28108177849164848399916019884,0:28116959711028017657542969414
+add:-283546689653578050474370627,2807772419117477871716212,0:-280738917234460572602654415
+add:9064465458779158311916969647780,9139819686732442186357751866469,0:18204285145511600498274721514249
+add:8840784216244154251572494530,60209012240418199299108682988151,0:60217853024634443453360255482681
+add:93815677427271630939740,22565184436411206947191022,0:22659000113838478578130762
+add:82452768800915418769333034684,31578884402602201747665,0:82452800379799821371534782349
+add:-861901423955324264599608669156,707341771563323556783706679,0:-861194082183760941042824962477
+add:-27282637700205513755848881,-503533726284787080825911,0:-27786171426490300836674792
+add:9289214479556466478450749,-7084113575511224733535260,0:2205100904045241744915489
+add:7017123255359412684282683,9046068160232439106672624,0:16063191415591851790955307
+add:251153423310728722653267854537,13062952884507685376788080,0:251166486263613230338644642617
+add:764970108101691141391204483,75231888234738846744202931914419,0:75232653204846948435344323118902
+add:70105736718198876906468336722477,2901679421786748849622789,0:70105739619878298693217186345266
+add:-277236273480908454984267,95439324803072858679031,0:-181796948677835596305236
+add:502022119894313002150611379003,-9553217783049460795811638,0:502012566676529952689815567365
+add:11235044224795237679279440,1598484681458068370777229,0:12833528906253306050056669
+add:6006446640030673298734990897916,3932713488343416708785849,0:6006450572744161642151699683765
+add:341984581388111664359529291419,253672139310821088560318393948503,0:254014123892209200224677923239922
+add:-16498480187763102357325186,16757917811449471275953805,0:259437623686368918628619
+add:4840293579085321724261731660,3299269918638542438501050537,0:8139563497723864162762782197
+add:862473464150144977188625432548718,390725508757117448688936595600,0:862864189658902094637314369144318
+add:-29573457775060793626221640796,-955486742447211372069984831882188,0:-955516315904986432863611053522984
+add:2764463542396067736191963723,33349178218458257881168366225076,0:33351942682000653948904558188799
+add:-564129660605536405453000618753,-996106182924479683180384656113614,0:-996670312585085219585837656732367
+add:8033177512692093044315018,-5381259101993480763476852450,0:-5373225924480788670432537432
+add:5694253375903848576996695765,3533498246256483823188758976,0:9227751622160332400185454741
+add:8049869890130722459017898,804302573811695296944485509,0:812352443701826019403503407
+add:-10782856862032822029370450127864,42183304229376991057468028,0:-10782814678728592652379392659836
+add:17953427150766889866624145,2672739534749259247084452652,0:2690692961900026136951076797
+add:382968112253902278556556412715286,507081979144423606544809226,0:382968619335881422980162957524512
+add:10675472848868311098607354530,921641093617028576338449657948,0:932316566465896887437057012478
+add:45793464872625930068611014771,895098402397211759149489341,0:46688563275023141827760504112
+add:-64085785899561813992220240078,-9948203496533963923520873499122871,0:-9948267582319863485334865719362949
+add:-36229685382343277189388317,3225709738074187586965400,0:-33003975644269089602422917
+add:62746144069561486173188762523567,41388696507099517847341965,0:62746185458257993272706609865532
+add:-607094025616255955599781697,-394867562893771866413821906158382,0:-394868169987797482669777505940079
+add:311268724839167391882108484,-82153236672690725073700221869998,0:-82152925403965885906308339761514
+add:-6835603694552724869687187061,-6023776712184941872282636664,0:-12859380406737666741969823725
+add:590358394226908898299218590543900,97734796237031665405902113169504,0:688093190463940563705120703713404
+add:776333186005384178281483204964,7251231826873456228321061,0:776340437237211051737711526025
+add:56669798612022472565446600865,-6052380717302970032083528141,0:50617417894719502533363072724
+add:6865898859037955833953890,178638282809455642352286,0:7044537141847411476306176
+add:5105205245055741189404951,893962641798284490158079805140673,0:893962646903489735213820994545624
+add:51316165533150178772523358024,-628375072698255873957923760051222,0:-628323756532722723779151236693198
+add:-87785238468437978540491414,89732479371379507893122052,0:1947240902941529352630638
+add:950318073610388416087529318775,402634948952512865122682232525,0:1352953022562901281210211551300
+add:-74572627412706083960240275,431357597384151709770753161,0:356784969971445625810512886
+add:9853321136670770651473838461495259,-83924966088311113186923377729455334,0:-74071644951640342535449539267960075
+add:650506501105456725689474061,287241011028313593932616830,0:937747512133770319622090891
+add:8132932977319394188366230514,-254188694333249311199490675,0:7878744282986144877166739839
+add:53320519909486593081198293,-74572156817884131125537363,0:-21251636908397538044339070
+add:-71547639554175546005091389360,-8140195760146170485331061575,0:-79687835314321716490422450935
+add:1327483718371853548235029647793617,54274563336128441076471770,0:1327483772646416884363470724265387
+add:1314001032447052278696101270,5415781672112089561501909844,0:6729782704559141840198011114
+add:47224974651866655046632261766,-76788661932424775106847892,0:47148185989934230271525413874
+add:792552859971310302936618155974,-487118690055436369708858828,0:792065741281254866566909297146
+add:8685351871091309367281665125018193,579376603481579380106078170606,0:8685931247694790946661771203188799
+add:-163023266227426934448401141075814,771214414019011070620622448527010,0:608191147791584136172221307451196
+add:681117685696813411930600559345469,53231124210443068505485918467568,0:734348809907256480436086477813037
+add:24728715686927944276955201,239070293086557045345907117925272,0:239070317815272732273851394880473
+add:764946100412930809834253766,-826649833775850040190545960601,0:-825884887675437109380711706835
+add:7808371142489773310260037786027,3411749587758291799422914115,0:7811782892077531602059460700142
+add:9487499431366548971411896854,617160736935684035360665548277255,0:617170224435115401909636960174109
+add:898285778199998316256066724,-446698135458890722737448919720207023,0:-446698134560604944537450603464140299
+add:679188320572774450433052775314,917321221948698358395231976875443,0:918000410269271132845665029650757
+add:-606026214573430597349972660492,-76705531041680588416688199753404,0:-77311557256254019014038172413896
+add:-2436189233935198704211905220849,37199591944878505577734886802440,0:34763402710943306873522981581591
+add:183575501000337709289570527203677231,136287320714071665681020786679234742,0:319862821714409374970591313882911973
+add:8590013432900716370831629971791,968114425708634187961093620824,0:9558127858609350558792723592615
+add:347137295949542839762519290637421643,102270809320390302037608013,0:347137296051813649082909592675029656
+add:8440473671167620611051468072483271,2296992478227176302012302522046,0:8442770663645847787353480375005317
+add:-5001669553432654706696400609,118900597514025159662837118047,0:113898927960592504956140717438
+add:-62002790901737049130724871593864,49447394219956225227401512811,0:-61953343507517092905497470081053
+add:86330941115371276117147730300459977,2177791532412716777679721138299658,0:88508732647783992894827451438759635
+add:946875123242781630779255037,47946896786026059202158912141346,0:47947843661149301983789691396383
+add:15336011900228959543893716525418719,388047623512726643322227444888,0:15336399947852472270537038752863607
+add:670173436182016731100418370242962831,4761361980899572407426780990276,0:670178197543997630672825797023953107
+add:16361593374554723036317118422757,959754436168611589130929042794416,0:976116029543166312167246161217173
+add:7037129211989227284511625030,-64039638650631553463764702068273727,0:-64039631613502341474537417556648697
+add:1669039732670522007255294145067558610,5040361069110054882215284201346,0:1669044773031591117310176360351759956
+add:1513189097366228884843540957233,759609367644509304958151974044245430,0:759610880833606671187036817585202663
+add:4895978309720518255173456993,-4110535948244791094217531557,0:785442361475727160955925436
+add:384532700809738729029745679298,-8056698430799793973614359358,0:376476002378938935056131319940
+add:-6388105307234743748019853948088503,4997968805095951937740134154116761,0:-1390136502138791810279719793971742
+add:975018502065461978578000363066,2247367452090296660167940131,0:977265869517552275238168303197
+add:78856706773590014370827059719,6542936662766324535583066287213231,0:6543015519473098125597437114272950
+add:6499328245520359687815445935758,158783937355037461719106652621,0:6658112182875397149534552588379
+add:-929274641312553715971084005591328,65105653662781997005394335939613534,0:64176379021469443289423251934022206
+add:456683941925696893937943252471,2047844563635520107891754533956927,0:2048301247577445804785692477209398
+add:2464091244058374057204697838093,548233532044481143606226540715,0:3012324776102855200810924378808
+add:-5782058275134622637686813910631,65732482103665178041908743240,0:-5716325793030957459644905167391
+add:9077295754335257518831628411071383,10924567149120537328883108077429125,0:20001862903455794847714736488500508
+add:4487883990386478000336258527165792,45494719991936774851608031864,0:4487929485106469937111110135197656
+add:-278061320607811538265660406605,6501055843301716146308769533884534700,0:6501055565240395538497231268224128095
+add:-98496078021467197122901029244,4781298078177162558520974148272,0:4682802000155695361398073119028
+add:-880487306232247995563348595589965390,1786978622507362310090719007228,0:-880485519253625488201038504870958162
+add:3564320220013161114076355137453361,3174192776315040318048578353150392,0:6738512996328201432124933490603753
+add:-17938701536608326039598376013574,6544909780634291186211124961480,0:-11393791755974034853387251052094
+add:477266862227893391363944723416214,75215386788899217183549861936487009,0:75692653651127110574913806659903223
+add:882168805504704249200404316267,397370099670749831094907204966440642,0:397370981839555335799156405370756909
+add:-5168732252762846279707583890106130,68924007866194419843572553425738646075,0:68918839133941656997292845841848539945
+add:13976907500017232058982276795936,62903564794422037566078537019953323966,0:62903578771329537583310596002230119902
+add:-723679233282687539426040870751505916,9944693303602413488927619210482961855,0:9221014070319725949501578339731455939
+add:19723375859398094253269538838784,4448602254481220443835883935,0:19727824461652575473713374722719
+add:435487568164299717641211729895291,30263286963580437915152248885,0:435517831451263298079126882144176
+add:821847194805020065585371899303,-56701356407219809621351993974800366087,0:-56701355585372614816331928389428466784
+add:906521314887358356519304370098899949,575586805546053112223797224287895841,0:1482108120433411468743101594386795790
+add:19861035347913984137892042959473300,9203641819631417294115804880148466,0:29064677167545401432007847839621766
+add:35489920465547911895345631311031287850,61963387682089469403889443775403001937,0:97453308147637381299235075086434289787
+add:711218176456565648939214863247002012,72467446712664186983159145098756557673,0:73178664889120752632098359962003559685
+add:453411180015845016525527797241902720,656188106785767735033442856252,0:453411836203951802293262830684758972
+add:3497788563739847797768025384670848,517400530521523434205853846962853,0:4015189094261371231973879231633701
+add:4155970281036560633085895732986331436,58654056236489765208332410680287635851,0:62810026517526325841418306413273967287
+add:-43796787638734252111746756631324509,15458635191255506747952752911563140015,0:15414838403616772495841006154931815506
+add:886478982594616386399515638094,791374254805498814484495931823029294,0:791375141284481409100882331338667388
+add:5420205765532053736853148082964602405,80894300860364935354122327418793,0:5420286659832914101788502205292021198
+add:6409540010109365565390431678312058,3761260998235788651953577451547946396,0:3767670538245898017518967883226258454
+add:379235320792985651222455993704383,39768702701817374238094976575577292677,0:39769081937138167223746199031570997060
+add:9741457286836201279089678473713551193,-9789501315839617552822514677465645799,0:-48044029003416273732836203752094606
+add:679351661380711616762980509555487422,5244958563307694732934184938012411110,0:5924310224688406349697165447567898532
+add:230190844936986997441295775275022034,-185909046836091915997263172330,0:230190659027940161349379778011849704
+add:3156689741537889100921303548469,547814421078639373357367180225132810,0:547817577768380911246468101528681279
+add:-62219007651568146709531118440682893089,-9434399409814593713428350812443801646786,0:-9496618417466161860137881930884484539875
+add:184174790691390536467483515964213892835,2941013349035333556270582770860221254,0:187115804040425870023754098735074114089
+add:51019963839123593098882577978755,1116589028775897480619143898066573,0:1167608992615021073718026476045328
+add:3161373461260957201319457188462572095,295012249650450244682353395660589081695,0:298173623111711201883672852849051653790
+add:255897713184471452642500281024049492424,5260363568754655790521228400406175726257,0:5516261281939127243163728681430225218681
+add:606315001345297293855907552090677,58643218561030036941054387859353998671,0:58643824876031382238348243766906089348
+add:7728401578087472448175772296881,2479932497409122334635317410130037,0:2487660898987209807083493182426918
+add:83912594421874997853645370567167,2586838887610120476863229517446,0:86499433309485118330508600084613
+add:31162728147482517541527422834730838,49272727945051817211201248857958834546,0:49303890673199299728742776280793565384
+add:7732493494017159067700264618259826225579,9076083109776747375814790855266491489,0:7741569577126935815076079409115092717068
+add:379595189057102692932728847043,78412390558490705293355381777932556,0:78412770153679762396048314506779599
+add:-80073436239675271494315527682263,50945580964846901715535623599314335,0:50865507528607226444041308071632072
+add:7287524755764369986358866728286492322771,-3434322398801915039360350216639455,0:7287521321441971184443827367936275683316
+add:5350901001113421691951885827606408,-52813130876478631706333437707256,0:5298087870236943060245552389899152
+add:-93922484436479929644974748134570042227,-18558847074134835688687179622179299456381,0:-18652769558571315618332154370313869498608
+add:6348261214416753548599493164564265,70959376021447769657800151242308058385,0:70965724282662186411348750735472622650
+add:82136982657867459725041723297845260,-4942386549903864832898696177047927,0:77194596107963594892143027120797333
+add:-637766414636467351411944290845261564150,3139008925795329253435316311633609560,0:-634627405710672022158508974533627954590
+add:7876071803789707417919831488411894460,-787451981013463104190187704083407112807,0:-779575909209673396772267872594995218347
+add:-6975874728401593555157382880902999590154,-5386051406453469842388696470942392,0:-6975880114453000008627225269599470532546
+add:263948302163372204339026784768887,-709208282236872695042395059556627390964,0:-709208018288570531670190720529842622077
+add:966883950465093993601498906417362169986,52803750507502030833811587668282000984096,0:53770634457967124827413086574699363154082
+add:758872502722448271767968272715108,924042905049846617145386931355586,0:1682915407772294888913355204070694
+add:8817515445646069320245128327534016,33540272364420722162627441428305029,0:42357787810066791482872569755839045
+add:7452847844446973070588448979886483,13672013320832031648561092777470,0:7466519857767805102237010072663953
+add:504207812168642571415434369106684,3112968037276454309667407723426693283,0:3113472245088622952238823157795799967
+add:79464727253769579340699162892454647,-3445737782055492967953863370896564268,0:-3366273054801723388613164208004109621
+add:27111645259145369800704958812916,67484517522542733254003181309322379,0:67511629167801878623803886268135295
+add:7962416479715287030323333279385706598,88254203468610078692514314020591,0:7962504733918755640402025793699727189
+add:39693287540792352830897524921810,-21314277451673979084086774678038501015,0:-21314237758386438291733943780513579205
+add:198918483468716913242822977257934441,-7728701263590045875855983145711563105524,0:-7728502345106577158942740322734305171083
+add:23489078790493512251447591514734933644032,5044415728397642226681534366309793929319,0:28533494518891154478129125881044727573351
+add:754857260375845266559134913354911,-107973684581827631710281010202379896,0:-107218827321451786443721875289024985
+add:-315532494063826496737110988346555619786454,501129324903842341869098009302271432013604,0:185596830840015845131987020955715812227150
+add:92594285071838024355958905365280662316,2187702621551700872791380132896499,0:92596472774459576056831696745413558815
+add:724288898592047956308741845059503937300137,57590734518283929259390943990555930310,0:724346489326566240238001236003494493230447
+add:2739606628137004623864591349778009,110573647075582659906006861365833637275224,0:110573649815189288043011485230424987053233
+add:-14276517096318036496680563063254770722,947355542566791575863860389736548529916,0:933079025470473539367179826673293759194
+add:2231429252956485218579039663297923538099,-513782743328474567896135012801752,0:2231428739173741890104471767162910736347
+add:-849056192493090160065711552591498902148,570178803220182344540821571410117099230685,0:569329747027689254380755859857525600328537
+add:71805397382388312493912292806954799278,80784372590768053283785033890385062,0:71886181754979080547196077840845184340
+add:88350358965992565491787153066170941,21234283677146108616947794414929963,0:109584642643138674108734947481100904
+add:715269430237566589970907864930513314,8865443182554480537011356202533506,0:724134873420121070507919221133046820
+add:1477643303333104073865392660271903836,-367890944067864281459059958232249,0:1477275412389036209583933600313671587
+add:52217735662219170731154120388630563,-294933344350299941699482081737942598484292,0:-294933292132564279480311350583822209853729
+add:61380058552546011441493813017768437169,2900762818425899718317517551345155090272,0:2962142876978445729759011364362923527441
+add:-277784196782412339397810200390714846163997,57298552978631155824394514405745061,0:-277784139483859360766654375996200440418936
+add:-240135707306520087768252873800163694648274,96353334913929088034747034183526033,0:-240135610953185173839164839053129511122241
+add:5682589714457375725889091714569040,1460653301509827608879103745623307421551826,0:1460653307192417323336479471512399136120866
+add:19638363083802509640291691621245056147864,4211029423275507408378664959653089,0:19638367294831932915799099999910015800953
+add:83194800067935752402123668615503029739,2541880714569630662018719665186119518080,0:2625075514637566414420843333801622547819
+add:5939482394780085376784755590138737708464,514468562230819790647711281175956014526779,0:520408044625599876024496036766094752235243
+add:90204831870247776142696176553164845,448604014584373050945946043173569,0:90653435884832149193642122596338414
+add:-28255771387063942974030915755487615886801,211023308891994717221529619029320336933917,0:182767537504930774247498703273832721047116
+add:757105867421757109115447689795304050728,9406978659060898637265625690923719984,0:766512846080818007752713315486227770712
+add:71046269267930793233803101419359460555523,1066119341117097582611928205374175134353,0:72112388609047890816415029624733635689876
+add:860460409596026218232712913311397528,-386403674339732916173292388406974737,0:474056735256293302059420524904422791
+add:51587104345453069942306514960268280925,7174136164833181606646937608176553464,0:58761240510286251548953452568444834389
+add:646810491958543131766676874643214951350,499259004231242695310290078066810898630,0:1146069496189785827076966952710025849980
+add:855002490358777508650454091557987435,509862775866892935549218038452333306616836,0:509863630869383294326726688906424864604271
+add:106603467132772647500729395434502230590051,-16368407452060510330634069459161959,0:106603450764365195440219064800432771428092
+add:516036973938460113725699447078888101,19774284176043121487876685246833573074044,0:19774800213017059947990410946280651962145
+add:952655868300967849134836490408672046390,26424621652588918937927182288854430428873,0:27377277520889886787062018779263102475263
+add:612516318964652612641515207511494523,9669431975435363339548442466828737776,0:10281948294400015952189957674340232299
+add:312358445059554864178031833622326259,3063646351543973236788253379318869856029,0:3063958709989032791652431411152492182288
+add:21961875002920796735366447872318305568,12735184963536281218871061660462862352679,0:12757146838539202015606428108335180658247
+add:-76958222715483937218117123118097824686,-94131755294315965491758099750033439180279,0:-94208713517031449428976216873151537004965
+add:9941064428919490001398667535954444,6153135198163214971541929596372799080,0:6163076262592134461543328263908753524
+add:3831883399874967153073325466609079148,532933850230226797587412822078065345376,0:536765733630101764740486147544674424524
+add:-50281475345524432188122843117426347,-9803783578868553758867748377042263121,0:-9854065054214078191055871220159689468
+add:834761861391838835749698262829275672420,462418116078562931546840078329636278799243,0:463252877939954770382589776592465554471663
+add:225390444541945757230864160941425071753376,-53966286270122861338860835026614792455718558,0:-53740895825580915581629970865673367383965182
+add:58072467659883242067246942042391055912061,6014910057066062653667358884004188529013385,0:6072982524725945895734605826046579584925446
+add:7983230467245365113789955920296234304,82831178283927503584223331110953816965231,0:82839161514394748949337121066874113199535
+add:-45132067499699119195319118239527377040857087,55414967908829898692681772863326254754,0:-45132012084731210365420425557754513714602333
+add:223736085581687840223151741351715016762,-234872704339511023869747996243506715388251819,0:-234872480603425442181907773091765363673235057
+add:28507472864431142856885789471402326707231,612001776806865658512116926003228872602978,0:640509249671296801369002715474631199310209
+add:181745193154135636884034106408465870431,1377247390938535372211751085008319196,0:183122440545074172256245857493474189627
+add:-4269390869184529398543606143750267674905,7096165581548063546128304224326254363,0:-4262294703602981334997477839525941420542
+add:679756117856607689911810374667015768583465863,6873132770775601366558132717863835975030609,0:686629250627383291278368507384879604558496472
+add:68811928716841819374127395790718594105543,-39375978475154900824641971995674964440336,0:29435950241686918549485423795043629665207
+add:-544206255007274743273093190267769706102594,-2633960527489961764864800511887586286863,0:-546840215534764705037957990779657292389457
+add:2104363621112481255876148263045164671673,3455315958528890329983695074392024415,0:2107818937071010146206131958119556696088
+add:34329184450930780849723051315762611673355499,-7104639609931302899460488253298995450,0:34329177346291170918420151855274358374360049
+add:43634150371577068764686894937264376668,-11959554165007875996906989926905112,0:43622190817412060888689987947337471556
+add:5024013516582802239298322665096973189555767,2088517329172254514727438561881167273,0:5024015605100131411552837392535535070723040
+add:566562417680186012953839263884602744810,7199277629017396422779479852344452527,0:573761695309203409376618743736947197337
+add:638955594778655267039016164163448484433233,14647767846572475359605733710956434972995,0:653603362625227742398621897874404919406228
+add:892892418549132886737629998256603006,-42420003645924668249063343987514804160205,0:-42419110753506119116176606357516547557199
+add:-345020858381297450936373802134725158851,-859477477801413864204931138561051434211277354,0:-859477822822272245502382074934853568936436205
+add:91737862563680387690935307847429742390,-6404695075658291424340413128158568521902,0:-6312957213094611036649477820311138779512
+add:-5423452022691148500208482455973347475028667,920708388791651749460962831411085083383900,0:-4502743633899496750747519624562262391644767
+add:8150633265487263016893827297406214487098531421,693305116681597826454527918912884500199574,0:8151326570603944614720281825325127371598730995
+add:-533542099871802731282960535234702413039265823,723089355050948526591740235214878409611,0:-533541376782447680334433943494467198160856212
+add:-87660042403521352943774533787359048954462,23205508268059470425857002842150306009,0:-87636836895253293473348676784516898648453
+add:611377119302093745013583546645763276869536489,-24306437719460476886753515868367600814,0:611377094995656025553106659892247408501935675
+add:4077104707730979108276738109711194036126856,11060272475917992334991062931569856434791792,0:15137377183648971443267801041281050470918648
+add:-7573466809324629854537923630574679416,47863519134315568229699768981973881143764,0:47855945667506243599845231058343306464348
+add:-799102320184378863119971307727324658691,-223055933928835873102241901074720286440913,0:-223855036249020251965361872382447611099604
+add:-892554445176156160154245376649692459,46912675277606111189784511368222685137077,0:46911782723160935033624357122846035444618
+add:3026665879602974291587291059690414946715394131,369940715997138180165001378043470020585,0:3026666249543690288725471224691792990185414716
+add:884243222337379604041632732738665534,784805891181951699244456801706510227963,0:785690134404289078848498434439248893497
+add:6161631921601317978027999219270688283511,7540058790546974071130804326383997513568,0:13701690712148292049158803545654685797079
+add:6921119983791225541212197181924239508872679243,1418358920528247154891120491105704894,0:6921119985209584461740444336815359999978384137
+add:354562064037463731505174515681520375545196955,298046963066931310381553348264288949421865,0:354860111000530662815556069029784664494618820
+add:9118288949631130571307463256861936097477907856,811804191882243735414480051639019704082019,0:9119100753823012815042877736913575117181989875
+add:12323504604096011377318065801800362182031140,8419570117283520873564639019491515440808,0:12331924174213294898191630440819853697471948
+add:40282114774095347321311816032119808177051,9392020059227568760693643864091980296962225,0:9432302174001664108014955680124100105139276
+add:293824315258364662435205611375731221153259453,69936479932599496690415175383522476194836,0:293894251738297261931896026551114743629454289
+add:744437789281951089483978067750841678986225684,6215758092668446071515969246800386681388042824,0:6960195881950397160999947314551228360374268508
+add:7555232352218578953388426959061233639843,-338121179318504388356512546357851050384,0:7217111172900074565031914412703382589459
+add:800786123647331529935991527240766809126924910,8084356801391362127584834876216208164918895003,0:8885142925038693657520826403456974974045819913
+add:10929663989202222972072257796740362711,2014764235099935818353734632287788031375,0:2025693899089138041325806890084528394086
+add:-2304110026472565466976559294239050373788594441,95118068539305153789040528913479244781984827244,0:92813958512832588322063969619240194408196232803
+add:92970515686777203278075298872457538269139530036,804034060487391950939245065492783268785530482,0:93774549747264595229014543937950321537925060518
+add:306074026230996345745669348355571285049,3351194990528556941059979503062943080591380,0:3351501064554787937405725172411298651876429
+add:-1801109034823531811485037478828625593344102,-6788371291545724511455362562828939498570517171,0:-6790172400580548043266847600307768124163861273
+add:9906924561298959226824383647599274129900,46505636651150809672589883942989253631123,0:56412561212449768899414267590588527761023
+add:-532368057068285718080209540340159606385179953,78439393969883180556469736987530860427701949507,0:77907025912814894838389527447190700821316769554
+add:1457791796516706098588078441562863530737,528666216820331549882926030036885918841998977,0:528667674612128066589024618115327481705529714
+add:47587357391699836981813632674062733663847158658,54288315220694727806529289306655335607545661164,0:101875672612394564788342921980718069271392819822
+add:2441679111284579236791979326321319109424,612350380810923282381362835527975935997871963997,0:612350383252602393665942072319955262319191073421
+add:-2297182432664233691613076128334534556985403,311366264931073208179039511983011701314592621,0:309069082498408974487426435854677166757607218
+add:812480504283331455325441717008120800963079831,821134520243619144054746507506987541221,0:812481325417851698944585771754628307950621052
+add:292567021381222422856988422202010933008593,322995618653906543956044582847376714984579,0:615562640035128966813033005049387647993172
+add:331282545048545544767134884053522581147,5766236410336035826171861644077140841513734,0:5766567692881084371716628778961194364094881
+add:40252183714117806066401858275236076131151,-72745188677928192885457824316277110692234611263,0:-72745148425744478767651757914418835456158480112
+add:46457019922262916743996775404831914092936856027,6315416110239465669051340102484371408912908926,0:52772436032502382413048115507316285501849764953
+add:5466283595093360991616260159696927423349371,9668800763746329080816551076148727500025,0:5475952395857107320697076710773076150849396
+add:19669588483473218340912326281765015036658,6428951178389068517174516071634753843412004200,0:6428970847977551990392856983961035608427040858
+add:-81431110841967281357837413471759747002352,59367885431507523151090269106192098957070,0:-22063225410459758206747144365567648045282
+add:793131141187380089412901409250143061286,49410607246090035402603177567556059311746,0:50203738387277415492016078976806202373032
+add:494932333118909260725671042445153518250291,4075181671023511749962590099189964240222,0:499007514789932772475633632544343482490513
+add:-547362235549081743238187402052314301548,927175407052843450557369599383180954617147573544,0:927175406505481215008287856144993552564833271996
+add:-272998916785610528588015856567128410368677679830,602403911895041304594532488687738325572579146,0:-272396512873715487283421324078440672043105100684
+add:8177918913965812142072794805257040419006,838843558448368858294329869233866828152454,0:847021477362334670436402664039123868571460
+add:798568364983632999724049529535252351299484436,1636919605401113337112219636142485235118757683,0:2435487970384746336836269165677737586418242119
+add:4076227872389818674764507178478356204607924906,4858120806733600624675339938519375739087835150531,0:4862197034605990443350104445697854095292443075437
+add:-58122662125434671011329360835993435253491,73132097808279681951175475035160758741946537,0:73073975146154247280164145674324765306693046
+add:733775087409818416274588823315348054416,97371071518767684325114545482209171317320411,0:97371805293855094143530820071032486665374827
+add:-113771533173503933275852574248237858610647533103,-12104130628645378506655176004172910468799298190,0:-125875663802149311782507750252410769079446831293
+add:19142539887689220939206017561014662533486,24783822476272570995796547534197064407548413574,0:24783841618812458685017486740214625422210947060
+add:439837175373522535394537896444136762539607278172,788273119543040327881133870675846687731,0:439837176161795654937578224325270633215453965903
+add:-3980465773532478253498557952430511370686544744,-22356254466454106659993425179664976374433,0:-3980488129786944707605217945855691035662919177
+add:9650385443349312084379714880369460479489737296,6396197664786865714161963852384918829120808565316,0:6405848050230215026246343567265288289600298302612
+add:894227798078569418728694383878564021992203400,1182303697127187181785402622190820894529084,0:895410101775696605910479786500754842886732484
+add:-4968456861598503731688245766554869039074227065751,926904708071249932339986591447176660865869610,0:-4967529956890432481755905779963421862413361196141
+add:5744863136870997246649436419851337184337852,528486352801627277403411298307704227595528990,0:534231215938498274650060734727555564779866842
+add:5651588707112308839251664128448753689228260350068,984180076053671456754725942868445032681314220925,0:6635768783165980296006390071317198721909574570993
+add:5999152998115672648494375904218236573991007462,-15627181548166981556755315951112371297310,0:5999137370934124481512819148902285461619710152
+add:-37220135577661031799960043003324908060140177399,9970705541292214994356839103435039397499,0:-37220125606955490507745048646485804625100779900
+add:81418507001304873846314147833079242440551,32906438533170379081041165307454763260134,0:114324945534475252927355313140534005700685
+add:-93195022996360129134236780916054647692069,5347394971811231651758505656470675163708448894939,0:5347394878616208655398376522233894247653801202870
+add:605079543296413508307097975102518892738230991,-102491396779053720487374578863736177412235,0:604977051899634454586610600523655156560818756
+add:-110305166634594825509078326414660546828041104,253473010673771926873011949379610506924336779901,0:253362705507137332047502871053195846377508738797
+add:21931199654933572392043984306892711921146445570,2907527660451297402481924885414001739485555606360,0:2929458860106230974873968869720894451406702051930
+add:-81846516530505341747573039394704262141139282278,119414978059342373259474020371815492807938,0:-81846397115527282405199779920683890325646474340
+add:-7594376981942593652353502069500431608125593919,51500020414584784205697427672128650432402168,0:-7542876961528008868147804641828302957693191751
+add:136465982599750396225253353955535355661156027759,5386715282857389783661176620617283963576556199,0:141852697882607786008914530576152639624732583958
+add:960930288983993235515929578403745857227039650174,201668060600182361443839360602375118505473666,0:961131957044593417877373417764348232345545123840
+add:927399705750647791187277745876572384967669031,-673794088022646279670235088913126760332168167,0:253605617728001511517042656963445624635500864
+add:7745147274519362522020786496011332545870526042,19019754982701808405498074108182013455237249,0:7764167029502064330426284570119514559325763291
+add:-842589681484827364133898448093132213715096,66373404917619583079354798332238441802307622071,0:66372562327938098251990664433790348670093906975
+add:9158459055331725756564214096327568283821833271587,-7389288408299737295395199016916294076133587,0:9158451666043317456826918701128551367527757138000
+add:4944028992893254151938145908432799220246101,-436673227225833465221751159174587350069599,0:4507355765667420686716394749258211870176502
+add:85957500826134796993374704843873074932736702843,-4737398263551254522274364145346551611616824,0:85952763427871245738852430479727728381125086019
+add:26693268270411692795540232504436733736819493,4761693453843664104004802004918903884493929,0:31454961724255356899545034509355637621313422
+add:597280400846352101193980095689737150106994666,774020411370064574149407278425457714972829559066577,0:774021008650465420501508472405553404709979666061243
+add:626155559446956944212578906031124683128572,190636244537054762721029791162041488568193458261,0:190636870692614209677974003740947519692876586833
+add:-51338951497767599237983853763132687032134115219,68079208415865834874846470899944876794467826,0:-51270872289351733403109007292232742155339647393
+add:9281945169594691475182670852780411412286110132,4120131010237928269938977002467007362193300912745,0:4129412955407522961414159673319787773605587022877
+add:144444680217834068698978156521073014198828507368215,23691353332382600912666065659579140865069030,0:144444703909187401081579069187138673777969372437245
+add:878907846660280522460467125993162483781740948299,5727027980609935208356763794713340938325393172,0:884634874640890457668823889787875824720066341471
+add:3863121890985058037468197591726440896929526748,3838808795310625556439132045393084001945658165756,0:3842671917201610614476600242984810442842587692504
+add:-43851511659924905732938464166653593999167629,374198438005814389346971540424050513685984,0:-43477313221919091343591492626229543485481645
+add:22107098238291185428187231696045952139458647,-1094439233801215665665730295403509442215518,0:21012659004489969762521501400642442697243129
+add:-94370080435346767326735355398641314752346677702547,900650711826114107815166281187719185619458093712865,0:806280631390767340488430925789077870867111416010318
+add:70130581982287853776073835767285560754385359048506,-532362174374052657999220752357898449008895,0:70130581449925679402021177768064808396486910039611
+add:368905471254498539128761742427996559644271835585,271908988467870372234177722038239359722817938904087,0:272277893939124870773306483780667356282462210739672
+add:1665461612154764119629895499464633250637874,19134987808509688322855052440395621824879039321919,0:19134989473971300477619172070291121289512289959793
+add:-70082361212896736227109455495902573787866185574,63015365869689393850987592591316804653013263,0:-70019345847027046833258467903311256983213172311
+add:-25078358419757381745462531594488486741766002505050,6161145995589782600946047354747671861460817403,0:-25072197273761791962861585547133739069904541687647
+add:666708317711411288619476006374466033771205130,781945629304382958374150588014142227194285896984780,0:781946296012700669785439207490148601660319668189910
+add:-792815175132398652587456324873505574700585654,21786271555833620127501336636667271735069671301676,0:21785478740658487728848749180342398229494970716022
+add:8661916666639431619374961032583120863479342934873714,6870583561131081729711383493275798626139956,0:8661916673510015180506042762294504356755141561013670
+add:681924022906622856896996499665629155099035690,-1004571345497457234878302490699035957625595966418,0:-1003889421474550612021405494199370328470496930728
+add:60230268321104247199768325351860140731648751905,-4983405216089518546950014876276513305697847179,0:55246863105014728652818310475583627425950904726
+add:2918902473029364921844125458709973674625996417335,-2210652159145259648205005443331558229225741752,0:2916691820870219662195920453266642116396770675583
+add:6803277105307410414680931382137753681870063418,-776208865523397828037840355299954380619094803,0:6027068239784012586643091026837799301250968615
+add:-25003719704019868385876356333662873293268630766666,9372027355506508855692368294638946856664530455245,0:-15631692348513359530183988039023926436604100311421
+add:8627504130949202764401824904787234047442744,-5835544012798417318076520693682832657982999792109,0:-5835535385294286368873756291857927870748952349365
+add:8260090424580577318194392652868871801866634,36338984070638282375666743416237170513165272265,0:36347244161062862952984937808890039384967138899
+add:-2567885127747973574087086225772899311267410108214,5508239791588330680899787231378688448833646,0:-2567879619508181985756405325985667932578961274568
+add:48666808545649708354733246480044529199921866,13005891966314816519574625124428351433895270842,0:13054558774860466227929358370908395963095192708
+add:8389420702531793876639200928278611121728614873,72321325080169680993090249289587185602319073066286,0:72329714500872212786966888490515464213440801681159
+add:65036752240714453689171239051023570841745399448,28805290908818160518681925899689595311583946916,0:93842043149532614207853164950713166153329346364
+add:8528322759745304970664183606826265148753341767,5634304035479369557540127200029887348029829,0:8533957063780784340221723734026295036101371596
+add:6995036754431505162769439569653358554669540097656670,2722846684750068252266709009646270633127873447,0:6995039477278189912837691836362368200940173225530117
+add:4614880368095698349182582007399802736977295545255,11355964798518264828005986699392784240730268,0:4614891724060496867447410013386502129761536275523
+add:9765319509166162487395146409291488887181479800078357,56035915231430273323816838439018348917266581235751,0:9821355424397592760718963247730507236098746381314108
+add:-1138347106436233679061275009102135358639634924718224,46159563323218296802052742149061303164800629266863,0:-1092187543113015382259222266953074055474834295451361
+add:745228794745562968451209928390566434920348152,53527148122790166734511060330707072382963660028206,0:53527893351584912297479511540635462949398580376358
+add:-588301306658858069453782008551175393534786100,8712212161075124266879455562405482117241102217433446,0:8712211572773817608021386108623473566065708682647346
+add:46121030188079872648021130753538085801476800798517,-39019521584656792767403515534426019969693675753732245,0:-38973400554468712894755494403672481883892198952933728
+add:29619919729277459435885608963790118777332486981,-52524378650492377071821593603303584552489704670,0:-22904458921214917635935984639513465775157217689
+add:98181101791503545628614157059694144214397756,1723001921171301726556866325501042586856901467,0:1821183022962805272185480482560736731071299223
+add:5153029430313427472772415517579200893432348228326467,-1040085720098897906942859081192037450000456492060,0:5151989344593328574865472658498008855982347771834407
+add:55004581470141018296263456318558804429110712,19377908184204050840224411596809648305527908013156,0:19377963188785520981242707860265966864332337123868
+add:1072136046766180220620214293788952197166650,-213267489440701336454712703551017176911643371,0:-212195353393935156234092489257228224714476721
+add:85287699588051450238950600525312209592474610983306876,517154134935551400902310308900510987679476894019343,0:85804853722987001639852910834212720580154087877326219
+add:3350463350046534274745259894989563302676256855267,99327287030974528755979749538531148523479743562098,0:102677750381021063030725009433520711826156000417365
+add:36843614050676239637380078007323912504843199635073,28079537606053733508869174435690016524431336472901360,0:28116381220104409748506554513697340436936179672536433
+add:626594076527207859168744152946567653623622813350,289789726716786201909677270796703151236725201042779,0:290416320793313409768846014949649718890348823856129
+add:93605170968295281833171644687712829154123033934,2543628559470582895074562108146894775567883682,0:96148799527765864728246206795859723929690917616
+add:2052998161971266479740877443236081325994829866117101,3539290099275844711415812545767592527236681167098,0:2056537452070542324452293255781848918522066547284199
+add:5417604415616705991065803076609145766510431919,1353196489306588682358657032784715674378273388275,0:1358614093722205388349722835861324820144783820194
+add:272499404407187599426080423265627888541662659954,1327146833710771382036670351680559306817615656153,0:1599646238117958981462750774946187195359278316107
+add:-699651119896474314900584685497791738111506192,-69672515802110594977623027100779022212514726206040720,0:-69672516501761714874097342001363707710306464317546912
+add:712509548377940176185869895492904750887086413,56176731066398404861602715769426642572627041935026808,0:56176731778907953239542891955296538065531792822113221
+add:7143592025239088040306437550950750880457741265799,79269337742179821463637514051770454228086789838,0:7222861362981267861770075065002521334685828055637
+add:85784228041270748531044763418005303861773086316768,479955707155465525495908770086376625866496445325,0:86264183748426214056540672188091680487639582762093
+add:8633607053652219081012560844815432350350653816,-27730558580923841131198160035073520602640809937568,0:-27721924973870188912117147474228705170290459283752
+add:86298209842676209783265202243860839968224984059,-14653841574444115669146420066088654283351629895,0:71644368268232094114118782177772185684873354164
+add:625971576355871986206876583141040580270991368399,1591656865887426266688630862274904247349299714291874,0:1592282837463782138674837738858045287929570705660273
+add:8094263949925391895110456153285525932274467906035,8828498248880817055759174086148047904385900536902829,0:8836592512830742447654284542301333430318175004808864
+add:82237003877466505256157158841093493965062954411803144,91547031285735648783322726839616156920221022695429,0:82328550908752240904940481567933110121983175434498573
+add:9037532307369285758380237914390337810953906576116947965,-2080798311402701935902060326222031250344403292352,0:9037530226570974355678302012330011588922656231713655613
+add:50808222368724781507631572923387538639418605384327,2105468684081970883293309501603862482752205466,0:50810327837408863478514866232889142501901357589793
+add:614695843041957442246110545422122115064228337420826,4173998806904671505997631134479640680904576896439869,0:4788694649946628948243741679901762795968805233860695
+add:1064820342923287213463623720132244635622458829981525933,-1475875068811641600756631104502187851477440325297,0:1064818867048218401822022963501140133434607352541200636
+add:10157417423684726201410937603631975742627908169404,7838021453657103572002203182188244231243955079181707,0:7848178871080788298203614119791876206986582987351111
+add:37159508474657925925316976495629749227380940275864026,1962232433094621175896408173610784235423834821218,0:37161470707091020546492872903803360011616364110685244
+add:90799712490109616993113540668118622608569993361558,6473804353031813836768680654473327017068712061,0:90806186294462648806950309348773095935587062073619
+add:8558267182043409385092694859321311049409595764196,-43855190592575763264725873745536703978426263630380326,0:-43846632325393719855340781050677382667376854034616130
+add:8862769280704424674067234121859535881853068385985015416,3128430671333004136364095742988724990646419068,0:8862769283832855345400238258223631624841793376631434484
+add:378208270494674096813484033949342736267924012919568644,1144519071359286777414333143799173474364390418550794089,0:1522727341853960874227817177748516210632314431470362733
+add:-6579674113733012078327119937146015198044119737,-3734798125808966311088975985514063521776488722551148716,0:-3734798132388640424821988063841183458922503920595268453
+add:2960711245597899800032622343542149905437203154361936820,499809669955373495757639913113238315793000498691,0:2960711745407569755406118101182063018675518947362435511
+add:25821180677407112730506355642526955953730655437874901,220829252352340433327709631917215008695896671223582832,0:246650433029747546058215987559741964649627326661457733
+add:4105370173243521757766753923407753132483088841573916094,-5859495212721416724385219267491089611350684535452912,0:4099510678030800341042368704140262042871738157038463182
+add:5163869845851925892481681950908088101067549260179722231,4902983733534376916005427640372005698206345908473,0:5163874748835659426858597956335728473073247466525630704
+add:8939484182366010380381840561998154807909027117547207,-5791890006411319753232065830229236658118816108248,0:8933692292359599060628608496167925571250908301438959
+add:701510238238697450550654709447628676278557462178180,78660480845787107751570298546903383688737254959620217,0:79361991084025805202120953256351012365015812421798397
+add:341765117982065537129466755082499645994576852735,692520757209429295113115688021272259739538890867946,0:692862522327411360650245154776354759385533467720681
+add:-4895783578731845919967474094433303503864596778179935462,-8364042240998784278401769408809806799945229261776648,0:-4904147620972844704245875863842113310664542007441712110
+add:14238409419953914857984647802372979092302755219238310,6371574430505907367749465495358382099864633219840163,0:20609983850459822225734113297731361192167388439078473
+add:819145829642159547700859583648855896951539123580831,361506805586624128214007976586393021628930076090363940,0:362325951416266287761708836170041877525881615213944771
+add:1877636417667934516336941709697932194927216313530003266,3110415340804941864303432168123355167418335131760417702,0:4988051758472876380640373877821287362345551445290420968
+add:7672066575928913691752679142441515012172611183558245718,371851147532253430639711983046051123330781047618685,0:7672438427076445945183318854424561063295941964605864403
+add:95512312207249366298896076611182343964081859466,-97124870343231010626703079092608549509450053912,0:-1612558135981644327807002481426205545368194446
+add:-5806422968663023549900750663638875296207673594658363702,90516128085557874002777142664275230359248090059,0:-5806422878146895464342876660861732631932443235410273643
+add:-1527157822675106197481254438080912892158041984128532354,725563661143607175528703551625121106037288811283,0:-1527157097111445053874078909377361267036935946839721071
+add:-42827691392859896582177202183556705231114395686423,45128827735882217281406911116739020388874185279388551,0:45086000044489357384824733914555463683643070883702128
+add:46043838505488963276375641613705710661972295575962167,28467164488355628577488094369127349235531802379663224,0:74511002993844591853863735982833059897504097955625391
+add:-38951950148008162832054098288607961881664530927148,8335283480464728668637429037127284541356281150509317,0:8296331530316720505805374938838676579474616619582169
+add:622249316814675692027128671081941223678839381254582193,7261720220517111354905851547139726385938166469124332501,0:7883969537331787046932980218221667609617005850378914694
+add:3674907036214085782411042221746956364413334313796,1921363713435768167432104932165249283578036436190717,0:1925038620471982253214515974386996239942449770504513
+add:7188482591275581867180190647387989483887113319876542897,6602680320762178166851882906088739930967430231717025380,0:13791162912037760034032073553476729414854543551593568277
+add:-1122742189773381273084251248143689561591037547534016,-968674210476153943757292285354448302755574664218668317,0:-969796952665927325030376536602591992317165701766202333
+add:-5630591882567573704954413450307476327113066874903314334,39824636924677667925199181345729096573735144801160,0:-5630552057930649027286488251126130598016493139758513174
+add:209583289465308712087487686838240265261210109472315151239,81969909236232824125903325576417695025146872644272065,0:209665259374544944911613590163816682956235256344959423304
+add:647747950632636576869808198783011688046450148232434870552,916898592764747488235431320315097102338752371550,0:647747951549535169634555687018443008361547250571187242102
+add:28135712883527960051641471442637534495815689268599701727,-38552244671238077902324238695360695260926661808213,0:28135674331283288813563569118398839135120428341937893514
+add:-831441344128176770720666876352870008663528096084544984455,-2692062828036480019863362944971350891750264323444185775,0:-834133406956213250740530239297841359555278360407989170230
+add:794701017798083397494303069423796491577530373372626,-72102207786198755767165144812992747956259847426428,0:722598810011884641727137924610803743621270525946198
+add:197485890851875072994741135376825653896503519991,138163469337810386780302197638192920802358090884502167,0:138163666823701238655375192379328297628011987388022158
+add:937892167666694076995649413871805692261114284540745180898,484506468570589158974739913192421910069689875922723630197,0:1422398636237283235970389327064227602330804160463468811095
+add:49513458769560636111865879434482526113781325925566233,9100294802196263191040735829862469546124284819589,0:49522559064362832375056920170312388583327450210385822
+add:6804265638701156312303584072108871897818849901582,-11345730118278439960458447085533973659139348981794,0:-4541464479577283648154863013425101761320499080212
+add:51279593637893634015629961349071462173442991832147136305,-630963561638139460898375258178326027272464749013574827807,0:-579683968000245826882745296829254565099021757181427691502
+add:-171297863190088468833128267336456231676696349106086723,25562345013839243089120015450478579141692354834498920234,0:25391047150649154620286887183142122910015658485392833511
+add:236820721337287547681130447452461282950000944868027,7910172708500900617141147757503793584328456508673025,0:8146993429838188164822278204956254867278457453541052
+add:6265195034976332988146228918664074473854894060855990323,7606251428765818252926521082377358210182682774550344917,0:13871446463742151241072750001041432684037576835406335240
+add:89597374568972918585799186543628138088356766678901,1813314149334378741507569909010462456324603409087645773,0:1813403746708947714426155708197006084462691765854324674
+add:195306949022209072289234099720202676610869290157465206,-994716438467019815849178678443452892613653602203942,0:194312232583742052473384921041759223718255636555261264
+add:-939205563958045162651332219711896963000039406190357,563202907700832072617064560363622275558376679989258989,0:562263702136874027454413228143910378595376640583068632
+add:80098286952047593891272622966959373457660113936107,5904947277434951020763542155046693897001992702425164,0:5985045564386998614654814778013653270459652816361271
+add:19798014000926405624727315383918920042183182364693,6487262615903993794908286483828887670955698777423148134,0:6487282413917994721313911211144271589875740960605512827
+add:84945814099981001691936754290990954291541653727223572796,-456805979472350610125202046336073888213752286874218,0:84945357294001529341326629088944618217653439974936698578
+add:2512089645159345096564730857111312670343564829071686,2455481799353124733391499423535890463012321535291607772379,0:2455484311442769892736595988266747574324991878856436844065
+add:73301381174453517580526931086388280775135813526768,4626165037419596821133153230043681255350276120564978,0:4699466418594050338713680161130069536125411934091746
+add:792820818959899903274588755045896284554931997668781703281,2595874074799206526967637468037895862567437806098280407872,0:3388694893759106430242226223083792147122369803767062111153
+add:31597081840709827246680247566853001879220752914725613176,2390964620594830956235541402980808255816375199839045,0:31599472805330422077636483108255982687476569289925452221
+add:31597081840709827246680247566853001879220752914725613176,=1,=1:63194163681419654493360495133706003758441505829451226352
+add:2037822438092847430389261539441146424774943894590,39916000644658200588230707520252700806573106896546,0:41953823082751048018619969059693847231348050791136
+
+# Small integer addition tests
+
+addv:51776377,-46479,0:51729898
+addv:7494538123,-48092,0:7494490031
+addv:5,20101,=2:20106
+addv:626,15974,0:16600
+addv:927,14290,=1:15217
+addv:71398252,45970,=1:71444222
+addv:93063,60606,=1:153669
+addv:-4895,63134,0:58239
+addv:8033997,6091,0:8040088
+addv:92778437607,15749,=2:92778453356
+addv:807578710629,-16317,=1:807578694312
+addv:6722,34150,0:40872
+addv:484482964826,45791,0:484483010617
+addv:63333,19921,0:83254
+addv:757593394565,58611,0:757593453176
+addv:5848315192249,20055,=2:5848315212304
+addv:21778,35258,0:57036
+addv:639687980,-1547,0:639686433
+addv:-8993430803,-39481,0:-8993470284
+addv:-825483,40649,=2:-784834
+addv:375685401,51109,=1:375736510
+addv:134791583451863,4578,=2:134791583456441
+addv:53129115309,51316,0:53129166625
+addv:471178234304,3338,0:471178237642
+addv:-7636956216875810,23137,=1:-7636956216852673
+addv:-2312413443812,31719,=2:-2312413412093
+addv:5200691919,55510,0:5200747429
+addv:5715872742,43764,=1:5715916506
+addv:5568388095431485,6290,0:5568388095437775
+addv:76084126643,54578,0:76084181221
+addv:96531391779281,46438,0:96531391825719
+addv:-828922693,15465,=2:-828907228
+addv:769843302686441996,27790,0:769843302686469786
+addv:1414000736454,15931,0:1414000752385
+addv:606227414766,517,0:606227415283
+addv:717100323961,499,=2:717100324460
+addv:-85406334226225355,-50533,=1:-85406334226275888
+addv:-3753831486,-36277,0:-3753867763
+addv:-58465715745893828,12779,=1:-58465715745881049
+addv:2855399155447860,5468,0:2855399155453328
+addv:4552049505281749,-33297,0:4552049505248452
+addv:87837072754930,40967,=2:87837072795897
+addv:-42693214607695890,-30492,0:-42693214607726382
+addv:70742576302309,-20599,0:70742576281710
+addv:118600972756003,10194,0:118600972766197
+addv:-882812251166,55167,0:-882812195999
+addv:-416381834108529,5090,0:-416381834103439
+addv:2956620172683281,-15742,0:2956620172667539
+addv:2711117679184010399584,9500,=2:2711117679184010409084
+addv:1356315685039,40425,=1:1356315725464
+addv:100388100074891247,28468,0:100388100074919715
+addv:735453579551845,-55120,=2:735453579496725
+addv:9573520208716968,57962,=1:9573520208774930
+addv:22464333496911435917,45263,=2:22464333496911481180
+addv:2318330134061664645524,35817,=1:2318330134061664681341
+addv:40085116522469,35577,0:40085116558046
+addv:-9824195637526213,46625,=2:-9824195637479588
+addv:1387219546869173,16428,0:1387219546885601
+addv:519326948996459554946,16498,0:519326948996459571444
+addv:901089575144273153684,48818,0:901089575144273202502
+addv:-7267047498859484256669593,10213,=1:-7267047498859484256659380
+addv:2746871124496359442,58189,0:2746871124496417631
+addv:-1505797511965887167260747,10886,0:-1505797511965887167249861
+addv:816815491488878842,49097,=1:816815491488927939
+addv:16917424131349552780253,38836,=2:16917424131349552819089
+addv:957454833834708924361,39916,=1:957454833834708964277
+addv:202026277214860503572,-38223,=2:202026277214860465349
+addv:968746861113481671,1030,0:968746861113482701
+addv:895889431267844251,44333,=2:895889431267888584
+addv:-3357720693387242036833,6150,0:-3357720693387242030683
+addv:659201417242721199959654444,44813,0:659201417242721199959699257
+addv:-400853063392189225718219,-1010,0:-400853063392189225719229
+addv:7218879194561993107952676021,-44154,0:7218879194561993107952631867
+addv:4721568551140507782,28030,=1:4721568551140535812
+addv:17034283717006469465522672,-11569,=1:17034283717006469465511103
+addv:41795594273804830816397,-7668,=1:41795594273804830808729
diff --git a/polly/lib/External/isl/imath/tests/bigmul.t b/polly/lib/External/isl/imath/tests/bigmul.t
new file mode 100644
index 00000000000..72974f35827
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/bigmul.t
@@ -0,0 +1,10 @@
+mul:1973284924569393016522181930166284437824113120930085705223363410232863255766399553325346410701486329074823374249547700471683909277697787590783678904983357211584574690370289495346677331618312561665754485123402827162476353576735207718451299565526093115255556962215997764515429748902159033904867393928929335369918394864191487555087825530530292436823694624357846430402766705368186347858763649288740551240105434820489955559033038872623623075504620415436212337263593361227009430895404467373404212231777284568356947010238293550872942631550054733886261493387307990754063500729850132294968984927109971586336754260617576297578,5023215555039217191451486096670046812323372237867852342682903508090873804207633443539517026163606065770027196694503291009850587117226026773591715017125540836707619882023150680605967194554434367524090941938814045780235333982097410791452776449214446635671357519707417878752761895933104747199582531838714305022614904134506738511247696618513698871318914624938137416674596881724436242382943205716649496664131501091102879563857843031208992280893614063087964394912022421136928015233318011144243860597237613050611024432789921991289922378761307428111094457098264457145099945444765267932710530788173695233378407323077034767182,0:9912235527621363370177765461045903296757346464251250997934314384765381968455767811674327750035883028560327843635490083086230089733649800500491928845965808260177110097000550870708488183060088779215210481900113545281854124601490142211180660492441361405426298053896802091578235012988730731854809702026093664780523793649405978324745399501432045298507869343282835244908856693641856464415460033802080004246708824900236489959461486545994943320360059459917374730418136788819890973086342429995201653932338829740545718352667527142958499428354077966431655595175455785104618218647409782931121099857213491801531717606789462812743975739913830932552436532349361163108142395102143904119547756730321871557900417573185916761969667939077354954258105548072267528998411702020631497735552158986372677452750936969993423245268272976429454770189221077520557005286622417163333812030510164503314440581497599501417407932697447376958591635071781976491704916693799964449632893911830806101578411062044010045678256608720149155356874608716245388282176400921764516344436742619757576145128777884235797616593795005421758664915151768829194432974835591116318659671888399376705850603804666493415116788205809451378581533592708248188469927900316495904963905315042780485196
+mul:9281860481025428743103260720025399298938288092709373682664752121448026422364244176957076161560781963714610840062462308785533773682081509516924811454802263149810015499242805866671806182669824281823377004291671016071522932056033291108610609315306035746008726247945073883264784349702632503413711514594728450092072160898603477481125780254532680608704164997261749601100642928524030186658056860132922920804055208139127600955714414432667835794981195051773905850760614924210968557995928682559530646363463541164514351639956960443946215999260668876064044712007044169839741253208493501852117173644320085073436239558982298112600,6461820852819773895887891707090409545105222339300767589991593922286229155430279300935431963821489860557211392101557073166691740801924350342690481832500741574765066771636009594821433888176432105527291712269105001105197791973525400419521802156326222007905452621388581343089554119326311972031808789454501569850634390353513026195347029048776084662261279361336878277930892526127759184987426337401986666833244149616653136274450771865938000177859526607860886891713725823803723429415374914088095471203681073462945634413721478459297998380784046348477788577160851236668812562054262272695670208399244540961973019014052558168787,0:59977719609253892722042877572104051408101805397813781927843789294722416373486626629774528405272256981042258018309437739185326109543499153652843618549437079862481903741355077622392955980952291940377584494183016978345215858006577896133494138343531131577292900447484484933940153864330993312663423548963573589721592630804430303529313438416057807260878676382165577508312265364581705446497795257921765099792473625934500220786302375753400097833125635066325976636969158668550422583295871444269629329520664064347927080680043172866686997969891857469015379192927001271209231629114491574459392387236668293395718184725588195195152678956030072754849704861168107422055308610203187476081482745232498851974127247916788413967230550779676328898994935061206241398061433819969649590309647846577368325165533615473712118854791617654923496518553311816034223039109644818155748055376095608924486676004240127363839126636148993476097467363646856228375774851238347182483585640237087473022416289005469183518515797794634470718006577945646586807657786278665230204669208538087683902595460600395463199673225484879511079106227162215467672070600187376901683430397215820702335580004490264383605166178465290892905016286750248542616725432536301930399671042547182331416200
+mul:7912472862067339862128371179317677419131938894010486952786566311807271094923069332388514681475314477095129839383791878789616020411634591014351511065638534352498100902940229903010080076033147913858702310386781454704764453620638192722142673704997301635080657906841977228453431784636268795567399742877979696735712353260720882016758802630449316568009735495464820484500112849579042319792054180751808291492597692968145199206126879627571212323371773988020895279516215647740755736659817523229210171324629444663573614970129038286402265282862415058866062409919400686067571225883598025018993264993072866008153094783713777842233,3201725902397772208341447704654332382791919074661304465094673003562268414312780910138677841790209187781035267718271550359273576299056459823432739891496517659999050131295751440278895964609377686119310540452547253245263824257293859748569384694164098523184164132157046027096354720108308754361750383079701345225130461743071738716695085603994849362372761995341700678666090085339160622218852314697895484240550249851988347340743956951710723755778934782102893613303732727155104650554024190836124710855983325513102342105122420688920843770754330984726835478343584190293399561063733594503384748007915045169469662902517503038695,0:25333569314500437108599815772429501373680322608913314601365306943723819341950927345977940371140685035806629270878047237205018842387430734765189552850021696237198239642293495906804381299300903869208226135003940108018078759100293636602524498314852735550782128370170231188998120042175944314926905277276072583015211137886295474308983469549440318811455833426554950412383746982707726227053848985460478532792206103062118340221448441569085773835002535297094293453339349660395100207046263749435022808551287672469069089094272260153240006042417355640412016581090184175248699060812193046639667626562834648506089700951846853126579987123062116039551606757622165057350453806797625779923041984890801656780414838861143950031146465833755299675796593415374155208079244535350498995407594399059593691111928041690837178741233242536763431952235684501117687869354466659838302659999947981358427161420945738762676783164008518789595931971474305683979958242844858007484186182190899873321326797561319701242638077070008212803881009955276396752500690925651017578103332620257046368245654905509937113127728190752471098993165924776064643774593124028657833142320855925010595166301204722218705230663769696225288154861096367993176213914077427256483682770659737804205935
+mul:5808324187702080655474460793682039951322360995931125673869791371944228644211378816153373947301972618673468024419809216698234959175295640166063762988660558965367914554186920892629719688885314609703455963977845612750271884481278417471936841270780965441117412446282412169100969024758168373693942106624503929819630667668476732052476696223555182229399707506392013582768244824407047675765649910095793401597173883674841030712174173054018546762918277235618291532242003800812379951389007164665130775067356573065178773886633889021628231165391459939591112464657659598153999220909590051109791624395690563647765208381376662473375,918729402656599354295427509394488660812811650986545042142269515180033877242550175086096078333116750486296504860969753318764397360672070743283292590583724934273152632680100030114145522324231651230586226973102509131367913652288365962855153489305948459500758622220373494821215068462533405866936756424017653969429333910353069394383604797810245598567635036667927595346004843560767022814009296322200770357321286444971587792559784113298566437496673370692769029520191499051311630305921790132367949451008467412252240244679740653218546677567374795191493091691181895973054804640859501444377706515253377176192389740639658485554,0:5336278211403410225943519042620965615785619555317282219346015490965402490268953491398003239066178293858189178402401757111178985594855165207776985174779911791823768749096812598455271447538265382632879247518155595749750602819268050354139537957357918637213694511920007326845297089513356097333014041709972148731714014484445915988844776055070353805573753587598803658209910219837061261823670768974929077810129897859279877221144040999522002504993617242444634441005711709824155554871737671327646822053264060565735107228683619949429470582056504636832239947839478335167862425087205811476396561330661528512869808146764271405115946216597932921295579405822441084739925916695069723138186232413577801041059512270479551378420195541014794476699958865807286746222858840284109951768425928740087238483028034722002174473841150445679886458245212446868769523239331330174814615221560520986189551103233794829342754962915857263215385954151542007327435281109291419192156862517657537231189038431999019986573647246318902197844837896116701072282756311874936853442457550589683870364331449005930361210722151521672814074171107488735222046242474639960036313988979683887454104915755099621937143196324447593623621066203333451482527676410948714122996747858076347124750
+mul:4289351015617211853860547293440287163118502026849525600172204430479364457520139869848831815115110666309028281362257922027167887676604882712946357785774765671053291569361256480674248716110951095880149104811531028000846825692159030869973707804728263847551536308296065212083263317121194233870838444421131817712327319493025493358961844276996294363551631856740972199816713986701316425469067461982409331003038962007405485449957519072614334803913032240759760944833349605582847295426216585712797815837902507714668306750095431507743637803032894122691956397938532173109072764661515711293817060848120252743975673113125247753747,1129243400327281633151431371474891473455867467281646580615131416918186134500058210362967474476291935913056166817170589720180888384893984130837655605609160519483475686999411456978438146043336536562159220682249690564087391733538120293725815373571240283145745271266418667658265953408844001550460545760069911655331444115026283289502832470850559638590225665815329814544221402813003890575490644213046498706732967784948480361985741430703857522843819419578526133778265155095749489410876608829677795172822626775506026922427707604322446404480105940239935673644113523059324254840712255877427181434254002649024354681415060823887,0:4843721326072859217924739456975877871730592847101085181527790647663373107593901947296442009364096344634703274313593786101304850876247763256161098298112279311640124203085232376040570318789033357875445637660657625729801200284217407957188046703959398051857408830260318911921120701333722007653177281821055544288036482973644506286720667660669123827281708456990562589037743832216048193876408309523302257690396843316573270798223002206543082163754435230120328349462372851186274316082236306199355982964083210551564485517422220956818077182845893000928069354900697467244100517711217647512106740360746188198070167537230256896186561769720724666496535533088417070244576470000350911551644970207092820479716847918547327933258080841778598694603733794328556831506027782599545271976125608421461150637806657972513810116161800305056210665818016285706544698227685536076722128657311114222869723283459946629814469251976435853584113074214728600366960017102944781196949905674572781584251454518622141686465871411947838733201476173396601005947322753083122168399723089970121912770142886331646964005500389958994113759402037759299455183775918663007587029195358902062641122546567477401625532541758569470800211805386875050358317201026695356110634225798225911354589
+mul:2922598094751746153870691566295068444832682377449634443644452036808313025110180304221606287367480270511738542685007831198718549192848393891804644713550364054117828837916381145944541939810080376799967571912016414096689178814643326642017130538718508791191026602318951021214103395742936719511134851054150494365154144550755804519428501885962875546302716557826154750576355553275917160667544245815793363700075966760245307752621192750454214313695198971665682789483848832034351563529541544408090967307450920552147497375102711833800774226189505763460050841396334194550570633737523051548126923180438589141499584449356454157781,301263854476835865302831775981280157037775814731880717517906672139362327909576030289130356551031249856290116188787587208441664042085339381130045070287550419156538713298378724228993892995370333046698005135756870427773491796745257234813488146992861769360888649780752254778964967516001628591841720032608844779416229017746534677888032360001957340989928039014267141513178879025837777147645983010327629059951078283105727024828148762758710195230027569199491918547602586967248624457368763471524299806755969674122616318652168130325681600833992180785147209796398791957157839966041221298841443636110696808763448994316318819400,0:880473167111567810988117967961880121548976598870490103359907404451794288634314088754703982882682833177383915593219929916760062726336137217195565128836228831115945317704393055974317368390656797236936312760587634287099001130993733243945419647905839367532106871136628959505856124206216765869030390930116922779023015952215753780775710838592094598640777970191507874750041226456888332070206936111152887141719425417531881441970211071893599749277222881299254752348929477247066394923935790203657132250180904188191913717059363295447971852930353504673614060561262045695029116400460109271428627838849952738530831538881267424864968780605625590534156059660049417419319454100204293309555760730912655165939915172711384623654862226288504196439643394977024748646967678483943835665120965656012280087576516616128951989019537622931843487928203695095825088113381854602767942831065334578782746652133152957849781352666171117141170614812817658757480681486453133627351917446563065914034736341623821165223200244445057536369218334564861784940394704850907451562300721495943024972967062949640936264682263417359654728928172240308459032455914059483410980465823622773353548898797178794257922243219031264284831902460218578846768551900722035824054391273507243751400
+mul:5926829196540658675475456498963270367274167353270350161220559308972890667000611959077400634022036756298496888045889139127967069561321992685909920175362591913993270611799645183177425442645246583405296832015660977965704980797187259222752640840230405885131399744453603991696537021254629232292058451234918953535616811141856188592686058223965739982132693674564657697584188823828175787137971950097846827086108380914550087286625763777114003492300442812034505494306586173660076762683909293356952194336742697639190379957186138293602890079658463645699601808928093978909018729566309848085271814423786075811123687515222571521141,9951748549035347469939830875084342841213955171500540569908439680913759851880792256750294922770245208009299837781200411491572872855217655269162163547244594548791001649285963901760838066367556260426444830819384430864282488995682230931798936940632516431790824149442647895647799515499501451313199296478183164266650410143061944307590041145587301786773822623122005086984557462948454440882483631228680923933447857195870319437437969503685592935555841532972330863543676262890554252868386868097538156042902583850929860163229668324731088466679335541839144081462858536522998396202372335534127835253275227166439208550011362833647,0:58982313857053834210030369008701535470547846378883471574850906519661590920623239557155133816718872389461593523638664405853333986848705490618952594452832827902837873064739619027951652972791249957555491448326595877448003385631909355204580249078753687938446662770501781443141702574212326646295344874829910024290326910430502035229144841509314463725728935072109280568176044293667824135683356181998327810932214680277918878645875609893787816791489540198200526206052593279579085310784507516815859424425808996966049588369054806335526262661190188588991128921011359320086022801222253658894714772351423922462488376381753960122147656387949595523415175858244128147046721635779584519776716527922563179399569323397526878913784277530861145139796781253014531853594223956266367885067511225156573281630685001517329742811780233540173221050224903621919442416853554192768813644401915841492966828144740472647777117385889467734627421827100398019644421335032837486242511571228006782734808577532905812345873829690513970221918856437531183865939487578348802015996867422278241109287621714275599191991940919835845537011096714711601047529737712802340247704082674118292833054347839678093716883543951111177062577074608322061562989806239684134854317815924284926631227
+mul:4777034176054735892839001319154604024448982911062996662961434499047973311450046365095175854088514975567276445923641765710483565552588310101703859907398033663982963466700114736836981086820103724619793226902430054022230749484829232751622018429096822596030038641334221042974404610831943227778280482931541043539126216389807230921518942393713547539642721143788088068568685638257090375125430847183020265156489658843788411995875911054271475454361570597270062164847413843213234002767652983163982217031030775985346429845722052312845786262475405890214193945400669516695016006129145191835497619324112510419184839333823563038032,9827138548939292009245650065800975788958754975503505329013026058397999436949984425213239460163893334243646132127297454621612856901543246299673374601632283715496329281241648395821925002725694160249373602782352654357507333003611095526709537503510444389839900076419267762739355812530600135102575311854184301816642079363387499882043347624028484658998836131051290010878235398822043835106058212641700259728565297115088713153106682478432953135863939627050490807699853245333608896404452729513744632901892423136011428170599697693508420836045009263224191727733246096441225270861482533930349836055052069956275296881553010823844,0:46944576701107943679938938351717570276643024426351383376012128990331836851800394169999825926287789789923977857842224952030837018641751724128416777942347287817243085205947279140888810687502712653904720940250076045512070807034595001066901214351395013853583253749775182943641508176342644616344704991826014772126193902151538695286620417331840280282729602713896669409104608963314021947099534454163546746786314376632556034151803662894104512257731557376023921031478485341917927131527641804456632089758164963179174829067502841242835472135512255663254933420936078744362206666240251798031087309505320414834036730091215957763177449453464018931816818279479765564154397725457327968428958452351403338069002258937875534583660748382069795371892066725535235829019294948550962261648137489651867767182000050986894967544702207404744805388059998480229757580719768298728934644409403172897264279729988289280804868097625427040524002128803008253639601815039926425566665683322030827022419320049680101981176755790419161472786615666424889499802013777946532365772475376346129529789899467556777542539903184853306724757517591411008018192458452871055585402125971467717860280265556030939477806408511006676155314529119943122617934755061739058181638708393543824435008
+mul:4718526549709911993506825300392344853225467500177328568314994788126810717786579407393677363360732454086076553654622431077040278132967064493298016988387203796834942642515095105038480589941892582203464757978762451494680419073901829593050682173084623555079499639864808992561773015425098686639107710126506218374693057900167675112099207386871851914556838486427512658440072954892382195328941863291925131611709258615015617716874132201457077873908213746723440854928237000349411712082236090494727142820721728009499408048129273013743078395120046662079326001366135078211783789585155007423087104738440174209004586903786989164923,6864909625695099184857987413146793144809795231762816099678934112289429933759119594825554881121839952705699464175423549805747165577308703501708566885788095967212817910018877393281757866693495857986692383902136266802917073126657350936148259550527207353925931727830829709553153285795187708071469565512676957784213778578364574484904487858142015156737351049851111701482889769961092136069932966937675469744753107902213424358119650624652509775218017409565394932197216635621683624922457211807452760603826715508259815323885112220648677904268244358078258267292267766114067884100779411269652418038495358844980710175781452273298,0:32392258330201459760562074159505402666827022332133743824383722373771586724279936834893209475335792360740207288712753288966019272688772189727359830430112385377963211525866654614652734441343015702880600337106757047952016128925022121801109717569522414321736297039964518897435783148195384835215896781072440523968496981818936751998711792513353592722753606646586300140596112682346518934342989922440494425543851079417451668961455337221634115522324089759170630437711987215149300155598498709258144994089401776318144221493654769821130765906090094965112873750275198731396444109844761570671491936925731286931889673265998052517878340520697512644133898593713774598643978958986749813165344980644092219544151830910222269638171801555630525215918638130181021806972858430511411445741538921977552404857036735214137961033740561691592280961494473639844034425651660408422689100017005963792872277451240550916940855637560252384459024952693573633908574846415082397672705378909528200133322572418467010953663042748965810118650644957942518667994045551271839593077571232233290052571470146092765056400446256851048896070598829313006513443533069418336284379590405097307714842901615964467210622771049744023258299567880689880017261076464212353340481079608972991126054
+mul:9351359077717175899950414794158087603156751215661949004587120106073267545901109456791730860642333677736460489711278989024326442512123908471776539363116436679164824939981569343722408520504708037728468632659374071452933990971885163627008124264246742383054580586823189866118106292666120868893909093218961607925558747851310421259521224120112349616696032997520626166708182604366198593113508419711212092952552738381785471705126020208187067765049493707603435017168771840449365758256918178174456397001413868398658687746818925263901770782577181315131090723377262366519979729982933337084774328653741904208050516673656644156545,1216016766515133990299168668478735765845001733139931228142324729567294927452246949091528311290839436344864081129175577116760112996696086551953114162706042576570065867528105907714734959487715485323991160014202401109849117829323361272785163230303985302397208164280805555950490245017175800587222856847357832531423637659868015190810500399483016069191576487343684935319583093232012062136782881389216056886912824752493825582458023165949476390088955696767644291944525456085901327930362230500131946293930906615027984889540977885375442171280684232489081312736136944281636434187988121106769493755643246344604960317372762640669,0:11371409428207585816935645514971157399477456508122422645057323321908767523269456583816541352834881341044768023230578135410646986307902229480486969521756932041792070183404871499743753639195221172390950269396259738917572970086985537003463801797780611812023947668962735701914400160076584463668883897061046609698150079230869671219723047659413380098398681168541189318039580846097222930562274632561522358056585578630564543897574680699501191088545558042869487637213954033470545221407447339126024545625169695761828292387153041130103874335098480537357654083162452706238752455266859966099385082784949007603605080575226559633436587076629170515896969351447588541709062809148081408725380230173050904929264600376981651953193133627520880237674546041286603479563072447211757006563163317121555286268728294863795655638987849849029666001617848646789972884742730075162580289223257765499073795704140984717050187282907922384088916411395714743783224419377067797857302004785665907904680432071096387636727273241941645361614333739368488852077835547570517599052273376169343996742621847611518237883451876811880344515555813725251939567959622992970218067169395450107931883100562142495317614789690641680450835968600224117925675820963997683401725608775582419528605
diff --git a/polly/lib/External/isl/imath/tests/bigsqr.t b/polly/lib/External/isl/imath/tests/bigsqr.t
new file mode 100644
index 00000000000..67aaa506290
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/bigsqr.t
@@ -0,0 +1,11 @@
+sqr:1973284924569393016522181930166284437824113120930085705223363410232863255766399553325346410701486329074823374249547700471683909277697787590783678904983357211584574690370289495346677331618312561665754485123402827162476353576735207718451299565526093115255556962215997764515429748902159033904867393928929335369918394864191487555087825530530292436823694624357846430402766705368186347858763649288740551240105434820489955559033038872623623075504620415436212337263593361227009430895404467373404212231777284568356947010238293550872942631550054733886261493387307990754063500729850132294968984927109971586336754260617576297578,0:3893853393532835086992417436028929533017113693729112812565021883956380915141255996799612067028873878620962721020287843580667785031474733116478946359424550361012589585752973317305997480128700704790709288646018647234120006459544716434681174565732418911811134893433511190240729608798717705538511464455525691334268473593164287128437946659209216966182223959978048461766767048994203857805328335121781687530460374272192439643337616561191454804340602152636521570315735724808211136112178623597726761562233624418966697972730157242837023392799098096001348791292540282769112707428306351952761016511009581482140339266124773156503871585331333229748575546970788710593878329700066394630525667688977999379996797554988699433650675888676455423881055671268822403174758764173450801472107412934932928242628018889547481661696413558606207836289835238941646919528531917854164993719517257318458050248512708310597280868179529982466268126947562915613777011430797948425936457263384797803263966764408262497707996175287022739124394402973694264968889229848339525935294695324028820522528376607382070267797540723336423743427176925087940756280955052040945732043168661526388800230588103529678940221446182218158117656968368051493245055497411735966238847890150408666084
+sqr:5023215555039217191451486096670046812323372237867852342682903508090873804207633443539517026163606065770027196694503291009850587117226026773591715017125540836707619882023150680605967194554434367524090941938814045780235333982097410791452776449214446635671357519707417878752761895933104747199582531838714305022614904134506738511247696618513698871318914624938137416674596881724436242382943205716649496664131501091102879563857843031208992280893614063087964394912022421136928015233318011144243860597237613050611024432789921991289922378761307428111094457098264457145099945444765267932710530788173695233378407323077034767182,0:25232694512387950837246573965423768214659605305747920385364235438142069506752963638176638070663137697548178189512977583934503415751046457217304699834312165759735798834063392638459720554883875322668860726378103278773377069820923135889568597012480529331635521511826460253219709548240571066232289334814339006865253319737519393614525866345823654520523063598485936725991745466055344350193829007241842078415817997984841814058315445235956513287712770234190490867970313521815239706704426480962959318704528841466812066587818519893723352288704763970670959149274002543782704910304301127024275547153165875047466897500391977033070459139260182367193259631752968757844481234924736806232657312752696107333138306380229367277562995612116036553257307316583486420415930866764617533873750528784187657897741011800821517930103416987940072347360626799917296234474844881851193687709571104637725109465383256753161526510645230553484635324115139968700121652080718290604667285871496065225935146563937996599437542585972890644223726730952165788539505477436754054328420237106613886502086271044799562764032162609215838263998005175988570392248195621627510973258180359384380604104188938302848583871731189060087097132563112796351181762659883855872472102926784944221124
+sqr:9281860481025428743103260720025399298938288092709373682664752121448026422364244176957076161560781963714610840062462308785533773682081509516924811454802263149810015499242805866671806182669824281823377004291671016071522932056033291108610609315306035746008726247945073883264784349702632503413711514594728450092072160898603477481125780254532680608704164997261749601100642928524030186658056860132922920804055208139127600955714414432667835794981195051773905850760614924210968557995928682559530646363463541164514351639956960443946215999260668876064044712007044169839741253208493501852117173644320085073436239558982298112600,0:86152933989221603452383960579862529767754507451814327308106099502021338841158564739970946221037114450601947058545585968015185524235118008637093904307143275940199882886916868864207222193239426427361340073440244139751159451898557777069779343414467483495630400743470728307452356966341313677960852068933154671924573760734273611606091152908307935158991039816559413312322566981208062121327548308369676448001395998891570657014429725703319770781094147168569110700521525439009556347021461844081202006912863907929538746074819161945225863226888248444085706919956519264360573870762587910641782352656676156415732700656963630951402092115464901859063766186151616572411364019115388448066844528476234630236343390094769930168862863247247299575418570145375916876386437237082903988846801896214556691481561360799069054218343648585202335896476703207744614538742683914717622691916676976341150631784446520414431143406963418046854017770653263907209702756518001381533976295371716790304760562189392378368525802079624573216454183740278425217025651543107627286662679019527820835682239802308666416070981938963841923859050577866586430415553449794707717857305424419844800957514744493025148562704471289382692563184970909544450306975779736393494626043617522278760000
+sqr:6461820852819773895887891707090409545105222339300767589991593922286229155430279300935431963821489860557211392101557073166691740801924350342690481832500741574765066771636009594821433888176432105527291712269105001105197791973525400419521802156326222007905452621388581343089554119326311972031808789454501569850634390353513026195347029048776084662261279361336878277930892526127759184987426337401986666833244149616653136274450771865938000177859526607860886891713725823803723429415374914088095471203681073462945634413721478459297998380784046348477788577160851236668812562054262272695670208399244540961973019014052558168787,0:41755128733936470013419340614768581207469280475771932448759452471724306748308207056387185341042180822565865975190354615808904657250278538353955888696480598934323757476309374738685684994497716128880324468585630205909258071948935579506193339045950864572735480453777206082914955771593313309955856894724849311870450595834339482685071806743252667708340467642167114083116000124778596927193502323818049586734603742810042021276752915040017354940400178030129663940983913088794072426640243829816327008274324005485264616967551641307060646091607001504654635788964056297229985621142475464282158634817498369712218561902410195152713461864918871424016455091203930645713444133980971449546681537220327549312525941229246794507705534347619463146219624170792658352361826542837966194021639735363473953690177390313887375288592504393102090201580067126091162084412913867210871907813153659746483106875412725262090893163145926694590206586186591043900660223003982254816402106419038767972908977390372043067587105414843306130785601573472584510045946592593734424590918536936724371910844356800883765758566604517939781506812650805380392096724391320635856788305664509062325460162834870676905242982755100465091215613432199297726350243940958759758306993142242781051369
+sqr:6461820852819773895887891707090409545105222339300767589991593922286229155430279300935431963821489860557211392101557073166691740801924350342690481832500741574765066771636009594821433888176432105527291712269105001105197791973525400419521802156326222007905452621388581343089554119326311972031808789454501569850634390353513026195347029048776084662261279361336878277930892526127759184987426337401986666833244149616653136274450771865938000177859526607860886891713725823803723429415374914088095471203681073462945634413721478459297998380784046348477788577160851236668812562054262272695670208399244540961973019014052558168787,=1:41755128733936470013419340614768581207469280475771932448759452471724306748308207056387185341042180822565865975190354615808904657250278538353955888696480598934323757476309374738685684994497716128880324468585630205909258071948935579506193339045950864572735480453777206082914955771593313309955856894724849311870450595834339482685071806743252667708340467642167114083116000124778596927193502323818049586734603742810042021276752915040017354940400178030129663940983913088794072426640243829816327008274324005485264616967551641307060646091607001504654635788964056297229985621142475464282158634817498369712218561902410195152713461864918871424016455091203930645713444133980971449546681537220327549312525941229246794507705534347619463146219624170792658352361826542837966194021639735363473953690177390313887375288592504393102090201580067126091162084412913867210871907813153659746483106875412725262090893163145926694590206586186591043900660223003982254816402106419038767972908977390372043067587105414843306130785601573472584510045946592593734424590918536936724371910844356800883765758566604517939781506812650805380392096724391320635856788305664509062325460162834870676905242982755100465091215613432199297726350243940958759758306993142242781051369
+sqr:7912472862067339862128371179317677419131938894010486952786566311807271094923069332388514681475314477095129839383791878789616020411634591014351511065638534352498100902940229903010080076033147913858702310386781454704764453620638192722142673704997301635080657906841977228453431784636268795567399742877979696735712353260720882016758802630449316568009735495464820484500112849579042319792054180751808291492597692968145199206126879627571212323371773988020895279516215647740755736659817523229210171324629444663573614970129038286402265282862415058866062409919400686067571225883598025018993264993072866008153094783713777842233,0:62607226792952120707247651690259584550519870655409677855259967323970315280127523038352871914217595657318525178928588450738646984186124330548937584545791047411539195482412684246501620725878474982273096945918283314804856302186143180922532479221483774049169665661942575676028716750572824612078547029156326889126648510908500466713726943581967682677688720020286471235758599038656604686024251557579582894251121291196845804656311881653516178849444455844734491852772836158003590931403972989130702566686718563356156866003782202713979799591740568927365378424851203143470432976436058675581145034980081878073994378951069636407956044433595527157452771941753992894632221806355150244262738932228009536850616640523085668143546230350996800173647076957602749446577970514855423674477236535999309116324096409059875960147686741898480716484475884168020125576823399861877763053135612337099607591166573133277345115055382830446955279324436937777170960368837490516357978919384758079145639420844517829747508647571589827612402546568196379111371730312522985608775973653102317116479931771770023631636770509419737783921899453982796775527984382371135662826874391308916487368098573786023125281233044093938346589157068552970819362523463113448971217548940797438426289
+sqr:3201725902397772208341447704654332382791919074661304465094673003562268414312780910138677841790209187781035267718271550359273576299056459823432739891496517659999050131295751440278895964609377686119310540452547253245263824257293859748569384694164098523184164132157046027096354720108308754361750383079701345225130461743071738716695085603994849362372761995341700678666090085339160622218852314697895484240550249851988347340743956951710723755778934782102893613303732727155104650554024190836124710855983325513102342105122420688920843770754330984726835478343584190293399561063733594503384748007915045169469662902517503038695,0:10251048754084828769243329882069275971914890627613738671716877356696804611372225772535909788437192398839842991123901962510118430249474946611045135201967809016816348471137614785988048128241390515692315971455106778002837246102797924605981990933580811595517905674487926190125149743783912791172620685090710721294031418339826218705767020474113475213303982913823024270407367538077398654621734474924951831977997748681939864774457132880966130787121010568095721257658186826775993645732246207566570744542977468845272538470202747808100801988318054298959125301114504026010747921910115853973562914401985468980995690517283225637392666056494069338918735138921764426048557221613239082343742804403199476104847288722226052090168714977201702134281100828032952230896037194398681770354240611642273082773400855766704556982242260945911858324534827894030863019362601675206293366185548957348669774225514518006218467888321089699097391620575727815238097871345555390807646501726425056233120235063071527081727369212097120985047406879578675516214002560189818550388605034487273578377097275389460683099839403381468382578885231830676913607497216090992928203120279557550890527892898136710592601635774254477237306606095549841913591690732525191072433380838558667303025
+sqr:5808324187702080655474460793682039951322360995931125673869791371944228644211378816153373947301972618673468024419809216698234959175295640166063762988660558965367914554186920892629719688885314609703455963977845612750271884481278417471936841270780965441117412446282412169100969024758168373693942106624503929819630667668476732052476696223555182229399707506392013582768244824407047675765649910095793401597173883674841030712174173054018546762918277235618291532242003800812379951389007164665130775067356573065178773886633889021628231165391459939591112464657659598153999220909590051109791624395690563647765208381376662473375,0:33736629869445035074327166424244667388357269999486865605478076413334103798774353682775639542213830809145772052196100574522690756062172293340346900291485418359566994652736736860394553990711528438046447648607265759258849563437038985527522027887469536324986597076326498910837071795251458205904524980493828205498641172851466789655356761510862552511481361948668830231946389600859901152088906546349833795040838140061368522170448758952855372046595253341556353216263984297060270145341296413999867239761086030849655515473988519859922461900886021497209068404156115345891990869710785087691035884591154201820846643004027670616846756481869815422806896037776208720169056623748294226301861321525789456138753657995854650377786223245822168795756177015382020556433922740315469664231971951907243785787603463207205574424710054218646675174351835854569823483723752860910674029346480228748308601384452239082508478253308005445835634293503650832325029963894202698752252776230543203916010757514406789343217818289245459834266233887027255260435438561649500763399981546227245264080216426993032919933996719529973685635989795024502963596132673681479045820438921344384798517847291471865516742005312681288127831399544453631661789669782852521261353330598972583890625
+sqr:918729402656599354295427509394488660812811650986545042142269515180033877242550175086096078333116750486296504860969753318764397360672070743283292590583724934273152632680100030114145522324231651230586226973102509131367913652288365962855153489305948459500758622220373494821215068462533405866936756424017653969429333910353069394383604797810245598567635036667927595346004843560767022814009296322200770357321286444971587792559784113298566437496673370692769029520191499051311630305921790132367949451008467412252240244679740653218546677567374795191493091691181895973054804640859501444377706515253377176192389740639658485554,0:844063715305751868681971206141868238620448349106067649090713042117549119633369793955554348233719755746126280893464820812016005338079930881262278122705660442998154342355231619912542048747564579820455957515967658062579765882068075603317542476485725126614065677508294074683170609567910430859163617312267835677287917010092241479784627554606309976396139987941907937127453128868471672503456384949412832353492125047104125088327869349587314979541859707555223546684520169107982699720021602759206250992533576051949917523223132790224645209557953390063396322748548091847415504398952105342081716845349560247052750420294095678053428216713216713011181812689683492914196236985079977491424396246564512152250347194515570324811898058414788694226000558523630907238488791193859962605342734660937039255359759104296817461843423523782150363606482926217674814654230899763084537946295374731646288495775906239750491832422646745846855470956372588268290873333606787465192588104280578046176481855676139021153292248933293930046473039414083316216665998616344058420309846209053553460359073991880276416769133021195916404214034472772439130482850276889991434513090312643865962017932695340904893119106854707377145235453780149075870382271613690866218610061236826686916
+sqr:4289351015617211853860547293440287163118502026849525600172204430479364457520139869848831815115110666309028281362257922027167887676604882712946357785774765671053291569361256480674248716110951095880149104811531028000846825692159030869973707804728263847551536308296065212083263317121194233870838444421131817712327319493025493358961844276996294363551631856740972199816713986701316425469067461982409331003038962007405485449957519072614334803913032240759760944833349605582847295426216585712797815837902507714668306750095431507743637803032894122691956397938532173109072764661515711293817060848120252743975673113125247753747,0:18398532135176406809034490875693170758925004882141511261808766893882448134661308449674877552336295208917642945790156108898313095424805879501417605739586230929916416741917205011890576364165214842655074817157593175638265096642262911624804249958062053834777196200988231246651694562541632157282179693998749538692029970111424591747477697863942461566583625378474559289840644351696058468544250603519147443482666917127248552520455914618534358459972013595330956153533329148549282058238538359006965923000938192868814224682091707519285881336562876756579025080274645910079084625282553972963075141236187211115990844325515052297351541590023546664412131806032342665984009007162435318353241414465270052529631433227305387943571878454069329525592969380744392762518290885050324171445597112387157817625779490377052814617138025027758796703313537279036322299993462750908493008657797831919621067953926089315029584404727826473302371816974351550286725462756040416199337645083147388751639897989371703481110044912875697392570337540041944755640545845535510530045287632724843324253307769460477224412912973549722946229475760911133865605380194780577819320270517078651641752393246783502013220800728332790909778902389930435716496708472843056646872808640669152540009
+sqr:1129243400327281633151431371474891473455867467281646580615131416918186134500058210362967474476291935913056166817170589720180888384893984130837655605609160519483475686999411456978438146043336536562159220682249690564087391733538120293725815373571240283145745271266418667658265953408844001550460545760069911655331444115026283289502832470850559638590225665815329814544221402813003890575490644213046498706732967784948480361985741430703857522843819419578526133778265155095749489410876608829677795172822626775506026922427707604322446404480105940239935673644113523059324254840712255877427181434254002649024354681415060823887,0:1275190657182721248462063420980207026343022717532622175860219061730792418936740434742094796665906100480439897110257178409857469307077098501942134999624668547631597875340226548233364555044904897637802662331582604911532131450166620402887103231322314236615939231233057651679712668806821697694902550747299740911409056026074325413724541784521105637039150272466375734348928193048571410349655195899575836960732640894105648518962149080274129413128568380000791288924018568364735478182966987827049189244120982249845311602108211176904677903690707944807032554116276797233387539070384134761545289596978472118656073247977568361787904215232007927547273675655812990627547232348919520589298481108958425401154144890217117213559902391607690446197638363620347853484948687625457207482930736345600737267824848389507129569922536325291727973935250559919378188248920389764990722709984543141728260567769676565198058565461309218448131493714100586880045778660348267815919731674340804133476623427737669995140408727297933180816128182764727848278876101607499408120957922795369902531715310169128136970642349303253384538063850831674689811408417573400679901877915536329660371027882694070998224914758044726450736635586342639879086413949670062421005617619755229788769
diff --git a/polly/lib/External/isl/imath/tests/compare.t b/polly/lib/External/isl/imath/tests/compare.t
new file mode 100644
index 00000000000..98a11343aa5
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/compare.t
@@ -0,0 +1,31 @@
+# Test ordinary signed comparisons
+cmp:0,0:$#0
+cmp:0,1:$#-1
+cmp:1,0:$#1
+cmp:-1,1:$#-1
+cmp:1,-1:$#1
+cmp:123456789012345678901234567890,123456789012345678901234567891:$#-1
+
+# Test unsigned comparisons
+cmpu:0,0:$#0
+cmpu:0,1:$#-1
+cmpu:1,0:$#1
+cmpu:-1,1:$#0
+cmpu:1,-1:$#0
+cmpu:-25,15:$#1
+cmpu:#x-ffffffffffffffff,#xfffffffffffffffe:$#1
+
+# Test zero comparisons
+cmpz:0:$#0
+cmpz:-25:$#-1
+cmpz:105:$#1
+
+# Test small-value comparisons
+cmpv:0,0:$#0
+cmpv:0,1:$#-1
+cmpv:1,0:$#1
+cmpv:-1,1:$#-1
+cmpv:1,-1:$#1
+cmpv:499,108:$#1
+cmpv:499,499:$#0
+cmpv:499,-1024:$#1
diff --git a/polly/lib/External/isl/imath/tests/conv.t b/polly/lib/External/isl/imath/tests/conv.t
new file mode 100644
index 00000000000..23bedfa86ba
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/conv.t
@@ -0,0 +1,228 @@
+# Output conversion tests
+
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,2:1111011101001010001010000111011010100001010000110010011010011000100100100011101100000111011001111101101000011001110111001111001111010111000101111001010111101110
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,3:22012212212000122111011022212212002120111111102001120012102211211202200102022110202002000211111221202
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,4:33131022022013122201100302122120210203230013121331220121313033033113011321113232
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,5:404041130042310320100141302000203430214122130002340212132414134210033
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,6:44515230120451152500101352430105520150025145320010504454125502
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,7:644641136612541136016610100564613624243140151310023515322
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,8:173512120732412062323044435407317550316717172705712756
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,9:265785018434285762514442046172754680368422060744852
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,10:1411774500397290569709059837552310354075408897518
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,11:184064268501499311A17746095910428222A241708032A
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,12:47706011B225950B02BB45602AA039893118A85950892
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,13:1A188C826B982353CB58422563AC602B783101671A86
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,14:105957B358B89B018958908A9114BC3DDC410B77982
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,15:CB7B3387E23452178846C55DD9D70C7CA9AEA78E8
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,16:F74A2876A1432698923B0767DA19DCF3D71795EE
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,17:17BF7C3673B76D7G7A5GA836277296F806E7453A
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,18:2EBG8HH3HFA6185D6H0596AH96G24C966DD3HG2
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,19:6G3HGBFEG8I3F25EAF61B904EIA40CFDH2124F
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,20:10AHC3D29EBHDF3HD97905CG0JA8061855C3FI
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,21:3BA5A55J5K699B2D09C38A4B237CH51IHA132
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,22:EDEA90DJ0B5CB3FGG1C8587FEB99D3C143CA
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,23:31M26JI1BBD56K3I028MML4EEDMAJK60LGLE
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,24:GGG5M3142FKKG82EJ28111D70EMHC241E4E
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,25:4446F4D5H10982023N297BF0DKBBHLLJB0I
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,26:12E9DEEOBMKAKEP0IM284MIP7FO1O521M46
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,27:85NN0HD48NN2FDDB1F5BMMKIB8CK20MDPK
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,28:2D882A7A0O0JPCJ4APDRIB77IABAKDGJP2
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,29:MFMCI0R7S27AAA3O3L2S8K44HKA7O02CN
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,30:7IGQS73FFSHC50NNH44B6PTTNLC3M6H78
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,31:2KLUB3U9850CSN6ANIDNIF1LB29MJ43LH
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,32:UT52GTL18CJ9H4HR0TJTK6ESUFBHF5FE
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,33:BTVL87QQBMUGF8PFWU4W3VU7U922QTMW
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,34:4OG10HW0MSWJBIDEE2PDH24GA7RIHIAA
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,35:1W8W9AX2DRUX48GXOLMK0PE42H0FEUWN
+tostr:#xF74A2876A1432698923B0767DA19DCF3D71795EE,36:SVWI84VBH069WR15W1U2VTK06USY8Z2
+
+# Conversion to binary
+
+tobin:0:0
+tobin:-1:255
+tobin:1:1
+tobin:97:97
+tobin:8492:33.44
+tobin:-69393016:251.221.37.136
+tobin:-218193:252.171.175
+tobin:662844:10.29.60
+tobin:8241131209300:7.126.201.178.194.84
+tobin:705223363410:0.164.50.150.139.82
+tobin:-28632557663:249.85.93.215.161
+tobin:-553325346410701486:248.82.49.135.113.248.93.82
+tobin:-907482337424:255.44.181.214.111.112
+tobin:4770047168390927:16.242.85.39.8.167.15
+tobin:977875907836789049:13.146.28.245.9.6.65.57
+tobin:3572115845746903:12.176.210.8.21.16.215
+tobin:28949534667733:26.84.86.186.243.213
+tobin:-183125616657544851234:246.18.159.29.228.28.174.208.222
+tobin:827162476353576735:11.122.171.227.198.150.95.31
+tobin:77184512995655260:1.18.54.231.215.68.126.92
+tobin:115255556962215997764:6.63.125.254.104.50.175.49.68
+tobin:54297489021590339048:2.241.135.110.149.175.144.125.232
+tobin:393928929335369918394864191:1.69.217.178.12.173.1.47.149.43.18.63
+tobin:-75550878255305302924368236946:255.11.225.199.59.30.217.134.166.120.200.174.110
+tobin:35784643040276670536818634:29.153.177.98.228.47.31.93.65.31.202
+tobin:-5876364928874055124010543482048:181.212.112.219.201.219.43.162.130.153.141.251.64
+tobin:555590330388726236230755046204154:27.100.137.45.209.201.206.212.69.137.217.165.34.250
+tobin:2123372635933612270094308954044:26.204.252.173.123.198.84.97.94.88.53.79.188
+tobin:373404212231777284568356947010238:18.105.6.21.0.246.144.164.13.115.91.8.162.190
+tobin:355087294263155005473388626149338730:68.99.39.192.10.100.204.157.215.128.79.45.43.110.106
+tobin:9075406350072985013229496898492710997:6.211.220.20.76.13.2.68.169.142.198.197.165.106.64.85
+tobin:8633675426061757629757850232155550:1.169.172.77.223.131.135.137.86.71.95.134.109.237.158
+tobin:-217191451486096670046812323372237867852:255.92.154.114.175.151.49.93.18.105.200.58.156.24.75.180.180
+tobin:26829035080908738042076334435395170:5.42.198.7.200.110.201.64.35.201.25.125.64.230.98
+tobin:16360606577002719669450329100985058711:12.78.240.46.160.248.51.247.149.232.48.220.205.240.69.151
+tobin:26026773591715017125540836707619882:5.3.56.17.26.95.176.214.116.53.154.110.71.84.42
+tobin:-315068060596719455443436752409094193:195.81.241.253.255.182.14.126.183.113.140.138.49.151.207
+tobin:1404578023533398209741079145277644921444663:16.31.175.15.121.161.137.196.26.125.240.115.59.220.1.85.25.55
+tobin:713575197074178787527618959331047471995825:8.49.2.79.246.51.45.90.242.199.86.95.47.64.104.90.91.177
+tobin:83871430502261490413450673851124769661:63.25.12.201.105.63.89.102.174.73.208.109.149.109.99.125
+tobin:1369887131891462493813741667459688172443624:15.185.188.136.198.40.60.46.152.22.161.146.105.88.210.253.87.232
+tobin:829432057166494966641315010911028795638578:9.133.123.83.146.186.254.230.112.155.225.249.127.219.248.43.131.50
+tobin:312089922808936140630879643949120224211369:3.149.38.92.196.150.155.232.60.223.247.126.50.176.14.127.177.169
+tobin:152333180111442438605972376130506110244327899219:26.174.219.37.168.212.28.162.39.139.47.209.114.56.212.157.2.33.192.83
+tobin:-2899223787613074281110944570982644571450999:222.183.242.113.50.20.39.238.192.239.78.170.102.70.102.231.209.137
+tobin:444765267932710530788173695233378407323077034767:77.231.246.225.189.253.236.180.85.80.95.147.220.91.211.171.195.205.195.15
+tobin:2928186048102542874310326072002539929893828809270937:7.211.139.211.153.76.242.8.164.101.41.243.188.255.255.239.194.98.21.205.38.153
+tobin:-826647521214480264223642441769570761615607819637146:253.202.98.131.34.175.212.21.119.210.126.69.61.176.197.180.182.201.116.60.110.102
+tobin:8400624623087855337736820815095169248114548022:1.120.178.112.248.52.41.234.187.122.100.10.161.143.20.186.83.68.157.54
+tobin:-14981001549924280586667180618266982428182337700429:245.191.228.168.55.2.155.157.248.12.207.194.168.98.220.91.66.110.69.189.179
+tobin:710160715229320560332911086106093153060357460087262479:7.106.23.173.245.150.209.228.252.222.62.180.93.143.150.200.182.76.119.140.239.205.15
+tobin:73883264784349702632503413711514594728450092072160898:0.197.120.251.47.105.95.210.233.70.183.8.43.3.136.2.36.106.51.96.215.206.130
+
+# Conversion from binary
+
+readbin:0:0
+readbin:255:-1
+readbin:1:1
+readbin:97:97
+readbin:33.44:8492
+readbin:251.221.37.136:-69393016
+readbin:252.171.175:-218193
+readbin:10.29.60:662844
+readbin:7.126.201.178.194.84:8241131209300
+readbin:0.164.50.150.139.82:705223363410
+readbin:249.85.93.215.161:-28632557663
+readbin:248.82.49.135.113.248.93.82:-553325346410701486
+readbin:255.44.181.214.111.112:-907482337424
+readbin:16.242.85.39.8.167.15:4770047168390927
+readbin:13.146.28.245.9.6.65.57:977875907836789049
+readbin:12.176.210.8.21.16.215:3572115845746903
+readbin:26.84.86.186.243.213:28949534667733
+readbin:246.18.159.29.228.28.174.208.222:-183125616657544851234
+readbin:11.122.171.227.198.150.95.31:827162476353576735
+readbin:1.18.54.231.215.68.126.92:77184512995655260
+readbin:6.63.125.254.104.50.175.49.68:115255556962215997764
+readbin:2.241.135.110.149.175.144.125.232:54297489021590339048
+readbin:1.69.217.178.12.173.1.47.149.43.18.63:393928929335369918394864191
+readbin:255.11.225.199.59.30.217.134.166.120.200.174.110:-75550878255305302924368236946
+readbin:29.153.177.98.228.47.31.93.65.31.202:35784643040276670536818634
+readbin:181.212.112.219.201.219.43.162.130.153.141.251.64:-5876364928874055124010543482048
+readbin:27.100.137.45.209.201.206.212.69.137.217.165.34.250:555590330388726236230755046204154
+readbin:26.204.252.173.123.198.84.97.94.88.53.79.188:2123372635933612270094308954044
+readbin:18.105.6.21.0.246.144.164.13.115.91.8.162.190:373404212231777284568356947010238
+readbin:68.99.39.192.10.100.204.157.215.128.79.45.43.110.106:355087294263155005473388626149338730
+readbin:6.211.220.20.76.13.2.68.169.142.198.197.165.106.64.85:9075406350072985013229496898492710997
+readbin:1.169.172.77.223.131.135.137.86.71.95.134.109.237.158:8633675426061757629757850232155550
+readbin:255.92.154.114.175.151.49.93.18.105.200.58.156.24.75.180.180:-217191451486096670046812323372237867852
+readbin:5.42.198.7.200.110.201.64.35.201.25.125.64.230.98:26829035080908738042076334435395170
+readbin:12.78.240.46.160.248.51.247.149.232.48.220.205.240.69.151:16360606577002719669450329100985058711
+readbin:5.3.56.17.26.95.176.214.116.53.154.110.71.84.42:26026773591715017125540836707619882
+readbin:195.81.241.253.255.182.14.126.183.113.140.138.49.151.207:-315068060596719455443436752409094193
+readbin:16.31.175.15.121.161.137.196.26.125.240.115.59.220.1.85.25.55:1404578023533398209741079145277644921444663
+readbin:8.49.2.79.246.51.45.90.242.199.86.95.47.64.104.90.91.177:713575197074178787527618959331047471995825
+readbin:63.25.12.201.105.63.89.102.174.73.208.109.149.109.99.125:83871430502261490413450673851124769661
+readbin:15.185.188.136.198.40.60.46.152.22.161.146.105.88.210.253.87.232:1369887131891462493813741667459688172443624
+readbin:9.133.123.83.146.186.254.230.112.155.225.249.127.219.248.43.131.50:829432057166494966641315010911028795638578
+readbin:3.149.38.92.196.150.155.232.60.223.247.126.50.176.14.127.177.169:312089922808936140630879643949120224211369
+readbin:26.174.219.37.168.212.28.162.39.139.47.209.114.56.212.157.2.33.192.83:152333180111442438605972376130506110244327899219
+readbin:222.183.242.113.50.20.39.238.192.239.78.170.102.70.102.231.209.137:-2899223787613074281110944570982644571450999
+readbin:77.231.246.225.189.253.236.180.85.80.95.147.220.91.211.171.195.205.195.15:444765267932710530788173695233378407323077034767
+readbin:7.211.139.211.153.76.242.8.164.101.41.243.188.255.255.239.194.98.21.205.38.153:2928186048102542874310326072002539929893828809270937
+readbin:253.202.98.131.34.175.212.21.119.210.126.69.61.176.197.180.182.201.116.60.110.102:-826647521214480264223642441769570761615607819637146
+readbin:1.120.178.112.248.52.41.234.187.122.100.10.161.143.20.186.83.68.157.54:8400624623087855337736820815095169248114548022
+readbin:245.191.228.168.55.2.155.157.248.12.207.194.168.98.220.91.66.110.69.189.179:-14981001549924280586667180618266982428182337700429
+readbin:7.106.23.173.245.150.209.228.252.222.62.180.93.143.150.200.182.76.119.140.239.205.15:710160715229320560332911086106093153060357460087262479
+readbin:0.197.120.251.47.105.95.210.233.70.183.8.43.3.136.2.36.106.51.96.215.206.130:73883264784349702632503413711514594728450092072160898
+#
+# -- From Tom Wu, triggered a bug in s_qmul():
+#
+readbin:22.200.146.12.243.10.174.111.79.92.242.37.59.156.205.75.163.223.107.103.20.203.19.168.35.69.241.146.93.87.91.210:10305260085868809781027103920001537650251216529133196585936939957967423757266
+
+# Conversion to unsigned
+
+to-uns:19:19
+to-uns:732849:11.46.177
+to-uns:2456939301:146.113.235.37
+to-uns:65221819301662:59.81.163.94.255.30
+to-uns:-844378241131209300:11.183.213.137.94.177.226.84
+to-uns:8570522336341023286325:1.208.155.227.240.84.37.160.100.53
+to-uns:57663995533253464107014863:47.178.211.118.41.71.211.74.100.90.207
+to-uns:290748233742495477004716839092:3.171.117.77.85.127.49.10.213.243.253.144.180
+to-uns:7769778759078367890498335721158457:1.127.20.101.49.86.0.169.68.4.237.33.216.119.57
+to-uns:46903702894953466773316183125616657544:35.73.83.24.98.4.211.124.18.69.32.88.95.142.132.136
+to-uns:-851234028271624763535767352077184512995655:9.197.141.78.121.20.132.41.143.246.59.33.126.2.92.102.177.71
+to-uns:-2609311525555696221599776451542974890215903390:117.1.109.101.2.62.220.206.134.57.198.156.134.252.135.230.114.144.158
+to-uns:48673939289293353699183948641914875550878255305302:33.77.214.236.147.20.12.74.7.55.12.207.229.43.143.81.121.102.216.82.86
+to-uns:924368236946243578464304027667053681863478587636492887:9.166.158.105.220.232.187.149.229.98.114.203.143.151.179.13.117.242.141.170.94.170.87
+to-uns:4055124010543482048995555903303887262362307550462041543621:165.97.120.89.181.168.202.95.163.0.0.6.89.126.141.209.204.168.88.165.194.166.83.197
+to-uns:23372635933612270094308954044673734042122317772845683569470102:14.139.121.201.25.49.14.230.89.139.204.223.141.232.201.189.74.36.63.100.115.152.44.110.42.150
+to-uns:382935508729426315500547338862614933873079907540635007298501322949:3.162.221.90.36.235.220.148.206.72.220.121.230.47.59.194.10.29.105.64.171.5.133.101.247.195.168.197
+to-uns:6898492710997158633675426061757629757850232155550392171914514860966700:255.225.26.217.121.147.85.123.62.227.155.115.151.17.14.226.20.151.216.70.129.251.123.127.200.253.229.131.44
+to-uns:46812323372237867852342682903508090873804207633443539517026163606065770027:26.126.173.147.234.225.62.206.132.172.56.142.212.124.86.139.56.123.128.83.59.140.190.156.37.116.71.8.107.238.43
+to-uns:196694503291009850587117226026773591715017125540836707619882023150680605967194:1.178.221.36.198.34.91.147.187.41.80.248.32.21.173.116.21.184.114.128.226.148.105.231.211.137.139.144.142.36.59.195.90
+to-uns:-5544343675240909419388140457802353339820974107914527764492144466356713575197074178:187.9.226.242.27.68.215.247.155.152.75.195.109.94.123.200.36.80.1.19.58.240.99.181.158.175.120.210.195.130.202.54.99.2
+to-uns:78752761895933104747199582531838714305022614904134506738511247696618513698871318914624:40.137.215.13.233.153.110.152.75.205.157.188.162.180.175.192.136.147.0.49.169.41.111.20.20.6.222.4.94.232.86.88.35.227.166.64
+to-uns:938137416674596881724436242382943205716649496664131501091102879563857843031208992280893614:7.94.95.163.78.130.176.52.11.67.110.168.191.141.240.164.45.130.231.131.248.48.191.162.48.249.20.181.82.141.159.150.82.213.105.159.88.174
+to-uns:-630879643949120224211369280152333180111442438605972376130506110244327899219912899223787613074:19.91.70.129.236.212.139.74.185.0.218.23.135.137.133.202.56.181.112.58.173.172.130.179.124.221.173.55.223.123.126.130.88.154.176.35.3.43.146
+to-uns:28111094457098264457145099945444765267932710530788173695233378407323077034767182928186048102542874:13.41.35.240.41.168.225.145.107.18.87.253.43.231.202.150.209.215.163.157.127.252.45.194.199.62.14.60.97.225.213.204.55.37.185.133.79.239.24.46.26
+
+# Conversion from unsigned
+
+readuns:19:19
+readuns:11.46.177:732849
+readuns:146.113.235.37:2456939301
+readuns:59.81.163.94.255.30:65221819301662
+readuns:11.183.213.137.94.177.226.84:844378241131209300
+readuns:1.208.155.227.240.84.37.160.100.53:8570522336341023286325
+readuns:47.178.211.118.41.71.211.74.100.90.207:57663995533253464107014863
+readuns:3.171.117.77.85.127.49.10.213.243.253.144.180:290748233742495477004716839092
+readuns:1.127.20.101.49.86.0.169.68.4.237.33.216.119.57:7769778759078367890498335721158457
+readuns:35.73.83.24.98.4.211.124.18.69.32.88.95.142.132.136:46903702894953466773316183125616657544
+readuns:9.197.141.78.121.20.132.41.143.246.59.33.126.2.92.102.177.71:851234028271624763535767352077184512995655
+readuns:117.1.109.101.2.62.220.206.134.57.198.156.134.252.135.230.114.144.158:2609311525555696221599776451542974890215903390
+readuns:33.77.214.236.147.20.12.74.7.55.12.207.229.43.143.81.121.102.216.82.86:48673939289293353699183948641914875550878255305302
+readuns:9.166.158.105.220.232.187.149.229.98.114.203.143.151.179.13.117.242.141.170.94.170.87:924368236946243578464304027667053681863478587636492887
+readuns:165.97.120.89.181.168.202.95.163.0.0.6.89.126.141.209.204.168.88.165.194.166.83.197:4055124010543482048995555903303887262362307550462041543621
+readuns:14.139.121.201.25.49.14.230.89.139.204.223.141.232.201.189.74.36.63.100.115.152.44.110.42.150:23372635933612270094308954044673734042122317772845683569470102
+readuns:3.162.221.90.36.235.220.148.206.72.220.121.230.47.59.194.10.29.105.64.171.5.133.101.247.195.168.197:382935508729426315500547338862614933873079907540635007298501322949
+readuns:255.225.26.217.121.147.85.123.62.227.155.115.151.17.14.226.20.151.216.70.129.251.123.127.200.253.229.131.44:6898492710997158633675426061757629757850232155550392171914514860966700
+readuns:26.126.173.147.234.225.62.206.132.172.56.142.212.124.86.139.56.123.128.83.59.140.190.156.37.116.71.8.107.238.43:46812323372237867852342682903508090873804207633443539517026163606065770027
+readuns:1.178.221.36.198.34.91.147.187.41.80.248.32.21.173.116.21.184.114.128.226.148.105.231.211.137.139.144.142.36.59.195.90:196694503291009850587117226026773591715017125540836707619882023150680605967194
+readuns:187.9.226.242.27.68.215.247.155.152.75.195.109.94.123.200.36.80.1.19.58.240.99.181.158.175.120.210.195.130.202.54.99.2:5544343675240909419388140457802353339820974107914527764492144466356713575197074178
+readuns:40.137.215.13.233.153.110.152.75.205.157.188.162.180.175.192.136.147.0.49.169.41.111.20.20.6.222.4.94.232.86.88.35.227.166.64:78752761895933104747199582531838714305022614904134506738511247696618513698871318914624
+readuns:7.94.95.163.78.130.176.52.11.67.110.168.191.141.240.164.45.130.231.131.248.48.191.162.48.249.20.181.82.141.159.150.82.213.105.159.88.174:938137416674596881724436242382943205716649496664131501091102879563857843031208992280893614
+readuns:19.91.70.129.236.212.139.74.185.0.218.23.135.137.133.202.56.181.112.58.173.172.130.179.124.221.173.55.223.123.126.130.88.154.176.35.3.43.146:630879643949120224211369280152333180111442438605972376130506110244327899219912899223787613074
+readuns:13.41.35.240.41.168.225.145.107.18.87.253.43.231.202.150.209.215.163.157.127.252.45.194.199.62.14.60.97.225.213.204.55.37.185.133.79.239.24.46.26:28111094457098264457145099945444765267932710530788173695233378407323077034767182928186048102542874
+
+# Conversion to small signed integers
+to-int:0:0
+to-int:399392010000012093849283940182938492839481928349823984:$MP_RANGE
+to-int:-29381082039841029384018230948203801985928309481203984:$MP_RANGE
+to-int:-25:-25
+to-int:101:101
+to-int:-1235:-1235
+
+# Conversion to small signed integers
+to-uint:0:0
+to-uint:1:1
+to-uint:10:10
+to-uint:-15:$MP_RANGE
+to-uint:101:101
+to-uint:100000000000000000000000000000000000000000000000000:$MP_RANGE
+
+# Tests to trigger off-by-one bug in computing number of digits needed for string
+tostr:99999999999999999999999999999,10:99999999999999999999999999999
+tostr:9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999,10:9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
+tostr:832136388736902947561088644572239329432528812529007215254079045034263648726187965907662527121488680217097287175564480588901672671661161,10:832136388736902947561088644572239329432528812529007215254079045034263648726187965907662527121488680217097287175564480588901672671661161
diff --git a/polly/lib/External/isl/imath/tests/div.t b/polly/lib/External/isl/imath/tests/div.t
new file mode 100644
index 00000000000..36a4831d408
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/div.t
@@ -0,0 +1,963 @@
+# Division tests
+
+# Tests for error conditions
+
+div:102233,0,=1,1:$MP_UNDEF,?
+div:0,=1,583922,-12345:$MP_UNDEF,?
+
+# General division tests, verified using GNU bc
+
+div:0,847887705,0,0:0,0
+div:80000000000000000000,25,0,0:3200000000000000000,0
+div:65000,25,0,0:2600,0
+div:800000000000000,25,0,0:32000000000000,0
+div:-4,58,0,0:0,-4
+div:36869,818935,0,0:0,36869
+div:364,921,0,0:0,364
+div:5169,898,0,0:5,679
+div:#x100000000,#xE424,=1,0:#x11F42,#xD2B8
+div:-6144,15855207,0,0:0,-6144
+div:680441,-8247,0,0:-82,4187
+div:-31218529,577983165,0,0:0,-31218529
+div:3,6280,0,0:0,3
+div:-2,39790,0,0:0,-2
+div:-310,611711,0,0:0,-310
+div:46573596,6038351,0,0:7,4305139
+div:4525534,39110,0,0:115,27884
+div:5938,7789378,0,0:0,5938
+div:19732849245693930165221819301662844,18446744073709551616,=1,=2:1069719901075515,6029073732495380604
+div:9,456578633,=2,=1:0,9
+div:538090499,1858,0,0:289607,693
+div:572,3804550,0,0:0,572
+div:288850,21164,0,0:13,13718
+div:-5190106,34726,0,0:-149,-15932
+div:7795,72811,0,0:0,7795
+div:781579692,-5,0,0:-156315938,2
+div:781579692,-5,=1,=2:-156315938,2
+div:781579692,-5,=2,=1:-156315938,2
+div:453020143,-3473628,0,0:-130,1448503
+div:8,853320290,0,0:0,8
+div:852316479,2925,0,0:291390,729
+div:8,5,0,0:1,3
+div:859848,9,0,0:95538,6
+div:70,48,0,0:1,22
+div:253385147,659538174,0,0:0,253385147
+div:-455686878,87344,0,0:-5217,-13230
+div:28271,635389,0,0:0,28271
+div:-86,2692,0,0:0,-86
+div:8591158476,73,0,0:117687102,30
+div:9082,275389,0,0:0,9082
+div:-582874,74264,0,0:-7,-63026
+div:237,4104,0,0:0,237
+div:7076150589,92653,0,0:76372,55673
+div:28665011462,-1272,0,0:-22535386,470
+div:-8056787359,8082209,0,0:-996,-6907195
+div:53192266,900107,0,0:59,85953
+div:91513,740,0,0:123,493
+div:-98721211,8015090320,0,0:0,-98721211
+div:11450,-36952886107,0,0:0,11450
+div:13925193,949882,0,0:14,626845
+div:683469315,-73092992,0,0:-9,25632387
+div:1164719,42872,0,0:27,7175
+div:-83594243092,3591081825,0,0:-23,-999361117
+div:87138285,266592788,0,0:0,87138285
+div:936091,704216,0,0:1,231875
+div:142238814011,709885571028,0,0:0,142238814011
+div:580,-60286,0,0:0,580
+div:5794931,-5726480,0,0:-1,68451
+div:88764678929,-2091175751,0,0:-42,935297387
+div:950181713208,-13449,0,0:-70650733,5091
+div:97846262,387939152,0,0:0,97846262
+div:32321004,4640815041,0,0:0,32321004
+div:9059,24970299,0,0:0,9059
+div:-223020,974872432,0,0:0,-223020
+div:628713585932,70889408675,0,0:8,61598316532
+div:5404031582279,-4343762403,0,0:-1244,391152947
+div:-27687,92528708054,0,0:0,-27687
+div:71252,-444744751915,0,0:0,71252
+div:2821624059,830276221,0,0:3,330795396
+div:77957,604211270,0,0:0,77957
+div:4336867764,377604023491,0,0:0,4336867764
+div:-1183882,537011618,0,0:0,-1183882
+div:7224227137658,26159,0,0:276166028,11206
+div:40420610021,29600662602,0,0:1,10819947419
+div:-53857,7190456320,0,0:0,-53857
+div:9365,85703,0,0:0,9365
+div:84454441,7874100414786,0,0:0,84454441
+div:-692,-92802,0,0:0,-692
+div:-31682292914,2103996,0,0:-15058,-321146
+div:675174791229,617791,0,0:1092885,274194
+div:151503,-7352433026033,0,0:0,151503
+div:-5675649814790,-45077421077,0,0:125,-40972180165
+div:-259966,4211178684,0,0:0,-259966
+div:99243,8777962733,0,0:0,99243
+div:-603163384555,4331787866,0,0:-139,-1044871181
+div:602983,3355548,0,0:0,602983
+div:-6945091776175,64113609219877,0,0:0,-6945091776175
+div:637048330,39484763123,0,0:0,637048330
+div:-268774166,54251789102520,0,0:0,-268774166
+div:96621785,-44159202070842,0,0:0,96621785
+div:259095,798144185517,0,0:0,259095
+div:673478104612,6115944997,0,0:110,724154942
+div:64865142,-7529340145,0,0:0,64865142
+div:62901084202908,923068964,0,0:68143,395789056
+div:857311552,30222,0,0:28367,4078
+div:6646483,1292987,0,0:5,181548
+div:855267457921,77070194891856,0,0:0,855267457921
+div:930905,-429874001253,0,0:0,930905
+div:-82732,973702689,0,0:0,-82732
+div:7498877,33402368,0,0:0,7498877
+div:2891132,3009602159727,0,0:0,2891132
+div:-16580361,45469862,0,0:0,-16580361
+div:28811879,1156690,0,0:24,1051319
+div:681237481,42215447,0,0:16,5790329
+div:952119,65641,0,0:14,33145
+div:669100,32909317724335,0,0:0,669100
+div:406354444955,4811582310504,0,0:0,406354444955
+div:-87218901,5441737753,0,0:0,-87218901
+div:262693,279060,0,0:0,262693
+div:950539838,98609240829243,0,0:0,950539838
+div:8061719120,-28536222,0,0:-282,14504516
+div:-3551675,11288323481405,0,0:0,-3551675
+div:3133528691,1315285,0,0:2382,519821
+div:1588170591121,9023526203,0,0:176,29979393
+div:1709754910,343280090631449,0,0:0,1709754910
+div:7694474,6311674489334,0,0:0,7694474
+div:285071476,771758808364462,0,0:0,285071476
+div:4473571504184,5027949393624517,0,0:0,4473571504184
+div:-314089112111113,-8919383,0,0:35214219,-5804236
+div:919605168565,-857045700084,0,0:-1,62559468481
+div:-2803909388714,46792205688194,0,0:0,-2803909388714
+div:-864476,-809506582,0,0:0,-864476
+div:157477674603,932718332239208,0,0:0,157477674603
+div:-86938062350,44113358240184,0,0:0,-86938062350
+div:7332602805,35651734,0,0:205,23997335
+div:40677613,7075290162,0,0:0,40677613
+div:6636106412767060,-388484912,0,0:-17082018,153254644
+div:9453362014,-644867786149524,0,0:0,9453362014
+div:123163311944389,-16324640549,0,0:-7544,10223642733
+div:55603403145688,-51970044763,0,0:-1069,47425294041
+div:-54436610546,-9254821627256041,0,0:0,-54436610546
+div:34541223746384523,408005019,0,0:84658820,283766943
+div:23462284247353823,2661546,0,0:8815284142,350291
+div:417392442148,-30391736401961,0,0:0,417392442148
+div:-718458863,-73668989433156990,0,0:0,-718458863
+div:-1215789,25426915315,0,0:0,-1215789
+div:8299846204145462,9023932210324,0,0:919,6852502857706
+div:-82615892630,85109462984880568,0,0:0,-82615892630
+div:828237348372,822759132224411,0,0:0,828237348372
+div:35003657,287087229590,0,0:0,35003657
+div:741329413510689,600380266222,0,0:1234,460164992741
+div:-454795890210,66807881739,0,0:-6,-53948599776
+div:442416942,-79456387864,0,0:0,442416942
+div:7067406608460,507872176187,0,0:13,465068318029
+div:57674203676661022,3315186364,0,0:17396971,2642557578
+div:-6677233842,881012314,0,0:-7,-510147644
+div:828372724537918527,2204184463,0,0:375818239,1222097870
+div:-97445457356928,3845827480,0,0:-25337,-3726496168
+div:644919922824665106,692147849,0,0:931766130,174110736
+div:-54599915326211,-274657876971100,0,0:0,-54599915326211
+div:3507375128,373578606,0,0:9,145167674
+div:19124901,485472050038835999,0,0:0,19124901
+div:687842561,49925524361,0,0:0,687842561
+div:193224391137090311,84335903540,0,0:2291128,41131297191
+div:388138056,66626944,0,0:5,55003336
+div:-656523898932,84101085851135799,0,0:0,-656523898932
+div:86004003567986,713613577148692,0,0:0,86004003567986
+div:7992270343,87209595913499289,0,0:0,7992270343
+div:-890969253231921,739402045213270955,0,0:0,-890969253231921
+div:6345032414365,821532347711110478,0,0:0,6345032414365
+div:-2988926571013999683,766437559276027,0,0:-3899,-586527396770410
+div:-15464671727416040,-618822744180643,0,0:24,-612925867080608
+div:21542413221581,-12802725163,0,0:-1682,8229497415
+div:210193665939,3964410139763307,0,0:0,210193665939
+div:-79273337971,91480286016,0,0:0,-79273337971
+div:6859567649816379680,-89417752889,0,0:-76713710,85837971490
+div:4244108501419250,1773608945178,0,0:2392,1635904553474
+div:-7873175456557395,-541450782136,0,0:14540,-481084299955
+div:2898452653,8240117642629,0,0:0,2898452653
+div:-8585567176400751363,39056741283,0,0:-219822926,-27546697305
+div:4923064817310182,488568656518880796,0,0:0,4923064817310182
+div:3946741285053501,-8922249541453011,0,0:0,3946741285053501
+div:438914382542168,98348892578,0,0:4462,81623859132
+div:257824992496,-9594074905801512,0,0:0,257824992496
+div:6213773111135227489,251684062660,0,0:24688782,155248147369
+div:-851789213354610296,395154960128827139,0,0:-2,-61479293096956018
+div:234318209260,31123149038286353070,0,0:0,234318209260
+div:243854015291982,52511298700,0,0:4643,44055427882
+div:7259566528156,6524807428024562671,0,0:0,7259566528156
+div:-887488809078966765,845297673812,0,0:-1049912,-637771662221
+div:65325904373281379,40360887138954,0,0:1618,21988982453807
+div:85548880813,9240276773237567918,0,0:0,85548880813
+div:7737568342993115224,69017119565996596,0,0:112,7650951601496472
+div:-2862875578129,87167074447,0,0:-32,-73529195825
+div:48121669474016423,812759701293155,0,0:59,168847097720278
+div:-82120995972822350,9793327794599,0,0:-8385,-3942415109735
+div:96669753363716639,3137138094734,0,0:30814,1980112583163
+div:44554701178616,52377515472783262637,0,0:0,44554701178616
+div:12903174971697,577437337389558244582,0,0:0,12903174971697
+div:38970472084822,-12255774904287,0,0:-3,2203147371961
+div:-371784186042,36063372236212364134,0,0:0,-371784186042
+div:-5423240799687893943,69598779690234855,0,0:-77,-64134763539810108
+div:78261697698230901561,532057670838,0,0:147092508,494031019857
+div:-867163311151035436254,1681644368464785,0,0:-515663,-1531175379008799
+div:425847772644293,726262561530005,0,0:0,425847772644293
+div:623414319659742,26868506006719423291,0,0:0,623414319659742
+div:3999344581644,6784937040418183244,0,0:0,3999344581644
+div:-418166904889870721653,99856664384501754791,0,0:-4,-18740247351863702489
+div:4737717701335,43868455388327,0,0:0,4737717701335
+div:-170318802370599286974,88681362021061351331,0,0:-1,-81637440349537935643
+div:-401236499756120675284,617234855370415616,0,0:-650,-33843765350524884
+div:8507669577483416,1708320712715767,0,0:4,1674386726620348
+div:-779872398090729,9483722067689467,0,0:0,-779872398090729
+div:-6974404749995800334378,88119801211272782297,0,0:-79,-12940454305250532915
+div:1644424212644083246063,6570040442718779,0,0:250291,2220195557331374
+div:380529423855576,-66584160392695795292,0,0:0,380529423855576
+div:-59486508603350002,3049574533592654270009,0,0:0,-59486508603350002
+div:4670852164286,194818165100985439247,0,0:0,4670852164286
+div:-9242375894510748,427966685403010,0,0:-21,-255075501047538
+div:-2547406540907066001,9156772267145703887,0,0:0,-2547406540907066001
+div:41045576141401448,295376215711793,0,0:138,283658373174014
+div:-8596645367243,618616563342036461,0,0:0,-8596645367243
+div:-8190662465572761,4614103375660380354519,0,0:0,-8190662465572761
+div:13625026664287920203,962611652006092322040,0,0:0,13625026664287920203
+div:-140239543538185,-36750209483049,0,0:3,-29988915089038
+div:19272745315539563545972,4913276356215789258,0,0:3922,2875446461238076096
+div:81488845695775561589,6137038314233733147,0,0:13,1707347610737030678
+div:59682455708892,188993136701455,0,0:0,59682455708892
+div:-45017621011770980,5037281596391885620833,0,0:0,-45017621011770980
+div:12784502496583369914436,66775897063651761451,0,0:191,30306157425883477295
+div:69627779066297453,44437721988866612,0,0:1,25190057077430841
+div:-9837326629633299,980665943940704469610,0,0:0,-9837326629633299
+div:1548374752880296357809,-3696277363166782287,0,0:-418,3330815076581361843
+div:-708439719674935281,5147784263606738,0,0:-137,-3193275560812175
+div:-7570135590104019,22684260196955,0,0:-333,-16276944518004
+div:7197857209654848797343,5395261067987895097519,0,0:1,1802596141666953699824
+div:42034917537094135582,97988383165721711085970,0,0:0,42034917537094135582
+div:231126155949672582,9057297455411228,0,0:25,4693719564391882
+div:-911497664257321106698,-18662736693873,0,0:48840514,-11481903135976
+div:64066981598227998719,731669238473176,0,0:87562,559739039761807
+div:35960724694947949779,-747063649911230162,0,0:-48,101669499208902003
+div:624879014956928,17179603356281093930126,0,0:0,624879014956928
+div:-3559399723529186749748,153806520430475822650,0,0:-23,-21849753628242828798
+div:-375790972015605,113007880734109473,0,0:0,-375790972015605
+div:-8787548671098011,8921111513701891873,0,0:0,-8787548671098011
+div:-4332240904268358207600,202327025748990,0,0:-21412072,-61385130400320
+div:9234628706335936400446,65579862120113054437,0,0:140,53448009520108779266
+div:-598537435499087,-2334884709153191798659,0,0:0,-598537435499087
+div:-8778093680300813378318,-5335331111760467,0,0:1645276,-1450067999274426
+div:834964892558660,4731312923556947,0,0:0,834964892558660
+div:697663848949724,16714097460480423,0,0:0,697663848949724
+div:660124536913505493,-400393621100679,0,0:-1648,275849339586501
+div:67401867410433679076,433247521397462506,0,0:155,248501593826990646
+div:-3192841130293725192,94067632460761922343048,0,0:0,-3192841130293725192
+div:-888171986451016091961,61046771373537922044313,0,0:0,-888171986451016091961
+div:5413476093760118894,436643671457387927452325,0,0:0,5413476093760118894
+div:3390818445571570,71193890227980923543296,0,0:0,3390818445571570
+div:3709278299197858947885,622346666342073,0,0:5960148,60492485241081
+div:61046636418932697473,752452096310648123,0,0:81,98016617770199510
+div:-9490582336573659,6796700304740895609,0,0:0,-9490582336573659
+div:-6770091537873296360125723,894260210116688124412,0,0:-7570,-541747289967258326883
+div:8265260740385351513048054,-37568692482712647407307,0,0:-220,148394188569083440514
+div:29941612974211919398,17117150207877877221595,0,0:0,29941612974211919398
+div:904565427385797381401147,732377327803549406181,0,0:1235,79427548413864767612
+div:828695336330867,665449887430200916,0,0:0,828695336330867
+div:583964043448404224,-159103379771833684164472,0,0:0,583964043448404224
+div:68659884135230073,3794043309187845772,0,0:0,68659884135230073
+div:-19577883397074285891599,89166539289139219809001,0,0:0,-19577883397074285891599
+div:47123114739550322,81879863505548403487,0,0:0,47123114739550322
+div:2081796666654613977139,-5323946267713561205491896,0,0:0,2081796666654613977139
+div:5580573071674875331019254,48049594740533118,0,0:116141938,18394751853316570
+div:-827318924045362735,6765606250148903029558502,0,0:0,-827318924045362735
+div:74355428058748494058359,-21632036475261687692382908,0,0:0,74355428058748494058359
+div:-704818230891696889912403,4179012972972804984179,0,0:-168,-2744051432265652570331
+div:54203012886802530,8642657915176877761716,0,0:0,54203012886802530
+div:99602518405709989487439,181452400672924186,0,0:548918,29533129791156691
+div:669551881716343753,65924540094419185740265,0,0:0,669551881716343753
+div:17773767489747228176421376,99265471480253104908,0,0:179052,86290264949236434160
+div:68861552761996536283999,3032962718342296259044166,0,0:0,68861552761996536283999
+div:-13017342749140884149199232,79805947528944429,0,0:-163112439,-988735239546901
+div:-846660807407559032521972,77200873303583960046,0,0:-10966,-76030760457326657536
+div:20732670221446843791112897,158830667623944099,0,0:130533168,938387893737265
+div:87479614966913872614027,-20093149492209048359,0,0:-4353,14135227327885107300
+div:815811689877913117,-96853054749489063852925232,0,0:0,815811689877913117
+div:88424170141166441101228,41882896205789554161109080,0,0:0,88424170141166441101228
+div:8907792217571919630,1822019507410919085762,0,0:0,8907792217571919630
+div:508794162072510930223084886,-69410487054586064946,0,0:-7330220,21655243065234616766
+div:7560829661415328254781,71577097034806313439,0,0:105,45234472760665343686
+div:7451615053542910305,1115867448037197150640,0,0:0,7451615053542910305
+div:1420226199720665341735779,832064548724686659546,0,0:1706,724079596349900550303
+div:-389977371089920999571936723,8114703647013040404,0,0:-48058116,-1916145250323817859
+div:675206408971175566604,36474013799024907341535694,0,0:0,675206408971175566604
+div:-502561109202609111272,-414660684126386698299,0,0:1,-87900425076222412973
+div:-7443609476960080458698600,-92469297206353960522,0,0:80498,-15990442999344598644
+div:24688964911945445107348,-799787361463460092976944,0,0:0,24688964911945445107348
+div:74622389634816941348941747,361423050927986753697692,0,0:206,169241143651670087217195
+div:57087631963106216588129,60933956374125435992007156,0,0:0,57087631963106216588129
+div:24667793118599351096874664,944711324818117322023856,0,0:26,105298673328300724254408
+div:564352217106369256763287,81622332712601232269,0,0:6914,15408731444336855421
+div:-419643083493336850638945386,-90994516601676379,0,0:4611740346,-16619082369458252
+div:3968897352690734435372,22251724057784007850845,0,0:0,3968897352690734435372
+div:657621764031152559636,1284248378184585349838990,0,0:0,657621764031152559636
+div:478747162724364955902006,88051418458918816631123,0,0:5,38490070429770872746391
+div:6665622554429783258955137608,694490725232295413492445192,0,0:9,415206027339124537523130880
+div:739043574063917325584775,6568858167203582304319770218,0,0:0,739043574063917325584775
+div:488239617545415130712260,-175755600464230772602,0,0:-2777,166315056246275196506
+div:-45020591983716715,29238208588753924571931348,0,0:0,-45020591983716715
+div:7127560906474483695,2443668648642679038,0,0:2,2240223609189125619
+div:56992002738244984812189281,5608720362174497796029,0,0:10161,1795138189912706738612
+div:6460467352419769344150698,317411399503484718457,0,0:20353,193138325344869395377
+div:-932907356818921691594434039,-97184909630029367110035347,0,0:9,-58243170148657387604115916
+div:3995705323622443163782,89030590085262709211588,0,0:0,3995705323622443163782
+div:767569373426935379750,1549154787571680632324257,0,0:0,767569373426935379750
+div:931318846320283067427330537,-86130685020277950106,0,0:-10812857,65883975492678017695
+div:31826303162303263286188,5737442550621928753,0,0:5547,709334003424493297
+div:57706427262137233402480,76482797550886260948017,0,0:0,57706427262137233402480
+div:72853807229779038632,3169975417424853790892514721,0,0:0,72853807229779038632
+div:656860988961860702860500038,2051614607117987332942,0,0:320167,1695044716052434458724
+div:419136122263611128595,629629147994291589835819893,0,0:0,419136122263611128595
+div:21718233877577237636870231772,28954985957426921952977486934,0,0:0,21718233877577237636870231772
+div:8137115583255366542038482,-53056312894008476008,0,0:-153367,28043639968602119546
+div:350144503855608500819,279913875130875757713464,0,0:0,350144503855608500819
+div:67536193348303696626965587175,157462565791912473045994827,0,0:428,142215189365158163279801219
+div:-6653909716122388287977917,-456461036794945909189066,0,0:14,-263455200993145559330993
+div:37893238038459578489871345783,58476986428077111625242,0,0:648002,33879092754002491279299
+div:9750862793806595478546835,831707298467569713898,0,0:11723,758133871275722520581
+div:82929154752623245294293,793446150807998771837734747,0,0:0,82929154752623245294293
+div:966515993017183338978310,77669990894453129707640,0,0:12,34476102283745782486630
+div:158090994204861340057333,31910675611432229121455470549,0,0:0,158090994204861340057333
+div:1330572162878429717062,21084117694617750279966598211,0,0:0,1330572162878429717062
+div:832245616705658749585054836,-6079221966362676227357795958,0,0:0,832245616705658749585054836
+div:-566340281799124821634,146366719895661144175,0,0:-3,-127240122112141389109
+div:4970340520764553911461,91205816337394717102255090410,0,0:0,4970340520764553911461
+div:3278473198323030526681,2105717666245284028185,0,0:1,1172755532077746498496
+div:2122422503626206527321754,17148805521927416661130,0,0:123,13119424429134278002764
+div:1912021218223919631352475809,38185948805565948914414505595,0,0:0,1912021218223919631352475809
+div:941796603263493070268724375,444845019508763781185108406,0,0:2,52106564245965507898507563
+div:104754716329414707284533930,43667472164404259911976738073,0,0:0,104754716329414707284533930
+div:89122706354696915439758538,31455209252293039108428126,0,0:2,26212287850110837222902286
+div:118480448597792962897533,67244410472175197017373,0,0:1,51236038125617765880160
+div:352695831583961620878034763371,8582622957634803011445036406,0,0:41,808290320934697408788270725
+div:-624005759812006640839,8172000984425101361637221854,0,0:0,-624005759812006640839
+div:7384400794640347039203,-628293484000022806320912136,0,0:0,7384400794640347039203
+div:-2828685708623719356215,7634212328177549702763918762,0,0:0,-2828685708623719356215
+div:-86550506492571342719558,666034531900739098444599,0,0:0,-86550506492571342719558
+div:642452648202950019476496886617,604805196719437392366385471,0,0:1062,149529286907508783395516415
+div:4662456248509569207839,-33567555776748285848111,0,0:0,4662456248509569207839
+div:62996041896426933131446657891,763936004120034809021339118482,0,0:0,62996041896426933131446657891
+div:8345367673768217736530,3642617362546668617513754,0,0:0,8345367673768217736530
+div:-84451394313979740929245775,1334835508641575600458674242637,0,0:0,-84451394313979740929245775
+div:1176029794050678765470272286249,40628825039402391375029153,0,0:28945,28453285176547120053452664
+div:7707482263998465479379,-2829972969411199798203141,0,0:0,7707482263998465479379
+div:-11136894339272544791100807454,67013816338042624404219,0,0:-166188,-2229685917126612460282
+div:-428729652188276782322695284232,-774565897177367154457859446208,0,0:0,-428729652188276782322695284232
+div:626676530287556077206017712837,908674926870287524187734,0,0:689659,688897120453562229270131
+div:2773148741407028218531427,557528937606955521382821134,0,0:0,2773148741407028218531427
+div:75539539184325529932345561314,-502273785664131486016696176,0,0:-150,198471334705807029841134914
+div:3606180022705211288777456393,122973836595862158705454565,0,0:29,39938761425208686319274008
+div:-30856676793350414230630,38692347037119733077452,0,0:0,-30856676793350414230630
+div:28070532442085800846842,6911568634505880039237117,0,0:0,28070532442085800846842
+div:94746783288740489316741633573,86780043180255118744681,0,0:1091803,71804408409905942683730
+div:-24888475865091602999453808074899,-2607720766137261712927817388,0,0:9544,-388873077577211270718923827
+div:53207047214418054977598334400421,4391350648985919720756952364,0,0:12116,1442751304651640907099558197
+div:944627096784739396211350732172,47554680361438235326247368315,0,0:19,41088169917412925012650734187
+div:90507814687564826997063490,263428140883010973433496,0,0:343,151962364692063109374362
+div:40830360719924046206003172846797,289018741615486979391301844046,0,0:141,78718152140382111829612836311
+div:46815309089103159131589670878273,844714076577304483690089137,0,0:55421,410251112367341001240816596
+div:766097719529863726042659,864954870692483641146857,0,0:0,766097719529863726042659
+div:36588837904828449995291554992448,5981291437419281216117821938,0,0:6117,1278182134706796298838197702
+div:744905055097349284759083504,-402232162933870784393172,0,0:-1851,373321506754462847322132
+div:-496174511680228005426626189898,6850190505814392535531175627173,0,0:0,-496174511680228005426626189898
+div:117807976873474930026716,72472466715338440688738889,0,0:0,117807976873474930026716
+div:29688886500382323149926912509,171231756792519788711530194,0,0:173,65792575276399702832188947
+div:95600026518374000257859,99155834015695214013381,0,0:0,95600026518374000257859
+div:947283711638216525748681460035,375183675933541675266484,0,0:2524853,81906386026327073533183
+div:41432664026918887246001356,89293848269510580767075145704,0,0:0,41432664026918887246001356
+div:347133325715091646723859014383300,8007256671477794251698509596618,0,0:43,2821288841546493900823101728726
+div:-72131155022320848089529987358,607237864853852225127081848,0,0:-118,-477086969566285524534329294
+div:52607679919645038811433035271755,-86393659667162016384842618430,0,0:-608,80334842010532849448723266315
+div:507690908006392398957998748,2764904388542893841465155862,0,0:0,507690908006392398957998748
+div:65723044947927998584588839362573,-414671665541745655865677654655,0,0:-158,204921792332184957811769927083
+div:58581181220230933312243002393,727812383468376773626369395972,0,0:0,58581181220230933312243002393
+div:55621061599265643370130457,75058109335016054327498821167125,0,0:0,55621061599265643370130457
+div:8042490680681402413656869107,985374040566072816763255884821,0,0:0,8042490680681402413656869107
+div:205865392688566277909245217913157,188746850681839171579701059,0,0:1090695,146384137702663123171367152
+div:645469876768555458540596006480343,-1176209889279660120170867010701,0,0:-548,906857443301712686960884616195
+div:-372748268475137934411499506,-6952751051457138928077564508,0,0:0,-372748268475137934411499506
+div:-53726448220098738825476944862,666316374954612779881255280093902,0,0:0,-53726448220098738825476944862
+div:3999043104096914451698824,53972081370928852391234278,0,0:0,3999043104096914451698824
+div:6875840365821778484266515548732,-48235349383818088293481585385242,0,0:0,6875840365821778484266515548732
+div:464946247859367335487708854577230,-91038566114714256247221434416,0,0:-5107,12290711521628833148989014718
+div:774638812953340934130134234932,1781076313255841252742417918164985,0,0:0,774638812953340934130134234932
+div:181439807984506382551684665,983773852096178563301436779,0,0:0,181439807984506382551684665
+div:-16817917749776745039099453680,29825644384864912855101360,0,0:-563,-26079961097799101677388000
+div:22133214432524045001245001353,-198976752808774771294935518769806,0,0:0,22133214432524045001245001353
+div:2921499120428770523924215,57361572214425723589097781,0,0:0,2921499120428770523924215
+div:123171649003149782751271079,-73094968897222766037958236983376,0,0:0,123171649003149782751271079
+div:769172117059026460908975826,97495810773186124439901474,0,0:7,86701441646723589829665508
+div:94112063717361782849247888341,9764365600045726199272325886020217,0,0:0,94112063717361782849247888341
+div:9469809875854665598033283678676801,13423826176729482294685830678,0,0:705447,11970959382501694048484373735
+div:-842464855184253146889699,56551832462429857048225522,0,0:0,-842464855184253146889699
+div:598571783530686410412162091727492,943878487966896512387279950152,0,0:634,152822159674021558626603331124
+div:6953911548504792867117243682880,-1243290077624733705142673151816,0,0:-5,737461160381124341403877923800
+div:-9281561117131091717433858956,24045037010263371696747810870864,0,0:0,-9281561117131091717433858956
+div:143976137737540251569359185478383,265536580911922810877928898030231,0,0:0,143976137737540251569359185478383
+div:40928612217108238156488248958516,652899471410195581619563697,0,0:62687,303052817307731502659484677
+div:-70884981920443005098389267,994979502748896336180903347917699,0,0:0,-70884981920443005098389267
+div:6634749014277303650696175833,495438828683857357740137178054,0,0:0,6634749014277303650696175833
+div:7422909929360831470432375670687378,44420776675922024505687379448537,0,0:167,4640224481853377982583302781699
+div:46314400055365971953154263039,8152799875814716360460312147,0,0:5,5550400676292390150852702304
+div:6591812486274558813658703427,17421702938564211067047963695822,0,0:0,6591812486274558813658703427
+div:124008796997131146663153333663944,123778079237035114605937158,0,0:1001863,119198477435638705314738590
+div:7901064786124799043739659032,5571379890858077238984496202525017,0,0:0,7901064786124799043739659032
+div:-6965802504602789618852220893,639736224353884761032877844589149,0,0:0,-6965802504602789618852220893
+div:971873099542038287548098257,33891065268003504765508649367,0,0:0,971873099542038287548098257
+div:675025802085588841328307981424510,5883130258364185867146732282508,0,0:114,4348952632071652473580501218598
+div:3002202702401536393223671580,32010263936497485071510555,0,0:93,25248156307270281573189965
+div:34972912833617921349910233,474530829196480379440614753566093,0,0:0,34972912833617921349910233
+div:276535788922741466724367182792751,-9977731202427442856055105791931326,0,0:0,276535788922741466724367182792751
+div:14688056569711843047315045,33632661368158430395335244297,0,0:0,14688056569711843047315045
+div:-879571497507836359459742179631,46691865250496831422027355865479980,0,0:0,-879571497507836359459742179631
+div:494117042357580878818138056,29316968901414007402594292795459,0,0:0,494117042357580878818138056
+div:1256269358576514580546391822558882,-5715622931835594771199373401675,0,0:-219,4547936504519325653729047592057
+div:-7954432693582559842284447426278,-1415175992700551307691498753891217,0,0:0,-7954432693582559842284447426278
+div:9290637525511632506517536450,31193173758140935479273605091020135,0,0:0,9290637525511632506517536450
+div:741965597318745797468077425593,5090853342489379493387893,0,0:145744,4267770973672583752348201
+div:28726807242801656618422278445,-66260445037131724567939080371803922,0,0:0,28726807242801656618422278445
+div:600680612706025211965401567803,601606994582634974447563159467,0,0:0,600680612706025211965401567803
+div:-66914527546382741959361703369956,7595234786937152212557447828,0,0:-8810,-509073466430966730588005276
+div:-477200248767482289180868434831103210,299754033389841609330851428,0,0:-1591972736,-104820787767789757788436202
+div:1602055237860095405473195539557021,-482613481963019529862911261825616,0,0:-3,154214791971036815884461754080173
+div:5847782734638264086149188726633444,856996324395574391409855532415801398,0,0:0,5847782734638264086149188726633444
+div:79271780305017072764462340,334727107872141024597713303,0,0:0,79271780305017072764462340
+div:-8309528822503909832876248028239283,-280321240085800591419535364757,0,0:29642,-246623880608702018380746112289
+div:-7036110366628173318660022670592,28316814714059617609323292157,0,0:-248,-13540317541388151547846215656
+div:948009776246268508005837034128,9919518492899054009114568949283,0,0:0,948009776246268508005837034128
+div:18836117763174709382287464458,-95991422838941512823432481785039,0,0:0,18836117763174709382287464458
+div:46329535017445104282274302989008943,2426057049787109955278434918171122342,0,0:0,46329535017445104282274302989008943
+div:297935043427322209379153089088,5013180436585374804022483003677803281,0,0:0,297935043427322209379153089088
+div:-118750521055580916050992218218817,60015490720625049417386142837,0,0:-1978,-39880410184568303402427687231
+div:575684179239053603789472576628353,7053037456193336012438564397416,0,0:81,4388145287393386781948860437657
+div:-22678246623112702170004970988490199,56088891589189424871010131732,0,0:-404326,-49442422098769608928465817567
+div:6471427876906983381994784223,7282306840714785835314255152341703,0,0:0,6471427876906983381994784223
+div:603142728037804458149682405206,-650651299197030110194378722974,0,0:0,603142728037804458149682405206
+div:95931851622486456387293188404091,30758076059621180125667261744973187,0,0:0,95931851622486456387293188404091
+div:-726881908942360166762114252209703,363140012331598428300964292698,0,0:-2001,-238744266831711731884702521005
+div:615441001400268210176031416893518,64796591895996509835103891278541,0,0:9,32271674336299621660096395386649
+div:-84863286321984569539608600726350943,95803928515186040910470967405915312,0,0:0,-84863286321984569539608600726350943
+div:127629355200690947978534550183,797344806129236668518995114759425,0,0:0,127629355200690947978534550183
+div:2288916268196725535426416610805794415,4632856553925567389796050303893057,0,0:494,285130557495244867167760682624257
+div:976908939861250135603632878187851391,-6608040757199335387091406901838035,0,0:-147,5526948552947833701196063617660246
+div:-12183790198926859582276525192366339,3503085624005426351029343283863,0,0:-3478,-58398635986733396469251090825
+div:162265381015355009933791722345838,7623537904684559645894301151112382716,0,0:0,162265381015355009933791722345838
+div:-593766143424589564713907089125639,224331769330731597387481028255128,0,0:-2,-145102604763126369938945032615383
+div:604869729619335696245226863211466041,93942209533557682128293773108407,0,0:6438,69784642291338703271551939541775
+div:742895297953619211242501957373791,531142018450802021651202332570,0,0:1398,358756159397984974121096440931
+div:27653047597891730507139754824,5480890077990244820355276983606,0,0:0,27653047597891730507139754824
+div:3784487646863079978435416373977,694796147453752363831293132728,0,0:5,310506909594318159278950710337
+div:2973223272105672225946453215625903,19361627619874023404230915287,0,0:153562,13011542577443945945402323609
+div:245900231135215525853387549499,-7177692471091872136903418261273,0,0:0,245900231135215525853387549499
+div:9997981965333038339861175645427,-4045879607573312864719096965459966764,0,0:0,9997981965333038339861175645427
+div:6806842983457720589405220668623962,-927052066456609430942182858322,0,0:-7342,426711533294147427714122823838
+div:-122270014267619817663497887649323141,-2162707234463692663424997827917303191,0,0:0,-122270014267619817663497887649323141
+div:-73410057200050892585310982601,-2781563564880350086545084449330,0,0:0,-73410057200050892585310982601
+div:41074074074626336295845220577523,73580647879659031572628791338989878719,0,0:0,41074074074626336295845220577523
+div:38518920335521852358928552909455,934752467373574138232063654381123270465,0,0:0,38518920335521852358928552909455
+div:4300545050696782443239516173845124,-9078020631753897849258060104921396,0,0:0,4300545050696782443239516173845124
+div:9125102035522831694438174632387280948,14030892071253083076166776508287771,0,0:650,5022189208327694929769902000229798
+div:10049229592281672286226252965830,-947015519470033748849687371329705317719,0,0:0,10049229592281672286226252965830
+div:74199952025194030063111669270731296,53730729670173947678290654632594,0,0:1380,51545080353982267070565877751576
+div:62962644403023975314385553509953336,18661881999119919255366397124335,0,0:3373,16116419992487666034696009571381
+div:-48885268599530160005042589357517742267,1224963343286960109782754733806,0,0:-39907535,-1103588784380283462421739114057
+div:8260532189465861184106347872307,8068023378797368816499164870542708410,0,0:0,8260532189465861184106347872307
+div:-873293644410280888333970242222255556855,-53468033733881855748079429886216144,0,0:16333,-249434788538400588913890687276903
+div:8118527378780784121252739484687134,7449409022714146507892440406735208908,0,0:0,8118527378780784121252739484687134
+div:28529491283005611559168619648453262781,-883723803503785940933815830371,0,0:-32283266,663961158020941954801575391095
+div:899559711064017522862617539102500,-566535897303370911043077254061825,0,0:-1,333023813760646611819540285040675
+div:15574337293150371571515035679594790928,-55555266615224096139156320494291715,0,0:-280,18862640887624652551265941193110728
+div:4585681465427957919096525629579,66250889555016187900342661335447207,0,0:0,4585681465427957919096525629579
+div:740366425347027728645955294884621471,-8981847007405192941035608249485839462,0,0:0,740366425347027728645955294884621471
+div:995741708152482543471981480782324347091,21342276145547465497291491758534,0,0:46655834,15123660154109622191683793959735
+div:-3250628989112846425058431588079956,188350448043333903099558871335715,0,0:-17,-48671372376170072365930775372801
+div:876756580410958121101100042110445,700377806984105935223010779109492,0,0:1,176378773426852185878089263000953
+div:273777021637125264614902200521817247,5596822025834012700584044296044,0,0:48916,2875421428699353133089736528943
+div:-464090250274653177412801749314226,331074623300822560323451165878,0,0:-1401,-254703030200770399646665919148
+div:396075925225537300206063956732379,43995671606762821537409289353046922,0,0:0,396075925225537300206063956732379
+div:-18658324380438997683615076571716,5092778408442460759386491384527084996615,0,0:0,-18658324380438997683615076571716
+div:-3965312367885757866883408465644,62732726984931603243998191276757746,0,0:0,-3965312367885757866883408465644
+div:18384490431288410418670437084794892,251064583418108672333112094297258,0,0:73,56775841766477338353254201095058
+div:5162911931645462592809376061314438,276766756569293637905979057590818,0,0:18,181110313398177110501753024679714
+div:8135417534757202149267580550442399,57219388491890904146726624261571751057,0,0:0,8135417534757202149267580550442399
+div:182770016919229728734188047616685,-40885421527209929308823628618058876,0,0:0,182770016919229728734188047616685
+div:92048299381294008029880374643382,11111217138310865417953673269446,0,0:8,3158562274807084686250988487814
+div:5200981870655088437520091813182496782,8050665661143383427978138223450564832,0,0:0,5200981870655088437520091813182496782
+div:756533369514441505798425699358577956,213131801093410029221386684045445047,0,0:3,117137966234211418134265647222242815
+div:799371912191908595027684426426504203412,17112684578666430604042990191541053858717,0,0:0,799371912191908595027684426426504203412
+div:1298725911189943981172370165599649,65794189885654690328812265324475773,0,0:0,1298725911189943981172370165599649
+div:860525228612860972598185202071685976152,151574827288199259902280707159394761797,0,0:5,102651092171864673086781666274712167167
+div:3584182117338772880305442381515310406513,415718227605762773246300051378162,0,0:8621662,71682816997193200587950163461269
+div:3468267249506034567392210570575412440358,2065367734321219422680254672539,0,0:1679249264,1757779312273888004381735679062
+div:50367071916831078065713924791723412318,65724451969804512659247548060987947789728,0,0:0,50367071916831078065713924791723412318
+div:79874071719000306927937931805669,6145217682421427626924604560525904590,0,0:0,79874071719000306927937931805669
+div:423797068560673311763985503147656006,69667145306964427593061472412068457736722,0,0:0,423797068560673311763985503147656006
+div:41523275633578269444354516606248777741194,-694978110274856348249211949536413124775,0,0:-59,519567127361744897651011583600403379469
+div:-87407113783597425860610212435025646,22427444695442827429769682014306,0,0:-3897,-7361805456727366797761625275164
+div:-5398995964042513456203407110806239,759328487523337723297727841375739581,0,0:0,-5398995964042513456203407110806239
+div:-486450683665060870587027665253017864,98034404319738594732566595585128,0,0:-4962,-3969430517963524032217959612728
+div:82802462159510025179539722591174489656,-7995658647747583535810574975199511344136,0,0:0,82802462159510025179539722591174489656
+div:-9247518837150320354892251517725,95037788396291796059988855373871527896146,0,0:0,-9247518837150320354892251517725
+div:-5710350451928497877474611321475359,884522303455599132933755693677751985,0,0:0,-5710350451928497877474611321475359
+div:-6247471877283545360155543727272765071,675373004151999159209581260366203727893602,0,0:0,-6247471877283545360155543727272765071
+div:549120950829660962410197911937811,48123906347804179379843793292937012521427,0,0:0,549120950829660962410197911937811
+div:-106448127960021997407899520808890,9065012874636494312839056387435045253097,0,0:0,-106448127960021997407899520808890
+div:69560159021211857117768649206402791,351520915367913488351778070201730208854,0,0:0,69560159021211857117768649206402791
+div:603624320694634013723571987622589,2701844331050375027455889272518786,0,0:0,603624320694634013723571987622589
+div:67014256406500009956329723823638317486,-1091809123530714597985512683792998,0,0:-61379,104213308278646576940805107893244
+div:235637292979855521853832255322576,-189051691838200548750099363324518519845,0,0:0,235637292979855521853832255322576
+div:46621760725175766077357844382212912326,382903788461287808084560177696868561667,0,0:0,46621760725175766077357844382212912326
+div:17972807610345735075506894651990254671255,55415225623081699101048670679962759717300,0,0:0,17972807610345735075506894651990254671255
+div:-99369177703763557258065488925907194288158,6888487468349330333818924437618675770942,0,0:-14,-2930353146872932584600546799245733494970
+div:6974086110297401606708008289033796059,298190885369602196463446343967843,0,0:23387,295874158515038017388642657851818
+div:22082353893401399289701395360491738,34004577923140732261317680713467602,0,0:0,22082353893401399289701395360491738
+div:3021321469279908093607775280467343863,54418828629265035058612376701138652,0,0:55,28285894670331165384094561904718003
+div:-773023736068095185985747288307356,62254616741081128985277622196480901,0,0:0,-773023736068095185985747288307356
+div:-2914004549648558380597177821180027971982,41945684266123534509905568470747536706,0,0:-69,-19752335286034499413693596698447939268
+div:7760354325840316590533609759835164008896,868363194633558774643668133661139838,0,0:8936,660818594835380317791317439218416528
+div:62481824056284557813538132809580514163491,3063406952822650811300655756477238,0,0:20396187,2989413594030548244777844306671985
+div:999032777586519798809642100185769791083086,53063722362186015952243063915405514648,0,0:18827,2076673643676476761935850430166805190
+div:1470131951969797494200280446936328952439,-985834190529311083948780402821210768,0,0:-1491,253173890594668032648866329903697351
+div:695257822575467619322639555633582443264,6467796678447835413755920250534956,0,0:107495,2018625717551520946908302327348044
+div:34431866058056304430649293119014790521,-66121478435132244087535870280208408759829,0,0:0,34431866058056304430649293119014790521
+div:458534877296422067611914397253412590469,229983379105475980155252782290948271559418,0,0:0,458534877296422067611914397253412590469
+div:2185065840509747880280098827050369,-23363950333069346956170201374188305,0,0:0,2185065840509747880280098827050369
+div:660127414048214811857806676633782977984,64123543109305824067686258949394280427,0,0:10,18891982955156571180944087139840173714
+div:748036409612739266280596599738236249637,-89094948094100676872295250639398845430367,0,0:0,748036409612739266280596599738236249637
+div:9049727473118706892393777842066328396165263,3856651773197697798307166289847038513869,0,0:2346,2022413196907857565165726085176042628589
+div:980189895420499303642948634803744800389758,-3190314421704305860902855244770982859,0,0:-307239,882810490075245016292255552797773457
+div:6108171433112534565184964245024814724366,4260996317082295106607737650284809362606641,0,0:0,6108171433112534565184964245024814724366
+div:358196359808272615858599795581371458918250,9543484816419438536292482064209522533404722,0,0:0,358196359808272615858599795581371458918250
+div:44482449128693269579458765976093879533678,400743721350983175894244132476709300635,0,0:110,400639780085120231091911403655856463828
+div:832339795151923812236511477767777941,2368224477252854985783540371974941967671687,0,0:0,832339795151923812236511477767777941
+div:-27251313242004640465020477977011074115415,2399123426123186914483922523780597130907,0,0:-11,-860955554649584405697330215424505675438
+div:434369443368140265771072488323999183210887,7582603002573727151808563609276596120660,0,0:57,2161072221437818117984362595233204333267
+div:-797664602996630747189073160786968930897788,8488149668482536480367533655921312940145901,0,0:0,-797664602996630747189073160786968930897788
+div:59063238214543857057620510112580247310883,28114133320457432516252314750546246,0,0:2100837,26711994025902474545948986923502981
+div:1573691164802147334879722389254185849497882,-7127075045154454822615337483298105005772756,0,0:0,1573691164802147334879722389254185849497882
+div:-40379721983479963451044525213342063379,5752617301360961501951105993116579979599761,0,0:0,-40379721983479963451044525213342063379
+div:-66553094204238345681366812314746973,179491260943660304940853680122139916257,0,0:0,-66553094204238345681366812314746973
+div:41557707370513928375878448109901883,632935174723424546856310964927309397,0,0:0,41557707370513928375878448109901883
+div:87216666974663503011714591959065214272591,-362212517956666997849487067083877113331,0,0:-240,285662665063423527837695858934707073151
+div:600930802118279524585230000011936249444105,276956438642688260499397309603052638,0,0:2169766,138070288388354494697143759139301397
+div:-9062026573948610573181435477111972535105632,26459705612915075584081819752039455108,0,0:-342484,-756815003826842757521154491791897360
+div:17653370013085499100472199530821555711,-7698383733180213420749857647904028433762549,0,0:0,17653370013085499100472199530821555711
+div:30662369693082036358310810281385879664,22236287546685236318100930067052020060194,0,0:0,30662369693082036358310810281385879664
+div:-512521060439171480106970932632563580,89514481912211104455621084880967327358452,0,0:0,-512521060439171480106970932632563580
+div:21086477798868875028201033077501739509,-32949987996179141109692270028847703801843,0,0:0,21086477798868875028201033077501739509
+div:-708751005350456170908462092345570661,20771494122418135637231294901492781698,0,0:0,-708751005350456170908462092345570661
+div:4761140473028193547540165802031057658,6168913684826084448506253549769822795,0,0:0,4761140473028193547540165802031057658
+div:1006721746946704053236444265263223831,-68339952093888456017995310177868766706,0,0:0,1006721746946704053236444265263223831
+div:49477930040212907700651237822802690917,932149775404881165633388914278605445476133039,0,0:0,49477930040212907700651237822802690917
+div:191141779546296204030941021563218099367,3656389331006196783212925046242222356116162,0,0:0,191141779546296204030941021563218099367
+div:52321773961113824095699208419101883834511175,3945419458824649179733387424219698232106948,0,0:13,1031320996393384759165171904245806817120851
+div:1778145454400348709637901904657092758,878609889134331105537302232981688580,0,0:2,20925676131686498563297438693715598
+div:74713594237827753439495191401245889889,5392802592936410381907322733518534312,0,0:13,4607160529654418474699995865504943833
+div:270095098083877602963826744218949767,47636389981971696673999931157764182609,0,0:0,270095098083877602963826744218949767
+div:7520391039221099182471773929113536857,381897415343050691905932641495648269699614,0,0:0,7520391039221099182471773929113536857
+div:63508808128380210731820150543656327585,-616515868713883945771114329692765309888882,0,0:0,63508808128380210731820150543656327585
+div:500726636417051241894505979036450257584284510,-2188106361907716060317149708820198851710,0,0:-228840,376558089498651529439670035952358968110
+div:9644202180018661897773323824784604735459,889341707658332087101739860527895964627301119,0,0:0,9644202180018661897773323824784604735459
+div:2169616399713342398130612752657502922,-320164160717395068313105728380324945,0,0:-6,248631435408971988251978382375553252
+div:-5377162725601993828110678056377142779006,55796345170536010537794307342731868052,0,0:-96,-20713589230536816482424551474883446014
+div:2037294950563567811082451474155649111,2834014022081568485840663386191616163,0,0:0,2037294950563567811082451474155649111
+div:614981246208238240735840654289003858288,59358494220000869333484696079415051563764262,0,0:0,614981246208238240735840654289003858288
+div:-869974954402953214631782702522562619117445900,461625972083775526198257072077692914743043,0,0:-1884,-271622997120123274266378728189167741552888
+div:502948632448506662993366487259075217376090892,42616114515034714091468739214068502864104,0,0:11801,35865056582001999943895793852815076799588
+div:6366779403200391484287273535628255514,82250958048563873223556347205141650947263970,0,0:0,6366779403200391484287273535628255514
+div:23811157225570913409830665082241103895611,7476929574668972035850358498197955282806,0,0:3,1380368501563997302279589587647238047193
+div:4433024520272083942063140827835336668419,-6814734610056822899976511626133696026724,0,0:0,4433024520272083942063140827835336668419
+div:968786326198881698061088417967223975939,599601873015338765622213846860944593816,0,0:1,369184453183542932438874571106279382123
+div:9195492262506042027630313206086692630450795,64887542474450141869346719067771980637953781,0,0:0,9195492262506042027630313206086692630450795
+div:167036152523476713010727258508768159942500,515803210529897970656947678674520384659564747,0,0:0,167036152523476713010727258508768159942500
+div:8138478748257408221805876607659300558448,49661986735515173743313027014090079675,0,0:163,43574910368434901645853204362617571423
+div:59222143484521909529262811142486420090033691,-51030363360606792052118776207857821648905144,0,0:-1,8191780123915117477144034934628598441128547
+div:-467669865565641334900015053005237790,-4166801708575196388168955453453946582052,0,0:0,-467669865565641334900015053005237790
+div:77373277085707339767125359451768440817535,1763315960012269607653138271304663086,0,0:43879,736076328961652913305245191129266941
+div:55495442705704588053146646518531149753186,-5663458625155167579301715514248517944795126414,0,0:0,55495442705704588053146646518531149753186
+div:488849922299811997818757217594597733202150566,939685030270889494431285974083671162411745,0,0:520,213706558949460714488511071088728748043166
+div:2400821515253609347478984845179365395392,174683346240076973534036449659865563554754338,0,0:0,2400821515253609347478984845179365395392
+div:94256886099064494671287831080381327786727083,933612219301830695726258097049775646275143622,0,0:0,94256886099064494671287831080381327786727083
+div:423105830682881413387057917631404228266134,257145583503215058907245918993287651344,0,0:1645,101345820092641484638380887446041805254
+div:9725239973027586290174961618324279259233,128059695274170533356219539907244279505,0,0:75,120762827464796288458496125280958296358
+div:8575857564646639781619620979013176021242222,-79327770769273229627122866232866675878,0,0:-108106,49577863588019549876402042891158775154
+div:8813097514151610923608219242438159700407184937,7989256671292882171963354392382046005647066,0,0:1103,947405715561887932639347640762956178471139
+div:-4220854853661426119955083509997540633581226963,-3143361547579787840091976435701544993088232,0,0:1342,-2463656809350838551651133286067252856819619
+div:18064088683968825697348480535147810355871,5304724916018022284963666250494765425823768215,0,0:0,18064088683968825697348480535147810355871
+div:668152482128694155192224637784736382693510,-95257956151627868536527340956566505149833532,0,0:0,668152482128694155192224637784736382693510
+div:61701221596016091555562189539716738900156785,-204037550501076287029400288051994390707,0,0:-302401,62286940121281584513032505583155969278
+div:9028974806172994844965393599047382592,34693980268705780311458320694963675758359651,0,0:0,9028974806172994844965393599047382592
+div:89063698366423052530435721631252853122745595691,-559482379459044468566903354300289497747749008,0,0:-159,106000032434982028298088297506822980853503419
+div:-1824554464595257659941777994663246309941052,73623748997742382675661945460325724770677,0,0:-24,-57584488649440475725891303615428915444804
+div:-55142421317035129657275321126826228423017036239,28826110399433506733627712523209314338730651,0,0:-1912,-26898233318264782579134782450019407364031527
+div:756782070286814928506227576085403683630,4000214993529718974257266487592194977145045820,0,0:0,756782070286814928506227576085403683630
+div:13159677289487357602217280155496420963004939,767301253318942647744497962442472942956,0,0:17150,460795067491193399140099608009991309539
+div:-88187589231094865339990742097539889292776818,510825751942051438265912944524438114392912,0,0:-172,-325559897062017958253715639336533617195954
+div:489109845016577010833075435898092017791090,110123269200994712057868031610104395461351967,0,0:0,489109845016577010833075435898092017791090
+div:19217131883780524110230989478044970954979,970929416394097229812264700944439582834558,0,0:0,19217131883780524110230989478044970954979
+div:24527357215769113990068349908153315315362058,-266862918096402442472122404915934028297493384268,0,0:0,24527357215769113990068349908153315315362058
+div:187180335008792237327827003721933462481,-854140420436008308741513900838309996093,0,0:0,187180335008792237327827003721933462481
+div:545261221970766906869881791377703238778715469,-8788464536650499527970204831752102396425142510,0,0:0,545261221970766906869881791377703238778715469
+div:-8978883239491077969334655758351790550761758569,404693816228247849601154967878424829635,0,0:-22186855,-219438296026172022653503521227250310644
+div:1672482949489286830657071584694755544154,-16569314415512041409298987093228138867183570,0,0:0,1672482949489286830657071584694755544154
+div:774730270533571544207396913338620375028137352997,48786260906229317422119214339872570992323,0,0:15880091,7792907516676258376772939019266087811604
+div:8223377606023157629124739253629162465167167,520715840696524916222797841353549481506911,0,0:15,412639995575283885782771633325920242563502
+div:19134961218524422663618095601519767611971718057,3320597299770542518684500859989485655905,0,0:5762505,2675610172546986065973326056572390876032
+div:9685331182266568794457591582614487872504040,213566802520062116223869626405725301078500,0,0:45,74825068863773564383458394356849323971540
+div:59252244414367138020160608470582658601544,-3576888946047794041513522160303428731243100275,0,0:0,59252244414367138020160608470582658601544
+div:9042130790289921021769539257940643994441439005,7080061253408914683252703075136834100504476,0,0:1277,892569686736971255837430990906848097223153
+div:37181356995874904748900986598480003983051,519027821181254318600589595065858229824972513884,0,0:0,37181356995874904748900986598480003983051
+div:4809573571268875241068163376639283894303,397857290741686940249008741474516933138008,0,0:0,4809573571268875241068163376639283894303
+div:57672160438267186781489366189915687528444846039,4311847164079124929339394059428992929411,0,0:13375279,1613350112775719684954110326408545415370
+div:8624907898892313136658244150578480770110291,18756723497726238453263886656453055357901904440,0,0:0,8624907898892313136658244150578480770110291
+div:4229153408642008158454182552166239580124743197222,723306877996286799790273745169628337170848,0,0:5846969,515510937124971245462645522951165247237510
+div:6302453408140626668691370469108993823368172,-26870693985061276927685322296318387971972897857,0,0:0,6302453408140626668691370469108993823368172
+div:-26183394096110224783461710144582526395666,8931365187310300822957876202988418128476294,0,0:0,-26183394096110224783461710144582526395666
+div:1337734304086488205388200603174151745237404,-37555196523265867970637056819130422860022,0,0:-35,23302425772182826415903614504586945136634
+div:1394934047175944473993592421680155397883435756719,3316595803755393152259408400413331925963184238,0,0:420,1963809598679350044640893506555988978898376759
+div:-3923445604156694953553293681269071976204126084324,-2385865039714571024603149142302411580843310590047,0,0:1,-1537580564442123928950144538966660395360815494277
+div:-4666574422365035446555661286742673507442477825880,6511395679936223490637275038009230986077915234,0,0:-716,-4415115530699427259372359528064121410690518336
+div:25682320341721789029990750876038989350503,2075225204575110735785546638041462321365144552208,0,0:0,25682320341721789029990750876038989350503
+div:507066551593936721924672174902109570507318,-90150385867099161583728850458645628165485311877,0,0:0,507066551593936721924672174902109570507318
+div:56460765920562193755877284769059649453013,106293089508542656937426290853822589311742,0,0:0,56460765920562193755877284769059649453013
+div:113389347059878790962060029189435317366606631,9123943931303946176502291145148092536746735300,0,0:0,113389347059878790962060029189435317366606631
+div:90965037743938985628689890077906379958065298745,355159479956085299356917050991168761100055,0,0:256124,171099666594416198867309844272190074811925
+div:-165340776845080586286334926027619556728505,4315813260375908780045944338058657645416510920831,0,0:0,-165340776845080586286334926027619556728505
+div:9675893678882076470951813438529414802324809,-49138410559062258960736821789190923818163376047,0,0:0,9675893678882076470951813438529414802324809
+div:52196020861900342939093799976830869614855,898691237498364401852494744239741816001653191,0,0:0,52196020861900342939093799976830869614855
+div:546701462352913231490095779602087905799659,27796772128829838971566803617855813694963277,0,0:0,546701462352913231490095779602087905799659
+div:-239361790908041495849499565651036682869595828,59582341264073879085346989042621623014587677976339,0,0:0,-239361790908041495849499565651036682869595828
+div:26247208631803295885744522675941429011719441867,94578293352355651122868883826971735945985150768,0,0:0,26247208631803295885744522675941429011719441867
+div:7151462784689393204933488144237700308252236907106,4869138896069717850331723402637093025616552,0,0:1468732,2675587124367180075367635717394552387255042
+div:444179011665054388522294113788022095382753092,87809235040601661387269133961569114730886240155,0,0:0,444179011665054388522294113788022095382753092
+div:9396002262631352355829080408353148431716175837629,627009066609807681311137500374921292105192019668,0,0:14,617875330094044817473155403104250342243487562277
+div:-67404859652885739843969210485993809184078129851,46946911826310720654816125341841364822782750,0,0:-1435,-36041182129855704308070620451450663384883601
+div:-857317750867775465958757317203227431120067,92423921722813825213538574566017075976934245071208,0,0:0,-857317750867775465958757317203227431120067
+div:-604814342197174902063835288834217421426135297,30987537976824612265560882867080135947080229,0,0:-19,-16051120637507269018178514359694838431610946
+div:537582514919678675297229509855601144545558,97995250751872994415105767317261578435382881110966,0,0:0,537582514919678675297229509855601144545558
+div:39007116647886661941726367331622958240358112679,-5144176915242189162509107363545822402755422,0,0:-7582,3967276520383711582315301218532782666503075
+div:720186514683083735071865829645724624020144283905,921875961665713476662472782679559347600188961,0,0:781,201388622161509798474586372988773544396705364
+div:4925300524276512099528492538263141469746686350,-21746080565844400504762758043901034656358047765835,0,0:0,4925300524276512099528492538263141469746686350
+div:5966000116741864064364725002160835848207074879,452383546194102189149587219685512801821102583315,0,0:0,5966000116741864064364725002160835848207074879
+div:1730022951574373079411594826626220707013971004,867119495065650306148038934759853852208599,0,0:1995,119558918400718646257151780312271857815999
+div:565379733109542105910214574424401953032077613,51059839129853759630343322732850868439955821491756,0,0:0,565379733109542105910214574424401953032077613
+div:380859104711500390575977473068323845888716252660,6180121353081961565969801679654221330060450855,0,0:61,3871702173500735051819570609416344755028750505
+div:68068921222429620875809588817152460375197553199,70847310210650369483877621724938884574632970327227,0,0:0,68068921222429620875809588817152460375197553199
+div:-722057802895969286253197273768040930277501,24306448094583832291685007488076569960645346636,0,0:0,-722057802895969286253197273768040930277501
+div:317592535736773933828600449815426639893020969423190,-93086204599568503148872348535005098881410913,0,0:-3411810,92021920119100246282360210893478434402340660
+div:611020260549327414799176188444349897969388695,3705943065234383781833374645394121853197511,0,0:164,3245597850888474578502746599713914044996891
+div:311597138605996430909903314778924265380533841573,900097580338833508210694004713940730225636589400,0,0:0,311597138605996430909903314778924265380533841573
+div:1471368037568797633184945517471946826925463570,-51986614090044718428104256857291140310189522,0,0:-28,15742843047545517198026325467794898240156954
+div:764577682558529028045406367446280331248422324968,3284529318538080158133345096780067681846690345,0,0:232,2566880657694431358470304993304629059990164928
+div:25345733340779680384223438130261035483720695,-4963832661075587414370207844502105067515360717435242,0,0:0,25345733340779680384223438130261035483720695
+div:9728219568997241790958216942026281594007662902,4830901363966824643813184028118279269292788953297,0,0:0,9728219568997241790958216942026281594007662902
+div:378990675295147250343254009937685278864098648256945,1608729233755427518873468676407616643664376791798088,0,0:0,378990675295147250343254009937685278864098648256945
+div:898267137520595727470006439782753575720539020,-10549538784345819645739254144254774260670381268575,0,0:0,898267137520595727470006439782753575720539020
+div:5995515572054268086933479746008640056780766451925,8030600055411670042494710011412948461403231,0,0:746583,6090884857231597651661557926755620958042252
+div:-29108480583332747319862771298993930146421704,1070825121844450385018502033657868394429345713,0,0:0,-29108480583332747319862771298993930146421704
+div:1309351864286127912492763722652139231241412,67215284518814518103811333196815587050385227,0,0:0,1309351864286127912492763722652139231241412
+div:5057770892603033060848565127774886456638357230325,4560833131311412489432012223910819044848375100332,0,0:1,496937761291620571416552903864067411789982129993
+div:633417011776645191559278275893992860044140785076,9267459276776555758115340080177517575774981964493,0,0:0,633417011776645191559278275893992860044140785076
+div:81198441395376013971576012512699341529160887275,7447901692377824339480278247455048336927582640790763,0,0:0,81198441395376013971576012512699341529160887275
+div:9051874321306026560005193316581192573940541867187,37537551211896722531771511300407567291038941024813,0,0:0,9051874321306026560005193316581192573940541867187
+div:2608213478636475749024179986585033501198860091868353,4860413071332838243659712432305837800300477,0,0:536623830,915784885941031884462459089442842973301443
+div:407598478820396357158686484143933270533665010845,4355992703916618082567359020934982484449368723357,0,0:0,407598478820396357158686484143933270533665010845
+div:630711778218873882494940824096903507347713330,57238514966674350042018295073350807282445218805,0,0:0,630711778218873882494940824096903507347713330
+div:93688378632955946315197302995234838965963790793683,3160654096505987021546437056562511465114160,0,0:29642085,1248727276013620984317459066303575325370083
+div:-2525656519498119353338247264242041272975381031,327276040767955818809485641052992513513655213981074,0,0:0,-2525656519498119353338247264242041272975381031
+div:66016468795885111884527337073458991710229978420,16320322768232010844919027662356786278707098868275,0,0:0,66016468795885111884527337073458991710229978420
+div:-2302712368656752027279644835027749767667073228557819,9316845119063833412338569173366972112730895383,0,0:-247155,-7513254530280253105770984235775145068780172454
+div:48838864669737321321234466529333448212306449830,-32564162155964258347156982593283846680395226572752488,0,0:0,48838864669737321321234466529333448212306449830
+div:-220645217365027594041560662624047120760954694026473,478332284603296206017913627846840038736821534931564,0,0:0,-220645217365027594041560662624047120760954694026473
+div:-72981125020238190928338132724424652132640002,39188164680782185128568299727848835374297549277320,0,0:0,-72981125020238190928338132724424652132640002
+div:848294406307295588337784985646050321749073734744419,1894284566269937543645699304914191326539279181,0,0:447817,1574693990967354998860017291904472233349746542
+div:88331621619959932308180786862825270799091494710705534,2178577739962310780960655130496700895938054790,0,0:40545544,2006897502197066182000445542767995672948349774
+div:-6856699040860275517650307648299585141626669701068,271009865938172922862180983261519271114664396,0,0:-25300,-149432624500569237128771783147582425660482268
+div:-88407824671930579360204282767163259115148101495,999762964506455261651611324045254876016161327250,0,0:0,-88407824671930579360204282767163259115148101495
+div:77210128389009986005731678815189051918123188603393,1004893588971319006745864695885807127204177369,0,0:76834,134373987661441419910771498947106517424633647
+div:297784613656392099571586950531714472282249229,38243230119670761105711715396092668555574825,0,0:7,30082002818696771831604942759065792393225454
+div:-35509945917648756037422888630539391852716391754248754,597284352710239029652457972715277271026334934549395,0,0:-59,-270169107744653287927868240338032862162630615834449
+div:801533871821359460893588251165565622439064765617,822025202425769092976017224921611946029366105,0,0:975,59299456234595241971456866993975060432813242
+div:-522010146755299559121351482887404344773949966,-3932667350437494585764045269025085811459344224177389,0,0:0,-522010146755299559121351482887404344773949966
+div:-58459624214325180544444869117416512994249719120541094,42099937836886376971951088854357470492133289729419,0,0:-1388,-24910496726889307376757787568343951168712976107522
+div:-253345562577317672511220652744246967807793182895907110,5749989880936090964050051849193062955356828797,0,0:-44060175,-2175044340819256659509727005208754118655047635
+div:929733472033240998779303334258721213318162598707,767612759141593942240674520830211174476840069251,0,0:1,162120712891647056538628813428510038841322529456
+div:964194291196691142924085838110342670268423649945,95195593030727305502485226537387747371662899678,0,0:10,12238360889418087899233572736465196551794653165
+div:-930824010798502796427972044794470458904018793646,59612624490118074742886336029812178788101136417100079,0,0:0,-930824010798502796427972044794470458904018793646
+div:4496931676886813794791418684601244183539575641824,17411178665119193136820706152905856572839870547600463,0,0:0,4496931676886813794791418684601244183539575641824
+div:-538173513290298732583524004704645684413620731176123,5191614740631357425621901873779740989648663178,0,0:-103662,-346046970959128706412664890173944661008818287
+div:645223072897535515198700423081805044495125969741938129,-4527829932821589910817760274407207149545929368,0,0:-142501613,4080777311682643434931455406859698817217867545
+div:99627943961043088669512673603139357672824609930416,466295743266513578268755141190344363951636566,0,0:213658,128046206330563766987646692761559645844511988
+div:8378463829762121913631626419465685262621092341,277603732177643189147101934156154702276101226001738,0,0:0,8378463829762121913631626419465685262621092341
+div:9842615010830513092601043514307725085136324358384,982829207195358411241726125114558021029115376,0,0:10014,563329976193962426398097410541062550762983120
+div:62320220612711436764404545275083408051364828569716359,29238061288213780350752248589890807799224738132935,0,0:2131,13912007527870836951503530026096631216911608431874
+div:-95796294809205390217092020218600576789023181059,165301144024373968274096547718999489219277029418,0,0:0,-95796294809205390217092020218600576789023181059
+div:87456781258209959765037687145068876793116934415493249,12068929953842578406244505715637579551016022265904027,0,0:7,2974271581311910921326147135605819936004778554165060
+div:4650729780737505464243409512735245030691695372618246,84864736041440063700547247893177477447164617313268,0,0:54,68034034499742024413858126503661248544806037701774
+div:-625358026462075054949936252035182773523079306781808,-7037095653882435960759081957329932874958248091338799,0,0:0,-625358026462075054949936252035182773523079306781808
+div:2568284414900282086629402504199999865573825319657504,5768783213527705673129403864116463929738223137152322675,0,0:0,2568284414900282086629402504199999865573825319657504
+div:21872791887330497853718749618057463060198347580531402,1324557936763556387760743907736237330887941028,0,0:16513276,1099563344481062563504290440813742452313443674
+div:-33663209218662096950671228753577152738857975888365,64455980252274430283628664249222461742909356825,0,0:-522,-17187526974844342617066015483027709059291625715
+div:897547639705131822906931936065160910250510030878007,5363864878695927157573012052790958211464944313132948910,0,0:0,897547639705131822906931936065160910250510030878007
+div:5009490811735999584822449253729050585733274306709319,2406843316925106774841027948556192949607544362335487460,0,0:0,5009490811735999584822449253729050585733274306709319
+div:26946852936100376197741904167965017845209833397099,308919640253848342394664627646584079095578466190402123,0,0:0,26946852936100376197741904167965017845209833397099
+div:1985893148050510215060586789904119885262534441,5866449806057188251900630030898916114586086296,0,0:0,1985893148050510215060586789904119885262534441
+div:5562239080137747796995442181907475991350284893459206265,156398892363409903713342341853412785128113829406,0,0:35564440,56612798080976501265602288199428588294379283625
+div:65178480098314895239449345070432724637440125039775,1290757832744933770056846180890168907973673153410496,0,0:0,65178480098314895239449345070432724637440125039775
+div:23657300680705528280619872949865464121904006372229057,54009346128207976631438579725539802296822123315,0,0:438022,18870935613940563883381325068840245386273546127
+div:2465896601579984309597565211236176792392608862458577021,-40289404326330144787151484318600863409012051557183,0,0:-61204,23899191274128044745765000529548307435258952748689
+div:4530895653520455283627656673385442171856783842314,-93233120674213574021733372853213159559027357138117667,0,0:0,4530895653520455283627656673385442171856783842314
+div:916112574807335146788888377531188026131378675176,967597859681274796485056494940030314717751207208858625,0,0:0,916112574807335146788888377531188026131378675176
+div:2836353387405193828295144729357504288167954496834813,-47750867938530360881039623534374164321838133495716184,0,0:0,2836353387405193828295144729357504288167954496834813
+div:888544290269727108571429100899398323213047387976643,232593764199419096127199419642853734112674182121501231,0,0:0,888544290269727108571429100899398323213047387976643
+div:-95528231285086139734583293340171808952248738222733284,793897402237626526946706417222476481392026422526754,0,0:-120,-260543016570956500978523273474631185205567519522804
+div:5037223546635984893254983907596574271648794864585,-135600768236385462209166458097331958573087149090026,0,0:0,5037223546635984893254983907596574271648794864585
+div:3597926907607703532951852295319420299540575082900605212,32397904521210638837288370977004776603517163371689911,0,0:111,1759505753322622012843116871890096550169948643025091
+div:2949870570599287735739111770944723963347077343574168440,13426005226039726224409657686289401061489856647303547,0,0:219,9575426096587692593396737647345130880798737814691647
+div:-6292945917085019054270321590350396947352956870846986425,341295410748594067077010194722238510564411359595737,0,0:-18438,-141133702441645504407620061763289566340222620787619
+div:576504230473861553261538972452278105135349421005,-435859823015036299275541119431403593387201588094,0,0:-1,140644407458825253985997853020874511748147832911
+div:513271751605046021061398181450246519536581003892,1804974737576433978846636236205909460681769870983,0,0:0,513271751605046021061398181450246519536581003892
+div:518565283589729505911763776861051767197425505162856,80256044584676536034995400588268683853363345693,0,0:6461,30979528134406589658493660247800820844928640383
+div:-8803453406819218000000306371196263081095678566028295082,-55765725990796735310893334087719738405325766157271534,0,0:157,-48234426264130556190052919424264151459533279336664244
+div:30910800403711655057148039026242334689849626271558314256,83948578597192063348545167380196449977141674761638849,0,0:368,17723479944975744883417430330041098261489959275217824
+div:49242996359867738984900367600384020935433157154372,2708783714074411929119022487862398012033030877105302717,0,0:0,49242996359867738984900367600384020935433157154372
+div:21379071756862143968426604961644165060562036140310,461158186026323145332549423710888480451753865883923090,0,0:0,21379071756862143968426604961644165060562036140310
+div:890497438806243182741322174370053431770114463163083,-553230364990398459699806691827737650133760743598577997,0,0:0,890497438806243182741322174370053431770114463163083
+div:3023647463972332206442886065358904974207929712372177354,954649340832479585995977185409104558411042237463566294,0,0:3,159699441474893448454954509131591298974802999981478472
+div:35489760963836552056324219511199170577078030263500,9911937794382297889765816250290479042378434631444578,0,0:0,35489760963836552056324219511199170577078030263500
+div:4135741741874158916022517640987066604514941788107532,-28163724964933933312984726177284380068495757852680949,0,0:0,4135741741874158916022517640987066604514941788107532
+div:545414705998769838413644038929944315836407586765492978003,40142701966897036750492630938275806447937324811027279,0,0:13586,35957076506697121451155002529209434731091882876365509
+div:75058649832069709510468311408895020488684235853480,-2888974200822060946807576793636547307530522265641548,0,0:0,75058649832069709510468311408895020488684235853480
+div:-66933551184377520017610837511897921700694960480368326,653887787579904832254964727311893728850303235046236,0,0:-102,-236996851227227127604435326084761357964030505652254
+div:2435629492619014604053848939625684854601784871657,-291893351983540450002470218001632642526157243983032264,0,0:0,2435629492619014604053848939625684854601784871657
+div:4353873124828196561972948174190449777941113312128,54820424043864696600903577780832618011158946935730643,0,0:0,4353873124828196561972948174190449777941113312128
+div:6563332558449452126564485551259042246419252988238165,698324403420861093632423144820174865039557171760521,0,0:9,278412927661702283872677247877468461063238442393476
+div:6651389855462289995786489027518276832180673970627,-491461095877924735369902036753617462691001210108931850366,0,0:0,6651389855462289995786489027518276832180673970627
+div:6927903135341590486179736781500384096788524701827,218829613953562480451106314783086433106706968172108955440,0,0:0,6927903135341590486179736781500384096788524701827
+div:545264621820945020606844611617845056531423301824882054149,875522645453735240583714479359375422140055663654,0,0:622787571,103319057246612448860090001299718413253014409715
+div:86684332448285178538540680259953842278268190530391877,1004758465343373611009533596159290181785288025548175925,0,0:0,86684332448285178538540680259953842278268190530391877
+div:-92317828450423143272179560065430627651793040689272,22070418041935886277960894290327131047538612473095276,0,0:0,-92317828450423143272179560065430627651793040689272
+div:7971256552090299009697202541746345670252715480656564528,201282600297357182844197939592816412476029915756077647398,0,0:0,7971256552090299009697202541746345670252715480656564528
+div:51609533271954429925110080029550304256694456133044809,485763884901242868745815971537580121006369686192,0,0:106244,35084506782578079607949511641880493715193261961
+div:55881591305337924534730793672599558668292512146650104410,2222509574710359486675225376172946110121737537397794673,0,0:25,318851937578937367850159268275905915249073711705237585
+div:19368449809775464181696546358821387683250538685332,24510908730652135218597094611704093063219507437128,0,0:0,19368449809775464181696546358821387683250538685332
+div:-2935049511482530629217049856269086660794528627329678715946,37471582465832914952060760873346941905859586735847868746,0,0:-78,-12266079147563262956310508148025192137480861933544953758
+div:36100788373557792247173517969159682950517798879230,5080501101336645920307905996377195554239168429725057140,0,0:0,36100788373557792247173517969159682950517798879230
+div:-619343993545565489581918826619755522056336720755028240,5722220737779420639556807213632172372985391133964,0,0:-108234,-5154212747676080127354659490977438635896761568664
+div:2214624479709129652867518274099800744215833156381,596426619358648105117142458022253139919252174606588,0,0:0,2214624479709129652867518274099800744215833156381
+div:5033621023669077052146401601213685801870950098584920712831,6799225107652133581418467714714131055036511563510,0,0:740322749,902228583435466263288772550060049562516909423841
+div:5358032037701639498140968139141468348228418868104,8558469544431829473340967206378658910509072615323310050,0,0:0,5358032037701639498140968139141468348228418868104
+div:9748963428125495559040360700047156483695054417931835757,89907138812423274211888428791450791283996367956807224600,0,0:0,9748963428125495559040360700047156483695054417931835757
+div:-37234857139625248358511007131249688678503673691725663734,-9768451005959695483831603140151504358763270636290461,0,0:3811,-7290355912848869628767564132305567256849296822716863
+div:14140350728384927368127641043017594043341305190489552,678387465698256214286200006608789600890351284725416,0,0:20,572601414419803082403640910841802025534279495981232
+div:16226406385251314022733101915283965938409231292486,-3756447461810096116929418499028120801376280771059460,0,0:0,16226406385251314022733101915283965938409231292486
+div:6545974979782747370293360546030862327851785067995680,-8744885285916351107220120754451051904389636789416979493,0,0:0,6545974979782747370293360546030862327851785067995680
+div:1152408063163445395815670313984522609667667839270597239381,95249480242199210996494814595420706184321580039151,0,0:12098838,32128876378241260984354491943697962902472875632843
+div:1690204685535914155988172971158586449220783297513957809,9929613337808118536737016690304412293482744573038,0,0:170218,5762400891834901871464168349997448737481780575525
+
+# Division by powers of 2
+
+divp2:6650822,18,0,0:25,97222
+divp2:-22,3,0,0:-2,-6
+divp2:626665862,11,0,0:305989,390
+divp2:382,7,0,0:2,126
+divp2:-8554783,11,0,0:-4177,-287
+divp2:80613086,5,0,0:2519158,30
+divp2:2476669303,30,0,0:2,329185655
+divp2:234993203,12,0,0:57371,1587
+divp2:78175,1,0,0:39087,1
+divp2:1092697,3,0,0:136587,1
+divp2:-51601200,8,0,0:-201567,-48
+divp2:-133,8,0,0:0,-133
+divp2:67494772097,28,0,0:251,117472641
+divp2:81070756,20,0,0:77,330404
+divp2:597,10,0,0:0,597
+divp2:-6061,14,0,0:0,-6061
+divp2:914736,17,0,0:6,128304
+divp2:5146181168,8,0,0:20102270,48
+divp2:908169,16,0,0:13,56201
+divp2:99131,5,0,0:3097,27
+divp2:828749,17,0,0:6,42317
+divp2:57934632020,24,0,0:3453,2905172
+divp2:374659,20,0,0:0,374659
+divp2:881062175551,18,0,0:3360985,123711
+divp2:8978255,9,0,0:17535,335
+divp2:-306454,22,0,0:0,-306454
+divp2:455535314,22,0,0:108,2550482
+divp2:-7013481097,8,0,0:-27396410,-137
+divp2:1902116776574,7,0,0:14860287316,126
+divp2:57980384,6,0,0:905943,32
+divp2:-6429952,10,0,0:-6279,-256
+divp2:-121080553817,25,0,0:-3608,-16163161
+divp2:9486785,18,0,0:36,49601
+divp2:-264976349260,22,0,0:-63175,-1194060
+divp2:-9957437441589,16,0,0:-151938437,-34357
+divp2:42280023,10,0,0:41289,87
+divp2:9445756856,10,0,0:9224371,952
+divp2:542833427595245,43,0,0:61,6271753240557
+divp2:-1989040985179,37,0,0:-14,-64895636571
+divp2:-842046065662,21,0,0:-401518,-1788926
+divp2:-36486783654,37,0,0:0,-36486783654
+divp2:12161238,12,0,0:2969,214
+divp2:522437544246,12,0,0:127548228,2358
+divp2:5771713949080,24,0,0:344020,16100760
+divp2:-192975675937641,21,0,0:-92017972,-1921897
+divp2:51399227509,40,0,0:0,51399227509
+divp2:76781489061746141,15,0,0:2343185090995,21981
+divp2:624421287579358777,15,0,0:19055825426616,5689
+divp2:585792449987,17,0,0:4469241,93635
+divp2:64111034807,16,0,0:978256,49591
+divp2:-4872049514614819145,60,0,0:-4,-260363496187431241
+divp2:-513726738058624,27,0,0:-3827562,-62639488
+divp2:-5129414645415250,35,0,0:-149285,-21103148370
+divp2:9777073958585027,20,0,0:9324144323,950979
+divp2:4917705257,31,0,0:2,622737961
+divp2:9309157350108809,25,0,0:277434508,16969353
+divp2:549889891480003,40,0,0:500,134077592003
+divp2:43259632605223,33,0,0:5036,721999911
+divp2:80760535636025,12,0,0:19716927645,2105
+divp2:95148114869248768947,22,0,0:22685078351318,2276275
+divp2:72784357307196492,23,0,0:8676571525,9292
+divp2:8695487295473310914,48,0,0:30892,162314927725762
+divp2:-999894977194,21,0,0:-476787,-166570
+divp2:422873004052896,16,0,0:6452529969,4512
+divp2:5850059500167,33,0,0:681,314043015
+divp2:279461298693250805,55,0,0:7,27259719560503029
+divp2:-2391765116812271696,39,0,0:-4350595,-221690208336
+divp2:93848076004932,44,0,0:5,5887145782852
+divp2:54463987988137594412,48,0,0:193494,268844485922348
+divp2:9735669349328114,31,0,0:4533524,691512562
+divp2:-96573804848256945392306,69,0,0:-163,-355587759787924163250
+divp2:693910684713664114,18,0,0:2647059191565,48754
+divp2:56085146568929935461,53,0,0:6226,6324008912519269
+divp2:7090107398039299,30,0,0:6603177,81864451
+divp2:767239571830013898753,66,0,0:10,29369808881631834113
+divp2:-74636360117262549362461,43,0,0:-8485171760,-6890174916381
+divp2:5461169750136459,50,0,0:4,957570122765963
+divp2:976702847245116276,37,0,0:7106448,71221928820
+divp2:3617864287401198,48,0,0:12,240164566873326
+divp2:-1309978694518086461,40,0,0:-1191418,-749976460093
+divp2:-2386749120888691269,33,0,0:-277854167,-244046405
+divp2:7266512965529689,33,0,0:845933,3826315353
+divp2:-6961513563355648932180971,48,0,0:-24732264461,-193888863384555
+divp2:5143351773441402886258,50,0,0:4568214,56404232132722
+divp2:900799510679250396,62,0,0:0,900799510679250396
+divp2:30978095034050773575947556,48,0,0:110056301970,184099523155236
+divp2:398942302365209775391228,57,0,0:2768218,44660240185115132
+divp2:914903526125867075664,27,0,0:6816562459810,77563984
+divp2:2551094792632393428431439,87,0,0:0,2551094792632393428431439
+divp2:6909886286515846175008,60,0,0:5993,427709407012247840
+divp2:461670131377821667,44,0,0:26242,15985200256995
+divp2:7884527998899506514865191,44,0,0:448183527561,3748608715815
+divp2:-17784618887403951072,44,0,0:-1010938,-9512034128864
+divp2:-2928855265612995457576576,88,0,0:0,-2928855265612995457576576
+divp2:8468445340017772238,58,0,0:29,109764431618131662
+divp2:97699128177500917404004263,94,0,0:0,97699128177500917404004263
+divp2:-901210903909447624384117,51,0,0:-400218038,-507572120280693
+divp2:-9099254471589743272646814275,80,0,0:-7526,-878753170044103808133699
+divp2:88420842262358445100031098,32,0,0:20587081616362194,3379223674
+divp2:5920604485769478876616913,30,0,0:5513992612966782,320526545
+
+# Division by small integers
+
+divv:-5721818303,-31144,0:183721,-11479
+divv:100359289911028,16,0:6272455619439,4
+divv:-80498620,-41490,0:1940,-8020
+divv:37386622,55859,0:669,16951
+divv:501578,15096,0:33,3410
+divv:6823,11067,0:0,6823
+divv:-56695604,31395,0:-1805,-27629
+divv:396,1627,0:0,396
+divv:82237128,16423,0:5007,7167
+divv:274600467,39390,0:6971,12777
+divv:258805,22852,0:11,7433
+divv:5139922232,23459,0:219102,8414
+divv:8755497783395,46470,0:188411830,43295
+divv:56370361453114,52292,0:1077992072,24090
+divv:81119249096,17631,0:4600944,5432
+divv:3925148017708459,17729,0:221397034108,7727
+divv:-289130964,59901,0:-4826,-48738
+divv:-2394107507926474,13709,0:-174637647379,-7763
+divv:-50229865870,26540,0:-1892609,-23010
+divv:3694598237147,64566,0:57222040,2507
+divv:-158417511658676756,-64615,0:2451714178730,-37806
+divv:4290308067505999,15193,0:282387156421,1746
+divv:560784439224,18032,0:31099403,4328
+divv:9207709447044,43308,0:212609897,27768
+divv:42833310641849859264,57815,0:740868470844069,10029
+divv:-95089845960500,-61243,0:1552664728,-23596
+divv:80687877739837,-30796,0:-2620076559,28873
+divv:87851714436662969875,61349,0:1431999126907740,28615
+divv:-5469457537,11848,0:-461635,-6057
+divv:-87902672172139257996,27307,0:-3219052703414481,-25329
+divv:-694576880064214,41179,0:-16867259527,-1881
+divv:47595892116434828,47204,0:1008302095509,27992
+divv:-505437926464614447947,63863,0:-7914409383596361,-45404
+divv:-747214784268033231559289,38881,0:-19217992959749832348,-36701
+divv:40648086806090824914,-26501,0:-1533832187694457,19957
+divv:23860923193973296,51883,0:459898679605,27081
+divv:-54927711987466879,-11937,0:4601467034218,-6613
+divv:4311756940677447464744993405,57924,0:74438176587898754656877,50057
+divv:6015889311543917179186719299,-50635,0:-118808913035329656940588,45919
+divv:3915173119649887691276,20797,0:188256629304702009,10103
+divv:209840208083311316090,36847,0:5694906181868573,6759
+divv:80000000000000000000,25,0:3200000000000000000,0
+divv:65000,25,0:2600,0
+divv:800000000000000,25,0:32000000000000,0
+
+# More regular division tests, all with remainder zero
+
+div:2546905999569583642767,14957376976449,0,0:170277583,0
+div:8820890915810513585008,1290654714992,0,0:6834431249,0
+div:32722399167479650872,485171756,0,0:67444979562,0
+div:281565136283209685892638788,662476076955569,0,0:425019326852,0
+div:378946105625441540737303,730177609549,0,0:518977986547,0
+div:4582336996784637790714331883462,524659399010705751,0,0:8733927201962,0
+div:30908196512568974558050436710,558351619821782,0,0:55356150882905,0
+div:22323179841972640636983704753,52956211127329649,0,0:421540351297,0
+div:52861155259463695471936251160,9468000366853,0,0:5583138277489720,0
+div:63260535208765360919938678377,42122224781389,0,0:1501832715082893,0
+div:28984143265639802151626094051438,400082299653446,0,0:72445452574997853,0
+div:3317964166851176108015612343691026488,4043377664512227983,0,0:820592198441457736,0
+div:66344183633702866132053676311141052606577,91178778320288608847,0,0:727627468320008374591,0
+div:5695550794829300030546270882518324992076491,700880200540761512031,0,0:8126282908883599504661,0
+div:39037424763225371397599506194643545880,7823304879274443640,0,0:4989889230399751117,0
+div:436302766535175847931361924986715811355695802824125,539874776595118725233603625,0,0:808155493551392334022517,0
+div:346745970223883677972239586841121624456285168,91526846077189641641348,0,0:3788461911289433710716,0
+div:52724986995800116311347732059133990047851510404883234,568154076534742483223872266,0,0:92800508125151146767566749,0
+div:2377848542111935708145523356022435793438514852230023651,78161062689778162572883876143153,0,0:30422418276855244470867,0
+div:232771550187355002750375300477927538332648185231317422242,385169380058229884085331084789,0,0:604335552717520311627548378,0
+
+# Bug fix regression tests
+div:#xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,#xFFFFFFFFFFFFFFFFFFFFFFFC7,=1,=2:#x100000000000000000000000390000000000000000000000CB1000000000000000000002D369,#xA11260
+
+div:#xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,#xFFFFFFFFFFFFFFFFFFFFFFFC7,0,0:#x100000000000000000000000390000000000000000000000CB1000000000000000000002D369,#xA11260
+
+div:#xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,65532,=1,=2:#x100040010004001000400100040010004001000400100040010004001000400100040010004001000400100040010004000fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80fe03f80,#xfe01
+
+div:#x0144E8D32EFB430AB38966D6CF217276A50D882C9BB1956E47F0C11F809819482F6671C7CDD70EBFD40A67E96E8728B1FB26092168F13A2689FEB0B86D689F12949DDF22AF0A030FDF2A27BB4CE09998ADFDD014B507C487D2BB6C71122AF93F13E99F22A7C5F2E728A50C7761551C4E9322502DB31D03BDED78A9301C50D57AEA88C1FEE4EAC7F0B38002C0F86D434B7D8311D4C410A0CECD6B81D40E8289F31045CC6F6C4EC203BF2A6BCF549759C92875BE633E20801C130874CAAEB8FD7276BE101898F12FE7648FB2C76C09D3643386B7F99B26FFA462DF54DBF401C8B73B5101B0A45D83774DC307ABB9F52A54E152E6FE5EBA1F5C91E0CFC2B84791413448023D6BAA4BB3B765DAC3C7D679832378C6737EAAFDB1395DDA29887653C17A4F16330550D9F71C99BD7D81777943CA1437F0C6C9AE89472A5CDC304DA0952AB154FF9F0B73A68FB5B7E661389AF3E407B4456A9FB5EC7FD7F78D0FA97C09DF4BEE8048687BFFA8B6231D9893ACCB75904A16BEB45C9B58DD4C63C9902D0C5015D2325EF7294EFD442CF7C6F837A8D6661DA492459429F9D7CE1251CA3375CFDD74A1C8EF5FFB8370245295E3C09B47D697EA3B5924F7181B1F9810FE479D2B17E63F1886053C32E53B4D6990DFE036BB50CCE32E76EB5BE5F2E0B40EFAB32D19968C0275277A4FFBABD2C5A24C982218DA3B32703381399A653A3CB9FA3009695581F18A7023727D6BE13E5D9829E9788BBC94DCFC493307101A0D7A8A212AA5FFAA45CAC31212202C23DC6ABB39D6192FEFF6FC3C084547036E2DBD6AE3DBB16D0101E10E899B32C70CEF1056DDFAD104E165F7D147C8143C6E6D08C0315D01D41D5FCDF528A8E2AF9B68526949742C691DD8EA545D9F450B54F447E52ACF59172A9BA2284703A6A525BA28664EAADA9CC9A1AA7875CE0273AA591F2AA8C20925EAA62037D109CA0EEA3824C1ABC869978B5B62F853980C,527,0,0:#x9DD4AE7AE3F3E047AB2F86F36EF8F04867BA224C9A45AC9596780B6AAC0290D95539B3274501D2411CDB86482673F35C5E41A4638DF46A28CD54634DEBE64A1E6ACE84760F8CE729DB28303CA956C1AA8026E69908252D172FCFA340B05236EDFBEE17A29F4EA5B964178B1D4EBF8AB92495B4130001D154C0AF742703CE32F707A796896EA61A92758FAAF9E4705B13ADF05F952998701DD5FC07CCC198FE167A50D95812D3CD5B67AC5AFFCD2A28654365B6C44FE8BC83A8C8856E9ED769A317D54C8E4D53FDC310DAF9677CC203032B951E697C5B26903614D1D448C2A7B3E357C60508FE4886ED8E2B9614F7E72AE7AA0410DE8A9EA328B6885D67423030B6A7388DAE88D78B1F8119A3A00C649F13525064648CB92FC88CF3A1038F2EDDA916ED8D06BA84AB4840D869A372C51EA44BC04179C5F7E08164001776D50CB6038FC968F29E30D97BBBF19C865DBAF7C1AD8D133F7EBFA2A80F5394F77DD530B88F0F323B7FC1A7EF8CEDD48FA12CE9EDAE6F1DF95FFDBD62452B214E4B51467A53A5D3C73E5408632E9E4097AA56DFA5B40BEF9DAB8E518867FD3D972BF155EA5C9A5EB17CD58074A742D5AF3DFCBC664CB5CA3FB4B0613485DFF8B5D03507D1513E399332A257DF90E7E9719BDF125430F7339462926404D531677F42E3E937A9CC83613A86394FFDF89A4BECDBA1CEDD9F6D82C4FB406A16F10E70AFF07927FECA0D60E176BEA8C4312E535AEB11B7665E858517F109BA90CEF68464219955024423D88981BC0DAF6E33B1A9283D412F16D06335EF9D86142025C37B54F0CAC5B5AE55097D9F6DACF547ECBBED87ED107543819C8DBD0099B65EBDD07D04DC74A3E2C2496D9E4E0E61D6615A7E08D3FE996DBE187750C4C1FB9B18B928B6550DAEAFAB8D7E4E8662AEBE7F77299D516BBCC8F2242B9FD28EA7460282819525F63E7E5C66E4D0C73181CE8577D3342D76CABD26D8CFB6,98
+
+div:#xC085B984D2F30F92A00B8814DCF9A909C8672B081225AA88A7293D276E46B240B96E345B76A5E2D4E5CE7F4C208616DD38CA2029C37FAA8EF2561C688DA55150788FF7F34E484596590DDE971387608FB88D92A8868F4A2F165D0222A272C5AC300AFEBB152B25D3FAB5999458B1AC27FAE5E2ED6D50E7F8FDE7E22178E4C954,#xD607ECBE4F4608C16A0FBDF0F4DC57278E937A73D2226CE8388C6B9B9DF9C58464CF3E05F29FC58B59CD34CBA4F47810D92B7B4FCAAD1860C76E091D0B1491B9,=1,=2:#xE64618B3D9A1E9B5DC38D204743994492C406B98FFFFFF95EF529A267E06AF4364F984172C9569DC33FCA47F08195C2937CD1CAAE1F954A2A78AA08AF59EC954,#x5BAA50658645474B56E43FF89470E38A4D69E90D43F0E1D5DBCAFDE8853AEDBAC364F06CE50511DEA15DE5D944D9ABBEA76EF56D1E1E2732AC396304B28CB7A0
+div:#xFFFFFFFF400000002,#x7FFFFFFFE,0,0:#x1FFFFFFFF,0
+
+# Spin in s_udiv(), rep. by Andres Navarro.
+div:45035996273705000,45035996273704960,0,0:1,40
+
+# ISL test failures
+div:-110768999339257979395151936604514986,384307167128540502,0,0:-288230376151711743,0
+div:-1141798147252782335678234520236874583761538254,990352029122461210705605426,0,0:-1152921500311879679,0
+div:-11417981504429295188771564013355757832033533955,2475880072806153026764013565,0,0:-4611686014132420607,0
+div:-19746054620424668475119147467564405598366894325375493578959094720,137015778031883893401769208133025156060969696320,0,0:-144115188075855871,0
+div:81791893044,81791893043,0,0:1,1
+div:66461399479760783996783510248698675,57646074961906893,0,0:1152921504606846975,0
+div:4951760153682756594365890554,8589934586,0,0:576460752303423489,0
+div:9903520270472025075672416238,25769803758,0,0:384307166770626561,0
+div:11141460315522012760862883825,48318382095,0,0:230584300062375935,0
diff --git a/polly/lib/External/isl/imath/tests/egcd.t b/polly/lib/External/isl/imath/tests/egcd.t
new file mode 100644
index 00000000000..8d9b695c54e
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/egcd.t
@@ -0,0 +1,752 @@
+# Extended greatest common divisor tests, including
+# constants satisfying Bezout's identity
+
+egcd:7,328492456,0,0,0:1,-140782481,3
+egcd:930165221,819,0,=1,0:1,-85,96537294
+egcd:166,0,0,0,=1:166,1,0
+egcd:44,37824113,0,0,0:1,12894584,-15
+egcd:0,93,0,0,0:93,0,1
+egcd:70522336,34102,0,0,0:2,-2785,5759331
+egcd:863,25,0,0,0:1,2,-69
+egcd:66399,5533253,0,0,0:1,1229584,-14755
+egcd:4107,14863,0,0,0:1,-1643,454
+egcd:7,482337424,0,0,0:1,206716039,-3
+egcd:477004716,83909,0,0,0:1,26067,-148185319
+egcd:76,9778759,0,0,0:1,2187354,-17
+egcd:0,8367890,0,0,0:8367890,0,1
+egcd:8335,721158457,0,0,0:1,-159892121,1848
+egcd:90370,2894953,0,0,0:1,591452,-18463
+egcd:67733,1618312,0,0,0:1,-106035,4438
+egcd:166575,4485123,0,0,0:3,-397448,14761
+egcd:28271,6,0,0,0:1,-1,4712
+egcd:763,53576,0,0,0:1,-18397,262
+egcd:52077184,5129,0,0,0:1,1375,-13961031
+egcd:6552609311,525555,0,0,0:1,173606,-2164516163
+egcd:6221599,7764515429,0,0,0:1,2913991310,-2334941
+egcd:89021590,33904,0,0,0:2,-5437,14275908
+egcd:739392892,9335369,0,0,=2:1,817116,-64718359
+egcd:8394864191,48,0,0,0:1,-1,174893004
+egcd:55087825,530530,0,0,0:65,-1805,187423
+egcd:243,6823694624,0,0,0:1,2218402779,-79
+egcd:7846,430402,0,0,0:2,-77457,1412
+egcd:67053681,8634785,0,0,0:1,-3793089,29455346
+egcd:6364928874,55124010,=1,=2,0:6,4571384,-527837761
+egcd:3482048,995555,0,0,0:1,328872,-1150261
+egcd:33038872623,62,0,0,0:1,-13,6927505550
+egcd:75504,62,0,0,0:2,5,-6089
+egcd:15,436212,0,0,0:3,29081,-1
+egcd:72635,93361,0,=1,=2:1,-22347,17386
+egcd:7009,4308,0,0,0:1,697,-1134
+egcd:40446737340,4212231,0,0,0:3,100060,-960797387
+egcd:728456835,694701023,0,0,0:1,99101538,-103916923
+egcd:9355087294,2631,0,0,0:1,790,-2809015189
+egcd:54733,8862614,0,0,0:1,-1246171,7696
+egcd:38730799075,40635,0,0,0:5,-514,489913393
+egcd:72,98,0,0,0:2,15,-11
+egcd:1322949,68,0,0,0:1,-15,291827
+egcd:49271099715,8633675426,0,0,0:1,-3947828585,22529669726
+egcd:175,762975785,0,0,0:5,-34878893,8
+egcd:321,55550,0,0,0:1,26131,-151
+egcd:217191,451486096670,0,0,0:1,198071748991,-95284
+egcd:681,2323372,0,0,0:1,917749,-269
+egcd:78678,523426,0,0,0:2,98880,-14863
+egcd:90350809087,38042,0,0,0:1,7341,-17435079373
+egcd:633,4435395170,0,0,0:1,406402717,-58
+egcd:16360,606577002,0,0,0:2,-128322922,3461
+egcd:9669450329,1009,0,0,0:1,293,-2807878044
+egcd:5871172260,26773591,0,0,0:1,6401741,-1403835749
+egcd:5017125540,8367,0,0,0:3,71,-42573911
+egcd:619,8820231506,0,0,0:1,270734085,-19
+egcd:60596719455,443,0,0,0:1,-151,20654863742
+egcd:6752409,94193,0,0,0:1,3303,-236782
+egcd:14045780235,33398209741,0,0,0:1,-7792585660,3277209961
+egcd:9145,27764492144,0,0,0:1,-4065243847,1339
+egcd:63567135,7519707417,0,0,0:3,-485762107,4106344
+egcd:875276189593,31047471995,0,0,0:1,-4089317138,115284166233
+egcd:531838714305,22614,0,0,0:3,-2211,51998558297
+egcd:4134506738511,2476,0,0,0:1,-377,629527076098
+egcd:6185136988713,1891462493,0,0,0:1,-495247968,1619475161045
+egcd:374166745968,81724,0,0,0:4,9131,-41805547421
+egcd:62423829,4320571,0,0,0:1,-1655596,23920135
+egcd:4949666413,1501091102,0,0,0:1,494932087,-1631978715
+egcd:956385784303,12089922808,0,0,0:1,1485803831,-117536040949
+egcd:6140630879643,9491202,0,0,0:3,631459,-408542209367
+egcd:211369,28015233,0,0,0:1,-7466081,56330
+egcd:8011144,24386,0,0,0:2,4799,-1576539
+egcd:9723,761305061,0,0,0:1,146419877,-1870
+egcd:24432,7899,0,0,0:3,892,-2759
+egcd:9912899,223787,0,0,0:1,82520,-3655317
+egcd:30742811109,445709,0,0,0:1,100330,-6920269141
+egcd:6445714509994,5444765,0,0,0:1,1710399,-2024833698457
+egcd:7932710,53078817369,0,0,0:1,-4132035559,617539
+egcd:3337840732,3077034,0,0,0:2,723227,-784527093
+egcd:718292818604,81025428743,0,0,0:1,34254894424,-303670650665
+egcd:326072,253,0,0,0:1,-45,57997
+egcd:29893828809270,93736826647521,0,0,0:3,-7295461626941,2326612589313
+egcd:4480264,223642,0,0,0:2,-23286,466493
+egcd:176957076,161560781,0,0,0:1,-31655390,34672061
+egcd:37146108400624,62308785533,0,0,0:1,28939329218,-17252518260107
+egcd:368208150951,692481145480,0,0,0:1,61559555031,-32732631176
+egcd:6314981,15499,0,0,0:1,-3877,1579662
+egcd:2805866,671806182,0,0,0:2,45436714,-189771
+egcd:98242818233,77004291671,0,0,0:1,37912166082,-48368707255
+egcd:607152,2932056,0,0,0:24,13034,-2699
+egcd:329110,861060931,0,0,0:1,423790795,-161979
+egcd:6035746008,726247945,0,0,0:1,-51545008,428383417
+egcd:388326,4784349702632,0,0,0:2,-1147292297345,93121
+egcd:34137115145,947284,0,0,0:1,456621,-16455174641
+egcd:9207216089,860347,0,0,0:1,-394196,4218585935
+egcd:8112578025453,2680608704,0,0,0:1,-855589147,2589349837748
+egcd:4997261,749601100642,0,0,0:1,-67513226341,450081
+egcd:852403018665805,68601329,0,0,0:1,-30001234,372779110814299
+egcd:92080405,52081391,0,0,0:1,-12636003,22340576
+egcd:60095571,4414432667835,0,0,0:3,-74437007062,1013343
+egcd:4981195051773,905850760614924,0,0,0:3,-146240346450057,804163027486
+egcd:9685579,9592868,0,0,0:1,1793043,-1810372
+egcd:59530646,36346354116,0,0,0:2,-4115037905,6739902
+egcd:1435163995,69604439462,0,0,0:1,7586354849,-156421967
+egcd:99926066,887606404471,0,0,0:1,169670756253,-19101407
+egcd:70441698,3974125,0,0,0:1,58887,-1043777
+egcd:849350185,211717364,0,0,0:1,-59186631,237440024
+egcd:20085073436,2395589822,0,0,0:2,-341128500,2860085191
+egcd:1126006461820852,819773895887891,0,0,0:61,-706362472938,970229368007
+egcd:70904095451052,2233930,0,0,0:2,400136,-12700165688899
+egcd:6758999,15939222862291,0,0,0:1,4123564111309,-1748590
+egcd:430279300935,431963821489,0,0,0:1,98776246963,-98391051236
+egcd:55721139210155,7073166691740,0,0,0:5,-369561824033,2911341799388
+egcd:192435034269048,1832500,0,0,0:4,7198,-755878513871
+egcd:15747650667716,36009594821,0,0,0:1,7200472117,-3148897400951
+egcd:38881764321,552729171,0,0,0:3,63876322,-4493383429
+egcd:691050011,51977919,0,0,0:1,22745801,-302406990
+egcd:52540041952180,2156326222,0,0,0:2,-170294052,4149305677871
+egcd:7905452,6213885,0,0,0:1,2027303,-2579183
+egcd:3430895541193263,119720318,0,0,0:1,-12421015,355956329656547
+egcd:78945450,1569850634390353,0,0,0:1,-213574967886499,10740367
+egcd:3026195347029,48776084,0,0,0:1,709073,-43992736549
+egcd:22612793613368,78277930892526,0,0,0:2,14856095743435,-4291603305253
+egcd:775918498,7426337401,0,0,0:1,-3568692411,372864079
+egcd:66668332441496166,5313627445077186,0,0,0:6,-18855448933863,236573103938824
+egcd:3800017785952,66078608868917137,0,0,0:1,-5030282046793581,289279111249
+egcd:8238037234,2941537491408,0,0,0:2,282888965705,-792255696
+egcd:9547120368107346,29456344,0,0,0:2,-2851235,924116168074373
+egcd:721478459,29799838078,0,0,0:1,-4113566985,99592822
+egcd:463484777885,77160851,0,0,0:1,-38346752,230338774171
+egcd:6668812562,5426227269,0,0,0:1,-1878258319,2308372291
+egcd:7020839924454,9619730190140,0,0,0:2,1676947567713,-1223899236455
+egcd:5581687877912,4728620673,0,0,0:1,-1477827499,1744435091593
+egcd:86212837117,93176774191319388,0,0,0:1,-16333778951401391,15113008971
+egcd:10486952786566311,8072710949230,0,0,0:1,162596692991,-211223200405940
+egcd:332388514681475,314477095129839383,0,0,0:7,-4152534349932681,4389046916654
+egcd:1878789616020411,634591014351511065,0,0,0:3,-55735306584035142,165011657725421
+egcd:853435249810090,294022990301,0,0,0:1,-71973674612,208911796010781
+egcd:800760331,479138587,0,0,0:59,2283452,-3816219
+egcd:310386781,45470476445,0,0,0:1,9204755541,-62832736
+egcd:206381927221,426737049973016,0,0,0:1,-51635348161827,24972293048
+egcd:80657906841,97722845343178,0,0,0:1,-44940641023991,37092841744
+egcd:3626879556739,974287797969673,0,0,0:1,-416739368163900,1551352175437
+egcd:12353260720882,167588026304493,0,0,0:1,-4766112882926,351320057681
+egcd:5680097354,954648204845001,0,0,0:1,-206590628821018,1229201373
+egcd:8495790423,19792054180,0,0,0:1,8077970807,-3467489852
+egcd:1808291492597692,96814519920612,0,0,0:4,-3825789187820,71457690917437
+egcd:796275712123233,71773988020895279,0,0,0:1,16421100444870785,-182179140537376
+egcd:62156477407557,3665981752,0,0,0:1,1292733717,-21918214413059
+egcd:2921017132462,944466357361,0,0,0:1,-167559490864,518222951729
+egcd:70129038286402,2652828624150588660,0,0,0:2,61204814273941601,-1617984186560
+egcd:4099194006860675,712258835980,0,0,0:5,-46544273205,267871728840131
+egcd:18993264993,72866008153094,0,0,0:1,-10126377677909,2639543177
+egcd:37137778422333201,725902397772208341,0,0,0:3,36710995342741392,-1878165459827929
+egcd:77046543323827,91919074661304,0,0,0:11,-3080180234575,2581806232959
+egcd:50946730035622,6841431278091013,0,0,0:1,790206978840254,-5884508662999
+egcd:778417902091877810,3526771827155035,0,0,0:5,-62143495200058,13716115340897371
+egcd:7357629905645982343,273989149651,0,0,0:1,-10489681694,281687051588686593
+egcd:59999050131295751,4402788959646093,0,0,0:1,2181599081375342,-29729763077344837
+egcd:68611931054045254,72532452638242572,0,0,0:2,5482399071936641,-5186064629726171
+egcd:8597485693846941640,9852318416413,0,0,0:1,4640854869916,-4049776069443081003
+egcd:570460270963,54720108308,0,0,0:1,16083505887,-167671472335
+egcd:43617503830797013,452251304617430,0,0,0:1,76760132288467,-7403152472886549
+egcd:73871669508560399,48493623727,0,0,0:1,15908333574,-24233601655059575
+egcd:99534170067866609,8533916062,0,0,0:1,-3636610149,42415108188475141
+egcd:1885231469789,5484240550249,0,0,0:1,1215645072521,-417883264932
+egcd:1988347340743956951,7107237557789347,0,0,0:11,216195821117034,-60483750895153609
+egcd:1028936133037327271,5510465055402,0,0,0:1,1073852868395,-200514113917520622
+egcd:908361247108559,833255131023,0,0,0:1,70168847825,-76493572911138
+egcd:105122420688920,8437707543309,0,0,0:1,1099150493096,-13693928112891
+egcd:7268354783435841902,933995610637335,0,0,0:1,177721439316803,-1383028419904388383
+egcd:50338474800791504516,946966290251750,0,0,0:2,-82754441959453,4399029230620270937
+egcd:38695580832418,77020806554,0,0,0:2,7049841355,-3541870284322
+egcd:460793682039951322,360995931125673,0,0,0:1,-12872500500857,16431118446002835
+egcd:9791371944228644211,37881615337394730,0,0,0:3,-994456930616087,257040192279396732
+egcd:726186734680,24419809216698234959,0,0,0:1,-2766640019167190414,82273258719
+egcd:529564016606,376298866055896536,0,0,0:2,28277719651140475,-39795131343
+egcd:145541869208926297,19688885314609703455,0,0,0:1,-4361261236227472297,32238803887896062
+egcd:39778456127502718844,81278417471936841,0,0,0:1,-7120109086823404,3484651347093815497
+egcd:7809654411174,1244628241216910096,0,0,0:2,-284584948977462005,1785681883582
+egcd:247581683736939421066,245039298196,0,0,0:2,-51357390229,51890244702955249521
+egcd:667668476732052,476696223555,0,0,0:3,60657763034,-84958248556823
+egcd:2229399707506,39201358276824482440,0,0,0:2,-5131877014016252583,291852262700
+egcd:4767576564991009579,340159717388,0,0,0:1,-29682941117,416027199034854288
+egcd:748410307121741,730540185467629182,0,0,0:1,-213318504992896387,218536599371724
+egcd:2356182915322420038,81237995138900716,0,0,0:2,5252342047370707,-152336090720664004
+egcd:6513077506735657,306517877388663388,0,0,0:1,85680643466766665,-1820594206381108
+egcd:216282311653914599395,911124646576,0,0,0:1,429112007291,-101862393081040854019
+egcd:59815399922090959,5110979162439569056,0,0,0:1,-1114788966780819601,13046726616842810
+egcd:477652083813766,624733750918729402,0,0,0:2,-154413302241487321,118059630163644
+egcd:659935429542750939,44886608128116509,0,0,0:1,15839652572247565,-232878989079292726
+egcd:54504214226951518003,387724255017508609,0,0,0:1,31301361124239357,-4400178916414896230
+egcd:783331167504862965,48609697533,0,0,0:3,-629742688,10148120643700831
+egcd:7643973606720,70743283292590583724,0,0,0:12,1182943528930131602,-127819754647
+egcd:4273152632680100030114,1455223242316512,0,0,0:2,12098554144849,-35526486240961014982
+egcd:5862269731025091,3136791365228,0,0,0:1,-386529556073,722375272334573
+egcd:659628551534893059484,5950075862222037,0,0,0:1,2470161881316403,-273843450328876151623
+egcd:9482121506846253,34058669367564240,0,0,0:3,-1589045402569649,442399009322730
+egcd:65396942933391,3530693943836047978,0,0,0:1,1333698073169157271,-24703295773820
+egcd:24559856763503,6667927595346,0,0,0:1,-250002320323,920829011695
+egcd:4843560767022,8140092963222,0,0,0:6,-479036307613,285038693786
+egcd:7703573212864,4497158779255,0,0,0:1,1735016188064,-2972059668409
+egcd:8411329856643749667337,6927690295201914990,0,0,0:1,57955419569688883,-70367197465289023043
+egcd:311630305921790132,36794945100846,0,0,0:2,5335676048581,-45189858410215015
+egcd:12252240244679740653,21854667756737479,0,0,0:1,7408241549029968,-4153234277439483257
+egcd:914930916911818959,73054804640859,0,0,0:3,3000864169057,-37582516567124740
+egcd:144437770651525337,7176192389740,0,0,0:1,-2917598661927,58723543558714060
+egcd:9658485554428935101,5617211853860547,0,0,0:1,449096244749153,-772196190086168116
+egcd:344028716311850,2026849525600172204430,0,0,0:10,4273604619400616489,-725383257448
+egcd:936445752013986984,883181511511066630902,0,0,0:6,37504920718991502298,-39766823953131263
+egcd:8136225792202716788767,6604882712946357,0,0,0:1,-763274997603269,940240423932206378732
+egcd:577476567105329156936,1256480674248716110951,0,0,0:1,165865135596220858037,-76231358802105687681
+egcd:58801491048115,31028000846825692159030,0,0,0:5,2620151256531588957285,-4965476229559
+egcd:9973707804728263847551,53630829606521208326,0,0,0:1,16368451878013344235,-3044035631088017117934
+egcd:17121194233870838,44442113181771232,0,0,0:2,-5375949729958541,2071068923785980
+egcd:194930254933589618442,76996294363551631,0,0,0:1,-38281520562566769,96916697409778838629
+egcd:6740972199816713986701,3164254690674619824,0,0,0:3,304736351600199807,-649195300386062944621
+egcd:33100303896200,74054854499575190726143,0,0,0:1,-30231828546967434629772,13512722683807
+egcd:80391303224075976,94483334960558284,0,0,0:4,9695304929308312,-8249266378534037
+egcd:954262165857127978158,3790250771466830,0,0,0:22,53714840833849,-13523654091347297164
+egcd:50095431507743637803,32894122691956397938,0,0,0:1,11834908275426407707,-18023731548159747940
+egcd:2173109072764661515,71129381706084812,0,0,0:11,-844279059631827,25793988931499293
+egcd:52743975673113,1252477537471129,0,0,0:1,198187508901071,-8346015665318
+egcd:3400327281633151,431371474891473455,0,0,0:1,205422443946739001,-1619262239320730
+egcd:74672816465806151314169,181861345000582103629,0,0,0:1,27254332141007722192,-11190710933415108645643
+egcd:474476291935913056166,8171705897201808883848,0,0,0:2,-1170007477720025417249,67934506766326698557
+egcd:984130837655605609160519,483475686999411456,0,0,0:1,30260545442548343,-61596346486657707977136
+egcd:843814604333653656215922,682249690564087391733,0,0,0:3,38030549017256981789,-47036639393790777318635
+egcd:81202937258153735712,402831457452712664,0,0,0:8,13421756749885189,-2705563458591282665
+egcd:6676582659534088,44001550460545760069911,0,0,0:7,1211181274540019933457,-183778794394919
+egcd:533144411502628328950,28324708505596385902,0,0,0:2,-1398171989606979473,26317219908236327476
+egcd:66581532981454422,14028130038905754906,0,0,0:6,517088823759485624,-2454252026321337
+egcd:2130464987067329677,8494848036198574143,0,0,0:17,-7062764335631653,1771305627228686
+egcd:38575228438194,1957852613377826515509,0,0,0:3,129868619328885840117,-2558778747355
+egcd:49489410876608829677,7951728226267755060269,0,0,0:1,3860693946871021816365,-24027917399688934216
+egcd:42770760432244640,44801059402399356,0,0,0:4,5296495695549791,-5056468564505481
+egcd:6441135230593242548407,122558774271814342,0,0,0:1,36997056041193015,-1944398045028139827512
+egcd:264902435468141506,823887292259809475,0,0,0:1,120342636882041621,-38693469240520931
+egcd:4615387069156629,5068444832682377449634,0,0,0:1,-2198712149475939054985,2002173834082799
+egcd:36444520368083130251,10180304221606287367,0,0,0:1,3547776565155412457,-12700702501188462318
+egcd:2705117385426850078,311987185491928483938918,0,0,0:2,48604570190513342423426,-421430988026778607
+egcd:6447135503640541,17828837916381145944,0,0,0:1,-5783155035268931939,2091262724234125
+egcd:193981008037679996757,19120164140966891788,0,0,0:1,-1586493554887429351,16095553194700936591
+egcd:64332664201713053,87185087911910266023,0,0,0:1,19609332567597552767,-14469453865385550
+egcd:95102121410339574,293671951113485105415049,0,0,0:1,106953417739910482828300,-34635575105438351
+egcd:65154144550755804519,4285018859628755463,0,0,0:3,-609852871996317628,9272874514298907745
+egcd:7165578261547505,763555532759171606,0,0,0:1,-174953906015578927,1641852952316256
+egcd:5442458157933637000759,66760245307752621192750,0,0,0:1,29074397305494111881389,-2370215838375818515507
+egcd:42143136951989716656,827894838488320343515,0,0,0:1,370905938581526544116,-18880586083238491373
+egcd:5295415444080909673074,5092055214749737510,0,0,0:2,-79624725963726612,82804680196255688279
+egcd:118338007742261895,5763460050841396334194,0,0,0:1,39330742550539324473,-807556862613311
+egcd:57063373752305154812,692318043858914149958,0,0,0:2,-70368857818416495450,5800057458900243919
+egcd:49356454157781030126,38544768358653028317,0,0,0:3,-1638594177535601368,2098214669607345263
+egcd:98128015703777581473188,71751790667213936232,0,0,0:4,1131009376775245397,-1546772628993544572326
+egcd:95760302891303565510312,49856290116188787587208441,0,0,0:3,-3088248308134997399905293,5931680690668486327459
+egcd:40420853393811300450702,87550419156538713298378,0,0,0:2,-17578959514036280337967,8115969657005769255362
+egcd:422899389299537033304669,8005135756870427773,0,0,0:1,1826207874406781724,-96475839795446732840135
+egcd:179674525723481348814,69928617693608886497807522,0,0,0:2,-17176881265197584758274313,44134262860096480672
+egcd:7789649675160016285918,417200326088447794162,0,0,0:2,-94835249783231044512,1770692222592009406889
+egcd:177465346778880323,60001957340989928039014267,0,0,0:1,24984084908903832591086708,-73894410929202849
+egcd:151317887902583777,714764598301032762905,0,0,0:1,183810322507486902798,-38913216802619989
+egcd:51078283105727024828148762,75871019523002756919949191,0,0,0:3,11485911105291504406000748,-7732604924142639690250403
+egcd:4760258696724862445736876,3471524299806755969674,0,0,0:2,856359023818037629295,-1174265290574387452901557
+egcd:261631865216813032,5681600833992180785,0,0,0:1,709538151924588968,-32673500929505135
+egcd:720979639879195715,783996604122129884144,0,0,0:1,376019130933410843211,-345795040670644006
+egcd:36110696808763448994,31631881940059268291965,0,0,0:1,-2383142920549669168891,2720576398805277667
+egcd:658675475456498963270,36727416735327035,0,0,0:5,3298655738340100,-59158629436863579657
+egcd:61220559308972890,667000611959077400,0,0,0:10,-26640911325438571,2445232377004423
+egcd:40220367562984968880458,89139127967069561321,0,0,0:1,26548285035112330181,-11978822394062224915657
+egcd:268590992017536259191399327,61179964518317742544264524,0,0,0:3,600487671783052773266369,-2636248332740054832357965
+egcd:834052968320156609779657,4980797187259222752640,0,0,0:7,-284790928354963265969,47689297559175644596626
+egcd:2304058851313997444536039,9169653702125462923229,0,0,0:1,-130649054522071275152,32828187439358617259301
+egcd:58451234918953535616,811141856188592686,0,0,0:2,-99923944925714621,7200562927828430183
+egcd:822396573998213269,36745646576975841888238,0,0,0:1,6092800501072128894693,-136361684305643132
+egcd:17578713797195009784,68270861083809145500872866,0,0,0:2,10088182822145144907111889,-2597554443418689739
+egcd:76377711400349230044,28120345054943065861736,0,0,0:4,-2062007766043178352451,5600622387542163743
+egcd:76762683909293356952194,336742697639190379,0,0,0:1,-75512400432970134,17213541871304020806343
+egcd:718613829360289007965846364,56996018089280939789090,0,0,0:2,-2524732262127936558957,31832180208715887766629415
+egcd:7295663098480852718,14423786075811123687515222,0,0,0:2,-3469836111463770997012649,1755070072665297072
+egcd:15211419951748549035347,4699398308750843428412139,0,0,0:1,6946404824215205904662,-22484725489054469667
+egcd:17150054056990843968091,37598518807922567502949,0,0,0:1,-7518057558796082945642,3429259918338934660227
+egcd:77024520800929983778,12004114915728728552,0,0,0:2,-2120493047554731255,13606164385813996546
+egcd:6552691621635472445,9454879100164928596390176,0,0,0:1,227870736946333719833045,-157925516866534574
+egcd:380663675562604264,44830819384430864282488995,0,0,0:1,-16273991432157066610391981,138184344602692003
+egcd:2230931798936940632516431,790824149442647895647799515,0,0,0:1,331133100467518126491471001,-934133541615045780146562
+egcd:95014513131992964781831,6426665041014306194430759004,0,0,0:1,239158098260009820460949479,-3535813695397102752012
+egcd:45587301786773822623,12200508698455746294,0,0,0:1,-4813378778407164821,17985229666126454386
+egcd:544408824836312286809239334,47857195870319437437969,0,0,0:1,-3285821056099126073737,37378495485205612484001511
+egcd:368559293555584153297233,863543676262890554,0,0,0:1,182689982444744817,-77971841749691835919840
+egcd:286838686809753815604,290258385092986016322966,0,0,0:42,-3439904517337276235112,3399377055680475215
+egcd:247310884666793355418391440,8146285853652299839620,0,0,0:20,77671205038431135851,-2357999065620583642815591
+egcd:723355341278352532752,2716643920855001136283,0,0,0:1,-647343221413917008844,172366784345707798483
+egcd:4747770341760547358928,3900131915460402444898291,0,0,0:1,-48191502504962163320631,58665242939847808459
+egcd:62996662961434499047,9733114500463650951,0,0,0:1,-2609387863316684519,16889016126666164094
+egcd:85408851497556727644592364,176571048356555258831010,0,0,0:2,10373200197110227040698,-5017601262696030666591307
+egcd:3859907398033663982,96346670011473683698108682,0,0,0:2,23114207598170766553332033,-926017483502444222
+egcd:372461979322690243,540222307494848292,0,0,0:1,-216390837474738389,149192949855933584
+egcd:7516220184290968225960,300386413342210429744,0,0,0:8,-15749172306804321015,394073238736743444182
+egcd:6108319432277782804,82931541043539126216389,0,0,0:1,14516925059734418621210,-1069243551048233051
+egcd:7230921518942393713547539642,72114378808806856868,0,0,0:2,-16718190793824596963,1676335948054892581924595036
+egcd:3825709037512543084718302,2651564896588437884119958,0,0,0:2,-590856988072406763814624,852495415840807251070275
+egcd:911054271475454361570597270,621648474138432132340027,0,0,0:1,177507600588673885690903,-260145507410443226451439067
+egcd:65298316398221703103077598,534642984572205231284578626,0,0,0:2,27704620476219826795345676,-3383688041836699547596371
+egcd:7540589021419394540066,951669501600612914519183,0,0,0:1,331190832641661629577944,-2624202995275280476641
+egcd:9761932411251041918483933,382356303803298271385489,0,0,0:1,-174786897144790383992576,4462481353982094260231281
+egcd:29200924565006580097578,89587549755035053290130260583,0,0,0:1,-12724495224425705121391303686,4147529720281901737723
+egcd:99943694998442521323946016389,333424364613212729745462161,0,0,0:1,-5705329051108614724676136,1710167963313731051974706105
+egcd:5690154324629967337460,1632283715496329281241648395,0,0,0:5,56290934452012514099439970,-196230655901744389641
+egcd:1925002725694160249373602782,3526543575073330036110,0,0,0:2,-3919880867811415654,2139710227393535147948013
+egcd:52670953750351044438983990007,6419267762739355812530600,0,0,0:1,-203989820551702316343657,1673763862318789910544563426
+egcd:510257531185418430181,66420793633874998820433,0,0,0:1,11533829131275308680081,-88605131851925052020
+egcd:624028484658998836131051,290010878235398822043835106,0,0,0:1,-122928139167747537660445423,264509596583252200647779
+egcd:82126417002597285652,9711508871315310668247843,0,0,0:1,1977141009391962114230902,-16719905131309273821
+egcd:5313586393962705049080,76998532453336088964044527295,0,0,0:5,7351068169285296934826456278,-507289354236443273333
+egcd:7446329018924231360114,281705996976935084208360,0,0,0:2,61771771846187437852753,-1632812017439206420394
+egcd:92632241917277332460964,41225270861482533930349836,0,0,0:36,-232831718389563965069268,523167552648600475583
+egcd:505206995627529688155,30108238444718526549709911,0,0,0:3,2815345833969785332425863,-47240638572857371542
+egcd:350682530039234485322546750017,732856831499478812681071778657,0,0,0:1,114634298969783930190784719020,-54854160136223590904319282827
+egcd:73936773633607324540860765536,5462243107704027813296706,0,0,0:2,434277168489579388852756,-5878363900642009138649028319
+egcd:9329801698838720379683494,2642515095105038480589941,0,0,0:7,174846258141415342001899,-617321323637898767831439
+egcd:25822034647579787624514946804,190739018295930506821730846235,0,0,0:1,17294294853830144704620058819,-2341282265740751416856382785
+egcd:7949963986480899256177301,54250986866391077101265062,0,0,0:1,-4923803556165288789334505,721536385032484788574613
+egcd:3746930579001676751120,99207386871851914556838486427,0,0,0:1,-48583865685594090026984533471,1834947756648482241123
+egcd:26584400729548923821953289,4186329192513161170925,0,0,0:1,1656738211241031433334,-10520766639746090510993433
+egcd:15015617716874132201457077873,908213746723440854928237000,0,0,0:1,408879360871055069439454937,-6760056426484746584749467457
+egcd:941171208223609049472714,2820721728009499408048129,0,0,0:1,-561073227079218020506735,187209522225614099075479
+egcd:30137430783951200466620,7932600136613507821178378958,0,0,0:2,874263946876564747820132932,-3321492162990162597361
+egcd:55007423087104738440174209,45869037869891649236,0,0,0:1,6370717719612306117,-7639941477849380770592557
+egcd:49096256950991848579874131467,931448097952317628160996789,0,0,0:1,-326595408525690731353759748,17214713445914733493338694553
+egcd:1122894299337591195948255,54881121839952705699464175,0,0,0:15,1530959605417535453487243,-31324174065771247623514
+egcd:35498057471655773087035017,85668857880959672128179,0,0,0:9,413483537492374633285,-171332532504207423622284
+egcd:1887739328175786669349,5857986692383902136266,0,0,0:1,-1152123029924601355085,371272259343532579901
+egcd:291707312665735093614825955052,7207353925931727830829,0,0,0:1,-3501220426060812684211,141706874954742490398970247737
+egcd:95531532857951877080714695655,1267695778421377857836,0,0,0:1,437662312686039158539,-32981534147821284545085645329
+egcd:74484904487858142015156737,351049851111701482889769961,0,0,0:1,17139443017007319377607732,-3636605376854762326364603
+egcd:2136069932966937675469,7447531079022134243581196506246,0,0,0:1,545901561496939760038844699835,-156573218627833145909
+egcd:509775218017409565394932197,216635621683624922457211,0,0,0:1,42814883976773638426025,-100749667317060906989689284
+egcd:745276060382671550825981532388,5112220648677904268244,0,0,0:4,-58944865145259393149,8593173083522474449221607614
+egcd:8078258267292267766114067,884100779411269652418038495,0,0,0:1,278129835236887309130321543,-2541344486065477531385724
+egcd:8844980710175781452273298,935135907771717589995041479,0,0,0:1,-48834539676535952819435698,461901374804996053728595
+egcd:58087603156751215661949004,58712010607326754590110,0,0,0:2,1191143911590048935583,-1178475990232715912474903
+egcd:5679173086064233367773646048971,12789890243264425121239084,0,0,0:1,105424447625040632402467,-46812261417225737221083455184
+egcd:77653936311643667916482493998,15693437224085205047080,0,0,0:2,2640971088036021388319,-13067997644040407190632050442
+egcd:7284686326593740714529339,90971885163627008124264246742,0,0,0:1,7198130762602806275082298459,-576399232016044918973300
+egcd:30545805868231898661181062,9266612086889390909321896160792,0,0,0:2,-538109282848491556444597462033,1773785449920680245879519
+egcd:5874785131042125952122412011,2349616696032997520626166708,0,0,0:1,561505530055217292587132395,-1403941478853022044849375718
+egcd:260436619859311350841971,1212092952552738381785471705126,0,0,0:1,249307384938854393628000175415,-53567486307626529321214
+egcd:2081870677650494937076,343501716877184044936575,0,0,0:13,-8002592767368064135037,48501542813302049871
+egcd:5691817817445639700141386839865,8687746818925263901770782,0,0,0:1,800431353877405067350643,-524406331883086413378341354467
+egcd:7181315131090723377262366519,979729982933337084774328653741,0,0,0:1,234315848781865941936193642222,-1717509905406328622700624837
+egcd:42080505166736566441565451216016,76651513399029916866847,0,0,0:1,-10862717669575888116265,5963465387040535737057564145103
+egcd:3576584500173313993122814232472,956729492745224694909152831129,0,0,0:1,112997896952360433126909373108,-422425074022064413751985822775
+egcd:39436344864081129175577,1167601129966960865519531141627,0,0,0:1,171787444425430917487358673786,-5802211669555479977323
+egcd:4257657006586752810590,77147349594877154853239911600,0,0,0:10,563538244311585376718458939,-31100907120886287790
+egcd:202401109849117829323361,272785163230303985302397208,0,0,0:1,23898973633160449229831945,-17732558216601391500943
+egcd:428080555595049024501717,58005872228568473578325314236,0,0,0:3,-27025471292559437633908505,199446682235027309708
+egcd:65986801519081050039948301,606919157648734368493531958309,0,0,0:1,177217106981913490775680119487,-19267788661516250973518154
+egcd:32012062136782881389216056,8869128247524938255824580,0,0,0:4,65752954911363551966964,-237327459876009040631431
+egcd:1659494763900889556967676,44291944525456085901327930,0,0,0:2,-1939570066390918372994278,72670242950040945291001
+egcd:223050013194629393090661502,798488954097788537544217128068,0,0,0:2,-161550947050238364712712345521,45127663552810491926056008
+egcd:3248908131273613694428163643,41879881211067694937556432,0,0,0:27,152368979327239401229505,-11820301337418926358261534
+egcd:3446049603173727626406694518,128204824207783873176312600555,0,0,0:3,1056928424865089617706172356,-28409444040782355854331071
+egcd:700031253558626136214208233370,52123353846012574000878521623,0,0,0:1,18394042136597105147975391256,-247037142178779880729238222953
+egcd:435876668588605457895900237986,271303986771473105323219943001,0,0,0:1,75954147113817500975823522812,-122027844129493972049386903631
+egcd:21894869356689284742223217,560101383667765190092124546814,0,0,0:1,-267658820677239482560763028061,10463025233963471610122617
+egcd:93550360054222226284955381499753,862954759319855471087513825,0,0,0:1,46956904727976525514024192,-5090458447435021286477243513311
+egcd:163036556076233835371222,325253846064704092481611715780,0,0,0:2,54681731490561412578180374911,-27409733321748193593258
+egcd:298760510595869651060219530,2623576823283807936237615,0,0,0:5,-2274816856798681184620,259045376379949119206227
+egcd:296230762513979639442717636233354,744175580561578635268252771,0,0,0:1,-32683945300355203946061855,13010357086674471069800614815901
+egcd:98928114229803289645575952596,348257401408420844843182275974,0,0,0:2,64013299296094164502149959938,-18184006885079414479620311729
+egcd:25494984833088459284053502,55538387170360999263101791354861,0,0,0:1,-13961772810342240040396540580435,6409173981787208904855911
+egcd:9359069710378270733841468708,7964135606537379331278169,0,0,0:1,-85301538328543188593444,100242271485686143586274937
+egcd:195970387106442905335558970212,98516089210647543971591302645,0,0,0:1,41045531049286373118094757998,-81648679653930215927296149435
+egcd:56089374569303066947729808,3639958663360642892752262467447,0,0,0:1,-1082612960697886770974458433228,16682355345789150259831175
+egcd:77185220697583421203504780317,38956103306675053558083657208,0,0,0:1,-15968896903521518756033811651,31639787534500855950959809021
+egcd:7188758981017613732187784596,8631409677648057462898487410251534,0,0,0:6,699438759027432535326542480920388,-582534817418185462274574963
+egcd:13002008635939628191889025,2592210142742456161455160840997695,0,0,0:5,75548903633041076033203125863138,-378938220044671750740451
+egcd:5392206357529202370293290582,948791676960011700258391458218182,0,0,0:2,187120500260806390833148058965610,-1063449833754065004912067599
+egcd:56544377896569143411201431214146,76585331663390150529866457483782,0,0,0:2,9058983102991352121685655626679,-6688416081888426016772130405426
+egcd:1031141749989374985000595839,2009599508279438972802543089088229,0,0,0:1,-126919473322514828506873048560747,65123407569678662184010846
+egcd:298829367007901182284218491,86088936999033370088419809276,0,0,0:1,-15810428616337484255943286769,54880691297149907598944205
+egcd:89096238096139543100186984,6280657804119840743206710613975,0,0,0:1,-2167845076635776547503368565936,30752645204900197093113959
+egcd:72302302888163686505438102,216294628465581933787047635,0,0,0:1,-41789803774641178599701942,13969367023054995629391271
+egcd:7344423585894563618479886291,64742746516225911812839171195,0,0,0:1,3780593925465397372719483346,-428870949858745274825015983
+egcd:476166266511928480941810303162,18227725793516746361381041226,0,0,0:2,4455414192209412199765379430,-116389612489299070719517452233
+egcd:2947038272293705986916176,304655516887206203888885395,0,0,0:1,-109032350828407811155001224,1054707671446621662700315
+egcd:5336534152617403337493975,121693724313422319665633935007584,0,0,0:1,-20927747392063258189216772528249,917727182113838425381039
+egcd:7843688392207875316169462536803513,961373577118119555001824067724,0,0,0:1,15264598965786873678488692173,-124541344352904002665189888529827
+egcd:57707445075805800484005722,3193791338236737476237368616160,0,0,0:2,-726032458195877241439267854299,13118414375725016916077568
+egcd:3888164897150599425315896428,205183819721771722595087705,0,0,0:1,89162997566753336326543942,-1689609042924883873671187935
+egcd:602417296292970251426446187098,518146488443536951749769338863282,0,0,0:2,-94681801709378439277053173041833,110080751806786360731992754598
+egcd:15607864856380204759343924600056208,85052708198112429563844521,0,0,0:1,36709574212910552715797330,-6736505931307702456822986279949959
+egcd:82966223347346884138560378408,387550826708631961461927727625,0,0,0:1,40689557976537119419523190072,-8710751525565014944116387463
+egcd:457941790845177233752849712592384,906379077457778070185230350,0,0,0:6,-38742338721240980168476766,19574299999617999644302509928229
+egcd:17520719333212917099310752269335,777312604525614950110016270,0,0,0:5,-37751502797693573191966387,850923400797104861105824821195
+egcd:7306687969771772551064816345560,93860833710620402880693367063925434,0,0,0:2,-22267197686818972849668228015866402,1733411680109554581599314098733
+egcd:9217304562871982912081196416939115,45870849307880337525730087,0,0,0:1,11332401339029049951636388,-2277136703300246618193509803178237
+egcd:2134005353764205569149428712160814,18399584757091279388913554789316258,0,0,0:2,3505886019286566312711773541099241,-406616759759275454593644975464334
+egcd:328060478808294918960133208057727,5348905699347524558908735435,0,0,0:1,-1625801360474358080252404807,99714072885871998294880707908974
+egcd:152187719989614115335894105182,345706102040316044204222170,0,0,0:2,76351546968434028595864981,-33611694390777105417832332162
+egcd:90466176767209784417980607,47937980732897762962198916204,0,0,0:1,18691494153161079961152768391,-35273659596235640430430634
+egcd:22191701690446556393936729275,39127301370409752749065478506260,0,0,0:5,-1218868518522681739916085065245,691301613338140203683659113
+egcd:2775905315510344742322701111035,7936207786535867419090958193322,0,0,0:1,1862857017468570252301586587547,-651585094029390131031434362252
+egcd:514225903257242358267890795752,12195287538749560345215842,0,0,0:2,2593213573051136744157827,-109345317829044919259315081931
+egcd:5110340321650167437688203484,5898223610382806099689579027273,0,0,0:1,-1018061900744385391688765044676,882069437338979035072954345
+egcd:44404545087402155313016176366973,25830952532663780058171102811682180,0,0,0:1,8891719587254083391047997850029457,-15285257592320164601304464794387
+egcd:63300097463298300923000480926,16725067069928349236075120182800720,0,0,0:2,-857298523517998961630904929133553,3244655454410895040363088764
+egcd:93746022629651569339267076554163,59574007540242509707977428342,0,0,0:1,11788481187505597040178059987,-18550426096928359281490940224140
+egcd:836458939105765496287004470978244,993138957276858432408154782964382,0,0,0:2,-230968215392250987185055187226932,194530107794670768100558065725255
+egcd:80307477121258242272132678185446,332941739408686566344932888055688,0,0,0:6,-19596167789673034226948559353263,4726709241167753753045385329608
+egcd:3788453611470993575354311943,818010566804135634923861221704098,0,0,0:1,-137813490037976101809867354792809,638255830952858499594495856
+egcd:259587623659498181771581731880751744,58285944586801516286178106,0,0,0:2,12918436162055871131672937,-57534731031267918251576351240716171
+egcd:958710310132392913096861246,493657249388271089046091328590299905,0,0,0:1,135918487767490572772558916150543076,-263961393703363123681764919
+egcd:4551280541337185611914329527123,908864538052498723441933539502998,0,0,0:1,7268920160967968521955585604127,-36400248331876396282408916690
+egcd:13070475233480910888148121360,4413285328570554568205135584756141,0,0,0:1,-1717230732757565870913316011799224,5085785325815291001604078501
+egcd:14182858242524025309933936657556,3681095590818104384942178227869,0,0,0:1,1066740967448959129497195096699,-4110036142652596636215627796247
+egcd:30711728727831843417803691928823465,812520406510931643757197797324,0,0,0:1,194250898522863680149137450729,-7342315162507265729295009482678716
+egcd:569581482051982147368669338544,92228924551131117274576467984481,0,0,0:1,-15253790413013464064435116976927,94203381343103503173116637169
+egcd:48368135803685842814525775885,40003260510798989461787462217258154,0,0,0:1,-10067998535127146280640641119302781,12173265733848893973291833209
+egcd:4930018459600661874298066807914,2880020912442370329450214542118524,0,0,0:6,99607976318992660230378108507283,-170508887575977201168637981194
+egcd:711972151064706829096321326250,7007757329792910915127427981,0,0,0:1,-2295746860897920906029564326,233242641537338029349184727921
+egcd:4867220801462747830964320558865,559593908596537627162047055199,0,0,0:1,-136024405963053072514365585053,1183109408518107154940668015954
+egcd:1945367852716329243161308578831818,27652505202701349899029917766402433,0,0,0:1,-4394234229043878775227521709624144,309136620491535022574591706581921
+egcd:2412119651934489718572203112,71072673842732776958058175719000,0,0,0:216,39866022094797375420918506243,-1353004046985744635384612
+egcd:6670138054949154699848469764210,11854940081839078859576304802,0,0,0:2,-798743094019718928779709705,449409838495131194424053526626
+egcd:5079267998502677211817352966622046,725385967799535801573193170671426,0,0,0:2,-8733269027224634938993697761408,61151739710183405161934626994145
+egcd:4480886776816194313314948946313097,7994809135117481733885678298185027,0,0,0:3,1325601507700856805107662436885592,-742965862823827740623264222516423
+egcd:1874083707489243811559858061454,9579456370990495994658664409458725694,0,0,0:14,297611345884849035866817528293453049,-58223405680490774590261172728
+egcd:8686331588156731815552370068,3661502563583219068024887206,0,0,0:2,434080449473510327885732734,-1029786721321607796844318985
+egcd:9453863620833568356276223534918,23089387412280380517663003882151,0,0,0:1,-733315877883858422418297112256,300253453100215815170432043159
+egcd:55969320483418908248140871212,85079326328092084335875608943,0,0,0:1,6383961327473919368001838883,-4199680379617232871527304365
+egcd:920794688460040921882938496,500020334426725550170801887474283487,0,0,0:1,-164831869162100766351156834325468988,303540274591861720062941727
+egcd:2844850591475245305055592454156239745,217485336689197516110267978741866,0,0,0:1,-16965642610700236477617589115003,221921712748763436022152765469317446
+egcd:2250199404990420542899432858,805700188980281851693883900245317954,0,0,0:2,-125668559037065384081466548929550437,350973377738811240057657762
+egcd:2676253116351366843635779601279052,36480162826421640007834066520660170608,0,0,0:12,587251884638716966437757250151967981,-43081898889148741230200589919875
+egcd:434143745379431441298635777347861647,3321086261271951935256233282,0,0,0:1,217185906813395152991805457,-28391283938371176479724338141821279
+egcd:328831327716598552708493006826883,5998904017653902496457354820710614,0,0,0:1,-1691762719070528355733005679612283,92734369387521661720402695326635
+egcd:82257549943062294615386699467607,981668433037552750731455606581623,0,0,0:1,459255931703398524802713311124392,-38482716228173528870552258975841
+egcd:74258380804562546584265075951,77261232078825514789206570986101,0,0,0:1,-17606092948365433867565372298025,16921810841773443299096443176
+egcd:16604612215694436405195267479037791,12088809689403272378161906752667109,0,0,0:1,3335737012027898468082114279119872,-4581809207139284046012442723179539
+egcd:117187641044570371899825799649735,8178592535769464440682270853557106,0,0,0:1,2457083678190030290584253972331461,-35206527142278737093501147598489
+egcd:68116770003229052128759620238,45736612498624533810503009289382345575,0,0,0:1,3731521474495048658135396258227407127,-5557455529701362669272570263
+egcd:2342779644629940837325383152346,35028149264501773716827009029,0,0,0:1,9345366038727486594063066374,-625043965692319665157982363807
+egcd:41835886127596634688804793376,2957403801973782095124355461083505178,0,0,0:2,-140338661769489730626292727126091297,1985252155681011990306970133
+egcd:25097271744035338424812948162775851793,6632509587157028992269773636929691,0,0,0:1,-1033804362959546806519618544340632,3911893181067603431716224112635814747
+egcd:96520534936943177089214535009509,153964299411236835495293391645461,0,0,0:1,-46118336610084143333960687917,28911679766215052420281648314
+egcd:351485939694896123221486285958,258506570841696812103157651165770,0,0,0:2,-46453451455854421472351814714311,63161779539565138403359187422
+egcd:28007417021035441195271408027331994,676148020718828368622335803516,0,0,0:2,7786979935141692020919165551,-322552440730491285420662042795887
+egcd:4413362764336697663014052800322,65693610499398083043787280412,0,0,0:2,-6078361211144309430831885779,408350413891448394748721866070
+egcd:197461225716508808586959311780588571,454511236742266442066996230684,0,0,0:1,-219776105748141429162113653733,95481158035346356765866516205288166
+egcd:744324786002890919135978033721,2141150730373780972923060548366089391,0,0,0:1,-874346039933062214689297981457141765,303947508147659392320612047426
+egcd:372181197908829408250471651219,78669259391484278000787446068847,0,0,0:1,-39097687514411049901323408115062,184969634735797925888333342957
+egcd:684001754049621391333368494606676207530,811149742697476858677211191126653,0,0,0:1,-10915635617581306251815187309810,9204606148505852521943359730207435417
+egcd:364115078887792552377812666799607025862,8827301542572999906405869168316,0,0,0:6,353056586514687016404428485663,-14563139848644964464623772510953465875
+egcd:938042970041490895536761429291587,259757840576661229754224229243143,0,0,0:1,98100150147783338002545568916477,-354261322783767043672286176280986
+egcd:820267097131794751974736885266425315,82778860358839053567709120364638296644,0,0,0:1,-6400683257976970254293978091743005009,63425249549479075033990058036517669
+egcd:5457600674875173931733854800284,215111250666665397843928050541,0,0,0:1,15698966476127453640130012992,-398299437009563514118180872347
+egcd:6974124210886759868095546470042140,692694405426414064223497416146001,0,0,0:1,29811566834519349840902140899878,-300146166038548580439590878684919
+egcd:578127999598677928196850592197,7973510834560431357694126562765421,0,0,0:3,1163976746730659318155746392537117,-84395388948370397153290973126
+egcd:14723115671662580034450839772216631448,337895382484927435971195174146558,0,0,0:2,-83832862484269350178843664235104,3652849359365062786475539074792751743
+egcd:5703374596739162783083891159661674696,33366082296877919793073058464756227504,0,0,0:8,-1420826709123263094052675997824009987,242866599892681179183222633947553490
+egcd:3887856931052935625932193493988,2024878462802165949196024488137162136,0,0,0:4,-38889854468224057532149506069268181,74670254545888366761385533837
+egcd:116797886673620424155638344455575785,81954763999357052682292188450710,0,0,0:5,3939912856352315655141769553963,-5614969439772751205749020485962445
+egcd:39829595917373567921976064035194822733,3324835861238165638267965325306,0,0,0:1,-506495325242796237927113416249,6067518813078093176620314277655697103
+egcd:172216102857743621234283534482806021,145818479011898244797230396928023167980,0,0,0:1,-39678809736017016135656043364181182859,46861893122703407143312718238723498
+egcd:7727386332979968071664568403819269717,8575912217193880571454308157117336041576,0,0,0:1,-2268426632858813001110639846963498854811,2043981854778897974533067749584386763
+egcd:1257841454013765362088088015288120393334,5205555031313951556768022638995305531,0,0,0:1,-2069900289624638164056699910111515249,500159228805191194406298831997643647957
+egcd:329035719059507603931777828933787916,63174092441176600783246575745147736,0,0,0:4,-245032949249890737539102034446971,1276228744002642318798325126059915
+egcd:87426773521557211600093712732512,508336012580310863309243338497305585,0,0,0:1,-205653577638095609940604488277326932,35369575066695095584232158908561
+egcd:362736691322477088361764242120205,3310232079384692960069748150503077194,0,0,0:3,-298020242142018021148617862617948095,32657189583460645957996941439487
+egcd:119651446745096900798041375200448579,34904565501135027467488578221618555201,0,0,0:1,3540823847551645875601198046573235235,-12137801744454264167914107388308264
+egcd:33213056682266640333567121628934,394975398517140989884982468602916178,0,0,0:126,618949137634363451274564985445508,-52046767643929692458960957957
+egcd:73953631593374110277606522091274192654,472933146030124955694766250141468288,0,0,0:2,-25101980308935881143484630826554441,3925253748048624389535318040775271182
+egcd:8710580473357199589908718434142,809420061697430276091837694297806840287,0,0,0:1,139259190736440579781799630396860501656,-1498638895878772876966684998673
+egcd:77046997340564369387791662570845,4689854151349789784672220940122,0,0,0:1,-1962814468060010425072973823553,32245983823849957256883772384363
+egcd:9502904350676529706040238562436114,120812359166607505889223477518,0,0,0:2,-23295919059968979396801881056,1832419233554513311030927129706327
+egcd:31192932152325411540357484553215718,868422046212786848257208790061091,0,0,0:1,-230532004021048809280348128406617,8280500468324364563224586249922077
+egcd:4323608585320872985487445640831972992,4084657409651854768355784706431953538,0,0,0:6,54695934287773592257749571957761641,-57895629266230261159874845651528957
+egcd:3107887987298186821475596783022,17295539125083136515530515139788847,0,0,0:1,-4548338553569994765732871853161292,817304777293980388775383524775
+egcd:6492834786527134721523710453730006412699,17967549886740060364182315507603,0,0,0:7,470846050128324576077742494869,-170147050245744662628832662693122120208
+egcd:799805327081992551235962453510248660453,527300566054543088930412034236453,0,0,0:1,-237075289836488158904993771580490,359593924105739027278040604269201695607
+egcd:833510079586844189468222881538313142775,163464471091603074311918213259985533,0,0,0:1,-61563360576469717421897023746373636,313913361301437981499182950778660790497
+egcd:49929157404053899498216569279542495014,52392311954248457857910547305304892,0,0,0:2,-12646518967361681435848485552856301,12051959773910155320611318460802797748
+egcd:8019914013817036621081087587164121,46265590541944209649621467308503531211227,0,0,0:1,13683404292013421097959669212670785871407,-2371951261245719997345654872544098
+egcd:6793690558655838315726513011194313858016,36465391197483395356496390604936557,0,0,0:1,17578619745456361142487500175464301,-3274987572521910182985712771749335932795
+egcd:321787145894134330720247393571488832,18281500192882799634120662107983334952501,0,0,0:1,-6095953088727896985909292224676751826817,107299692324481991773965193337745245
+egcd:6047548862579556374720382350020069977,568658196833000836860083279186765,0,0,0:1,-60242414519379328797326699138997,640664194123467451661791719429686438
+egcd:2870680665840606619961146285976303711365,201189029370140692788327587076886544,0,0,0:1,-17987198256416229496582948278184755,256651679413089218267919705828623910104
+egcd:39798370242867453845816667887487587,35013670694520682198689629893928314,0,0,0:1,2054010924317556869064391839728301,-2334696295115298268400128614101999
+egcd:73858651956033138177599059035112771,52098398670389170171335995363841,0,0,0:1,17240380939183249647785945691706,-24441275123112177186980477847169325
+egcd:7644571930682061497288549926132,785802125855010277645849882091997,0,0,0:1,271947942761049618119207873759383,-2645609551610500508344199027815
+egcd:41557893857172527363631252083795195,1371686406573225335634810457756964207,0,0,0:1,-655209336639216756304666696201636448,19850834662935335118652391694675823
+egcd:973653542609832491247256728338117715,2002969097578635540682944029408420962675,0,0,0:5,175219282530720533493371867912236604557,-85174991154795587826633985259908870
+egcd:831391603082990206528467891742567543,91348680460502373319036115086068410,0,0,0:1,7961031378909225546181572782336037,-72455722479397588386999277916029549
+egcd:176911664463691309750764037723638110826689,460013441967893539463255590714202,0,0,0:11,361642599535882299511849044819,-139080271113761217419393593167310893140
+egcd:6348236474737074437089035380543803,95699625549966825347938548412205080931792,0,0,0:1,-24203197508040948460999995184599094127421,1605519565440601434387009540507317
+egcd:36378047425993403908760151690761395656927,8324175954260445983822589970605585871744,0,0,0:1,-37338373251079967191012744395502594657,163174964152701799172289301950393962035
+egcd:5858122486508222854576912675764622,153452046194711393162502085210831888,0,0,0:2,-1917578181935824357411526205393145,73204679545178717228315912714034
+egcd:112814326530446724164485340282110380257,1110948014051557856317025720135946251,0,0,0:1,-463407619011972388363881014261728099,47058024125949149529869264751419106444
+egcd:6762936490294534151595858255833949,728054939347597344951631101746688290337,0,0,0:3,-3202433078336335166791354061436519790,29747551115599101396300822706649
+egcd:605526563136558093297316930606967635244,9300793514406874242288831761716510,0,0,0:2,1345751153121394580612078693754308,-87614897516475468831438470665488535865
+egcd:4991270541520370370359273753865001,20395641239574465006088950312639388,0,0,0:1,-6874587192924230257223537357557787,1682365567137806304784656152958051
+egcd:500946862886657134755071848342560490955748,3247882743399223852727598527588480210044,0,0,0:4,-23547587498989715538211417876627327203,3631932251908272984390735044167733370292
+egcd:35871368552972366494601834117723560353107,1239860437073895516621923584113449874234,0,0,0:11,51469208630308277351083609242535070737,-1489095785865112466538607676302494302572
+egcd:81015511060223907703360673011829949,18579927224926372016967617691018603546752,0,0,0:1,5992620067510956522835707392099844262933,-26130090364822596580080018527487583
+egcd:686805747950297226208831836097754506778,415846263888979485125026003401455197236311,0,0,0:1,110107419398192448360459918988248994607406,-181851840695728638721354366896502478797
+egcd:1552581181786867650628866738064485666,85001787017719566705908468802934139661004,0,0,0:2,-14586161026251782336851603095136839467709,266420270895607062006639549884867549
+egcd:2851667439961142964793942899685249435,5962772303345585675470039928831166,0,0,0:1,-2115221698102148418532942878583229,1011594697552485521822302637286789576
+egcd:976351980138172140382095386377096085376164,333761105209340508973257305004288242553584,0,0,0:4,-11680691421845751055896280275529788227959,34169548281993462971582117489794480071420
+egcd:20256356281064282905418422186773378,36340325278599621781402169518780276,0,0,0:2,-7025630039156045892929526907737769,3916136250324079267011293834961209
+egcd:394033413204458189167729459825446183,8154588797405589591500377773574341,0,0,0:9,165356907535808812271372935734782,-7990120445312753421042830670631317
+egcd:665386750398767451333668812103953203673693,8552358001531037761606275007435960,0,0,0:1,955024064062749227842006843214437,-74302357130697440661858910661622274980954
+egcd:5687975873047240253725753499538688,999307950133750868872575786467795722,0,0,0:2,-124602922769525950861094557747847926,709229240425208460210072090208845
+egcd:874386700310057076622355171620744115078787,6285850330763062054705785971806513126150457,0,0,0:1,-1288975686576661743329027505076878260385105,179301627951558198068988999319064038000148
+egcd:1355399916760756632497111838694490983,18711706480754058334085390313570835572010,0,0,0:1,2437253796054429273026706937620795028837,-176544752649619721719844994195203277
+egcd:36233162261680351064206988631037080,28152769682211333909464292684458349851046,0,0,0:6,-441278995396378059385736368512158452537,567934651664879095404422678700021
+egcd:4627432565929377000942281079613356,26956649857247707823755540417743526,0,0,0:2,4330342191483523965289985331335031,-743355223464507160483903148381059
+egcd:6854846008427410556215762033804468577678,7155117253417530565506970580853273,0,0,0:1,-2452250746495250667905605947764875,2349339730700732618876715217888241493587
+egcd:2209645186813254112014092471353574880075,64182917222911163587618920972678745056,0,0,0:3,-4461195093044247750680745185136778743,153586946360569502568644586700147510013
+egcd:3025313331138953295279745199525101,8653524593948850180321261885145757158940,0,0,0:1,904226340311477989339899624174300049361,-316121826662884025029029485732009
+egcd:8175371412709228305420266641849867,82198171379976862350953285654395132,0,0,0:1,-2003681145318731802560456037905993,199284695518342758166966519484151
+egcd:84689792444868552924138110130100582,948880824334996164969139354006847,0,0,0:1,335813075011390237303675237523472,-29972088057443111534563303078311649
+egcd:8798524220512740895216632300585304,949715540408757144575796561647960443,0,0,0:1,-365201672634729056326900567364188532,3383366519058383956113494719486803
+egcd:217649222873019166379207709389541260,16404476006672084886049791516665079733587,0,0,0:1,4012192602792553158779189839801583942744,-53232459339725558831435308832318597
+egcd:594697321798546733359335415436661243,385951688100825419173743409926063859804,0,0,0:1,116343479007815023999562971626758550519,-179268953881601291313670792169485229
+egcd:56227820964445229423667006497516016715601,81892476688838156595578659146703309694103027,0,0,0:1,25913798344112231705938155558240294564843998,-17792555222598091584460603000915882858511
+egcd:836582345984336327468570096848318493595052,901634981123482446675039618318674827,0,0,0:1,429320451122865276676843207141615999,-398345137110681379270140802352205993417561
+egcd:70540891202696028214987115150030744,9583233767357631859259680519209578191440,0,0,0:8,-65514112814860871412811677812543980163,482240548076342233536804327541737
+egcd:9903948980685538036955142798518546054188477,73908402033109722105152729700594715538850,0,0,0:1,-31422618411370648401934291718142285762887,4210725722988152216237083404707290444549206
+egcd:540759354899060646610120700119399427327,91829281306603966715331478896265100858175,0,0,0:1,-9770047081196394787775469051083116371787,57533330129430781482128884413734461642
+egcd:87721157714374242858698347997325066587969,3284901878940400480442656721233156988,0,0,0:11,-123316683391743383266271066589127117,3293091432036939336610864709449064364218
+egcd:4743734019370435439736155675086368671242,373647739342207812233533011552089267317,0,0,0:1,-108245641206455177441179302126281646589,1374258363087126030891243596578927294967
+egcd:84363520867921952836929767189559325742,422634774589111146040596691819371580962015,0,0,0:1,3529869940822424493948866300794579980218,-704608977581504060641229871924854517
+egcd:8145193020311860837319395234399151215,532483509543719726427588068482044258548,0,0,0:1,230786770856496735053640355467784076499,-3530255419123562891236643633077796683
+egcd:2377647587095841620160668696819055129523472,773096322510799886986749609397216837,0,0,0:1,263630662321274282849039145784297888,-810792639805759699888475288147822340650355
+egcd:75184748541587873957500013097478130,838111431578529041793523211422510010621443,0,0,0:1,170760592066107917165103873007351219014134,-15318478774501769393625664676412633
+egcd:579262716093774075220251800110978515474,6043876047565477568423604334043743356163,0,0,0:1,1258844697728783566949425789115960891115,-120651349069335995640079130709736259543
+egcd:66383499181676556938103877122737166934035,530832541812442581934024695453113464955694,0,0,0:3,58293023611847179837332973337639810769253,-7289859947210577726709498679713475897458
+egcd:7920960396383675142682578572154754762141,798535291859442961798164423259513237,0,0,0:1,151926171612145541807953823850652973,-1507010649099546070150810894614252028216
+egcd:175236050519274673434166760526111360606823,281877686251107928756886484438054967,0,0,0:1,30236916062321703712671871858025268,-18797506894262892734920915273989626884589
+egcd:4355982041361439306851196662378203909,230636237869932319651414274905344806569567,0,0,0:1,-64199936549664682976687684995834852683768,1212531791403025059927999150787108039
+egcd:72466256004741341461529939955428815241048,404507868131062510694999082807036449755,0,0,0:1,21713717675376618978762676626454759457,-3889941204725080048332941044415757290037
+egcd:7876383615744606969586418493837128431527179,897248260026492001519641792023993581200574,0,0,0:1,328885352293723988890704291802089818369491,-2887079658631153099411074216761336194523512
+egcd:823746082909669336405179113773513767930385343,37536559251756687921153410535826723241292939,0,0,0:7,-2029208842362729101726422682288492660756476,44531328087129752982635593229262336345380225
+egcd:658695079684573590715110773468603499162,3354130807798642409123305655417010832860771,0,0,0:3,318657279290364283792244027119488336746923,-62578949361845124027649122556776393513
+egcd:4349656478540188481997316018037862985088490,688164220169053746563537722321624153,0,0,0:1,56153129479244282567341033533205593,-354925199932218939235077939287991582863873
+egcd:7196129991932253742247456920599960563583,1551953095381685219390198409960379051033,0,0,0:1,651009094600825687351894649336633273547,-3018613181428336616312033224198849913300
+egcd:33718565587845077554141406672209629947944,694018815107815973458210855280455125239178134,0,0,0:22,-11818955283142246659701315974948629193544001,574218177114593127458433250572665313149
+egcd:48034338404178048948731566945929396028527,245664579509095487326837561653834012231174,0,0,0:3,24571615785870174014749679914459909098657,-4804442342296368964974395821258650295714
+egcd:485688355671330103332655405066123104761671,70636792660478486808211498921213574664883214,0,0,0:1,19547946123779409908059764963032815931101605,-134408846325241118506649731947663309341911
+egcd:6405149591444338689334448812244664862636234,9522703507242637580231918951297251454383627,0,0,0:1,4648320274874893850302119473915399249290504,-3126547695921952271338054472863305659139405
+egcd:64888595504329753453829805980940122981,73955307031239460966127905414203750404095,0,0,0:1,9965146616771182675098528346228259968446,-8743447818881541791120354159157072395
+egcd:624397623292152787575544548499552047680257187,960228998573111999015226085451185104,0,0,0:1,419057942589135698988432238815099419,-272496231381448951268571570751366533430073263
+egcd:60540572208222349219969550724682829020471030,4146162156445517660494465536041682341,0,0,0:1,-1307551616090572205211276468970533788,19092336489263721226601454355991849598797301
+egcd:415933355431563557683948328005258732307,5191044700097573019754760781524192087,0,0,0:1,1272462334566092003025721823752845041,-101956264885641864639215199859367306478
+egcd:9944542537317183395984185860699341460076,7450240798258772130917228765744091077415,0,0,0:1,-2889467954547926066102243756339464559009,3856846746608830907837548122674598401739
+egcd:4675993042036765219044958471374401510644291,6536407542677511110744163901635941172672,0,0,0:1,-785059225257024547643372954589113914325,561613003920024127328079524546062364650733
+egcd:500068345406386239937220975858990964037635,31309949109544510956180803197239985764729,0,0,0:3,-1337847095354555157020998431688305125259,21367488686743026560783774598424528170692
+egcd:806337865275549066573685960631804017167976,42306413004831134281119351290563344128,0,0,0:184,109822054528620172938148368508740339,-2093150298482413200450472447557203137060
+egcd:75157219623632887126944407240803003838398,4795768824229131006026406965734558941262273,0,0,0:1,375827824436403534958920350232021578113439,-5889811493651217920413308759091284230977
+egcd:277262123821617241116745186212290538176548,4446513976462629109342017933070790727,0,0,0:1,734493945181565476977850175671555945,-45799327799969845689934000551863252036517
+egcd:98171317282291412247388001560687711655155,51444743731067016851540276812580755320,0,0,0:5,5036290558758038355810670649180532431,-9610686000386638919489216467402354664865
+egcd:11014904274052317243271908163944833907947641,71515011684041336572702882283905967103935856,0,0,0:1,22425609806502481498757965832664201241272121,-3454043276916581370784741983560371109627385
+egcd:87146147055128061249851083940353618024451530,227751615279709532340759791204097256262332638,0,0,0:2,-48331440979237806245330122927282663110593182,18493387446627430920818738708903565546903449
+egcd:402410699751971626070151333628642606391822950,9235049484375572036983799138607635445972248515,0,0,0:5,153549074522224851922845419478631135245172365,-6690791492703523748388769353438975615410083
+egcd:949267985651789297050574941117571101295556,5494464173916711420285490445361551565873818839,0,0,0:1,2312316926578234231731272711847855389498723615,-399494538794444801285919505216009539379901
+egcd:2652808479750993333843650846776418156707877,915987161711340965720691406464012679987924553,0,0,0:1,213033065472660034588639329773318587419735771,-616969261334816443264024565709812558076022
+egcd:1163472262648389280712221532386409222890356,857318074714986117766247044705267090767144356,0,0,0:4,-58043325122501989349933223216924978819779359,78770996207404485098817007910493906597668
+egcd:10406098257685455333151512936763024878968848,132372816094796368125357785730208051589,0,0,0:1,-32359440420839902616239305059134083709,2543841904381874254942688300338927982667997
+egcd:9959025918172523065346020240503154713303537545,33255835687967680839900430396715330645,0,0,0:5,-2158235906216683429459031976527278345,646320469261857919214099624368160581238329214
+egcd:20019690353839180990330900629296501436697659484,19010146624748888880368271406285795722061,0,0,0:1,1935509632476532363016337521607327705259,-2038295878718141770102878985700637985667333055
+egcd:5207112395329419329605828389549218469303865220,385309659461901750334677757380851297191,0,0,0:1,165915572078042391660107459840258089603,-2242199256442908119061230570559516064159668349
+egcd:601993736892612416519724463932736313173624,96686409886473200154411387090103804018,0,0,0:2,-10124237854286044843764528144646895899,63036033567153639591480721728193636660221
+egcd:9451492454940277922879179145156727251630812630,890293318906622270914566376145745936579427,0,0,0:1,-43405247621678402209625928105193852993915,460796865133092194091416698827502410647445713
+egcd:421136320827745191070632842619729525606371205,5096571308608922651479373999535629936434586,0,0,0:1,2075009266732940120807179123930369827773227,-171460716501561691306683845372085898878504919
+egcd:6991302085135094450298373606130554478351,38899616762470308043236153517332129921230176375,0,0,0:1,14126040436007201764984293331381102890858042526,-2538827478892831192526315111045693967367
+egcd:27088648614991201551819724048844336626611308269,66943487424321378156955754932465286944711,0,0,0:1,3124674948499217771505415118094328323367,-1264398150927660424730004830166744953548129302
+egcd:26633206192249265107832407597998778309,28885683872079634891270314620229364998599495,0,0,0:1,9892272799081534529886664444698656529168119,-9120882937536253989479027571007889246
+egcd:1293392085583226795107306787473899947221,227416266407034301082063615024346171491,0,0,0:1,-29907285136077480460193096683361056071,170092696126889751795759289938962958812
+egcd:79278263825216401490025404779637155001507461,6902468820227813108248070623732536421506899016,0,0,0:1,-828360674462642860581800632473551541382892027,9514131509009287407522188041794942836491653
+egcd:1369065262257696288586379151913703456926925,3921318368201662164740427949862301432814147,0,0,0:1,-410960600654239702792755872263158438997325,143480286394165720161890484611766660313358
+egcd:306811423659369908685018354614281524950,502749149014618067791749640767411770493,0,0,0:1,141326450781475203732924651029513241656,-86246927816738114071710451592343402043
+egcd:9719811370227578672711620046487180969505460,433430579275086048076182917145558458171286,0,0,0:2,-21526798977219262508638934913326592901682,482744954943713828666591712770941953706527
+egcd:5788020148019388092466048940831790038394,75552141815311856081164996922322733981520384,0,0,0:2,-10518739104218372390717930642371017316511851,805836504487242701754398309597647648769
+egcd:856377298658655395314577199206116518702414869,7440017597742186912190292505781910769381749,0,0,0:1,3131903658221817580778138665646284726818753,-360495275616161421170385112657167062910608644
+egcd:1689647907310953553519794122563381184305246481,7013833160958039894149455543255572091142877259,0,0,0:1,3398821499458899262672354561225223368687478979,-818783609774341856728010232260343119764124822
+egcd:7909384989092513144957228763780800053405820795,21477020481637847440258297023176370214097826,0,0,0:1,8859749519842138091084779610567087626046933,-3262797552354666439266711401038798592605600059
+egcd:30979357654518132817819836417705740257922764,260940405630631925922236059628149432070542923194,0,0,0:2,-31298236747286947106814487094222102681769572678,3715788161694199667767789519431128923820201
+egcd:984850871549275259750343917908080800989821,977566457784993078336038170702548828397820,0,0,0:1,-129037873131119636035172993956125957494919,129999409046825903670134925875065572390725
+egcd:259004643342990580972799103658759292285,825595283492252050104233175225637957516,0,0,0:1,-375346335685149725207452317778364301475,117753148241117547777519554141059751586
+egcd:794001855955218991102614066001175910817213141182,174022684013084507387799105725951096751,0,0,0:3,-10938806147098475396784404050656099019,49909771430013704026181882273607321813941786211
+egcd:9811672997383161859807242291870208222778,13360741920658508650761847028208454943504591143,0,0,0:1,-1533646877846983951433473286385655919684529373,1126257938986564477278948068254744237365
+egcd:814664124635912365609614464622452998365491267078,6619294472928701717769024660487632849749,0,0,0:1,-20513340331737189016390223384951047090,2524662184626944204865785704990399314361764729
+egcd:65349983887385540524173152888970462548991658424,660961177147869398908783897959724877565,0,0,0:1,136074117943219163120699904988199259974,-13453802919940888187441439968788876247928595515
+egcd:9480849241792212657354357845320329169823,109501469778488317937641164193300571933305,0,0,0:1,3804987659970807633940154130872070360587,-329443197831394171414676889854922460020
+egcd:27503221926847760895555182327237470261,628279771111583514714898881996093117588062576805,0,0,0:1,-220013546416993125291275595704774951395099395899,9631189276257473190741590492577938648
+egcd:9168322681946840027266828729455827850468,17545637116438090457732596682574619803340605948,0,0,0:36,-5813964096141413249612569112312284994308162,3038037236318899283433014963271953349
+egcd:2822315921382556721951896564280262300560,9667399667971791940314575307296845555254630,0,0,0:10,5947088441699739947657932361375488982750,-1736202388578886042166718097228730473
+egcd:5505800972045902016093732268279937842194207316,51771316999189365770795878029705923949174,0,0,0:6,-3811017207863891625916436251841504892445,405295894788019795906550250885730982995283199
+egcd:315267941927920486224102737047056204820506827,53799684850237810468689873350190525649040,0,0,0:1,-5914499459775939664589775100476101941437,34659163476663297256696619263386415724342510
+egcd:9236131800332788704514704731129950333068432256,263545285729806754190856317347550775965605470790,0,0,0:82,-536397367813719623726930035810410515130829203,18798426891833334693523979076019903671419395
+egcd:4691968437686244138977558753087888903984652912321,529627716152176622105651175417186500904294321336,0,0,0:3,-62906908078037944919327151653884810577788339093,557291882983286077007886029051098501072983943821
+egcd:26280657162235005084493562155644126686642367,1370831800919999167427179169348201053666488416,0,0,0:1,-668950545558535940883160448398038518399005825,12824665968877633003981478280580109910324086
+egcd:6045536043693122656233686475730851232212520209,9098289067800470455174047447178904376043370047963,0,0,0:1,-4206871815253583433092955625418062663341089554958,2795338222470951124088702397531861215608753021
+egcd:975864626523714146502659630640337751487212439,6940988044327081299708879840237906908066266,0,0,0:1,182253857832309393566019050168841800978819,-25623886940908208028290520855889573665491690
+egcd:7654068749692096886133022573587354873176,8748850507770691102882209873577170582376569780827,0,0,0:1,1964615562778113529408565381234249139996181774218,-1718774663124332015670834305172702577021
+egcd:850756247079996358624434449149782878253590,77804648630198634241116586202790778174949752,0,0,0:2,15630184779111518797262593460062779851865543,-170908519965767105980455355954051171663309
+egcd:82272488067830066441292242534154314172131040679,688350307921755313885460920932900835434083205040,0,0,0:1,122655586374168160071266274502558269222291956119,-14659948793933732247908546146130285866296684120
+egcd:50275540077712584568735998044458763684689,12487524215373463010691321732158466401371527,0,0,0:1,-4310272707559638258553658315624231083512470,17353422865679261179696672421592621956753
+egcd:392457454844037291990581880634611045578102532,2006776942135757695410535631587193797511467,0,0,0:1,199439819133605873020173563252516107678750,-39003659135343525760309650090094101928308197
+egcd:122656263585184646029569124623378862644114041656,280853932414286875647350581672340197593777,0,0,0:1,109974473329532838224195381954535972984910,-48028731064556951924576138949303550622577592767
+egcd:122723560516597269398769177665063637962901,765616664403695605489624269692889608096979049375,0,0,0:1,-258226752172223790724516164492921485841472381649,41392132539192550495968547772584597424794
+egcd:6372235942926383038761681930859971388824310569,450457134311977647755977405844641979355735844426,0,0,0:1,31158770674255982909157224955056954353717569041,-440776764988213077644482491833524983838080428
+egcd:55710124200643562666353596472476352006557402,129521722711569048118860224844308955120907039667,0,0,0:1,55524240351481153050668122616773552997196032054,-23882189499716295999156216742362854145492121
+egcd:52638437489786006097404197485813719704184482762165,38484575113442816269970218082013142493165049225433,0,0,0:1,8178630279958745518165064668394460744601578134160,-11186568059401556693065851931124978194437124969703
+egcd:8865739212422336318534105978323392918519865739,156466530229954316319347454260872006246776,0,0,0:1,-22332727854888622695494970502136839031101,1265421689689503887387017047199762890477050140
+egcd:265397516257014571242786403736445985853962,32533852784248587969347758598232018992116038855339,0,0,0:1,-12908032440841768357183540035974013542745984846425,105298311032592235052498055248608994180209
+egcd:3535080036435391574837524982968689282803781,74249567587110445850983262206024731586008,0,0,0:3,276939285966568545124733076132658099351,-13185296196863522858383215997152316071266
+egcd:47346135611124365598287053304187866567992166810,576740218461234987857552610598030250941997676415,0,0,0:65,-2126430640686396085034515662972949280965477373,174564336349217453788449880226773993486353933
+egcd:820830106986357361740709716178206505926491986956,3217456208051702777250937472105195691807814504596,0,0,0:36,-11508975978649369323663700445407671174097770014,2936143764821793638026885620541736768610769895
+egcd:61739911443386844943500901189571167227813737,3848550281723202830510194085486377628651546,0,0,0:1,282984239815910264880297243679049891924891,-4539741104353078811173218272678740948066221
+egcd:4935130472338939834485774824152368863725458605,1035806531451219174441688602906921731365011,0,0,0:1,-351908970967360751930093135356643002982497,1676680570528195395018821587922991870638322426
+egcd:3266540541396232463580738683146696014840917,4935087952292184155374454402916005109216111873405,0,0,0:1,924328175593731869854608058802170988017990845743,-611813910576679910370160267913438850314786
+egcd:14026215249956339676506155791652279539578905172124,30781337324124641929530137787213325258646,0,0,0:2,444505386198527884956851751358641210372,-202548971831029013803042093087467123341818781381
+egcd:4294047460058049577385615940946646673529873,7888285331485320409101196690477192599721030309,0,0,0:7,-535244381384157584881763833984960586681612928,291364305398447665235093604580474039882939
+egcd:3323417013847245232113101349532994925521490334138,5122451664153873677965641025886074343796981341587,0,0,0:1,1425515532127150707596577092883695524648753420721,-924866232731438695305713017060351754850266688931
+egcd:80935426461988829507228088844586242462996089069583,653780401944410326556349775523493660318880484692,0,0,0:1,-2131004721544266945571387397182966694100115521,263809951197286132655279411613822876325373015332
+egcd:226598141134799568921266709711899059121200358247,76992399049617831317308817003284176072753,0,0,0:3,-11448437027496398690279470751607992954914,33694164376637528064598542583627016152058686337
+egcd:664319721933063857023655129340934847648590823,658199665265274466519942300240556524715643,0,0,0:1,124352795083709078633408434668474547721672,-125509049322160532052275511129607044720504885
+egcd:8884738003622398686160547451276690420223171,4299975907886085056063300778367761002052776699,0,0,0:1,-1116654257404751368771631661850560365381800860,2307264210358821074298460923747673330704239
+egcd:59719426635130468128765525893511605775762068605,15511948776571237043257049623825428922813014745,0,0,0:5,97984350967559952500670074951721914832581821,-377229795126457555963914383461705837385561060
+egcd:363283435899720839207247713911327116143466,2646681445153091542108809095748079207088831696,0,0,0:2,-645295047870741251832001677370106736568796843,88573183821900377839952804802844006175665
+egcd:52931164096003232205392055066962781951605227742808,947807568550870804286088054962593413637490,0,0,0:2,194186113496156753567887057914625616943499,-10844497743719497124422772319106386069172727940731
+egcd:795766141035085366569782895765897502125872618,5246887073403305711124413150544060139255883684657,0,0,0:1,127592149200051856506732829832319739908307643715,-19351190672651565653969035751475639783463117
+egcd:82250667724186953595968128381514526686421673,289549134724791932338507372783255493005385,0,0,0:1,86151709811972420581533505911642683307877,-24472653542377849432010330789204946130679372
+egcd:61639425939671741256997475006356513882668519581250,3578514828596765772820255901738596048541569387462,0,0,0:2,20996407912033026016667547576264242700583756497,-361660239647628207370955868455456400780266234704
+egcd:27684537637183448026151946909258691476828389542,9528939357362238270010422927669825442411130925,0,0,0:1,-1491403989803236735430244778811958637923713822,4332993247150086860055318193545031767864356713
+egcd:5435307729184909003359952075698243178049039204593,81652326357120772943208044441275143659212363293,0,0,0:1,-18786061737353190995893206957396074979160669634,1250521952251468167669960168322598898079025280191
+egcd:10924773406337855054647765543952064725613723120618,14527409504138198936169926863040904530587755,0,0,0:3,1943780369495648845597031433407372402007186,-1461744441249394454828419839546381797839691182739
+egcd:52213006390422220435171878651888270946818062,871645758909254953745968603137179283818003972840,0,0,0:2,-29741256420958113534899191845042319813299285189,1781549896496816094656316432366924841439533
+egcd:4688712561272866795875010705784298446804017837,70990811276700678878005205180077865101611393303,0,0,0:1,-25861123710957590275105742577281286038202175280,1708043244069738879850646003632659154370684087
+egcd:601876680344350654318757321802040059504236,57573030176060116021084277750039823155966100,0,0,0:4,833675530078099686733366641090550664373764,-8715363061372584744643797829391972554063
+egcd:857505478933565140863302872774416730451047627,974314057900536449023558662039365613006496,0,0,0:1,29431249747985173674309139068596168851555,-25902795619249680104451374326446194507504004
+egcd:45485812933729425157241764872535935492149300,423866118406290068921435664923874810909565066,0,0,0:2,-92026904416450995131867199112617558634435512,9875567726185991444222573035098359638524797
+egcd:8708905393403458838119906185182390415193154723813,2649214839375624500171797402777266233996857,0,0,0:1,-878693520989369471627635491452708391853508,2888576128426243950131007882950541927952108467965
+egcd:669875536982562277168757149616294771674281736129,97516567980777338564845413606958767175755421280,0,0,0:1,46381889226420155390297645103754990574679184769,-318613478664861551321523526265950713581534609390
+egcd:552142172787258525043120366564284640581592165713,863962961122054854184533799151634607728550493,0,0,0:1,-120985334199661742489066675182491559538012882,77319408708953488066818827922573705864500213519
+egcd:8912171393647579492805585431506224333605369238663,52587987699344024446727521307243310639764632765,0,0,0:1,-24208869892720635889960417808933792198197524458,4102716364884452109263231978180096274383271959027
+egcd:275693664465005824088249757937188874572769224053886,3466602115356222955936873595606282941132234317,0,0,0:3,-221006434365087927325688159903180401056179309,17576310096434242315782225656574466646053079410381
+egcd:5028642354464479207857147979297496218105888083856,6176113771729541577635381980538182053262643750137555,0,0,0:1,-710631712528650391026653778416986011431221346318294,578602153413129397137286808053013793718378471803
+egcd:8465402742576453065707574311196744344728516738,61661356518501223354721904644532208588697512,0,0,0:2,14937393734471008272165421983397469074399301,-2050734220366918264382181168692457172485461053
+egcd:33090073711191135330109687427439016660084475,445642221929395862212411325653215048318205553,0,0,0:1,-165351447151677755593906743574229677911339226,12277767467392269710361072198887310106213167
+egcd:38084383375564641238722495396072746414069859975328,95831351502059780199491060292730447215506096476577,0,0,0:1,44701417714871641774374755091058724540366425072078,-17764811859591030607619685717710642838720797546079
+egcd:39669808567342798362844877241009314051976791967,99119958834519191165493856402857838929818011836481,0,0,0:1,21195389536433434447160930459850047078305039520162,-8482822786723704528943403211431983212657912413
+egcd:656394443821895273811037542396860681243032484395,734418747296348194673752402369075033727947320580668,0,0,0:1,-198348208669444102178880145335745201028303476849097,177275787950594932355555641521970313763246167487
+egcd:4151672272018474022265799254859348963458925,8657522863384451966497522640761563355339408510876,0,0,0:1,-2593012562485881796973545247397827317361955393143,1243466350195667180206121886940940782727901
+egcd:616193338763982804182193956310277879275176598293949,1991282968221128113819350795131871998526550,0,0,0:1,672187344044686564879107554044311287720999,-208005276202308979536534651654988391029147577601071
+egcd:8687537844058264818625968633794987777114571540965,4588008014762873083430262838940515379172783903,0,0,0:1,-273131667435174631012578706118035112399381704,517183424618854791062408052693760196421481021687
+egcd:94299417704457808128488838366264331063646462702181,378910566091211661215935743383333262065042992,0,0,0:1,128249482146971828065759668548405619393919421,-31917430047190763670990418627993655771034878683475
+egcd:436084754250362560867427019991801320098048671740882,654347024914243888183493882710929942025818488523755,0,0,0:1,-124697661855776361333795036367240691582603011762292,83103838109598963945718792347908533185519371904059
+egcd:576845066105037981878716311963244757143336175108810,47169550600388313323767894641195570046736010,0,0,0:10,1719524489809815702007774620101569793957264,-21028379651032953624905166044366014052373893560783
+egcd:455450311793013669133010532968680473621765301849,196887903745437577462662843393301335218213938749,0,0,0:1,-62895287849643879856045665234849365671155433961,145492322872554565259262962480158041518555693610
+egcd:3900215337216547857536549769208785869150917,703107675983691037178395903530670398382868009,0,0,0:1,-291772656941803838282558784634427859227791877,1618494905481932988460302827539233588975690
+egcd:4235417950821263716456215603171042810879865369448,30099855971642941146023855759175128865528083067679923,0,0,0:1,5433558916670879875362806366021878036014090738651158,-764568209037069458320253834476596864323900548821
+egcd:220042544397196218820917335251808518190371752175199,933535692277684232594974193302788809761883748,0,0,0:1,-449365625423429659602361441217910654207591337,105919416258801934451915453319879733490159050690718
+egcd:5686178248384112550645420272297349915998890583392866,6394565636060087046686488902334128218389439375166652,0,0,0:2,-386878534783330326592254369705226038342074430538853,344020287608948398285006281037355413110304951350725
+egcd:794165469687755539056069459111608933432404895,782304420953549695337102011535232984737054552,0,0,0:1,15995811988912600943335882434276695389371735,-16238335360201271890738766944404884526025987
+egcd:9449310146893908465306850102371521287231298790519,13201049101057800842831327281338645274946911094123582,0,0,0:1,2999793730046215341383581586839770857893954084651465,-2147252170256912651603598387202626192386287752937
+egcd:107247303626237439573377913856037555329228637,248037365489312307060126693885968609330300538729254,0,0,0:1,3295187394963377883360979486845920526196477093867,-1424785182489835167324341201022464061856757
+egcd:77133522083392356030810996444450842713578606,362446320582641682962892932453319089993578656338136,0,0,0:6,-12252467688569006394870089744676118644607994086307,2607492291584185635921553686052009701918118
+egcd:3746529922356093187817513741403069494944937614875518,21163192571109744382435762015727356715830696078192,0,0,0:2,3360441477707708557262863370472736448288910259287,-594900533379131316626599736433550281233005427135467
+egcd:1480332370019794273587942168003226621597722167298822,76107169267609678850598825056993761581288230,0,0,0:2,14857689610118706993669180053071538933427241,-288991419405294102329201336816763365353292004875870
+egcd:87998368974239358270522399707979936427930543218697,29464787743750967717125516987996695441482348481,0,0,0:1,-10786185369002819879240292144429281969862945959,32213594347963902773511656741076864997101194881504
+egcd:6380501221201357438439263574761686303469688367209765,2101187057561466700690279154331921103508225955903802,0,0,0:1,145825347333296093990690878414508843106434447353569,-442815789957334350484616630550368772984065306700842
+egcd:175895697545417190557526178538864907787776215968336227,5776330255785661509841982629017072861313591718920,0,0,0:1,-1178091011635241644387254463790507228219378563237,35874185008035358988026900184682989666782145774075290
+egcd:93915008302504565970294462868559347357873734156532,843248938319701518093307338244595352966717434,0,0,0:2,151276724006692666989516063064725067523333305,-16848114649719091351395265497230824419920506759837
+egcd:5976711283802179473855536437769569634799149864037,172795022672485802101638449934309020644291613,0,0,0:1,-82366904453391796214074238888113409850549992,2848943214015556962691631373397667435722686056285
+egcd:2205248615867285476540661866508420170225141139,983067017505522956565352285112444457364117116888337095,0,0,0:1,218267429603838059510873324752454714497132891681911749,-489624754418200054062883904405297170239063538
+egcd:197117471835494353404914690778881470433860149135581,14191428012947823659636428685835151126952873593,0,0,0:1,4459525876016258192519437797582725274696114004,-61942354600486601745601801863681456852754652027611
+egcd:83820729536850105215720647153262328929793073678,98655882859633233870604900342857378466000427081,0,0,0:1,-47880418250666765255679449182794532875903726259,40680509585126232668822359561687380513654344563
+egcd:85021523085826077943750195658443246760234911045931,47005020817553666242267156046836837169033298,0,0,0:1,-22669310085724864052132047557226288756475911,41003689335106972184099227663484803158330242761279
+egcd:5946017255219161818471671405255932514415767039839,6345872556760394171049368149822641242688180053,0,0,0:13,187171763444601755684128559806849993896322673,-175378015422918739007590870520259264416567583578
+egcd:71419612666385070427345623221576087904278400094,54972479988506664671028428434907112336472819338750,0,0,0:2,2179890297903206135328344242764978585525743095133,-2832088360648962656287313107815515563957911534
+egcd:5562790597381394993959486043063470014111501298412109,626590695183962064663009600613096722773908377293252,0,0,0:1,-303862519026371604863957069193342886543269595527523,2697651875025465536959295692693138029979462283932754
+egcd:90975070092326503556334167670828683463142797887371,295231087609240283637008177080140457131796372960954,0,0,0:1,-47867129509253228973744519011198722760573329294115,14750192798078785017913570665381167139156130951029
+egcd:42687927598884676578701708409630846818779523811494,523099282468377097295263711037946167371766507649747737,0,0,0:1,26078560817221509087425598130571631203765655378478163,-2128161428162465937231181781214658658975752224633
+egcd:149816245892721291534122835342563111201446590523,42288103374933513898890089821708822543153841946467,0,0,0:1,-5793317563557773262285017616969069220347034903402,20524285067631197541636488904710796574034942341
+egcd:12209271420687937418818672144031853294587657600243,62252474450489282538022150950275214557489689,0,0,0:1,-29660844749864463057583581069915997873519776,5817235496494160175697352420052606379606904518921
+egcd:379128079964034811949790348241734661654811843827149599,87839782929720118794817037174959224009493462534,0,0,0:1,-18238653567217319969185225852935419777019511901,78720432558454288371409573793995440050250015166426550
+egcd:114215100939505653408300174032176291289669380562,23741400935738901134986324457933329645223539201365657,0,0,0:1,-1827217335953581276681577241157959216199445411446483,8790374798405201192178937348284544880847527471
+egcd:1926579880365706875550579926206866629082953879469101769,3149513448830666223576844897044248210956111085,0,0,0:1,-25053848460898792135835176590575779166100741,15325618116798233452500443229076217786312231314349798
+egcd:34061999712899400597535018329561333406378163617467742,171772975832275747480880934476689264812053050103356,0,0,0:2,-30353734173948016840673304098829017018627498398083,6019042749355297425828459633966808378067330339305673
+egcd:69099794678760243778781800244520189661090743680330,84272230826240573484054504866235051739757277304495597,0,0,0:1,28460232196411257321137881889341868158873397195672407,-23336230475929248726663652223642021667308541046297
+egcd:3730778374119404797425236403038460041746582520101,7496868998594071853311205794112072400183459199,0,0,0:1,-3417158685287301201140604914926004319611879342,1700531478727317431970501601480361491459818880857
+egcd:694479210821228795777963254574810624923840260622974,85973514938807029266086479669558486228659003996037,0,0,0:1,-4363087914001491864265409481816897855579273618450,35244270906174989824540564289343982280916293290873
+egcd:976689567441345731919313645335687701163688099904322773,265009793970603358383229061050229738244347533205920,0,0,0:1,-96111738809058080341677874192436389369700333445283,354218352450277244615910581013823408191179307271342353
+egcd:11306238535217366491646986230523588259738750710860,9711793888012260176296349031139366341426284472,0,0,0:12,-88605262509097782289291274601914001329437685,103152130796347815361130641167067199415554197871
+egcd:51967669483767224464737921823977975662824880006456,1280946574522273740836915199783500350492882920,0,0,0:8,10268330208562887554239646266539240997802113,-416583486807630194700790333441124375693097218206
+egcd:2608000098327642864267195515218438837191124764,76463054831351286123635518055043629109951547944085,0,0,0:1,-2838713528640047131970640855543361319685828626166,96822775105523699697177482202209085573424645
+egcd:4468842728483750749309421622173029139461617867432562,104288232549062003896035112908374600291926031581641,0,0,0:1,-40897526108506312057324550666951171967489049680830,1752495058126446443607941125177833715948426475092021
+egcd:9515999226131724451239821556730726791154394377871161,7017412308925966316941922876372144830810785912251994145,0,0,0:1,711542578372858898917028457620268762515142703628762671,-964891091911944776459586890186052584752080420639414
+egcd:213839504515148236538273214896810704701481567163944,7404902411186480168131101360415567235929305381970861083,0,0,0:1,3380833338481241432824569741692207456495975720502139882,-97632039668337051697511687169125113631113481270429
+egcd:4704143575442564619226639933367529686541295734236339,6208190661916178838888950379033665108451167558784,0,0,0:1,1036231609662380598181323571412442265592690061947,-785185657902980530502486174709506058502162341225648
+egcd:7800918125130733756931790281898023131423182325003,49727855698492641147972884260023067177838769605345,0,0,0:1,19886322404414182208422530205281052324435144823897,-3119611145659963799957590789424626986012404758802
+egcd:16259480181384339216392327597672842436080220095778,4211887904631546369945283484243515208523965162735,0,0,0:1,60867090942630605523831629233862298664493090172,-234969990011354799892126958820227867474219476729
+egcd:250262833515008658954045947163909193707871367256381,9360574256964093238653836590939739950376635341916,0,0,0:1,-4577416570401947847275576528151972968266287934083,122381085779547263818532525602930002569551981217314
+egcd:49350305588299753800512832973348076363359882929159394640,82697581133815540138675428448684737574082443779556532,0,0,0:4,-7094756990744589041872300640946840405432374076597223,4233841193026162290519658157361356032844712511769908257
+egcd:6929763065061301565614851166591733819231208368855577,7015852829866459363250622386383961076838110347968449,0,0,0:21,-140151926963831515623623343137474264566890746373088,138432157931912474126854600439744488201286606016053
+egcd:798771392168930640410188390828161875038624287357,26910611328285765453242714553447940950358339441064142,0,0,0:9,-589064228600178541791155571644660170053125967736035,17484837048696468032579268233817988200645136912
+egcd:25397454048672817537966781867771032309891340572691,23256250389273255570062468054746082424429806429,0,0,0:1,6728497363996047750398121428930431990223003005,-7347990314789774434378123575091130429836158761726
+egcd:123423695423831974268547456942149055439119884772839,46840700163848752557976957753546114906692522490120,0,0,0:67,338082829316269748785166702372267870226049440293,-890837071341720045931329882131992024423327017348
+egcd:255083834192307897983466926757917955799611163337033,19691274316552711716703825178816583758491484527599,0,0,0:1,8267652047084102914471657271320768345286498962274,-107100452212241711960185536892796650356109725315359
+egcd:12995280360832692505430343465201277534610726091988596,59465235355121959404752559527335404508679919016,0,0,0:4,-7141155689480540101632551150483184164353752087,1560597880945943136073564871687625551494286751865366
+egcd:22991573949171758827108078165749233594263284484912054137,283817289083807864939015806533699958979417645701638,0,0,0:3,-14276343780208855857892287243849657918266920759821,1156503237720469287676414796512164794747302414005802460
+egcd:73499010438519566918821582344590421556887663107370504520,3896393550660794088432191407076243899495579652351675,0,0,0:5,-256046171286391936281227275615268399494905890920906,4829886912457785280143525162619404419581682774707946415
+egcd:9583870140187439825440257165562832875040106160360,144350435363505176257999415244713117818105415897,0,0,0:1,-47530478459628272998131044625702170795099568341,3155694903939446205334553339280276087238902971313
+egcd:2461253900541942202429868097665121039076482321402912,4470103014382515051213146843793545738275750665419,0,0,0:7,-245912852093874846806381542597934573753889813353,135400451502357810057163583858882200066572301755797
+egcd:7046608505460840717651450079359511868310129053953828335,58898419892762238699911322923913407676555176583579748895,0,0,0:5,29358649717475420636966955061254137346962695123318402,-3512469624561697691831838742681262193506315801921927
+egcd:506826573770755010074059089662551590730419138892682,2122797248606187597520041255704732461621253654865,0,0,0:1,383346693931445995397683618340486631342217567423,-91525599809021126197144665711931909038630799314789
+egcd:651539360489382353856038642218105742846167090450124082,62040904220472849789353991154770087142114255535343,0,0,0:3,-2355997477848366312104173979342645132007028304972,24742145675004203493726030544699958619654829318107349
+egcd:21241404865403392359971818730574585605571301440311980,633711839015175748736538000969606849077009552352665518,0,0,0:2,-29634494220450461639960895856430281807980194035925990,993319441051141196492952842918573155102238513897539
+egcd:705059512890402826453839323123808449258609192987,54700053492589412596920621965162616297504870254670606577,0,0,0:1,17209927692044096764621482310232491609809545108074829881,-221828361412398689301748597143984873381349400098
+egcd:415394044144508415296949741318653110880449387898,712027399337932687761182029057846295919208016685209861,0,0,0:1,311602633323208816932778876458826680113268935109136666,-181787776906565417455080707523448468254230808647
+egcd:83651009241467439062630103095611805553814512321696,446490369450787055845922775483794833260870810890813375784,0,0,0:72,-1344835414515943831032725871506341368981976803617565435,251958042961384654578843735842923162844346873473
+egcd:6070283815502486157201490923461524628539767903594155636,3804770539341434134928308971505690245714256366681925,0,0,0:1,891543412196165172397968883307773535161244063478816,-1422404187036464521764325842283917202125611790642909427
+egcd:96178348424332762060134475763000420774833630208152855,2806142261547257037797431000328431629728168038259049468,0,0,0:1,-225250250276381610381864841594193349660878357372833721,7720277532117966753867311498921456722048818963874392
+egcd:865765710958745231463327672884696335768725685962,880656889492281564646438436388571726030066590436314543548,0,0,0:2,62379218473169386716154064883279697033462165217514103793,-61324437558888497176774502622595381331609802518
+egcd:3070091985634497235831095568321669340142231224753241,3872660861602828375769437905423007683683302354983,0,0,0:9,-130408390759835341307955887188778334976643191426,103382601688896077821738216002703636813104276203725
+egcd:9504468312001233029402718544926917268255994088587,210179277000215612334709921044939204096404089694219,0,0,0:1,-54268679178541938321110274347377533333619467634554,2454071347795548035690892610366452456534032251421
+egcd:9812086714469743421916608502147765364717936946446424,233160386400300595605996182320148818062281081024933671783,0,0,0:1,14451818554970487550218007381375932641589632889155020753,-608175767043463911892366241689545509336116825541137
+egcd:4360347517898600722460235991841444558919923303109907,283395924916312034671252929842416261359155988664543,0,0,0:1,-105355408855707603292421311080809208231429401696971,1621004944361269525623546575360221751817290611287086
+egcd:907128595118057734919250855358256235977656150196435477,4751580206547799719609283650403815057095853254068516282,0,0,0:1,-889356095279141478429404461825805439836321286132426239,169787799048096169202610086149258055777141370865005422
+egcd:3973997826695458235929341947630757918334953729985,919677988629130382841929983511305489218360268786013503512,0,0,0:1,384594482287927020029873640499023823049367287552218834897,-1661861712108041873322099084387127370672735847462
+egcd:324009569902112154788016906941706831494599024684,58395597253468362692345409336860870479092825229925,0,0,0:1,-24289711240864138406494464493033446495436364142986,134772127734877303605549194460068805419486762181
+egcd:9872056470535077418025544166904013532879288870389,987664828323257512963011567924222937884833452375999089884,0,0,0:1,-258549889378418898215810868491864809363285916014306422747,2584296853749008257728523207193933514360103172426
+egcd:6138432786866037932815463907301440109085864021227742475,9643623319216552530346508247173742908756209280545686430,0,0,0:5,405384190611356540803926039847087441116531679787752407,-258038241909272527261791760130585315013837095770089124
+egcd:9769529614309261031704728459798815700297631096679,3517848632227013216032933216030143937697714956834420809911,0,0,0:1,824442973956188793176135575810678140011131714049438939237,-2289586872950597937723114927397934685180169653102
+egcd:147669070524401967353624660276651246996312407855626175,618549790847610101709816507641892193136137457678390333,0,0,0:1,-236805668183208014750730197115976279202350305381572622,56533642776931164630044536099572395597955604255694447
+egcd:80869456296117844580165320271841144299624178440949,1514427424327350480216517445312029963129987647776900447567,0,0,0:1,42937034698172799579489980026944211003937200326398387877,-2292810203533548889500989218354940644696579422616
+egcd:780887627633271006167866160971476360466719486004445,6754024108447725515883403276228352886002003364798583358,0,0,0:1,-1452325437600127814516627181590300017598700651740748185,167915149147974595643816598065833917458080039787797
+egcd:7199869643335698558244236956584912995424331052926,1527691037819148269409741859243943945701460882281456,0,0,0:2,57636477641770614383597878932375099638471007783959,-271635504463112985014746084869260309486608865147
+egcd:455180951765525170462545338088508018606122351276980553,556221150703226579334767784298557173503136268977244374088,0,0,0:9,-26099094677797268547154896038734560717230667555583420223,21358070869183507434245801704745654317447493932633856
+egcd:93476519277392442254618836667858506817969980392044,987802175681385610339163711595695835800228648753133,0,0,0:1,453471836205864432156593588057832292869365167568759,-42912406838557667802187349192829335384746711750815
+egcd:9180181445786644280041614496157713989549610132944896,7069909765059709568140852896063908165359626347795742,65537,-59832818838,667:2,210652202891822695654795784473414654009859303252815,-273529013631655892016199829860413659231566937548689
+egcd:273907002017625351000357839595395794496103882311,58944774459707213986630692862708398194596783791903184158,0,0,0:1,-12003726808325219248723901188186062373690817244591520681,55779411376906145094866211582214461320097963024
+egcd:22771998405981875169000582212334819990253681885689,60821984515441323586153842147099185189621658456861319,0,0,0:1,-23264721625000571047177124342948563692619090190183688,8710406409472299618111529542234963792113787292207
+egcd:3842241889401713108515872147470991560356182059740378113,6515515734620532620891823824801930655919134250326,0,0,0:3,153369059865421665432317909089784699996324017593,-90442729379334735477828876314356700692421064332545681
+egcd:2864468548588229088711156824748351772387325226285,715849610154437365072792769096891349579259900786933,0,0,0:1,268550748090675670123276782608442742660458501428618,-1074604443019284165403977646554099860591230618013
+egcd:3810898561978236785388520202269462480808294248695893,1062108199707865331145512609955734128758543891943,0,0,0:1,339617394241108857543260840698815161575640725383,-1218564586632720303123702323672631316897985132530526
diff --git a/polly/lib/External/isl/imath/tests/emod.t b/polly/lib/External/isl/imath/tests/emod.t
new file mode 100644
index 00000000000..cb2340832d6
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/emod.t
@@ -0,0 +1,756 @@
+# Modular exponentiation tests
+
+emod:26,73,10858,0:4748
+emod:-79268,611,80,0:48
+emod:46600826,0,8487413,0:1
+emod:1465748,364434193,5,0:3
+emod:873883,48223971,348,0:127
+emod:-52,183,125544,0:49784
+emod:-846,394,969114928,0:877192256
+emod:7054382,917,9,0:5
+emod:3768,797,42,0:18
+emod:357352724,2093262,84225,0:72601
+emod:109912993,364,8323,0:5279
+emod:-3224,270672,198893010,0:47016406
+emod:55,95723840,523703559,0:372050017
+emod:791480518,904571,581451304,0:444873224
+emod:7278,922,2398,0:2040
+emod:-5,925972,33496,0:15809
+emod:0,649246,262,0:0
+emod:52004,997,2,0:0
+emod:-4115715,8,234398,0:3299
+emod:-13612,2576,57,0:7
+emod:9843599271,9688373,8509,0:5780
+emod:3415850521,762,3050240,0:760241
+emod:38873,18109,6791035,0:4721568
+emod:504242,66851907,859955181,0:352955933
+emod:67731070,2628566175,7885095,0:6298660
+emod:575051,8,72796410,0:35016721
+emod:3,0,6595628337,0:1
+emod:80479332,13,9,0:0
+emod:35578433693,9608165878,32791508266,0:32575013339
+emod:9998073,96042198253,2871019117,0:94477702
+emod:8502,88462049796,288668,0:234260
+emod:966350153,6125446381,940,0:33
+emod:51249,46773,83983261446,0:2570243355
+emod:2571204,205,4404831987,0:2226688593
+emod:19,439650,888059767,0:247638574
+emod:9485028101,55407,3066739,0:2994746
+emod:868043,56705619,183207,0:162593
+emod:7072012,750002,2399910888,0:1322891440
+emod:55779049,27843295,96,0:25
+emod:57835434,31279309,90443,0:13168
+emod:-6511,7486344275,346901687,0:325667244
+emod:635099,3669199,81611251,0:59252827
+emod:8010935551,34,9927,0:1405
+emod:24885132,4526383,58404,0:15444
+emod:613003,6878758,49607641,0:43381288
+emod:132639004426,81043,587317316867,0:532884551555
+emod:4439384,43262747,10119,0:7922
+emod:689907710540,460484866,82087637,0:30398950
+emod:84094,867130,62309,0:9025
+emod:-33557432,60878,580294942,0:194480658
+emod:3869257,4125450573,456883055,0:129529247
+emod:9878539157,15920872437,4738245,0:2745542
+emod:8582013178,46758,28059,0:26806
+emod:48259672,37258629489,7377276929,0:1692584431
+emod:920350,289730727,1122526,0:471310
+emod:13029603,4503668042,8665149,0:1456593
+emod:6938077836,651113,5180493,0:2235984
+emod:-352466,9169937470,70675259176,0:18255076720
+emod:612474,308813590252,510155,0:383521
+emod:180356946205,710633896291,575721,0:242878
+emod:83046,3518,9768613,0:8644737
+emod:8670878985584,7549509958953,968064799634,0:673069231488
+emod:-37831593555,141781,3434657,0:2539127
+emod:94250019226,452692809515,99738576,0:82526128
+emod:-1746555354919,310727,6925934085655,0:2276231760446
+emod:777851791,126226427233,84192406004,0:11526643943
+emod:3511,42864,89474,0:53201
+emod:611596753206,17005495050,3708625387380,0:2318918831736
+emod:482182433948,97822330605,90338471939,0:27830209373
+emod:8971927,5117957930887,1928567236065,0:1437815380378
+emod:67445777442,3930771,4541604,0:773076
+emod:-52133,16783,3337,0:541
+emod:22,7787554274,823549,0:503210
+emod:46816685133,272923,22855404855,0:4704305202
+emod:181225207536,22085689725,67955765111,0:5581219593
+emod:207971493064,41707850,9115746425,0:6454330776
+emod:42840650,206759347,852090956,0:15995168
+emod:27703329637330,20686092,8407250,0:6767250
+emod:-4953,669615,741766623319,0:660186892888
+emod:11957529241,380932179443,973373783,0:970856001
+emod:78726001052485,62593863,24053,0:22766
+emod:340516095,798875,2556443616,0:348235359
+emod:954899979887,472716,979176,0:21817
+emod:1669727071,1008664017563,37837,0:17717
+emod:592681,30974401363809,65653048867352,0:2039369146553
+emod:-47884,525888510,60238953788774,0:8466915489354
+emod:5643430747,31164,8629966388917,0:7441630635230
+emod:-9134817647675,7013427758650,14493293680,0:10069704265
+emod:16875464,4824632,157384425878173,0:110131510850102
+emod:-1891400577,334033142140099,1461471589,0:500051598
+emod:337804687158388,2747595,7100373337,0:3797937129
+emod:597469670,80669751974,564129148100,0:462736594600
+emod:-373150,494511905,69961532,0:44955656
+emod:541002,396515,663670,0:448308
+emod:7443329,192200716115,819064750,0:75062949
+emod:352331718576096,937115695,121165545639266,0:64461611886972
+emod:94655436207250,2442730,199021327246786,0:98351560387664
+emod:450100,441162616,8233398,0:5554612
+emod:-562161185511147,564556372236072,6280258,0:3623203
+emod:-87181577138119,6636401624,33493475420,0:22078084821
+emod:63757825,675193212577,791180,0:551825
+emod:75719430,7834623506500,81861106,0:11697720
+emod:7636428268,342917,424075566,0:382499056
+emod:2847036414481441,3486471,96180960030,0:59848561291
+emod:7605693821889,6857556039961694,9340113967299,0:2791642232520
+emod:8460275679756,1249967640481565,3530286614,0:1855000398
+emod:-21034390,9455714874055,499517062,0:436407454
+emod:-67878984199,6771837956,26518969637,0:25569641018
+emod:24845854,38512788750888,97880493,0:44709115
+emod:913222119920236,89756684,24503538,0:2358514
+emod:282825837874763,49707087,4419250635,0:2888992652
+emod:63007338,778023537730086,51807416,0:42047040
+emod:86515727,37854772745819,932061443536802,0:913958455659941
+emod:16752138958,84132272429,883645897,0:66146743
+emod:76020717,31715587905196,205759754,0:84248649
+emod:408229656454238,503345091356,5122409740,0:1428721156
+emod:335638746639,5761369582225304,4092173299,0:3495108299
+emod:4118216,163393347759,33772615,0:18314396
+emod:6140126413594,8416471601616,48576280861410361,0:26480949886245014
+emod:-654797902884,3118772351656763,49622473264915,0:8452790798791
+emod:724850698,6033802538378749,5080656658,0:3131590110
+emod:-67747240120320,5206803331886510,16513427532371,0:9305404239198
+emod:571096000432,140739165,2954342334466067,0:1353110426217941
+emod:-99625731171,97620037702645811,44537854660922914,0:235109017589213
+emod:33191179298252,90227008,7699370104843722,0:3200733061202818
+emod:63893120170170773,976336027,635053357,0:242474238
+emod:42622029452,37698167195197,75773078526,0:28876796648
+emod:83620114446490,8610382003,464773010095268,0:378308871158308
+emod:9574472571,9560271542,228122075654,0:119978765197
+emod:56753833744514594,333744771296,46684214084,0:22141695456
+emod:-72021302,2716854503311092,329338426,0:308255178
+emod:-12837777900800,17117883244,11645469,0:4924588
+emod:517104019809,96545405933271150,48276368795,0:10960026506
+emod:749819481,17040593450696047,13586015736,0:2311264233
+emod:-3050009718172511,728537309,5801457671812805,0:5155502323398924
+emod:583365344369904345,274298196969,206968876678,0:178154366245
+emod:38505842262,85917484751521,136556283742,0:107808326812
+emod:15796803,666915498303283,9286239329074,0:2947240710171
+emod:1386598857453,2520081676103,9050689134,0:1960415451
+emod:837113484763,3657616517904,83176471315,0:52463786271
+emod:4678899921,2786079987037,15314196040,0:13824191401
+emod:326751076,992797863718,911067433083695337,0:303879844417619866
+emod:756697895735,14491908578947766,2765309614060,0:864557526445
+emod:11248294,4566321352111312,1353192745166,0:172343816040
+emod:7099878002228869,59309793877,927000340655945159,0:5356010609771131
+emod:-52873339014,197683370410545570,9868414456,0:6992876320
+emod:413327450631,3360204571,9303944255,0:1706685666
+emod:-50582368810,137417275741,67023586922155120,0:46974101556682880
+emod:557831168094776659,36136648411374,6960687433,0:6184527385
+emod:7693794217685,34977654183341149,7387705549462024391,0:5937660734860285181
+emod:1230160392609995,985408024602754529,44727668402979310,0:16636048945342015
+emod:20103166039699,5221451032884,543018728744286356,0:478895368134894537
+emod:87410236728907840,255693035925652,37882890299906,0:34530311513908
+emod:-302501648157631,240206529977,230243222283595,0:46069838353259
+emod:71032979947810,4416429704,2419723038477582,0:15218189462248
+emod:355188737187056,6605255426444793,75874689681,0:60034193666
+emod:6806384607660,60639456674,98209051459683,0:1432252996158
+emod:65303175086889,48887808654898,73427910350,0:4396384481
+emod:7752516269162058,62869883943828471,54774176016,0:2099905536
+emod:4326860229332706,2310571812316625763,54001071080,0:33511865496
+emod:6209542490007593568,8412972472856318,788629588235,0:362055759304
+emod:49913992353929542,2486110799,4585324963758433261,0:995513978680870140
+emod:349243489434121,6540085499657705,1389913007264228051,0:177284383643046305
+emod:375679038462457,2350871880932563,6382236922719413,0:6083733543560031
+emod:-30721033347396,77626742323874,523758275336801,0:84240020331255
+emod:5192099267362805,550370357942059,3061410194809,0:1707076237630
+emod:3546331202177649495,63420031374822,91402241031313,0:53901671764582
+emod:-79044395581,9116190241482576941,239200013057,0:188422584849
+emod:286354276465,8227634038665534,8044901060955,0:5958399217675
+emod:826012386295,49355018525,20566214354390,0:4083971754695
+emod:557522956445489849,32695219802913423753,6644227791725857,0:4886117301253388
+emod:-970081051547602,98172198401841564685,928763975802,0:22343542292
+emod:321415667027595,92728916953004350117,4993968573660723,0:2876297201989143
+emod:-8699136317926938091,34913749137460,747114775995,0:558798686791
+emod:-750347276056433413,65602570699247,72710009984856228277,0:105504442183260111
+emod:796490992759,979812498143888903,84011139142607244,0:27172815871253503
+emod:11599197279102044,36330854506634,5869662463842692,0:4784840887360516
+emod:-34727277565261165051,53891223619,2799195351079917048,0:2607666110843551325
+emod:36836705996677,91726402457474120970,787136088375328120,0:479138071357571209
+emod:786215427840767085,6538388351143408779,402285004679,0:145021397316
+emod:970294384045960,339246418487,392505811982975275,0:228766017656314150
+emod:346820606266075,751258033318226,999763369665239019738,0:843347570419357235431
+emod:5301442588198654136,6353479688437885432,36561155260520,0:30332565944536
+emod:-983848133889575,94515815574826812,64461274919837567,0:37200063729864517
+emod:1440437495907,707949003595768210252,773151956245425964025,0:534921841457783741126
+emod:9193524500595,90938893533,22068045096454773348,0:2946366481749712299
+emod:380288714663108486927,73556495897685,78844051786179,0:11766474674606
+emod:-26813489896157,716398856020,4739728890232268011,0:1219466999743008960
+emod:70217805755997,315269791230838613,7083375858304586,0:3059227926161215
+emod:-504603375916094,8554599200483,203113429839514225,0:156384813943715991
+emod:165732904527293745,925640726772320963,700604179708906,0:676451920881317
+emod:8166221848180,76217001334707,46983566031377519480,0:36926290142288602000
+emod:-709635175190425441750,1295562689422083413,78349035380937817045,0:39271509694798926445
+emod:-2183184852451752183835,379414486190148900,724528035479902191477,0:637578758017403897095
+emod:4238159883750584463888,7386606561456,5728437931813448,0:4306066978435024
+emod:1805409007202,743465586820332156,626695586336006980,0:577226884938331876
+emod:941901705860483,972657766381340158572,16833834708698,0:382737644745
+emod:36719313097210,86800505504547056103,565303478138221,0:473055435424504
+emod:-2666022326987011,3591998328200,40859674965133754,0:23789375408884171
+emod:7645153844358510457,209771482022016006,905933746892551078,0:296096846282298881
+emod:7851918408989360228,84734870178640245420,17989167921034697586,0:903417754686768694
+emod:46165799974266,2935049136348,8423621229264979968786,0:6706766736891832422390
+emod:546378248247723,8703795888148,20029030818332,0:13614240516425
+emod:811349021801350852565,48747346545449,8830100158031,0:5382741806069
+emod:885481101754677356504,7096462381701,455223655560834,0:43346926638854
+emod:-80474402802255,3514824850066,78159132039306813,0:54916880583163335
+emod:7131297407676,3315297183633054184085,934198951388076635723,0:651097991912957628236
+emod:12957689764990,546447634520927,3127766567382808,0:233348459584880
+emod:52914542138895536,376010137099253465,490953375293336830,0:36400103844339446
+emod:45685344805562074769093,61394436169997,80543985329602650474818,0:71110063880403297977149
+emod:-3761985423518632726760,956482080293262442007,25753912455108628113,0:8836130744460244129
+emod:80642483462801,144058405752215292120,106396321855736640702,0:8066898094483615543
+emod:529953061572415,79301418791778407635,92480175275263158380,0:39970833689504413995
+emod:74684906365344856040383,442523186603390862631,9182842638237756,0:8987946408749887
+emod:-71808994356961094403637,86526866467357,8474332396093731,0:2594467781892122
+emod:407234425686004311062,856447201531274,99637771372094,0:11888452937044
+emod:93295648386572486115412,25979074094596934000,83211005582689,0:77383113960508
+emod:9427365949717166,750902522043226813,9221846367078539073,0:7648128015969044021
+emod:92605054801073,5909052810075662,88928490696637500993,0:37110323432146043137
+emod:-82692010434673,814335630290109048818,53615009335053,0:46299654891349
+emod:45016205353589874668,95117600743459,2986728093611093895058,0:319442824024520549342
+emod:-47452361244427905002,7926505809295224807,3915672967969228,0:229192748539424
+emod:-2641799394644983,25158485319487,548355600533885000,0:46465320728116873
+emod:767992806236118220,58099104472634917573004,48648467500194542,0:23718576556107152
+emod:-85155145157549109,521405736695668,339367664853783,0:2173663047474
+emod:3109969578772647428011,22269815033051372764,91121430284940146293642,0:52586393883507723599717
+emod:504356843590479398148,4419882553863792022,9212984461142295,0:1998044953256529
+emod:-10529450854970073999,5289053916959379831,999122926156817831483980,0:128976265175682275841921
+emod:25251527460055267035,26387387620759906501,323214288066858358673,0:254793115154305799288
+emod:6257997874497129340,9035751438224410218,1608008778482293,0:444618779310887
+emod:-9314563912100585682096,5935830113611844768083,947452458146468426,0:907834316089122654
+emod:3164647012237657886390,72243936723121379261,8112420611117792966,0:6801353756302558894
+emod:908809580547671,11401194426509342,3883128241166899713060,0:688491805461764918101
+emod:829435256639678,469855084024947,237050421425357196,0:185926450835794340
+emod:-193452572186083034,763665077760046967,629827785597782,0:574275231643438
+emod:7638580239647112236,383888251385090059747,356384740003525821086,0:304972626268345366750
+emod:-72910784081163807426,4623502102569648619,293471055432367196531956,0:13722886778137743252076
+emod:156391592094203189804337,180577077123580,281066969751444,0:219820379090949
+emod:93982143896834595,99254856446162105637797,82935001019817754026,0:28907883734889605835
+emod:82453615072254173,9862903307325418383,569773975023302632076,0:311001760399812937577
+emod:3599043000903587396023,1768639534098606,38013039729215754,0:1079943278228851
+emod:863869462578254620,414856952917501776,32810489269754337315502,0:30667070092013729127996
+emod:-67081501875735917569336,2248358004479895344546,812436139390882,0:530577288676906
+emod:-932875447143221697244421,22884241204983991,156603178117421124,0:5900450340225199
+emod:-4456681099810903468721166,99859000729568447523,4675399066130721,0:113161030847184
+emod:-843621806462466979,168009327704701836752481,10448286951664808938217,0:2076672088394686331297
+emod:4833390360325487794744,8202438083226798875527459,271225323310380890,0:109131151997473424
+emod:657374545071472745,615300564202736701004,50439174668838374,0:15625484688443795
+emod:334093752354839787827005,401544420239962514,99419641355758954494574,0:38382862135390739723851
+emod:156986963896657756211092,9173759581769093378967163,8482190150813633225,0:846371056378442363
+emod:1965032331757601512,642865979115343140209,9373512589399604415598947,0:7634824208068996776380749
+emod:-884974536295232799227800,81559669471762219,77787068435634953,0:63000181811454420
+emod:2100689836805842766786405,3628560134433649198454,34727948234158164340523,0:13219112123623843462414
+emod:204578349882954931508,882862780583656098107,571211084473029381559,0:187547454428552727366
+emod:35013594249255180219043301,910526477139765124,281006281284018940,0:134109664959487161
+emod:-467870778338402348427,54493035145105123686,5912947085723132571998682,0:1228965263004421246389831
+emod:94103148636604290205719396,6986083069335320780020283,858637669487264716206825,0:855205440944993038852461
+emod:9132908171171712697673,41809905452128490,174186492804184908063,0:154317930053007308485
+emod:7763434019228270224295,2502174946472481,71917943549435776979260745,0:6076366391198365677016715
+emod:-624036880788622535703082,608930212992798754,7235811042721337412628,0:1325308214356957324816
+emod:41112778559515327410738,82601330734126683,389247780403397923,0:182819510299862932
+emod:-647553347892336647456803,634286301340932198340,4512267124852163233,0:4111852157418352314
+emod:79428691080290217,198093832523396251835,150772939563126693976322,0:36470696123667183989883
+emod:6751000393418867022,67240075486544827,663245235329581121676,0:362034082749896584032
+emod:57296278532026543994019,519712307129820052877,663606606885427005,0:297293712817608939
+emod:531634944201680433,69864774974090600,96423733207237312620797,0:20862933415144438574915
+emod:4605715778913218047806,7769596422373325424743519,563574411491581221,0:123599395766971416
+emod:910034907691723750329932,17528561702379847624714,7515500539229911873279,0:6808962399448284143279
+emod:61052317026574460778685340,77880774451137672778485,69232824274358824169,0:51811780816940817487
+emod:7504746423220767824904370,1945066924906518322,80909556817814270662793,0:22566971663084142719867
+emod:929639344035642594793369698,3240062063297979069920119,850413690404585997068724106,0:175349368401050551985442488
+emod:-55736601709440224634358,811055227679722468934466,1713909333328494414590,0:1152624446078802914104
+emod:-1356054913265870994230220,28314681428333792392,42265180710762324353,0:34292912442229873713
+emod:795295333902960419,8481745029583236616,343155151194196011568598680,0:313527770347784158498537041
+emod:2432870569967522452,48595187151195492,378387522780739724,0:233064959084707632
+emod:6831853307491550923094341,4409540435311149052023,91972635448121089016,0:52155803105308856869
+emod:99769909628484709088680438,668486550259622211760148794,99625276554619484105,0:10139590869737725659
+emod:5889039212181347754641685,676061753141375585943062606,776941837814809562309,0:443449450881823633972
+emod:479351744822383002190971448,468173515469111051509,167960102357712774,0:66373795292168212
+emod:373219776743647759815237747,78249029163204510445,237186840834301611953,0:93966418449839408977
+emod:548375816882114508561323746,896053512213126651537,4677386569405408164,0:4478771625586068820
+emod:543601581214625935,1432960291544699189690679,924713807666487815493709763,0:862081075000207249513732210
+emod:1726232497710046755875742,5018298664228901655980708,7598365887065911342569,0:4962214251289027951290
+emod:9940521109172176165804017,4735918364128985502,350872142370229985,0:77630482962237299
+emod:935844817555228747927989470,350944095522512127242,825141475757917666304,0:534643899908921707520
+emod:2636017152603937585811,88011950079842198071310,5957119762224240516059563,0:2064861372547160647113440
+emod:459469197042596126,604919581582116554623882,89801712022876493637,0:68195913281093479378
+emod:4677369076208454967820890632,13495127487606866501768,951687217731413972141,0:425940812723542345395
+emod:1566835275008318146,21867518155515654397956,7894931071725936607844864896,0:5253224487355519414221016704
+emod:3095066120724771665597351,7840426399106867615329405,705258460541720096620295,0:414423194663820488096331
+emod:91875762895950687211242590,6694585759057681706987,7365408657949985936,0:4938741305415608976
+emod:443023899338514715234998,24793081831491994199,24949681672266832443634,0:22293819994495988487874
+emod:8441986070029128775,997522126456942441153610,11266967419294676193463,0:4453548841469958625938
+emod:295284416391225922343593,3617280519422675857505683400,14967809405365615010815,0:7477177024743894714751
+emod:2748651151308839006,37444237944901366482969738,351048919067619839,0:320910471543612655
+emod:-856968271079561907778735,54979731653719035309,13976862935818813774447156,0:9945835571304601097054109
+emod:-3585077692884519189,1798930632211469960587972,70639908743442539388,0:23667983555955792981
+emod:6524605456430450605,56279387249888817212050,3814442499042852567,0:1145383276626865816
+emod:85234961390603945529096,75018358449394308437641627,12556653126866666115633914,0:5730557471924420585444024
+emod:2456775653742592876022454990,3560359960250729589724528,66846897799509249930222618344,0:17148877353421047482932486912
+emod:60282271857634247950,2052963624811178191751039152,906040428126999262088429727,0:32620681800129303136189897
+emod:54070246300857636559309,22183829543621704345694286,197786250025515478569975,0:12804855038900748642766
+emod:9617136486380916397202,4126846760685727322075123,78146300710034615866,0:51417588230377161780
+emod:62448246499005815495980,271071921688103354259,84492924742872826420211992495,0:66230579346601533104993148070
+emod:291386580832558654322705,764558287307875268927802656,447484733675418860019,0:11605899890452215403
+emod:32205011691602629984379183426,29358614276116380282,907702927282762504936328,0:643210659902127157683712
+emod:432494591994967547828093,358695607350358964677676,38957308299840969040967042,0:16197996155411494418456541
+emod:62528660927816817311355639978,47252461860428008289625225,6282175389133291127280,0:3555910613503639333728
+emod:-7614434286778285473167,474945456781970658327,621222471994372349220,0:549700448153054416597
+emod:311184079845536545337250910,9227029559805107004632726,52006471030183808566923631,0:25043301259244786049173911
+emod:3230868170439410850659865082,898186274112724548080138325,97707512380767417641,0:86932054306036765096
+emod:834011756636699109536519415,655009820336167759334332874,6890219519286864975018117944,0:2569215046679239758839951841
+emod:92892177448912750218,741399635351000593290121,624016777142908239971157,0:25136877523502693125494
+emod:836992515247957659739610,2583612763764193545264,1174519855635794829842116895,0:750264993625612676826364480
+emod:320791582460540931132160011,677439026930118779930468052,7415527559007185772557,0:6931004685726629652067
+emod:101060981222042386397,835069990698118657833498051093,304411313271626308269946786609,0:285961239724909691347928816210
+emod:-9581797085167617798550,69848378277411149359046,669942888182689235848827883504,0:254947621159139967003748108640
+emod:-94964174425453007033,714714872860590256160828941,146992630364320648886162567,0:112947428019587305836657677
+emod:490519145948557684335954,9081227005048911779923546,22555674763700463167272317713,0:5273066867735076907883920377
+emod:1222395170293635119614342,198182065457378753800,396502033389928296562225041686,0:76278932978086825000656068226
+emod:51847702997938374834482757925,65476864639254697225873266265,9982159563202907510238115896,0:520589670319457135074666741
+emod:444956279289663791215,101406862272274292233509,2521187648951207508813886007,0:1270796539216569834626269783
+emod:241755197289597987901,2982588579376062144566419683,46590075624035346402027176400,0:2234222576652608430033640501
+emod:30298268536110439415,5662223601814697342044103898,1675333306953772484178502284,0:956756379448476070508796445
+emod:9243876208586685329510289,358317687877159897071845946358,23373687043380292463158517976,0:18143528811380542759393916529
+emod:23933345236350049832324943731,1463874466227132752562758546,30285509683054247993598313,0:22909785183159204540182817
+emod:8232014647356048136737851,23114731717567737971387,5589633642881113626832,0:4835838093570844807475
+emod:1572721001930467120310,32884392623150618360081,127189088301879894538319,0:56473705512662665317934
+emod:-6309990340663959494270231,54301230262284516360861,714321021064688153899314430099,0:84913950012890099224323844767
+emod:724404836134898298450826978,79473347677565218701802220,85097228863562935294353,0:23425975598985124017685
+emod:1248615504830621338524,4939277515828927242493219,856480994935389549295086483,0:208559579900786673941630403
+emod:71694075133584459673485423,491471707800513684058387625,57613309973036459402620201485,0:9334604736522066347584171098
+emod:487205142874162363228855132,32170196309678727121574378501,2365947677964956706238797837018,0:1460443051085803997813915083462
+emod:10498793931533837751986544,83121914354650984352606,84780501352556446964608987,0:2663500197542495228867200
+emod:858271416618515546128946278,461548172771122263789060099,290346398222664413963288252,0:199454897909502042282033164
+emod:194961196331029028416806,3010397360933184988474874531100,8894255215761028137154900,0:4725434487338660122833576
+emod:406136918536976813980235355,373377808309891123266509790,8051548562083247464877013,0:6712616553296291113074471
+emod:-2530001401510124123338044,9596531290218038290076321444660,94617861891432411698686664,0:82720940727488645909580144
+emod:962341019433102549599309756,87959647015007020857271,4814935972310202770646,0:1937702586166074196292
+emod:-9481051936536536822112378933,19198535394666739186712937,381277436963458897720268488253,0:221821071935200208681658632115
+emod:188158462154750488255090,5147960444849946425093800,557834326930177732304779,0:535548855861651576845189
+emod:320937896085553144086178,691095750038113040331093041,26671339372282533818130976644,0:16304271928904332907031077440
+emod:6459406930432717296751,26393034277242496542604,95792580547993865659473661096,0:16263747513649826536284379625
+emod:-3955284617135866036386266,88955985063356610183176901,47993723273921407452861564818084,0:36345079468314192494573668280420
+emod:4469223387855120286647143627227,112486512731974346137499409882,674951744546236842962508833599,0:263941892665547640864795291242
+emod:5842180236545542508010186,3813995676143309308292843196544,419290459505201296652777,0:194534437035210733745993
+emod:52508914199335388219666638736,609717218258403246894120563,365684533154366812172288342,0:306118597360054606711715756
+emod:5797432698581273588431858,441479045571067025706603688,282607387577967901654384422862,0:110229077503714060775972506150
+emod:65328925252943246789191171238484,96713927150618911532802278,22277460692198085977483518,0:7608494060818884444883860
+emod:-3505111910190253821104955721,8184864474744270904051127420,194419774575051270128492444,0:162992788664326488651926473
+emod:-604067818162739797934946139,9043516039569227564714121728292,7767059317109793197108173473745,0:6948009587818483763849064344026
+emod:7754422959972636616784266184,659289209085822436564762,8509024996912387887787842,0:2665536004048450967780290
+emod:36416867151518840487645460967878,844372541160118666333682064,952635585495157217378104,0:851359968458957942741896
+emod:6507853401807441673041800837243,34718667350062293363755353,5468669123427020938108147,0:4716020318197938412234249
+emod:51211857820907905381543,77515986228844405658622,52805031690609904659313514144,0:46181146040418002449595796465
+emod:-3481005717923100913496633,72515117151236778732398780112,164464215085523994586779407667,0:110489875791376642480427623726
+emod:9727520131157808840831645280,924001182352699721614717943074,93954856739560714418171822477006,0:53602981268650203244797808464888
+emod:6268799672425688143953868,65752004602477767685988190527369,919519002172663755283332370,0:743721248544699996778206728
+emod:217255430663108140697379866,5639408060368994877725872115390,827864622867155990409562324662297,0:346888052171315931113255266057390
+emod:9584126703131986575758741162,32590496648447908561813496450,160498103515332847853363,0:53968810450556766053341
+emod:-76826728747216724677957902631,961349485758023144791477276257,137367232300949721808331182,0:4959768054309457695928319
+emod:62055398452252367690310080057082,129229535556008217119353115725686,9981426678099891826285608,0:805998125116661384829888
+emod:202510417400115156940889305598,15341206726182593212766128,996183974088677690094216724625421,0:817289450583828545947664474415931
+emod:-25516453293605744322947001163,5071219340735886356369047,602175104818483716891162778987,0:411839702152622861532714876139
+emod:993183387816460492640272,1614311327330565172683092096222,497972804217752566422039,0:494226915046684056423589
+emod:-139458968709342780820670342293,84079268451086347933669527964491,7982294793121272710766231686742,0:4200752285053689019247323342313
+emod:-642079420338207037888590791886,5097585020105759079603894,1749318042304737154855400042,0:202512538887870570156602468
+emod:526399148116041173415852373,940696687718156710488520497,50662078590094962860547244145,0:45895605101830456875539711113
+emod:8906813754152277992921404,80888477226023092123029527,13570789641532548676576422141690,0:11991254102988651371230177697914
+emod:93310258111859031487846046,779504595719824871139074,2316452607286039459212508186835,0:1841260888091242285457152387296
+emod:90444057415261195182482901256,534224787389163242275249003871,5364056042511354002232797243,0:2973840956442065396692091111
+emod:3159667409620907467186412,992919840843965860035887,83366646442680814563981888244,0:48427633954764114194397665660
+emod:99320619586506347666588920440,4405632885227428882941735745,19542923441973303902244764,0:2496404967738009049373508
+emod:80097846201870647655651438569,7478823295278459690728990,760398924078893349243418019,0:626123454565827223374998274
+emod:-617776158199232099295079230176249,968254047400958548769181004211204,44388668787389960907543,0:12309724362933796108087
+emod:1941484805465095241888868932546,28318560596248215297413369,78732478295542770828847418,0:11323556200622810322816682
+emod:6902476729554822701916716,82251167994228841481066017,35882713885308531026666821,0:34780023777540678364801405
+emod:5062468746465213498385560089,8136268100978763412711554289,68866609367366454712369109,0:44871781917238275621305468
+emod:88628634209852159542629660518,9900653566206690096097393485358,5146762817312746650783957833123075,0:1130545067675413155892767251194249
+emod:4183039741492584407492357481,978182783653208012914682683,64655693200972774031969126,0:5025716145757911119761805
+emod:5009607688574515313104324,2147563655528822623340385945,6236086785233460500733859,0:1405104917101339899753318
+emod:936982273588401762969515216739112,973707182278032902057390292,1894889840757299574823297466,0:1186002927649083815020840328
+emod:-979316518105993608150102623315,2370209457844401593122209941555,54428721194110089109350854,0:26913462600141970364018171
+emod:-5655018125941779786582905,17920278334613052052585561795,924138192567854018477877769509401,0:61476589026820682320306888608974
+emod:84489372498470137649774035034,7109018035481124695636450,5797230889810299281193349634019,0:5612051483938131301074837863677
+emod:107426142087823893785249225,5226421952107015855967156538,834564679898397955796242150,0:374409797926018190303172625
+emod:157094343256569268019396107347412,3363666015878047053403499712,3077292378832241991737688300,0:2345199073898407378386288256
+emod:4599347793505224871406391916492561,10349753756389543100648649,65816642199331170025417801554157,0:24079921356378393197992579532100
+emod:847167595799527189060120024265075,9107386461422683351260870279493410,92958250555849386269043855,0:35153939443890825069457375
+emod:-1191675132738936968619514,74950542877141809186776499,30939415755921402575464055877087805,0:17053440194220346967773901128643571
+emod:-6782161375037252568833831731,21588926184031614794842404042439,87384900356318490043390649044683,0:78411924985423842001255202388041
+emod:725370238412744340662463645,801132128288180827454102757582711,620855082501145881156782549,0:359871609759550116946514648
+emod:-874379189856445894179721337013,990125527305844856332150787749081,8231539277268138641840413167,0:2289484932966836920485418470
+emod:-83008902474732975330921978226,82794210686607729439615194829247,147791999288202013476656713406,0:146693025926271847405525671222
+emod:993041496775769783771922013177,652198618560534787722679399482,14725280081827750297488969316270418,0:12116281278492392720710544362298223
+emod:46622323497579971935863115,394817683428792448650089831981,275712081411878292477481334593,0:158697271488808580622506705623
+emod:-3898794108935715830804259645307545,8539310275091037665015112113,410028214486245399572630623,0:154269296324614984783868211
+emod:79671715478701846571943769152118,50747562547703106180109929449357,4023635598183808950664694822818865,0:1391680419606609518497878438964728
+emod:559336542916921480977013076660,3500214095929566980492663465,336757157474053361967887529292827,0:205213355551911588287255669283398
+emod:67082036968759143737139839,523004801838061152155611054,471652207874138548702202353,0:106442966546624668524597821
+emod:-3256665451209505423898886159916,59781980277755911367047005074,91129573344353344374535568122224243,0:32050945513189163759638087657164892
+emod:421990276114311172439204299235,35826815490436606511044043492,15446384327646373190492730438585,0:9198468415514629536422965781785
+emod:44343136069714981893949445602918,74625812833376942712384866,8553344812866281257132806310141,0:5783836105657448834498697176854
+emod:-3350599651069474402466963632288428,111533243609492247217520718860965,19776907108357809938962249484450996,0:8355570250148181808922442971171888
+emod:1174811337592368749244214511251994,42091803705746744966101838336617,845309015023334575607631339,0:328886787862996931441907071
+emod:-29148586556051713564217625193,68513553022673456091977636318,517234274741375130441484814600195366,0:261242636773611113876824326123905043
+emod:6504167945767766564692832116,79109138160593227576416337070705,859309929776480635814520707,0:653461697201929229418946370
+emod:93782137244393346713836734,79816233695566241785503895940612,47212904918142268923262812947,0:35930841356748083688108060545
+emod:-481374015950451874599738760,971500384056236606682756504,449203445432063323041956755151715073,0:326479696526020517109710611255112326
+emod:33975864000889551938267169,96711853837688512196605358270819,1078256621965966374431724388,0:90992844234742791085579521
+emod:108501037609635132976961872036788203,6219795372158712553653962311654,8716372274939376496374246159612450,0:46493029021502557862865275214619
+emod:-2231157093133343418986538244814994,83376994288776233556841533573723558,947070007417842767887988323,0:569695285035798211404990578
+emod:4320183260196502618997084267,41119367893002798881298799670088,928548312561033253354469301,0:685331663284665282972257551
+emod:989219761371718106548064391401720215,746254976033978038152730412247975,899234555824809502131806801683692,0:353153945728216728164717147859487
+emod:70249906941776493080760539479,449610892140392817236359849962857788,4178349342228788164226432276235,0:1335233721704565001505221772011
+emod:545502797337663151341732385037258,90145671428166124528612984500230,65353209667979259637734612828610332,0:56057131907461848190987965655332892
+emod:70201665323655856669206321215,82151238444466709049154516320141984,720986595714891193688614781,0:434647021965056085408831563
+emod:421198830106569057199561575692,1004609557346343726386068926525410,633868114840728850333551602744,0:604704399006232077090793233120
+emod:4615256370681079013157800020325,8400414787259268709004735030130,44141279558739534891246414484563077,0:18767312155202497589136865119303869
+emod:51901922040540262359036981493,66541229620660433942048401110186352,604842069438884017503376380377487,0:560241581983999804968823332813883
+emod:865876649476766227336308707540,54523494380158570191694786271952,30189625477183041262303690798037,0:5517799863814849137124453024505
+emod:540104790337412628896589738918163962,25517420734892235958218943479822962,516223444101948157559494280688,0:285444604149225295822139831184
+emod:-120865564927993207924741653485624,913588382476805140812832387555144,5292849031978636063718154558956,0:379625045854381376013487318700
+emod:70630316045710645831137056416098,472369686133234789698150515963,59384539168300629700324758824,0:15022806530946436030583838784
+emod:3922428518882665203875466914597759,68182625456652248599363364893901806,6502711284299228524855233028593,0:2808475877330758629142848372619
+emod:-767906197466320392395972570845,5881247518778543233940000315537304,287419172400279725552523866012,0:208494064792679452780358308329
+emod:-183473058607238695125794649,5195900726421669056563048427,4401632354842192930996857262,0:4089525058119677938261594431
+emod:165422203258159204617067246120,96059662222900813086080021260,42765970916596985181285425013,0:3450069033793034400281980621
+emod:-6202976578952904184671995477658,2047878587371155342936292231391653173,638007817147957433105556793060,0:264771935095789602347821114292
+emod:5715510499720116696692085743763,585913772675513473362454296932,1051092429534137447273592584087,0:682705608964805508054206642997
+emod:8554351601263637934780353184462472,2234206121089089275957949179,718140465388982120919431110935367,0:184669837268894201543573681894661
+emod:80692144241982166867606755367641125,2849616930185309069767665166,23879511236239108118965785436012,0:20523073803895280124615325144457
+emod:99791107145824395590258329666,325370594025067544378522706736314,96399847267939282102767305772251127,0:2325174100015879854256600082049436
+emod:4159932940100685089115794076141116759,23990995412460118678564628973765928,80832081463108433977538716243727639946,0:67527463845329678499612133471786203313
+emod:788157166896159069390966287243419,1486322813809144772467638907874658537,891915835907995407210370317163200,0:102062258185041646930644428900539
+emod:39482400163217130341378273663281863,5988616246240813543901974803730,5233286401955663097666421133559,0:1266706417570788723251682663891
+emod:37283395352033119876301598293239416669,13544410706066077917137340119619527,90922298984492607133074207595203967287,0:29635409004691233225521023456097882412
+emod:997092394433838709995127446401,945171627926561384468473783312841500,810366180441978415788967038942786,0:208268256396490525163362174178287
+emod:8028402014609956835909160326346782,26557618265296731376128156126,460114218338498016675422156130523617,0:57220159633664593786040042202487645
+emod:82562576995621135938138768719119421725,80752496992618170687901372956534626,1448566551160810322268830690053691854,0:646521647376500058682612093836622553
+emod:85548648520427764614796522518452921164,89651898605887779463577396538675594569,65124148378449835470532787649213,0:40497439208050142443242215136607
+emod:16837336872939465286295768414551331,569935780141651744430445423490,8783437523930110362354247602517607,0:2046943362901310534745130604075491
+emod:-4440812678686390091523604851953175,389451017692789149570538026068781,1428843786528259273557255613906046765,0:1080150304658630116675444179316296480
+emod:967128946679209456313061694178754547,71927999075234140765964350500643464922,5912388198893179472569863818550882,0:519919011257421171091112245394593
+emod:50956630538253741318888787410839027467,7254477767965547955941480470459567,615206000459040658792942579937518,0:553679691619602644270040205425927
+emod:3275455955848771032620932860648810050,31488699805619979770222331680514,80458424575688534547636632889962148887,0:6244384826050692991633033848953781669
+emod:-21389208725934970402070480138,83394267330366428453791161248271,435867681437150310057862989648368134,0:48165848424304409414740281589776608
+emod:85613012922122238849286197885966265,6264623415046666744379998032348811600,4673861359129062110917409479097,0:922666804172116833801730611634
+emod:280083488936332437588802230890313578923,244124978249612335794064534642,2375736859306949519167609169171687,0:551623669267415869843380453511910
+emod:781188309374419725364720820335533,135014953285485878049171718509399492969,344084387156056462159513838518,0:106507543249649319840719909431
+emod:98561799065473561371563615410812461706,9134726040214334897451541211570930222,77036158481210325032314040316433349581,0:10604005574133189996015761603720044688
+emod:5834647121579885467217130407763503632,200264652092134485478998460165283,49796811768811795244403981652327326,0:12616757208278628842077030859699158
+emod:7156274802094801607862890235975,298547310278869882278519047422,3385164957713213782961023671150442537,0:2365150345459624684113261880718766685
+emod:79536547656264208689393334480936544,8321385671827825288762542280445,785140248493770428377830327387,0:667723641201713821468357364660
+emod:2401918006460405664310271707131,7938856973411329632754746333467451353,50252536011125420227927790886850,0:2560962372344356633910159134191
+emod:-640484386299773856766873434498216561663,521312377097674590222482921347754,2076627816299488817471309926917653,0:1044102083342050524913059924893882
+emod:45733835810902836305620972021854492,637659651938075050952475958589,780295381235534049283047240996085162,0:356302494046578600997282893502520224
+emod:-705304982613296623295125876847640,664590498867602222651797274067257719868,7499703984527131597058855628260006298,0:4482230223758031512649996652730841066
+emod:9684252440964253807141800312433763,190043365382656690493696042245955707225,3095261211042298242370348907837021107,0:2250643148518714515189768690498752024
+emod:-89032437425480643935967748757354416,621983182028088553431259572347916435410,38079815655996180160875323024441762,0:32643143118487494012451637529005930
+emod:6548447424813914775693159183257,65121910212312442407559411924073,985538984256472333797587014404581436986,0:740155433087747455737389029181370989287
+emod:4289065821289287300568064096399722,9121623380688074176040884046612007916,961296580001696582058791225882,0:45381992080327999853100134788
+emod:-72973996651785334626703541251510,851343162677051554053312177517930014,11415255076241129984914658151314087,0:11296475116822862530646104043954143
+emod:6215781314311141827082903466280283111,82690774957918159004435315373320417,27716342728984668538238211473421,0:2433474471136329719554510283452
+emod:39290925538924182292886302889784,3013982337030112395184480691476,2874832168405952076336884530324927723027,0:2409837907629149262138096279585792264660
+emod:9277827192686619891057091530556789562,96429757152650874683611007657644,4535029359155968493194223758827,0:3867452547234619026743402511805
+emod:5694258184281411312360339289572762440841,7178050879307469422753687401052115032679,9753293426594405370122100566371326332981,0:1459323522232121155703484803621777382578
+emod:2631708872518347779478401470159636,69245107191231315124801771805922519,5376563717710166640876235141463100221,0:1586930529708153725166340638954835393
+emod:-532822740296211412518831858845632,40668524195320929579193193936667373,505606545836126920558776593155866029,0:421534471253420106860659063178492972
+emod:-18119290713835899269532794976004002911,37879676757802798170292588489563693,51891136935808235992985547250049168,0:14815387892201994526759362316856817
+emod:944625015888233591695043379987489,7693259777885983120642487312415887,3163174379156957158184811373016,0:868511369288625949950763838225
+emod:-8261719628034460466290601450600373559914,269611237440354291239517315110858,799350125207208117394870062241902513223,0:399235834451270298186875260990350588241
+emod:79473780570881594097438192951192117314,7169647683642226403729056378024586066648,22954171389461145428057650940743,0:2168846776879932971592555333531
+emod:95869904428201135413560110749448802753,158340104707707507507946829328121,90984891161322604272382067470532492205,0:5924564037970417636455059119103926748
+emod:-22521492621302175192658392780275102359,7693302694515406325578226762983037994984,782722878640118008162156430550954718,0:119815974456412544146474518425004437
+emod:9963842744602755276656167034564168,48412659540989981271789655274768,43293723041754769021056672485976,0:38945698446931926733887929540536
+emod:1320877778921077387166182925462256771230,57630920609252345178704453175970,3193372771615772702336566528721798637962,0:788819527153114047491271244519182772544
+emod:668849032341201560206891871233861747403,888433768055712910244091518751770,267361236110795236214710559012632439586,0:155637798445501597369455066609821901151
+emod:6512075833061087798080551616254563514,32092556887038243782172094249883515187,7726674502992997466882017926352963171,0:3997773747495074686605793565307898133
+emod:175331741086869721483946575985451578,498971069791965179508784120214414266,36153226259659293800129850353069792,0:11517636272100517299763240352733600
+emod:-677346278108428877376669412246870,9122326662016035239584815083992070495176,8466447950617025601185822550216037750,0:7996073485764019141592014511479503500
+emod:3004006376153998272508651886671867319,89420637491378914617711759949193596,94841662569213792123219861089357581,0:91022466232802632841224039771245469
+emod:141963083020862928745284661527006268743,1094074097142911406442396572480839364679,14372416626149499532166554918559602886813,0:10501331757552726404117414997172439332093
+emod:3537251641169958447429792087940591841,85312557100182485395003016294806105,4933954336062823716515388316534139210277,0:1264190504163163061419402586060377117556
+emod:7613372643252414055043698859413975454452,8104856536803203203690055640315246210,22350828251203871238906729812254148392345,0:13852329926953072565535594189985589893489
+emod:5496200720802281470038810856743043086,13398984382633586073486065955736662183,79312825247526611330966937485082122,0:66661235819185738734811419475614276
+emod:63918543446915084085082601250202595579,8493763746998771444323258554325712411,4937677683346782838292257801829180799,0:3333170338194997537460486316124046513
+emod:36261747289234573444167038136694149416,2349120291543932920428306772143,686686391823818082220818261012540,0:264297913952895694560131373515156
+emod:91704684660004985825508358858995087038874,2015370309491008506921827067333129594,9135792372038219712944984119888962386,0:4529804613575839287527481063380800506
+emod:30278645824646334826846693204541658068926,12818636001054407099890316510058892,7851583114283368731828210428552882985,0:5669753244104840595149054032720029076
+emod:2796270570869456261650857714163957,11563304674625187778126296571762555,6215093511413186796467390016946078,0:4670137082336559942534996304341551
+emod:768218963811498104890466470855528,87947819439418684675632728454831941,1973550877645428060151378123682620,0:441798238493938931699648323746568
+emod:-2428535063509936208105830667774640,3035965301290018588642321798578636,188189970059256072630697270059421551204,0:187579612082668219226020920724838998284
+emod:-68851281721881705328338599426899449637,61411216780529093075213667248360855790,762904049248955019330945036218634,0:462150975555814307044400024262763
+emod:50381922933536391983048133911745304,1327567537265931585748836565776184592881,802215654672213785119298527941754940929,0:390003904015432758428242187678591715653
+emod:529101440911633844520662940603032143,43786012747535262261511038179577399,511020742387225982022507255362265561978107,0:43144871536679970770284455068495104451271
+emod:-83888631215376392729015255508425419556,2987291005239618438509136686862070733775,961384311110037617113682300965438706,0:29648441889315953286284555584666926
+emod:-821196282249805910413962910577363,899754172277729178591041212333965173866,28634570307010794416106940080087125523,0:13173340434987909802210494442005883282
+emod:381631360270395672709101001383167564,5158459604313031569589122775835258400018,179977223820697561825527184706001338,0:90425662788930319644902518702187078
+emod:86931293242801082346374758755111010579020,2626551520446310376390615092828594222,938653251144169045231475456784193560847491,0:365195163429401966471156565576650759315955
+emod:571783539909088029876839939054322959996,3089568378114138198880587155086119890,2744081752554506253029969486161407282,0:1264543407557838374228627104087788028
+emod:-90886625513314511815555188570608546,51200053536142533814421471973168803,3158468647093861876601465341868309,0:2925547080612167963149993945191255
+emod:678603997120076532741658796530004849,43414916815768520427422498534418015,8716484032032480216675313011200057709,0:76319340105732892359044842900479950
+emod:612730541295585524235353860578447295001,22424302005854819986022320120713071951,173790728285176883772120949725911541084,0:137975127594893849412331247896142478137
+emod:13948884468878712500594129935211199120603,9383236477661484239823311361156037555,7150124390877159720608122766898971171111,0:5539575869437504207805443963399777689601
+emod:54492739252211246006137151994700249,67190668798711463919179422578016332737406,5016308665959551730292366483247498,0:4961979712444768037254544658761431
+emod:29680512164999518310606641453082247,1353001032424138907392467987475747589038,459082082784205465090366530024559,0:450480541453779074511769512964428
+emod:15403192267035685992492637058662708278079,691714738501419527821402660938221344683,7782687609483337882572886515961628752,0:7725198743465314962321221679530076511
+emod:126478593002688908873146865473634929634525,6358340236015836865079291052256775,642178072362342080585886203440168430935,0:218622928181521828894284595162507920145
+emod:13913359834837755549848482705915052266,903509443568563265008997239488312244,38405152518791040164077250979465916520,0:28518709836314856470772911348321435016
+emod:83931848804764686468764875474979982242,37231771700852953560669364821981996529,8064976106252567560098554617279771,0:3942705697569048252011335611766898
+emod:87898783621436420303252969787195069,967379407272322490869598290122854378588,601280977875708034746188580088928109,0:411325933760221674646671409872577059
+emod:-574877736091741275350898383808389927915699,594958545957868400560169903622579655897,4423949440914171636206327704817250586403446,0:3323591297752691954350870547829008827201931
+emod:124800993363976911520180513839889298395611,3963571144428060960568682938453332161723183,674078271234292330095446224557694423193,0:422135852569833954257620597634971621477
+emod:90777341202629209516486441959509025385211,33892788023206849882232725042383975802458,965834508749187083956638172933001579344,0:656580209956545000201526160758647431417
+emod:428177661658876831707141329481947688426,65730335739816729185618200604751902,5583905204611961380972834719217342953,0:1199936539591520430103110063283203324
+emod:7784166932835047133921651620293244411254,45683020890860577526532414749737728,8865546781759541156004910823031924045350,0:8781672808470559198269957754771904762286
+emod:-50974859063823766693159687850998551,4260289458698540774171384011548170301484,3075280497472455596559827351977048841679,0:640353521741095591912508608109444685750
+emod:-44302701915422822099105814706266768585326,352328336928075991743029118271328701469969,197750610229907539580754650086642390905,0:93246465784416858941838796225126642669
+emod:766771922418857228732717683752395675,53187483912419491901307730154421458430,92096091103428097138850170920718803085695,0:57565491053888594101424663327538976145125
+emod:52721172881006130419437464601359973583,52365059560631450286814267296264202147,498576604623229902884884195640797562,0:181571367769928285755960377087597847
+emod:-130061614640638992198273716595411981919,2346118145486800692560690336691790893,1645004080847919147880779643424152795003,0:465587055828660570780657181568452731225
+emod:307876682184042075642894436987556451604446,414568064245406529394828107789210339588896,477711345483924032017056685517738462284,0:109389690976160199299716512672430415312
+emod:5371610880889161920476163626282917268,671190145264797106864756436651734380622028,857741777438607646271321549114765205923350,0:287287981571642915909267131628181821120776
+emod:5204868302533203940801436297790593533332860,83487861479973096451480151041003379,71382668037578608278694683426146288,0:30832566835341111033409687661632112
+emod:556625156486454810659526673624620788538,4626440741141159394644754018141116454244,72891055350325059886351235380188925751695331,0:57282604851594939929936357788070706169855035
+emod:-89511300923170376817021029243002896666477,903721376056645176029730798837754904819,2013905533937026971053538084460982634236907,0:570791309010977172526727690555890004463372
+emod:69694851714973479181534773177163535244,386316471197222025887461600408882433030749,490469070636694229175921907889063586231473,0:427487689181588318519876546414273004996449
+emod:-588196597032453101052930493773379817093105,42480403111373035847406143062717911612705,4544690508644322943234886196205261164011,0:2047663912083358415178872122408088880103
+emod:18601385516319880347082113262021644716,353623982591699522702650394835799306077,882857015216699962449940196076317077670033,0:167450675786501647351135027234844843065181
+emod:8987750839863791535937648238891007778,4992783303820924306757780883007042021257,44078061546357456041964194188918599,0:7906772385757741707231672436897321
+emod:3066043816339025712845503823677606013,902933129598925384688189274201201551,9952994249589962222132861005360182224154,0:1174534817927019518079679504541484744197
+emod:-8621225450444798677120486482628514696,99155842760569961250514993113606863884,25114933437945893268599527258089494552599091,0:2901441178432592927100180880754049113544590
+emod:90281107710916849341198657251024115664365,754667850911713614499014770880887141334,30898295870918445141561498179371522917819,0:13951738483311575701788614225768771977539
+emod:-377295017128784286263228943698366029281236,815351785301111612401048321797886149066,29710296428625255526774084470011099286,0:16786657050746173886424618254498209594
+emod:90209342286956964721158878154317059477,1184109459781060213060226071584865744,30538892118817816797303238023509341587403,0:28384974665672321900008538327342162253338
+emod:-76207593117960738992003792949566245548142,85201520873038006008429375802296986890284067,9310049288843035339384905918862674083743,0:702354734188303284325632288622165913045
+emod:3050032614782701178357664755062786032,6801863531876714949028658176036217984466954,43950118108330216557290417378894698723105,0:39620291264605476263313200424175332570554
+emod:677773161150320527783770738001557704372,737402634272859936882908890962095194591840,6047292927355913043161167285175711434800,0:1483012736746464157045759924622953000576
+emod:42088022811917334978597559931011799497514,588319468481766273347382652716318465,741545598763153697103785060193676712330111,0:531456297231876059205154397650433936193557
+emod:687777305090023482357070950201516321450289,6133564983213467693779486826114552977,7627976248578721073068053781703769523841594,0:5843136042246311804421931194539413550947857
+emod:91512065672092684699107288546273626439473487,77707078677517557779288077287329555442145,77507839007463389547163721496077953290665164,0:38085531137788908878444542689408043701328043
+emod:212359500386820079595762158387084577,717033680869242497989232895502553209306,57994712116702439737072157729729872704610052,0:50129132851246790997550498079907544729976657
+emod:-825584369512058731518137754499088478179447156,1557907027924626933995813818185230430454,687117774891041750881385770197632894,0:469172376510748056891468208407987466
+emod:-637734412004053009388081157566315826855075,36476067391256503367264361488762844508,8901726487790531465993910110654847381,0:4608357665978022682117013835997146678
+emod:-54456151981942190750703318217840449704343130,99982993771652282608320462546135364960046,75503441196796803933415452275033785162139990,0:1100695159195786352512500747472823910559430
+emod:56697516355737268216190660504482018822,88504062521017516515948614320857837302,31042097144177216624878213666191323514,0:27351339735066170958422624002651576306
+emod:-98852251157147894938842540415683732209931823,1103039394658513749769074015498619281,7550633351197275605040420550766377478,0:5707985330709738472127894458871700507
+emod:852323466440811463681452434704718127867279,34051201027780798621123886995870064920,795262345784174548938737711612423959,0:548570523642232944065382365273044931
+emod:889194223622807557021642095643419375,97697994551840383739114494141322582209674192,70985658980570759747746606912921132003556472,0:54920500907444323447367511646922423261389401
+emod:-59429009735672945055727939898766153531198,3806951738924291817324705452300312658284621,90645462413613180896154498632105428944,0:8969737683089946972629350404791649984
+emod:-788749280314228561044345431332920373159,44015816904317649966556444126647542275202,81067964499763345132379481470512547700720528,0:421573413445326284503993935343886089184977
+emod:9008250476728385872623793527898989079,2093760923583615910781525258418818015395,84876061848991122343034995751598547888,0:60481132777467814904735222040023224935
+emod:7323424567945169155005613073259826377279633,5345346096429285612041846952680414187,7435331969248825511490730370379710920,0:5701245548135054050237139667347533017
+emod:51404894860307832493700969749859131586957518,9938875974899784631458092317153698579925696852,919124325203452723338865802119093445414631,0:581269944116304841135442821130730046480816
+emod:6976423617979510411465515007491044851,811899783025865657772563202580630898795428571,6842295935464600709869948911248187992875653,0:1463570911818405692736959800443272136874063
+emod:9244740154784184489624653851590988118413336333,74724797442153844622872240019401506034596,415430272200957807957520540642458327434814547,0:227245764253849571682827833616120828123015976
+emod:926378595873538467696967488061013453069,13726821339710674251825283897470743239,984332184269068978074654811562030364,0:366045593329883963651763814907781689
+emod:-2813562000424875340357193353899248540030,886165849336487766393906742230529958590960,2271217318347813010825877828107460187565073890,0:736934018978417266185885759728676558811563740
+emod:272054208241621617590554322826124010321,247618769151239284337079695008609818283496686,649481706449462881752315195565911763474,0:256814202110410998800134363843790671923
+emod:528587416597254711558479148286684876795995,56025560898493899721803630575638541012744107,9092163742836866873755879991932002700857700053,0:588768500717688902898041234316335534968163070
+emod:-36376510103909754880425141038180683008,697554526126494541279186939566773312469,7678019691033242250502480954454444789783096,0:5565390320666040024632809464519631265578088
+emod:27353070533528810361133250533207881585,454632738024798173419305392484295653512789,8645616700024063945147977100235060594126432,0:4587159063853018443969072957434344637693713
+emod:4564708845856171353601915371168338496301854853,7977961275571093400571875056194861455149,813927549830561854195243397042782008374,0:175995834338047549986610112197044992575
+emod:78175395789694647002168837493633590621186642,8578229500974640597201805617750253952058296,20420572460880064835714904978798146323419,0:13267874012653989247914000024945154331041
+emod:140750235074048885495514519935667682244,2119009829407208281675487240867001784,80904987806406684614200209335872193933373288,0:20538605766997209360435961966799813436662320
+emod:9887824160642886854268459508821295133,164654330601600177496087425862536885517,74733613066493027861988707350740433987311667,0:5362288908065092864439824122867646582501022
+emod:55287594962561555095068246083044803040880723,936954069289825306215654233135813117759441,745114678852371902761659303193044148784138736,0:290151193402965126922268234821385444873479187
+emod:49271627767039808526745187094137141719732,30065281370305611177302331797431914619013097,484472846194900484542233448660288882119501,0:458376187678161540698348417833456289330989
+emod:-33619977831470526307371048811162970364476,3021585613307372422202371415945287499364,41518376269473392058127463402457118308536,0:24307170522911035642636754257602979386776
+emod:-25382128605388905979122243374547045342,828302867171033162078210088228770176829233725,8266339347894794362758578546936481856264205,0:4167869286530376166812379465397611080036603
+emod:7806062802262727519367165518120421617547186762,51990474722372679127714742060768843445794,274591070028574724870239318997476790646356,0:180286762288683513660209941777027215969804
+emod:-14318350583742657677501199469782146645295,961806524953716379402040320560202880271077808,3687275580612869739753747169826129862213334399,0:2737868566562935158202389734126986146079719735
+emod:5760787392296885353944866764267524928758610,46155936499409386931117510358618192060334282485,9185503223984382023640943204999579979071680929,0:7506254742023345352482567480829597623259247559
+emod:758462979498659646336246209035644159621552,136635434728102133698904796510225702345660178,9498019876743551759329514429520428372065505605,0:5565366837043674646400082916150410306576873804
+emod:182033670937033200311127104143473575388632458,465202911160104863025573660937504913136,394894056005762580037702893386135121788,0:316367714111986031710088217259606247428
+emod:2632031473801519112928562274312812079466,2498635333283012493093325455044250943493,799862304047991036206572453520324334513,0:260071365955878514310663254591271630685
+emod:1021726135630824830413448736592392545545812,4431216689055888716659906849751643616246362757,595012854621587453243625735815790460446478875,0:506405473722516168522817128617260580471663667
+emod:-74647441813141773592808970599111638815902798,9458739990542641030328044128925695503721278,67632705274078858494220871541834514286,0:43860643833521638278988180954457097574
+emod:74347467735199697397903862391515976816,27228101096114329060763685814389121867,2329466465821059768201256128129347846,0:527826993612543999076744976068461088
+emod:70535640036795289071039498872891011642193,175763117977529697478928626604560680829675857,705090454888208372647565597170374314517,0:179091754275860670608755581507296361572
+emod:243670574841881773841146078165542230152996248,27224356467518163226383802462318164385847,52881980947180661815959615676455311403364453,0:6543936847510216013770565818083740841303302
+emod:-3063522500685962875075820880911603917,3092546229913230570432064938454622435247872,445936607970411171632403906819964092617858,0:244095099022673834362318413541677305006965
+emod:39258083183616152671542900110410755401440,89093980612505699952982513757457937212093,962271109020614661437340991578568879083263254,0:305927769953786743646130969214578455895721012
+emod:-898028156876410713010493580194881547802568137,51663960553269149619746641641026382469722494,88192102753654247658195333315719037577000020,0:85184597556224178158455641450790019451878649
+emod:420238670197853908213239792155799109438,56874184795237971698065659542105288066970508072,7039994314494472877016149904621158951181,0:4195556681277481820163873546402003983965
+emod:988537214014327037772289213676835383723493,513562354885152593212937649884550491754906560818,93157394660505505194821589054314827610053,0:12739336675286048975363676477920500556548
+emod:842740677032405514674303211263314042915529378,8831402402931313770942586028473722467913,682852291371107996249203176454681279672468752353,0:650699316446407153033148645266760437516984688808
+emod:825599814726370563248636889273016715133942454,475680601046386573129475547513603110412899,416247625434559948206627127417433632778118351,0:339574109914067304840079566026200464971617828
+emod:567648490639035833763803769141627245584615838614,50724317254941774744692403469242853096809,41148923802029037929684987081095814446741364,0:20502707948232123804215524099617477740021816
+emod:115087026829239549004467892483132444989997188,4535425742394168264586248943679679529149663,433955044135381795877250546954925503743568344878,0:251660326553696762196196778824084224173978677678
+emod:12036785909772650615373227006202901241216144834,7640930319417728873563211760140268194907,413484971952354004891213262066509431492,0:386239521261870781782143346233879040668
+emod:320557378119349288211730243419102961495,84587343773197883044120518369669143774565,450141050577587452674598657343574939265610,0:231814299231780092365918681959558354516555
+emod:4760513985682144284402040197893582245744274,700922306891278320888270773879393663215011878,508613578824050038059978191899173905936352067,0:226155180059930658457926847583608180369805551
+emod:-1986722625420716592016545661236480979772,6587808211180976790034063002169935351319078136,248018664573312581284613240553608321163,0:47757498985820966232985385469724481611
+emod:878958607745362254467126051915110114983,76503615843648834046772312529145734419,599816542297740804095006213529020435923894574,0:250411227594713677669720417184781499038401385
+emod:842403714056568268363014451655139215576923530245,882962407685597232301145770370705099374,82560775215139790378071910956865546821689,0:16330945270987575660257305978980256916947
+emod:34552684591792222791353473595987201905919750508,212190283105668244835487282221966055090390808214,911560266007572327824644939132754269623196,0:375847062861355613267496115505135609589744
+emod:-255595855064966654171339977100486303810714342893,6536377115945497812146512349336490454281691,2358447779128139560919507162522654854246713,0:464809906345666089854305504087451343505919
+emod:18482506274556543305894610082680844279454,209945312016600815281820143389332478519181,699102020350956658786203685996030350661513312761,0:72242030557111920456295390210910475158413094888
+emod:6415210528618065990871168801815200139332991888,597649022838328236100124856044642774484278,7231830016713662975924622826283198323690910,0:4006117305107713700741948795422083910788724
+emod:6064555073982428831750221623690023330296876,92735364529176955551691773164814148521984,57696657922579845113546414118019201058924665,0:6870916878745310102921277390541323644461026
+emod:9386717595978609521086313430321645886736486585691,1936977561716961194789196774828364291100085,308710514484691606827023276042134027471318,0:55355445075743293412821307947169157597655
+emod:853095304936028332312865139673151355180032547,402516533127912932547366145735034332969264851347,3612211333648128600921169717824883676314264487,0:1447874577344295276390988945761876053311260753
+emod:61856527307782794639480931649487570761759,981353953577921813238706114977389364158181496476,2875727585132422327960555829952850177070241,0:501562823449987389919037987877783485624875
+emod:-3267284769511763375166288313542521834448737,75871983689910147433442901613935364192726737,598080070299105299737322321312252319973858,0:412778730998143883082550011380441775883929
+emod:405422539092856845025942882047354831627260512213,1337913948299733086787799108945523111815394227,36305189460456946509918912104812255759867575,0:30995366858217213552892783895317137044496967
+emod:6960366366888598610646870748629752920549287367,39434037540809306957325491962655662351828,3736135718526702463297936582263494485512861834479,0:2992479585704247653816936018623391133511705239998
+emod:-1826866256845184317995843519306378742885,6087838149038632125552666538607155530202455862,3505196452565303635830882879536478893015661284510,0:2876258092163187750168292253816666759927848105405
+emod:-30453880527433344036376413763327782174850922,958106051241874716971554801010144468715392785302,83704796154657119123303823148452214065244,0:12172291368658411466771610032308050809112
+emod:-356428887897712690551027940776016664193551,974311528436818547612106283639362895440535373,4175822946282741428795690626208558273399181,0:2217100635742324748464089855768646097870944
+emod:15887850640158985382379829997884660521441664,3279446731722646638040158087688724381294988413421,52724586555424276758984551014477985909146482,0:35842723031112195508473058690940883109069966
+emod:-2754358773916450393380020466377500694537892748,6693196828758606502929005505195902945008422,81987501340134124186844933306300364101202601696,0:64957670918930713389913976423032686263311873504
+emod:64795655511571826535953650784879339331120906280,201781316213631005455227216755502850172048,9183404199411504412156373561368468657063847925055,0:2917132830074900548165772586526792013580435602635
+emod:322376591049977138697730895670752146989338805,223962315373891826478293010620538065565321,134425497979583765111585462044979782868043951339,0:12680763077525899140335801175036995248897549410
+emod:7378293498837163030108494500023638035245941999,2701192105797571727239301264973963904903943488,61103840672560006595434005526860223512609429784,0:10575104110432808219323836371535482428895151433
+emod:6586150511971850295907641345124913235499024397884,25513878140895710942385809529884547574325,402623421320542043817163858150135923312140690478,0:212703145455744928999402867801599663279882403300
+emod:1148513813380533679268801317870273567836422766,78264425883354201492861909224929965803589851,888529022913756404039252857597221260693723470,0:344612069767725463911981963977120251304004566
+emod:156897858936863936558762112272942619182648359,5998398850499440904999529048665563755755197719,4114314816923307068086587017590920904175696,0:2365605906155718722370615329402928970075415
+emod:87182346175010426980309825602413855400180387897,6881708075476719061473118229291803541629550,874317437435696504884100729090652126764764928199,0:358356267780280626874735799972579854632076151004
+emod:911804580943517196035138307824767637716096,51910018818079388343993224114362468044260,755719409656106996416099738309867560127420,0:619648429452324074929397811402394241260156
+emod:7907371058268574577015600989784286442091497358826,51384490845283761025532093399709612887400222268,714932241344452067231089183566607442645499,0:39652714695362677793061396306809603985720
+emod:74152151887141438565558836677120157654525413725,3865673216281651353443515507748331062737635617119,39515541452736626357498604574956947118936,0:3348164210948022420110568984992044206893
+emod:1921212600092818926909753666688437613889202174324,15126673218216417698630762186472446617543479982,1513247907205025148358918017400696573029502,0:47771732582221332296766778100437627607854
+emod:62177741738385906366557378447871109683100,42062431220303473355860970126711938425550656184,773958434020341693602047125826174529582651,0:442082897911401536767776238214849664334966
+emod:-1806808081053455087879198258615146551580359661,44724668030512207581826980240922859464701,5189597819742605059176771398730210738088315756312,0:4809675330086812178815566854450153052638869156587
+emod:139380296373533535850169111091445251133031553,5568131554680055330705039219787143467175996,518185013729942602529965143602253217637466,0:193773139480058911982453569250459620737303
+emod:974121940443001500503304094214484700334099,728467767024352630604669587731875660396330,44674919076720204028296797718736637414521026104,0:21438174710368725104589700570479560530599609609
+emod:-527405333948184200720039219764919299319468854,635924082359258060601853893045398322160190689738,947819620520708699044943964793321010513297329179858,0:342816230736644110664562034099738209027304408209052
+emod:4964014414366266067601563988433897971039777,972491441089677662999190229721797813272801,938609136796638825673168709652895939249020,0:757905229497791954404463471617284756626357
+emod:-3836548959134851265232468756686852887039589263025,91958638726161076829164170565310939352504345492,9842518325582477123987885320987474902828056396473,0:1785937883725230279579795187739041151659042418262
+emod:362003077050650651287331998851003608874005730075,7224278456794231058200539570034490392355119609450,686491790315346927921146778571888891553496,0:316447529525677730606205777277031419657281
+emod:511417748058568151891786589987253660165796727,8094482124265898686460762144280960033447161606040,186381274246323455788720228571054777422314708850,0:45279922457870097101374197162961699877223826551
+emod:81264000690609604351458160311340827489802109902,391885387725085278459091170640814114585520,862357107879749607217822835234106152392133001671034,0:589199761114611925556876493283500689288324693424922
+emod:60467632250983508695725501646784109879778908745114,837672302787514343932615418244003255566590288,469196685288767236431865642803573408203650783,0:47351563702942679095591216340308509524717890
+emod:-459476727597478328887650694792354077730065535006,6551100280420641334568069542701824749257357,44015235164158274406848669553614570342982958461378,0:28017796628275197434019563629223716729911088938710
+emod:895843043275999934611988163188471273684218111033342,7246774352032830692528490542295484830970866278,861847510016050471694148161127317335094105768,0:654035466899277641878411664189821364246515408
+emod:286589462111588691084089929906408043383921020101,9692415030522370188366193590872225386635917218031,719298087261564603655693066504254890048009456875,0:427302318670364247525213648717424428327518555601
+emod:676436471530083898997041363054013845405132592805,9826535789561484874848870984693688846169671622,81123191412086856575942178138898627611978864,0:58559446218187016378111352068475314798576601
+emod:82851204887068882391372029299659256702159316,172869110320082328384071354204393838581736,67056444908658930881509973314864718767829541458,0:19106724465380212672652647774912584474721840748
+emod:696109009687864457810113686337232495156421183,3401811110841371494776087049474111559799131700,4299920714282089106120610636935635090268618368,0:2020511812293185382323106458123683937285282817
+emod:642181116705547745922861595409305314439788715713,3191544116958009442265013426506709691563847359096,11503959864174296512003111411775254312499675635074,0:4542807727654055188419122200833174452933393471703
+emod:-43473592792665227303659232677180275856179335420193,367337932661391050359451420336432743104912012849579,40336899717936194492442741600463146885238391884,0:33883445452210304367843379593615127696274144511
+emod:149677082879100259644810248166250018278560400684397,67835958963093533534750484479612188112600772232,2417319759617452658480101694897700221629257,0:413114555403103000658332346965315753541371
+emod:4308690827834618796779071688055990154958119217979550,8139792103252594022614523084666149717083186251,15533037471757153506550580840055923919409189,0:7020715664515618963916470331313209937794066
+emod:4607793512504764431422636985189117330151450,5810855517430042248184284609190428320492582797693,254077145071398684004350471347456740109867649920,0:249414146109210156171911011976187568245339994880
+emod:75015031620454344801239233353680150096201722256401,4993964830386180911249138189300268494685186990942,4241132252523512745096917242615525253291052986,0:433337045531299838053635884507298069666061467
+emod:44960897309673530453555266827045004683193626,9864385579695978005342342313046773936648945269556,64756470723619643596096247881962254980723676611,0:49116998830009971503948732099380336099106902368
+emod:824638657497552691308275418547421010797730757488,7102337564045908912215659769896546075594806,7549559927659163526633926834915307075816410605,0:431856052905253153141408472781012880375756789
+emod:-8258821865451861122164335490949730530149357550,91240131099914556769212391842754945963419588729545,608091538039563385874042418452351103116377287,0:138416095708955483721209050087621590198128350
+emod:6918006637544381236582913953764444433570928,142116742659743263417878030971625713139395825277,42465778998553599048069556979313575711603846192266,0:21075269211617428685041608731276059490981153877082
+emod:22864575309091005999606038194627722799352002613109,896391086004059443203372771274754832310503484093,891750130247908667659048761409012710669636399491,0:291616836488219220269230095553451995714008687531
+emod:-8194888032441259199630599625358473476489205,5233704072524169370158667063506533972281083980647,1489037233721004711195744120696209782731350261503,0:552028516294652365815212711109824092516937002021
+emod:402772636759093114336215386282519687390989479435779,189516067274441373930013687419363508463761721803660,80415811227458788175575610653906545982219330975,0:22728298548876566392049076077182437096372400601
+emod:25478733323871259877912385362343090774624815,7071155968374703054163176660383261326011527019503126,6134327557381540088147721199406548730558126028,0:1024740410140626130936532360899124497564707733
+emod:1373842982649207730088589912059387373550201,5632296300635658701077632379614186637591919259,15391327625104216613547146396703256586018696280834,0:4302181480010047578962481977259846491527280155375
+emod:9495802289929888822634017883238054795580349,5002682765682429592404202303916871057826935,15884650860342620721715065457253891894018967206,0:8941067791071558272472337248264693834973616755
+emod:31600516776786509284343708819765575234628755,228791299265655690472626502236069938161188391,40936664868340332393928739047239776545553829753710,0:30627744149685105327689441848075123499867991131765
+emod:38524550306915104068946046715826855759569613774844658,9194419836976281683587306717261558747169442193954208,7779595009435858929206493144805114063764499766215590,0:7087991661129889057406934247049530530993451959597276
+emod:554411708679558039842538802463328992263904679,6237197282110482695552284318126536429504723341,10950325577001918036371982331444541813617574475194180,0:5787600514717071948035385347363174161644959891539359
+emod:-65036555989091136374058985938454117449763159,34831798653870828072406297626104961773750661,31676515243089740330950585861176809143792092,0:30732949823978690229767791353264924799202285
+emod:519484888832782036702272050651904638826888669,753074873494165067376985336730357180001686201437,26162868641248965913351015420400997201482504702269,0:18484433084399526415475352405874231763303729896278
+emod:486622002393256987329857884862358772922652299948862,5397488133084406712845993173123874999792355443180,52221363514636645344562494690476680459663806696245,0:31424877006247871341476564009060753196816273746886
+emod:2519545249333346583863745851735514920346268018,5762304897220756179596577719327585953058564086,25968687826793482314025869361353695830319122017723364,0:11446923482269709284929175954873487230221266306098484
+emod:25181558468391709065005750569128856213137442801,17395204260174949840937998424068393371443165843074,5405603350542397445284851120217561963941561607,0:4017170326519248316993458817903116669933612061
+emod:407900825111562209157049195681691242826792800,267987715516648071532918817255425280495590423956301,68776425368933157858220727119994638551746175,0:47031090204538290387899250133897480746869275
+emod:-98803819636216862704666508079523455809956165947,98671412267375938209192375718233476934668297,55621612703501672327703967617091220387319483168426,0:32713255624638051486342207442183163021264516435649
+emod:3699193512054702576853653403075240437897079123,8717079191539632537960810302588868157436232036,48522242477672943422659170492335520141870413,0:8651476435014431039453023117472444582400514
+emod:77936539433974741743578486606140093995870301132423,954499217422932957346614451159347140560185480521281,163215414633308466314077081093001860212713379,0:103758294538389867607040992307260424637536023
+emod:-4028502338091434385570286181712320072468742558,96989036369391542800442739082061530586823254263116116,78068537791270178387717266347434743278287908,0:21669953939490893566721670542161427811188984
+emod:918884247467748036366436587703999780118117975546957,5615852005546776682559779744353394064478095142,2401794658690427064436304716694865657554211766,0:960515354911580091015228026871019794883284885
+emod:9780239941823826659833679733394177755526189646937,89322777323067153562491076481435606732771405285,29157211787311713009469704820603173835586448915,0:21784603970310613711389261139944185838629281707
+emod:96098774697583148524351932903096795874200556392,6980912905868697403003059554264649562235986501752363,208924194204367947369626074783038546699206285520,0:79697661577989072841423526677085730430307916048
+emod:-573991994177224613634480756482666353761100288807,7158287307293331130042236674166424104745547165,9922520662865454426464919345018943051389988697,0:5619512846811035521678742038957891764003573958
+emod:59911103774024380942223423632168855379630335,6818486079655068602807082064093124643116770724,8864024398516747656055508658685364700493232356531142,0:2383722465709179243642856098503264547092886596175227
+emod:-62313348406991266015553975744856571685314477634,21991981158838978996770304861386400122523958836,954507703567266334987920599572200024950117776,0:673874525887635950319127294209157951664603712
+emod:9820087452416196217911209095780565350316442900,148320444363560053307036007569156568389928195017362253,3631113047524475643723456921191780561936707959783575,0:1549830330276375593962772767912210881310119448216925
+emod:-25798647424975836057412872830909832741720494281462,9299188364970643235457620086027788049113237501724,522064657371945322423320375992281138757129069042588001,0:314662317723871224913513394778330419886523487691115165
+emod:930783335744991271355677086538660736067905998974646378,776787459928168870257234381028892429138274839820310577,3676898834201974197391604163986622259912692963,0:1454707990857958111219870293206602713503203390
+emod:754324807048657228679765605878761298609690360511998,958586904489606201890927436646020906824192582152,225179126294857543684132265900588355218787359997532,0:184341533271280210707350262029004357506956964249100
+emod:-4277241617014152774634908150956976406225721463619,740666737188827503974760746294458696679071963170918433,84911564006449909724569329147240459921838626102161,0:32837984989291416730559017868100153859989248628941
+emod:7690914272601666512634428163546937580730709939602,14197296902658248167889786104196831416278344312144,81931815436335281188537823089415033249544638767808135,0:3199600947635353412828955610370257711774177287067436
+emod:40693757858681089447717885993659911215985324585652278,39136056473317073147714521234945625238580560862152494,56180103978500893124049541126696155778770577135,0:35530182604079785705672771377947698867955134584
+emod:-61262007457380831475587401250265303407703358053,5605602757602617615751362780250832755031303714,39786650424951253014286369945896326084999234541,0:30624920045735321607213022533773280830319909832
+emod:-8294197985009320613004835515579701550690472035947,27497176409134737028455478387441759659126437088890626,878254584167789416959102500401944397284939932959,0:96787593049516460622263353747535019044011554347
+emod:936948855951886126122485690093336688820905438,952037324756179560869502130218077067074192084922,33269225773280332072695417422958575761899978253499,0:31343729843026164021419525495602740164653732233547
+emod:1825784156631469036083553494921853600892959329084,1792152855908535702866815908479066064573203506328,7584434492468684030603996404862850988077230764966,0:5668645854080378677534840608739670840420553612804
+emod:4771542980687362499528587321796090255401127670935,49673918430106064176014347389103358990211599558,566808710453386184370243734899518529679284370157755,0:122614051205229170899163057352055351000892027836640
+emod:1823975371238131949336117473697450176001493124551422412,105862300137903514746181350899950234467623927399,872150475093096064129104506408316916638215646399,0:41655575950454700889468004661814966001328043635
+emod:-7403599133408228298723066626194976743023770563,8091134022905952963104699681073539225469153697858,5425355350845048150843160638835947264066541393,0:2741144821308534612335116015287775234294403710
+emod:890646208254935784836741265729061048252488750371261965,3014682556575993233966766524815533447095651265,546627202244553599303777629347742865125211029412308759,0:129189292373035871943643466963326800150883513587943803
+emod:-478301676028477872037215528133488673909770705969021,4776644958028138697511933491453433971900379293,9804006501217419003156374248597140990532373604359741200,0:4256526039075877642788870040517474793472829088151023139
+emod:-2685385133378038265400322588836701680595103090,6682051156600485359090971175835317671334686963274670,272381294217617274132435187599076952898337370816,0:160448248258559406045792992578310861095674214848
+emod:5610352369978196066557531911583288845257728872885,29105174820600183606830671874489670474983812495,10153364462051971143078318734983556641603678006,0:5654495476089063930689151404880397736789807021
+emod:226106902099977963681448571570521911815066120995317231,1707966440323110108128795246285372866871484571190343733,3022313205119289698061840897980713840817653246137,0:1577789001757918961027109729382551177312942381192
+emod:56994398320188483459448108143592444430607410910,776571171150667113541269029583357392475898590899457,2952252481199115860737553986433506978840458215941629739,0:2115048663787786340261444189400738968421587522302410834
+emod:3490308621678382172799094687550532898406999135779394,92096452137945096831873480789275081374251295752,41859985473397465016337344479699193310470254681186836,0:13883201384282345984019723588819996850955384028405568
+emod:78199345624452323665538899878571977010103711120353586,426889339090868016603770192089391858795483010444,614591398724869622540933622810612317245462099,0:522221021562810412369119229465715299116874680
+emod:24494234546606769948911248691757492347200292227140712,737664088655731527937609365429682453415687199299030,41867909567513789892657868211831771169136305959589936,0:29639257666757184257116019424419930205524205997421488
+emod:56340168172071966259164709446976804762407806722929085,9330607041404161548877129661058575432184418559,9073094112420733297526890865499708444478527878927152123,0:154033683820095649526112863414229406070106242714564017
+emod:-98557586380727162991959870302640551435620563142855,352179144624443366108174660913068150097236769961283,82957931261705630469780521065649609232909069967906297,0:4611469772581670990273871321012941407812443591119341
+emod:-327557046252127633720556940076118229316928253056031837,87561673782562800570041955183322599955629735731,999914991747113895498838412296608587151797268932915993,0:394844471425716300825167828282861382716619299699558452
+emod:62239294453310399816462667483598707872602240932142297,4658914995757017485299221864332093690860930515,2486140058721179216992139245736934931657664228105707838,0:1785631544920858868455392242463320012563257587191303743
+emod:98844248773908427486663349850376500066907267527022459,30192206183400841123051111248262548983869820657370418,68953646632746416359816661196045006942249287619,0:46348894487037788897865804485372390262476609587
+emod:157314584387460613339515315779646913728585159983563958,7129487243609251992087268468464230874147780513130629,7635331003686312032946464576006029771208342239,0:4241581628875360523816771058381935521234659115
+emod:-20413864406387948000986404651284225843901612271532247,60570204203293653144874911182227469571265725493933396798,74868812887175685382885501310045723065586089753,0:19048798896908808195904371996264452593501059126
+emod:-9994818638674529038541342163911785506433155975282,2441529131191726286407021656054505236538534218505,868763054397265950319354411340564521520500110285341,0:713646341945805538982296660502179127412919111592110
+emod:89928590797284478729252348706855088798121290869809060,59274533239795541803239071337695221071797917061551,458720998639333601494661224903885165927950415283068,0:238541586391208422370502281952541020478014766570928
+emod:95798368921402497294705740910984389802169456614551866,5780238728300624701546948669191486225967922222,17602545836464476089657116165016615105637757631075883410,0:78935491841772453025866169047063528694493328256027716
+emod:-6285988010245529074539471748460012192454923426879038527,4464035763112866760911458677964807167647554031374417,557426143112327094606990154681823173588434990737834515,0:492308894761273719919857937651384253941194670007301468
+emod:9216609859426876786581364775917107940830826147193,2584656223509851604195298909793029088361431700609487947,97854661860659618908160182622420008085466240143877617,0:85437882709473882823892529660893798801236147303713473
+emod:9369310120459129777778887291797647697234777683432051,29114272244461903760267994837317966967186291374,9778907141259037429006274419046033685045015909549812,0:6158258816758612931552439105354775382106793792840429
+emod:121095461268256661739120249224368430821121813080,24216928007688542369493467184086532629768906571974067315,1289101505296127733900239534120001726302383453437972,0:559264053276767206654909871928116713399654543670428
+emod:182013722639261555865084991953687573500429962535766,5312171499532129540711226268300910853763234503893756460,373925090068292154121977949608424249047611823254,0:314492433924568960493434943112384754084000516952
+emod:93122409584336684208634425627697110814180323391,14785829877381197130422634393843365096818009069934141,71932199753627287791733451362196318752438103297,0:8651254301747600278741940327234016885952587642
+emod:47314169772357749238033685118725095245857710174326752251,7737526111797627477363360414613284237413174897695810,22636439121232576533369780871442014748582558494258753099,0:13481881160769756096301137118624702877253559402875253449
+emod:40437135697420911841447145598134529938086874417869482,34142834203311856114775566332299272975314691621831451157,61483400000688184187598139984127464523117551228,0:24693895005298972635867796289890449288509340480
+emod:602105062592660782251188458378445123063805101057628877,8347043677742730027972079328186098141974290663352,26831519142227837662521069711039879610686983918942079815,0:19346421778661788162968173970766981230660937987122859431
+emod:-631401827295443763663013499197680737231639584989,4430590554183773954781048837898216988481838421600006676,2298393896534361874746279427962482679705626081354993,0:902945851002567106949268418213474969113107638762554
+emod:27786418359632188385534950865019584947593363685667,98296086104810263777729111156693306399745439517905843246,885588959591327389647962772187472088293854582596501585,0:219691806105674835153486211154061118027834335467768059
+emod:544755872510174513208896610649845089424204895203973,87613019793007744065404211674234696040702876770839324,4802706142382015625537025588688720114067633075179938214,0:4385825975408070392248170302791202812902625274088936755
+emod:266945202318091617395513307631280644325314217797596447,327566429748960361523726509719626329764280050772,11519336904029441280173947176416866297494364467208,0:9214541334269337101551342582484701318239260425185
+emod:462274575377872280232466472100106379919338255223,55208106570738920386188352962242729542845793547908872955,394947463398055276743090558014108833519958843326036,0:14090943624401742126636618168767136948067183397671
+emod:498588690178207860433541173652626793819053542771822736281,7320383073654496423015034860141911017275032239632,864143543362782361157239005190574446540608427530,0:405837700105174778010475141584205874050426805841
+emod:9889983273673267055836467894511050393862566401427167421,9249465646754817541871880579390030265752574382697001,25959701663622988366438447815418575609294742760915,0:14146692686195759173905915586727366427907029148496
+emod:8977490701791885156174343111351369788045969359197758,310958534312954656622864682281335777958703646747002872696,174885990030766375557335981487351371779234545791,0:172268700100468974308770735824988553302287984097
+emod:75891699691571906472460353214537778119193566652164258472,75642710398299172975011498854625838470353049691991252,955726338299637204220414390179262210175010011084260057,0:871551220400711242628454200406202564111664531240532043
+emod:817687870329204460156610156013195890028396416937162234,71199838789107588122529185516473983414598608665610,9797217400749418393402581106919553154845468700907872,0:9732835751266971971517518815617086242024182057719936
+emod:656535389260219421975691249279051158130957449883966,9965820125071850776397934471591602941345422709213,7172697024967323900460450488928712811727935935053426,0:952029660753929926293707648671191250800460252928490
+emod:66765940995445083043566397231259337861214788967954,698949221229345492777837382914330269944860925101870058401,370977162689246158196783733149906357225503977003,0:56780810013712823080333031377883978714594923759
+emod:-24860118467430048016063231699711679455683726879672563278,546329058333516554426292196577372643895447816095329334984,102083942512514956911062347152596366057306100868,0:89329427941719016468252169448693561927858667460
+emod:518281434431704435940150792966272899127164218411,19290830216216089485046976601623655817078004660590796816,216069676358948655463888215158143195786697578360538582,0:86506166688482117996142986160440612354876384284094157
+emod:517542901438648396791987658999334820221431246981278,4954735021213009892606598900462212813613793939697004110,5546708620630276172568015746256008412046274679011721163,0:114558840275328029858937724196533085168759209383758948
+emod:97796431105417086121597265848245224080646880891314620699,3566309852926516051758561425477409449674731444065,4237358411463841472327670289343773756088420869185382928335,0:1728379035119996080675313770460691892171354788520339293899
+emod:8797217794906750966627546899905389746578400755524,87461473070045326370501974269638901791524473673607812671,63579576817694957532492907897275166360331019259167287988,0:10068755237067361214693799084814132014570304060924282180
+emod:3559874918456198560844107856956492116344121248206,45190612746644425408414684724540657030439304479324039,684772758312255825130987448842421703263477856778082,0:500105229544177258096786497048655528691069662344352
+emod:244693542815021761876325478432698673186866834942911366704,569049151750280294347914587638406693043104703456596078,40418336644392592645116495825339904699620388961770,0:29946736018608816763137681085572521922498414649586
+emod:9552030352913538449959248911819718532447389423411634,15303289522386175735929093158193781525599040386989921,17905297851878021472325954407339512702437837940804355,0:7227207308763570886905006773221274115571235787935329
+emod:2427953611523095508885901603899411553216124564768970531,84219397598182701873267938504642229898519369455120690652,5124565221346746692094768907421280792680721722663049,0:2356962294194965054880021165404451023189256523983359
+emod:4450272023458109693579519823508011943468990250887770429477,9852180148050086854797451708622242708750405652182828950510,53218591961090046740426308696077544888041718958796756705,0:20722361228858746975332642022116538507546307084688876639
+emod:-3004436507840212393446088399233355090512633931853,49762352101558708510764823100128412949214842904414503,62339832791097134323794421391092834208651832053582621969,0:18644587060060960018044094951299852000053162441627275349
+emod:88466522329785151709268834138668446416231472463853002,84423940822580221018912007091908955924620089965579353300,4272746558814012659752446371362908792507498696285890777,0:2076687497522815194513922920413442770240123518700437310
+emod:-452137704321173773725358540484655780134513962685597,108536825158896375705138771152627679486775845056880757255,7443505375179903958445129175383134980666720252160978,0:2626655033625685458909447520232601675412626580083149
+emod:3646226144731352080332815382512112527325988973642,736730185733372156433101295886081895604485817722725,187559548105706428460460100309284194685793795827962,0:153703862976742792640135721867824635074042235940792
+emod:7128578973288696116455318246508827884395148700024035843,120044617176238734085406385417402387651027645325661,437777976047468143063879147080739099513994845762621846093,0:383512808517870785600076597930828756369001886406596109329
+emod:92651404329219142594991415600374429189694983250618442,1831956594370082650320589803647600704949512437508530740,989079198090857685320779737579388665165981389775724354,0:429473741854566274661236706264645428539362137664132958
+emod:783048980600864030214223520282343154949582263988130988029,5640798680918146067495300825091961866365823288705,712576055151408429943237184396668347415006718010549447,0:132303576760619346367560792334725765196706066347238184
+emod:54419766013288244584593400647946050509291116271357,37442044497849759156397618484039469808263267657304,55409955411797081810766022756739065410388681698701498,0:625989815794948434601895148375843191288774735399931
+
+# Regression for overflow bug
+emod:#x02,#x6FDD97BC0A760282D5A180D2308BE3B075BB6456F26B1DD0BEB2C1B0F880CF2C8EB724F2AD0567F7899D9A980C7DB93E418ED09AA3E35357F4F2E05963CB636A0C91B1BC7A000ADAC40F332D6ACCF4A3285112EDBAA95BB27904794ACC8D6FF188E2B04888ABFB11665BD1D915DEC8C6575706067AF3F7179BA57D1465D78129,#xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF,0:#xD2C80DADBC0C72DBAC45F380064FDC5FECEEED268C7E86368DFC436908B2D33426C67DFAFAA56FAE89722EAE3644270B0512BE69DE61FDE07585001B5EA4FFDA1B8B98393D657E2EC4073CE4A6953093EF7C3B130CE1BB316C97CAAA88F83C32575D6E1128E107BF66910AAD2B84C44128370DEACFE7EC8A98B2CEA4DB7B09F1
+
+# Jacob Refstrup reported this failed in 1.11.
+emod:2,#x10001,#xa6aabe38d013970f47a8751ba8b3a2d20b6cfb1be2f63d7c36067957eaca627750d9fc9b03ef2503fe73d8209099752070a15c40d481c71c014731f580fd905db763434f999ee24b0fd4b5f304948181555531e5c058a8574023602191f3679cf350ef9cacfd883b4ab466e2ea10e661f20e06347995b8a751aa9c17c0cc18d495d4140fcc9917cea0506352ed4bd505b626d6803c0769cf88eb7b3a15419e38b81a1ecb6e3695f8e1f3ef7a72afc40a26787f3feeedb1da6715771462e783c04b20804c4228e7bf2d647f2b745f64295006f2b8aec12dc96eaf720fc7d5b220c465664b95ebbb4efd67cb65b73d0556ee10a7d103d25c9da5fe2a757b193b53,0:#xa53fda84e114af74cff65ac6367f2d45a7a0bce93a0b837ffa48d1187fa7f48a87e543aee994bfd1837ce5c72dfa26ae45b1179e486d9f242fe0efd942b0e210edd0b34b870128165035931db003c5158e5104d7f220eb682a6a7878af64e88908a8969e65b827c1d212f911deedd62322df956766b42d284d7fe88f79821bf1c0f70b6fa657faf6eb8ead181539c80c1a13e9efa7890f4e63efcecfa32b4e1211bbdffcd6a945a04ac46f9888f7d7a6d182a0f1abe5aa2b1319d0cdf03074fe20b45a2f58daf4603b63ea35c2ec395c51e3b85b10f91cf85f1909788d6a5603ad7738eaec0a7d393e3b31477710adaf98662113fd349d34103aacb05f42849a
diff --git a/polly/lib/External/isl/imath/tests/emodv.t b/polly/lib/External/isl/imath/tests/emodv.t
new file mode 100644
index 00000000000..4600a31feef
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/emodv.t
@@ -0,0 +1,305 @@
+# Modular exponentiation tests with small exponents
+
+emodev:19,2,84,0:25
+emodev:19,2,84,=1:25
+emodev:19,2,84,=3:25
+emodev:92,693930,16,0:0
+emodev:92,693930,16,=1:0
+emodev:92,693930,16,=3:0
+emodev:522181,0,166284,0:1
+emodev:522181,0,166284,=1:1
+emodev:522181,0,166284,=3:1
+emodev:437824,312,93008,0:26544
+emodev:437824,312,93008,=1:26544
+emodev:437824,312,93008,=3:26544
+emodev:5705223363,2,3286325576,0:818318913
+emodev:5705223363,2,3286325576,=1:818318913
+emodev:5705223363,2,3286325576,=3:818318913
+emodev:6399553325,6,4107014863,0:3307178134
+emodev:6399553325,6,4107014863,=1:3307178134
+emodev:6399553325,6,4107014863,=3:3307178134
+emodev:29074823374249,77004,71683909277697,0:8940258342532
+emodev:29074823374249,77004,71683909277697,=1:8940258342532
+emodev:29074823374249,77004,71683909277697,=3:8940258342532
+emodev:78759078367890,8335,72115845746903,0:20414099940189
+emodev:78759078367890,8335,72115845746903,=1:20414099940189
+emodev:78759078367890,8335,72115845746903,=3:20414099940189
+emodev:-702894953466773316,312561,665754485123402827,0:84548134549060215
+emodev:-702894953466773316,312561,665754485123402827,=1:84548134549060215
+emodev:-702894953466773316,312561,665754485123402827,=3:84548134549060215
+emodev:162476353576735207,8451,299565526093115255,0:235405725752406313
+emodev:162476353576735207,8451,299565526093115255,=1:235405725752406313
+emodev:162476353576735207,8451,299565526093115255,=3:235405725752406313
+emodev:5569622159977645154297,902159,339048673939289293353,0:314927034088061888405
+emodev:5569622159977645154297,902159,339048673939289293353,=1:314927034088061888405
+emodev:5569622159977645154297,902159,339048673939289293353,=3:314927034088061888405
+emodev:6991839486419148755508,2553,530292436823694624357,0:4272543854207020971
+emodev:6991839486419148755508,2553,530292436823694624357,=1:4272543854207020971
+emodev:6991839486419148755508,2553,530292436823694624357,=3:4272543854207020971
+emodev:84643040276670536818634785,63,64928874055124010543482048,0:22546118193382720472157537
+emodev:84643040276670536818634785,63,64928874055124010543482048,=1:22546118193382720472157537
+emodev:84643040276670536818634785,63,64928874055124010543482048,=3:22546118193382720472157537
+emodev:-99555590330388726236230755,0,62041543621233726359336122,0:1
+emodev:-99555590330388726236230755,0,62041543621233726359336122,=1:1
+emodev:-99555590330388726236230755,0,62041543621233726359336122,=3:1
+emodev:700943089540446737340421223177,8456,835694701023829355087294263155,0:258410405038140346743628562611
+emodev:700943089540446737340421223177,8456,835694701023829355087294263155,=1:258410405038140346743628562611
+emodev:700943089540446737340421223177,8456,835694701023829355087294263155,=3:258410405038140346743628562611
+emodev:5473388626149338730799075406,729,850132294968984927109971586336,0:685051590046393947084559076736
+emodev:5473388626149338730799075406,729,850132294968984927109971586336,=1:685051590046393947084559076736
+emodev:5473388626149338730799075406,729,850132294968984927109971586336,=3:685051590046393947084559076736
+emodev:7542606175762975785023215555039217,0,1451486096670046812323372237867852,0:1
+emodev:7542606175762975785023215555039217,0,1451486096670046812323372237867852,=1:1
+emodev:7542606175762975785023215555039217,0,1451486096670046812323372237867852,=3:1
+emodev:-3426829035080908738042076334435395,0,2616360606577002719669450329100985,0:1
+emodev:-3426829035080908738042076334435395,0,2616360606577002719669450329100985,=1:1
+emodev:-3426829035080908738042076334435395,0,2616360606577002719669450329100985,=3:1
+emodev:5871172260267735917150171255408367076,88202,31506806059671945544343675240909419388,0:9882411358511873694991988201288706348
+emodev:5871172260267735917150171255408367076,88202,31506806059671945544343675240909419388,=1:9882411358511873694991988201288706348
+emodev:5871172260267735917150171255408367076,88202,31506806059671945544343675240909419388,=3:9882411358511873694991988201288706348
+emodev:14045780235333982097410791452776449214,6,63567135751970741787875276189593310474,0:34130827114620482312672610863840969228
+emodev:14045780235333982097410791452776449214,6,63567135751970741787875276189593310474,=1:34130827114620482312672610863840969228
+emodev:14045780235333982097410791452776449214,6,63567135751970741787875276189593310474,=3:34130827114620482312672610863840969228
+emodev:719958253183871430502261490413450673851124,9,661851369887131891462493813741667459688172,0:326930997921634036854135001452458647807696
+emodev:719958253183871430502261490413450673851124,9,661851369887131891462493813741667459688172,=1:326930997921634036854135001452458647807696
+emodev:719958253183871430502261490413450673851124,9,661851369887131891462493813741667459688172,=3:326930997921634036854135001452458647807696
+emodev:443624238294320571664949666413150109110287,6385,784303120899228089361406308796439491202242,0:342407852738883656584329996186795949032601
+emodev:443624238294320571664949666413150109110287,6385,784303120899228089361406308796439491202242,=1:342407852738883656584329996186795949032601
+emodev:443624238294320571664949666413150109110287,6385,784303120899228089361406308796439491202242,=3:342407852738883656584329996186795949032601
+emodev:1136928015233318011144243860597237613050611024,0,2789921991289922378761307428111094457098264457,0:1
+emodev:1136928015233318011144243860597237613050611024,0,2789921991289922378761307428111094457098264457,=1:1
+emodev:1136928015233318011144243860597237613050611024,0,2789921991289922378761307428111094457098264457,=3:1
+emodev:1450999454447652679327105307881736952333784073,77034,7671829281860481025428743103260720025399298938,0:4381187915548158452304254783248892025314678287
+emodev:1450999454447652679327105307881736952333784073,77034,7671829281860481025428743103260720025399298938,=1:4381187915548158452304254783248892025314678287
+emodev:1450999454447652679327105307881736952333784073,77034,7671829281860481025428743103260720025399298938,=3:4381187915548158452304254783248892025314678287
+emodev:-28809270937368266475212144802642236424417695707616,6078,19637146108400624623087855337736820815095169248114,0:6346379403436405925654497852274419173995099516658
+emodev:-28809270937368266475212144802642236424417695707616,6078,19637146108400624623087855337736820815095169248114,=1:6346379403436405925654497852274419173995099516658
+emodev:-28809270937368266475212144802642236424417695707616,6078,19637146108400624623087855337736820815095169248114,=3:6346379403436405925654497852274419173995099516658
+emodev:54802263149810015499242805866671806182669824281823,700,42916710160715229320560332911086106093153060357460,0:13057328573793336952133919465279513927703000293901
+emodev:54802263149810015499242805866671806182669824281823,700,42916710160715229320560332911086106093153060357460,=1:13057328573793336952133919465279513927703000293901
+emodev:54802263149810015499242805866671806182669824281823,700,42916710160715229320560332911086106093153060357460,=3:13057328573793336952133919465279513927703000293901
+emodev:-87262479450738832647843497026325034137115145947284500,0,72160898603477481125780254532680608704164997261749601,0:1
+emodev:-87262479450738832647843497026325034137115145947284500,0,72160898603477481125780254532680608704164997261749601,=1:1
+emodev:-87262479450738832647843497026325034137115145947284500,0,72160898603477481125780254532680608704164997261749601,=3:1
+emodev:100642928524030186658056860132922920804055208139127600,5714,414432667835794981195051773905850760614924210968557995,0:389354308493629553310648689336990724529053681122415475
+emodev:100642928524030186658056860132922920804055208139127600,5714,414432667835794981195051773905850760614924210968557995,=1:389354308493629553310648689336990724529053681122415475
+emodev:100642928524030186658056860132922920804055208139127600,5714,414432667835794981195051773905850760614924210968557995,=3:389354308493629553310648689336990724529053681122415475
+emodev:-9286825595306463634635411645143516399569604439462159992606,8,7606404471200704416983974125320849350185211717364432008507,0:7552810691207713503035685321335559561108880936575121774165
+emodev:-9286825595306463634635411645143516399569604439462159992606,8,7606404471200704416983974125320849350185211717364432008507,=1:7552810691207713503035685321335559561108880936575121774165
+emodev:-9286825595306463634635411645143516399569604439462159992606,8,7606404471200704416983974125320849350185211717364432008507,=3:7552810691207713503035685321335559561108880936575121774165
+emodev:3436239558982298112600646182085281977389588789170709040954,0,522233930076758999159392228622915543027930093543196382148,0:1
+emodev:3436239558982298112600646182085281977389588789170709040954,0,522233930076758999159392228622915543027930093543196382148,=1:1
+emodev:3436239558982298112600646182085281977389588789170709040954,0,522233930076758999159392228622915543027930093543196382148,=3:1
+emodev:98605572113921015570731666917408019243503426904818325007415747,66771,63600959482143388817643210552729171226910500110519779197352540,0:20785847662807375106647030150336411392148138353164443936289703
+emodev:98605572113921015570731666917408019243503426904818325007415747,66771,63600959482143388817643210552729171226910500110519779197352540,=1:20785847662807375106647030150336411392148138353164443936289703
+emodev:98605572113921015570731666917408019243503426904818325007415747,66771,63600959482143388817643210552729171226910500110519779197352540,=3:20785847662807375106647030150336411392148138353164443936289703
+emodev:-4195218021563262220079054526213885813430895541193263119720318,78,94545015698506343903535130261953470290487760846622612793613368,0:90102715451299572179538269962926144393625103247204607297473248
+emodev:-4195218021563262220079054526213885813430895541193263119720318,78,94545015698506343903535130261953470290487760846622612793613368,=1:90102715451299572179538269962926144393625103247204607297473248
+emodev:-4195218021563262220079054526213885813430895541193263119720318,78,94545015698506343903535130261953470290487760846622612793613368,=3:90102715451299572179538269962926144393625103247204607297473248
+emodev:782779308925261277591849874263374019866668332441496166531362744507,86,593800017785952660786088689171372582380372342941537491408809547120,0:331857206426756526945777967606015729867677745543253114395853770569
+emodev:782779308925261277591849874263374019866668332441496166531362744507,86,593800017785952660786088689171372582380372342941537491408809547120,=1:331857206426756526945777967606015729867677745543253114395853770569
+emodev:782779308925261277591849874263374019866668332441496166531362744507,86,593800017785952660786088689171372582380372342941537491408809547120,=3:331857206426756526945777967606015729867677745543253114395853770569
+emodev:-368107346294563441372147845929799838078404634847778857716085123666,1256,205426227269567020839924454096197301901405255816878779124728620673,0:29070586076917968101851296107557342940225724785154296253334920994
+emodev:-368107346294563441372147845929799838078404634847778857716085123666,1256,205426227269567020839924454096197301901405255816878779124728620673,=1:29070586076917968101851296107557342940225724785154296253334920994
+emodev:-368107346294563441372147845929799838078404634847778857716085123666,1256,205426227269567020839924454096197301901405255816878779124728620673,=3:29070586076917968101851296107557342940225724785154296253334920994
+emodev:-3986212837117931767741913193889401048695278656631180727109492306933238,146,8147531447709512983938379187878961602041163459101435151106563853435249,0:458849149288958792038072118798350524070548896798699913432941879587784
+emodev:-3986212837117931767741913193889401048695278656631180727109492306933238,146,8147531447709512983938379187878961602041163459101435151106563853435249,=1:458849149288958792038072118798350524070548896798699913432941879587784
+emodev:-3986212837117931767741913193889401048695278656631180727109492306933238,146,8147531447709512983938379187878961602041163459101435151106563853435249,=3:458849149288958792038072118798350524070548896798699913432941879587784
+emodev:8100902940229903010080076033147913858702310386781454704764453620638192,21,4267370499730163508065790684197722845343178463626879556739974287797969,0:1559194008070478152155445790765388085122959413923185554185144471054870
+emodev:8100902940229903010080076033147913858702310386781454704764453620638192,21,4267370499730163508065790684197722845343178463626879556739974287797969,=1:1559194008070478152155445790765388085122959413923185554185144471054870
+emodev:8100902940229903010080076033147913858702310386781454704764453620638192,21,4267370499730163508065790684197722845343178463626879556739974287797969,=3:1559194008070478152155445790765388085122959413923185554185144471054870
+emodev:-67357123532607208820167588026304493165680097354954648204845001128495790423,7920,54180751808291492597692968145199206126879627571212323371773988020895279516,0:38482445641925799800186404699759520693970772165979000339200404095536700469
+emodev:-67357123532607208820167588026304493165680097354954648204845001128495790423,7920,54180751808291492597692968145199206126879627571212323371773988020895279516,=1:38482445641925799800186404699759520693970772165979000339200404095536700469
+emodev:-67357123532607208820167588026304493165680097354954648204845001128495790423,7920,54180751808291492597692968145199206126879627571212323371773988020895279516,=3:38482445641925799800186404699759520693970772165979000339200404095536700469
+emodev:21564774075573665981752322921017132462944466357361497012903828640226528286,0,15058866062409919400686067571225883598025018993264993072866008153094783713,0:1
+emodev:21564774075573665981752322921017132462944466357361497012903828640226528286,0,15058866062409919400686067571225883598025018993264993072866008153094783713,=1:1
+emodev:21564774075573665981752322921017132462944466357361497012903828640226528286,0,15058866062409919400686067571225883598025018993264993072866008153094783713,=3:1
+emodev:777842233320172590239777220834144770465433238279191907466130446509467300356226,143127,809101386778417902091877810352677182715503592735762990564598234327398914965176,0:717304943713249257110869278409054343635488519531912801196499856064635084080304
+emodev:777842233320172590239777220834144770465433238279191907466130446509467300356226,143127,809101386778417902091877810352677182715503592735762990564598234327398914965176,=1:717304943713249257110869278409054343635488519531912801196499856064635084080304
+emodev:777842233320172590239777220834144770465433238279191907466130446509467300356226,143127,809101386778417902091877810352677182715503592735762990564598234327398914965176,=3:717304943713249257110869278409054343635488519531912801196499856064635084080304
+emodev:599990501312957514402788959646093776861193105404525472532452638242572938597485,384,694164098523184164132157046027096354720108308754361750383079701345225130461743,0:552831886836151341677818629154179022877513599687843019762824346082731337442633
+emodev:599990501312957514402788959646093776861193105404525472532452638242572938597485,384,694164098523184164132157046027096354720108308754361750383079701345225130461743,=1:552831886836151341677818629154179022877513599687843019762824346082731337442633
+emodev:599990501312957514402788959646093776861193105404525472532452638242572938597485,384,694164098523184164132157046027096354720108308754361750383079701345225130461743,=3:552831886836151341677818629154179022877513599687843019762824346082731337442633
+emodev:-717387166950856039948493623727619953417006786660900853391606222188523146978954842,55,249851988347340743956951710723755778934782102893613303732727155104650554024190836,0:94917559281978557652285194564919194471255372629172461015483079456525825293407904
+emodev:-717387166950856039948493623727619953417006786660900853391606222188523146978954842,55,249851988347340743956951710723755778934782102893613303732727155104650554024190836,=1:94917559281978557652285194564919194471255372629172461015483079456525825293407904
+emodev:-717387166950856039948493623727619953417006786660900853391606222188523146978954842,55,249851988347340743956951710723755778934782102893613303732727155104650554024190836,=3:94917559281978557652285194564919194471255372629172461015483079456525825293407904
+emodev:1247108559833255131023421051224206889208437707543309847268354783435841902933995610,733,5945033847480079150451694696629025175030386955808324187702080655474460793682039951,0:552121131858054985509439507160337194912532999251631220245735338315863124161594561
+emodev:1247108559833255131023421051224206889208437707543309847268354783435841902933995610,733,5945033847480079150451694696629025175030386955808324187702080655474460793682039951,=1:552121131858054985509439507160337194912532999251631220245735338315863124161594561
+emodev:1247108559833255131023421051224206889208437707543309847268354783435841902933995610,733,5945033847480079150451694696629025175030386955808324187702080655474460793682039951,=3:552121131858054985509439507160337194912532999251631220245735338315863124161594561
+emodev:-32236099593112567386979137194422864421137881615337394730197261867346802441980921669823,5,91752956401660637629886605589653679145541869208926297196888853146097034559639778456127,0:60518806834095575644319015741820323735595936545413392902275336817607638484905412448628
+emodev:-32236099593112567386979137194422864421137881615337394730197261867346802441980921669823,5,91752956401660637629886605589653679145541869208926297196888853146097034559639778456127,=1:60518806834095575644319015741820323735595936545413392902275336817607638484905412448628
+emodev:-32236099593112567386979137194422864421137881615337394730197261867346802441980921669823,5,91752956401660637629886605589653679145541869208926297196888853146097034559639778456127,=3:60518806834095575644319015741820323735595936545413392902275336817607638484905412448628
+emodev:50271884481278417471936841270780965441117412446282412169100969024758168373693942106624,3929,81963066766847673205247669622355518222939970750639201358276824482440704767576564991009,0:62281703540827707015524754807406004815705275005421409683659540143504669055166031995074
+emodev:50271884481278417471936841270780965441117412446282412169100969024758168373693942106624,3929,81963066766847673205247669622355518222939970750639201358276824482440704767576564991009,=1:62281703540827707015524754807406004815705275005421409683659540143504669055166031995074
+emodev:50271884481278417471936841270780965441117412446282412169100969024758168373693942106624,3929,81963066766847673205247669622355518222939970750639201358276824482440704767576564991009,=3:62281703540827707015524754807406004815705275005421409683659540143504669055166031995074
+emodev:-579340159717388367484103071217417305401854676291827723561829153224200380081237995138900716,651,307750673565730651787738866338890216282311653914599395911124646576595981539992209095900511,0:151509745004628309027577206278564432986410874344501872366280516978352818925422691489195213
+emodev:-579340159717388367484103071217417305401854676291827723561829153224200380081237995138900716,651,307750673565730651787738866338890216282311653914599395911124646576595981539992209095900511,=1:151509745004628309027577206278564432986410874344501872366280516978352818925422691489195213
+emodev:-579340159717388367484103071217417305401854676291827723561829153224200380081237995138900716,651,307750673565730651787738866338890216282311653914599395911124646576595981539992209095900511,=3:151509745004628309027577206278564432986410874344501872366280516978352818925422691489195213
+emodev:-97916243956905636477652083813766624733750918729402656599354295427509394488660812811650986,0,504214226951518003387724255017508609607833311675048629650486096975331876439736067207074328,0:1
+emodev:-97916243956905636477652083813766624733750918729402656599354295427509394488660812811650986,0,504214226951518003387724255017508609607833311675048629650486096975331876439736067207074328,=1:1
+emodev:-97916243956905636477652083813766624733750918729402656599354295427509394488660812811650986,0,504214226951518003387724255017508609607833311675048629650486096975331876439736067207074328,=3:1
+emodev:3292590583724934273152632680100030114145522324231651230586226973102509131367913652288365962855,0,3489305948459500758622220373494821215068462533405866936756424017653969429333910353069394383604,0:1
+emodev:3292590583724934273152632680100030114145522324231651230586226973102509131367913652288365962855,0,3489305948459500758622220373494821215068462533405866936756424017653969429333910353069394383604,=1:1
+emodev:3292590583724934273152632680100030114145522324231651230586226973102509131367913652288365962855,0,3489305948459500758622220373494821215068462533405866936756424017653969429333910353069394383604,=3:1
+emodev:-7978102455985676350366679275953460048435607670228140092963222007703573212864449715877925597841,29856,6437496673370692769029520191499051311630305921790132367949451008467412252240244679740653218546,0:5317938765885037665302910560037583058809520625824168737742040261509540549928785850499941206729
+emodev:-7978102455985676350366679275953460048435607670228140092963222007703573212864449715877925597841,29856,6437496673370692769029520191499051311630305921790132367949451008467412252240244679740653218546,=1:5317938765885037665302910560037583058809520625824168737742040261509540549928785850499941206729
+emodev:-7978102455985676350366679275953460048435607670228140092963222007703573212864449715877925597841,29856,6437496673370692769029520191499051311630305921790132367949451008467412252240244679740653218546,=3:5317938765885037665302910560037583058809520625824168737742040261509540549928785850499941206729
+emodev:67756737479519149309169118189597305480464085950144437770651525337717619238974063965848555442893510,0,61721185386054729344028716311850202684952560017220443047936445752013986984883181511511066630902828,0:1
+emodev:67756737479519149309169118189597305480464085950144437770651525337717619238974063965848555442893510,0,61721185386054729344028716311850202684952560017220443047936445752013986984883181511511066630902828,=1:1
+emodev:67756737479519149309169118189597305480464085950144437770651525337717619238974063965848555442893510,0,61721185386054729344028716311850202684952560017220443047936445752013986984883181511511066630902828,=3:1
+emodev:13622579220271678876766048827129463577857747656710532915693612564806742487161109510958801491048115,28000,84682569215903086997370780472826384755153630829606521208326331712119423387083844442113181771232731,0:61921681237911684957734827136839012206257886339643336895704703733211281700691618371720081605408837
+emodev:13622579220271678876766048827129463577857747656710532915693612564806742487161109510958801491048115,28000,84682569215903086997370780472826384755153630829606521208326331712119423387083844442113181771232731,=1:61921681237911684957734827136839012206257886339643336895704703733211281700691618371720081605408837
+emodev:13622579220271678876766048827129463577857747656710532915693612564806742487161109510958801491048115,28000,84682569215903086997370780472826384755153630829606521208326331712119423387083844442113181771232731,=3:61921681237911684957734827136839012206257886339643336895704703733211281700691618371720081605408837
+
+# Modular exponentation with small bases
+
+emodbv:9,32,84,0:81
+emodbv:9,32,84,=2:81
+emodbv:9,32,84,=3:81
+emodbv:0,45,69,0:0
+emodbv:0,45,69,=2:0
+emodbv:0,45,69,=3:0
+emodbv:-93016,221819,301662,0:211706
+emodbv:-93016,221819,301662,=2:211706
+emodbv:-93016,221819,301662,=3:211706
+emodbv:44378,411312,93008,0:33472
+emodbv:44378,411312,93008,=2:33472
+emodbv:44378,411312,93008,=3:33472
+emodbv:70,2233634102,3286325576,0:2426711328
+emodbv:70,2233634102,3286325576,=2:2426711328
+emodbv:70,2233634102,3286325576,=3:2426711328
+emodbv:39,5533253464,1070148632,0:416533177
+emodbv:39,5533253464,1070148632,=2:416533177
+emodbv:39,5533253464,1070148632,=3:416533177
+emodbv:7482,37424954770047,16839092776977,0:7609954661820
+emodbv:7482,37424954770047,16839092776977,=2:7609954661820
+emodbv:7482,37424954770047,16839092776977,=3:7609954661820
+emodbv:75,7836789049833,57211584574690,0:32805712142475
+emodbv:75,7836789049833,57211584574690,=2:32805712142475
+emodbv:75,7836789049833,57211584574690,=3:32805712142475
+emodbv:702894,534667733161831256,166575448512340282,0:98236745124961586
+emodbv:702894,534667733161831256,166575448512340282,=2:98236745124961586
+emodbv:702894,534667733161831256,166575448512340282,=3:98236745124961586
+emodbv:16247,353576735207718451,299565526093115255,0:280933599223623558
+emodbv:16247,353576735207718451,299565526093115255,=2:280933599223623558
+emodbv:16247,353576735207718451,299565526093115255,=3:280933599223623558
+emodbv:56,6221599776451542974890,2159033904867393928929,0:837205353236184592624
+emodbv:56,6221599776451542974890,2159033904867393928929,=2:837205353236184592624
+emodbv:56,6221599776451542974890,2159033904867393928929,=3:837205353236184592624
+emodbv:35369,1839486419148755508782,5530530292436823694624,0:3355242496236254343057
+emodbv:35369,1839486419148755508782,5530530292436823694624,=2:3355242496236254343057
+emodbv:35369,1839486419148755508782,5530530292436823694624,=3:3355242496236254343057
+emodbv:-5784,43040276670536818634785876,36492887405512401054348204,0:19286493506125729203919284
+emodbv:-5784,43040276670536818634785876,36492887405512401054348204,=2:19286493506125729203919284
+emodbv:-5784,43040276670536818634785876,36492887405512401054348204,=3:19286493506125729203919284
+emodbv:0,95555903303887262362307550,46204154362123372635933612,0:0
+emodbv:0,95555903303887262362307550,46204154362123372635933612,=2:0
+emodbv:0,95555903303887262362307550,46204154362123372635933612,=3:0
+emodbv:70094,89540446737340421223177728456,835694701023829355087294263155,0:418424229988754966300052414286
+emodbv:70094,89540446737340421223177728456,835694701023829355087294263155,=2:418424229988754966300052414286
+emodbv:70094,89540446737340421223177728456,835694701023829355087294263155,=3:418424229988754966300052414286
+emodbv:-5473,886261493387307990754063500729,850132294968984927109971586336,0:19962186036319737098397980927
+emodbv:-5473,886261493387307990754063500729,850132294968984927109971586336,=2:19962186036319737098397980927
+emodbv:-5473,886261493387307990754063500729,850132294968984927109971586336,=3:19962186036319737098397980927
+emodbv:542606,7576297578502321555503921719145148,6096670046812323372237867852342682,0:6019928069694583180163173577702370
+emodbv:542606,7576297578502321555503921719145148,6096670046812323372237867852342682,=2:6019928069694583180163173577702370
+emodbv:542606,7576297578502321555503921719145148,6096670046812323372237867852342682,=3:6019928069694583180163173577702370
+emodbv:35080,873804207633443539517026163606065,7700271966945032910098505871172260,0:5423974510417358397307357591894900
+emodbv:35080,873804207633443539517026163606065,7700271966945032910098505871172260,=2:5423974510417358397307357591894900
+emodbv:35080,873804207633443539517026163606065,7700271966945032910098505871172260,=3:5423974510417358397307357591894900
+emodbv:6,73591715017125540836707619882023150680,60596719455443436752409094193881404578,0:19278231891294150546581628518996450870
+emodbv:6,73591715017125540836707619882023150680,60596719455443436752409094193881404578,=2:19278231891294150546581628518996450870
+emodbv:6,73591715017125540836707619882023150680,60596719455443436752409094193881404578,=3:19278231891294150546581628518996450870
+emodbv:235,33982097410791452776449214446635671357,51970741787875276189593310474719958253,0:12917271140684347997107415362626020816
+emodbv:235,33982097410791452776449214446635671357,51970741787875276189593310474719958253,=2:12917271140684347997107415362626020816
+emodbv:235,33982097410791452776449214446635671357,51970741787875276189593310474719958253,=3:12917271140684347997107415362626020816
+emodbv:83871,305022614904134506738511247696618513698871,318914624938137416674596881724436242382943,0:318195604484243187814770062976379619616506
+emodbv:83871,305022614904134506738511247696618513698871,318914624938137416674596881724436242382943,=2:318195604484243187814770062976379619616506
+emodbv:83871,305022614904134506738511247696618513698871,318914624938137416674596881724436242382943,=3:318195604484243187814770062976379619616506
+emodbv:0,571664949666413150109110287956385784303120,899228089361406308796439491202242113692801,0:0
+emodbv:0,571664949666413150109110287956385784303120,899228089361406308796439491202242113692801,=2:0
+emodbv:0,571664949666413150109110287956385784303120,899228089361406308796439491202242113692801,=3:0
+emodbv:23331,111442438605972376130506110244327899219912899,2237876130742811109445709826445714509994544476,0:1993464329197419695692136638851665690518853959
+emodbv:23331,111442438605972376130506110244327899219912899,2237876130742811109445709826445714509994544476,=2:1993464329197419695692136638851665690518853959
+emodbv:23331,111442438605972376130506110244327899219912899,2237876130742811109445709826445714509994544476,=3:1993464329197419695692136638851665690518853959
+emodbv:-2679,2710530788173695233378407323077034767182928186,481025428743103260720025399298938288092709373,0:154954456135957386487732495151651926343687936
+emodbv:-2679,2710530788173695233378407323077034767182928186,481025428743103260720025399298938288092709373,=2:154954456135957386487732495151651926343687936
+emodbv:-2679,2710530788173695233378407323077034767182928186,481025428743103260720025399298938288092709373,=3:154954456135957386487732495151651926343687936
+emodbv:8,66475212144802642236424417695707616156078196371461,8400624623087855337736820815095169248114548022631,0:5187964347290625676649944455881080044360235674382
+emodbv:8,66475212144802642236424417695707616156078196371461,8400624623087855337736820815095169248114548022631,=2:5187964347290625676649944455881080044360235674382
+emodbv:8,66475212144802642236424417695707616156078196371461,8400624623087855337736820815095169248114548022631,=3:5187964347290625676649944455881080044360235674382
+emodbv:9,10015499242805866671806182669824281823377004291671,1607152293205603329110861060931530603574600872624,0:322976644144573292044502952628119378896898007465
+emodbv:9,10015499242805866671806182669824281823377004291671,1607152293205603329110861060931530603574600872624,=2:322976644144573292044502952628119378896898007465
+emodbv:9,10015499242805866671806182669824281823377004291671,1607152293205603329110861060931530603574600872624,=3:322976644144573292044502952628119378896898007465
+emodbv:-94,73883264784349702632503413711514594728450092072160898,603477481125780254532680608704164997261749601100642928,0:385098763603163293508297247576178742276025427508920032
+emodbv:-94,73883264784349702632503413711514594728450092072160898,603477481125780254532680608704164997261749601100642928,=2:385098763603163293508297247576178742276025427508920032
+emodbv:-94,73883264784349702632503413711514594728450092072160898,603477481125780254532680608704164997261749601100642928,=3:385098763603163293508297247576178742276025427508920032
+emodbv:0,403018665805686013292292080405520813912760095571441443,266783579498119505177390585076061492421096855799592868,0:0
+emodbv:0,403018665805686013292292080405520813912760095571441443,266783579498119505177390585076061492421096855799592868,=2:0
+emodbv:0,403018665805686013292292080405520813912760095571441443,266783579498119505177390585076061492421096855799592868,=3:0
+emodbv:-559530,4636346354116451435163995696044394621599926066887606404471,2007044169839741253208493501852117173644320085073436239558,0:980083462330793649852651395567038357390956681750027115900
+emodbv:-559530,4636346354116451435163995696044394621599926066887606404471,2007044169839741253208493501852117173644320085073436239558,=2:980083462330793649852651395567038357390956681750027115900
+emodbv:-559530,4636346354116451435163995696044394621599926066887606404471,2007044169839741253208493501852117173644320085073436239558,=3:980083462330793649852651395567038357390956681750027115900
+emodbv:-82298,1260064618208528197738958878917070904095451052223393007675,8999159392228622915543027930093543196382148986055721139210,0:8315318460941735744654692360810076563134610768999859190038
+emodbv:-82298,1260064618208528197738958878917070904095451052223393007675,8999159392228622915543027930093543196382148986055721139210,=2:8315318460941735744654692360810076563134610768999859190038
+emodbv:-82298,1260064618208528197738958878917070904095451052223393007675,8999159392228622915543027930093543196382148986055721139210,=3:8315318460941735744654692360810076563134610768999859190038
+emodbv:-5570,31666917408019243503426904818325007415747650667716360095948214,33888176432105527291712269105001105197791973525400419521802156,0:19067105956731919771713581587977175395882533198855245354642060
+emodbv:-5570,31666917408019243503426904818325007415747650667716360095948214,33888176432105527291712269105001105197791973525400419521802156,=2:19067105956731919771713581587977175395882533198855245354642060
+emodbv:-5570,31666917408019243503426904818325007415747650667716360095948214,33888176432105527291712269105001105197791973525400419521802156,=3:19067105956731919771713581587977175395882533198855245354642060
+emodbv:-26,22007905452621388581343089554119326311972031808789454501569850,63439035351302619534702904877608466226127936133687827793089252,0:8473726082518788387163006019447427099005218230673702028073224
+emodbv:-26,22007905452621388581343089554119326311972031808789454501569850,63439035351302619534702904877608466226127936133687827793089252,=2:8473726082518788387163006019447427099005218230673702028073224
+emodbv:-26,22007905452621388581343089554119326311972031808789454501569850,63439035351302619534702904877608466226127936133687827793089252,=3:8473726082518788387163006019447427099005218230673702028073224
+emodbv:1,775918498742633740198666683324414961665313627445077186593800017785,952660786088689171372582380372342941537491408809547120368107346294,0:1
+emodbv:1,775918498742633740198666683324414961665313627445077186593800017785,952660786088689171372582380372342941537491408809547120368107346294,=2:1
+emodbv:1,775918498742633740198666683324414961665313627445077186593800017785,952660786088689171372582380372342941537491408809547120368107346294,=3:1
+emodbv:63441,721478459297998380784046348477788577160851236668812562054262272695,670208399244540961973019014052558168787791247286206733986212837117,0:211218046769494325969669872092652715825286994236558200831519171517
+emodbv:63441,721478459297998380784046348477788577160851236668812562054262272695,670208399244540961973019014052558168787791247286206733986212837117,=2:211218046769494325969669872092652715825286994236558200831519171517
+emodbv:63441,721478459297998380784046348477788577160851236668812562054262272695,670208399244540961973019014052558168787791247286206733986212837117,=3:211218046769494325969669872092652715825286994236558200831519171517
+emodbv:317,7741913193889401048695278656631180727109492306933238851468147531447709,5129839383791878789616020411634591014351511065638534352498100902940229,0:2840857949915095558231699206349834791724216125018136484978445417022859
+emodbv:317,7741913193889401048695278656631180727109492306933238851468147531447709,5129839383791878789616020411634591014351511065638534352498100902940229,=2:2840857949915095558231699206349834791724216125018136484978445417022859
+emodbv:317,7741913193889401048695278656631180727109492306933238851468147531447709,5129839383791878789616020411634591014351511065638534352498100902940229,=3:2840857949915095558231699206349834791724216125018136484978445417022859
+emodbv:0,100800760331479138587023103867814547047644536206381927221426737049973,163508065790684197722845343178463626879556739974287797969673571235326,0:0
+emodbv:0,100800760331479138587023103867814547047644536206381927221426737049973,163508065790684197722845343178463626879556739974287797969673571235326,=2:0
+emodbv:0,100800760331479138587023103867814547047644536206381927221426737049973,163508065790684197722845343178463626879556739974287797969673571235326,=3:0
+emodbv:720882,16758802630449316568009735495464820484500112849579042319792054180751808291,49259769296814519920612687962757121232337177398802089527951621564774075573,0:5513704439164313512320603722396796903350762139161644395131273954203378131
+emodbv:720882,16758802630449316568009735495464820484500112849579042319792054180751808291,49259769296814519920612687962757121232337177398802089527951621564774075573,=2:5513704439164313512320603722396796903350762139161644395131273954203378131
+emodbv:720882,16758802630449316568009735495464820484500112849579042319792054180751808291,49259769296814519920612687962757121232337177398802089527951621564774075573,=3:5513704439164313512320603722396796903350762139161644395131273954203378131
+emodbv:-65981,52322921017132462944466357361497012903828640226528286241505886606240991940,6860675712258835980250189932649930728660081530947837137778422333201725902,0:2906363080300504036446988558153247540678666818543108704882000018688053575
+emodbv:-65981,52322921017132462944466357361497012903828640226528286241505886606240991940,6860675712258835980250189932649930728660081530947837137778422333201725902,=2:2906363080300504036446988558153247540678666818543108704882000018688053575
+emodbv:-65981,52322921017132462944466357361497012903828640226528286241505886606240991940,6860675712258835980250189932649930728660081530947837137778422333201725902,=3:2906363080300504036446988558153247540678666818543108704882000018688053575
+emodbv:97,722083414477046543323827919190746613044650946730035622684143127809101386778417,902091877810352677182715503592735762990564598234327398914965176599990501312957,0:889212904562853779260747052184064517476716523608339827860458031582708193206654
+emodbv:97,722083414477046543323827919190746613044650946730035622684143127809101386778417,902091877810352677182715503592735762990564598234327398914965176599990501312957,=2:889212904562853779260747052184064517476716523608339827860458031582708193206654
+emodbv:97,722083414477046543323827919190746613044650946730035622684143127809101386778417,902091877810352677182715503592735762990564598234327398914965176599990501312957,=3:889212904562853779260747052184064517476716523608339827860458031582708193206654
+emodbv:14402,889596460937768611931054045254725324526382425729385974856938469416409852318416,413215704602709635472010830875436175038307970134522513046174307173871669508560,0:104803682559692025313965046839630608596949538962860573954122948467983495146496
+emodbv:14402,889596460937768611931054045254725324526382425729385974856938469416409852318416,413215704602709635472010830875436175038307970134522513046174307173871669508560,=2:104803682559692025313965046839630608596949538962860573954122948467983495146496
+emodbv:14402,889596460937768611931054045254725324526382425729385974856938469416409852318416,413215704602709635472010830875436175038307970134522513046174307173871669508560,=3:104803682559692025313965046839630608596949538962860573954122948467983495146496
+emodbv:99,8493623727619953417006786660900853391606222188523146978954842405502498519883473407,4395695171072375577893478210289361330373272715510465055402419083612471085598332551,0:424015515432121716805639629631123704621802071965154851362821400859180276022226483
+emodbv:99,8493623727619953417006786660900853391606222188523146978954842405502498519883473407,4395695171072375577893478210289361330373272715510465055402419083612471085598332551,=2:424015515432121716805639629631123704621802071965154851362821400859180276022226483
+emodbv:99,8493623727619953417006786660900853391606222188523146978954842405502498519883473407,4395695171072375577893478210289361330373272715510465055402419083612471085598332551,=3:424015515432121716805639629631123704621802071965154851362821400859180276022226483
+emodbv:10234,1051224206889208437707543309847268354783435841902933995610637335945033847480079150,4516946966290251750303869558083241877020806554744607936820399513223609959311256738,0:849166472390089324447217011402258926811127602345244477949055266800343927988355770
+emodbv:10234,1051224206889208437707543309847268354783435841902933995610637335945033847480079150,4516946966290251750303869558083241877020806554744607936820399513223609959311256738,=2:849166472390089324447217011402258926811127602345244477949055266800343927988355770
+emodbv:10234,1051224206889208437707543309847268354783435841902933995610637335945033847480079150,4516946966290251750303869558083241877020806554744607936820399513223609959311256738,=3:849166472390089324447217011402258926811127602345244477949055266800343927988355770
+emodbv:-97913,19442286442113788161533739473019726186734680244198092166982349591752956401660637629886,60558965367914554186920892629719688885314609703455963977845612750271884481278417471936,0:39492300709350508322185513215823770925957483374622610701455481874758748756164234825489
+emodbv:-97913,19442286442113788161533739473019726186734680244198092166982349591752956401660637629886,60558965367914554186920892629719688885314609703455963977845612750271884481278417471936,=2:39492300709350508322185513215823770925957483374622610701455481874758748756164234825489
+emodbv:-97913,19442286442113788161533739473019726186734680244198092166982349591752956401660637629886,60558965367914554186920892629719688885314609703455963977845612750271884481278417471936,=3:39492300709350508322185513215823770925957483374622610701455481874758748756164234825489
+emodbv:412707,9654411174124462824121691009690247581683736939421066245039298196306676684767320524766,96223555182229399707506392013582768244824407047675765649910095793401597173883674841030,0:45372936066320285565767345060984614982597172133924700246907679760042995966513245912459
+emodbv:412707,9654411174124462824121691009690247581683736939421066245039298196306676684767320524766,96223555182229399707506392013582768244824407047675765649910095793401597173883674841030,=2:45372936066320285565767345060984614982597172133924700246907679760042995966513245912459
+emodbv:412707,9654411174124462824121691009690247581683736939421066245039298196306676684767320524766,96223555182229399707506392013582768244824407047675765649910095793401597173883674841030,=3:45372936066320285565767345060984614982597172133924700246907679760042995966513245912459
+emodbv:12,741730540185467629182772356182915322420038008123799513890071646651307750673565730651787738,866338890216282311653914599395911124646576595981539992209095900511097916243956905636477652,0:597882447446136206020843479948282217243162285637054743586243300633734568794892620330552220
+emodbv:12,741730540185467629182772356182915322420038008123799513890071646651307750673565730651787738,866338890216282311653914599395911124646576595981539992209095900511097916243956905636477652,=2:597882447446136206020843479948282217243162285637054743586243300633734568794892620330552220
+emodbv:12,741730540185467629182772356182915322420038008123799513890071646651307750673565730651787738,866338890216282311653914599395911124646576595981539992209095900511097916243956905636477652,=3:597882447446136206020843479948282217243162285637054743586243300633734568794892620330552220
+emodbv:8,813766624733750918729402656599354295427509394488660812811650986545042142269515180033877242,550175086096078333116750486296504860969753318764397360672070743283292590583724934273152632,0:187419881697087928981580635353669700411908736518656599363509921235901203393697886905365360
+emodbv:8,813766624733750918729402656599354295427509394488660812811650986545042142269515180033877242,550175086096078333116750486296504860969753318764397360672070743283292590583724934273152632,=2:187419881697087928981580635353669700411908736518656599363509921235901203393697886905365360
+emodbv:8,813766624733750918729402656599354295427509394488660812811650986545042142269515180033877242,550175086096078333116750486296504860969753318764397360672070743283292590583724934273152632,=3:187419881697087928981580635353669700411908736518656599363509921235901203393697886905365360
+emodbv:801000,114145522324231651230586226973102509131367913652288365962855153489305948459500758622220373494,8212150684625334058669367564240176539694293339103530693943836047978102455985676350366679275953,0:7455082526360199945904164673384849878483828122749940095337812295059378328144102232203949899838
+emodbv:801000,114145522324231651230586226973102509131367913652288365962855153489305948459500758622220373494,8212150684625334058669367564240176539694293339103530693943836047978102455985676350366679275953,=2:7455082526360199945904164673384849878483828122749940095337812295059378328144102232203949899838
+emodbv:801000,114145522324231651230586226973102509131367913652288365962855153489305948459500758622220373494,8212150684625334058669367564240176539694293339103530693943836047978102455985676350366679275953,=3:7455082526360199945904164673384849878483828122749940095337812295059378328144102232203949899838
+emodbv:6004,4356076702281400929632220077035732128644497158779255978411329856643749667337069276902952019149,9051311630305921790132367949451008467412252240244679740653218546677567374795191493091691181895,0:2157703003465786984862106104496545852077633747681111082485733289488843538802921375640668056154
+emodbv:6004,4356076702281400929632220077035732128644497158779255978411329856643749667337069276902952019149,9051311630305921790132367949451008467412252240244679740653218546677567374795191493091691181895,=2:2157703003465786984862106104496545852077633747681111082485733289488843538802921375640668056154
+emodbv:6004,4356076702281400929632220077035732128644497158779255978411329856643749667337069276902952019149,9051311630305921790132367949451008467412252240244679740653218546677567374795191493091691181895,=3:2157703003465786984862106104496545852077633747681111082485733289488843538802921375640668056154
+emodbv:0,30548046408595014443777065152533771761923897406396584855544289351015617211853860547293440287163118,50202684952560017220443047936445752013986984883181511511066630902828136225792202716788767660488271,0:0
+emodbv:0,30548046408595014443777065152533771761923897406396584855544289351015617211853860547293440287163118,50202684952560017220443047936445752013986984883181511511066630902828136225792202716788767660488271,=2:0
+emodbv:0,30548046408595014443777065152533771761923897406396584855544289351015617211853860547293440287163118,50202684952560017220443047936445752013986984883181511511066630902828136225792202716788767660488271,=3:0
+emodbv:946,57785774765671053291569361256480674248716110951095880149104811531028000846825692159030869973707804,72826384755153630829606521208326331712119423387083844442113181771232731949302549335896184427699629,0:63291678821403600137229027314563244771616884878395099760855279589610716265728494065685311702593475
+emodbv:946,57785774765671053291569361256480674248716110951095880149104811531028000846825692159030869973707804,72826384755153630829606521208326331712119423387083844442113181771232731949302549335896184427699629,=2:63291678821403600137229027314563244771616884878395099760855279589610716265728494065685311702593475
+emodbv:946,57785774765671053291569361256480674248716110951095880149104811531028000846825692159030869973707804,72826384755153630829606521208326331712119423387083844442113181771232731949302549335896184427699629,=3:63291678821403600137229027314563244771616884878395099760855279589610716265728494065685311702593475
diff --git a/polly/lib/External/isl/imath/tests/expt.t b/polly/lib/External/isl/imath/tests/expt.t
new file mode 100644
index 00000000000..c778929860e
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/expt.t
@@ -0,0 +1,154 @@
+# Exponentiation tests
+
+exptv:25,37,0:5293955920339377119177015629247762262821197509765625
+exptv:0,5,0:0
+exptv:10,5,0:100000
+exptv:1,-1,0:$MP_RANGE
+
+expt:-1,0,0:1
+expt:-1,1,0:-1
+expt:1,1000,0:1
+expt:10,5,0:100000
+expt:10,5,=1:100000
+expt:16,2,0:256
+expt:16,-2,0:$MP_RANGE
+expt:9,114,0:6076396096647706909168138770838836135530328017648434830996201971201776350890241322455818405320466786549738961
+expt:-86,476,0:662617332696362860524067230796827820618815284881665908870595313490845384402730799402221740741547892729430741053639014274968962128613995528237195069353968871860065099842959580048834695510748974202424908905352730826874949676923389706328585129209694843598031316497606363273659659518137129001683914681077900538211178870670637655474948719356656149928857724507047191532188701873201466847680543186709462811132458087950485580962981785390351911145306017418845982546035812744084364382432586452339098567898296989357418159116783507112574874002896769395516552960579886303506398054290885811079444534809660731243125017742263312078176886504861185566719851630353701862941682854137129215263285153620969438652988427729550528379121310832057528645876351114476064584186293636620546183047738657594287749786268444920697293633564476272776432769083439149706832453778408583421346390651383448852253784001810843070684412323782386158601772005993742336
+expt:40,238,0:1951092843947495144613498268620728941092873839165606969286973099765857336762353512575191314414682481974891831950879139309654984799555178316431360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:9,761,0:1508515174935868832740908844641413400230908698282014024654729092918735474326353646362638387096847659573480147230064829611049820323852929496264239478087068540642226919569780605621815548160687919464946810325130045648382743363240874672014902866728521582870078261816669666838432797381766007612134725161586319767428484319859256110793709691241551836459283171491322903212579581783263716842956174378353601721913353516686324030063352338083503343527729254306613462747468830270057853272630516028854927235895950242106874919224742672988595490274178820331573555174825456815488479104792855190670321093410569224479462267429452231735849215995686173314732407799996091669536594590589720060331368687564979078136565140955509332862196370159944529609
+expt:97,144,0:12448864341302864356285624793135454957839907062356377399873019819913674333304037397385881749787740378047787615516124593880867160513889753519548772992938610862712907794913424958325207507075928443769586211194132774382517001523776118917770065797726717096819996931978519564039067219497326081
+expt:25,122,0:353737464016668451855824972300304366432911374927310085530570894138105520257533012294512947342224925759920017160034290220932919252862236536572027034708298742771148681640625
+expt:60,794,0:71136550947732097223049080592911024204723415862845308040389197768507697553695725763485652390828706079386079253286683076446508807986344183438029484620306186446936364042768259107355223169364392353311443322952870623266797106042061359252992933819289381215897875409197357921675407844235432207568030978595888122411284106189806970016530299277993693667005155741905298746901362592844010565441606260646610040560804127639267467909340287601194961411351728753184912061106832973826776921930054951881992593414738674333726484856598478050587647451437933451435999205268943471465348558111458293504367268910731207434743916849298071460249600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:77,531,0:532813311656570249504626338521175986931059533505926279525440059983661596994102351537446926949363360529365260710018282274969608991708422465645470353238950991164094603760337431471373797674342466447685331328334896929530869521639021347860305641901746618212067382436047417802334922329714967747069071224609067366771145964345230898570999327581370275837424654936614015736099665593408214589717971837806254491231718922616012680565189067437536528526576020597271981783296886490561985553063246822960810078500648480156559918530508398231087164252252053517193755387712164533565474034807917780960207694570186046344187446803758345139338159388892261095589551022214765624192005132067602116482379395414788544646979450596452460362555591887638135655580299669062424023518502777571809123694201495640270788238169354113138409879326088017367705387411669267281998186298445497315171994082486321864442017377055208040226703055135151101106282748423896319916554310684705542590586019379478759401961042716809342108506273015769966750567573
+expt:69,147,0:2045579385385676298810517927458702060863220937986515106749791476657551971253912701625142580828008387342063850849956585037595400455275752324351745210872040235629033488870814386789439565218837255775426196335872604764004481418507627655312643367630027383681234193549436923389
+expt:63,5,0:992436543
+expt:43,146,0:30647461956799913663494655425076773992386225973903296590660647835395776515882377986142610962128804096035118305690037018948311119864211319779734143116465886493057052663022568542180068531441910862918530533350093865623799781552091321941805049
+expt:98,726,0:426708164655477000890275450255347996233537359230825603678068055078572185768690530483979279727883872477967005148697167468182222427688835250730805216703200346494527373336005252179998129153425179169405541975856774474069498366622503869407903427510194050762239470842997997171904492470843168606219304544549428357468779947949943413206194819154200161585559598504692063910328095937302046813011102683058231640089632368478947866970023522346778845648102870898031392605132459073175114548205304577635185214718149330416992983890351407166804165953949747506605647268028309196988233767305361741291382876521135508192965016090404300931198517364604358975250384413502392769253607192796721507324069628343907393125548382919869819440252750811077561632309583741878536279703230000857054139878422446147127180603427708828429704600917447413869817618302245994562895269981736545881770397064210337561050137140587310204526285808818450640283721161279575346308077129128490827488909459752308152575975333376251163648250120013220501057296109952540925755870893739088626118741752210805146783700608707536622996922837160677398003341203351388553480766110431344123182677789104679858022371096216510424982048676315996005859351101823572640031789389690671319495099716878889860298319419347560159622529618640118175355266744662407331598655239886273495406443560838728384648401252398353045183922227138034113900212648350987135932227570141916304732230558988327877007227972193394243239402490072781553664
+expt:27,994,0:5964603431471868470779586030579897508944005422481111504996101053704042888070620658634603446892718184220478121160877417420632344218074218536055055853341137441998294000251200835878902350186488825026483460943513306200517889603246366106853840145090440733291280737628836962672475155047075274192277218811417069065936482209339531226972570820904792756362193437359255260272908936652780579152117702725740119749377918245976402017781340294169531390247883611378505356757467342298706583634922064709088257785640184257059718176205448907751675016209636121926542527171904829380257098579043693273941177601321704542520456253669795714215535002523967268853493688846286706973999035367452588515476784419866076998252005842676395279638218578241484332229406009518807659452519350666942646794806449473475747553767493845162021519112769640526941059309326051192732830213515976229333540580413722595827300619108280969740698513378110488385074544619780641948295405495780237236276684111403379203230366783709039063472719411695740144082704697603632985497552873504333474571968038639730745252032873211100978857900893481330626200727251839567315077961576806464237728134101031182507236896333266479325934856175889116335417594516961071359041380154522292684361535083826965209299951003822498563135386891475232447007531309326110170827274814394069801400172716308094800028763449103928013302738446528312264064411790429063607977721347425016445446736220565463902437544468120409
+expt:-34,885,0:-228476523750723373644687014002375633344738959573253313295673378381427602021772078020242635916606956729056926140060033073714690114938322706601446752472086204645016603045913330963730961808178207763215017501900858842569395980296056740108703232651676106742955978639790402346938757058023705396206982274162272726053788981662544438635344871901487308331092875364378228725341155111018434010367438360637105101040524061771063338296772106596332044158968115550006262659165852163296710243618168537491315057352543683129215465809356035846400682903175992116512861339446629911475952731908088842546841550719832093476305343487020461708563559436380209360381168143472508064742652734842472679645707885058211800145889276047957973692059807305288049119319173129319106681652756562743739107763982095644384826187365922752532925851190935179707337534386963062100373634441547376770817028643050332728353004280762321859734138238987031675696783935311587870039192834643563874032592612926869623391797208269743645539702607895028584122500698098111011232061951530722490246531280555160067707338914792416989446928511604549465504192826378832978906732786898284995067855250035120805001076275382922780012160428673191761070264969953411775690292328243025746069928396010308859738310517827535649006402912255952898688436528776249218886864180489977578374114695105630836780908831245277680459913198577305780224
+expt:68,110,0:3766867964664544159080663337184475494042561418541340945804586832720994284771961635397385875362345125057120310938269750846083952813873238584240580179827028286414766076572917365783013027168357407600410624
+expt:53,658,0:3745606907993421946887439162000086810348803803092371857142904229709206909828318821048723175183121197130197244352493778939138463422250852343527134762386848777080851567505679505075345465770806895721134211771274772293259989505354294489544040145546102855689216456038976289617392680444976953405298744483530421163275053596226349987392709474693470945596072586963883209895508334043197301264236788171635960039858646321742025220295519025375907766179640091678782720809671950054095805941850551155084902979965473850917202849828979441725255702684409539964150439149357477472547510742865588406211296859461563407639715931477329008440374383580709783691664845736383663038801784370088793404842551953417842873348778874221805705399715354432210347494670220197359227112393213208248173978860627750353040703341367562548515958900446957626661507861996868491462583136836486757565972785201597859791653509981302034055855843211266876872054969345931382022744508783063231741810980521737612696916450990320941990166412615155878082383699204415978877720954451681587069814429903479542778158301091332107305065103043241495237616334706497558758024048371354995778381078122856889
+expt:92,804,0:7680919010486502611899642593747149466649196229266501367711103750663463292831658713415279184569662244175409947032999989257086334914196151008717155913095724421214123565414211404671154819304177054262624540117568190722055697928671476680220542928701368559838336428067111425536616146489821648041701273110577053706361418086034761443472306518865080966679098105467798346917600554685542898553062250741733411314786612840508881986382144004386089851397484105951275595996231115064888236880983094071936561219536816852038032287045459246026554363716223803369919418940349582736218979681160219265039593199424543894793508283019529562836802500641291446928979006411204413367433175378170319515975143760263714327381242315380104084348844582613710587726111048178373881327576604839032050152609478011520362808140313650631437624206065559757026169586967629556330683105990075123728304036555187713491828534603673570621146978011206391066697511863181519910465645525817216154078233941728180083417123747740080789188156807592630560128265705528875621630095351201299879483799930273817796360416169388658060657506361895914025279478414056917576529844826749149254978523394656765480215719926358133890602585178838119464948003289948380599052143243657411917203711988600003537438673472852245599607482384889722702462622774797489957621592414208918554109594415643546111991744898184380453126034201383595790269274373055123173862494511611609472258838476906869425218506801608515950342031211116660445405063954103192171748610888916224658384554763772392708457944737818761788668778004849546835031715922094579082757147279920864952420663296
+expt:-93,17,0:-2912125755884410842622249251854493
+expt:83,344,0:1455002626766365151331492634356788248715003383435775455996374149087127274539469938480434554541764208550166395886013614290542493336553727055035200479566375122407588223498846894540017410056428775935861377005037728217969587830322338737768781971954310027112710091083345708154562101156949905590633490616529984721229205694585229393810736667126990248301840585766896715156041016184889232474489806021208434163212143568783993412750969879402550558174816868622343662524065027291485375058885945026037942093663550462847296831559200222610314374017319326883901944196944190346470731947264070070668533749087738060363624871768516622722491132752341069559484881101460722290741607521
+expt:37,509,0:1639372139330474505096339736526839874531950388106785764526499216811362225270703761672667866735996696543474964780972938761569608985235961843219297731833082892285640739207743839560976358344004254125552207884861967683494079795135492763316903001285669079285642352434013330494551450924529881670919372226435491663678910321572802241052671829048684593319302540499062531002552822413972447877352398056117420144161447269350831919710819792646829325266226815447766753199630288869617053962763718694151712581758666586038482541785095213523640877958314344476036711277346617174429612617143676944589174538616885971879400465341144053670575443367839317972672752212894927196448994763102499581012815364079440761668903982747115134081448923972310533501089520501466675410274312105259815806872362946932755486301682363073385077
+expt:34,19,0:125342809160496617801464152064
+expt:-76,29,0:-3496183156153757826996482351208459912924449087659442176
+expt:37,959,0:8043653985532953716889715133535087168670385482210859421739682450017285673683111089377825581114293665656145651712345850663980083336468179806875814073857765425892155354598266669506804046627707739916500884106198506997527648083295900530561613402364276614913200001026056509772329191449641564220726849838723452604518199139241770839665976645631344667870833619675231878104275459443798340311110952188496587631537611487174398583536053876742575306117395796907118640363142612543112228300527887243345970257920772909373983605623295787525934506659963651305156708304203030998266284694349384314377300558457176325498546062335314396443971466680283426513605059525173724321570541512640520991258079091372220776160186495883992700218975056631545666177364476484572440897669270951851900895176798423899545287983761049721641455850562227655219058197710285516766496107629355803471562655222885223162182968326669241365735898955624385521019652649599364538263697078170698660931177959033737136065046900419098588879986481831152277650601951389732469419718135458317284510180252252347215282909809244252103764833246379696609330932880474725472382498914394849425766909318546858182860618752740997875122661035517690985707005948901199463714885386589945448510035753998020104333298915321476036121567051616071951554677670098530225928071546828420949645455483886944027286648764164718652180618519663834711653112733332792953298854502679756506895010313106988391740237915628327936616978344717429852330779137901687317622168225757826112789753604087557655040173
+expt:53,855,0:18024719238727749739525445919483313820179132397627088793412502725451984940695378279438673546750025166612239273512610516827961724525198882762072448802914929186534874689268838685049338395668464648214285629458942854743809087942072596640624011936285554457003232121031929203367446328606007087882829501707445687372318602594007967315081778231244881573239906171935915143655956161425143440493226007667195047540127725460951375078510152848109086910835297918453026272054497519156136102101888168736867868647822194907272146486388416624265152334316284765111597489635974901154683366709520639989936829700879404498384693571443613183789387222654028458579806593806268491518181218800476712301946966270100813204092285152986557168694900881657470791233632087214162768980287038944834419004548322680351210051534951796722585140993240046500305409149666028347813321755225701104959869144974670164886058856826565923628643498059733335090448195444279918303399796642120257846094099858071377352515014517392246807264485477604806428498201472579832708245125875380579584993781814239835479412029038694921470435633141289405105409413524512605572562361133641297988371189750573248231052889827586537697292556993264681319509450424190822893352470802584486267244129501288234774550146263799764737409541494978039756256344516245332054030367728222980738023243510101784709043134443224472285495023599866477956084806532775907376656412097028192665531115092097120219791652662455717002643200873090340640713123160526016567186689389757
+expt:32,656,0:2389933285405466860396692079116393607592094511377675771193917107985577957215786660857642782380647855358562124487585166367387947413551391813528167636162447060549990168729176552922878656050672076285621550614985470720664776531442576135048333979096784310286244860102378967371399286213595759636919115966603400112237639950891727815590236647193809310063401704857160813929322419325892381145791656471799426867797910499315367811275543479800432663111156312795121794429616492767525864645383481760770859827287365500386734880646418760089786239708463669779102319740012320361344177543946675529942817886591133769700783852263121450795052384716461322528105766425932143907687036561966697338295352111191252732978138183228296826658380107463086196091321472046087589204515401546744232072241940768351560772822305604027448970361890755796703363650465900018004257276623522292065343862084678326596045941765842024484410215769394555885885158749838834979597158322722201614329459219680380702370857126529706245613395378176
+expt:44,825,0:705436783209414656391711687641131832457317079567241536806961190125032329799945689381531828701711922651328924171833912445806993257740496413957550233738157646707468341476136656655190568061765250287343123150183203457096310554778580693127605900054156781937329687900011079033154328368560570397733837126414151383627725550551123061599523989519231809246838020349444255196435779598286912941849683826803885007041497453499648698536652839190738405213015416967571009307605140974000980854307563054593796685305388455731431361267420888839574695702395994221207745406708122106371051596919061007969322392348313397932391816147444777599673900815310461704623664643196151052250877625946280731633882993330125061545681460076713485728798412351901806167839675417726868727194522011871552299094826966964668768915141255798918499796543486231511141788910147145213662462426979493734390203264331227425018827335966699727291310495771236126927600243376852048316429905244128279916690719962985233688697060839371456481476421673214751905689846742695604260150120965796700034367974580976289127610455139192549104607458487162099297483432995551188890538592998367871918611578833922235492029074979130410421219592032895629208451572864516745372515998761341772487485436904736855847415242732131193954436562666516079556232801577061434743967882168334814393918596862293538397642429151346165775119942485356314624
+expt:59,114,0:7535799365523929401466950149815776414046724006436301251256273386014282698913901410854119082161738764751825402834444249521979494417181418024031729730875375541703751272328798861158409927866104969176716761
+expt:33,638,0:648475603635833183196469398829966467819872179533313634773199294300845287950459501715005525988291242251589147926178661960824082441163194476232580397116885117509943674289579029366937003306245475847226805096473463034937358215125841547863811379526289909390311989707533329900551425869234787887523054960552278032611552781528108935648755207909825160440738427953647870234694868460377213725626413535570112216908805974133165357493773798997957325074032229891071788781461177535131032268348271529076288914099185644193139733366057736098900551638267073002144185264974730918597301702988431169584478969558388865801487275460346465072354829295831509446111012459075308582088675497358398567086973619837648636885329011064845212317340840818123718736632174769798597171923150676024529241760831961841633158660369965791581395332178142007133509696793640532076763117981014872625633261577688978190292542653541593712317454035995088612040333001542622676149361438454964780663603604979033175966419868609
+expt:69,872,0:29950710056653639866040347513592954608907832187759095021784612336213340883909743941015111690452867673342534673834960600259673961740938823369536279442812481113707789275256589878997231276618632636210489615929064857400027555434720369902556432133478971302553689173725290340815598949062749239632058821352962601488612707115779689919582783658366139458929359238601369623679788087432179938746909197524719589777317181141198765254386641701187353660512871784711559256412459533781485842843404652110331152933616653843115472865088192382607300085255939568539834001519100403938776165952337332146706473461537817329969120309309517770547565346056282486046731066492332789904059680738904349305243649494763250736765491708310216396673397796961838301667209428954933817477191941146364618594356436871426698169064040813675818513426197050972194802492745959927175153699196273914186935407179377493000883694252000018528388345695513167889176432751477073481242404466807236118127264128971920247017078705326478921858295937254808875182604664522156032745827731392987081529736044441817762936554493023891039839715605648021019219907116643520667553628457465780133403776577685023637262452859732368262675698820414066865949360110605575303893868842664652278685058236518116527393248213186175036314144344761002775344535262642684517202791126837476442938864508396830200526809879345482138492481769343790209140327431667550761817827241581355415614928705123841250085260545474358015032657030444618098608485724932887367556645547344897117535819883458173888231937264034262930323293309593162187140783379967834211500900425793093911669240962055595069032779064523361
+expt:-35,560,0:4765460083484463473472807029671198741039814209947733085375343877805519722128264213906493004712395811794836067456926301347831701213543102558807372013840371317686389493491044956157976970854534780866809198779109650495115701056756779233669845873333611352227016172179141127201204621485258250872410797565587431587955801098712622722961241140244408879022252575756465947941316439513115927707432620645580331357844859947529159485059102032289565818525572625258477572647406049297215450764812141735725360033399668564250475303073470958824427283582477027047896762000913374878650247253682919902323190143426951007619514663885034098702528525398380830769050070744862297092823136092265705202572748338959960458521661389246148014773201598614888333659845567286582320269709906762495527111679682357140289756441194587185256840255908734955659782455404151202404960940839373506605625152587890625
+expt:-83,209,0:-122270392573975557137544098494603104038431911133401401060669780228862020091902727664948350712829411551252088259762269665003646460255858818493536471916081519810436077327712541465284264947694222413222906768064481479603637285266239005383584918898692141414316852928726367305370720092433674542731019975979821342341530442634729485864001750080837642935553282153040722532849483710322964546566862518809499408403
+expt:-22,544,0:18964367700820944190420983771842117471035813402172302356001324232625456871631696158159426747244273988396896874782255417862295115980915085588836421854267161890941876064963407590082206716515749082957670650572915503706055302390446576711188138153431530926911613355471966093726010812009574536833618487020923293412479710272640024885745749390406182848296906282562712038022234856787439331540733410267670953621778020862196051822262364620284766229990123269618359711309083829625146905646383609813594662427186141810814135462546643373090731265237443450146344536874441550683786161973931814080708597655835455648574641882644636540462283387226460671638812957375987034299333511378035037854459892174703913394380151030879671916383365880966083883565056
+expt:55,53,0:173469266931818817701197572759460512158186359368276122994156906997886835597455501556396484375
+expt:56,7,0:1727094849536
+expt:69,511,0:4486269579432801228328894978520612039865782962773314299890064827550076871686539386493998487559513347930912978842976457609693197201213966463505628022312395013622414842679517721662844319556038654381323108565877674965192437982575193911756281655521858715295957459295213878788866632588753200138937292160832095681182024559479348223221677348390842846953123958441380139228198612700886931654375724810762399664286697632157511028362743434949776821972216621014709224808699213105247588616225388811148034573781049594047599184470666181439258133413347363982316136095491031694475463436444214376593921337732387516213520549630132463991049105936530704212604782416902497080757979392934118897752584527916561354795284032980721598161111294569421622420394749960961723356836189382523894823797755998521714994563261231632958790842100581461483738927484818446238271808447886746812572795337464271466846423907255769829987902959874517226021350215314613561013455027818736269
+expt:65,627,0:497364306835738758369203816929587563621484908670308464881508611000120397210171552818133505588600972283722504217038299267610870712281857521011539651202476710112665851438274405311118329759864306530206464076881590237702559066115100823897031634086082484171733231579340629242599537765843919362377197750957150409164905009889637997973633002262727089466214411540563439873655647562353181575977350122226034217971081813504998125791931120734615674206813835553948971108562651944903797187278504359842148559086576885512335220747304460608200450624832543393270309192761368009850923893828230888362356748911750574377927901251690822238297994571714786631993517145675163841742009468644933432283278288658898061814717433241276039971839163707090134740016885115455078319929919984436448696758395047545344494824758451226738937682595385197871210901912587652241955896134593132930558535330562369949669112499207879073779991774258219495999580367039563626586056205306276658856886524280676036800529831507826841752629258128889348309920708180393144270583624503924679141781718886992556665276474942605349507318130943424722182510632471387490571856915266835130751132965087890625
+expt:46,193,0:817074232257484121156770823318605146696751569369000241039998457282648867989095210690478016388511247325018574872571127938218392125122241277384005423186652367061816702091193768108652663491211481548491110769652180143820817287796926886145903321477727282551759124806922035803851540296187694499862514735119610739703337122267136
+expt:35,224,0:7434331703617558866735418205564382401519158226603733006962337038114968755942018524978551854012503800960010205708607955416310926336526408147412201804428417291385136369283229527393145734163012864208910675715691737778124973593953966099385511183284037573029373908498077607797410012638709522747893758502294434854784643817993128322996199131011962890625
+expt:48,871,0:2296771307785108997996275281694403742355413375274328510033245315525621390174696501258885481415349678804771928342175537874324074456135373852706084607201324469163233145482596686038350670427036741247616932972355015054433455747986815070761138607427191348086868570458350738831195704010357098624395027409387096510181101959230801667175083036850637754119339482591099632372672743060138882768223599588213396264220864703488219466055760560916641000944392297133620617588807928555012293449584277763904964488395570608415840137573373251523555726603443441113068235906294848808710212674698053441585803096252716528906610961258208381697805496015211611434136696039563551082904259850787494200559601774616526509976357060921883050658747159151714704641435607899726584101580154243983256304378508592421407973560468995638307786371450739384529436653347101351955239349662908173828605297840447911481941092339861863239287090444745959885402693797565521445366949111927811171516747397914656348938374407730394789915004848099910670723354943700564628811075303193718039885360453078287438644715151039299030827041903587917146772156422724773803085293734569147130667846393861058073699252566570823424630289221233864648893789083533315907406376875479011330114253420148543906354793351474113233267966052291368733321678620499879469220151506192717633536571962409876554555026897490062209992621985629094620892105629420732687045223957170224155835158216412193474005114831859911410553422254858147750406913717620915044352
+expt:-36,518,0:146115200201244140508535808225340127069092033074086594939641038813380464643092784368499957960397457415719662913975450241240449832879511228597374618467828990096974163693493678321796688824401816250266725231269351174696889365960762080267621636961848851793903147492257687807404324628050042266187673582798121678172191086987308854792095986157320245166750739737004704454814011348168427466038007182398317491734265151076778063010496132619211679988260689473089297585811096036931998406782027461402044049893679481715416361137493463388085294521529831982907701884889345802533151813498254699533482401990075682782757616061340632427940899702653394635849940302575034960855494543054252959646383879992036574182030574286127878688271055584323109202843000534198573252028967226364808637164514811988498672481692393863899485418029056
+expt:67,225,0:735920003111339161159356395080570801473725293860740494275221824045023812579963935301031775447575688346607267267532812956137018229766093126468162396242424350409934923304882749620115802577608721780903966951407943056069309235411902308234969497397301699503940488310770219419812977280307849553181552764429270926502167344901946040611637758836796263098836023546748650013560091709744036462304218800125741698559917914307
+expt:64,327,0:417687513717921146683814441049501323149276759827878850220310682498444752633939174795763205590085370174509431176916209651043434482148970466887815330179965962230671681555803952508317812856112304403464539027712767146228053984109968456131599036017965241520523692299911631594821772907828969071619810063458617810626197420731690747206373943510385502671614727661759398749224149762165354813028102550602008280537871902180618847076481978941607093146933705617051198474299205992992784680935699867987139285893610877812099445086372781691711812234396546078333906858033970549278924593901475494268981324283904
+expt:-25,467,0:-68862700495331938784380419966649877120052824256986622780279879321123463371356437053662605722822371713113741286131261775228105217869324551668789632411755509078456849695493437707718952335537901163716308200277822404533843040793058284766310091608343833157319217838813156052838258955825903648017660766106461430902101129851205246720686051369993734795826264711765354552138512394382816264477130422900505062094863105482712026465196187406241972801187592058303442054845271865009183194933559721460674706658198949275466978787964466683095692914947643154576581856285051087744587327756364233631868758575460879749512993364615070536471908013709253282286226749420166015625
+expt:39,139,0:143873356853696095816280231561762895966095121358512894018038780434656905244853021253466390417066964861759354168210279589225963338479315659197113508775296585740367513592599261280433915157811377734958643545758755017210195959
+expt:-95,925,0:-247933317851371692765238123220353261074803765143732218785336375547364098379952983086176914411708967965243034975624089734549054262155405601872988521853631418092306768960388547432760579266561975163002729996245381862957127425938796307154036020276283894081669921750185924525104091927547088831951444593347428073211061542081598903847868922087058124406471582647813289892107277092495163694211929855009513467354559044835615466736137087947544617589164470286717500588970895846757222008275492885619438633488692498481179512599142893182301567662753282826824205385088400850355763371781678525389031580015072637605912123616365008472820886799996936155624310901771575510951295719809269053623900174867256402312047226014214451002303098027112553312370656182542716538763092449820889312056658510682841044062831350452293919927832336800994362138064805630261807651118108456301725299789286301137388212766815512960048788081683942442538085959986120065061285006871234949930940185524537103913351720159010805686696397758933127125408357428549627886466305653330611608087733791050176139563443301008883800301224683395958487326723987984535755499835378139919056198037756593511533680696923763042182818051706007416822608172896694323975433662457082439992053758519686924061393975580909143061424199971052081917912118305230171515641167651175575831760969677740062001963108837109680812905974982663520916997121589375625626487587266051342244289361033565546995111061042957242305246986582855170773641851842228652472157775674690273006693174629830847980593151580935023679044298283432329850647778394157726704922914014083180482909180414233817825446242940819724654162541194190922934651789175392031213637280829578333494425326947316977013855379710169610940508930766848830071334425047278453644935556250177705704902919191612346964146136409193037371777312838361240210360847413539886474609375
+expt:10,790,0:10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:38,727,0:318181364845266673293939034580700586615440320951037592693430676258808017944424452887520229213529156147652152548660229015222939861579338359559018300102639754560937092707601655387811647657615783015052071118531074778468055452194170663662420447464862055872460088793374322229582464089946075887299294193817540314008779527867126627186841075133467621258418817935949751545729428873936316847772054961100333271621441963886222050417381885840563709089357402135650374520106690685058742735682668165890186931960150146694452795036044289394868653254020018082650676484218338479013477191914691177584198123357631992799912818573072108670426678744162041820440354139322736565922639316890634686494961802003379496237970297257659344819835969921578132529764554764775387964765201989940411202080226725613765864563543622841931061034686660258178316702259830705725064960086720549582591661146532434470239211074978214823780252294240896745420707470768467541239033990368271634631401684194520335589793556924858688944215388612471082194103983918698849904549069496888168308090987990818992745725204687937832492824270761610420142018658784694019990897837283216723902382526473775384524270600192
+expt:34,140,0:25529857218193114702174428995046692565363901687129767356632099628880917562050351316339403612051006254976853376622453913126272976393819424111873308895894292132165245320628698829331239739743398255119320169479694974976
+expt:16,677,0:154606681340974124033724916902627302485363041461934511562903250082108656614988464109648607664350683544053521938530767427600678633466981349875552123311129851630541427823062009528531348391461351902236714300408426870798081310080290256564473876678342716043349504953916566734770683646870083782168391645037091096887725074202784437995895234871118748161377827084898726055250090503083390633622079852383302615813886977424887371916745952542456924382093237294285328320534432277883419048461987671479977721049775052451336009020607051890596444709721396693315217517965349881355454288834865724272352477664124571092063711425076519590380710563089443910597712561034332057450154631167542515719607903185440744035174760067913386635899419010434568177660006643202632247398908883971060098166563478386618325197936106985114484308324182451552256
+expt:6,706,0:2370187868170736180128996880721994304027981016428826558124299374475962263011616081209558299337721916323935274576896010123644085589608182399969109349184244152181717235854411892769936008301419019510706362282451476374286734568331276868548412899353395251910059734878220922682256862053827867397853562809960786231614060068494140882400067369125402792475819991480014501511652656632709028304308993356905586688240373617002392227009641266162761580915216325822191118000345304381153590367158129348967240326861414168892378280984649126875465847201669629322152902656
+expt:76,281,0:3225666254982005051650393297063271441718814825117776170427014225270006782094402082487845256842905212014111773807699305585198980793893448295836068068070917535721168698915088215578832824619604662314479653278742492907609252295864963415964828492105414048009356278895083198343094504871689181249621303435108028838697311751040340640118912946160635394223543123655902100316582935791118589542551193090214863975492460201159924354445816812213366018820916069793903958454530414527672845513966606441240056930757447014687133057326317955318808576
+expt:18,645,0:447471924335366323510556443313429700068812234629235460450763927673222040496888107200760252341703827945191621326306131795482065495578664462850472512309208303012474749490243865165651244373346115911654861626284849310331418035860337441989794201851669712221122090746182713388579296175033571904584078117965994933295275297103840168214754293386003180820988449264532865805743450873842642690490009197041409759427844949926369573051943199612022394939265067082007558614061463253995880975471188662315261624151062500359331883381108257415114898922045511558749525591359567772810243728526346583785738997208574199792837718461074881349077212584333624940968146337548498271397497840948183881043905337007166709139932188874261432029055567751709278200083034120925981318112036767874722249963589907141208823123050935466250723940859117568
+expt:38,388,0:9037233162685752053376455537502721342270736042628911593411187820255850239811996204786955561847703657226822474981226433833893660651795689900570630384290367549695011356487125952090574619505343150852674019087633094038448212974827153618462678721327783567647950749746305048046039645769130932898726170627803026748555303885698486663393441172336532741462629794066215797431699115607727238433090103791079601594737166721617874568124700807143370244859773481280231903946961271883712351477922567791456197385467880154554338880438639750996366163411447302912395804684732748389562157940271392193893922966877712008059498487345053696
+expt:-53,961,0:-10693273783600734316315714480041535221366626391070652169481102268537307894640601690397477696258749742562195832242552646613189180449413635841376794326217929699139495316029126112610199345461230984883346783455894745072918234142756324123553503913216798272404688802123185365091119718074925049882233927864436065352441795323304595442144701951516685757397182021033950771925191451161942776319733212924587917285871042600950991564279236504812265880751815730359811693631083452415593025707823313397391467358190650783232378570454741033068772420053491342610776102390217648020227762293217888965761840533847099886723514168515183975698570560700046391474030860444256074699445298615381649814262336045393110771426131519842556272342779016381298742869204722523464017593559562643622326956756787868098747774454389349057962560351445716834035262214568687712133450404931561726575840016754345335968416895437533133106784692856314926056588599354521991402833078563695458116405668054338438928149786528236240697114627604940900558577671850669754855161031297481210200709336712927075772035987106414260818355636404688451829315745413124591033509314578360848228738843568098733649384111596453174139763494748428119399833236094765497395040014927396796803419365269517770431524291886017302139482314655716680780294886334131069691255122316199720460643469796601064562003254702066340683252320430491769624200733429385588367602550126577348991899954540173131577135256775953664267528916851026738118382069532086600634832714152507186748303140799773366399952508384413524462895427617680029976682845372011808593897598687010617459593771185880907170544507963089979836763018697440064683745136860496786467398309247801653
+expt:24,659,0:3624167720890114802953487528882213552899975941370552554329513099376544209818189786714454437032689083823830559210703982255340689476005362403899468531020537380006871571749241446843383626812449117417305212547159344386130625689077819341774113065166198322275559097572679481175645104461252543777972030011842688825307404880548921803031127032140294965934932124130451113999567382233597289101129667669422461740167339579466317525327207235602937780467185586995750085737222095672175124755623264554299753026627050426905461119988938722765511047677254959618655219659560371687805940337041876822078905563120206071769003516902911102160952293062550519277843309757303919027154659813054662466523344826296354696819676501832559230684594091362492325587744451955871184496572010101281716464201362384124303957980156819470050845018195253142021574427135662512522551131249157276857182203346963051964089533177481641786738454705685271070900224
+expt:24,87,0:1197782680101993558280692226488373902822663746844330952273499589865047835820100735571943168026820232018026475094146023424
+expt:74,900,0:203492195695385637811035038604720591140552513788947796070956567581984736792471731249691172218148855021082026970704996363773142346074349135425135963357684169839046304274718335440539737845426708166907155882416103467979779965950248991451379072444893391480544023125591578249908365143894932986279251195201771680227260763948792352936603246330319755571622810515846412833416610215943371396912549385505415900612631771649294092252136231153758926269683448101315780244106657481380278801404098349704834462242414233848548074782034341541814977421309404166439064217724352480695426781157497383082801267848091972668055615592471820028314038214611664559270461638562962083716708158789715725864674555451425781736717842336751000970187435030966278734709392131234668572146766791316051896061637266899364682542146271901296285157019816702372549096549022107433241920866238031206698288958221202218632016024210082467069376475499042527317812114570642803224866302666554372000471823903015245471090472707641476693056302565407925873424770841334676265472397398045286273466791200069893478024154625862765074269711308789130828925453589264234500803624442724824603006351547935458354176575577193029177679995128433886548139638707554538291806471117578045308611020975110487218424109419478440720096710842152057246110025136351560085959690150206324456752232548848972311293881638155478974286423259965771742724362278920613669975929606425566174524456931028511307439225074591462541836290927880691511343917965103496059384368500739378244369199231681115377111475866919320958869237569684233879998976599199774623618592008415441793489599256106350578620210330523214745293501592975212532951752926208891738168918126903740755841015125828096229376
+expt:69,543,0:312648443078484768295888815598845711939768666257291433888513312757955049368020160698630214239551072326750999792081447984468792281784366584961486617285817648690364818430979007147880947832896589374742603762111790546410744285504068124412810547392012131346756698151463417807121112731347729403260984454420384883458358195998166979494748478670615869985947232052762056592943794463276191202025608190774698452993168999008156807611820727458156566335247124610066310858249753566038784341494062081025248869417660801751147084173434635188719725442490006572202113716375420781068822739057141812677299815087162596322545640703492929693633783845458495004922557983277693860984056624336776034398970301860440468265923692038302131802660874130160823777321529100807734183365271603815201483619478837176405601832237316540578306276376458696902711394652750821782153970726977230649237363702489026445302222042642632912600454038910186382368705894343877258931593200635310200405119407405120535210771274792854910251876704104130656951309
+expt:54,530,0:1474662736655096656312338279909177255103797074286295793375027509375168436887287143309336449315957822362332074972461382683286797326877474651509739917544753283401205851132747553963526978426226509486446008694568119578399112394135310582133814792181430889458385225614364665191714345684166126923640114344412210292872490366419258147481273591304234282967518734863233094427554073982927115901949385739053040841288630681194000841739865889168738376527086934295573433603264828521334566838823869117642465232442629165125207009991732054135918621566022150672289445131265256648929940581735965044254187533327954696081027388229809762269205140612326771928146305517366531304549928582772855377825128227036208742669924062385323267632632943920240050640881476505929970785291909572050487719596150442436573679196485824822432870194747280187996123290839971281376461049282852724465409463771310117744414420026630389950888196241467693900151918455422976
+expt:-84,689,0:-673640355906192963680854382395597279844991495307708500762664884953750280820203051032786298142078133894280971340126666823703549559943495473379620456496637792111780395798111098844210312668985085973564668031838744003567469055747069065192031462953751775303646522049111090958707099958568715666445558819096127800586726116121938372786122995565072105666246516054767846555535819145164971484723840655291769178603047752590255749910890559652661832177657587633043896917516743806552357328358607488168344891668330944104480564369749820890670196494165679972464070728580289276173364888339312490946125601330630747303595303211714451602985604824640650790788957226193419801364185053958966373216314087383429341884277698769522842899547363770116372724893917923171530322741674875748776826251410886127808937300207685295104886265377799994629948453289346468117865398420831689205702265516443957514776123773586799797709730156072453168535652382546461520516180270928971757408912398951511864855349540254511900269624608773339111608340753334445558782955747228498729808997160178550956563569619227991188807243565793371441378712685201693989991158958417406905444641725997669829449050156320054612300296488530139587379779862430775560465112395949278438701569138898951204188270163608488455419654051297485964746817157884159015683507047747566104920764542724284450774974464
+expt:75,389,0:2505136873002946052821571944823592082408787982442343539331511593683631375266061611945471197761357031711510886915023731134485877973866520759948988373363766768657863172035979520149693975667330757807327190596028499425293356360109900636077772084412582887566894237468021689121483843531949402500679864184300241610176967959666214567894484564567187709777650474627724716339736193918464027876178424957702442801379144695328707996397566477572403174056763614383402310541133628718945533392880172251145025200868578667966567102968410404698307362393252463909620132842830908725719886487634875664806284931154944418880613973079280757557147546572939584559289443428088245026515302516929139885052576138027479661467278315711837421986274421215057373046875
+expt:-90,493,0:-2764121656403808255688998318308448927779841418065114299643004937365951143205621653706679499387531179825563949289390297858821486365687544518614573344000251044963118567564039833580386521905044421727153991835591278223063849704280112286033144210330626593002183744292468432067084387118208158609151278745306808847873085867331739532972963860539108442723664744816240576949951467742831617638950862455974397049424866492109130205243025439534284350885748646940037382914614547509931290000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:-78,713,0:-115731536307359192637735081399829109511702293973922696694208047458262444229652160307279087329855878256079999392518677233048314972657057388874094275182501289421919041337127404591027574520060185351444059593154392195135354268588962536879418312873113711549229994647861923000955099677819115616815194464713534830563588649882898053840400195424586032548275013843268241516993330630236304363211493713517911756737817101493890807716278347242379720375897560983549657660651681988416735332099874519575576530792228244128002461198707035814595388684169319814963566786245098551322585402939881500335265639906067916278437416968431351004007211662828198106584287898060279705437441896284017744946256629249246220165360343009335114244569954394057846850014421787925696186369699659423147781488451057285691394827566399868414895988087540099866995327706689353227627368171888882696031349643682455531264058160696858927471245322701673243300242916477186602464825933213315337095950543131154067825494224012789649177821755061866161853106394589673669448275431723352429590524472448401745233005597262909298660312513585040969384431420061687766818410927875672704386212307596396632002473179981323601609734932089290982557135462892951962999979904301332318424478936510361126749344194878185769161091829612201395286090063520676684836034985334594621505414563276756705579096792040160061812562668290048
+expt:36,763,0:287612717441501252938235364995076989912258567835194305503864222905817654453491398558770456798842563403876433023498607174234086604662738885378449834211542708982978196216184813939600530734616215970579451031345428619291554254395119224829150049864061092082799955573360133603219521595326864695021799168684562013852249376992623873343118112855686115088808687279222093858336092955998950873167464052797680801992263797310300356797391216282203047175649924968146172953919714557432086976362430640363345164555500849478372610459794623063760436116166308460356269543727122939698305973093062079308977070843850732062284240023079465164860441817815804509328285118427837803457119764359138865084351583806289107350041743083265057334370946088906064154344591975302967899967697344349561592938790173718507304039781398805086538649982989194487018155662504702768958902129616878720294795677270817445558061795402174726521022090102401668102031654702766531351739548933899772524672856784086512436602122477055532078885288888908773574437636605795708667526674002708829716332805686493462673251888541522849276838867497234297868970484972490798084656418668432596022103085029156910177825279909646274306163059443534849729765631328256
+expt:47,567,0:1200840839795357756556171793866035488669397069402218058853429523017606108853866073051675237735344222717110142579489091060363324010183030955999583202587790744873920391925268687014453103791428866488369403851229457767518484585400595793732678736929295286963479405802380386638374173162627363885156520588965951827128250889143941188182953700926722256155063001822289750113998809814892368365148536721743814094413016337848688568918084494871619775117616358924448269763664022118923055017911137842861355188743612895261789827872451309409128169082116168520009588315723475618309774431818335253416491565575448829636518484518313005184981691618323760943375615590224232297887531959092930319995333870473790498756459817363196667267350757707139114347799391414825307971212091044223074718730556986735254848581373154216006935257074685468225843364862663458199989272421190309964881842705492582909183953774649449964290445535763582719721041629607601034000766219103889698770634063
+expt:93,245,0:189811445138907350552800803028132318270856486385053418037712749975151905680839772940450886299589953341083999271531699036629608182153885935579378849451189841246877163907007586748371382526385877632296297367806278260073619502837087612560855634258114918915142457424551221666268613973872509210548656938814203992202491112249204302074777529915290725274509877730873272245110513173712234923547513758360328049613739612358250332564697958770448525150872819149530642122991079434707200113667499693
+expt:-32,412,0:132370456868089885903728134916792123229979044535154622595605894871140987448802881098535736981597853547268988767936094287847913714280410812805481072174892167662104073696464879991808809985596015029436652086821140759661740927560170521238888834410398394247502421409940705455667510851752205552056534626811618859097761109564081530555125656725768476650930897040696615149886691980619883285333853446759459196371669470109465000830819767736722846319827541624437545423803544499106306804575519579034243488673510700931803310410369834741948404811173882422130791081531135326386594346734508460627224488365883999000804776390900106160766976
+expt:-73,370,0:268817937446766145442198106557555707299852322454026359428476916174845729180692785461163460485079723744959939462749245845895687904735816865076794263717604966012182689168095690958838217033687276040045060280067207626046312195168080651837761881395764886113963753760834412127698107460752445557996802419849779908408253837884316512634805178240609167419868913614668320759158141050801534936091723675844304423297869129029497377604564133226027972677630729381553858132072499006005550335236095584481554598465568525006973584347149020417329885051185116957434174133558557099710477806848859002101511273766789849989896446599654420469118962896980442098745167512954118478569833907613848252608011717544208148049
+expt:-65,904,0:7476088006612927635813859446573471148405722216005428337873036043231186079958168234655128261355783807158721704379260915957758217822077621867500440560206384169070769533159985551483020985475710683700979236907363112033644990047101957273046170714199216404483780160537007038623527166449258864160198748783512961234393617386826793415081976514354630915756963837537486398859606568067746395464131895813501401617041983662268869523438391204770495826612433408765458410620435663877807032464442529968477115921940103577390216858052825708753864587656082968468616911026081653819514030331916018123044661418565642911025530870993821616297682244798142168034872991984538769820084587324504721191662886576517902618307361704402178724708336420139149948284282543262975792304028749420427332919952946188081580583790225269482964488371646996041495410496609499748805494361565442458937572152995474884127357284721870748060112844298373068726360209939266659158366899951921314063488385052535648321076683428148126105842193642286024992930678285755041759862538217409572268726649499499606980773383704800598813078039204400082630771801675842668399057762298657807788837860460553823914353025003459058307226171183437694740812857306950156717503856430459650244670803765893833707297125156273455126961026717976027495374263765611273780285988547067568437963799276682277771865186868699849332832741068240987335316519864763484922262355869276408357104152723004824262877136699430206518871186162960291243767646620145129860636993132567141351134152092406933156142883106133693959341914156343195330930009161411582963602590356021133287170265873006021777183311414517741244623039165162481367588043212890625
+expt:-77,614,0:2019785527067220859016075096184821912149421106403027443543560963240192036701879476616954690218222713063782827876839369054281035769658427703648498436632136421739556912595801858063198011831673005695866824564211542399160220651543556138188133469744318628351948574415103501052771273393981204066697612765091526265490864745203168780093996025480290335505689022134191478915929217289966800333369370418943444639005411560553516922153999320601289370932595922673608497374963224036658222600028845023713848177941244589411074334426669985928674891448116003285619161392614412835348838786861689490408617856711975955518135283909499974832312293000442708315178452215588031532966458821114754177230599064225634988092966765366270357352136983827262519338412138264927508379009517645365508020391394723293691499336705517066728129446273985998316873616836259122863394701325807912500191267168031985999081769304410020219207253073778474082824985837553109700468359743907719360064109613799688571311209634969765328990761517943042264537196838333401400347380897531424713195839839974898196239469825106641941501788961002992626402375484540632168133513967413294827065585616353005356965040287767941447609
+expt:-51,351,0:-227578803811760559923803665892351520428370789673508990418850061972740388632750522239984381328651663024374140778482561178630115570070474657027787117315641203458108979183298782364210915367865734034950589483411688132192087107896659215307961790261180554632888410345697285434656919490027197985190413884000757019718417174783272092501346827675850086279238576158406359659768393692045443493046761068561458216727137559396464882832268384099230639577378336557744586454311460874543212467858982205362934063365853125812601286856625659044169653638370861329579070059094709483721882329882116015560878826102047594205051
+expt:50,702,0:47527289157378995587876810145877577731621780159337975811043651439146356231936805088930037426315546580065265737582454716869456561094715587588615614596313199454696177025793364822808942384619882008554402956376005194359554004974096403788137885595666449606725010563408965535017560520176300458833774557317910487124563377753556232426423122662213885097303501569798166547963265331566412324291699762962584993997746712370064075751466905079402279342701902764578049398469516972909332253038883209228515625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:99,984,0:50702746367732423332636756046707088578844764784173362783707521133315788404642161576107293454340562078957046303833670333713130937649400178138638781061468425602312597594693701873663307101648324074767020103581094560099128401539216160840172463185716103882966689828690031541684807314202742848158232180498584873013282070399063315854921210409313246152527668347143019550364225837781560926140640093081116049657971469048051468284711694257785789178809823941465962040360930016157617452358728751181336693124773903638007273836503394835409596627165112284850875254019710400215921524572141759487839278218635745589782578579334381032101526933997551326789078325869307607100354120311604173747476470292725643886125380388270758769897729363768023262199885056661555947313285025375746755494964841587184402442187978403892800295699470235365305791026570731207454053082865363542424265608839239142648022105330036603608639151764223209401458833898013848306012540918241308571343492002358749458954575469142998610765627649222413431262464681890620336354859534385697259957037363331495002282308313059575072371143057132684161422385180562511230179934391119387461580548233050228505428143177483520819923735804035411728110201914987438877780430590906308303881797836439366427239746559919144471214829376603306425594428226006996275012485608462520827573208905537492316802360406651053484551978898843772619804303428095512709190321751942504748924572861274319455120692685486947434437367729541467272766686966807916370179754298758691241170194777607607571459715789461966313236323523592837374223651504636299665197397806178032081657083412157743291936555271637270327920149177481942718892398679774780630393442679911779866113264527251757137767743475728830777662545861851530110286521972777533327238249737517010066472027602218338978796182855291347346819511885654909739106341730048204503382676292182395762019301010339302187086865618764387685077382309395957419707422191992883094903391508671890404797538764337688679015997252261601
+expt:52,827,0:1363845534203275602945715020440112734101654002035408092138994948157965218152597293322552516013541102339042395990176596143927924801584852182694494402174469146476365708253904854631754423456184213955558063795789571339488371939150388709770832326123293382199321743931181340567197060909930816221066728909932740981323058976498861029285889367417218324674394634948477294304297443288075797373908416729496901734018773669789061707665790116223052131538693972561939226658646132503581784089567145866185449011839827233650866407425601793037832263017989277208429957875080013654195540329347914131526642439138839114974367753637477200190329282310264113595396994805361388494628682431321748217640801660295524027806208203770728640462587823579475986549878451221998889514922178015943053639821129315654194174336476091685209054536280060360926059507789375655383925910919328884755937580198622348199281035939633612639571160057396942003035048191323428551521466383128724883857629281100336791723016090894181692768913507036769585784474370724499814943464300066137630528362913596888302207349032278219095928598441501164781762405564581223661028609149292490970074970826464288906555662494076317777084113019235504450774633168894206571329889041276981381226535278534026720907837639336650956477462141594816136215684669130211088491324847506030723793623545095412834551391863147335556256713198925300756827943629425257037444345305406856996887201268436359318843454128128
+expt:60,323,0:22021853740468578834412999517383915986003725826542069182383222392560149753844176723050212105982537239537599021478108969602682255828632115769764860327553473474873742876444567203370333512921531141121798618506475910567199986084415121901524096659710646681600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:93,407,0:1487853124884939684161385095260700523967859232818286064937128697770803227477244897265636431308165638318966698855220495473642835305695739102629480041222137050463066756784476730673688602838369260908469031821258574541365094727586343393304192201159344658073883254741254481946525006070001016365758933994228518537153685742527173077615516552516989509505043555164058392121782339357054879545731381596514378851078834808332428961106140341211035824086439359162868820393089217972263771995780773037041591155928597930802603797367287480285258739006095757736651824883846891644962424204439039748118255361764570889647940764521065367186406409883179355871269579713473352431638000331921603972636225043550734332376892148456648021902107583989118652297791718607641268173465287735838369363888845836639239193661056146350176700757
+expt:40,532,0:1976584504954205257348587370301926826655826657852950374579114824486624409843704559491800622084346918898311307268718866322166100951033139422529427733796274510952318596450843372699872145918879065832419606235085401060175854330319264634942415582511323792390723208128503608909506002101860376290882104576621154915114333409116160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:87,730,0:706406052439804276576366923069975401164592339719248046363175133041504186269361366113522873942837171766575825692907350413361305763457682609785452731784223726861092814681363318067351830762134706310235218630451383037256434744365437287493102400695653964561812007768770271884322063288345456326150855163077971604365104144672964323628928074590169741911380893259497388141831058301465764795085547886037717455631758754798786277409911481103533394944945594049303351200226257695107186231608269522603794233543597973234060805867176925733535004507818576356738265678541985876988343565444956563176444492195721906970792397883768414377487670435384357764529998377542821466271982699148147379912153120661855805478752385210208666518800046101644963551222667137255772127065300202085523460000468880606604031569380116746352741827362128287425183441335754455687265829010585467574413596756689179258204408286889278803328179345980814287315190200086811052836534046524248233679177100752570989171333960664035727831280319345425290977756020974412906899038592201787348761825228061083631544347976763613084792365803249527341553106644812202911851620419765048510696413924148728211652659875437527114828561845302300246793974650997138116778423178153360481516286629888500954470861598210243812921260066728648008448752894712658707214973199057680079905435919626256730123127286301269269533605024856318874090809110868170349185734499760880296308653980901200084758996049
+expt:93,605,0:855428814634958918544599433108540171368754753688076725315883503766618616635962892836439002252201637178631493204536270801813620260674345152674646475870593626683064317677060559261922597424647952067084352720270230897768699019551822862416702016439561791131256840774075776817158756158362876954703668271367349100772697424595673989246853166711784033450960087641035381498697333940896283341471626085405973825001412103159308752988378154950172135332537721061626398804507352072137874822359784882151232478545958168287870325307214815056872605634979408681579673200606265939799910966127483516061505432535339722111470845347125788524278717471958918210481766553564146010755715128950367184222764324448405602954498081027273677629683607327120669429941319549473748000856525799606103272316670237148246821455126298282076072799525481524482941289874128889144124068775066511048362399672727230153446359840323405054769633940438256055614689237151453949465506127337023888311827938050913222460384888518805017976698191594508859162464655030117614187828782625057625442536831551817101524758129922535918617854470433795037085700145033888156152683557013427888199380333661049871576750433106831383797201751809880804414028368093423693
+expt:19,963,0:27524390933462438193837863038173257600749953407807781713047411800439226575830665293723529758944853530204290511646210815182136606877662463470431698540803603366243306719651411385140530410420060215533879433895666800137273296375613114999995493626942192121350040312694984901577002074624731875041793317359566297539168950875820565444735886011981922691483574660663239016046035782355557105396128292283603712352714496861384151418904174890595393015389865531243654829040983885834314285234495791323218841795533872159352451945484907904644311539896414067347389400151749600657579278895960573693934814752676278273915895909394982922563318173736071016647179057619243763230042827139542125644226762956903187476598431665900029305113678469725913961143048032016348386870923089862955467576132232067430573022824628886621106941902269773912408414386384958744554226394315986912008000652067452553259073901900219599312892013220890882796369063146728028726932516237716682483149607295171755157994925014520354281344751176954994548850375523372990992872608235206800552848373884097904303114896951128191894747953292238976905990208894450092732832100441840572843532041330491790737292506221131878514424077507009732780885474368274416396249038243621795514514228806975329626059
+expt:56,854,0:89655113212012673099023948416704807879861978221153827237199661778584008468165651080543902613878620062782298351513276228294432072744284649261971266393894256607375431816304583821803793716587924442301007552505586044505538442132617485337199937369235592237428954101205944468928491652642992561924170992990684875183153689532992782682092920117235762980760669791412674782564117374541646440937370311927125956106266172810510670685525518812212950138056170979608664706763694733342515990968354863012666224960142013969526617072730522216789165659791684923653320596610175398020948129729808736281334106447129989405194534944350195768931899586302086738465979769199582498488866115372356961255007890457956873669299696404273010639537644911751286565659364626323246621985820562215324013173040199503927765343915648047310527662125096994825235508795834438673893661434170547036065620501605840890610501329654028608371726543612867845130909422255505338304701800505808679604352191497405251720910198472034708192083380402820761289291643085960629808979419703266679006005273854103326911946960981639672499634075872556388250454617093178267203875157005188789441834290824824375362710217394654516436622832004430364564578406063107709727937712128720552024767984099273684466490280196940322959059058007593299284990312017697525386129849377270562464418952129091640339393380715993311611910305891157877528570148396220151382371598274439328443130602108218216942517868406522662920683285329640812262460209537817661379779669996166934404739153002496
+expt:45,612,0:5835236069718882114506897382533566247377415373160348322335381401959804325982764654985369043691019754782274324932902412422919504450121982411071559141523227598048101908706172870018726600366871511993242258104983964714191482096777425460159405868198347157194247010711764769855120922789922675107180581288360243567263537448253664324716669975682189100014404252781455216273744498335122639653589122310702857513362909180771831512471469920303997788269181344157274446834696917540185278250066349263511743262735271477684129972106758329375646539895223543706592566504943908712300110805454844873245197309482926904374664094429569566237475738252689670337625545730148780598867696059299091915732424441403497739984466234589413447120981326541342694519489432552938181829843044368724644161584697373078490608422316687980922524068552209758486036117805534388377565978109780133632127524991766800756255658237049157308049222993126272044553147845347401604176748405215264533091894230978452810922757566292930209161937682438292540609836578369140625
+expt:54,451,0:20397910418377356550287300571804200557786099666116822595739338489264108594693629585863016865675849836447133820178583817056787257865484263341787975124682123033432566176550892031542044673807061607597691619952835660477594361209973279361945781375083740594965736649506183676117824430817491153516247325248281553959922896499435214529883689562648236636643053318925258184450463587681659723559391253678624035379856699358467799364301117153745186153084620238270375863919362076592257374084773424126742009360452069312697567282746968871243121905805216854913928572510658635514695126678391222696789673476384418005261871513244182859164066090813969042874136599996354815022967528679816614580768946293305191453668744093542408847163544646677483277319352956875504219155308754191860667890267580442087522304
+expt:56,73,0:41469229998734605907229666533990439080884762393847798172038084645287681671512979662987869210144861737361911662097025032274313216
+expt:22,325,0:19380780692127535243822988975518862106688283415440409657318777291773460112826177488864304471507503296260257393000381968404530628735640782306320769328605753305997492221828698343046454208648959261843736522465022722130523152030591371634509064404845763380835114201823755461164985487277973692677490997892134149211679493862203005748191879355934593251640178434694460018581599355100053236481539133268074642752831875821126444829199442221499154432
+expt:1,259,0:1
+expt:70,28,0:4599865365447399609768010000000000000000000000000000
+expt:2,431,0:5545339388241629719156828368286167406872874150751633150340959161229242615611251246079948812208279156194782421922807143657948315648
+expt:-79,826,0:27540854187929799985257468247523155680538433703286824739517469481759833990910653892340315597031695813840072524465738129420981768137177778398386187136483179521533720543407277753119393284152155957481914060287817028607256937594519868156459054669091954974712188347267089425432969106634444194388017265965949995692097701957114472823086198047050856806061672798574128287158999679211211045866881231653749742181206820843018712814234776885483960209113108635431190289016087501917845943054954808695879153901235902843669634627518243307894193841992956050535767242625612932115880911409609569876836530027970817956419533492446863797815044925775952042741550534011707510148845849950514957657983203500516405099685290711977967093948805920524360187028296830546987867500833588472504414005192236672391462985520150287811665577020744455460650359790618613062093825277825004505744707271241064882064070718065648023094280188167073044844547232500114457694590999166919669094693398432022411757793919755408026466841256100301169395413642500129881284167587546361348378140644375492018741141892055856217500455547981975199608522237536059854818106117812566998653773404384267708945402650064006573487698794343692465354553659902815430390133210939131290292916108564064726731071156431583014478295860724491974850345289250462234755107356158270289808695989364604670354446702945425544248554707467316099882094498480778646008506840517719579244276824018750506251514906770636895869751648864985470369467283659845225076014465077719158624528591794989379957868089133908677744283634297198521265648631548657239277970447594973921
+expt:66,694,0:580084506530496199901715842061550478736929285435953296906334763408916457294745083700943659750072194007911117976928910771034469652824787161140202192812060086123933696794422026495786736350391860998721709184616206282429321340426294474560554065373638494945279261660818135550623361880986266761169809383156965092394530526878349935560951819098684650456236731366518214247980897154666883115720824687584260186753579248039306484564334815454921665784875496640601208054064934367623514543431818401964065471753818112528393669877004534296514842252720036344695851083439754895878703603097422007514258951525128317284811160997854687940441212627578246621158606819889227734453833088076792053010410429208939580294030978672807007323066516188519488729062055117608304054056122408278794377322396923294276347941530691555115638860207628093697674034586478685823166311562429468232346680345400111368599877502918619287029806863424209567337550321781645413583273156313569257554412238414216208778666350590080290958187713067860125458768396034295744470317801851373266428602679222973688293459392062447571375823266655946023131694535754930689276382991650046678195497949989578167243234281923601875893680839438188017891503234218524380143598199558737455868031691457764742432465500138998414409914742091022336
+expt:61,929,0:372749204262219234661028605059600082005472058401807779391175774103147347020721809274006944812742694550566021615220848169519541529572954087195954262275827015340392843546317426147733284748546026914169745283094850736754214694252834868482075113112267516722630530017429413488354970058983032863915079743805868398514511489371415564743824566521175475718773953538278821907613967819226017166214104739437588073569813368813398149488565589556629477697737427900926249987010320503591278599110557450366143792209234346301744107084844660292442687200498652998894095601669905889013178322152368594429857818699973029703219264103421059688221938804094297461171047462303386552014767355489371231645242214605709573806038882091320000969833466616172674723281820861230659720784846394592186695882554183766611030058785231355760030032991550909225744604523622367813062613525325165760288801654110165225918836315855062845073372541514571337989620384391488490776891951817514249041749473163422333900356474699047977817400879900507930748372050203706672988848432054792535888114117248293709532406518972437029506673903536575555598954258917589173484915883729820461151786963746755203344621234694493460419788239808892616004989648342937608880857613762630401759659568336317724218590545423848713453198029293212741308983125342860690464093569963158486256404302217070545170719057156149028351035109222842931378174195730467004520244530634927115724793217592798273975809563142500814120034065476390178392762733701597980347726390211680084858484316148662425498700389466706121929317730214556147564067838219041971460802562516019394610534531801572433089111247198407104918760032599577878951582322678994706142652947962481341
+expt:-9,601,0:-3160444535448242529092641683723644059539145692308657340859411006936058865374641314408196086827043799075550619379423798587542309132164609200204439951579781831500807632453119338125875367204968679095724562036128784121814572255501838157522005562307704591221323902634201333248104060896549891818729439534161465226719835137730531986768862453929457126667118122860406909711654476082395260883189301675745656233295957116371351513365076222859294597957033255348289403621311527049289776180957730267554140209309181978595028474886982653235278904914878205932888067162450567679909275108376009
+expt:97,61,0:15598246895092955513443352386309396583401527586016822407020611754291026801166140429261857563228075418881342331811243126497
+expt:74,605,0:767698049587939197359683749977648383836859839557642912409031546875066993197361480792391911022007587571205286132111673072469130312439363390154975794877785145691154425588220181582417662944285388056619181981589072518943031753597130867006603410867195350232262952739727149609075085699454676389509914456400111058880374719374067186562888441743787354629796015365677880935538353010170412164805965916706642591317263073481887535024205339087233459024635435688359086659169461648708865487255695675398023180920346709788305388156864497546177737256623458491643341041204795577475348427124793503135829398978121525554056766257030843704524575334061514903999726663601269068024921811397693529872001218499944501992703297464998852615587466138862714871448007704439720092007333440282216859169819279737835066578327985762318343795059984146296977874262661155133530578457531318820157803398989111207312212355231067323772033741977708388313965862076950112842132301934452667454484343330105847945439333136829953705856876014817393705072041603637057816525800795342430049224928087060220666508991256383019365798391401213524865142728401193068597503580931118244325830426624
+expt:36,975,0:248278005620103284639045703633892910971579590446576896390366023318446808572139362706941322105353809474568993267209279242065096446488620910399483811208530728287594195549653360186846362277601130595472769480324082311203270696569975943570941969562919822812104500652408711500447873544596047411274288014555337548896670749271601634625491645631804888387660782682890889223510249234197182987228667338352972908620961079256927945363991111693736862822062801054752644720735597690210678508403694665212607341057194061256992464781310624503950172678945568406904426022068101752528300052652001276542298094132591990104962487076763890948081836407437498998808161080386782802526119075692789537066681886677023071338001090161651248031406605922396939134353858229048521453819325323124966146924584063700897925385709942659537790517149987487173581392712392934799338496185296838242169097046867947616557569663967960878013987948526741195844085783626887255741456401906399763700966299733165267865215995696668857089937482337710909782176011909086961041572658525585707034935545895295838426884822305638121505564930966674346565073344787297923158159728519118453365025481613806608095528043429679151758551183290377061790258979194328969739145711528285504071957396890777097691503292292512140424378576323419960320470786958549180355944550997252189926822915544222112451356508263343401791620402670748174883090503543874879537424232633444841283544725100377811657760945870884387665856213462789220780358446036998302940381411899721937124651210804520592109143837152301285376
+expt:-7,998,0:2557666612174935343076642515066804502377520561389767696864275525553001216974247274131608960292888178840788079990848858707874061009535980056363078332058256731224798188707371509890293039384338196239143157226455217716275665577013531086263168378395631166498491605806001681974869749146726373202776324945125013953453368299778708945971227290643969595629713562243419908025456961888745599561183240940509205834167387996660455423008573664383326301867960985504323358173474091543641085509125145760080557840801210219094336590559580686735948781675614855516621028604833789337737476275129016558156702593389621170307048966068339005329960325088885775363738622269191020959920658840427262709698255458449248536217491851761664583813025566114309314584253990687002952980625513485971873761776789106023932689391842584592322920065018940027985924506720083084514443495522449
+expt:98,601,0:533177103720501595374014423272499180364132378499160666153205148287497431057729394569971402806644432590292381465328310811262311129879335218558809778840423111439831395996547946125056037438926572002773115800873538665211948124422673756566945099641176492241232608229762984189514655606698161295525325616990201393228718812438865636613600881016384894116920222938495899464735527691752379448855611912417527389079639150256802359259202228730317836086556170590276966277499401959437472907925192927018522051374174184596825818778972688910983212905978633684186938477351015355179910878863238407299688657725777618404474888655212468833055969341513248604687220063488622962824592611061373538419157946717588609988450009564429746027878532253109391471912738954897803162861544906424860818226748531212662795741229276596890126256794061814383421311422736715585563600029962135442113826772475696417325421015883937926780471519318690864459664035455228247945210545963671338082833659176679989196527849975925731239343901932556903446683281672284250829662800543414520052002458669739331249230862598278859245402390741706350229540923193423152041354794777470610379380463931916503753572520250120327494841108274055472875847368852693579726848
+expt:71,113,0:155665870729530205341310326859872459537926086918288608509540470629351860391099882586273156224776434943964531186950530766165453973920218517388369336029496210775525110769905804823288221938617835119278838123463111
+expt:88,907,0:442367935572376572508225245682376008933489111316498137860990507028355805276660122793212942345797461553842453310264287269547264461627567883151291662994492100078344571908312323703967322111609104550792111450058081718989072815115851882388563478737616122984915164909745468851730941089128173523430879823706000843384957667316760881888264090864169349212921302774263449334569646606880597808832359653989122198423765672987068986676530059825422164710070729150784542517772146017930986715605834667445246856197609230392607836274592038028103289662613608042193082727017234381117193204646042933195569061774171215561867979977536504587733669688385439306083861005747682093252438793416405292269393894857797371282733609831597024792462532979252620533612898923536406352613040278291119133710169841942272610880326076250824796315291769779313197811055736478745579585246354714882550479199964522615379791935029462701848490881087210486616588742015690198161694007740631075914977342479383653037979280440452432330650580558326686619170505019301413395716564578646343919112222038215172712390311828679340129762907111087076354552831143978497060075661718540626266557415357423140554743330726141178661837462646531942496692764465824964428334360066828688839099062489813585188443877907045253387120110743470809899546315304940652259267302446808962933370950281961149706759813262075876658787778751634455269684666084979732880496655480607530401657107712607869822390372442674816531402008096066231847402127938718306972865332558595609085653122439480481119259426244455543280347111130355917037063730253045491171053471360412763262481476838567930318043324002372902635753161108413432524658790895161967566922959535333684336970564087502342071263031219942567744837673438233646370315543730522460987677141774838398907195160788992
+expt:54,693,0:3538959212637179650332389010097218547839980601093690465533384462821473107518120134643329245982087864317937908704373458854914106407415643779615995841169386600913075521454433838879465455760020550207139247760073103240863782684441878651997401564323185374793175538443983412787862620393247499479636694089753362683716397696397917283398425558068217711985447159317136026122405227956991309955957305130230342078570923159947618234652978345575496908772641954759715818896470873163820343504250486061693462131428151141184256959845856167488510754499527069147459850959898142673913068231658647704696101725713008481473114205759711924188717911743864320055181356930972595979239402793810079643314094026495828298793070503069066311897901487935228391178144871449270977053884209274680793281139427835365536821473478187015781075924946317138803162094976414459954194354095344108788615082753544608345483223312927636999008063997529650656957732197940704471295178444341702958910607189754168223147765846213872939337214235441488423377963042762703792152968410669091074122567701986969963794378828129171913930842249996279788381704931705888803023880349755565650291290845634952973640558107667121388591534953156403175205437026399021173691121664
+expt:38,856,0:197132715335944702010464928289068787258126989327281133977642459352310471635694659935863663034893224402661971507965073109281478523865599215163431556175379522026942698195490717331056237820749570952967717007649366271894056379198300178606041623775325949617283624435203477373703809019861048596220111560408850308709136073536236931756950635354870794668286264213752040997939539541387051080544346518658745783173789667395614130438466933466487546913034843807849350170476768221968845260192149232038583063007145032622472464523166365735920186939572956871374170348147525734840393491062416576459571924060826547986510253181877148984750114103946480014297867097001766341891006238734128868718256859876341374385005847514034681950344623145375661088734911525281809871480522601658340102129823934063220140098540350561496324424874246538855230619339148284533370024488661745011726445642690111494919560707585228174864187763259132194822208827893654702830695772629276887925981051128487055423282643887884462938381948997470435721291697587128910687319970929427859109724267542710439086909913634572523183081655946843912895400563035037344361397713522987937999965880651790361428060580389888264631102954948376159211750103503891634869806965067088907401334445114937251493551662240660610686055435327064505561719003363736562191988450674773018772056555774194438968053446880417310543649670866927616
+expt:-31,708,0:765736298588882623745464551248533589516728262330945024485987989003966799697519427922524828295538506333120906420497833190822172854823291505196845183135662558430608661582624850664725007618784585092336587620980112185589698249795027371672676312069829503342898152005067487306044707288099529713186820460094321862725166577558202701116811479992992160597205251212891371390724533853382322337514186669568739285186663884891566968084627353685451588298678227268272695471519080722554889447126207382826609688589782622034263523702002067627492259917412663020367888185843581319175113423749435759149520782360313210168155362235445104891714946334675780994250948917428592423464724255498014927635397210595806788729762917250871841151153544592712985783889618176401395175667540813239941136361290336680403138159551455700446304015319933056996010034922500542872536431111997459504310947292431025900542295004555040557979582695891302414344669597914053356301361988698100342875761385692372383787936620811489997313151757515795773510401149056466969197955066877735357001712514205212720669933441
+expt:83,555,0:1225578881193055029211627122654046612502838285027451787523333889078091117395677304740312290856548894569025972732093305262022262904766698517843710251028889032008071021523615947494541437140578410083242439006303675242241181694132064945370271165796403044400021233214176036607316649425463754916274528213700425307672925070793107159063558868221691827352040472536655806967633986881743762489226940035732391901428677713410085277373744973773271636779960125482940121021337248817093605269643954914154264236561300490516647836816796937996874660377751119032325126115584325317487570936637230731531209445181074951179372481656744462723784646444882817173348451279220016187868806676293898865251048319248697918535078227324297131747582957851638254483032160979834998953230605023477565269493853309225765083693484738566931845020418708591682116652295291303636819498565470825532192376545824497931844947390200802139827837145992356261755130151073475298317589343849166306928091630048941968076783492543886466245827183954554006162583165658402103419444975524038123795891288877937208254234082383456107
+expt:-14,196,0:437617814535571368432038511337652545614427696923129424177713451048312616488063444444116568548619798360728579274072579602558189605289698688298076102960815381950768025379270967729373733335391251544937988597855682119418496679936
+expt:-98,54,0:335898517749742807149149239304847110365424413007280865740297764742923286290279482895371271867934265713885184
+expt:36,114,0:2621109035105672045109358354048170185329363187071886946329003212335230440027818091139599929524823562064749950789402494298276879873503833622348138409040138018400021944463278473216
+expt:19,880,0:2009874029398980029295434722831970797532919043227819887587032786743144365367526664823247908827194455630622170606057232748931122179234484742203908570131852774251405487769265120505741541610105732725739348564765526542332365086458667418301828317751506967076229654788429336978672638225832010298145579102409262752736707461051491772477782570352887264641512286428683926389567737024065515860584891869348632484190723337772808946418211067908239231699266990927693314506689204660382252789414936010605752823023740942793443449899582312545405585967436891389485301908118540573354341705957891466220807814875490535322936464464190634279487514642962273091394501124072606449141530155166291432938436888069305529351823734620388268783707293175582244589408920429277320778044335476174137843245578718617250608413970893780067437205632161590787983801169075275248391505534693130703217363266217430925635281802546131654287314896587348755945486748557565093898213697334397719214794326654886046758572050840080888194502573280655340846994980936684326929231978782129907525294831982650961681342044316149573667246042886388298925914414391461565675869861333636998206401
+expt:22,721,0:77046492558224796788761802514088072131880275970877661304506183244811291459780757474421304659351160305442644292605839122224017614753423013459535933948248049249528771300446785986946709805896287030039183115458755228202024899421282006247675157856987007861882304710551488072995285854106976686201919909140206483194373001181110350256617582296405321373555584594309012456901291312584219573768786649572212517073683836945456976006726338250005200687545264869064958787610169087462340120923702046458000168595260841096750492141312671829384006125954306548840981666835043447963679445859020819819138834089832266078096711197961096290254275206028869494312694951676428802173538454063412657550689313921331316469141026674958943351278665317595537923216695203682252676572051050680540810268656944394976378717156317037697429183535766592224765986513447985454463834647332790672247864336230364221176419961961474234981387758066111628913552702951065406243272417272225028996432449465191839224742019072
+expt:17,917,0:2097301675874874262337384393256157290550457272641070742685181359655298484419530330975119591493945747194067982196745980906719459748758882521093062942106370414411307130989688371347312396400965251294933801479523245300205124498392914857119952454973605402952283548281059993829706858741240642855866024547671426840363544681591758614171705795900874121429015664043430807387470485214251545286572177964862773770430978379005467765291145746924901839002665096400397942453076588723612807208413217092949289492019664961222972978192822676475920744552252701836678236202368876327668639558452692524803118939191010230124869369557526977853787148876084719302299232475362067256488446210852407409309331633276993895009372306807316745243435453345840085033563601310824164178695180595270040323771052788593322649328459197776655430007609049049177562253219889705605903722950620003852016584473859694998609725264429690598113186546955167630012283368654064816468752154783362082778625443452372549847742049125737902403986921080094805248820329567053386368469178503759368276006576774606472539223477845778733320367553885443289921963031175184555111324035235498303342308177
+expt:90,974,0:27052299935047786065293705383293371594928459960636493591858679901229530489397827439967797113560000179030752129693483986009759069814344789464328028124389302229982080849292903566689398199538736384291803478523321463426163427287122485942132332484438824633259632500429907489423839508356778347605611863182944177635491198031896503926679224776089106017711039660784400591006292140993879293923209120615399556982103777565419076004780936708141570335102044570334141660285505239366482840745962298126113781491303989125579971415048181359429126117863548989486391973761921728851807165407598678812115381168882267007400683443822154895256736017606370596941988046175011944197627446203315020223655176866443121247527516304873917419276577740100216553128143639001206191984430353639022361358939550577829476281299576074140336299277402936582067383619719327798911232272710866516643940342077662311510080648261530453984792175767586937809041407061474275004126136100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+expt:88,533,0:25660449281262222538494450001863125622542059254495725488128163750941665069643744134848017926826911153501794213458141136118798686952318128330169211354566747333325537986995462503989216458427236156137402612135248417253059095443287160848570588029400648482452870347054911987033926310964969317423952372643231383031833176623179144615827641601677528585812306167020803446102194410693881507224213793037477717521197480665170498415644315118063624358208859552595534937279894843336541477825309304143549461073381212334783418760579349454160671722140424226639994874257433085267041153503087290920628156801330326875713842007053978145083999034880721014435679044734743002931660496447382048291494534747035171647495659446493320583080918221954598494959009870518773105244525770713362092498386891958081893316423699439660136195380395615149744310401608278793638807731614951269163459033645996046310958400025916261303110642807596573667882890880336479719496725477724544562900521034037056197498694805705196162644018155788990216861162622711326815130754780320976368304128
+expt:12,155,0:187539665641051633765939629010126862030861602821510134598513247329704373202067865855904581679588305105558426392209111518109357753525875656563557488739845521658156679168
+expt:84,732,0:37362626400287469786015728314475507196576346217451577972340560264817777335475340674816958024184760346347561438501466002380065324994816957074697212139052544975947819746208063697307962302948345421020870897563746896137814303577394468618413663330314199040777371901150981465952170446359267027980870158458849108279054769543589192992244998367449195186118755704549074553943383839728968976499539257576575130852721502719453361944489930498227884992093281287795552589618712166509707464487440188402096761270376491306019370966520073730856558528831146413882339665688468833965993044432654395376803788836651945621982999063779396803021750087040026958788856842217636023983209404960799438677955235981923691837336224814448363848125978496886798250942574484985336211014321720899330415880628445289132294841424914787671230730112190724165482715241239871542120185970126756942511944451784053266847219551455015565798473788074284186189118669182080184743138159319501208245476233431491562603292975987521331235533354675181947901194397959442206360514628651055734093466035888302489823943737682169815612826149059209986740615789135359084267106289623915297355833264060175823550703443673841878097340893266267479095018072578698649320448199760433477235766344924312161142440752268668342566161645418763284828712617629493206149751363684796869848593636426521501235005044720096689821574083797399723544574440327020813476324227172574108126760343901889888256
+expt:79,286,0:526439064947238802053645461445020487916872652166019614740851000911432565395604993916756724273343382808249492973087992062325249551325359686735575913143465467581047691930038117373467695602824586884710893085987595912587448288044732217351433963632626007275558435035805433116956578902569644720408764508101410145243233157169608100135310715793917742521403034578354501408583090243486810991762771487300120584737790555454222432759955623420408431532698387943150871884498498636773443364760233971133647087214954160646197476641876831719032258038195184329121
+expt:-48,298,0:1023030868022814299054713017964868399102957735431782102215916358604604051659703035572837203405877079107051634525945219766070256763817295621420805604993635631490817683951846687765019250182667988090399985362595946141453130325277952090882208566546530763707685586001179407168248639583706997713561296809021500677647862937784168307555475376888964203999111072179073538018050362405289547337600007038981171944778216894564706920577451010395411246759676715366409166040432558779691978486479294657424378342139756544
+expt:67,294,0:734500327961443669234315379892319347436893827696021491142391697563378578446291077887806124176875773502748252261770540334529098051241702520337994712391193396474812051324450141046760676076260316236367877489247807236984474045776385255239037010394553624592302745770678862650712113089224670041590960921068572134081690133046715543153096542269435280673848480153667033339024712187305544312593068136273774422287977966196973980766284625470220034542418965941570269327451886686200812785835233820579323336965260949631248809309330127020161010203411929
+expt:-18,16,0:121439531096594251776
+expt:23,783,0:17096043011003615277598794858486068754024940440179973307979725548138117553890262896641152305435426637168346356686100176044925372354921872747501460658856273444772550524367017737008810328712782564379920672077160208017588610872900933505244440864632694623791999654579846020232116933586706946483379032274515986264401321379356564215058936360373677277919864278279794625946762796494116433783821073561146442740575287992208852561076777520575751129272827760948307704793048037510164918774200200085555861489097574107784367443496372000977637695193822915836028040509766497522766784721558336792917997571201278516192223590838889688612546686389608843721034916667041733614883996563547634015007274594387270209090391868747626612843208187603964244920932750585408044205476476229852915573917584786214180312460069710688659542311237951704151388274748457930956937912692497993167574943229551708370492252437047946879513486746068495028744525641440991301695614236365008498571998939850585670845752278477745811135337129266946940607139194863121256913904896962276321551899101278415815402393374517929767
+expt:-66,815,0:-8478274364648612330188917253283022359058819830563672517212108821628253393962000107434004509667343937534845252876105916914550690362654306802088184928424521570461209219177571955862371964722226410637046742655117010513197262769697714640814368023744763233323396664955472317206306714935880218313050258650385673367221675620501577511198414613930001668113399143106311450680541330404416353053190642499775032620035730460907253528440201689228392425128611695226403417406791574278689202884590346418539029059209980814013704118450210566908353305850659319394569789593583277865075164609668529102638203772555818321297822419290710586417444995207152787848623117218947477799582750664329264358615866224038190922228629974680499679526981709174616924365577700177072886843030924028404354842213079523220238443352288912242203925033885655177475234008253977458800922719481452623217104266383098663601342961199447190374025272206739771683319522016840242048283276894211421554923410027867743938181352146258867339132020852657862198937040181786435550099700309055348307396827575249256603692440439981038825878568365720841374284500628316724088850430536784223423104076749618800240805402030937435626889672205773792103911906204527061949920720885833279883726692710574946314456869324980999570723090979946872598945360813531346459611164448392012613641192887272701599318084665769391014924333193179500033230229853166710458920123986965349475008600343653534535593116799600793757728203652141876940711203421375996087235090052747651710976
+expt:54,664,0:20391845050873191652345159631406874537839455686365280217235427133476142582092996043619608390016389292965226896811762634987782972686518739140212360064330493755768007040302669237780668310608681482526562495176314471562104423826827089408141436551453430030964346636473177072344012300123214143559305872414360567214132682148167038413419037687295369781258678081076745492992503736782832174090246186699082419488498244657442094259244802484573507417869446357085909447262706180711907718273125250308231346034020925518798041278971653974463785808172029353263314071093941305571685611808887063740166405396225068221678544525487393228625876836004989079566259935122474245224409591612160442040129636723080187009657142522509070943421819954801779957035427054617629433447229882724015810298068048100626156055542733454456801321357919554628269944544954700528568251750045531145328694687448392559273455873142746224088225238286750883430569184631252959597186815034796504990060130502168310308220045378042228226870235350079089558343443820937472250762918032769865387382756419568756482286011357857171768933280108973733824989544483820081477750150555112569963683757807113376801387242848256
+
+exptf:-1,0,0:1
+exptf:-1,1,0:-1
+exptf:1,1000,0:1
+exptf:10,5,0:100000
+exptf:10,5,=1:100000
+exptf:16,2,0:256
+exptf:16,-2,0:$MP_RANGE
+exptf:9,114,0:6076396096647706909168138770838836135530328017648434830996201971201776350890241322455818405320466786549738961
+exptf:-86,476,0:662617332696362860524067230796827820618815284881665908870595313490845384402730799402221740741547892729430741053639014274968962128613995528237195069353968871860065099842959580048834695510748974202424908905352730826874949676923389706328585129209694843598031316497606363273659659518137129001683914681077900538211178870670637655474948719356656149928857724507047191532188701873201466847680543186709462811132458087950485580962981785390351911145306017418845982546035812744084364382432586452339098567898296989357418159116783507112574874002896769395516552960579886303506398054290885811079444534809660731243125017742263312078176886504861185566719851630353701862941682854137129215263285153620969438652988427729550528379121310832057528645876351114476064584186293636620546183047738657594287749786268444920697293633564476272776432769083439149706832453778408583421346390651383448852253784001810843070684412323782386158601772005993742336
+exptf:40,238,0:1951092843947495144613498268620728941092873839165606969286973099765857336762353512575191314414682481974891831950879139309654984799555178316431360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+exptf:9,761,0:1508515174935868832740908844641413400230908698282014024654729092918735474326353646362638387096847659573480147230064829611049820323852929496264239478087068540642226919569780605621815548160687919464946810325130045648382743363240874672014902866728521582870078261816669666838432797381766007612134725161586319767428484319859256110793709691241551836459283171491322903212579581783263716842956174378353601721913353516686324030063352338083503343527729254306613462747468830270057853272630516028854927235895950242106874919224742672988595490274178820331573555174825456815488479104792855190670321093410569224479462267429452231735849215995686173314732407799996091669536594590589720060331368687564979078136565140955509332862196370159944529609
+exptf:97,144,0:12448864341302864356285624793135454957839907062356377399873019819913674333304037397385881749787740378047787615516124593880867160513889753519548772992938610862712907794913424958325207507075928443769586211194132774382517001523776118917770065797726717096819996931978519564039067219497326081
+exptf:25,122,0:353737464016668451855824972300304366432911374927310085530570894138105520257533012294512947342224925759920017160034290220932919252862236536572027034708298742771148681640625
+exptf:60,794,0:71136550947732097223049080592911024204723415862845308040389197768507697553695725763485652390828706079386079253286683076446508807986344183438029484620306186446936364042768259107355223169364392353311443322952870623266797106042061359252992933819289381215897875409197357921675407844235432207568030978595888122411284106189806970016530299277993693667005155741905298746901362592844010565441606260646610040560804127639267467909340287601194961411351728753184912061106832973826776921930054951881992593414738674333726484856598478050587647451437933451435999205268943471465348558111458293504367268910731207434743916849298071460249600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+exptf:77,531,0:532813311656570249504626338521175986931059533505926279525440059983661596994102351537446926949363360529365260710018282274969608991708422465645470353238950991164094603760337431471373797674342466447685331328334896929530869521639021347860305641901746618212067382436047417802334922329714967747069071224609067366771145964345230898570999327581370275837424654936614015736099665593408214589717971837806254491231718922616012680565189067437536528526576020597271981783296886490561985553063246822960810078500648480156559918530508398231087164252252053517193755387712164533565474034807917780960207694570186046344187446803758345139338159388892261095589551022214765624192005132067602116482379395414788544646979450596452460362555591887638135655580299669062424023518502777571809123694201495640270788238169354113138409879326088017367705387411669267281998186298445497315171994082486321864442017377055208040226703055135151101106282748423896319916554310684705542590586019379478759401961042716809342108506273015769966750567573
+exptf:-18,16,0:121439531096594251776
+exptf:23,783,0:17096043011003615277598794858486068754024940440179973307979725548138117553890262896641152305435426637168346356686100176044925372354921872747501460658856273444772550524367017737008810328712782564379920672077160208017588610872900933505244440864632694623791999654579846020232116933586706946483379032274515986264401321379356564215058936360373677277919864278279794625946762796494116433783821073561146442740575287992208852561076777520575751129272827760948307704793048037510164918774200200085555861489097574107784367443496372000977637695193822915836028040509766497522766784721558336792917997571201278516192223590838889688612546686389608843721034916667041733614883996563547634015007274594387270209090391868747626612843208187603964244920932750585408044205476476229852915573917584786214180312460069710688659542311237951704151388274748457930956937912692497993167574943229551708370492252437047946879513486746068495028744525641440991301695614236365008498571998939850585670845752278477745811135337129266946940607139194863121256913904896962276321551899101278415815402393374517929767
+exptf:-66,815,0:-8478274364648612330188917253283022359058819830563672517212108821628253393962000107434004509667343937534845252876105916914550690362654306802088184928424521570461209219177571955862371964722226410637046742655117010513197262769697714640814368023744763233323396664955472317206306714935880218313050258650385673367221675620501577511198414613930001668113399143106311450680541330404416353053190642499775032620035730460907253528440201689228392425128611695226403417406791574278689202884590346418539029059209980814013704118450210566908353305850659319394569789593583277865075164609668529102638203772555818321297822419290710586417444995207152787848623117218947477799582750664329264358615866224038190922228629974680499679526981709174616924365577700177072886843030924028404354842213079523220238443352288912242203925033885655177475234008253977458800922719481452623217104266383098663601342961199447190374025272206739771683319522016840242048283276894211421554923410027867743938181352146258867339132020852657862198937040181786435550099700309055348307396827575249256603692440439981038825878568365720841374284500628316724088850430536784223423104076749618800240805402030937435626889672205773792103911906204527061949920720885833279883726692710574946314456869324980999570723090979946872598945360813531346459611164448392012613641192887272701599318084665769391014924333193179500033230229853166710458920123986965349475008600343653534535593116799600793757728203652141876940711203421375996087235090052747651710976
+exptf:54,664,0:20391845050873191652345159631406874537839455686365280217235427133476142582092996043619608390016389292965226896811762634987782972686518739140212360064330493755768007040302669237780668310608681482526562495176314471562104423826827089408141436551453430030964346636473177072344012300123214143559305872414360567214132682148167038413419037687295369781258678081076745492992503736782832174090246186699082419488498244657442094259244802484573507417869446357085909447262706180711907718273125250308231346034020925518798041278971653974463785808172029353263314071093941305571685611808887063740166405396225068221678544525487393228625876836004989079566259935122474245224409591612160442040129636723080187009657142522509070943421819954801779957035427054617629433447229882724015810298068048100626156055542733454456801321357919554628269944544954700528568251750045531145328694687448392559273455873142746224088225238286750883430569184631252959597186815034796504990060130502168310308220045378042228226870235350079089558343443820937472250762918032769865387382756419568756482286011357857171768933280108973733824989544483820081477750150555112569963683757807113376801387242848256
diff --git a/polly/lib/External/isl/imath/tests/gcd.t b/polly/lib/External/isl/imath/tests/gcd.t
new file mode 100644
index 00000000000..df7537e650a
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gcd.t
@@ -0,0 +1,761 @@
+# Greatest common divisor tests
+
+gcd:0,0,0:$MP_UNDEF
+gcd:0,0,=1:$MP_UNDEF
+gcd:0,0,=2:$MP_UNDEF
+gcd:0,=1,0:$MP_UNDEF
+gcd:0,=1,99999:$MP_UNDEF
+gcd:-7,328492456,0:1
+gcd:16522181,930,0:1
+gcd:844378,24,0:2
+gcd:209,3,0:1
+gcd:70522336,34102,0:2
+gcd:32557663,995533,0:1
+gcd:641,701,0:1
+gcd:290748,-233,0:1
+gcd:-95,4770,0:5
+gcd:6839092,7,0:1
+gcd:787590783,-6789049,0:1
+gcd:721,15845,0:1
+gcd:-37028,-949534667,0:1
+gcd:618,-3,0:3
+gcd:16657,-544851,0:1
+gcd:28271,6,0:1
+gcd:-35357673,5207718,0:3
+gcd:99,-565,0:1
+gcd:9311525,-5,0:5
+gcd:6221599,7764515429,0:1
+gcd:21590339,486739392,0:1
+gcd:335,3699183948,0:1
+gcd:14,8755508782,0:2
+gcd:-5302,9,0:1
+gcd:8236,9462435,0:1
+gcd:43040,2766705,0:5
+gcd:863478587,63,0:1
+gcd:8874055124,10,0:2
+gcd:8204,-89955,0:1
+gcd:3303887262,3,0:3
+gcd:75504,-62,0:2
+gcd:436,2123372,0:4
+gcd:3361227,943089540,0:3
+gcd:37340421,223177728,0:3
+gcd:-35694701,238293550,0:1
+gcd:4263,15500547338,0:1
+gcd:1493,38730799,0:1
+gcd:-635007,298501,0:1
+gcd:4968,-98492710997,0:1
+gcd:3367542606,17576297,0:1
+gcd:232155550,3921719,0:1
+gcd:4860966,700,0:2
+gcd:2323372237,867,0:1
+gcd:4268,-29035,0:1
+gcd:8,-73804207633,0:1
+gcd:395170,26163606,0:2
+gcd:-70027196,6945032910,0:2
+gcd:5871172260,26773591,0:1
+gcd:17125540,836,0:4
+gcd:1988202315,-68060596,0:1
+gcd:554434367524,-909419,0:1
+gcd:-40457802353,3398,0:1
+gcd:410791452776,4492144466,0:2
+gcd:135751970,7417878752,0:2
+gcd:9593,31047471995,0:1
+gcd:-18387143,50226,0:1
+gcd:413450673851,-124,0:1
+gcd:-618513698871,-318914624,0:1
+gcd:37416674596,-8817,0:1
+gcd:6242382,-943205,0:1
+gcd:-4949666413,1501091102,0:1
+gcd:-6385784303120,899228089,0:1
+gcd:6308,-79643949,0:1
+gcd:2421,136928,0:1
+gcd:333180111,442438,0:1
+gcd:723761305,611024432789,0:1
+gcd:-91289,-9223787613074,0:1
+gcd:10944,57098,0:2
+gcd:57145099,-94544476,0:1
+gcd:9327105307,88173695233,0:13
+gcd:73230770347,67182928,0:1
+gcd:4810254287,-4310,0:1
+gcd:7200253992,9893,0:1
+gcd:-92709373682,-664752121448,0:2
+gcd:-2236424417,-69570761,0:1
+gcd:781963714,61084006246,0:2
+gcd:78553,-3773682081509,0:1
+gcd:24811454802,-26314981001549,0:1
+gcd:805866671,8061826,0:1
+gcd:4281823377004,2916710,0:2
+gcd:15229,320560332911,0:1
+gcd:6093153060,357460,0:20
+gcd:624794507388,3264784,0:4
+gcd:2632503413711,-514594728450,0:1
+gcd:7216089,86034,0:3
+gcd:112578025,4532680608704,0:1
+gcd:-972617496,-1100642928524,0:4
+gcd:86658,-56860,0:2
+gcd:2292080,40552081391276,0:28
+gcd:57144144326678,3579498119,0:1
+gcd:77390585076,614924,0:4
+gcd:685579,959286825595306,0:1
+gcd:346354116,451435163995,0:1
+gcd:443946215999,260668,0:1
+gcd:640447120070,-441698,0:2
+gcd:1253208493501,-8521171736,0:1
+gcd:8507343,62395589,0:1
+gcd:81126006,461820852819773,0:1
+gcd:87891707090,40954510522233,0:11
+gcd:-767589,-991593,0:3
+gcd:86229155,43027930,0:5
+gcd:-431963821,48986055721,0:1
+gcd:101557073166691,-74080192,0:1
+gcd:-34269048183,250074,0:3
+gcd:7650667716360,-959482143,0:3
+gcd:-176432105527291,712269105001105,0:1
+gcd:91973525400419,-52180215632622,0:1
+gcd:9054526,-21388581343089,0:19
+gcd:19326311972,3180878,0:2
+gcd:501569850634,39035351302,0:2
+gcd:-3470290487760846,622612793613,0:3
+gcd:827793089252612,77591849874263,0:1
+gcd:19866668332,4414961,0:1
+gcd:136274450771,8659380001,0:1
+gcd:952660786088689,171372582380,0:1
+gcd:429415374,9140880954,0:6
+gcd:-368107346,2945634,0:2
+gcd:2147845929,79983807840463,0:1
+gcd:77885771608,-51236668812562,0:2
+gcd:62272695670,208399244,0:2
+gcd:61973019,-1405255816878779,0:1
+gcd:286206733986,212837117931767,0:1
+gcd:-131938894,1048695278656631,0:1
+gcd:27109492,306933238851468,0:4
+gcd:-314477095129839,3837918787896,0:3
+gcd:4116345,9101435151,0:3
+gcd:63853435249810,902940229903,0:1
+gcd:80076033,14791385,0:1
+gcd:-31038678,1454704764,0:6
+gcd:20638192722,-14267370499730,0:2
+gcd:8065790684,-1977228453431,0:7
+gcd:362687955673,99742877979696,0:1
+gcd:1235326072088,201675880263044,0:4
+gcd:568009735,49546482048450,0:5
+gcd:849579042,-3197920541,0:1
+gcd:1808291492597692,96814519920612,0:4
+gcd:6275712123233717,739880208952795162,0:1
+gcd:774075573665981,7523229210171,0:1
+gcd:2944466357361,497012903828640,0:3
+gcd:282862415058866,-6240991940068,0:2
+gcd:571225883598025,189932649930728,0:1
+gcd:815309478,-371377784,0:2
+gcd:320172590239,777220834144,0:1
+gcd:654332382,7919190746613,0:9
+gcd:-5094673003562,268414312780910,0:2
+gcd:-77841790209187781,35267718271550,0:1
+gcd:735762990564598234,-32739891496,0:2
+gcd:-5999905013129575,144027889596460,0:5
+gcd:6861193105404525,-4725324526382425,0:25
+gcd:859748569384694164,98523184164,0:4
+gcd:570460270963,-54720108308,0:1
+gcd:61750383079701,3452251304617,0:1
+gcd:-1738716695,8560399484936237,0:1
+gcd:9953417006786660,90085339160,0:20
+gcd:188523146978,954842405502,0:2
+gcd:198834734074395695,171072375577893,0:1
+gcd:-102893613303732727,155104650554,0:7
+gcd:90836124710855,-98332551310,0:5
+gcd:10512242068892,84377075433,0:1
+gcd:-726835478343584190,29339956106373,0:3
+gcd:5033847480079150451,-69469662902517,0:1
+gcd:3869558083241,-8770208065,0:1
+gcd:46079368203995132,23609959311256,0:4
+gcd:979137194422864421,-1378816153373947,0:1
+gcd:-72618673468,-244198092166982349,0:11
+gcd:529564016606,376298866055896536,0:2
+gcd:554186920892,-629719688885314,0:2
+gcd:3455963977845612750,271884481278417471,0:3
+gcd:-41270780965441117,-4124462824121691009,0:1
+gcd:47581683736,9394210662450,0:2
+gcd:8196306676684,76732052476696223555,0:1
+gcd:2939970750639,-2013582768244,0:1
+gcd:70476757656499,-100957934015971,0:1
+gcd:3674841030712174173,540185467629182772,0:3
+gcd:82915322420038008,123799513890,0:6
+gcd:466513077506,73565730651787738,0:14
+gcd:-38890216282311653,91459939591112,0:1
+gcd:576595981539992,20909590051109791,0:1
+gcd:956905636477652,8381376662473,0:1
+gcd:9187294026565993,54295427509,0:1
+gcd:8866081281165098,6545042142269515,0:1
+gcd:338772425501,-750860960783,0:1
+gcd:6750486296504,8609697533187,0:1
+gcd:736067207074328,329259058372493427315,0:1
+gcd:680100030114145,52232423165123,0:1
+gcd:22697310250913136791,365228836596285515,0:1
+gcd:30594845950075862222,37349482121506846253,0:1
+gcd:866936756424,-1765396942933391,0:1
+gcd:6939438360479781,24559856763503,0:1
+gcd:927595346004843560,7670228140092963222,0:2
+gcd:-357321286444971587,7925597841132985664,0:1
+gcd:6673370692769029,520191499051311630305,0:1
+gcd:9013236794945,1008467412252240244,0:1
+gcd:406532185466775673747,9519149309169118189,0:1
+gcd:548046408595014443,777065152533771,0:1
+gcd:23897406396584,-8555442893510156172118,0:2
+gcd:54729344028716311850,2026849525600172204,0:2
+gcd:-7936445752013,-98698488318151151,0:1
+gcd:6309028281362257922,271678876766048827,0:1
+gcd:6357785774765671053291,56936125648067424,0:33
+gcd:11095109588014,9104811531028000846,0:2
+gcd:-921590308699737078,472826384755153630,0:2
+gcd:652120832633171211942,-3387083844442113181,0:1
+gcd:32731949302549,335896184427699,0:7
+gcd:3635516318567409721998,16713986701316425,0:1
+gcd:6746198240933100303896,2007405485449,0:1
+gcd:-19072614334803913032,-240759760944833349,0:3
+gcd:828472954262165857,127978158379025077,0:1
+gcd:8306750095431507743,6378030328941226919,0:1
+gcd:7938532173109072,7646615157112938170608,0:16
+gcd:25274397567311,3125247753747112,0:1
+gcd:0,-6378030328941226919,0:6378030328941226919
+gcd:-6378030328941226919,0,0:6378030328941226919
+gcd:-6378030328941226919,0,=1:6378030328941226919
+gcd:-6378030328941226919,0,=2:6378030328941226919
+gcd:400327281633151431,37147489147345586,0:1
+gcd:28164658061513141691,818613450005821036296,0:3
+gcd:476291935913056166817,170589720180888384,0:3
+gcd:84130837655605609,16051948347568699941145,0:1
+gcd:438146043336536562159,-2206822496905640873917,0:1
+gcd:8120293725815373571,24028314574527126,0:1
+gcd:-667658265953408,8440015504605457600699,0:1
+gcd:53314441150262832895,283247085055963859,0:1
+gcd:6658153298145442,2140281300389057549,0:1
+gcd:213046498706732967,784948480361985741,0:3
+gcd:-3857522843819,419578526133778265155,0:1
+gcd:-4948941087660882967,-779517282262677550602,0:1
+gcd:4277076043224464,448010594023993,0:1
+gcd:-644113523059324254840,-71225587742718143,0:1
+gcd:264902435468141506,-823887292259809475,0:1
+gcd:1538706915662950684,448326823774496344436,0:4
+gcd:2036808313025110180,30422160628736748027,0:1
+gcd:7385426850078311,9871854919284839,0:1
+gcd:804644713550364054117828,8379163811459445,0:3
+gcd:981008037679996757191201,-641409668917881464,0:1
+gcd:64201713053871850,879119102660231895102,0:2
+gcd:1033957429367195,1113485105415049436,0:1
+gcd:14455075580451942850,-1885962875546302716,0:2
+gcd:2615475057635555327591,71606675442458157933637,0:1
+gcd:596676024530775,2621192750454214313695,0:5
+gcd:71665682789483848832034,351563529541544408090967,0:3
+gcd:5092055214749737510271,-1833800774226189505,0:1
+gcd:600508413963341945,5057063373752305154,0:1
+gcd:-92318043858914149,958444935645415778103,0:1
+gcd:385447683586530283,1775981280157037775814,0:1
+gcd:80717517906672139,362327909576030289130356,0:1
+gcd:31249856290116188,7875872084416640,0:4
+gcd:5339381130045070,-287550419156538713298378,0:2
+gcd:-28993892995370333046,698005135756870427,0:1
+gcd:9179674525723481348,81469928617693608886,0:2
+gcd:7522547789649675160016,285918417200326088447794,0:2
+gcd:-901774653467788803,236000195734098992,0:1
+gcd:142671415131788790,-2583777714764598301032762,0:6
+gcd:951078283105727024828,1487627587101952300275691,0:1
+gcd:19185476025869672486,2445736876347152429980675,0:11
+gcd:6741226163186521681303,2568160083399218078514720,0:1
+gcd:3987919571578399660412212,9884144363611069680876,0:4
+gcd:99431631881940059268,-291965406586754754564989,0:1
+gcd:36727416735327035,-1612205593089728906670,0:5
+gcd:19590774006340220367562,984968880458891391,0:1
+gcd:70695613219926859099201753,62591913993270611799645,0:1
+gcd:77425442645246583405,-296832015660977965,0:35
+gcd:807971872592227526408,40230405885131399744453603,0:1
+gcd:965370212546292322,92058451234918953535616,0:2
+gcd:418561885926860582,239657399821326936,0:2
+gcd:4657697584188823828175,78713797195009784682708,0:1
+gcd:-38091455008728662,5763777114003492300442812,0:2
+gcd:54943065861736600767,6268390929335695219433,0:1
+gcd:-697639190379957186138,2936028900796584636,0:6
+gcd:96018089280939789090187,29566309848085271814423786,0:1
+gcd:-1112368751522257152114,1995174854903534746993983,0:9
+gcd:-84342841213955171500540,5699084396809137598518,0:2
+gcd:225675029492277024520800,92998377812004114915728728,0:8
+gcd:7655269162163547244,594548791001649285,0:1
+gcd:17608380663675562604,264448308193844308642824889,0:1
+gcd:223093179893694063251643,17908241494426478956477995,0:3
+gcd:-9501451313199296478183,164266650410143061944307590,0:1
+gcd:4558730178677382262,3122005086984557462,0:2
+gcd:54440882483631228680923933,4478571958703194374379,0:7
+gcd:36855929355558415329723,308635436762628905,0:1
+gcd:28683868680975381560,42902583850929860163229,0:1
+gcd:24731088466679335541839144,81462858536522998396,0:4
+gcd:-72335534127835253275,-227166439208550011362,0:1
+gcd:474777034176054735892,839001319154604024448982,0:2
+gcd:6299666296143449904,797331145004636509,0:1
+gcd:8540885149755672764459236,41765710483565552588310,0:2
+gcd:385990739803366398,2963466700114736836981086,0:6
+gcd:-37246197932269024,3005402223074948482,0:2
+gcd:-751622018429096822596,3003864133422104297,0:1
+gcd:-6108319432277782804,-82931541043539126216389,0:1
+gcd:30921518942393713547539642,721143788088068568685,0:1
+gcd:570903751254308471830202651,-564896588437884119958,0:1
+gcd:1054271475454361570597270062,16484741384321323400,0:2
+gcd:6529831639822170310307759,85346429845722052312845786,0:1
+gcd:-754058902141939454006,69516695016006129145191,0:1
+gcd:976193241125104191848393,33823563038032982713854,0:1
+gcd:2920092456500658009757,8895875497550350532901302605,0:1
+gcd:9994369499844252132394601638,93334243646132127297454621,0:1
+gcd:569015432462996733746,16322837154963292812416483,0:1
+gcd:192500272569416024937360278,-235265435750733300361,0:1
+gcd:5267095375035104443898399000,-764192677627393558125306,0:2
+gcd:51025753118541843018,-1664207936338749988204,0:2
+gcd:-62402848465899883613105,12900108782353988220438351,0:1
+gcd:-8212641700259728565,297115088713153106682478,0:1
+gcd:-5313586393962705049080,-76998532453336088964044527295,0:5
+gcd:463290189242313601142817059,969769350842083604500926,0:7
+gcd:1917277332460964412252,-708614825339303498360550,0:6
+gcd:99562752968815530108,23844471852654970991199350,0:2
+gcd:3003923448532254675001,7732856831499478812681071,0:1
+gcd:5794073936773633607324540860,-76553654622431077040278132,0:4
+gcd:-644932980169883872037968349,42642515095105038480,0:1
+gcd:41892582203464757978762451494,68041907390182959305068217308,0:2
+gcd:-5550794996398648089925,-61773015425098686639107,0:1
+gcd:26506218374693057900,-167675112099207386871,0:1
+gcd:145568384864275126584,40072954892382195328941863291,0:1
+gcd:3161170925861501561771687,413220145707787390821,0:1
+gcd:723440854928237000349411,-71208223609049472714282072,0:27
+gcd:94994080481292730137,4307839512004666207932600136,0:1
+gcd:7821178378958515500742,3087104738440174209004586,0:2
+gcd:869891649236864909625695,991848579874131467931448097,0:1
+gcd:17628160996789341122894,299337591195948255548811,0:1
+gcd:99527056994641754235498057471,655773087035017085668857,0:3
+gcd:596721281791001887739,-328175786669349585798669238390,0:1
+gcd:266802917073126657350936,148259550527207353925931727,0:1
+gcd:297095531532857951877,8071469565512676957784213778,0:1
+gcd:-64574484904487858142015156737,351049851111701482889769,0:1
+gcd:9213606993296693767546,-974475310790221342435,0:1
+gcd:-6506246525097752180174,-95653949321972166356216836249,0:7
+gcd:7211807452760603826715508,25981532388511222064867790,0:2
+gcd:244358078258267292267766114,6788410077941126965241803849,0:1
+gcd:-84498071017578145227329893,51359077717175899950414794158,0:1
+gcd:315675121566194900458712010,607326754590110945679173086,0:2
+gcd:3336777364604897112789890,24326442512123908471776,0:2
+gcd:-631164366791648249399815693437,224085205047080377284686,0:1
+gcd:-9374071452933990971885163627,-8124264246742383054580586,0:1
+gcd:-8986611810629266612086889,39090932189616079255587,0:1
+gcd:131042125952122412011234961669,-603299752062616670818260436,0:1
+gcd:-5931135084197112120929525527383,817854717051260202081870677650,0:1
+gcd:37076034350171687718404493,6575825691817817445639700141386,0:3
+gcd:6586877468189252639017707825771,813151310907233772623665199797,0:1
+gcd:2933337084774328653741904208050,516673656644156545121601676651,0:1
+gcd:-9902991686684787357658450,173313993122814232472956,0:2
+gcd:9274522469490915283112908394363,44864081129175577116760112,0:1
+gcd:9608655195311416270604257657,65867528105907714734959487,0:1
+gcd:853239911600142024011098491,17829323361272785163230303,0:1
+gcd:23972081642808055559504902,-4501717580058722285684735,0:1
+gcd:5314236376598680151908105,3994830160691915764873,0:1
+gcd:4935319583093232012062136782,881389216056886912824752493825,0:1
+gcd:580231659494763900889556,96767644291944525456085901,0:1
+gcd:303622305001319462939309066150,-27984889540977885375442171280684,0:2
+gcd:8908131273613694428163643,418798812110676949375564324,0:1
+gcd:604960317372762640669451812,820482420778387317631260055,0:1
+gcd:3125355862613621420823337,52123353846012574000878521623,0:1
+gcd:35876668588605457895900,-237986271303986771473105323,0:1
+gcd:-43001262189486935668928474222321,75601013836677651900921245468148,0:1
+gcd:50360054222226284955381499,-7538629547593198554710875138,0:1
+gcd:16303655607623383537122,23252538460647040924816117157,0:1
+gcd:29876051059586965106021953,26235768232838079362376,0:1
+gcd:29623076251397963944271763623335,47441755805615786352682527,0:11
+gcd:9892811422980328964557595259,603482574014084208448431822759,0:3
+gcd:-2549498483308845928405350,2555383871703609992631017913548,0:2
+gcd:-935906971037827073384146870,879641356065373793312781,0:1
+gcd:19597038710644290533555897021,2985160892106475439715913026,0:1
+gcd:-5608937456930306694772980,836399586633606428927522624674,0:26
+gcd:7718522069758342120350478031,7389561033066750535580836572,0:1
+gcd:718875898101761373218778459,686314096776480574628984874102515,0:1
+gcd:1300200863593962819188902,525922101427424561614551608409976,0:2
+gcd:539220635752920237029329058,29487916769600117002583914582181,0:1
+gcd:5654437789656914341120143121414,6765853316633901505298664574837,0:7
+gcd:103114174998937498500059583,920095995082794389728025430890882,0:1
+gcd:29882936700790118228421849,-1860889369990333700884198092,0:3
+gcd:8909623809613954310018698,-462806578041198407432067106139,0:1
+gcd:7230230288816368650543810,22162946284655819337870476,0:2
+gcd:734442358589456361847988629,1647427465162259118128391711,0:1
+gcd:47616626651192848094181030316,2182277257935167463613810412,0:4
+gcd:294703827229370598691617,63046555168872062038888853,0:1
+gcd:-533653415261740333749397,-51216937243134223196656339350075,0:1
+gcd:784368839220787531616946253680351,39613735771181195550018240677,0:1
+gcd:5770744507580580048400572,231937913382367374762373686161,0:1
+gcd:388816489715059942531589642,82051838197217717225950877,0:1
+gcd:60241729629297025142644618709,85181464884435369517497693388632,0:1
+gcd:1560786485638020475934392460005620,8850527081981124295638445,0:5
+gcd:8296622334734688413856037840,-83875508267086319614619277276,0:4
+gcd:-45794179084517723375284971259238,-49063790774577780701852303,0:1
+gcd:1752071933321291709931075226933,57773126045256149501100162,0:1
+gcd:730668796977177255106481634556,938608337106204028806933670639254,0:2
+gcd:921730456287198291208119641693911,5458708493078803375257300,0:1
+gcd:213400535376420556914942871216081,4183995847570912793889135547893162,0:1
+gcd:32806047880829491896013320805772,753489056993475245589087354,0:2
+gcd:15218771998961411533589410518,23457061020403160442042221,0:1
+gcd:9046617676720978441798060,7479379807328977629621989162,0:14
+gcd:2219170169044655639393672927,-5391273013704097527490654785062,0:1
+gcd:277590531551034474232270111103,579362077865358674190909581933,0:11
+gcd:51422590325724235826789079575,2121952875387495603452158,0:1
+gcd:511034032165016743768820348,458982236103828060996895790272,0:4
+gcd:4440454508740215531301617636697,3258309525326637800581711028116821,0:1
+gcd:6330009746329830092300048092,-6167250670699283492360751201828007,0:1
+gcd:-9374602262965156933926707655416,-30595740075402425097079774283,0:1
+gcd:83645893910576549628700447097824,49931389572768584324081547829643,0:1
+gcd:8030747712125824227213267818544,63329417394086865663449328880556,0:4
+gcd:378845361147099357535431194,38180105668041356349238612217040,0:2
+gcd:25958762365949818177158173188075174,40582859445868015162861781,0:1
+gcd:95871031013239291309686124,64936572493882710890460913285902999,0:1
+gcd:455128054133718561191432952712,39088645380524987234419335395029,0:1
+gcd:1307047523348091088814812136,44132853285705545682051355847561,0:1
+gcd:1418285824252402530993393665755,636810955908181043849421782278,0:1
+gcd:3071172872783184341780369192882346,-58125204065109316437571977973,0:1
+gcd:56958148205198214736866933854,4922289245511311172745764679844,0:2
+gcd:4836813580368584281452577588,-5400032605107989894617874622172581,0:1
+gcd:493001845960066187429806680791,4028800209124423703294502145421185,0:1
+gcd:71197215106470682909632132625,70077573297929109151274279,0:1
+gcd:486722080146274783096432055886,505595939085965376271620470551,0:1
+gcd:-194536785271632924316130857883181,8276525052027013498990299177664024,0:1
+gcd:241211965193448971857220311,2710726738427327769580581757190,0:1
+gcd:667013805494915469984846976421,118549400818390788595763048,0:1
+gcd:507926799850267721181735296662204,67253859677995358015731931706714,0:2
+gcd:448088677681619431331494894631309,779948091351174817338856782981850,0:1
+gcd:187408370748924381155985806145,495794563709904959946586644094587256,0:1
+gcd:868633158815673181555237006,836615025635832190680248872,0:2
+gcd:945386362083356835627622353491,8230893874122803805176630038821,0:1
+gcd:5596932048341890824814087121,-2850793263280920843358756089,0:1
+gcd:92079468846004092188293849,65000203344267255501708018874742834,0:1
+gcd:284485059147524530505559245415623974,-52174853366891975161102679787418,0:2
+gcd:225019940499042054289943285,88057001889802818516938839002453179,0:1
+gcd:267625311635136684363577960127905,2364801628264216400078340665206601706,0:1
+gcd:-43414374537943144129863577734786164,-7033210862612719519352562332,0:4
+gcd:32883132771659855270849300682688,359989040176539024964573548207106,0:2
+gcd:8225754994306229461538669946760,79816684330375527507314556065816,0:8
+gcd:7425838080456254658426507595,-1772612320788255147892065709861,0:1
+gcd:1660461221569443640519526747903779,1120888096894032723781619067526671,0:1
+gcd:-11718764104457037189982579964973,581785925357694644406822708535571,0:7
+gcd:6811677000322905212875962023,8457366124986245338105030092893823455,0:1
+gcd:234277964462994083732538315234,60350281492645017737168270090,0:2
+gcd:4183588612759663468880479337,-629574038019737820951243554610835051,0:1
+gcd:2509727174403533842481294816277585179,366325095871570289922697736369296,0:1
+gcd:9652053493694317708921453500950,-91539642994112368354952933916454,0:2
+gcd:35148593969489612322148628595,-82585065708416968121031576511657,0:1
+gcd:2800741702103544119527140802733199,46761480207188283686223358035,0:3
+gcd:441336276433669766301405280032,2656936104993980830437872804,0:4
+gcd:19746122571650880858695931178058857,104545112367422664420669962306,0:1
+gcd:74432478600289091913597803372,1021411507303737809729230605483660893,0:1
+gcd:37218119790882940825047165121,-9786692593914842780007874460688,0:1
+gcd:68400175404962139133336849460667620753,8111497426974768586772111911266,0:13
+gcd:-36411507888779255237781266679960702586,288273015425729999064058691683,0:1
+gcd:-93804297004149089553676142929158,72597578405766612297542242292431,0:1
+gcd:-82026709713179475197473688526642531,5827788603588390535677091203646382966,0:1
+gcd:545760067487517393173385480028,42151112506666653978439280505,0:1
+gcd:-697412421088675986809554647004214,6926944054264140642234974161460,0:2
+gcd:57812799959867792819685059219,779735108345604313576941265627654,0:1
+gcd:1472311567166258003445083977221663144,83378953824849274359711951741465,0:9
+gcd:570337459673916278308389115966167469,6333660822968779197930730584647562275,0:47
+gcd:-388785693105293562593219349398,820248784628021659491960244881371621,0:1
+gcd:11679788667362042415563834445557578,-5819547639993570526822921884507,0:1
+gcd:-3982959591737356792197606403519482273,-333248358612381656382679653253,0:1
+gcd:17221610285774362123428353448280602,11458184790118982447972303969280231679,0:7
+gcd:772738633297996807166456840381926971,785759122171938805714543081571173360415,0:1
+gcd:125784145401376536208808801528812039333,452055550313139515567680226389953055,0:1
+gcd:32903571905950760393177782893378791,6631740924411766007832465757451477,0:1
+gcd:8742677352155721160009371273251,25083360125803108633092433384973055,0:1
+gcd:36273669132247708836176424212020,533102320793846929600697481505030771,0:1
+gcd:11965144674509690079804137520044857,9349045655011350274674885782216185552,0:1
+gcd:3321305668226664033356712162893,-403949753985171409898849824686029161,0:1
+gcd:7395363159337411027760652209127419265,44729331460301249556947662501414682,0:1
+gcd:871058047335719958990871843414,28094200616974302760918376942978068402,0:2
+gcd:7704699734056436938779166257084,546898541513497897846722209401,0:1
+gcd:950290435067652970604023856243611,4001208123591666075058892234775,0:1
+gcd:3119293215232541154035748455321571,808684220462127868482572087900610,0:3
+gcd:432360858532087298548744564083197299,240846574096518547683557847064319535,0:1
+gcd:-310788798729818682147559678302,-2172955391250831365155305151397888,0:2
+gcd:649283478652713472152371045373000641269,9179675498867400603641823155076,0:1
+gcd:79980532708199255123596245351024866045,35273005660545430889304120342364,0:1
+gcd:-83351007958684418946822288153831314277,-51634644710916030743119182132599855,0:43
+gcd:4992915740405389949821656927954249501,4523923119542484578579105473053048,0:21
+gcd:-801991401381703662108108758716412,1462655905419442096496214673085035312112,0:4
+gcd:679369055865583831572651301119431385801,6364653911974833953564963906049365,0:1
+gcd:32178714589413433072024739357148883,2182815001928827996341206621079833349525,0:19
+gcd:604754886257955637472038235002006997,75686581968330008368600832791867,0:11
+gcd:287068066584060661996114628597630371136,52011890293701406927883275870768865,0:1
+gcd:3979837024286745384581666788748758,7350136706945206821986896298939283,0:1
+gcd:7385865195603313817759905903511277,1520983986703891701713359953638,0:1
+gcd:764457193068206149728854992613,27858021258550102776458498820919,0:1
+gcd:-4155789385717252736363125208379519,513716864065732253356348104577569642,0:3
+gcd:97365354260983249124725672833811771,5020029690975786355406829440294084209626,0:1
+gcd:83139160308299020652846789174256754,3913486804605023733190361150860684,0:2
+gcd:-17691166446369130975076403772363811082668,94600134419678935394632555907142,0:2
+gcd:634823647473707443708903538054380,3956996255499668253479385484122050809317,0:1
+gcd:-3637804742599340390876015169076139565692,783241759542604459838225899706055858717,0:1
+gcd:585812248650822285457691267576462,21534520461947113931625020852108318,0:2
+gcd:11281432653044672416448534028211038025,711109480140515578563170257201359462,0:1
+gcd:676293649029453415159585825583394,97280549393475973449516311017466882903,0:1
+gcd:-60552656313655809329731693060696763524,493007935144068742422888317617165,0:1
+gcd:499127054152037037035927375386500,1203956412395744650060889503126393,0:1
+gcd:50094686288665713475507184834256049095574,-832478827433992238527275985275884802100,0:2
+gcd:3587136855297236649460183411772356035310,-712398604370738955166219235841134498742,0:2
+gcd:-8101551106022390770336067301182994,9185799272249263720169676176910186035467,0:1
+gcd:68680574795029722620883183609775450677,-84158462638889794851250260034014551972363,0:1
+gcd:155258118178686765062886673806448566,-6850017870177195667059084688029341396610,0:6
+gcd:285166743996114296479394289968524943,559627723033455856754700399288311,0:1
+gcd:97635198013817214038209538637709608537616,-43337611052093405089732573050042882425535,0:1
+gcd:2025635628106428290541842218677337,8363403252785996217814021695187802,0:1
+gcd:39403341320445818916772945982544618,-3081545887974055895915003777735743,0:1
+gcd:66538675039876745133366881210395320367369,385523580015310377616062750074359,0:1
+gcd:568797587304724025372575349953868,-809993079501337508688725757864677957,0:1
+gcd:87438670031005707662235517162074411507878,762858503307630620547057859718065131261504,0:2
+gcd:-135539991676075663249711183869449098,3187117064807540583340853903135708355720,0:2
+gcd:3623316226168035106420698863103708,281527696822113339094642926844583498510,0:2
+gcd:462743256592937700094228107961335,-6269566498572477078237555404177435,0:5
+gcd:-685484600842741055621576203380446857767,871551172534175305655069705808532,0:1
+gcd:220964518681325411201409247135357488007,-5641829172229111635876189209726787450,0:1
+gcd:302531333113895329527974519952510,186535245939488501803212618851457571589,0:1
+gcd:817537141270922830542026664184986,7821981713799768623509532856543951,0:3
+gcd:8468979244486855292413811013010058,-209488808243349961649691393540068,0:2
+gcd:879852422051274089521663230058530,49497155404087571445757965616479604,0:2
+gcd:21764922287301916637920770938954126,164044760066720848860497915166650797335,0:1
+gcd:59469732179854673335933541543666124,33859516881008254191737434099260638598,0:42
+gcd:5622782096444522942366700649751601671560,1818924766888381565955786591467033096941030,0:10
+gcd:-83658234598433632746857009684831849359505,-29016349811234824466750396183186748,0:1
+gcd:7054089120269602821498711515003074,4095832337673576318592596805192095781914,0:2
+gcd:990394898068553803695514279851854605418847,-7739084020331097221051527297005947155388,0:1
+gcd:54075935489906064661012070011939942732,7918292813066039667153314788962651008581,0:1
+gcd:8772115771437424285869834799732506658796,-932849018789404004804426567212331569,0:1
+gcd:-474373401937043543973615567508636867124,-23736477393422078122335330115520892673,0:1
+gcd:8436352086792195283692976718955932574,-24226347745891111460405966918193715809620,0:2
+gcd:814519302031186083731939523439915121,55324835095437197264275880684820442585,0:13
+gcd:-237764758709584162016066869681905512952347,27730963225107998869867496093972168,0:1
+gcd:7518474854158787395750001309747813,8381114315785290417935232114225100106214,0:1
+gcd:57926271609377407522025180011097851547,-460438760475654775684236043340437433561,0:1
+gcd:6638349918167655693810387712273716693403,55308325418124425819340246954531134649556,0:1
+gcd:-792096039638367514268257857215475476214,17985352918594429617981644232595132,0:2
+gcd:17523605051927467343416676052611136060682,32818776862511079287568864844380549,0:1
+gcd:435598204136143930685119666237820390,902306362378699323196514142749053448065695,0:5
+gcd:7246625600474134146152993995542881524104,84045078681310625106949990828070364497,0:1
+gcd:-787638361574460696958641849383712843152717,-98972482600264920015196417920239935812005,0:1
+gcd:82374608290966933640517911377351376793038534,3375365592517566879211534105358267232412929,0:1
+gcd:-65869507968457359071511077346860349916,233541308077986424091233056554170108328607,0:1
+gcd:434965647854018848199731601803786298508849,6881642201690537465635377223216241,0:1
+gcd:719612999193225374224745692059996056358,-315519530953816852193901984099603790510,0:2
+gcd:3371856558784507755414140667220962994794,-46940188151078159734582108552804551252391781,0:1
+gcd:4803433840417804894873156694592939602852,-72456645795090954873268375616538340122311,0:1
+gcd:48568835567133010333265540506612310476167,-10706367926604784868082114989212135746648832,0:1
+gcd:-640514959144433868933444881224466486263623,495227035072426375802319189512972514543836,0:1
+gcd:-6488859550432975345382980598094012298,1739553070312394609661279054142037504040,0:2
+gcd:62439762329215278757554454849955204768025718,79602289985731119990152260854511851,0:1
+gcd:6054057220822234921996955072468282902047103,-41461621564455176604944655360416823,0:1
+gcd:41593335543156355768394832800525873230,751910447000975730197547607815241920,0:110
+gcd:994454253731718339598418586069934146007,674502407982587721309172287657440910774,0:1
+gcd:467599304203676521904495847137440151064429,1065364075426775111107441639016359411726,0:1
+gcd:-50006834540638623993722097585899096403763,-5313099491095445109561808031972399857647,0:1
+gcd:80633786527554906657368596063180401716797,60423064130048311342811193512905633441,0:1
+gcd:7515721962363288712694440724080300383839,847957688242291310060264069657345589412622,0:1
+gcd:27726212382161724111674518621229053817654,844465139764626291093420179330707907,0:1
+gcd:-9817131728229141224738800156068771165515,5514447437310670168515402768125807553,0:7
+gcd:1101490427405231724327190816394483390794764,-1715150116840413365727028822839059671039358,0:2
+gcd:8714614705512806124985108394035361802445153,2277516152797095323407597912040972562623326,0:1
+gcd:-40241069975197162607015133362864260639182295,92350494843755720369837991386076354459722485,0:5
+gcd:94926798565178929705057494111757110129555,654944641739167114202854904453615515658738188,0:1
+gcd:265280847975099333384365084677641815670787,79159871617113409657206914064640126799879245,0:1
+gcd:116347226264838928071222153238640922289035,68573180747149861177662470447052670907671443,0:3
+gcd:1040609825768545533315151293676302487896884,-81323728160947963681253577857302080515,0:1
+gcd:995902591817252306534602024050315471330353754,5332558356879676808399004303967153306,0:2
+gcd:2001969035383918099033090062929650143669765948,4190101466247488888803682714062857957220,0:4
+gcd:520711239532941932960582838954921846930386522,-3853096594619017503346777573808512971,0:1
+gcd:60199373689261241651972446393273631317362,4966864098864732001544113870901038040,0:2
+gcd:945149245494027792287917914515672725163081263,8902933189066222709145663761457459365794,0:1
+gcd:42113632082774519107063284261972952560637120,550965713086089226514793739995356299364345,0:5
+gcd:699130208513509445029837360613055447835,1388996167624703080432361535173321299212301763,0:1
+gcd:2708864861499120155181972404884433662661130826,-9669434874243213781569557549324652869447,0:1
+gcd:-2663320619224926510783240759799877830,-9288856838720796348912703146202293649985994,0:2
+gcd:129339208558322679510730678747389994722,12274162664070343010820636150243461714,0:2
+gcd:7927826382521640149002540477963715500150746,169024688202278131082480706237325364215068990,0:6
+gcd:136906526225769628858637915191370345692692,539213183682016621647404279498623014328141,0:1
+gcd:30681142365936990868501835461428152495,-5027491490146180677917496407674117704,0:1
+gcd:-971981137022757867271162004648718096950546,4334305792750860480761829171455584581712,0:2
+gcd:578802014801938809246604894083179003839,4755521418153118560811649969223227339815203,0:1
+gcd:-85637729865865539531457719920611651870241486,974400175977421869121902925057819107693817,0:1
+gcd:-168964790731095355351979412256338118430524648,170138331609580398941494555432555720911428772,0:4
+gcd:790938498909251314495722876378080005340582079,5214770204816378474402582970231763702140978,0:3
+gcd:3097935765451813281781983641770574025792276,42609404056306319259222360596281494320705429231,0:1
+gcd:-98485087154927525975034391790808080098982,19775664577849930783360381707025488283978,0:2
+gcd:25900464334299058097279910365875929228,58255952834922520501042331752256379575,0:1
+gcd:79400185595521899110261406600117591081721314118,201740226840130845073877991057259510967,0:1
+gcd:981167299738316185980724229187020822277,8133607419206585086507618470282084549435045911,0:1
+gcd:81466412463591236560961446462245299836549126707,866192944729287017177690246604876328497,0:3
+gcd:6534998388738554052417315288897046254899165842,46609611771478693989087838979597248775,0:1
+gcd:948084924179221265735435784532032916982,31095014697784883179376411641933005719333,0:1
+gcd:2750322192684776089555518232723747026,16282797711115835147148988819960931175880625768,0:2
+gcd:-916832268194684002726682872945582785046,80175456371164380904577325966825746198033406059,0:1
+gcd:282231592138255672195189656428026230056,96673996679717919403145753072968455552546,0:2
+gcd:550580097204590201609373226827993784219420731,60517713169991893657707958780297059239491,0:1
+gcd:31526794192792048622410273704705620482050682,70537996848502378104686898733501905256490,0:2
+gcd:-923613180033278870451470473112995033306843225,62635452857298067541908563173475507759656054707,0:1
+gcd:469196843768624413897755875308788890398465291232,-15296277161521766221056511754171865009042943213,0:1
+gcd:2628065716223500508449356215564412668664236,713708318009199991674271791693482010536664884,0:4
+gcd:604553604369312265623368647573085123221252020,990982890678004704551740474471789043760433700479,0:1
+gcd:97586462652371414650265963064033775148721243,969409880443270812997088798402379069080662,0:1
+gcd:-765406874969209688613302257358735487317,687488505077706911028822098735771705823765697808,0:1
+gcd:85075624707999635862443444914978287825359,778046486301986342411165862027907781749497,0:1
+gcd:8227248806783006644129224253415431417213104067,-96883503079217553138854609209329008354340832050,0:1
+gcd:5027554007771258456873599804445876368468,9124875242153734630106913217321584664013715,0:1
+gcd:39245745484403729199058188063461104557810253,220067769421357576954105356315871937975114,0:1
+gcd:12265626358518464602956912462337886264411404165,-62808539324142868756473505816723401975937,0:1
+gcd:-12272356051659726939876917766506363796290,17656166644036956054896242696928896080969790493,0:1
+gcd:637223594292638303876168193085997138882431056,94504571343119776477559774058446419793557358444,0:4
+gcd:5571012420064356266635359647247635200655740,-21295217227115690481188602248443089551209070396,0:4
+gcd:5263843748978600609740419748581371970418448276216,5384845751134428162699702180820131424931650492254,0:2
+gcd:886573921242233631853410597832339291851986573,91564665302299543163193474542608720062467,0:1
+gcd:26539751625701457124278640373644598585396,2325338527842485879693477585982320189921160388553,0:1
+gcd:353508003643539157483752498296868928280378,10742495675871104458509832622060247315860,0:2
+gcd:-4734613561112436559828705330418786656799216681,5767402184612349878575526105980302509419976764,0:1
+gcd:82083010698635736174070971617820650592649198695,632174562080517027772509374721051956918078145045,0:15
+gcd:6173991144338684494350090118957116722781373,-738485502817232028305101940854863776286515,0:1
+gcd:-493513047233893983448577482415236886372545860,510358065314512191744416886029069217313650,0:90
+gcd:326654054139623246358073868314669601484091,-749350879522921841553744544029160051092161118734,0:1
+gcd:1402621524995633967650615579165227953957890517212,-4307813373241246419295301377872133252586,0:2
+gcd:429404746005804957738561594094664667352987,378882853314853204091011966904771925997210303,0:1
+gcd:332341701384724523211310134953299492552149033413,851224516641538736779656410258860743437969813415,0:1
+gcd:8093542646198882950722808884458624246299608906958,-36537804019444103265563497755234936603188804846,0:2
+gcd:22659814113479956892126670971189905912120035824,-7769923990496178313173088170032841760727,0:1
+gcd:-66431972193306385702365512934093484764859082,36581996652652744665199423002405565247156,0:14
+gcd:-888473800362239868616054745127669042022317,142999759078860850560633007783677610020527766,0:3
+gcd:5971942663513046812876552589351160577576206860,5155119487765712370432570496238254289228130147,0:1
+gcd:36328343589972083920724771391132711614346,626466814451530915421088090957480792070888316,0:22
+gcd:5293116409600323220539205506696278195160522774280,-89478075685508708042860880549625934136374,0:2
+gcd:79576614103508536656978289576589750212587261,852468870734033057111244131505440601392558836846,0:1
+gcd:8225066772418695359596812838151452668642167,32895491347247919323385073727832554930053,0:1
+gcd:6163942593967174125699747500635651388266851958125,35785148285967657728202559017385960485415693874,0:1
+gcd:2768453763718344802615194690925869147682838954,295289393573622382700104229276698254424111309,0:1
+gcd:543530772918490900335995207569824317804903920459,3816523263571207729432080444412751436592123632,0:1
+gcd:1092477340633785505464776554395206472561372312061,-80145274095041381989361699268630409045305877,0:1
+gcd:5221300639042222043517187865188827094681806,28716457589092549537459686031371792838180039728,0:6
+gcd:-468871256127286679587501070578429844680401783,7709908112767006788780052051800778651016113933,0:1
+gcd:60187668034435065431875732180204005950423,6575730301760601160210842777500398231559661,0:1
+gcd:85750547893356514086330287277441673045104762,79743140579005364490235586620393656130064,0:2
+gcd:4548581293372942515724176487253593549214930,4238661184062900689214356649238748109095650,0:10
+gcd:870890539340345883811990618518239041519315472381,-326492148393756245001717974027772662339968,0:1
+gcd:66987553698256227716875714961629477167428173612,90975165679807773385648454136069587671757554212,0:4
+gcd:55214217278725852504312036656428464058159216571,-38639629611220548541845337991516346077285504,0:1
+gcd:891217139364757949280558543150622433360536923866,30525879876993440244467275213072433106397646327,0:1
+gcd:-27569366446500582408824975793718887457276922405388,634666021153562229559368735956062829411322343,0:7
+gcd:502864235446447920785714797929749621810588808385,-661761137717295415776353819805381820532626437501375,0:5
+gcd:846540274257645306570757431119674434472851673,8616613565185012233547219046445322085886975,0:1
+gcd:-3309007371119113533010968742743901666008447,-54456422219293958622124113256532150483182055,0:1
+gcd:3808438337556464123872249539607274641406985997532,8958313515020597801994910602927304472155060964765,0:1
+gcd:3966980856734279836284487724100931405197679196,7991199588345191911654938564028578389298180118364,0:4
+gcd:65639444382189527381103754239686068124303248439,57344187472963481946737524023690750337279473205806,0:1
+gcd:415167227201847402226579925485934896345892,586575228633844519664975226407615633553394085108,0:4
+gcd:61619333876398280418219395631027787927517659829394,919912829682211281138193507951318719985265,0:1
+gcd:-868753784405826481862596863379498777711457154096,545880080147628730834302628389405153791727839,0:1
+gcd:9429941770445780812848883836626433106364646270218,13789105660912116612159357433833332620650429,0:1
+gcd:43608475425036256086742701999180132009804867174088,26543470249142438881834938827109299420258184885237,0:1
+gcd:57684506610503798187871631196324475714333617510881,471695506003883133237678946411955700467360,0:1
+gcd:45545031179301366913301053296868047362176530184,-91968879037454375774626628433933013352182139387,0:1
+gcd:-390021533721654785753654976920878586915091,77031076759836910371783959035306703983828680,0:3
+gcd:423541795082126371645621560317104281087986536944,8300998559716429411460238557591751288655280830676799,0:3
+gcd:-22004254439719621882091733525180851819037175217519,99335356922776842325949741933027888097618837,0:1
+gcd:-568617824838411255064542027229734991599889058339286,663945656360600870466864889023341282183894393751666,0:18
+gcd:79416546968775553905606945911160893343240489,57823044209535496953371020115352329847370545,0:9
+gcd:944931014689390846530685010237152128723129879051,9132010491010578008428313272813386452749469110941235,0:1
+gcd:10724730362623743957337791385603755532922863,72480373654893123070601266938859686093303005387292,0:1
+gcd:7713352208339235603081099644445084271357860,603624463205826416829628929324533190899935786563381,0:3
+gcd:-374652992235609318781751374140306949494493761487551,-8211631925711097443824357620157273567158306960781,0:1
+gcd:148033237001979427358794216800322662159772216729882,-2761071692676096788505988250569937615812882,0:2
+gcd:8799836897423935827052239970797993642793054321869,7294647877437509677171255169879966954414823484,0:1
+gcd:638050122120135743843926357476168630346968836720976,-521011870575614667006902791543319211035082259559038,0:2
+gcd:-17589569754541719055752617853886490778777621596833622,-757763302557856615098419826290170728613135917189,0:1
+gcd:-9391500830250456597029446286855934735787373415653,28432489383197015180933073382445953529667174,0:1
+gcd:597671128380217947385553643776956963479914986403,71727950226724858021016384499343090206442916,0:1
+gcd:220524861586728547654066186650842017022514113,99830670175055229565653522851124444573641171168883370,0:1
+gcd:-19711747183549435340491469077888147043386014913558,-1141914280129478236596364286858351511269528735,0:1
+gcd:-8382072953685010521572064715326232892979307367,8986558828596332338706049003428573784660004270,0:1
+gcd:8502152308582607794375019565844324676023491104593,10470050208175536662422671560468368371690332,0:1
+gcd:594601725521916181847167140525593251441576703983,963458725567603941710493681498226412426881800,0:1
+gcd:7141961266638507042734562322157608790427840009,-4549724799885066646710284284349071123364728193387,0:1
+gcd:-556279059738139499395948604306347001411150129841210,96265906951839620646630096006130967227739083772932,0:2
+gcd:9097507009232650355633416767082868346314279788737,-12952310876092402836370081770801404571317963729609,0:1
+gcd:4268792759888467657870170840963084681877952381149,45230992824683770972952637110379461673717665076497477,0:1
+gcd:-14981624589272129153412283534256311120144659052,-3422881033749335138988900898217088225431538419464,0:4
+gcd:1220927142068793741881867214403185329458765760024,30622524744504892825380221509502752145574896,0:8
+gcd:37912807996403481194979034824173466165481184382714959,-90878397829297201187948170371749592240094934625,0:1
+gcd:11421510093950565340830017403217629128966938056,2237414009357389011349863244579333296452235392013656,0:8
+gcd:192657988036570687555057992620686662908295387946910176,931495134488306662235768448970442482109561110,0:2
+gcd:3406199971289940059753501832956133340637816361746774,21717729758322757474808809344766892648120530501033,0:1
+gcd:6909979467876024377878180024452018966109074368033,842722308262405734840545048662350517397572773044955,0:1
+gcd:373077837411940479742523640303846004174658252010,174968689985940718533112057941120724001834591,0:1
+gcd:69447921082122879577796325457481062492384026062297,4859735149388070292660864796695584862286590039960,0:1
+gcd:97668956744134573191931364533568770116368809990432277,32650097939706033583832290610502297382443475332059,0:67
+gcd:-1130623853521736649164698623052358825973875071086,97117938880122601762963490311393663414262844,0:6
+gcd:5196766948376722446473792182397797566282488000645,612809465745222737408369151997835003504928829,0:1
+gcd:-260800009832764286426719551521843883719112476,-4764630548313512861236355180550436291099515479440,0:4
+gcd:446884272848375074930942162217302913946161786743256,21042882325490620038960351129083746002919260315816,0:8
+gcd:951599922613172445123982155673072679115439437787116,170174123089259663169419228763721448308107859122519941,0:1
+gcd:21383950451514823653827321489681070470148156716394,474049024111864801681311013604155672359293053819708610,0:2
+gcd:-470414357544256461922663993336752968654129573423633,9062081906619161788388889503790336651084511675587,0:1
+gcd:780091812513073375693179028189802313142318232500,3497278556984926411479728842600230671778387696053,0:1
+gcd:-1625948018138433921639232759767284243608022009577,842118879046315463699452834842435152085239651627,0:1
+gcd:25026283351500865895404594716390919370787136725638,193605742569640932386538365909397399503766353419,0:1
+gcd:4935030558829975380051283297334807636335988292915939464,826975811338155401386754284486847375740824437795565,0:1
+gcd:692976306506130156561485116659173381923120836885557,770158528298664593632506223863839610768381103479684,0:7
+gcd:79877139216893064041018839082816187503862428735,7269106113282857654532427145534479409503583394410641,0:1
+gcd:2539745404867281753796678186777103230989134057269,1232562503892732555700624680547460824244298064,0:1
+gcd:-12342369542383197426854745694214905543911988477283,900468407001638487525579769577535461149066925224901,0:1
+gcd:25508383419230789798346692675791795579961116333703,-3196912743165527117167038251788165837584914845275,0:1
+gcd:-1299528036083269250543034346520127753461072609198859,600594652353551219594047525595273354045086799190,0:3
+gcd:2299157394917175882710807816574923359426328448491205413,-72838172890838078649390158065336999589794176457016,0:1
+gcd:-7349901043851956691882158234459042155688766310737050452,38963935506607940884321914070762438994955796523516,0:4
+gcd:958387014018743982544025716556283287504010616036,1443504353635051762579994152447131178181054158,0:2
+gcd:246125390054194220242986809766512103907648232140291,244701030143825150512131468437935457382757506654,0:1
+gcd:-704660850546084071765145007935951186831012905395382833,5588984198927622386999113229239134076765551765835797488,0:1
+gcd:50682657377075501007405908966255159073041913889268,-221227972486061875975200412557047324616212536548,0:4
+gcd:-65153936048938235385603864221810574284616709045012408,2620409042204728497893539911547700871421142555353,0:1
+gcd:2124140486540339235997181873057458560557130144031198,6337118390151757487365380009696068490770095523526655,0:1
+gcd:70505951289040282645383932312380844925860919298,7547000534925894125969206219651626162975048702546706065,0:1
+gcd:-41539404414450841529694974131865311088044938789,-87120273993379326877611820290578462959192080166852098,0:3
+gcd:8365100924146743906263010309561180555381451232169,64464903694507870558459227754837948332608708108908133757,0:3
+gcd:-607028381550248615720149092346152462853976790359415563,-638047705393414341349283089715056902457142563666819,0:1
+gcd:9617834842433276206013447576300042077483363020815285,528061422615472570377974310003284316297281680382590494,0:11
+gcd:86576571095874523146332767288469633576872568596,28806568894922815646464384363885717260300665904363145435,0:1
+gcd:307009198563449723583109556832166934014223122475324,138726608616028283757694379054230076836833023549,0:1
+gcd:950446831200123302940271854492691726825599408858,-72101792770002156123347099210449392040964040896942,0:2
+gcd:981208671446974342191660850214776536471793694644642,42331603864003005956059961823201488180622810810249336717,0:1
+gcd:436034751789860072246023599184144455891992330310990,72833959249163120346712529298424162613591559886645,0:5
+gcd:90712859511805773491925085535825623597765615019643547,-747515802065477997196092836504038150570958532540685162,0:1
+gcd:397399782669545823592934194763075791833495372998,-59196779886291303828419299835113054892183602687860135035,0:1
+gcd:32400956990211215478801690694170683149459902468,-4583955972534683626923454093368608704790928252299,0:1
+gcd:987205647053507741802554416690401353287928887038,99876648283232575129630115679242229378848334523759990898,0:14
+gcd:613843278686603793281546390730144010908586402122774247,-5096436233192165525303465082471737429087562092805456864,0:1
+gcd:-976952961430926103170472845979881570029763109667,935178486322270132160329332160301439376977149568344208099,0:1
+gcd:-14766907052440196735362466027665124699631240785562617,56185497908476101017098165076418921931361374576783903,0:1
+gcd:8086945629611784458016532027184114429962417844094,915144274243273504802165174453120299631299876477769004475,0:1
+gcd:78088762763327100616786616097147636046671948600444,567540241084477255158834032762283528860020033647985833,0:3
+gcd:719986964333569855824423695658491299542433105292,-615276910378191482694097418592439439457014608822814,0:2
+gcd:45518095176552517046254533808850801860612235127698055,35562211507032265793347677842985571735031362689772443740,0:5
+gcd:9347651927739244225461883666785850681796998039204,-49878021756813856103391637115956958358002286487531,0:13
+gcd:-918018144578664428004161449615771398954961013294489,-670699097650597095681408528960639081653596263477957,0:1
+gcd:27390700201762535100035783959539579449610388231,-1589447744597072139866306928627083981945967837919031841,0:1
+gcd:2277199840598187516900058221233481999025368188568,9608219845154413235861538421470991851896216584568613,0:3
+gcd:-384224188940171310851587214747099156035618205974037811,-365155157346205326208918238248019306559191342503,0:1
+gcd:286446854858822908871115682474835177238732522628,-57158496101544373650727927690968913495792599007869,0:1
+gcd:-381089856197823678538852020226946248080829424869589,-3010621081997078653311455126099557341287585438919,0:1
+gcd:116824003493453841699155925492342665434851317689062,-23510392931055495213857939210838689217666922526899551035,0:1
+gcd:580076669302513896163920831671903321718154827187111,57642903862300589084685292813271561699366462736142,0:1
+gcd:5760449410973032312996903274730533429280588604119,54924391723347076414566698417788233810196808558058264,0:9
+gcd:5657781195595763129830083459999757852112323789572340704,692061618840647789470644193517118113508111433346167161307,0:1
+gcd:-411686824144764716061907353842274549877341843077020461,64596348790121485579427789661619008385819947602752810318,0:1
+gcd:632256394728894097701649213009572878755743290206395156077,831219707790000649838963373434914934485492976701321111,0:1
+gcd:1670481530219772906326138470230000469885289884882422,468290338328174403769157221534943442214405575737600,0:2
+gcd:-5940255960924729598832299636442321100271324046668226,57672031765846684220194592702663453624777841860734299817,0:1
+gcd:1070320750308710183653165839089007570013512879851785,1457798154372592051774290334996812066679847800239,0:1
+gcd:4878833860261622243309660185570248437064542060170266009303,2713399212910344466363698742990679778889654409261764714,0:1
+gcd:-153727669883775746511963322850970227020812560900211022,967696702028565741720227898697068313091723784217356354,0:14
+gcd:-540592613733911579302709730020084890208422708295834255759,1487237786400760689794761062671094249214728767786149324317,0:1
+gcd:6147134348286513705872901614503400707429078163757093529,477008107151085089956583728568535862114663515203848020888,0:13
+gcd:7614680849639684551334463800131196276563566036683927,25187069984138015151555984154271413618496480687947851,0:1
+gcd:34751974072174908316243318351151710272413759348773,8306602488518142539700335965542308143538343391985,0:1
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/.gitignore b/polly/lib/External/isl/imath/tests/gmp-compat-test/.gitignore
new file mode 100644
index 00000000000..64a46a937a9
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/.gitignore
@@ -0,0 +1,10 @@
+*.o
+*.so
+*.pyc
+#for now...
+test.list
+gmp_test.c
+imath_test.c
+wrappers.py
+*.tests
+_T*
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/README b/polly/lib/External/isl/imath/tests/gmp-compat-test/README
new file mode 100644
index 00000000000..b03282517c0
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/README
@@ -0,0 +1,106 @@
+Overview
+==================================================
+This directory contains a random test generator for the gmp
+compatibility layer of imath. The tests cases are randomly generated
+and run with both gmp and imath. The results are compared and any
+mismatching results are flagged as failures.
+
+You should not see any failures when running these tests.
+
+Requirements
+==================================================
+These tests use the python ffi to run the imath and gmp functions. To
+run these tests you will need the following items
+
+ * libimath.so
+ * python 3
+ * gmp library and header files
+
+
+Running
+==================================================
+All the tests cases will be generated and run automatically by the
+makefile. First, make sure you have built libimath.so in the top level
+imath directory.
+
+Use the following command to generate and run the tests
+
+ $ make TESTS=random.tests
+
+This should generate all the needed wrapper files along with the
+randomized unit tests. By default the unit tests are output to the
+random.tests file. The tests can be run by hand using the following
+command line
+
+ $ ./runtest random.tests
+
+You can also write your own unit tests and run them by passing the
+file name to the runtest script.
+
+
+Testing Methodology
+==================================================
+The goal of our testing is to ensure that we are compatible with the
+gmp api. To test our compatibility layer we generate inputs for each
+gmp api that we wrap and then call the gmp version of the api and
+compare the results to the imath version. The results should be
+identical. Any output mismatch is considered an error.
+
+
+Testcase Generation
+--------------------
+The test data generation is inspired by the QuickCheck testing
+methodolgy. We want to test both random data and important values such
+as 0,1,-1, etc. We generate input data based on the type of the input
+parameter. Most apis take either an mpz_t or a signed/unsigned long.
+
+For each parameter of the given type we generate the following values:
+
+ mpz_t: 0,1,-1, all min/max values, all min/max values +/- 1
+ small numbers: 1-4 digits
+ medium numbers: 5-20 digits
+ large numbers: 20-100 digits
+ long : 0,1,-1 short,int,long min/max values
+ random long values
+ unsigned long: 0,1,-1, unsigned short, unsigned int, unsigned long min/max values
+ random unsigned long values
+
+The generated data for each paramater is combined to produce a series
+of inputs to the function. The input data format looks like:
+
+mpz_add|0,1,2
+
+Which represents the call mpz_add(0, 1, 2). Additional test cases can be written by hand.
+
+Test Structure
+--------------------
+The tests are run using the python ffi (the ctypes module). We have a
+single description of each api that is used to generate the following:
+
+ * intput data
+ * c function wrapper to call the libgmp or libimath function
+ * python wrapper to call both libgmp and libimath wrappers and compare results
+
+The test_gmp.so and test_imath.so libraries are loaded at runtime by
+the python runner scrip and used to run each test input and compare
+the results.
+
+The code generation pattern looks something like this:
+
+genctest.py ~~generates~~> gmp_test.c <--includes-- gmp_custom_test.c
+gmp_test.c ~~generates~~> gmp_tests.so <--links-- libgmp.so
+genpytest.py ~~generates~~> wrappers.py <--calls-- gmp_test.so
+gmp_test.so --loads--> runtest.py <--includes-- wrappers.py
+ ^
+ |
+ reads
+ |
+gendata.py ~~generates~~> random.tests
+
+Adding tests for new APIs
+==================================================
+New apis can be tested by modifying the gmpapy.py file. This file
+contains a list of all apis that will be tested. Adding an api to the
+apis list will cause code and input data to be generated for that api.
+Rerunning make will generate the test data and code to run the test.
+
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/genctest.py b/polly/lib/External/isl/imath/tests/gmp-compat-test/genctest.py
new file mode 100755
index 00000000000..67c140e2a21
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/genctest.py
@@ -0,0 +1,266 @@
+#!/usr/bin/env python3
+import sys
+import gmpapi
+from gmpapi import void
+from gmpapi import ilong
+from gmpapi import iint
+from gmpapi import ulong
+from gmpapi import mpz_t
+from gmpapi import size_t
+from gmpapi import charp
+from gmpapi import mpq_t
+
+class APITest:
+ def __init__(self, gmpapi):
+ self.api = gmpapi
+
+ def test_prefix(self):
+ return "test"
+
+ def test_param_name(self, ty, i):
+ if ty == mpz_t:
+ pname = "p_zs"
+ elif ty == ilong:
+ pname = "p_si"
+ elif ty == ulong:
+ pname = "p_ui"
+ elif ty == iint:
+ pname = "p_i"
+ elif ty == charp:
+ pname = "p_cs"
+ elif ty == mpq_t:
+ pname = "p_qs"
+ else:
+ raise RuntimeError("Unknown param type: "+str(ty))
+ return pname + str(i)
+
+ def test_param_type(self, ty):
+ if ty == mpz_t or ty == mpq_t:
+ pty_name = "char *"
+ else:
+ pty_name = str(ty)
+ return pty_name
+
+ def test_var_name(self, ty, i):
+ if ty == mpz_t:
+ vname = "v_z"
+ elif ty == ilong:
+ vname = "v_si"
+ elif ty == ulong:
+ vname = "v_ui"
+ elif ty == iint:
+ vname = "v_i"
+ elif ty == size_t:
+ vname = "v_st"
+ elif ty == charp:
+ vname = "v_cs"
+ elif ty == mpq_t:
+ vname = "v_q"
+ else:
+ raise RuntimeError("Unknown param type: "+str(ty))
+ return vname + str(i)
+
+ def test_var_type(self, ty):
+ if ty == mpz_t:
+ return self.mpz_type()
+ elif ty == mpq_t:
+ return self.mpq_type()
+ else:
+ return str(ty)
+
+ def init_var_from_param(self, ty, var, param):
+ code = "\t"
+ if ty == mpz_t or ty == mpq_t:
+ code += self.api_call_prefix(ty)+"init("+var+");\n\t"
+ code += self.api_call_prefix(ty)+"set_str("+",".join([var,param,"10"])+")"
+ if ty == mpq_t:
+ code += ";\n\t"
+ code += self.api_call_prefix(ty)+"canonicalize("+var+")"
+ else:
+ code += var + "=" + param
+ return code
+
+ def init_vars_from_params(self):
+ code = ""
+ for (i,p) in enumerate(self.api.params):
+ param = self.test_param_name(p, i)
+ code += "\t"
+ code += self.test_var_type(p) + " "
+ var = self.test_var_name(p, i)
+ code += var + ";\n"
+ code += self.init_var_from_param(p, var, param) + ";\n\n"
+ return code
+
+ def make_api_call(self):
+ bare_name = self.api.name.replace("mpz_", "", 1).replace("mpq_", "", 1)
+ call_params = [self.test_var_name(p,i) for (i,p) in enumerate(self.api.params)]
+ ret = "\t"
+ ret_ty = self.api.ret_ty
+ if ret_ty != void:
+ ret += self.test_var_type(ret_ty)+" "+self.test_var_name(ret_ty, "_ret") + " = "
+ # call mpq or mpz function
+ if self.api.name.startswith("mpz_"):
+ prefix = self.api_call_prefix(mpz_t)
+ else:
+ prefix = self.api_call_prefix(mpq_t)
+ return ret + prefix + bare_name + "(" + ",".join(call_params) + ");\n"
+
+ def normalize_cmp(self, ty):
+ cmpval = self.test_var_name(ty, "_ret")
+ code = ""
+ code += """
+ if ({var} > 0)
+ {var} = 1;
+ else if ({var} < 0)
+ {var} = -1;\n\t
+""".format(var=cmpval)
+ return code
+
+ def extract_result(self, ty, pos):
+ code = ""
+ if ty == mpz_t or ty == mpq_t:
+ var = self.test_var_name(ty, pos)
+ code += self.api_call_prefix(ty) + "get_str(out+offset, 10,"+var+");\n"
+ code += "\toffset = offset + strlen(out); "
+ code += "out[offset] = ' '; out[offset+1] = 0; offset += 1;"
+ else:
+ assert pos == -1, "expected a return value, not a param value"
+ if ty == ilong:
+ var = self.test_var_name(ty, "_ret")
+ code += 'offset = sprintf(out+offset, " %ld ", '+var+');'
+ elif ty == ulong:
+ var = self.test_var_name(ty, "_ret")
+ code += 'offset = sprintf(out+offset, " %lu ", '+var+');'
+ elif ty == iint:
+ var = self.test_var_name(ty, "_ret")
+ code += 'offset = sprintf(out+offset, " %d ", '+var+');'
+ elif ty == size_t:
+ var = self.test_var_name(ty, "_ret")
+ code += 'offset = sprintf(out+offset, " %zu ", '+var+');'
+ elif ty == charp:
+ var = self.test_var_name(ty, "_ret")
+ code += 'offset = sprintf(out+offset, " %s ", '+var+');'
+ else:
+ raise RuntimeError("Unknown param type: "+str(ty))
+ return code
+
+ def extract_results(self):
+ ret_ty = self.api.ret_ty
+ code = "\tint offset = 0;\n\t"
+
+ # normalize cmp return values
+ if ret_ty == iint and "cmp" in self.api.name:
+ code += self.normalize_cmp(ret_ty)
+
+ # call canonicalize for mpq_set_ui
+ if self.api.name == "mpq_set_ui":
+ code += self.api_call_prefix(mpq_t) + "canonicalize("+self.test_var_name(mpq_t, 0)+");\n\t"
+
+ # get return value
+ if ret_ty != void:
+ code += self.extract_result(ret_ty, -1) + "\n"
+
+ # get out param values
+ for pos in self.api.out_params:
+ code += "\t"
+ code += self.extract_result(self.api.params[pos], pos) + "\n"
+
+ return code + "\n"
+
+ def clear_local_vars(self):
+ code = ""
+ for (i,p) in enumerate(self.api.params):
+ if p == mpz_t or p == mpq_t:
+ var = self.test_var_name(p, i)
+ code += "\t"+self.api_call_prefix(p)+"clear("+var+");\n"
+ return code
+
+ def print_test_code(self, outf):
+ api = self.api
+ params = [self.test_param_type(p)+" "+self.test_param_name(p, i) for (i, p) in enumerate(api.params)]
+ code = "void {}_{}(char *out, {})".format(self.test_prefix(), api.name, ", ".join(params))
+ code += "{\n"
+ code += self.init_vars_from_params()
+ code += self.make_api_call()
+ code += self.extract_results()
+ code += self.clear_local_vars()
+ code += "}\n"
+ outf.write(code)
+ outf.write("\n")
+
+class GMPTest(APITest):
+ def __init__(self, gmpapi):
+ super().__init__(gmpapi)
+
+ def api_call_prefix(self, kind):
+ if kind == mpz_t:
+ return "mpz_"
+ elif kind == mpq_t:
+ return "mpq_"
+ else:
+ raise RuntimeError("Unknown call kind: "+str(kind))
+
+ def mpz_type(self):
+ return "mpz_t"
+
+ def mpq_type(self):
+ return "mpq_t"
+
+class ImathTest(APITest):
+ def __init__(self, gmpapi):
+ super().__init__(gmpapi)
+
+ def api_call_prefix(self, kind):
+ if kind == mpz_t:
+ return "impz_"
+ elif kind == mpq_t:
+ return "impq_"
+ else:
+ raise RuntimeError("Unknown call kind: "+str(kind))
+
+ def mpz_type(self):
+ return "impz_t"
+
+ def mpq_type(self):
+ return "impq_t"
+
+def print_gmp_header(outf):
+ code = ""
+ code += "#include <gmp.h>\n"
+ code += "#include <stdio.h>\n"
+ code += "#include <string.h>\n"
+ code += '#include "gmp_custom_test.c"\n'
+ outf.write(code)
+
+def print_imath_header(outf):
+ code = ""
+ code += "#include <gmp_compat.h>\n"
+ code += "#include <stdio.h>\n"
+ code += "#include <string.h>\n"
+ code += "typedef mpz_t impz_t[1];\n"
+ code += "typedef mpq_t impq_t[1];\n"
+ code += '#include "imath_custom_test.c"\n'
+ outf.write(code)
+
+def print_gmp_tests(outf):
+ print_gmp_header(outf)
+ for api in gmpapi.apis:
+ if not api.custom_test:
+ GMPTest(api).print_test_code(outf)
+
+def print_imath_tests(outf):
+ print_imath_header(outf)
+ for api in gmpapi.apis:
+ if not api.custom_test:
+ ImathTest(api).print_test_code(outf)
+
+def main():
+ test = sys.argv[1]
+
+ if test == "gmp":
+ print_gmp_tests(sys.stdout)
+ elif test == "imath":
+ print_imath_tests(sys.stdout)
+
+if __name__ == "__main__":
+ main()
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/gendata.py b/polly/lib/External/isl/imath/tests/gmp-compat-test/gendata.py
new file mode 100755
index 00000000000..225f71b7aa0
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/gendata.py
@@ -0,0 +1,338 @@
+#!/usr/bin/env python3
+import random
+import gmpapi
+
+MAX_SLONG="9223372036854775807"
+MIN_SLONG="-9223372036854775808"
+MAX_ULONG="18446744073709551615"
+MAX_SINT="2147483647"
+MIN_SINT="-2147483648"
+MAX_UINT="4294967295"
+MAX_SSHORT="32767"
+MIN_SSHORT="-32768"
+MAX_USHORT="65535"
+
+def plus1(x): return str(int(x)+1)
+def minus1(x): return str(int(x)-1)
+def apply(fun, lst):
+ return list(map(str, map(fun, lst)))
+
+mzero_one = ["-0", "-1"]
+zero_one = ["0", "1"]
+mm_slong = [MAX_SLONG, MIN_SLONG]
+mm_slong1 = [minus1(MAX_SLONG), plus1(MIN_SLONG)]
+mm_ulong = [MAX_ULONG]
+mm_ulong1 = [minus1(MAX_ULONG)]
+mm_sint = [MAX_SINT, MIN_SINT]
+mm_sint1 = [minus1(MAX_SINT), plus1(MIN_SINT)]
+mm_uint = [MAX_UINT]
+mm_uint1 = [minus1(MAX_UINT)]
+mm_sshort = [MAX_SSHORT, MIN_SSHORT]
+mm_sshort1= [minus1(MAX_SSHORT), plus1(MIN_SSHORT)]
+mm_ushort = [MAX_USHORT]
+mm_ushort1= [minus1(MAX_USHORT)]
+mm_all = mm_slong + mm_ulong + mm_sint + mm_uint + mm_sshort + mm_ushort
+zero_one_all = mzero_one + zero_one
+
+
+mpz_std_list = zero_one_all + mm_all + apply(plus1, mm_all) + apply(minus1, mm_all)
+si_std_list = zero_one + mm_slong + mm_sint + mm_sshort + mm_slong1 + mm_sint1 + mm_sshort1
+ui_std_list = zero_one + mm_ulong + mm_uint + mm_ushort + mm_ulong1 + mm_uint1 + mm_ushort1
+
+def gen_random_mpz(mindigits=1, maxdigits=100, allowneg=True):
+ sign = random.choice(["", "-"])
+ if not allowneg:
+ sign = ""
+ return sign + gen_digits(random.randint(mindigits, maxdigits))
+
+def gen_random_si():
+ si = gen_random_mpz(mindigits=1,maxdigits=19)
+ while int(si) > int(MAX_SLONG) or int(si) < int(MIN_SLONG):
+ si = gen_random_mpz(mindigits=1,maxdigits=19)
+ return si
+
+def gen_random_ui():
+ ui = gen_random_mpz(mindigits=1,maxdigits=20, allowneg=False)
+ while int(ui) > int(MAX_ULONG):
+ ui = gen_random_mpz(mindigits=1,maxdigits=20, allowneg=False)
+ return ui
+
+def gen_digits(length):
+ if length == 1:
+ i = random.randint(1, 9)
+ else:
+ digits = [random.randint(1,9)] + [random.randint(0,9) for x in range(length-1)]
+ digits = map(str, digits)
+ i = "".join(digits)
+ return str(i)
+
+def gen_mpzs(mindigits=1, maxdigits=100, count=10):
+ return [gen_random_mpz(mindigits=mindigits, maxdigits=maxdigits) for x in range(count)]
+
+default_count = 10
+def gen_sis(count=default_count):
+ return [gen_random_si() for x in range(count)]
+
+def gen_uis(count=default_count):
+ return [gen_random_ui() for x in range(count)]
+
+def gen_small_mpzs(count=default_count):
+ return gen_mpzs(mindigits=1,maxdigits=4,count=count)
+
+def is_small_mpz(s):
+ return len(s) >= 1 and len(s) <= 4
+
+def gen_medium_mpzs(count=default_count):
+ return gen_mpzs(mindigits=5,maxdigits=20,count=count)
+
+def is_medium_mpz(s):
+ return len(s) >= 5 and len(s) <= 20
+
+def gen_large_mpzs(count=default_count):
+ return gen_mpzs(mindigits=21,maxdigits=100,count=count)
+
+def is_large_mpz(s):
+ return len(s) >= 21
+
+def gen_mpz_spread(count=default_count):
+ return gen_small_mpzs(count) + gen_medium_mpzs(count) + gen_large_mpzs(count)
+
+def gen_mpz_args(count=default_count):
+ return mpz_std_list + gen_mpz_spread(count)
+
+def gen_mpq_args(count=4):
+ nums = zero_one + gen_mpz_spread(count)
+ dens = ["1"] + gen_mpz_spread(count)
+ return [n+"/"+d for n in nums for d in dens if int(d) != 0]
+
+def gen_si_args():
+ return si_std_list + gen_sis()
+
+def gen_ui_args():
+ return ui_std_list + gen_uis()
+
+def gen_list_for_type(t, is_write_only):
+ if (t == gmpapi.mpz_t or t == gmpapi.mpq_t) and is_write_only:
+ return ["0"]
+ elif t == gmpapi.mpz_t:
+ return gen_mpz_args()
+ elif t == gmpapi.ilong:
+ return gen_si_args()
+ elif t == gmpapi.ulong:
+ return gen_ui_args()
+ elif t == gmpapi.mpq_t:
+ return gen_mpq_args()
+ else:
+ raise RuntimeError("Unknown type: {}".format(t))
+
+def gen_args(api):
+ if api.custom_test or api.name in custom:
+ return custom[api.name](api)
+ types = api.params
+ if len(types) == 1:
+ return [[a] for a in gen_list_for_type(types[0], api.is_write_only(0))]
+ elif len(types) == 2:
+ t1 = gen_list_for_type(types[0], api.is_write_only(0))
+ t2 = gen_list_for_type(types[1], api.is_write_only(1))
+ return [(a,b) for a in t1 for b in t2]
+ elif len(types) == 3:
+ t1 = gen_list_for_type(types[0], api.is_write_only(0))
+ t2 = gen_list_for_type(types[1], api.is_write_only(1))
+ t3 = gen_list_for_type(types[2], api.is_write_only(2))
+ return [(a,b,c) for a in t1 for b in t2 for c in t3]
+ elif len(types) == 4:
+ t1 = gen_list_for_type(types[0], api.is_write_only(0))
+ t2 = gen_list_for_type(types[1], api.is_write_only(1))
+ t3 = gen_list_for_type(types[2], api.is_write_only(2))
+ t4 = gen_list_for_type(types[3], api.is_write_only(3))
+ return [(a,b,c,d) for a in t1 for b in t2 for c in t3 for d in t4]
+ else:
+ raise RuntimeError("Too many args: {}".format(len(types)))
+
+###################################################################
+#
+# Fixup and massage random data for better test coverage
+#
+###################################################################
+def mul_mpzs(a, b):
+ return str(int(a) * int(b))
+
+def mpz_divexact_data(args):
+ # set n = n * d
+ divisible = mul_mpzs(args[1],(args[2]))
+ return [(args[0], divisible, args[2])]
+
+def mpz_divisible_p_data(args):
+ (n,d) = get_div_data(args[0], args[1],rate=1.0)
+ return [(n,d), (args[0], args[1])]
+
+def mpz_div3_data(args):
+ q = args[0]
+ (n,d) = get_div_data(args[1], args[2],rate=1.0)
+ return [(q,n,d), (q,args[1], args[2])]
+
+def mpz_pow_data(args, alwaysallowbase1=True):
+ base = int(args[1])
+ exp = int(args[2])
+ # allow special numbers
+ if base == 0 or exp == 0 or exp == 1:
+ return [args]
+ if base == 1 and alwaysallowbase1:
+ return [args]
+
+ # disallow too big numbers
+ if base > 1000 or base < -1000:
+ base = gen_random_mpz(maxdigits=3)
+ if exp > 1000:
+ exp = gen_random_mpz(maxdigits=3, allowneg=False)
+
+ return [(args[0], str(base), str(exp))]
+
+def mpz_mul_2exp_data(args):
+ return mpz_pow_data(args, alwaysallowbase1=False)
+
+def mpz_gcd_data(args):
+ r = args[0]
+ a = args[1]
+ b = args[2]
+ s_ = gen_small_mpzs(1)[0]
+ m_ = gen_medium_mpzs(1)[0]
+ l_ = gen_large_mpzs(1)[0]
+
+ return [ (r, a, b),
+ (r, mul_mpzs(a, b), b),
+ (r, mul_mpzs(a, s_), mul_mpzs(b, s_)),
+ (r, mul_mpzs(a, m_), mul_mpzs(b, m_)),
+ (r, mul_mpzs(a, l_), mul_mpzs(b, l_)),]
+
+def mpz_export_data(api):
+ rop = ["0"]
+ countp = ["0"]
+ order = ["-1","1"]
+ size = ["1","2","4","8"]
+ endian = ["0"]
+ nails = ["0"]
+ ops = gen_mpz_args(1000) + gen_mpzs(count=100,mindigits=100,maxdigits=1000)
+
+ args = []
+ for r in rop:
+ for c in countp:
+ for o in order:
+ for s in size:
+ for e in endian:
+ for n in nails:
+ for op in ops:
+ args.append((r,c,o,s,e,n,op))
+ return args
+
+def mpz_sizeinbase_data(api):
+ bases = list(map(str, range(2, 37)))
+ ops = gen_mpz_args(1000) + gen_mpzs(count=1000,mindigits=100,maxdigits=2000)
+ return [(op, b) for op in ops for b in bases]
+
+def get_str_data(ty):
+ bases = list(range(2,37)) + list(range(-2, -37, -1))
+ bases = list(map(str, bases))
+ if ty == gmpapi.mpz_t:
+ ops = gen_mpz_args(1000)
+ elif ty == gmpapi.mpq_t:
+ ops = gen_mpq_args(20)
+ else:
+ raise RuntimeError("Unsupported get_str type: "+str(ty))
+ return [("NULL", b, op) for b in bases for op in ops]
+
+def mpz_get_str_data(api):
+ return get_str_data(gmpapi.mpz_t)
+
+def mpq_get_str_data(api):
+ return get_str_data(gmpapi.mpq_t)
+
+def mpq_set_str_data(api):
+ args = gen_mpq_args(20) + gen_mpz_args()
+ # zero does not match results exactly because the
+ # results are not canonicalized first. We choose to
+ # exclude zero from test results. The other option is
+ # to canonicalize the results after parsing the strings.
+ # Instead we exclude zero so that we can independently
+ # test correctness of set_str and canonicalization
+ nonzero = []
+ for arg in args:
+ if "/" in arg:
+ pos = arg.find("/")
+ if int(arg[:pos]) != 0:
+ nonzero.append(arg)
+ elif int(arg) != 0:
+ nonzero.append(arg)
+
+ return [("0", q, "10") for q in nonzero]
+
+def get_div_data(n, d, rate=0.2):
+ """Generate some inputs that are perfectly divisible"""
+ if random.random() < rate:
+ n = mul_mpzs(n, d)
+ return (n,d)
+
+def allow(name, args):
+ if name not in blacklists:
+ return True
+ filters = blacklists[name]
+ for (pos, disallow) in filters:
+ if args[pos] in disallow:
+ return False
+ return True
+
+def fixup_args(name, args):
+ if name not in fixups:
+ return [args]
+ return fixups[name](args)
+
+
+# list of values to be excluded for various api calls
+# list format is (pos, [list of values to exclude])
+blacklists = {
+ "mpz_cdiv_q" : [(2, ["0", "-0"])],
+ "mpz_fdiv_q" : [(2, ["0", "-0"])],
+ "mpz_fdiv_r" : [(2, ["0", "-0"])],
+ "mpz_tdiv_q" : [(2, ["0", "-0"])],
+ "mpz_fdiv_q_ui" : [(2, ["0", "-0"])],
+ "mpz_divexact" : [(2, ["0", "-0"])],
+ "mpz_divisible_p" : [(1, ["0", "-0"])],
+ "mpz_divexact_ui" : [(2, ["0", "-0"])],
+ "mpq_set_ui" : [(2, ["0", "-0"])],
+}
+
+fixups = {
+ "mpz_divexact" : mpz_divexact_data,
+ "mpz_divisible_p" : mpz_divisible_p_data,
+ "mpz_cdiv_q" : mpz_div3_data,
+ "mpz_fdiv_q" : mpz_div3_data,
+ "mpz_fdiv_r" : mpz_div3_data,
+ "mpz_tdiv_q" : mpz_div3_data,
+ "mpz_fdiv_q_ui" : mpz_div3_data,
+ "mpz_divexact_ui" : mpz_divexact_data,
+ "mpz_pow_ui" : mpz_pow_data,
+ "mpz_gcd" : mpz_gcd_data,
+ "mpz_lcm" : mpz_gcd_data,
+ "mpz_mul_2exp" : mpz_mul_2exp_data,
+}
+
+custom = {
+ "mpz_export" : mpz_export_data,
+ "mpz_import" : mpz_export_data,
+ "mpz_sizeinbase" : mpz_sizeinbase_data,
+ "mpz_get_str" : mpz_get_str_data,
+ "mpq_set_str" : mpq_set_str_data,
+ "mpq_get_str" : mpq_get_str_data,
+}
+
+if __name__ == "__main__":
+ #apis = [gmpapi.get_api("mpq_set_str"),]
+ apis = gmpapi.apis
+ for api in apis:
+ tests = gen_args(api)
+ for args in tests:
+ expanded_args = fixup_args(api.name, args)
+ for args in expanded_args:
+ if allow(api.name, args):
+ print("{}|{}".format(api.name, ",".join(args)))
+
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/genpytest.py b/polly/lib/External/isl/imath/tests/gmp-compat-test/genpytest.py
new file mode 100755
index 00000000000..16363980c1e
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/genpytest.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python3
+
+import gmpapi
+import sys
+
+def print_header(outf):
+ outf.write("""
+#AUTOGENERATED FILE
+import ctypes
+import os
+import sys
+import binascii
+
+verbose = False
+fork = False
+ """)
+
+def print_cmp(outf):
+ outf.write("""
+def passt(line, name, a_s, b_s):
+ if verbose:
+ print("PASS: {}@{} {} == {}".format(line, name, a_s, b_s))
+ return True
+
+def fail(line, name, a_s, b_s):
+ print("FAIL: {}@{} {} != {}".format(line, name, a_s,b_s))
+ return False
+
+def cstr_eq(line, name, a, b):
+ a_s = a.value.decode("utf-8")
+ b_s = b.value.decode("utf-8")
+
+ if a_s == b_s:
+ return passt(line, name, a_s, b_s)
+ else:
+ return fail(line, name, a_s, b_s)
+
+def bytes_eq(line, name, a, b):
+ if a == b:
+ return passt(line, name, a, b)
+ else:
+ return fail(line, name, a, b)
+
+def run_test(test, line, name, gmp_test_so, imath_test_so, *args):
+ if fork:
+ childpid = os.fork()
+ else:
+ childpid = 0
+ if childpid == 0:
+ eq = test(line, name, gmp_test_so, imath_test_so, *args)
+ if fork:
+ sys.exit(eq != True)
+ else:
+ return eq
+ else:
+ (pid, status) = os.waitpid(childpid, 0)
+ return status == 0
+
+# custom tests
+def test_mpz_export(line, name, gmp_test_so, imath_test_so, *args):
+ # do not use first two args from the test. need to create our own pointers
+ used_args = args[2:]
+ gbuf = ctypes.create_string_buffer(b'0xdeadbeef'*1024);
+ gsize = ctypes.c_size_t()
+ gout = ctypes.c_void_p()
+ ibuf = ctypes.create_string_buffer(b'0xdeadbeef'*1024);
+ isize = ctypes.c_size_t()
+ iout = ctypes.c_void_p()
+ word_size = args[3].value
+
+ #Test with a NULL pointer
+ gmp_test_so.test_mpz_export(ctypes.byref(gout), None, ctypes.byref(gsize), *used_args)
+ imath_test_so.test_mpz_export(ctypes.byref(iout), None, ctypes.byref(isize), *used_args)
+ gb = ctypes.string_at(gout.value, gsize.value * word_size)
+ ib = ctypes.string_at(iout.value, isize.value * word_size)
+ if not bytes_eq(line, name, gb, ib):
+ return False
+
+ #Test with a provided buffer
+ gmp_test_so.test_mpz_export(ctypes.byref(gout), gbuf, ctypes.byref(gsize), *used_args)
+ imath_test_so.test_mpz_export(ctypes.byref(iout), ibuf, ctypes.byref(isize), *used_args)
+ #print("G:gbuf", gbuf.raw[:gsize.value * word_size])
+ #print("I:ibuf", ibuf.raw[:isize.value * word_size])
+ gb = ctypes.string_at(gout.value, gsize.value * word_size)
+ ib = ctypes.string_at(iout.value, isize.value * word_size)
+ if not bytes_eq(line, name, gb, ib):
+ return False
+
+ return True
+
+def test_mpz_import(line, name, gmp_test_so, imath_test_so, *args):
+ # do not use first two args from the test. need to create our own pointers
+ gout = ctypes.create_string_buffer(b'0xdeadbeef'*1024);
+ iout = ctypes.create_string_buffer(b'0xdeadbeef'*1024);
+
+ gmp_test_so.test_mpz_import(gout, *args)
+ imath_test_so.test_mpz_import(iout, *args)
+ #print(gout.raw[:70])
+ #print(iout.raw[:70])
+ return cstr_eq(line, name, gout, iout)
+
+""")
+
+def print_api(name, outf):
+ outf.write("""
+def test_{0}(line, name, gmp_test_so, imath_test_so, *args):
+ gout = ctypes.create_string_buffer(1024*4);
+ iout = ctypes.create_string_buffer(1024*4);
+ gmp_test_so.test_{0}(gout, *args)
+ imath_test_so.test_{0}(iout, *args)
+ eq = cstr_eq(line, name, gout, iout)
+ return eq
+""".format(name))
+
+def print_api_map(outf):
+ outf.write("""
+def get_wrapper(name):
+ test_wrappers = {
+""")
+ for api in gmpapi.apis:
+ outf.write(' "{}" : {},\n'.format(api.name, "test_"+api.name))
+ outf.write(" }\n")
+ outf.write(" return test_wrappers[name]\n")
+
+
+if __name__ == "__main__":
+ outf = sys.stdout
+ print_header(outf)
+ print_cmp(outf)
+ for api in gmpapi.apis:
+ if not api.custom_test:
+ print_api(api.name, outf)
+ print_api_map(outf)
+
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/gmp_custom_test.c b/polly/lib/External/isl/imath/tests/gmp-compat-test/gmp_custom_test.c
new file mode 100644
index 00000000000..1a0739bdfd8
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/gmp_custom_test.c
@@ -0,0 +1,24 @@
+
+void test_mpz_export(char **out, char *rop, size_t *countp, int order, size_t size, int endian, size_t nails, char* mpzstr) {
+ mpz_t op;
+ mpz_init(op);
+ mpz_set_str(op, mpzstr, 10);
+ //printf("%p,%p,%d,%zi,%d,%zi,%s\n", rop, countp, order, size, endian, nails, mpzstr);
+ *out = mpz_export(rop, countp, order, size, endian, nails, op);
+}
+
+void test_mpz_import(char *out, void *unused, size_t count, int order, size_t size, int endian, size_t nails, char* mpzstr) {
+ mpz_t op;
+ mpz_t rop;
+ mpz_init(op);
+ mpz_init(rop);
+ mpz_set_str(op, mpzstr, 10);
+ char *data;
+
+ //printf("%p,%p,%d,%zi,%d,%zi,%s\n", rop, countp, order, size, endian, nails, mpzstr);
+ data = mpz_export(NULL, &count, order, size, endian, nails, op);
+ mpz_import(rop, count, order, size, endian, nails, data);
+ int eq = mpz_cmpabs(op, rop);
+ sprintf(out, "%2d:", eq);
+ mpz_get_str(out+3, 10, rop);
+}
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/gmpapi.py b/polly/lib/External/isl/imath/tests/gmp-compat-test/gmpapi.py
new file mode 100644
index 00000000000..27f94fcced9
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/gmpapi.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+
+import sys
+
+class CType:
+ def __init__(self, name):
+ self.name = name
+
+ def __str__(self):
+ return self.name
+
+class GMPAPI:
+ def __init__(self, ret_ty, name, *params, out=[0], inout=[], mixed=False,custom=False):
+ self.name = name
+ self.ret_ty = ret_ty
+ self.params = params
+ self.inout_params = inout
+ self.custom_test = custom
+ # most functions with return results dont need extra out params
+ # set mixed to true to check both the return value and an out param
+ if self.ret_ty != void and not mixed:
+ self.out_params = []
+ else:
+ self.out_params = out #param location of the output result
+
+ def is_write_only(self, pos):
+ if pos in self.out_params and pos not in self.inout_params:
+ return True
+ return False
+
+ def __str__(self):
+ return("{} {}({})".format(self.ret_ty, self.name, ",".join(map(str,self.params))))
+
+ def __repr__(self):
+ return str(self)
+
+void = CType("void")
+voidp = CType("void *")
+charp = CType("char *")
+iint = CType("int")
+size_t= CType("size_t")
+size_tp= CType("size_t*")
+ilong = CType("long")
+ulong = CType("unsigned long")
+mpz_t = CType("mpz_t")
+mpq_t = CType("mpq_t")
+
+apis = [
+ GMPAPI(void, "mpz_abs", mpz_t, mpz_t),
+ GMPAPI(void, "mpz_add", mpz_t, mpz_t, mpz_t),
+ GMPAPI(iint, "mpz_cmp_si", mpz_t, ilong),
+ GMPAPI(iint, "mpz_cmpabs", mpz_t, mpz_t),
+ GMPAPI(iint, "mpz_cmp", mpz_t, mpz_t),
+ GMPAPI(void, "mpz_mul", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_neg", mpz_t, mpz_t),
+ GMPAPI(void, "mpz_set_si", mpz_t, ilong),
+ GMPAPI(void, "mpz_set", mpz_t, mpz_t),
+ GMPAPI(void, "mpz_sub", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_swap", mpz_t, mpz_t, out=[0,1], inout=[0,1]),
+ GMPAPI(iint, "mpz_sgn", mpz_t),
+ GMPAPI(void, "mpz_addmul", mpz_t, mpz_t, mpz_t, inout=[0]),
+ GMPAPI(void, "mpz_divexact", mpz_t, mpz_t, mpz_t),
+ GMPAPI(iint, "mpz_divisible_p", mpz_t, mpz_t),
+ GMPAPI(void, "mpz_submul", mpz_t, mpz_t, mpz_t, inout=[0]),
+ GMPAPI(void, "mpz_set_ui", mpz_t, ulong),
+ GMPAPI(void, "mpz_add_ui", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_divexact_ui", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_mul_ui", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_pow_ui", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_sub_ui", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_cdiv_q", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_fdiv_q", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_fdiv_r", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_tdiv_q", mpz_t, mpz_t, mpz_t),
+ GMPAPI(ulong, "mpz_fdiv_q_ui", mpz_t, mpz_t, ulong, out=[0], mixed=True),
+ GMPAPI(ilong, "mpz_get_si", mpz_t),
+ GMPAPI(ulong, "mpz_get_ui", mpz_t),
+ GMPAPI(void, "mpz_gcd", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_lcm", mpz_t, mpz_t, mpz_t),
+ GMPAPI(void, "mpz_mul_2exp", mpz_t, mpz_t, ulong),
+ GMPAPI(void, "mpz_export", voidp, size_tp, iint, size_t, iint, size_t, mpz_t, custom=True),
+ # The mpz_import signature is a bit of a lie, but it is ok because it is custom
+ GMPAPI(void, "mpz_import", voidp, size_t, iint, size_t, iint, size_t, mpz_t, custom=True),
+ GMPAPI(size_t,"mpz_sizeinbase", mpz_t, iint),
+ GMPAPI(charp, "mpz_get_str", charp, iint, mpz_t),
+
+ # mpq functions
+ GMPAPI(iint, "mpq_set_str", mpq_t, charp, iint, out=[0], mixed=True),
+ GMPAPI(void, "mpq_canonicalize", mpq_t, inout=[0]),
+ GMPAPI(iint, "mpq_cmp", mpq_t, mpq_t),
+ GMPAPI(void, "mpq_mul", mpq_t, mpq_t, mpq_t),
+ GMPAPI(void, "mpq_set", mpq_t, mpq_t),
+ GMPAPI(void, "mpq_set_ui", mpq_t, ulong, ulong),
+ GMPAPI(iint, "mpq_sgn", mpq_t),
+ GMPAPI(charp,"mpq_get_str", charp, iint, mpq_t),
+ ]
+
+def get_api(name):
+ for a in apis:
+ if a.name == name:
+ return a
+ raise RuntimeError("Unknown api: {}".format(name))
+
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/imath_custom_test.c b/polly/lib/External/isl/imath/tests/gmp-compat-test/imath_custom_test.c
new file mode 100644
index 00000000000..8772ae8c6a2
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/imath_custom_test.c
@@ -0,0 +1,24 @@
+
+void test_mpz_export(char **out, char *rop, size_t *countp, int order, size_t size, int endian, size_t nails, char* mpzstr) {
+ impz_t op;
+ impz_init(op);
+ impz_set_str(op, mpzstr, 10);
+ //printf("%p,%p,%d,%zi,%d,%zi,%s\n", rop, countp, order, size, endian, nails, mpzstr);
+ *out = impz_export(rop, countp, order, size, endian, nails, op);
+}
+
+void test_mpz_import(char *out, void *unused, size_t count, int order, size_t size, int endian, size_t nails, char* mpzstr) {
+ impz_t op;
+ impz_t rop;
+ impz_init(op);
+ impz_init(rop);
+ impz_set_str(op, mpzstr, 10);
+ char *data;
+
+ //printf("%p,%p,%d,%zi,%d,%zi,%s\n", rop, countp, order, size, endian, nails, mpzstr);
+ data = impz_export(NULL, &count, order, size, endian, nails, op);
+ impz_import(rop, count, order, size, endian, nails, data);
+ int eq = impz_cmpabs(op, rop);
+ sprintf(out, "%2d:", eq);
+ impz_get_str(out+3, 10, rop);
+}
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest b/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest
new file mode 100755
index 00000000000..4a9f5854a5a
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest
@@ -0,0 +1,3 @@
+#!/bin/bash
+export LD_LIBRARY_PATH=.:../..
+python3 runtest.py $@
diff --git a/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest.py b/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest.py
new file mode 100755
index 00000000000..2c1a35f0f2e
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/gmp-compat-test/runtest.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python3
+
+import ctypes
+import random
+import gmpapi
+import wrappers
+import glob
+import sys
+import os
+from optparse import OptionParser
+from gmpapi import void
+from gmpapi import ilong
+from gmpapi import ulong
+from gmpapi import mpz_t
+from gmpapi import voidp
+from gmpapi import size_t
+from gmpapi import size_tp
+from gmpapi import iint
+from gmpapi import charp
+from gmpapi import mpq_t
+
+def print_failure(line, test):
+ print("FAIL: {}@{}".format(line,test))
+
+
+def run_tests(test_file, options):
+ passes = 0
+ failures = 0
+ fail_lines = []
+ for (line, test) in enumerate(open(test_file), start=1):
+ if test.startswith("#"):
+ continue
+ if options.skip > 0 and line < options.skip:
+ continue
+ name,args = test.split("|")
+ if options.verbose or (options.progress > 0 and line % options.progress == 0):
+ print("TEST: {}@{}".format(line, test), end="")
+ api = gmpapi.get_api(name)
+ wrapper = wrappers.get_wrapper(name)
+ input_args = args.split(",")
+ if len(api.params) != len(input_args):
+ raise RuntimeError("Mismatch in args length: {} != {}".format(len(api.params), len(input_args)))
+
+ call_args = []
+ for i in range(len(api.params)):
+ param = api.params[i]
+ if param == mpz_t:
+ call_args.append(bytes(input_args[i],"utf-8"))
+ elif param == mpq_t:
+ call_args.append(bytes(input_args[i],"utf-8"))
+ elif param == ulong:
+ call_args.append(ctypes.c_ulong(int(input_args[i])))
+ elif param == ilong:
+ call_args.append(ctypes.c_long(int(input_args[i])))
+ elif param == voidp or param == size_tp:
+ call_args.append(ctypes.c_void_p(None))
+ elif param == size_t:
+ call_args.append(ctypes.c_size_t(int(input_args[i])))
+ elif param == iint:
+ call_args.append(ctypes.c_int(int(input_args[i])))
+ # pass null for charp
+ elif param == charp:
+ if input_args[i] == "NULL":
+ call_args.append(ctypes.c_void_p(None))
+ else:
+ call_args.append(bytes(input_args[i],"utf-8"))
+ else:
+ raise RuntimeError("Unknown param type: {}".format(param))
+
+ res = wrappers.run_test(wrapper, line, name, gmp_test_so, imath_test_so, *call_args)
+ if not res:
+ failures += 1
+ print_failure(line,test)
+ fail_lines.append((line,test))
+ else:
+ passes += 1
+ return (passes,failures, fail_lines)
+
+def parse_args():
+ parser = OptionParser()
+ parser.add_option("-f", "--fork", help="fork() before each operation",
+ action="store_true", default=False)
+ parser.add_option("-v", "--verbose", help="print PASS and FAIL tests",
+ action="store_true", default=False)
+ parser.add_option("-p", "--progress", help="print progress every N tests ",
+ metavar="N", type="int", default=0)
+ parser.add_option("-s", "--skip", help="skip to test N",
+ metavar="N", type="int", default=0)
+ return parser.parse_args()
+
+if __name__ == "__main__":
+ (options, tests) = parse_args()
+ gmp_test_so = ctypes.cdll.LoadLibrary("gmp_test.so")
+ imath_test_so = ctypes.cdll.LoadLibrary("imath_test.so")
+
+ wrappers.verbose = options.verbose
+ wrappers.fork = options.fork
+
+ total_pass = 0
+ total_fail = 0
+ all_fail_lines = []
+ for test_file in tests:
+ print("Running tests in {}".format(test_file))
+ (passes,failures,fail_lines) = run_tests(test_file, options)
+ print(" Tests: {}. Passes: {}. Failures: {}.".format(passes+failures, passes, failures))
+ total_pass += passes
+ total_fail += failures
+ all_fail_lines += fail_lines
+
+ print("="*70)
+ print("Total")
+ print(" Tests: {}. Passes: {}. Failures: {}.".format(total_pass+total_fail, total_pass, total_fail))
+ if len(all_fail_lines) > 0:
+ print("Failing Tests:")
+ for (line, test) in all_fail_lines:
+ print(test.rstrip())
+
diff --git a/polly/lib/External/isl/imath/tests/init.t b/polly/lib/External/isl/imath/tests/init.t
new file mode 100644
index 00000000000..074f5d61f07
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/init.t
@@ -0,0 +1,12 @@
+#Unsigned integer initialization. Assumes sizeof(long) == 8.
+initu:0,0:0
+initu:0,18446744073709551615:18446744073709551615
+initu:0,567:567
+
+#Signed integer initialization Assumes sizeof(long) == 8.
+initv:0,0:0
+initv:0,-1:-1
+initv:0,9223372036854775807:9223372036854775807
+initv:0,-9223372036854775808:-9223372036854775808
+initv:0,4324:4324
+
diff --git a/polly/lib/External/isl/imath/tests/invmod.t b/polly/lib/External/isl/imath/tests/invmod.t
new file mode 100644
index 00000000000..f969b039d2d
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/invmod.t
@@ -0,0 +1,452 @@
+# Modular inverse tests (no undefined cases)
+
+invmod:-25,37,=1:34
+invmod:-25,37,=2:34
+invmod:-5,11,0:2
+invmod:22153,514,0:383
+invmod:6521,442674856,0:28104185
+invmod:83,8990271,0:2924546
+invmod:643111,73,0:23
+invmod:6756751,5,0:1
+invmod:4310757,655173482,0:578093623
+invmod:67658,37989,0:29720
+invmod:140,456739,0:394753
+invmod:8363,2152,0:1827
+invmod:6067,5554,0:1061
+invmod:134706247,840181,0:713245
+invmod:581,8525,0:3096
+invmod:991357,2885,0:2243
+invmod:9820551,53210,0:5931
+invmod:366,3905684875,0:1846129736
+invmod:4582993,6971170,0:6590887
+invmod:4261,5,0:1
+invmod:2089582769,72370,0:34059
+invmod:1385486874,274843,0:100773
+invmod:2496082853,33877892272,0:25370727693
+invmod:29,77842490059,0:18789566566
+invmod:160735723,837433,0:536522
+invmod:33,92874448,0:39401281
+invmod:17,801910,0:518883
+invmod:1243,47177637,0:28769629
+invmod:5553626,17225545633,0:4551550593
+invmod:493375452,7744903,=1:5021402
+invmod:505,75126821802,0:15917960263
+invmod:8082104357,6160949,0:64657
+invmod:4793,63911,0:44243
+invmod:846,4453189,0:689560
+invmod:5475,596527544653,0:311392826049
+invmod:239,28531,0:9192
+invmod:71044,91829,0:4016
+invmod:2923052473,673,0:362
+invmod:40113371,396,0:23
+invmod:799762079,671587,0:280457
+invmod:6137106,72083,0:61684
+invmod:2663959394312,7297021,0:6396652
+invmod:16314,437519,0:121837
+invmod:5409920801970,224827,0:146917
+invmod:1701531745,565383113204,0:392963934477
+invmod:6702285244447,4818940,0:3886523
+invmod:3853762105973,7986397045899,0:4649165556065
+invmod:83203877,17340640,=2:1474413
+invmod:349,3756,0:1765
+invmod:513237329,6426867498383,0:5161899757325
+invmod:218717486055,4764721,0:3629102
+invmod:5697807566182,23837,0:17052
+invmod:640499,3706953268445,0:862821487954
+invmod:74365895080186,37008968409199,0:35062440514236
+invmod:5447180,17521,0:6484
+invmod:87747,309211711,0:64843296
+invmod:65052052,72604563,0:26029330
+invmod:1200121,9944190318201,=2:5066700447199
+invmod:487321393172,41829673981,=1:18173847806
+invmod:3762709971997,877939264220,=1:575680399733
+invmod:78323027,3830390625030,0:1772587463183
+invmod:1324701179,57116535299,0:4144192403
+invmod:663267333048769,9458708,0:1445501
+invmod:925655,3262585612,0:2494330419
+invmod:809760047,253746243247,0:109619303279
+invmod:6962181619,44237293531835,0:34688460868884
+invmod:32137986591347,450053710,0:207388563
+invmod:171464220392,1821508963,0:85136287
+invmod:4866698,1559814931871,0:875727775988
+invmod:83084876,852948279591,=2:67614759050
+invmod:3087717,3533808897939368,0:3296313572604861
+invmod:685072,47729803,0:7913327
+invmod:3403087579775453,307599045,0:85279967
+invmod:618837304,2026545,0:580654
+invmod:1617142737,5396772102241213,0:309489822606449
+invmod:398279389,695426305815576,0:548019512309869
+invmod:807807859,101277481,0:1799573
+invmod:4399921090,93999639721573,0:23138878622757
+invmod:6198378859,5720311022,0:2650981593
+invmod:86572714,9776668159093959,0:99027417792355
+invmod:1106685402600,781883021,0:593993010
+invmod:788429239716,54846845,0:23729486
+invmod:26682164884969,84892199507532,0:38639429314105
+invmod:490223409,87336215488172224,0:60928799099783953
+invmod:11687153,155174158,0:112979329
+invmod:81995673521,1680666567,0:4778198
+invmod:36278417230108,2563749243683,0:97972077091
+invmod:81100161947491318,626490251,0:10036586
+invmod:84353708437,789691774074278,0:384046667492909
+invmod:4784222527,220196213,0:137693182
+invmod:656338347,17114903662,0:2025727201
+invmod:205944554689,55544669634,0:45790392391
+invmod:58311406949710,684448841,0:398362627
+invmod:2984553893,39836508385650164,0:23063415225053961
+invmod:1226833387651,868339671575144482,0:861301708657625181
+invmod:7850491405,3995878481964,0:222583321669
+invmod:60187945992,93467753554255,0:39782639687763
+invmod:26790048589,54188485741,0:37088225013
+invmod:2047388699,2277281699,0:1326800159
+invmod:437698007378203709,87810457123843238,0:45519261037663357
+invmod:10176318725,798739962893,0:680424092570
+invmod:784178983329613758,151005933385,0:62880260387
+invmod:774192548697746,10018080225753177,0:9683250774295598
+invmod:726085395694283800,277010088622579,0:180332658128036
+invmod:734218324557247853,1620310233702,0:916743102467
+invmod:707389886770553113,418168493503742,0:189385161021501
+invmod:171716270659493,2040489403879802122,0:1953367125622896751
+invmod:78774439204,843419490844271841,0:461564113792074643
+invmod:9092444912687,92042830376149639,0:47447717686388633
+invmod:61162406254,726431645806031683,0:276675014746837850
+invmod:6502138975909229,1737018911640,0:657596399549
+invmod:87574684954665,78519506900538949759,0:47230364038284735522
+invmod:1306210408858148,134301015531,0:130837017359
+invmod:44107140793537552339,77941696100292187182,0:44195935179151712467
+invmod:67019007414976,320349107407,0:230029544613
+invmod:251668932025135,35962140459304117641,0:27454542509813399095
+invmod:1960384563191744911,414832971260173594,0:324345091445220853
+invmod:9693842669955456325,3433846821305106979,0:3209295184025178668
+invmod:95824904457431,207730473678560854,0:115346241869098615
+invmod:8243018284897799671,54774169173707248,0:44653415179102455
+invmod:311780668918,56602194650033,0:19477344474056
+invmod:5901525417230160,6175539028945276481,0:2734302477909765310
+invmod:15817645817088013342,83873087573263156355,0:40986420565770894283
+invmod:2776285597517168189,3599586054083,0:1736805497387
+invmod:5082710450857887,9056726269284017335,0:4011503044106438893
+invmod:8584682476237466436,7357902067222453540607,0:5765479814487665631684
+invmod:2319480092078509424,6781626293282491,0:6716281365540188
+invmod:1240939184380232105,937916010642767528344,0:266041850377015782033
+invmod:658085025934773092927,87790861684417147140,0:36756492918534162863
+invmod:2569452374055474,1282307723894094781,0:817830828946766758
+invmod:888631770342009119641,963322788372149745005,0:58576054803607756901
+invmod:89415261698482,94033558717297,0:55696542331400
+invmod:56380027660316644352588,35652220511128407,0:2604464463341384
+invmod:996226476453670075,45399567279611724302531,0:4432450575006272604766
+invmod:34615237368338359171,8816907924734450,0:7867417936877631
+invmod:57100661310425224095499,80123941311371854,0:35581152205723201
+invmod:4003341194576048121,875086915466219,0:805682679112747
+invmod:6669592405841477476717,4551036259229300,0:1731901161660553
+invmod:4899954396030393,8249234915987429715052,0:8042076059164143158753
+invmod:457015587799729799209,94904436585339172647,0:67495506193470607315
+invmod:2416330080921791,12841205070842866551072,0:9627123487316001173279
+invmod:315334615429521629,57080600687534315852534,0:35876106943989391629797
+invmod:245635836236733543965,350204895578119,0:266548953036562
+invmod:534172301537220853627465,54572957533260480823618,0:28391508956926418431025
+invmod:64835058866700508778320,82305874730776723,0:57154164927574349
+invmod:2935419197344029519,38389371660425629010,0:28166170186967145769
+invmod:3817779121449271,177996364073619,0:33676152326515
+invmod:738146746050725,4141892900866715689963,0:1939330976850898748447
+invmod:92817796396830036287569,23833760274805751,0:18027905863154323
+invmod:324768538678274222,672713761279277469419167,0:179185315765267484078532
+invmod:145806963849046841647,254534976684286765771,0:200530074654889210574
+invmod:5843892547087945,8037935722129342683168,0:4622521916530352817625
+invmod:635350174582720198578,895650784125257583255317,0:608770468357452782491563
+invmod:64902256585483042893,64861417659113483501885,0:48500544464636732858792
+invmod:1348003478873768067340578,79797413707905564041741,0:40891858728897888244861
+invmod:6267734989419158151778,3802309231789144649797859,0:283176065685623872919005
+invmod:3615002399473406,3318504485101385132081323,0:2767667426638532783172948
+invmod:899009032038735494294979,792084588352351084,0:424508678737216543
+invmod:81206746001376489750557,7237607374878187597720,0:1600326671975281670573
+invmod:3627972699304722008437199,5520898889538066465900,0:2272155478759642709699
+invmod:34685989123390710817647,6655359456977349621184,0:2132453240661862741327
+invmod:7144620105437275474852,753995169282415124087,0:275860832898605149106
+invmod:3535338302168469766025701,5721768567217856428,0:1398947754214548293
+invmod:966210500401822916283782,66395891256125996529,0:10363406607924246032
+invmod:5107776515340409,616676046831960893161433,0:328705736461746618977486
+invmod:205573655301723270437,35922475780693975,0:13536061393525448
+invmod:6678162870767249806,72542902715331741208361,0:27163420735919994491369
+invmod:4198363950348197654359,656021938174219663877448,0:30249336864266481152527
+invmod:6624293151166291066603,935090767412780504,0:703056406859110987
+invmod:1425474699733426865447,74057791800633068553,0:32399215003249997555
+invmod:535428418244353401,5758069448318181075415,0:651913765960044782491
+invmod:511900281901325868358066640,7525380451505858160279157,0:4065406882222502194971660
+invmod:212919955640465965,878153960566548562,0:662636940932888511
+invmod:889569596018809758462291211,81473326768558522502336,0:56487291469860004699555
+invmod:443144861277824063183398,3761174124237053075,0:3604887025386113137
+invmod:33394484114211334386,72967632167182065995369,0:31523450321558696309323
+invmod:4146649809313089447250,2358753923413902348191,0:2114494919004119612967
+invmod:9887121613180137575733557,461028287216014552,0:243298503783102749
+invmod:97465366227467312864072367,488220214874854052,0:130500775756515095
+invmod:19292649676011135522471,7877659035660734746,0:283664033368712393
+invmod:88902959369842150471660679,458945796034863505452,0:116241488588017347323
+invmod:1839945988509816044751,9750948399412779544,0:6294451275142512167
+invmod:9857520075588286024975851,1918199730912356922553,0:1407196181358170021243
+invmod:98092461637270194063,69938396621942574346694,0:39897238269802969068339
+invmod:219033411512598606789840689,795134880363756976388,0:639110818118499283141
+invmod:88186459451009468808509156,931160442943017676802173071,0:629562198515766072504373649
+invmod:9710794978083575389221590569,4251433051225510685,0:1014964735988867489
+invmod:8101415155618280845453190902,1531876453912452699591,0:368176555527134025784
+invmod:29409670089331883811,535811823788496989270023400,0:370280198672135017584348691
+invmod:8305842606005328583,9579564753339003236281695,0:5722440512759901640334872
+invmod:39386484402035672640779147,405797130275770630884183427,0:110208599835163794381201071
+invmod:832687365793006297742,184982557537022296058374571,0:83904068232925523197663651
+invmod:6553207532807060406664,502238468947067021963,0:454270228642816251641
+invmod:37454379370943067757286870211,36494426305368965154254726536,0:33638650562651500684923138787
+invmod:38605483438466601679,682239274139689477361679,0:13199577887729473047769
+invmod:7965022961827711681795,2285716672004926097772197,0:2122955484406134178638446
+invmod:300057798344833538558206311,8931778125815914295,0:6565813118197443911
+invmod:324842828083012251597681011,187662727615575337969,0:123961367799983618478
+invmod:59548842983097072068081,529556931168692661765381,0:204382555679859518219042
+invmod:876100791904547219529602,984558128732533432702173965429,0:90974750030008269191789684241
+invmod:412262036467011789370687,7642721479883866583632505,0:2279185286560398311684903
+invmod:35558590466031758855977117,887974042467941992656,0:704625358717245867829
+invmod:626663442467211390440132060640,1374148771090265524803717173,0:590755849649898431023419435
+invmod:85901909124840045452734003634,27175621479815508400005,0:6884774470049680531679
+invmod:4803896245161574921869066442,515522173785247100331641258677,0:82575699585005426552163954975
+invmod:30894573328276878531856,4087591712675305723294627,0:3493627083082495776432430
+invmod:9141841986580679278669126,505635384209785163519211124141,0:336188649744514864135515371530
+invmod:188695176591763873562433787,661611817437909433157465,0:375067540836983193116438
+invmod:241487793644307094737649980023,4603295709537644102260078209,0:1875185676154036094527511246
+invmod:5293130391697702045129223682241,4410288170386013446930,0:3281121803360293450491
+invmod:6033846664871710576440686677569,96946807752243502281276550,0:45266733495357578832984479
+invmod:89038378306924494551626,95628444614978025043615,0:23786747307100516932196
+invmod:12710922165960068258466731689,4790016424576553135438840,0:1207752742860172910912249
+invmod:2735034594918378899070448537355,1893682211859850854604,0:435685035552133636619
+invmod:68329358155371632083140828250982,6288770840498808006152991055,0:5931193047490714028593816373
+invmod:83897752529920362009921,66649056389057335553727631393,0:43268302813732520149524641842
+invmod:9689473529426673026778331,88076063449762644474294178,0:68554034321312192241642365
+invmod:73977485020743016621210217010220,53253046617921140492481,0:34299048109456536013621
+invmod:9682622686213510676332035159913,126726573785394345551110507947,0:87562143297844604196976477132
+invmod:5131707842034728461484683196411,9833933722624780748771816760,0:7636914556132154008767009131
+invmod:622466933719692949758353,8720875070568727490840986966,0:2243063168207109573811220613
+invmod:371914469040335929323957821,29979763825336998478908474,0:19112551112998202208882569
+invmod:460040264854684284500867207882,176619007178719669689957899985,0:84600278607589920579666033533
+invmod:7814781702042412652917732124,44974092645758858215810834392705,0:22525065545650129764783444827969
+invmod:689879593008118336507276219555,7029140833503782253304852,0:1657942681146249790361611
+invmod:588753311584356398728925335104347,655245595214265213328588954,0:5370808165845253986418065
+invmod:215270851453007875328537243236,930847670919175461277424586154331,0:854093280868657781869727944640825
+invmod:554018901896459973640131751591,9763486748180940629420083557,0:4943017226299795649673145282
+invmod:13807862007846696356170492992,218480252372917913755483,0:162381198060244352285330
+invmod:3647663862216963935039311,3498263635673871413147938009,0:815287510808909642460179901
+invmod:1394556521513041955902249647007,8314730285674311054788894925503,0:4701759015019363383377776837184
+invmod:765922458203903632153317653598,772684127072442440623494065,0:681475643232329050740648777
+invmod:1636182686335177476661316231316713,898482806249393672761387906057,0:629953274075151653191843542345
+invmod:584489430664515187742143663,3226379401343487951747550753985,0:2300722785510258273879270270657
+invmod:70597555974027836626331232,9067577360780247310463700060912415,0:1343885645550828326227031879126813
+invmod:83016782422655848478468587,3574392772750510684744014,0:2160375438947262160886701
+invmod:9509632620059688913461744335927,2001546646968510097453590971258811,0:1579171227651658107693890864008934
+invmod:5305698102006965934646514142,1880423512328598313144733245,0:1158802006274691372231434298
+invmod:25818273392182891028387183709,372712587491320607948739787619341,0:83620423512820588265929334666867
+invmod:2062301690726594241599730508623,1295011898282606475280524130169,0:1126618128280194264421190196682
+invmod:15525882195404306532803603053735006,524851347004182298259949574931,0:117558057158627958293103758908
+invmod:98049989631901137366836343057866,2132117143964644775000173275,0:1776678869002856275917157286
+invmod:68035486069315280099382173380,136804376642014663925354513,0:116540031317166597205778667
+invmod:930885787290248986653715917201,839163742792309140697583306,0:467450716792956567729742385
+invmod:618219232165541881120714807027054,551811312165885959528421318411,0:241084816664595048546274133494
+invmod:607491972766521656095997601,4258761064370347279045518650,0:4106442789435765086100078351
+invmod:1794059822501926214368058365897,641293693468680328700219247,0:412236704145068075117115904
+invmod:66038046351270827218975238,828243810057190999751749430463827,0:201240403207654658512757471515946
+invmod:22489979027542119833361766314814004,4267735327278945325377118240414149,0:831989298493288398125903826182123
+invmod:96656949043354906812270332568634084,17593722554451983298697234832943,0:10389378262088955098639501532940
+invmod:1475127063531246543305342130787,5712802933759973674949655288556,0:911126023377734859289288839875
+invmod:94805314820797148511000189717800001,64899576259694613046461539176,0:48109809959614533507389959049
+invmod:5787223135405198552481837574149,5421074820227552626308319526063,0:1887880601492799950765024255248
+invmod:28973562312482088535256834009,12322004931428309561996283040268471,0:6951695655429544292118574942872356
+invmod:3696872012110541582072428310551341,1523878544437625304694982047192609153,0:120514356890624212938061146933103186
+invmod:7388600304197232842534029909,773289223233970187052705366304,0:734898540650399983999883872093
+invmod:7331236475650961531766667058913110203,693192479825024022606662504949920,0:571670151801413885792817856265587
+invmod:5235989645992380877547648143027,9843490764540995482808427936563,0:7792497103048946162851333200848
+invmod:7889040487772265051508734223198,970333028842680057477545240961989231,0:820851624929176605383247534276742509
+invmod:636939509978082435344561123977,8632390068721323171174332473333535190,0:993190319417433889538526784654541983
+invmod:91838639727927578174237486907982,9330677294050455577402341248771486991,0:3372468877355534050061501496367400668
+invmod:10921336389827150720097811900009211076,7589092431150460928351199116667067691,0:866721211802572827148277173383125007
+invmod:658155257851240068821873115015976,558927662049398106193187373360428065,0:209745203635098313869122201832200296
+invmod:5585592751467684477444331029739,27200783107220910874350734817147653,0:1132197483918030242577531292806291
+invmod:7637148852097915353546826493,42198395510943407752409176135,0:38579422829892871530093056797
+invmod:228011811609919943842937730868521189,269359008901950141311260148678129,0:204220292063517008126064637465387
+invmod:85379073141618507288535187863547,3311778009260578617664169854013,0:1251094538034868342736717399878
+invmod:178538609345684608529279115948180,3209187922934820372906185622931,0:625228980755918910363724543435
+invmod:514451212940578583651534706134690,261960849561824473447008674451593,0:131626741363323972030200440147547
+invmod:9634204149807611579602377719343249239,91352833806659059550235201423093,0:43744490808833751862541187085697
+invmod:180205999846263895162745909652272689,61037131972980180275583850831,0:22758511829661545789258800814
+invmod:21945771136787811201569306864610194,240543080450829974515246807891357405,0:181461539213602660625514174427621814
+invmod:35517481628882114783536774508289,73933641713139782399722231157687221982,0:55192567983407494884175622090344427645
+invmod:61133421177402004520562281574369023,490575463215034765455424331786,0:428078344043933589235114932577
+invmod:61997134551496924667492900578768215075,53694317203253417994456413131837794901,0:5127049382196704081839504435078188237
+invmod:149407595591992713390607359968523153,9733723254627254068241609649090688,0:7103143213776435125430106007909873
+invmod:724677347918056918707332818251,4206398531197287079326882898987,0:3352013813776874655296817354068
+invmod:904144691211996824768615430166153,57579709060839020187927414941125095,0:54557924391254568447415464374061082
+invmod:464828030341876048255162748051,16315883710383791874911854058033061,0:1898204461581732360730698325426064
+invmod:19170845621606248311569905259730887097,911211106537315652144761781751982143011,0:11609063390937807744161998275631424941
+invmod:857469002074663726099005122270054136,767466745792444095098639793741965637031,0:72659426270163915638661477107149562702
+invmod:130093804885990385658501097171753042,91493100398010395343582415770659586075,0:71562287103402903271519248491284598728
+invmod:3558394519963770405007494484958693,5649100976897692393477567234571091,0:1778327570753831461149235315785758
+invmod:827172132916351233103886705694689183,7406200609002751101596817359849513044605,0:182683152383530805186420471977735101947
+invmod:44588398105132907935221361042363023,849039192087829478839986564159076706,0:756327512592089069079417038566139671
+invmod:87482753881086943893477139352309,15136288595019926379451404752790558,0:7380826408731655136881662259683287
+invmod:2816393010081341842764909636597751163357,666424385901140622144416941996627540,0:37970402623680773312812150346972833
+invmod:44160925420830144883476086426186778817,3964315773874336539018935736605912590999,0:3339494318496833279004795765823107883695
+invmod:7784294051005222901032501449689049491,82221954950326057541175302867376355231,0:35060237646445852249886804139112143661
+invmod:8782186458787754387943640751003,287196330910083697223737780139934653,0:151169934658998501405294488263167850
+invmod:52961061996773303218378119209138937,4138078150303278572595508400662,0:2334686283357105837861457163873
+invmod:120067972673320339436684163684521541899,5003127736361658398228918751147,0:2804153651535384761721045391262
+invmod:21160862616768687388014009097902145,984271481536213754460622644543049509,0:110991439312803462463226099820276772
+invmod:94870103291793687661854548564670156557,4654396151789059038730576061157487355,0:4545904732262329435720397277692160608
+invmod:126765551422438407604981735815319,4526482948583699374467868274935682,0:1340347586087681863052878791652111
+invmod:561052644739230772711625537622190085922,182709904797036712378783653059935117,0:81730760740395808028866350847708745
+invmod:8440958912355253192980982965295847,99976107874430648288932536807344574289,0:44322197083360812344238924546434599316
+invmod:622818497925638835644269035686568759453,5506232467142585446362605183461,0:5370963830087767870403236824410
+invmod:57453345384809312296011379661001742955,386140250699346346360045382167776159,0:63476384227956307102053350966611778
+invmod:83416537340827284838496955161681676081,12832473375703257825108506495959421,0:499463210654774129441986832321381
+invmod:6764203692091211849546587544996797291,56141668772394375440300081823159,0:33236198277199128613406762379601
+invmod:40370041535056934456885738109160412,509721817241840184167083180099626991,0:11491022410510426082577074611522170
+invmod:878180470796147113848439165151873,17763546710042203623413235393081,0:14204683605998536689672179103545
+invmod:55590867394053732499429322189218399778872,43372981951757571058338676426693,0:33510348378637076952275179882521
+invmod:7546327535456972783460913206047380047,86726167905648033666208453441434584,0:5322052162117479044160819033125903
+invmod:329955968415706177763208593030907,50516382401253954262072882036248004026668,0:34401169217941393127943862147280363000747
+invmod:87048112982262598454925291684403335,805959667741585911092793285492264429037,0:379430630180430216461244147576608482936
+invmod:71555142355447318269121083903394685,87398662401733013244354964840378552,0:67043514123128780636096809791233709
+invmod:1711583735940653927946109180989149,26241424080043582566688947607871596,0:23154984666365483606784578156029249
+invmod:542489709314546955942774519697358722621,143873444084042887511916303711981530841,0:121457408531791726256743734440607914263
+invmod:3781041336068211601179549569884186970409919,327900172706652019993358885788160915208,0:285215395500809506516326193309579388695
+invmod:6149927428146656336227133345815170519,7588487705630577686965956743882876270164,0:4653797610323419583601822953872210529815
+invmod:559049983877521594210938163489019460719,951902276119605669127355840612003004,0:683326157826438593722386803692042151
+invmod:9570949170433291990391807356653340234145159,8534474723057896563545270622977282626469,0:7559467634929916340724978098594978746637
+invmod:987849800664220039883494398655886160465,6831497903141449539539967513122604383199548,0:246607561273243347599128464506339845374005
+invmod:916515834175745144405438914198070103556585,4056859814803168890581397499472591207566757,0:1770209812768098816334392652319997964773464
+invmod:1228631771902154967504229180729583591093,695152447128287511961827228275915906161196,0:68820532783317596490391949047646875295925
+invmod:85204895476713840095779420329627903803,797154697565857850707103989977884356052456,0:189834737137977542797303467784002206530403
+invmod:459421385046429900048441785147457350775932,7698087947447355511478579587800901996173,0:1050954140018038340522121385945573583123
+invmod:8211730416251817740382555577378910158254614,52604175850251752026919899874340035,0:40445721575495397750278068202293844
+invmod:13222111757762648331396301846656536813259327,266888325807002880450404100257370089541565,0:109298344157958287037388161546711172781058
+invmod:563240385133071678994472898571956920719,3993868915925455184846327870408751385272,0:2785525939806848082603069961895833469023
+invmod:521639521589957338674682854605577427535430,91720686816082732671407774270039351,0:17647263388578210512345389034742837
+invmod:5156816003277235939668801939908183725744,5153042308730983383934473837808025008231,0:1734593135670097399582886018375080924055
+invmod:9790574355124996717257076778746595337,7094481197220145398883635593951185851053,0:4633443452058944189941546476417089729612
+invmod:3738689158705918826996178299424238668515201,6395182435555998218010243005378643333837,0:4032119940417970860053188513124120286092
+invmod:13614043167840054636971961619348110233,9922954903164743574284496007816459280672855,0:6390894157193464477433210223562314675849502
+invmod:7722989551905267507172665225415434299,285028691296471922732299049703480528,0:80127272552190846362411085374898803
+invmod:34955948774875418184052263202780817611505383,25511643971935598979339727281441119179,0:24793574418979515087827479198686647984
+invmod:9752514502992806699558935311322486653812,3763087306264536914043797765340033186467793,0:1025569723180811973169033467813546203362574
+invmod:27465132713599700004772511614559440798,13274810225615043094606232580958497359,0:10132125917976802477194900566349825181
+invmod:875919373810765425715940434040195178,5349809266782277700868243297033816292139395,0:2651731185643620478354040628390151701549142
+invmod:6881906840916466478584802007995526309234459,756717805668582535693388931894211346359,0:145296958725486236992417439558326443417
+invmod:334311791774893954611025022303233183505395489,584529866497361400618684187440397242,0:292400244436936079523712480681940227
+invmod:65712090641887119990742721342873930,4336182528635667934371588198046750892623,0:558253505423903869478690367363302598682
+invmod:4492701702646633574790657588147591497,887008290240310205861702963649926144764,0:434334236746323412542488940776733666249
+invmod:411586476025579573736047981166427386223,60898553483467476285120690698220614489936966,0:19455038575262424591552585688228685688467833
+invmod:6367597108696643245107048337012153376861093,65889932274525424609098394737176730568661,0:65870071424966086215554796795651660966036
+invmod:1049560658786859350707338961047775237,5274992996959254283334337773536473890159,0:624593399529926255525711013688044195635
+invmod:107527378432083555117117943876656903468876,716429394528758636372948757175038602405647,0:444454875067125022527116753199711164880725
+invmod:555145963886409519368431903982210135919242,8268229830304970030006026946953367235680701,0:6387083941953876784249641453937804161251014
+invmod:77948002708019596204938559286354567269,455121612933774657179682813659815211,0:364811843921650022521340876006123246
+invmod:498360659435361921366498611099013149316057,5728485554979561072455795106370849106458,0:3102501845651843687065534092900673818593
+invmod:726843237990292819218621975265928124471239641,2887158075124871990135103381732069919679,0:1068470994113776781214157184472987715710
+invmod:14490257580500837566390302262779531170047157,32393480535449409499704778950027988096,0:30287826764106717477700071788946051485
+invmod:6270142013450141253944931199020500202121765035,3763601356640037994669890437848434673885751057,0:3156243150557294814061853765553333562512998545
+invmod:809245912199158373741272239723610868982823,8030588855423774308237502000480454393456840856,0:904571791041508997839920338301126020187933047
+invmod:19533970453895817522762076874428022848,66299209695045887406306821511839592998483515,0:13599402726209549954335916901935358290831417
+invmod:23199633133008878062415683980086247896344005,61479113901097914563017676528126502674819176957,0:50989713359156907028812686282866020892767441337
+invmod:2862728440518115487475964440740584330473078140,51210656799701051518059629917289349291243014631,0:17918271858261676405666583245056315801120815006
+invmod:14971096876073425168884018562366418693791183,9559636375986473567719335761058531628207,0:5109731903973538125843601711325876342232
+invmod:532670798205641227016874816346924933526518,8612651409966775146216925722782469875353075,0:3211535369857991680135616378366713231520582
+invmod:5277579668620044053588021313993390529699415,7623352070936849233565453286144593741688259,0:2195179503632503483804554417001536677298355
+invmod:1703242284411257170432455927132332917751,91946197833078813303494400074098343464254335961,0:78127206681265732452981591549234092643891370502
+invmod:661687018626315126767845163322826263674289,28536010760826245705236059697847500278395679313,0:9982270980885276298051810649502841807467187592
+invmod:71856999282924192732858943855372784788,27823718424741468425870327772094802246951559365,0:18935276857302206232390405420351565823103424567
+invmod:4662964353558658735645456824027896151772,33878933564208336888348089073090367622314169867,0:10548442440909583945565305765948929087304389925
+invmod:62009389758664279395604249729164619334196,538359108562320297007051503463417099077320173,0:398148791843022164991556905409865960939044422
+invmod:6183332385813041506672156000574955880665,871559003971682075020587679481749233390914546267,0:361446020046797748452828311000569764812530143855
+invmod:9155753362316784223456266001165269228274821262,564516474013187481573175782767769679250281341653,0:119205620905238875198589061317020547195431291469
+invmod:2381725363012237979273240212723131218823907332557,627105554257965120883096528911164566660356,0:171572488325502115512339758443240079349533
+invmod:98450611484841078779323233743949010093062874462,498474891646461337593869229973450784375275,0:479013309851681824382144106029434631482323
+invmod:302941267046246453138910366044154426837953622,83818905504557213907433754163930101975463487685,0:77920560252131060387953578558356224479003138993
+invmod:3017383944801662240691138696888601411338516995657,61737866641820357298733518758961763874892655287,0:57869330891359519120660303033767633391977224135
+invmod:374917274538161669733321516492506551738043651,77803838634333688188670502424982439317036,0:68639725794250011077961000847054314676555
+invmod:5358355766108806240333647212584488077935,587627440281100756115550692187455782420924,0:314618325830273870368608880986071270807683
+invmod:86122802573518542982029793217367784359435,4444541935970557301558909662301636875859,0:1955320382109976216143063234526457146856
+invmod:623824975419641052226172487141306430801018589,20768350634786110695583221446196247762848997250,0:12103767314840562576462750961286924811261413809
+invmod:7590027145148728758973273983569196467947062255394,90068309971049962266103924501064672741412670385,0:6331972725698812300523110784176833763986644684
+invmod:686524668697820444915978210393072714624818,186650354938328642532017629073639972204995691795,0:65611028587457585490550162776486984373381347012
+invmod:8533533853350881783993052422423559214064752671,63016121594055151516162786594467518419073,0:131371511974154164830815450922802421883
+invmod:5344740912348618433699936772348773718405033080,754609660139342129058931248435676900268044223,0:601779294202074328690589293303990212685307436
+invmod:2630687964404181803667484048857594086603863164778,42030243673690269464501320091336384623277873,0:36838170059220383772604498138745951997014365
+invmod:5306175182479523993478999645749970458659031750359,758113498568456349896540610013930582835369681777,0:501795105681317857414510503515044239126764236204
+invmod:806866598044057476584935940512202394402119521,947641922298177262021501581582394143250064926,0:76703572909587691543666595336149993104408285
+invmod:3752967247553075344733410201251369307099526185073,4402571726399572455553419679967331632378787202832,0:2918979067711444062792869424130652843352323160497
+invmod:40984400287710529101974761448375262101587597378,7767837478658170863917839375734721468526147967,0:2136424825671493001327961172463161875887529706
+invmod:401457319584326150334816297804779451405784588169,540188815699793070242075787313955763858504,0:67372106144949744344758423425304866564305
+invmod:7328132145926961595815732345858284613765167,9787719863595769932092399021858175294652078,0:2230156054528184544247089349526629112621319
+invmod:77171202039883192025885180439962488662357894253,12064457568855376162922164978659009383963542,0:352639382534756831500079601223680437740983
+invmod:1689300510107332942753596615492360305248158883808,5021685778114233976935875054258022503184892416233,0:1762404213252802117851393076433629721481995643743
+invmod:413626471608667549603757397530674300567855542919,759613621964327430276342657441698817566357,0:642374968767231560916741285504168484044924
+invmod:815487836506353402229957209437685304756474,231515992882606539156732730332354159627815,0:55964822173154353392771255475917621969154
+invmod:296426386298708272323405866802864845229206612199046,342337072550591175877277735718537487310584965,0:76144006758731629943626088879647674452875321
+invmod:1368837997243033258097250654549080178537403,72416746615410564704099840606609957868938364467,0:42273580850321891614742957751910595825483883404
+invmod:9641372200812485192345151698897221555588679358147,287806137472581046723231335880874585176303828,0:255252466811823779617792436926094192052670967
+invmod:46719509859424879114122464677053888891786863,210544160158454559735214754459187198735974410,0:140373812459197552193672103292254446400518517
+invmod:69471867059868794437449477784309966908311269,475692585941773291840125734394747164491541976266150,0:329429867057697325602436904654233483107661273264729
+invmod:7405667221685129649068997020918698026393175001749,796216300173551602800332455600650397180944683116991,0:130410302259950789489978656088071644453583901435057
+invmod:9875331536196145287163751005066164594069492626,2201640116844513333140292091820792899163450729637,0:2047598928737481788502134745016206195377427587363
+invmod:62945526176222857740120186454769067947012290363570,44934526527044082707728840604580666450874671024251,0:43861879034315837687481092531336507739461347512032
+invmod:5812420662398017239905743494134134746465045897292,52956025052699844938819589327012098626977604723,0:13815068782356510869666523823706600133524973512
+invmod:62988324661142084736397879043193595721220178,7404210351476786487650626340728674929309799,0:5036483589239858803333996442909574578899948
+invmod:286333666557475431954356887797614991091286553885,730177931071629647633748484619415338517839601274,0:363260706789674293461306138407487067104937300831
+invmod:49616721004820516975071365326319319198923021689,132795538845737308034029046093145336156955241,0:56876640900410852290230149182444669136767187
+invmod:5446872665716082344009604433844511709028377538969,2280298209842444269643398464555071512122870262,0:375611662251833543184276080958156903157176019
+invmod:48133060961114172650826182330907073912078935,8721390832897265296674009086319009860242439839,0:7702992209702028145739081817455455176622350078
+invmod:40807573183755241530172346993573440974806877031,21200726747362217929091368487884445712920776,0:11454862264524468743635374252060129893516039
+invmod:4876011850332170585030918362754881792191414391238,883237429556989698304596380266521788568157904911,0:527685501843148925165860150493838048613672434138
+invmod:9004216524525198565187718452531030887145904294,8878366789568435967650795187708828058761785,0:4981848279005575310485064446844029075803929
+invmod:6993868737949430623485012912067313181948980567149,72587842808105829695332807775836181652781451620987015,0:29356657469761942723664151650917553481140935005518584
+invmod:75838243096115096340554120168203104139210864575119,6451996398231430323660940321776782700563518057974,0:1345394845933169255579194602505266246529197837419
+invmod:485790318680850515659798197857065903571954663516221,67351781195434836704429039169834802850340728665,0:34078566883503330914204885404291533157887033436
+invmod:371333400895514427330799618912986292421266652,74735768661976283216974595800490448686381913090033,0:775734485942448008241221468847983305862557765286
+invmod:6097834709804461306077622570209088350134909102,13260744904604742982854800098901232265425978195193,0:7180051176576380055634721013915424214485695619650
+invmod:600881693193364832300600937554551319012583954782229196,796027198454713309819370879215945879338962169620342457,0:305489886166685871022060158652320831304722506678707663
+invmod:5662964710494261101411655474670941615613599315,444220509796947509810830805138094482931853315876829854,0:83502974856377599186566250358062403371236716847533769
+invmod:6270395747183927103046939721473439728631174048403114,8803495340207614105802361410280441129955119276551,0:7638483007340998905004349443806488928949129256475
+invmod:5312750065420550632940178685674720232414077135667861,57930039498945162545687903211875639956633916330,0:20906112474411708869764963749645301466537400461
+invmod:8502626964451493813784509478933179204113913861,151683587165616476059679476891877738245602771985126484,0:17577340844446441446896817780642040689999518731337537
+invmod:4941004253366524324322788098717712122185453894,507952581732578381349957316858286666961520136240812511,0:312115745275256030023730055964263277096930720173778858
+invmod:423987861634880847990099692392247549547399923116457,6773005116228586899620384151284037878817381874,0:2411264735887581238523319245355992628456396037
+invmod:526342378928843427610581233811595257981048046869299,7096065565042815656938985029340106874450131548364,0:2266210293557852404933929618783723210631424222303
+invmod:78446630124873873738016711675224033887037462247129,7662020477272785489947682873719507826211767799272559,0:6618353901163261801200450611723749392144591388751943
+invmod:146724084718984069653032415105637599783153962,30298034422463313667029878130649415526567724423891,0:15840758667632633447433042854062793488919393155550
+invmod:532466063698619582407914116981870172085275218057609611,503389009870258977998715866699908326167138509155621,0:429130769700630834787501129352450771879630731320433
+invmod:664376039724377171384810644630468503764696090762,224298076389079709612544590641569981088172697659695,0:191050396356473488451331811254972158658440851245723
+invmod:835483973043657359948123633363211141824404441813878015,69643224478201509070483710852895974722854115357803189,0:53721439884173124810110466416454653383681843157933247
+invmod:813970262809468815021442298539024428784964079319,429074523317944731991730858790207763790104061278625586,0:158332012181946654631830290462479503904893230674781917
+invmod:3905569509910236582271054510190653771408672274545828967,21054133848316667891192282660059320939317809341779587,0:17094616510862655692939144695877501853951076117185513
+invmod:4691307104554605783547935208868795800777868512,942772133788456146227915931545461264049922041187188131,0:469683594104330994724852019245006601277880263578881551
+invmod:6344527026541951916306965449095645749422549760,76368107869275310020917570118694704915444730867,0:41500809372700676201512721693097909656425890041
+invmod:1532687328617246474516893240843261381746745335187504567,32537955155074651543885535513776259898758463526907,0:31592260213499097541600572787744360343931765806593
+invmod:7018504221615574834208014706510055329334098873351018,101610242334178923059833344503899037186775079202559303,0:10649252292552342413027086385381658365781051021861494
+invmod:614235942250741815189766632484724986765317349320542,9362550248383847419253207491333265608402756140737,0:8160460781303503000366571190909239384952542647609
+invmod:7775933593191150830308054268586415011508980457,368533946098442033007225558534059472616584669800220,0:253801676862101461324685686415984317623566854941793
+invmod:114994724586756601240947074309582797715956747530865,3876970882437444481290779177938795657877704941299426992,0:511133484674702237970986949221474571854159368113080049
+invmod:967002084921847074704293339527143050334641639867373423,67184311934061779941934593909885344171962367245011554,0:54742265392939905619225231956123009510166549574440811
+invmod:6280498620763463276942694339653106561075254543429361993,12246227880575723984287633819537276950692995636118272,0:6888911322746399525364250058022364228815026516488953
+invmod:44275278051846293224710462815690831294050926191,3528785552950193331450403045205521284400464217,0:120514793436107018084728538690789624267772938
+invmod:77233427780696709885390992536748673614121634321979788104,491164926805617690128308614539794239093995145700823999,0:199381937154931303182568760928699286043016185484364692
+invmod:2935661752367750120971963892075802637450138243541560,9020651236069334749255637029615697294334736998960171627,0:3125819936094028800430390470247841155021420396038210016
+invmod:302473523210899830602993285719361792150121191223306880,65877646712326499599771065429073023167212168003911407,0:52297679713827579628631563559676964578000626147057904
+invmod:267895147221485475464503294804253313969059499267,749147805746876465294375899176118315575206244421458271,0:129024846433542980463213625490720174159069030878062276
+invmod:3781978240476513092005529074451902150648006057998586,27364485741607024708356504480914129745315051983385,0:25329045084429371227591358650591561585384348697251
+invmod:948013514376879058094102833630021404464006764852569,8353743535195396401876310124547966294825033103946,0:7927522032829817758549574325420299949503254620703
+invmod:6773542220739678376382399310753118322321830877020076563,23546371430476080325875311266723651505011788851,0:23034799134897779290547258699648209277778406267
+invmod:56696856401426408452242119629657459089185724508184784934,7221005627051658808617341708011763226860565840269,0:2227292432795108865092977039762847004980273813910
+invmod:92662353717508325061448569170875221120898258909234857491,562238642230582644285673923363000274985338785203064143,0:82872573566192386039048139131290614037215257242199497
+invmod:89468591435176366016645724528914029419829867195549,705411786218184999265977265146374736801000908422516,0:485602435630685604293519285770866831844583644332693
+invmod:2277395840205666058520703175677485655050927000860231,792131783062753783192832245011815485211186317516729,0:36274050046894199444508304306949846655815849306835
+invmod:612911230333178233436163590340359496090089351991282071005,572255259654004408298629798022675847670239895312539448,0:403266920799126234196133278222931567019309289982594389
+invmod:213241578824971760442836297601417939805892681628568881016,3475071686128494213859357380055444712046960621996643,0:314926700961595267117992983958097210528266000605468
+invmod:89881958503908564448695138563460417549093214244379,33280210266097827064329998950581767848637995197241605416,0:12771855655553092160496981250440547140648269015354531011
+invmod:73159396554894592455810450837975467585529573360122965037,161924163103234420910961871269258741990082667722423375,0:55900291355504579400968626517795006263004157119627223
+invmod:869777439024092504944123032140706083242764771562615,3691156600535012715499994551919740723415019969643,0:181436500307965243185392814904512789376492449509
+invmod:9146539798430854552628645300653561881701305853292111330247,6627303121361849299873564751355803129746293824560475542,0:2409578230798119285960935905755578839375100707728705163
+invmod:24992448558250395162546529057033728367963608818369,97104418275857998682685499767517746419160351530467647181,=1:62070924902659777799435874506647028956762328885724256288
+invmod:11569840794297110873922272445085763696814732411121,3856710587570728871230191743757018008573821992755,0:80733435598402588027986814199605794544352758136
+invmod:649787313291617912250345498890431010716418004127770,550784775616289426175030973861257697988532404146125403,0:190014706473838692857161698137541544033343388692933291
diff --git a/polly/lib/External/isl/imath/tests/lcm.t b/polly/lib/External/isl/imath/tests/lcm.t
new file mode 100644
index 00000000000..14eb20b514a
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/lcm.t
@@ -0,0 +1,780 @@
+# Least common multiple tests
+
+# Basic tests contributed by Hal Finkel
+lcm:2,3,0:6
+lcm:2,3,=1:6
+lcm:2,=1,0:2
+lcm:123456,34,0:2098752
+lcm:123456,34,=1:2098752
+lcm:123456,34,=2:2098752
+lcm:-568,34,0:-9656
+lcm:25,=1,=1:25
+
+# More involved tests extracted from gcd.t
+lcm:0,0,0:$MP_UNDEF
+lcm:0,0,=1:$MP_UNDEF
+lcm:0,0,=2:$MP_UNDEF
+lcm:0,=1,0:$MP_UNDEF
+lcm:0,=1,99999:$MP_UNDEF
+
+lcm:-7,328492456,0:-2299447192
+lcm:16522181,930,0:15365628330
+lcm:844378,24,0:10132536
+lcm:209,3,0:627
+lcm:70522336,34102,0:1202476351136
+lcm:32557663,995533,0:32412227919379
+lcm:641,701,0:449341
+lcm:290748,-233,0:-67744284
+lcm:290748,-233,=1:-67744284
+lcm:290748,-233,=2:-67744284
+lcm:-95,4770,0:-90630
+lcm:6839092,7,0:47873644
+lcm:787590783,-6789049,0:-5346992417735367
+lcm:721,15845,0:11424245
+lcm:-37028,-949534667,0:35159369649676
+lcm:618,-3,0:-618
+lcm:16657,-544851,0:-9075583107
+lcm:28271,6,0:169626
+lcm:-35357673,5207718,0:-61377596706738
+lcm:99,-565,0:-55935
+lcm:9311525,-5,0:-9311525
+lcm:6221599,7764515429,0:48307701428550971
+lcm:21590339,486739392,0:10508868477933888
+lcm:335,3699183948,0:1239226622580
+lcm:14,8755508782,0:61288561474
+lcm:-5302,9,0:-47718
+lcm:8236,9462435,0:77932614660
+lcm:43040,2766705,0:23815796640
+lcm:863478587,63,0:54399150981
+lcm:8874055124,10,0:44370275620
+lcm:8204,-89955,0:-737990820
+lcm:3303887262,3,0:3303887262
+lcm:75504,-62,0:-2340624
+lcm:436,2123372,0:231447548
+lcm:3361227,943089540,0:1056646008421860
+lcm:37340421,223177728,0:2777850107114496
+lcm:-35694701,238293550,0:-8505817017478550
+lcm:4263,15500547338,0:66078833301894
+lcm:1493,38730799,0:57825082907
+lcm:-635007,298501,0:-189550224507
+lcm:4968,-98492710997,0:-489311788233096
+lcm:3367542606,17576297,0:59188929003209982
+lcm:232155550,3921719,0:910448831390450
+lcm:4860966,700,0:1701338100
+lcm:2323372237,867,0:2014363729479
+lcm:4268,-29035,0:-123921380
+lcm:8,-73804207633,0:-590433661064
+lcm:395170,26163606,0:5169536091510
+lcm:-70027196,6945032910,0:-243170590407510180
+lcm:5871172260,26773591,0:157192364779785660
+lcm:17125540,836,0:3579237860
+lcm:1988202315,-68060596,0:-135318234527479740
+lcm:554434367524,-909419,0:-504213148079308556
+lcm:-40457802353,3398,0:-137475612395494
+lcm:410791452776,4492144466,0:922667275633904368808
+lcm:135751970,7417878752,0:503495826902570720
+lcm:9593,31047471995,0:297838398848035
+lcm:-18387143,50226,0:-923512644318
+lcm:413450673851,-124,0:-51267883557524
+lcm:-618513698871,-318914624,0:197253063714294189504
+lcm:37416674596,-8817,0:-329902819912932
+lcm:6242382,-943205,0:-5887845914310
+lcm:-4949666413,1501091102,0:-7429900210422557126
+lcm:-6385784303120,899228089,0:-5742276615660794337680
+lcm:6308,-79643949,0:-502394030292
+lcm:2421,136928,0:331502688
+lcm:333180111,442438,0:147411541950618
+lcm:723761305,611024432789,0:442235840862251429645
+lcm:-91289,-9223787613074,0:842030347409912386
+lcm:10944,57098,0:312440256
+lcm:57145099,-94544476,0:-5402753440923124
+lcm:9327105307,88173695233,0:63261949288116530887
+lcm:73230770347,67182928,0:4919857571607036016
+lcm:4810254287,-4310,0:-20732195976970
+lcm:7200253992,9893,0:71232112742856
+lcm:-92709373682,-664752121448,0:30814376416612439465768
+lcm:-2236424417,-69570761,0:155589748609671337
+lcm:781963714,61084006246,0:23882738195060678822
+lcm:781963714,61084006246,=1:23882738195060678822
+lcm:781963714,61084006246,=2:23882738195060678822
+lcm:78553,-3773682081509,0:-296434048548776477
+lcm:24811454802,-26314981001549,0:-652912961735421705488298
+lcm:805866671,8061826,0:6496756880801246
+lcm:4281823377004,2916710,0:6244418530970668420
+lcm:15229,320560332911,0:4881813309901619
+lcm:6093153060,357460,0:108902924641380
+lcm:624794507388,3264784,0:509954777752056048
+lcm:2632503413711,-514594728450,0:-1354672379322310051777950
+lcm:7216089,86034,0:206943000342
+lcm:112578025,4532680608704,0:510280230883694129600
+lcm:-972617496,-1100642928524,0:267626142282779963976
+lcm:-972617496,-1100642928524,=1:267626142282779963976
+lcm:-972617496,-1100642928524,=2:267626142282779963976
+lcm:86658,-56860,0:-2463686940
+lcm:2292080,40552081391276,0:3319593382689853360
+lcm:57144144326678,3579498119,0:204547357129208422518682
+lcm:77390585076,614924,0:11897332034318556
+lcm:685579,959286825595306,0:657666902604804292174
+lcm:346354116,451435163995,0:156356427156803253420
+lcm:443946215999,260668,0:115722572232027332
+lcm:640447120070,-441698,0:-141442106020339430
+lcm:1253208493501,-8521171736,0:-10678804794135860887736
+lcm:8507343,62395589,0:530820677310027
+lcm:81126006,461820852819773,0:37465681276782021316638
+lcm:87891707090,40954510522233,0:327232894803129615339270
+lcm:-767589,-991593,0:253711959759
+lcm:86229155,43027930,0:742052409059830
+lcm:-431963821,48986055721,0:-21160203804962069941
+lcm:101557073166691,-74080192,0:-7523367479146517284672
+lcm:-34269048183,250074,0:-2856599318438514
+lcm:7650667716360,-959482143,0:-2446893018624669653160
+lcm:-176432105527291,712269105001105,0:-125667137897384071121162656555
+lcm:91973525400419,-52180215632622,0:-4799198387886300095948868618
+lcm:9054526,-21388581343089,0:-10192813993374435306
+lcm:19326311972,3180878,0:30737320286435708
+lcm:501569850634,39035351302,0:9789477660994928712734
+lcm:-3470290487760846,622612793613,0:-720215751744466904366758866
+lcm:827793089252612,77591849874263,0:64229997108241062748844324956
+lcm:19866668332,4414961,0:87710565885715052
+lcm:136274450771,8659380001,0:1180052253653656430771
+lcm:952660786088689,171372582380,0:163259939044179413638699820
+lcm:429415374,9140880954,0:654205802258564466
+lcm:-368107346,2945634,0:-542154757013682
+lcm:2147845929,79983807840463,0:171792896056056736025127
+lcm:77885771608,-51236668812562,0:-1995303742544970246669848
+lcm:62272695670,208399244,0:6488791349735036740
+lcm:61973019,-1405255816878779,0:-87087945439289091663801
+lcm:286206733986,212837117931767,0:60915416394244148267933262
+lcm:-131938894,1048695278656631,0:-138363695208977699906114
+lcm:27109492,306933238851468,0:2080201045794490233564
+lcm:-314477095129839,3837918787896,0:-402312517253922259873876248
+lcm:4116345,9101435151,0:12488215692214365
+lcm:63853435249810,902940229903,0:57655835504559765637068430
+lcm:80076033,14791385,0:1184435433375705
+lcm:-31038678,1454704764,0:-7525352125810332
+lcm:-31038678,1454704764,=1:-7525352125810332
+lcm:-31038678,1454704764,=2:-7525352125810332
+lcm:20638192722,-14267370499730,0:-147226371004802594482530
+lcm:8065790684,-1977228453431,0:-2278272977117641090972
+lcm:362687955673,99742877979696,0:36175540507397430642015408
+lcm:1235326072088,201675880263044,0:62283868250058987186578968
+lcm:568009735,49546482048450,0:5628576827704468332150
+lcm:849579042,-3197920541,0:-2716886269614901722
+lcm:1808291492597692,96814519920612,0:43767218183093114768373606876
+lcm:6275712123233717,739880208952795162,0:4643275197065752315694969352877154
+lcm:774075573665981,7523229210171,0:5823547966683781965601892751
+lcm:2944466357361,497012903828640,0:487812591499242877115539680
+lcm:282862415058866,-6240991940068,0:-882671026265275987882021444
+lcm:571225883598025,189932649930728,0:108494445780794463607647612200
+lcm:815309478,-371377784,0:-151393913606918376
+lcm:320172590239,777220834144,0:248844807655600692320416
+lcm:654332382,7919190746613,0:575753660527071413574
+lcm:-5094673003562,268414312780910,0:-683741576547274437277800710
+lcm:-77841790209187781,35267718271550,0:-2745302326850733800658699930550
+lcm:735762990564598234,-32739891496,0:-12044400238928708979996609032
+lcm:-5999905013129575,144027889596460,0:-172830731364054662969688260900
+lcm:6861193105404525,-4725324526382425,0:-1296854562448559876288579018925
+lcm:859748569384694164,98523184164,0:21176291659055938820647004724
+lcm:570460270963,-54720108308,0:-31215647812506387460604
+lcm:61750383079701,3452251304617,0:213177840547497299540279517
+lcm:-1738716695,8560399484936237,0:-14884109500328036282376715
+lcm:9953417006786660,90085339160,0:44832847342864414393180280
+lcm:188523146978,954842405502,0:90004947576640310936478
+lcm:198834734074395695,171072375577893,0:34015130305505499211880376370635
+lcm:-102893613303732727,155104650554,0:-2279896847959124297878354394
+lcm:90836124710855,-98332551310,0:-1786429578786341640294010
+lcm:10512242068892,84377075433,0:886992242016856266730236
+lcm:-726835478343584190,29339956106373,0:-7108440343718461118245907014290
+lcm:5033847480079150451,-69469662902517,0:-349699687543783241256712189585167
+lcm:3869558083241,-8770208065,0:-33936829509626159538665
+lcm:46079368203995132,23609959311256,0:271983002096177133105574201448
+lcm:979137194422864421,-1378816153373947,0:-1350050180039492392646639294639687
+lcm:-72618673468,-244198092166982349,0:1612121956052969066631874212
+lcm:529564016606,376298866055896536,0:99637169476421881457260938408
+lcm:554186920892,-629719688885314,0:-174491207704210180689290044
+lcm:3455963977845612750,271884481278417471,0:313207657811150223746536093433451750
+lcm:-41270780965441117,-4124462824121691009,0:170219801814430998805436931657817053
+lcm:47581683736,9394210662450,0:223496180345027475456600
+lcm:8196306676684,76732052476696223555,0:628919434030412315441895170091620
+lcm:2939970750639,-2013582768244,0:-5919874442628068251907916
+lcm:70476757656499,-100957934015971,0:-7115187849144405009597945529
+lcm:3674841030712174173,540185467629182772,0:661698573546054604863388890438315852
+lcm:82915322420038008,123799513890,0:1710812768272220630953988520
+lcm:466513077506,73565730651787738,0:2451383957524498065361030102
+lcm:-38890216282311653,91459939591112,0:-3556896831865504089438972828136
+lcm:-38890216282311653,91459939591112,39285:-3556896831865504089438972828136
+lcm:576595981539992,20909590051109791,0:12056385599118501431228849261672
+lcm:956905636477652,8381376662473,0:8020186569762664723411553396
+lcm:9187294026565993,54295427509,0:498828056823282593136101437
+lcm:8866081281165098,6545042142269515,0:58028875622012459166053127387470
+lcm:338772425501,-750860960783,0:-254370988898468150127283
+lcm:6750486296504,8609697533187,0:58119645214823136262078248
+lcm:736067207074328,329259058372493427315,0:242356795500164369960320250670469320
+lcm:680100030114145,52232423165123,0:35523272567534917195872964835
+lcm:22697310250913136791,365228836596285515,0:8289712216805950219366224267686882365
+lcm:30594845950075862222,37349482121506846253,0:1142701651822614557685156508694964954166
+lcm:866936756424,-1765396942933391,0:-1530487499507519421423353784
+lcm:6939438360479781,24559856763503,0:170431612152541518812930232843
+lcm:927595346004843560,7670228140092963222,0:3557433962772809951143296742471775160
+lcm:-357321286444971587,7925597841132985664,0:-2831984816439127983772762412958328768
+lcm:6673370692769029,520191499051311630305,0:3471430704396611186160057152801823845
+lcm:9013236794945,1008467412252240244,0:9089555586614859880726704766580
+lcm:406532185466775673747,9519149309169118189,0:3869840572441069484183117712436347484183
+lcm:548046408595014443,777065152533771,0:425867766090470284154159790254553
+lcm:23897406396584,-8555442893510156172118,0:-102226447864489365824170750635622456
+lcm:54729344028716311850,2026849525600172204,0:55464072490506137031056639711882908700
+lcm:-7936445752013,-98698488318151151,0:783315198342695407195996516963
+lcm:6309028281362257922,271678876766048827,0:1714029716965733695518439315219557494
+lcm:6357785774765671053291,56936125648067424,0:10969323930774361884705778197353487648
+lcm:11095109588014,9104811531028000846,0:50509440857484599522180551729922
+lcm:-921590308699737078,472826384755153630,0:-217876106943941345664446493248646570
+lcm:652120832633171211942,-3387083844442113181,0:-2208787936835953406166467995677302807502
+lcm:32731949302549,335896184427699,0:1570648125658156079680986393
+lcm:3635516318567409721998,16713986701316425,0:60763971400954533716595371769881217150
+lcm:6746198240933100303896,2007405485449,0:13542355354775500078274959306009304
+lcm:-19072614334803913032,-240759760944833349,0:1530639355946797274927793576109768056
+lcm:828472954262165857,127978158379025077,0:106026442953302260750986298136195989
+lcm:8306750095431507743,6378030328941226919,0:52980704043597587430846783712468533817
+lcm:7938532173109072,7646615157112938170608,0:3793931277507783816896749585208034736
+lcm:25274397567311,3125247753747112,0:78988754224550174717491855832
+lcm:0,-6378030328941226919,0:0
+lcm:-6378030328941226919,0,0:0
+lcm:400327281633151431,37147489147345586,0:14871153349853852722430493627433566
+lcm:28164658061513141691,818613450005821036296,0:7685322634656510878949613649488100605512
+lcm:476291935913056166817,170589720180888384,0:27083502690607291480376538585587184576
+lcm:84130837655605609,16051948347568699941145,0:1350463860485469013094700782617631882305
+lcm:438146043336536562159,-2206822496905640873917,0:-966910545365262749689560255553699552306803
+lcm:8120293725815373571,24028314574527126,0:195116972081450718759827878362986946
+lcm:-667658265953408,8440015504605457600699,0:-5635046116424757633428637247402232192
+lcm:53314441150262832895,283247085055963859,0:15101160047199676268547968068076341805
+lcm:6658153298145442,2140281300389057549,0:14250320999144418995877331910041658
+lcm:213046498706732967,784948480361985741,0:55743508468763934304784144916207849
+lcm:-3857522843819,419578526133778265155,0:-1618533749336956944635887834826945
+lcm:-4948941087660882967,-779517282262677550602,0:3857785106731510951136294197380142396134
+lcm:4277076043224464,448010594023993,0:1916175378810781677476700564752
+lcm:-644113523059324254840,-71225587742718143,0:45877364252933205602125580469623562120
+lcm:264902435468141506,-823887292259809475,0:-218249750270876020336340975899569350
+lcm:1538706915662950684,448326823774496344436,0:172460896054755625075686197059836448556
+lcm:2036808313025110180,30422160628736748027,0:61964109668796220999356441366572614860
+lcm:7385426850078311,9871854919284839,0:72907862380963907579111265026929
+lcm:804644713550364054117828,8379163811459445,0:2247416621621120599518832306788891161820
+lcm:981008037679996757191201,-641409668917881464,0:-629228040654107304092567432937180101798264
+lcm:64201713053871850,879119102660231895102,0:28220476184584758536715661672075339350
+lcm:1033957429367195,1113485105415049436,0:1151296197233604656037339121652020
+lcm:14455075580451942850,-1885962875546302716,0:-13630867953974143493153933318215890300
+lcm:2615475057635555327591,71606675442458157933637,0:187285473579953754910128144228132079173078467
+lcm:596676024530775,2621192750454214313695,0:312800573973981674572351390206292725
+lcm:71665682789483848832034,351563529541544408090967,0:8398346796158551916852810998534107080858545626
+lcm:5092055214749737510271,-1833800774226189505,0:-9337814795210574311088704576082129905855
+lcm:600508413963341945,5057063373752305154,0:3036809105884103889579068197287884530
+lcm:-92318043858914149,958444935645415778103,0:-88481761605267642819033271229511079347
+lcm:385447683586530283,1775981280157037775814,0:684547870529570889684189390051875975362
+lcm:80717517906672139,362327909576030289130356,0:29246209529290308450092391020660324351484
+lcm:31249856290116188,7875872084416640,0:61529967699339457577602450142080
+lcm:5339381130045070,-287550419156538713298378,0:-767670640990486609645612376307748948230
+lcm:-28993892995370333046,698005135756870427,0:-20237886216353643864566444205658230642
+lcm:9179674525723481348,81469928617693608886,0:373933714172176229761960288978914029164
+lcm:7522547789649675160016,285918417200326088447794,0:1075417478665223340089057247433582968006102352
+lcm:-901774653467788803,236000195734098992,0:-212818994726447447848669649751186576
+lcm:142671415131788790,-2583777714764598301032762,0:-61438537158574095028788610137898909056330
+lcm:951078283105727024828,1487627587101952300275691,0:1414850291441640178530450466337072693601856148
+lcm:19185476025869672486,2445736876347152429980675,0:4265693291522152053797221279874464505382550
+lcm:6741226163186521681303,2568160083399218078514720,0:17312547945462088421236893499979478635434280160
+lcm:3987919571578399660412212,9884144363611069680876,0:9854293188987727688997011704065958289363314428
+lcm:99431631881940059268,-291965406586754754564989,0:-29030596829995156232729757591886192217768052
+lcm:36727416735327035,-1612205593089728906670,0:-11842429336086311491916222123088564690
+lcm:19590774006340220367562,984968880458891391,0:19296302740348077288926838014277057458742
+lcm:70695613219926859099201753,62591913993270611799645,0:4424973742363186825608316839246937058962268777685
+lcm:77425442645246583405,-296832015660977965,0:-656638577252342429795743277063990595
+lcm:807971872592227526408,40230405885131399744453603,0:32505036378154987781247713889763216622213248024
+lcm:965370212546292322,92058451234918953535616,0:44435243317668098531171705039686887170176
+lcm:418561885926860582,239657399821326936,0:50155726622771131306218069956618376
+lcm:4657697584188823828175,78713797195009784682708,0:366625063037526091489561582727843402285697900
+lcm:-38091455008728662,5763777114003492300442812,0:-109775328309201979538317902240813878138772
+lcm:54943065861736600767,6268390929335695219433,0:344404615677603400985934681975925581105111
+lcm:-697639190379957186138,2936028900796584636,0:-341381470880647489965333380835887162628
+lcm:96018089280939789090187,29566309848085271814423786,0:2838900578701380961562729671686086004548591987982
+lcm:-1112368751522257152114,1995174854903534746993983,0:-246596684713071723298909011042483787097081118
+lcm:-84342841213955171500540,5699084396809137598518,0:-240338485172501289667138051435146885070099860
+lcm:225675029492277024520800,92998377812004114915728728,0:2623426456932243737035123197311725507407124192800
+lcm:7655269162163547244,594548791001649285,0:4551431025156545678791700910016320540
+lcm:17608380663675562604,264448308193844308642824889,0:4656506476542203967645749547080047894928850956
+lcm:223093179893694063251643,17908241494426478956477995,0:1331735513765267693007651331958962321896225698595
+lcm:-9501451313199296478183,164266650410143061944307590,0:-1560771581254303549338241248628058185171476308970
+lcm:4558730178677382262,3122005086984557462,0:7116189404010403994895797264339269522
+lcm:54440882483631228680923933,4478571958703194374379,0:34831058528320962440312711060757171496803301801
+lcm:36855929355558415329723,308635436762628905,0:11375045853945367585945011810669865443315
+lcm:28683868680975381560,42902583850929860163229,0:1230612081254607193977374775224312156657240
+lcm:24731088466679335541839144,81462858536522998396,0:503666290303833545129681622218515211800503256
+lcm:-72335534127835253275,-227166439208550011362,0:16432205716068881729381218555965397710550
+lcm:474777034176054735892,839001319154604024448982,0:199169278989010220914577285259796918419130972
+lcm:6299666296143449904,797331145004636509,0:5022920141051174455685525850770945136
+lcm:8540885149755672764459236,41765710483565552588310,0:178358068219039923285097732763708140948642565580
+lcm:385990739803366398,2963466700114736836981086,0:190645117326654704160162372267660375658038
+lcm:-37246197932269024,3005402223074948482,0:-55969903033365437079467727082210784
+lcm:-751622018429096822596,3003864133422104297,0:-2257770423049491832679123307914818295012
+lcm:-6108319432277782804,-82931541043539126216389,0:506572343704992558730984950135146447174756
+lcm:30921518942393713547539642,721143788088068568685,0:22298861303554770289882384831917605974237310770
+lcm:570903751254308471830202651,-564896588437884119958,0:-322501581409949262735089396741686909437933608658
+lcm:1054271475454361570597270062,16484741384321323400,0:8689696310866008240570033696584650327520025400
+lcm:6529831639822170310307759,85346429845722052312845786,0:557297817952459046702350223377401463955562766253574
+lcm:-754058902141939454006,69516695016006129145191,0:-52419682724305615903366455441899934040585146
+lcm:976193241125104191848393,33823563038032982713854,0:33018333628496693179640404511073605465668736622
+lcm:2920092456500658009757,8895875497550350532901302605,0:25976778934365816392930294156133718389132099516985
+lcm:9994369499844252132394601638,93334243646132127297454621,0:932816917987935116609350111907831170748502078677269198
+lcm:569015432462996733746,16322837154963292812416483,0:9287946242754509292015515862839485902412735318
+lcm:192500272569416024937360278,-235265435750733300361,0:-45288660508178593749288683427056889794244460358
+lcm:5267095375035104443898399000,-764192677627393558125306,0:-2012537858983468571142965526423649868280387392547000
+lcm:51025753118541843018,-1664207936338749988204,0:-42458731648769528582814028192013959879836
+lcm:-62402848465899883613105,12900108782353988220438351,0:-805003533538860189408921682314395887504788189855
+lcm:-8212641700259728565,297115088713153106682478,0:-2440099767342009818056382435156531921584070
+lcm:-5313586393962705049080,-76998532453336088964044527295,0:81827670879828485147952271763338965987967674927720
+lcm:463290189242313601142817059,969769350842083604500926,0:64183518010432075137644646337185534388781059156662
+lcm:1917277332460964412252,-708614825339303498360550,0:-226435190344805337091761225274903062722243100
+lcm:99562752968815530108,23844471852654970991199350,0:1187010630368881028219592827335680236477514900
+lcm:3003923448532254675001,7732856831499478812681071,0:23228909960284118604870886637597256802569606071
+lcm:5794073936773633607324540860,-76553654622431077040278132,0:-110889383753149576103727978239709891143940060899618380
+lcm:-644932980169883872037968349,42642515095105038480,0:-27501564342225351457715028479060110852667069520
+lcm:41892582203464757978762451494,68041907390182959305068217308,0:1425225599311887918623588695629495898803810573641200629076
+lcm:-5550794996398648089925,-61773015425098686639107,0:342889344934094297210650346841878123357696975
+lcm:26506218374693057900,-167675112099207386871,0:-4444433137302729109790367830963302830900
+lcm:145568384864275126584,40072954892382195328941863291,0:5833355320423028246614959434448834158605847827944
+lcm:3161170925861501561771687,413220145707787390821,0:1306259510591710846827739981054213899841485027
+lcm:723440854928237000349411,-71208223609049472714282072,0:-1907960672801919279694226377330300776949407891096
+lcm:94994080481292730137,4307839512004666207932600136,0:409219253303864061854413637026462925940577498632
+lcm:7821178378958515500742,3087104738440174209004586,0:12072398416934336857114452721997626257582201406
+lcm:869891649236864909625695,991848579874131467931448097,0:862800796939950559315938082847205513561495590052415
+lcm:17628160996789341122894,299337591195948255548811,0:5276771249993287502058785568793774940966579034
+lcm:99527056994641754235498057471,655773087035017085668857,0:21755721802962104371752823247713242761829805420293549
+lcm:596721281791001887739,-328175786669349585798669238390,0:-195829476074104675040288189805440291150559409100210
+lcm:266802917073126657350936,148259550527207353925931727,0:39556080564609535241696861668682911763097415546472
+lcm:297095531532857951877,8071469565512676957784213778,0:2397997540817274789320989692996853463867804361306
+lcm:-64574484904487858142015156737,351049851111701482889769,0:-22668863311335277552737854676715612712147868228723753
+lcm:9213606993296693767546,-974475310790221342435,0:-8978432538291752468015873684497297955614510
+lcm:-6506246525097752180174,-95653949321972166356216836249,0:88906882198279699370047684476316613423860643189618
+lcm:7211807452760603826715508,25981532388511222064867790,0:93686904456803121715837451769742014367676981343660
+lcm:244358078258267292267766114,6788410077941126965241803849,0:1658802841074748272013529977344553715539817794996972786
+lcm:-84498071017578145227329893,51359077717175899950414794158,0:-4339742996343244440353286358071234877760977371555165094
+lcm:315675121566194900458712010,607326754590110945679173086,0:95858973542817944770878937652762380762977850708481430
+lcm:3336777364604897112789890,24326442512123908471776,0:40585961367908674095931490287547594986841572320
+lcm:-631164366791648249399815693437,224085205047080377284686,0:-141434596550917146771849565583627819691166316250805782
+lcm:-9374071452933990971885163627,-8124264246742383054580586,0:76157433551480046450059234199385450235104896467545422
+lcm:-8986611810629266612086889,39090932189616079255587,0:-351295032903711635666432166463380265071682698843
+lcm:131042125952122412011234961669,-603299752062616670818260436,0:-79057682096673636704088945577099341952975178863719227684
+lcm:-5931135084197112120929525527383,817854717051260202081870677650,0:-4850806806078831488870903900854502497422338114185819841089950
+lcm:37076034350171687718404493,6575825691817817445639700141386,0:81268513076859634022073542658756708736205992975479215766
+lcm:6586877468189252639017707825771,813151310907233772623665199797,0:5356128048043411806613358165516537614499231407192441180568487
+lcm:2933337084774328653741904208050,516673656644156545121601676651,0:1515577997760262602679690085554979355436376363966312331240550
+lcm:-9902991686684787357658450,173313993122814232472956,0:-858163516540686876248980610636336072294554939100
+lcm:9274522469490915283112908394363,44864081129175577116760112,0:416092928505602244504563614588785724831758965222564048656
+lcm:9608655195311416270604257657,65867528105907714734959487,0:632898366137150893335309426569727530606624485604541959
+lcm:853239911600142024011098491,17829323361272785163230303,0:15212690288662738268179355293062413175232317048772773
+lcm:23972081642808055559504902,-4501717580058722285684735,0:-107915541362031999704526719592126415237678659070970
+lcm:5314236376598680151908105,3994830160691915764873,0:21229471758282529614266075257916580301482995665
+lcm:4935319583093232012062136782,881389216056886912824752493825,0:4349937458332745712903267792817007035077166975812760371150
+lcm:580231659494763900889556,96767644291944525456085901,0:56147650832913989511127904567807102400387849749956
+lcm:303622305001319462939309066150,-27984889540977885375442171280684,0:-4248418333819511268163760331043084702315340960497818786623300
+lcm:8908131273613694428163643,418798812110676949375564324,0:3730714795515386967446577233797553865021052144672332
+lcm:604960317372762640669451812,820482420778387317631260055,0:496359305672865772215202726749222319854411791662969660
+lcm:3125355862613621420823337,52123353846012574000878521623,0:162904029521719649924422263486125418351967284017515951
+lcm:35876668588605457895900,-237986271303986771473105323,0:-8538154584211078670353490608427234416302669875700
+lcm:-43001262189486935668928474222321,75601013836677651900921245468148,0:-3250939017782005364312622194873995196088464819832369459876131508
+lcm:50360054222226284955381499,-7538629547593198554710875138,0:-379645792778070687264466482409787805710036592944271862
+lcm:16303655607623383537122,23252538460647040924816117157,0:379101379065406527294500251303186510479764610602154
+lcm:29876051059586965106021953,26235768232838079362376,0:783821151311760139992194729309972935608098240328
+lcm:29623076251397963944271763623335,47441755805615786352682527,0:127760977248178043763492761350640873496807885066769451595
+lcm:9892811422980328964557595259,603482574014084208448431822759,0:1990046433925368031040084916604965307795191807343715566527
+lcm:-2549498483308845928405350,2555383871703609992631017913548,0:-3257473652590120103062390285427854673645669471900340900
+lcm:-935906971037827073384146870,879641356065373793312781,0:-823262477154750723009760282203349336801144752145470
+lcm:19597038710644290533555897021,2985160892106475439715913026,0:58500313560112043537702497574448903543850923995448495546
+lcm:-5608937456930306694772980,836399586633606428927522624674,0:-180435114247317699327868488365007039436425700237558020
+lcm:7718522069758342120350478031,7389561033066750535580836572,0:57036489919551968141273365317951375124662579683087349732
+lcm:718875898101761373218778459,686314096776480574628984874102515,0:493374662700091643313347796063672168629137876643552239724385
+lcm:1300200863593962819188902,525922101427424561614551608409976,0:341902185229544560458110713971475236149786740307102643176
+lcm:539220635752920237029329058,29487916769600117002583914582181,0:15900493227532973069876042371837383552914044277544832315498
+lcm:5654437789656914341120143121414,6765853316633901505298664574837,0:5465299524692900146239549597899398996727386837109100340037074
+lcm:103114174998937498500059583,920095995082794389728025430890882,0:94874939452788796816569177101730218978113456477925771422206
+lcm:29882936700790118228421849,-1860889369990333700884198092,0:-18536279750198114735901679591403044437012106352304036
+lcm:8909623809613954310018698,-462806578041198407432067106139,0:-4123432506961820007043026316146032423296431299840587022
+lcm:7230230288816368650543810,22162946284655819337870476,0:80121602758364354591303319881368491740552371776780
+lcm:734442358589456361847988629,1647427465162259118128391711,0:1209940513118819039348215846845414818873067603985854219
+lcm:47616626651192848094181030316,2182277257935167463613810412,0:25978170360121936072057209849558211193870620332212112548
+lcm:294703827229370598691617,63046555168872062038888853,0:18580061101894254060770213008323255399294285845301
+lcm:-533653415261740333749397,-51216937243134223196656339350075,0:27332093479044801759907744737948616465079304814903154775
+lcm:784368839220787531616946253680351,39613735771181195550018240677,0:31071779944040382951244796866071327091341523727977793343837627
+lcm:5770744507580580048400572,231937913382367374762373686161,0:1338454439750996843543440906327507234975603867940884092
+lcm:388816489715059942531589642,82051838197217717225950877,0:31903107702510265086302832415272579698669593814016034
+lcm:60241729629297025142644618709,85181464884435369517497693388632,0:5131478776995614297555781224894400552133266197008401795116088
+lcm:1560786485638020475934392460005620,8850527081981124295638445,0:2762756612065888665370691207806362094705896562533237612180
+lcm:8296622334734688413856037840,-83875508267086319614619277276,0:-173970853806483090137656801493133601685389930382427030960
+lcm:-45794179084517723375284971259238,-49063790774577780701852303,0:2246836021296323435311993617164824492625064891225000325114
+lcm:1752071933321291709931075226933,57773126045256149501100162,0:101222672644126613791673432521136796654007466067313063146
+lcm:730668796977177255106481634556,938608337106204028806933670639254,0:342905912253069470166105593930151155858159563381855355668230612
+lcm:921730456287198291208119641693911,5458708493078803375257300,0:5031457870064330030425732359718797657583243087557468300300
+lcm:213400535376420556914942871216081,4183995847570912793889135547893162,0:892866953884353287726737673843872033409506009951957939872404338122
+lcm:32806047880829491896013320805772,753489056993475245589087354,0:12359499040704505410450582731649402374098432708182687703644
+lcm:15218771998961411533589410518,23457061020403160442042221,0:356987663435240813815179640133949762707316007457480478
+lcm:9046617676720978441798060,7479379807328977629621989162,0:4833077826849448212160770633271094897459555793758980
+lcm:2219170169044655639393672927,-5391273013704097527490654785062,0:-11964152245187612169646728984856115656974060298999913416474
+lcm:277590531551034474232270111103,579362077865358674190909581933,0:14620493377741521712796730933686046346752536860927744682009
+lcm:51422590325724235826789079575,2121952875387495603452158,0:109116313401543756339172704192689685091698905367472850
+lcm:511034032165016743768820348,458982236103828060996895790272,0:58638885702063744673892798532850716778223793123163513664
+lcm:4440454508740215531301617636697,3258309525326637800581711028116821,0:14468375222607860310511042523813260258037478238688128668452580237
+lcm:6330009746329830092300048092,-6167250670699283492360751201828007,0:-39038756853585645999814749830700965509494204090781844412512644
+lcm:-9374602262965156933926707655416,-30595740075402425097079774283,0:286822894147961315557763521486314502763707907853113422466728
+lcm:83645893910576549628700447097824,49931389572768584324081547829643,0:4176555715011469153471691311085610269167538819874387285307996832
+lcm:8030747712125824227213267818544,63329417394086865663449328880556,0:127145643461956118439868630218929081813205737418762248914457616
+lcm:378845361147099357535431194,38180105668041356349238612217040,0:7232177960221771411730351326884973759795619786776357172880
+lcm:25958762365949818177158173188075174,40582859445868015162861781,0:1053480804486029724349686454924029433193919106275980799524894
+lcm:95871031013239291309686124,64936572493882710890460913285902999,0:6225536155454490886042480192744349881519233810545112600285876
+lcm:455128054133718561191432952712,39088645380524987234419335395029,0:17790339110761304357582067458548970370146644724724054396868648
+lcm:1307047523348091088814812136,44132853285705545682051355847561,0:57683736585366097743814172916945483114493512756215268800296
+lcm:1418285824252402530993393665755,636810955908181043849421782278,0:903179951493194917152704617449910466299855863874287914489890
+lcm:3071172872783184341780369192882346,-58125204065109316437571977973,0:-178512549949750604044117019967590439630943828607057692292564658
+lcm:56958148205198214736866933854,4922289245511311172745764679844,0:140182240177343281524353792167921226808367574258629117519388
+lcm:4836813580368584281452577588,-5400032605107989894617874622172581,0:-26118951038819470026364723997465834517846139303988539028714628
+lcm:493001845960066187429806680791,4028800209124423703294502145421185,0:1986205940102641576976415454897329744147895770653902923543957335
+lcm:71197215106470682909632132625,70077573297929109151274279,0:4989328060232124924682056253101608707528304143079252375
+lcm:486722080146274783096432055886,505595939085965376271620470551,0:246084707185430303071142220010478564391091338964955649213186
+lcm:-194536785271632924316130857883181,8276525052027013498990299177664024,0:-1610088576841469642302988316918048088947156051499250583217058380344
+lcm:241211965193448971857220311,2710726738427327769580581757190,0:653859723678484041534242084550730982398579984949338286090
+lcm:667013805494915469984846976421,118549400818390788595763048,0:79074086979016886300666397440542951393124558234159091208
+lcm:507926799850267721181735296662204,67253859677995358015731931706714,0:17080018861911569471437509381376023258751803251807601040628418828
+lcm:448088677681619431331494894631309,779948091351174817338856782981850,0:349485908913850840791957607115202038571061594442475706481388741650
+lcm:187408370748924381155985806145,495794563709904959946586644094587256,0:92916051411047078205447640432962006059741039970472932758203488120
+lcm:868633158815673181555237006,836615025635832190680248872,0:363355776215354156722969079237153819583812159512078616
+lcm:945386362083356835627622353491,8230893874122803805176630038821,0:7781374816351144698349349350957993282560652485452042714874111
+lcm:5596932048341890824814087121,-2850793263280920843358756089,0:-15955696178454147555303366966824500182482049050635229769
+lcm:92079468846004092188293849,65000203344267255501708018874742834,0:5985184198822387758738668838849529371861013959766705099028066
+lcm:284485059147524530505559245415623974,-52174853366891975161102679787418,0:-7421483123046841473739983029315899581631043634755295287353072179566
+lcm:225019940499042054289943285,88057001889802818516938839002453179,0:19814581325767463952213083138864703402608880611447063777953015
+lcm:267625311635136684363577960127905,2364801628264216400078340665206601706,0:632880772719489569595591177205490383145217286350462293583250151205930
+lcm:-43414374537943144129863577734786164,-7033210862612719519352562332,0:76335612648449696783117174288123936538806867445493650875293612
+lcm:32883132771659855270849300682688,359989040176539024964573548207106,0:5918783702233763351390712750327251738350635067527850802106390464
+lcm:8225754994306229461538669946760,79816684330375527507314556065816,0:82069061219943782694121246737779709549970645203965267471994520
+lcm:7425838080456254658426507595,-1772612320788255147892065709861,0:-13163132073595363322916797538873046375619972048032782894295
+lcm:1660461221569443640519526747903779,1120888096894032723781619067526671,0:1861191218611314482654724970474950053651690424934372619599424189709
+lcm:-11718764104457037189982579964973,581785925357694644406822708535571,0:-973973145508581880509230586205500094467304746237860191614936369
+lcm:6811677000322905212875962023,8457366124986245338105030092893823455,0:57608846316878860294885890656152159404437095902874498977846649465
+lcm:234277964462994083732538315234,60350281492645017737168270090,0:7069370551432789506447807101173043521312584531845436775530
+lcm:4183588612759663468880479337,-629574038019737820951243554610835051,0:-2633878776348494576596482359410905898287329191507888206720841187
+lcm:2509727174403533842481294816277585179,366325095871570289922697736369296,0:919376047774859744204436335735246570640422606903982773682501840263984
+lcm:9652053493694317708921453500950,-91539642994112368354952933916454,0:-441772765486426429307043005631104317228468588998611266554815650
+lcm:35148593969489612322148628595,-82585065708416968121031576511657,0:-2902748942528768024032450841226352229253814757005116581031915
+lcm:2800741702103544119527140802733199,46761480207188283686223358035,0:43655609222787234193883724749974391389581728627052774652634655
+lcm:441336276433669766301405280032,2656936104993980830437872804,0:293150571825055340462835975394089506580252706417004262432
+lcm:19746122571650880858695931178058857,104545112367422664420669962306,0:2064360603074142331524120459909153582079341868724637548439444242
+lcm:74432478600289091913597803372,1021411507303737809729230605483660893,0:76026190159474490029899083115858462446496838080724392481739931196
+lcm:37218119790882940825047165121,-9786692593914842780007874460688,0:-364242297316869514078703840625474873421751340567491159263248
+lcm:68400175404962139133336849460667620753,8111497426974768586772111911266,0:42679065138613326270921172084657529459737080671434543323843052007946
+lcm:-36411507888779255237781266679960702586,288273015425729999064058691683,0:-10496455175296151796260705657513107808386313037221881095512634792238
+lcm:-93804297004149089553676142929158,72597578405766612297542242292431,0:-6809964806556531666828055851398144826196098989021186645152603098
+lcm:-82026709713179475197473688526642531,5827788603588390535677091203646382966,0:-478034324056320484117325267961249121989480834362662252362566162209526946
+lcm:545760067487517393173385480028,42151112506666653978439280505,0:23004394006312331510547051427125022225825594077610367254140
+lcm:-697412421088675986809554647004214,6926944054264140642234974161460,0:-2415468411815081649186019052688434218369772793280624742868196220
+lcm:57812799959867792819685059219,779735108345604313576941265627654,0:45078669840470262146069880262711457187904686148856378194042226
+lcm:1472311567166258003445083977221663144,83378953824849274359711951741465,0:13639977574949655229291079317010538142583886970067850684854934118440
+lcm:570337459673916278308389115966167469,6333660822968779197930730584647562275,0:76857957961877010509843395509780188770354864577206186663499194154396425
+lcm:-388785693105293562593219349398,820248784628021659491960244881371621,0:-318900992250380064850834487637248605290643186101012034699480634158
+lcm:11679788667362042415563834445557578,-5819547639993570526822921884507,0:-67971086574770424077123666817486620774164160205639229582134644046
+lcm:-3982959591737356792197606403519482273,-333248358612381656382679653253,0:1327314746365915910353403610458733118195746910957791963061720284069
+lcm:17221610285774362123428353448280602,11458184790118982447972303969280231679,0:28189770433973774114920757867056877758202824175213356039046635823084394
+lcm:772738633297996807166456840381926971,785759122171938805714543081571173360415,0:607186430168577693296664258953260658244617930008242877365346151059192252965
+lcm:125784145401376536208808801528812039333,452055550313139515567680226389953055,0:56861421070087227190049678638474498681709153815504817562127254516683512315
+lcm:32903571905950760393177782893378791,6631740924411766007832465757451477,0:218207964368018909275497254276866261100277667630506488424913763424307
+lcm:8742677352155721160009371273251,25083360125803108633092433384973055,0:219295724487824718593455764107115931859507036987734897375677251805
+lcm:36273669132247708836176424212020,533102320793846929600697481505030771,0:19337577198109381261236591896304826004083902938845516133439528067420
+lcm:11965144674509690079804137520044857,9349045655011350274674885782216185552,0:111862683830807014974569906953845003630437520055543213513177982475306064
+lcm:3321305668226664033356712162893,-403949753985171409898849824686029161,0:-1341640607589716272160331793818630136041627867704613639659980122773
+lcm:7395363159337411027760652209127419265,44729331460301249556947662501414682,0:330789650023303701714182934884591650253917627482713804287730858240648730
+lcm:871058047335719958990871843414,28094200616974302760918376942978068402,0:12235839765439807545562104355459585845290919144959079858231362602214
+lcm:7704699734056436938779166257084,546898541513497897846722209401,0:4213689047354900490455012376163453543698919981174872047646684
+lcm:950290435067652970604023856243611,4001208123591666075058892234775,0:3802309808564151732408385790073534886035212910698424588605772525
+lcm:3119293215232541154035748455321571,808684220462127868482572087900610,0:840841067384377328832287433031234586779556451356106729978612352770
+lcm:432360858532087298548744564083197299,240846574096518547683557847064319535,0:104132631550882737065113576806715978014672912813529852776264204584935965
+lcm:-310788798729818682147559678302,-2172955391250831365155305151397888,0:337665097870164518242716524072816191896004699076265879441113088
+lcm:649283478652713472152371045373000641269,9179675498867400603641823155076,0:5960211640807708792849652271953975864417053692073644908051640832431444
+lcm:79980532708199255123596245351024866045,35273005660545430889304120342364,0:2821153782949751307464444766122322349363016295719088889624882638630380
+lcm:-83351007958684418946822288153831314277,-51634644710916030743119182132599855,0:100088364703334986444002041507106189114327438112522438638963055385805345
+lcm:4992915740405389949821656927954249501,4523923119542484578579105473053048,0:1075598426283215515120154478613079151358480623324833686397654095263288
+lcm:-801991401381703662108108758716412,1462655905419442096496214673085035312112,0:-293259364831640743777507251364478142142085309047027174124191748729195536
+lcm:679369055865583831572651301119431385801,6364653911974833953564963906049365,0:4323948919089537646576384302944771028193868888345656961053886629066066365
+lcm:32178714589413433072024739357148883,2182815001928827996341206621079833349525,0:3696851628871457289339239307548138692732309404324005056784243872842227925
+lcm:604754886257955637472038235002006997,75686581968330008368600832791867,0:4161075479046440938277498574104870338592618123335252527305070790309
+lcm:287068066584060661996114628597630371136,52011890293701406927883275870768865,0:14930952785995133944874986127466642449246463907028312778992290363623480640
+lcm:3979837024286745384581666788748758,7350136706945206821986896298939283,0:29252346199869589826241656345690372038181000414430037048634183660514
+lcm:7385865195603313817759905903511277,1520983986703891701713359953638,0:11233782690466247146504034010039435409908987896556224062130175726
+lcm:764457193068206149728854992613,27858021258550102776458498820919,0:21296264735745627187463264202183322605488975579352986954871347
+lcm:-4155789385717252736363125208379519,513716864065732253356348104577569642,0:-711633030316107622405824053747853916334740454203908038895636729654066
+lcm:97365354260983249124725672833811771,5020029690975786355406829440294084209626,0:488776969262511703376009046688465573304498084561257966650740834323390307646
+lcm:83139160308299020652846789174256754,3913486804605023733190361150860684,0:162682003406234977077539172530366012958142362329068266990181550029868
+lcm:-17691166446369130975076403772363811082668,94600134419678935394632555907142,0:-836793361933716751903610096654309723151466648559815713270120684946807428
+lcm:634823647473707443708903538054380,3956996255499668253479385484122050809317,0:2511994795956101788922355113644864677876582447280810271598141786556658460
+lcm:-3637804742599340390876015169076139565692,783241759542604459838225899706055858717,0:-2849280587465938677344529171806295752584262014073034029610817921718004492337164
+lcm:585812248650822285457691267576462,21534520461947113931625020852108318,0:6307592927715191546338604981717905869057205471110964228553485605458
+lcm:11281432653044672416448534028211038025,711109480140515578563170257201359462,0:8022333709146834455095073412796362253303159149746025747385289864175542550
+lcm:676293649029453415159585825583394,97280549393475973449516311017466882903,0:65790217728903847286239146189723168106268785797184624412977724659312782
+lcm:-60552656313655809329731693060696763524,493007935144068742422888317617165,0:-29852940056683907903878516926766558721475796609356660329816267168289460
+lcm:499127054152037037035927375386500,1203956412395744650060889503126393,0:600927217446543074982206780295985557213897685478460386666725894500
+lcm:50094686288665713475507184834256049095574,-832478827433992238527275985275884802100,0:-20851382851131060794973993277969178760786122158514529534407995697925158487952700
+lcm:3587136855297236649460183411772356035310,-712398604370738955166219235841134498742,0:-1277735644700296381952103446442115125860633433942353227167692631711417651290010
+lcm:-8101551106022390770336067301182994,9185799272249263720169676176910186035467,0:-74419222253790694721684461955969753328255728462706287902254787547941248198
+lcm:68680574795029722620883183609775450677,-84158462638889794851250260034014551972363,0:-5780051587904985041122626676950144438458787116758152359160332249952887573639751
+lcm:155258118178686765062886673806448566,-6850017870177195667059084688029341396610,0:-177253480669014543271712665559172404205382093546240559566299352291761960210
+lcm:285166743996114296479394289968524943,559627723033455856754700399288311,0:159587215627409862324848662934458300983070878875254327058667651841273
+lcm:97635198013817214038209538637709608537616,-43337611052093405089732573050042882425535,0:-4231276236516932968241697386864918819022381398914657632453889680479868318366424560
+lcm:2025635628106428290541842218677337,8363403252785996217814021695187802,0:16941207601064506909583426911328603088283663942724754575178256243274
+lcm:39403341320445818916772945982544618,-3081545887974055895915003777735743,0:-121423204418458019221260007112987567988534380636151689137057510881174
+lcm:66538675039876745133366881210395320367369,385523580015310377616062750074359,0:25652228210848657783496179630561675959121693223651695460689142031947191471
+lcm:568797587304724025372575349953868,-809993079501337508688725757864677957,0:-460722109353884289924314758764698126555664169725436270804746626487676
+lcm:87438670031005707662235517162074411507878,762858503307630620547057859718065131261504,0:33351666475531395026558166505559631395861641079699397271443823762152715254487064256
+lcm:-135539991676075663249711183869449098,3187117064807540583340853903135708355720,0:-215990910217346375421192415314259011732701914127161619020473509115908570280
+lcm:3623316226168035106420698863103708,281527696822113339094642926844583498510,0:510031936005639216824268963288080554001943557921657188124458629796737540
+lcm:462743256592937700094228107961335,-6269566498572477078237555404177435,0:-580239923795081947084080072036122971178457338970051983328091895145
+lcm:-685484600842741055621576203380446857767,871551172534175305655069705808532,0:-597434907618612100896516584776549623778036010575252420692205107539068044
+lcm:220964518681325411201409247135357488007,-5641829172229111635876189209726787450,0:-1246644067523866218886679493927269969586873926750864717926006590010013112150
+lcm:302531333113895329527974519952510,186535245939488501803212618851457571589,0:56432756626801787093558631197271214562205468328076903171812192205238390
+lcm:817537141270922830542026664184986,7821981713799768623509532856543951,0:2131586856457765504425364967419253491712890096440257591636701106562
+lcm:8468979244486855292413811013010058,-209488808243349961649691393540068,0:-887078184482608830617084669743435658018755140226162895602555001972
+lcm:879852422051274089521663230058530,49497155404087571445757965616479604,0:21775096033467380006952525371180650761765159390311330589646735611060
+lcm:21764922287301916637920770938954126,164044760066720848860497915166650797335,0:3570421454491268052799273529790558940088345201564664677181891708888054210
+lcm:59469732179854673335933541543666124,33859516881008254191737434099260638598,0:47943247634591169393256397833360901700530080487187711490425670722367956
+lcm:5622782096444522942366700649751601671560,1818924766888381565955786591467033096941030,0:1022741761403951928879352842728218349531334767337439634606427252402319167074810680
+lcm:-83658234598433632746857009684831849359505,-29016349811234824466750396183186748,0:2427456599698498400779164525993522755993904434491695109250156524973603839740
+lcm:7054089120269602821498711515003074,4095832337673576318592596805192095781914,0:14446183165815794387548075169511726311756130919745539387698300521071801818
+lcm:990394898068553803695514279851854605418847,-7739084020331097221051527297005947155388,0:-7664749329459790605184280312841813382942964148487855083039273635724968309932797636
+lcm:54075935489906064661012070011939942732,7918292813066039667153314788962651008581,0:428189091349545982631162674290883455991732907828213951097897291399359180583292
+lcm:8772115771437424285869834799732506658796,-932849018789404004804426567212331569,0:-8183059590092457014103801212671744691867340048481623621821910552497102330924
+lcm:-474373401937043543973615567508636867124,-23736477393422078122335330115520892673,0:11259953531119359125561737495585820068714950649943932579707916447562566182452
+lcm:8436352086792195283692976718955932574,-24226347745891111460405966918193715809620,0:-102190999680700937261627650760472234672389538208298360366751473305837270280940
+lcm:814519302031186083731939523439915121,55324835095437197264275880684820442585,0:3466395851301998018482796204627115585152729004909209666935241139850294445
+lcm:-237764758709584162016066869681905512952347,27730963225107998869867496093972168,0:-6593445780002155177144945210712636481509108047897422208741783636396128278296
+lcm:7518474854158787395750001309747813,8381114315785290417935232114225100106214,0:63013197233061936586019793610222181046567760778431006705881553819854209982
+lcm:57926271609377407522025180011097851547,-460438760475654775684236043340437433561,0:-26671500698797845620038488129522785806400814035581845817517898599701653568867
+lcm:6638349918167655693810387712273716693403,55308325418124425819340246954531134649556,0:367156017513396353523080763860964198057435071526450849007117311720362229502079068
+lcm:-792096039638367514268257857215475476214,17985352918594429617981644232595132,0:-7123063409158501091874013108015475150372207113988264273740643324379095124
+lcm:17523605051927467343416676052611136060682,32818776862511079287568864844380549,0:575103284025979425337961066906823946761256491065774387656701755680364474418
+lcm:435598204136143930685119666237820390,902306362378699323196514142749053448065695,0:78608606206555625579369041525511439839013315758266695141072573521539666104210
+lcm:7246625600474134146152993995542881524104,84045078681310625106949990828070364497,0:609043218765848459070950953243439359310276390319003636791153856018486171335688
+lcm:-787638361574460696958641849383712843152717,-98972482600264920015196417920239935812005,0:77954524036229481100840641198098180090516196148063542559493953965332234357616967585
+lcm:82374608290966933640517911377351376793038534,3375365592517566879211534105358267232412929,0:278044418522442081159379773928407521481969102832422171826378968402371349113290496806086
+lcm:-65869507968457359071511077346860349916,233541308077986424091233056554170108328607,0:-15383251053406881762895333316227673851604711244588922960984017463587249932847012
+lcm:434965647854018848199731601803786298508849,6881642201690537465635377223216241,0:2993277958557881269328249998872265799210459572563672559065439071522179016609
+lcm:719612999193225374224745692059996056358,-315519530953816852193901984099603790510,0:-113525977986857927473880514812648272923195988059593175472980415910454192781290
+lcm:3371856558784507755414140667220962994794,-46940188151078159734582108552804551252391781,0:-158275581287791729316741990876515371668219778704190560942981767461139678285151388114
+lcm:4803433840417804894873156694592939602852,-72456645795090954873268375616538340122311,0:-348040704375306339795449754303228838077133852627838127804760032434988381444430972
+lcm:48568835567133010333265540506612310476167,-10706367926604784868082114989212135746648832,0:-519995823348494578419271225922535589824979430677892239954987805560794580396454386944
+lcm:-640514959144433868933444881224466486263623,495227035072426375802319189512972514543836,0:-317200324136634298803490410310491121240672331811889843420769547754733113081885677828
+lcm:-6488859550432975345382980598094012298,1739553070312394609661279054142037504040,0:-5643857776890793418849823122431638031104808487025959819767412990038492341960
+lcm:62439762329215278757554454849955204768025718,79602289985731119990152260854511851,0:4970348067570324615570705607275557501940237030878572771873031709232361903784018
+lcm:6054057220822234921996955072468282902047103,-41461621564455176604944655360416823,0:-251011029419288750464457350960394818104993744337372045669164809905502059613769
+lcm:41593335543156355768394832800525873230,751910447000975730197547607815241920,0:284313304731966064820099773565043464563065151891136193714105004651834560
+lcm:994454253731718339598418586069934146007,674502407982587721309172287657440910774,0:670761788770571291425639315014529979293655007270270606543282922218043975379418
+lcm:467599304203676521904495847137440151064429,1065364075426775111107441639016359411726,0:498163500393153194363286906417357715847233221784448787935167388300077631164094454
+lcm:-50006834540638623993722097585899096403763,-5313099491095445109561808031972399857647,0:265691287149161199757555723574229252417144350517780818574650795718178070835125661
+lcm:80633786527554906657368596063180401716797,60423064130048311342811193512905633441,0:4872140454403075663557443919045087358815687394738194780627830508431609174608477
+lcm:7515721962363288712694440724080300383839,847957688242291310060264069657345589412622,0:6373014220677391433202574116816230429840218559515683152967957040454035241151415858
+lcm:27726212382161724111674518621229053817654,844465139764626291093420179330707907,0:23413819814445912412285655292812080594927908481755534067419056195692713990178
+lcm:-9817131728229141224738800156068771165515,5514447437310670168515402768125807553,0:-7733722414353494049116967432808422342245494692973084146482292477938628590685
+lcm:1101490427405231724327190816394483390794764,-1715150116840413365727028822839059671039358,0:-944610717631340024199197825772309008665579808517055858746594565467440593828772160756
+lcm:8714614705512806124985108394035361802445153,2277516152797095323407597912040972562623326,0:19847675757208518019561453963926275072330819370134031638574421823784137713762913438878
+lcm:-40241069975197162607015133362864260639182295,92350494843755720369837991386076354459722485,0:-743256545050331739906343199965798133902862257044301031935484830446583922737000605080615
+lcm:94926798565178929705057494111757110129555,654944641739167114202854904453615515658738188,0:62171798077717196972382133382107571708777354355494810646721424261049356268684505946340
+lcm:265280847975099333384365084677641815670787,79159871617113409657206914064640126799879245,0:20999597868187843053561037716605216806384147652131248848290439305459650098340274115815
+lcm:116347226264838928071222153238640922289035,68573180747149861177662470447052670907671443,0:2659433125362780479271819825899011059848120776197137181515334033569979255463087175835
+lcm:1040609825768545533315151293676302487896884,-81323728160947963681253577857302080515,0:-84626270592412620351087782103887368619510384932135633101731317980537259985615260
+lcm:995902591817252306534602024050315471330353754,5332558356879676808399004303967153306,0:2655354344316609212808731137647072862609841217315610320176187816399151656665305362
+lcm:2001969035383918099033090062929650143669765948,4190101466247488888803682714062857957220,0:2097113347636056547892257576607870417625666910651072024691458074358445968441699186140
+lcm:520711239532941932960582838954921846930386522,-3853096594619017503346777573808512971,0:-2006350703824226084150485654917370322708059670415383459171549901585565143080576862
+lcm:60199373689261241651972446393273631317362,4966864098864732001544113870901038040,0:149501053975666897103050547412658552280636970592772990519302688978409237225240
+lcm:945149245494027792287917914515672725163081263,8902933189066222709145663761457459365794,0:8414600586329679076832097202813182563472890369046719691038445973643576962794864517822
+lcm:42113632082774519107063284261972952560637120,550965713086089226514793739995356299364345,0:4640633466226213589957981239329763407434377391979443407814888806055710449184842297280
+lcm:699130208513509445029837360613055447835,1388996167624703080432361535173321299212301763,0:971089180295924181746449876683106046223557368848629195863225292564207370057125033105
+lcm:2708864861499120155181972404884433662661130826,-9669434874243213781569557549324652869447,0:-26193192361391605615558952560977409140576479476697591006776382263831361618654765273222
+lcm:-2663320619224926510783240759799877830,-9288856838720796348912703146202293649985994,0:12369601973796782329028816697760192304592616771255092738637656832851511205556510
+lcm:129339208558322679510730678747389994722,12274162664070343010820636150243461714,0:793765242343485804331099446227740401740373258846764856738702670720734536754
+lcm:7927826382521640149002540477963715500150746,169024688202278131082480706237325364215068990,0:223333063737919130606048178474544752216924447740470128636366880733694566431051631661090
+lcm:136906526225769628858637915191370345692692,539213183682016621647404279498623014328141,0:73821803873042744699575963663268898393281778327505656899589792517391459419633645572
+lcm:30681142365936990868501835461428152495,-5027491490146180677917496407674117704,0:-154249182152711677657936575800296045756593757870287279358854312185891271480
+lcm:-971981137022757867271162004648718096950546,4334305792750860480761829171455584581712,0:-2106431736321153641881651019375387709927826224608513058301342860436792581080007376
+lcm:578802014801938809246604894083179003839,4755521418153118560811649969223227339815203,0:2752505378260798366799002210776469662264057939931455802132200174149940527887564317
+lcm:-85637729865865539531457719920611651870241486,974400175977421869121902925057819107693817,0:-83445419051606298238772725013236132640041467317129471694684769066837807060528339092062
+lcm:-168964790731095355351979412256338118430524648,170138331609580398941494555432555720911428772,0:-7186846898937614525591235743048196241372711495546492763752347187132124897827551810593064
+lcm:790938498909251314495722876378080005340582079,5214770204816378474402582970231763702140978,0:1374854172651385139955310854649879453753928013886594694727948344749512222152267012777754
+lcm:3097935765451813281781983641770574025792276,42609404056306319259222360596281494320705429231,0:132001196770618914910107580782114196079241607233335405092295156225025350707315539424419756
+lcm:-98485087154927525975034391790808080098982,19775664577849930783360381707025488283978,0:-973804024748081746850819013189941767013339940621603669747325245218966911782355198
+lcm:25900464334299058097279910365875929228,58255952834922520501042331752256379575,0:1508856228661518846300670852569471328709790883165326524402490612694204718100
+lcm:79400185595521899110261406600117591081721314118,201740226840130845073877991057259510967,0:16018211453189077537841902603464990449906833086676810898799136608951219916977272932106
+lcm:981167299738316185980724229187020822277,8133607419206585086507618470282084549435045911,0:7980429628634459820355488852068596406179426323528568158104015662222056961076466559347
+lcm:81466412463591236560961446462245299836549126707,866192944729287017177690246604876328497,0:23521877236122927651693163907061883464266675326601201698284201208926249964967269289793
+lcm:6534998388738554052417315288897046254899165842,46609611771478693989087838979597248775,0:304593737826342807250457708401174251945994165789414852595908172190369819865656343550
+lcm:948084924179221265735435784532032916982,31095014697784883179376411641933005719333,0:29480714652101151829666949589520351343767111464822561182540749953951625181413006
+lcm:2750322192684776089555518232723747026,16282797711115835147148988819960931175880625768,0:22391469951939378515729446954104603778487035357551482666768260498213644003304482984
+lcm:-916832268194684002726682872945582785046,80175456371164380904577325966825746198033406059,0:-73507445518318567912336331397416597212835389484585058461161628079009895397414630993714
+lcm:282231592138255672195189656428026230056,96673996679717919403145753072968455552546,0:13642228000642615449413724806392411795013641635130782296987254387670532396261288
+lcm:550580097204590201609373226827993784219420731,60517713169991893657707958780297059239491,0:33319848399733645437661395589377990023027893949147177182635468091834964459423419287921
+lcm:31526794192792048622410273704705620482050682,70537996848502378104686898733501905256490,0:1111918454707274300580233711800474352600757530537587705043968883837787075495194713090
+lcm:-923613180033278870451470473112995033306843225,62635452857298067541908563173475507759656054707,0:-57850929796353591491544159777994055136678493390586182701070726329142717640752659048072310075
+lcm:469196843768624413897755875308788890398465291232,-15296277161521766221056511754171865009042943213,0:-7176964965596105854796051880140430745806790021143791822882675477990460153884190250962482808416
+lcm:2628065716223500508449356215564412668664236,713708318009199991674271791693482010536664884,0:468918090485879510666557537656446407094985302907396727300429235150492228937795661972156
+lcm:604553604369312265623368647573085123221252020,990982890678004704551740474471789043760433700479,0:599102278427707884215998875763263404402845043498163599628915781601939770631217226224053717580
+lcm:97586462652371414650265963064033775148721243,969409880443270812997088798402379069080662,0:94601281092717085428971288705993159426354381047162321909314102361504796669908919902866
+lcm:-765406874969209688613302257358735487317,687488505077706911028822098735771705823765697808,0:-526208428248781293790355829561494931467780389995278558390525263117575307179181438701136
+lcm:85075624707999635862443444914978287825359,778046486301986342411165862027907781749497,0:66192790874005569505967522431892177262190586520494284537342391004284567008622094423
+lcm:8227248806783006644129224253415431417213104067,-96883503079217553138854609209329008354340832050,0:-797084685105450364093424636607878440722968607757607323583949926033112024630877523264018947350
+lcm:5027554007771258456873599804445876368468,9124875242153734630106913217321584664013715,0:45875803094102741048036279096734905134493820588179489085096405521013297169145538620
+lcm:39245745484403729199058188063461104557810253,220067769421357576954105356315871937975114,0:8636723668031045203182769468262937482316831571209371261835666035163932603354648043842
+lcm:12265626358518464602956912462337886264411404165,-62808539324142868756473505816723401975937,0:-770386075474250281180131471535743658895165686987724121596740049447065305055237711577605
+lcm:-12272356051659726939876917766506363796290,17656166644036956054896242696928896080969790493,0:-216682763563059549497954402078347159387989008283715984882662478463368364976841430670970
+lcm:637223594292638303876168193085997138882431056,94504571343119776477559774058446419793557358444,0:15055135657086962151475550300387890956134219709831955986646383218960383823718063770077359216
+lcm:5571012420064356266635359647247635200655740,-21295217227115690481188602248443089551209070396,0:-29658979915057488281375910245844852139690143598685009046127888233506587535909343755368260
+lcm:5263843748978600609740419748581371970418448276216,5384845751134428162699702180820131424931650492254,0:14172493323161468463600107052030558175510328324645921496255479072988481662969199337241737080215432
+lcm:886573921242233631853410597832339291851986573,91564665302299543163193474542608720062467,0:81178844364292397724319168352869382688643286956887488649289119221530204376834605255591
+lcm:26539751625701457124278640373644598585396,2325338527842485879693477585982320189921160388553,0:61713906974613847646349243530903967347131153357438117664659209426320342893497093511371988
+lcm:353508003643539157483752498296868928280378,10742495675871104458509832622060247315860,0:1898779100263273019527576105561544611151524288153407344701797320631121810003097540
+lcm:-4734613561112436559828705330418786656799216681,5767402184612349878575526105980302509419976764,0:-27306420595655124123966761566392172844463942752586247604702902500841784311547866248421200284
+lcm:82083010698635736174070971617820650592649198695,632174562080517027772509374721051956918078145045,0:3459386089510696037697607329475150733631394015157940860209532577771197095497123578020748981085
+lcm:6173991144338684494350090118957116722781373,-738485502817232028305101940854863776286515,0:-4559402954616091182455382994371638790076884277447195239272169152306248043072153085095
+lcm:-493513047233893983448577482415236886372545860,510358065314512191744416886029069217313650,0:-2798537377708440066088399588452377494483186344049452196318380194547765420639340322100
+lcm:326654054139623246358073868314669601484091,-749350879522921841553744544029160051092161118734,0:-244778502769254807928944561265310682694306143662100245399456722534220714864996773263060794
+lcm:1402621524995633967650615579165227953957890517212,-4307813373241246419295301377872133252586,0:-3021115881486111596495041468952452755324614644604079117686302481886685354889693688255116
+lcm:429404746005804957738561594094664667352987,378882853314853204091011966904771925997210303,0:162694095393619197081345508962117529189396776805991399292350948184192266104441374225061
+lcm:332341701384724523211310134953299492552149033413,851224516641538736779656410258860743437969813415,0:282897404121038737349436193561640178534459124296792792204901752510516940857699900180164210635395
+lcm:8093542646198882950722808884458624246299608906958,-36537804019444103265563497755234936603188804846,0:-147860137514913904634692391142170680202258776956700982397999849944457772330156859656606216759234
+lcm:22659814113479956892126670971189905912120035824,-7769923990496178313173088170032841760727,0:-176065033300511807783943084226119789640585676482818345603663798333554090985834476284048
+lcm:-66431972193306385702365512934093484764859082,36581996652652744665199423002405565247156,0:-173586727457475315287286644140245293266784314041722406717122380794776682723917233628
+lcm:-888473800362239868616054745127669042022317,142999759078860850560633007783677610020527766,0:-42350513133226737836563925020363583106497633262140965689620958730476127814149430051274
+lcm:5971942663513046812876552589351160577576206860,5155119487765712370432570496238254289228130147,0:30786078004495581876769132581215368897074670048309664867385023649025961965929287514674208420
+lcm:36328343589972083920724771391132711614346,626466814451530915421088090957480792070888316,0:1034477349232295636348590401427803652375984824843092173570332762552453722767574062788
+lcm:5293116409600323220539205506696278195160522774280,-89478075685508708042860880549625934136374,0:-236808935355212916308616284114978382722590502180363697942174473357408509364368655169830360
+lcm:79576614103508536656978289576589750212587261,852468870734033057111244131505440601392558836846,0:67836586361655850604287977041894979998590061103440929502231721634765812139562797406437018806
+lcm:8225066772418695359596812838151452668642167,32895491347247919323385073727832554930053,0:270567612842635564451661105276011053846580530826552326236219991362408128533171344851
+lcm:6163942593967174125699747500635651388266851958125,35785148285967657728202559017385960485415693874,0:220577599751307459197829958073417379960145796516327396960366172323789774042408250526882467026250
+lcm:2768453763718344802615194690925869147682838954,295289393573622382700104229276698254424111309,0:817495033025002504068133964169976601685138884223266625508984010676066936521469461617130786
+lcm:543530772918490900335995207569824317804903920459,3816523263571207729432080444412751436592123632,0:2074397839310259902661375133149465196577634869313509399704184579022798133468044005917222187088
+lcm:1092477340633785505464776554395206472561372312061,-80145274095041381989361699268630409045305877,0:-87556895907716629238600642139851536991533588781637223712321645442750907264691471870441282497
+lcm:5221300639042222043517187865188827094681806,28716457589092549537459686031371792838180039728,0:24989543060159632642010593077696572867622550344397734652621919451008087743078495099798128
+lcm:-468871256127286679587501070578429844680401783,7709908112767006788780052051800778651016113933,0:-3614954301459024712014678778499413536274302047069226791616378154943247688691115133744342539
+lcm:60187668034435065431875732180204005950423,6575730301760601160210842777500398231559661,0:395777872486342581314679269175741080629857948827943943881264571589081297075932686603
+lcm:85750547893356514086330287277441673045104762,79743140579005364490235586620393656130064,0:3419008997693330405464249977225918848757344180361491250868746891061450981564188882384
+lcm:4548581293372942515724176487253593549214930,4238661184062900689214356649238748109095650,0:1927989497077451677556406438992119682437686855444693788604757451990503919504977805450
+lcm:870890539340345883811990618518239041519315472381,-326492148393756245001717974027772662339968,0:-284338923205026619246910784734503794029639825911870769385331694156076881647046490736423808
+lcm:66987553698256227716875714961629477167428173612,90975165679807773385648454136069587671757554212,0:1523550949045970063245867032701707546441284497509992114155614817828087572926246444944809463436
+lcm:55214217278725852504312036656428464058159216571,-38639629611220548541845337991516346077285504,0:-2133456904923420705886788529419803172916228952081562524788395230166386012381289930934886784
+lcm:891217139364757949280558543150622433360536923866,30525879876993440244467275213072433106397646327,0:27205187340566323080358381531226152260280933712987740283334272666071747659070919682319193540182
+lcm:-27569366446500582408824975793718887457276922405388,634666021153562229559368735956062829411322343,0:-2499620015475006770093631859600965442502552615908591007003664916282081612538456035180769712012
+lcm:502864235446447920785714797929749621810588808385,-661761137717295415776353819805381820532626437501375,0:-66555201713275857902811739936791100923712566713387105483008138592982591252568436643492447609805875
+lcm:846540274257645306570757431119674434472851673,8616613565185012233547219046445322085886975,0:7294310410643867160484254450457795378883045914986526511813394090546583372432655817659175
+lcm:-3309007371119113533010968742743901666008447,-54456422219293958622124113256532150483182055,0:180196702528418384342054817105817441009885252753576126005393548812004572770935068818585
+lcm:3808438337556464123872249539607274641406985997532,8958313515020597801994910602927304472155060964765,0:34117184630454650095284221741033298990688190756311433174116017572873358206925691228892157828959980
+lcm:3966980856734279836284487724100931405197679196,7991199588345191911654938564028578389298180118364,0:7925233947327058439656989443340159765395723535993677440234885472317622785961246017870345088836
+lcm:65639444382189527381103754239686068124303248439,57344187472963481946737524023690750337279473205806,0:3764040604273435895633212274119116479837782295002539485107922790189834206416168312084346995236834
+lcm:415167227201847402226579925485934896345892,586575228633844519664975226407615633553394085108,0:60881702804300728422164607733352957690389009263077497409872743056634977203755428913544084
+lcm:61619333876398280418219395631027787927517659829394,919912829682211281138193507951318719985265,0:56684415789370483176959265833922690931907142380410669255035534110985337015940545738093879410
+lcm:-868753784405826481862596863379498777711457154096,545880080147628730834302628389405153791727839,0:-474235385460008330984602458660116725933386690418517481411723635621365531412330794841516078544
+lcm:9429941770445780812848883836626433106364646270218,13789105660912116612159357433833332620650429,0:130030463448925543470092963482754387029792169816829218586198208779745648441067644420051623522
+lcm:43608475425036256086742701999180132009804867174088,26543470249142438881834938827109299420258184885237,0:1157520270054909035662868646857940204973664076401942399990577391349752558661122837219065938780138856
+lcm:57684506610503798187871631196324475714333617510881,471695506003883133237678946411955700467360,0:27209522534225930626068350341042360052253774045631066166444663548471852016504199451585344160
+lcm:45545031179301366913301053296868047362176530184,-91968879037454375774626628433933013352182139387,0:-4188725463286255430640627639956152535588659815635253627540812068959602079281136816961500757208
+lcm:-390021533721654785753654976920878586915091,77031076759836910371783959035306703983828680,0:-10014592900700703269560078738266286134110215752142363776248874904012749586637416869960
+lcm:423541795082126371645621560317104281087986536944,8300998559716429411460238557591751288655280830676799,0:1171939943652147365555234596255224305456012312168414340835337509553512002426738855055186061245720752
+lcm:-22004254439719621882091733525180851819037175217519,99335356922776842325949741933027888097618837,0:-2185800468589145609464205476226975010639204222945574205629223171319215468510436674371426805403
+lcm:-568617824838411255064542027229734991599889058339286,663945656360600870466864889023341282183894393751666,0:-20973963051704229852295393571808922528386258405366303052934095222591753315525189202845488663836430582
+lcm:79416546968775553905606945911160893343240489,57823044209535496953371020115352329847370545,0:510234056260462346114599875341456302082293607904671871750490172957566065355271803332945
+lcm:944931014689390846530685010237152128723129879051,9132010491010578008428313272813386452749469110941235,0:8629119939424787805155145456276331139041940822281098763310858175298740567987777487797475766318567985
+lcm:10724730362623743957337791385603755532922863,72480373654893123070601266938859686093303005387292,0:777332464030946381953104911976964384403745616151494866542937429270491850221347238960076456996
+lcm:7713352208339235603081099644445084271357860,603624463205826416829628929324533190899935786563381,0:1551989362092082286509226742932313310071126914988546921498365356500657461247063016086607508220
+lcm:-374652992235609318781751374140306949494493761487551,-8211631925711097443824357620157273567158306960781,0:3076512472105121389035620380499987642797429799314779956051883946663228512561940943539675904376737331
+lcm:148033237001979427358794216800322662159772216729882,-2761071692676096788505988250569937615812882,0:-204365190130688570487960579178439169815175152384146484286930819001830464147276002695624969962
+lcm:8799836897423935827052239970797993642793054321869,7294647877437509677171255169879966954414823484,0:64191711545589794049942507329622817162690486075145161653225201426081306037945865801824955971596
+lcm:638050122120135743843926357476168630346968836720976,-521011870575614667006902791543319211035082259559038,0:-166215843823405648565930328412825365823057474431930443033112986539191112250557243418309377653802490544
+lcm:-17589569754541719055752617853886490778777621596833622,-757763302557856615098419826290170728613135917189,0:13328730467773320372749612468589169429951770262414798041479922130537436948993914504659373603202928558
+lcm:-9391500830250456597029446286855934735787373415653,28432489383197015180933073382445953529667174,0:-267023747648382060661246943486871855039477521250741910116209365765385119618211444260651874622
+lcm:597671128380217947385553643776956963479914986403,71727950226724858021016384499343090206442916,0:42869724948406755644439192851387407923848606069058040508413206852418378147081162495135671148
+lcm:220524861586728547654066186650842017022514113,99830670175055229565653522851124444573641171168883370,0:22015144722464404290431089740908195479979690191563438782672166808199720494718314317705872276000810
+lcm:-19711747183549435340491469077888147043386014913558,-1141914280129478236596364286858351511269528735,0:22509125595197123566803201916751380078133670163026469768611121772532745591006866402480422089130
+lcm:-8382072953685010521572064715326232892979307367,8986558828596332338706049003428573784660004270,0:-75325991703876567601582024901200837475422482663143278160590315962341962045355062611862457090
+lcm:8502152308582607794375019565844324676023491104593,10470050208175536662422671560468368371690332,0:89017961548415452362336397742460566038542969501801207576446421265423116103719862689218894876
+lcm:594601725521916181847167140525593251441576703983,963458725567603941710493681498226412426881800,0:572874220691643607273440473752072791294210386705034629979437739545297813514469057230330209400
+lcm:7141961266638507042734562322157608790427840009,-4549724799885066646710284284349071123364728193387,0:-32493958294643778569864068941415075147150500523994618476463881411873140452414616492271247820483
+lcm:-556279059738139499395948604306347001411150129841210,96265906951839620646630096006130967227739083772932,0:-26775354102004285429276113769844676372118786237607285907901215316500732869575305395080596584428063860
+lcm:9097507009232650355633416767082868346314279788737,-12952310876092402836370081770801404571317963729609,0:-117833738981010925067125768441840140051091195908538031159411055746004033932320364747308545111613833
+lcm:4268792759888467657870170840963084681877952381149,45230992824683770972952637110379461673717665076497477,0:193081734692577312252243894972856695658000409843190512520961090560296517492619302198905276169040861073
+lcm:-14981624589272129153412283534256311120144659052,-3422881033749335138988900898217088225431538419464,0:12820079665343060974655754692608143432268798103331572831567462724320648718570784069585310147032
+lcm:1220927142068793741881867214403185329458765760024,30622524744504892825380221509502752145574896,0:4673483952404909633169042534451903822067192939697796248187569718957914620535643481481844688
+lcm:37912807996403481194979034824173466165481184382714959,-90878397829297201187948170371749592240094934625,0:-3445455247922915696812807051659782073986976942393793434021443082292576682286942256582247061114555375
+lcm:11421510093950565340830017403217629128966938056,2237414009357389011349863244579333296452235392013656,0:3194330836527727905955302104398524198341681114056770994737458183451820031389704288272506307261592
+lcm:192657988036570687555057992620686662908295387946910176,931495134488306662235768448970442482109561110,0:89729989238185994297883659301090589093198151954531577310187242340555592504853957169920465976427680
+lcm:3406199971289940059753501832956133340637816361746774,21717729758322757474808809344766892648120530501033,0:73974930479281653383172304844520436444384314366038505444774962096871058594711397484185935845291417542
+lcm:6909979467876024377878180024452018966109074368033,842722308262405734840545048662350517397572773044955,0:5823193847214313361590850639006414894786757219881236880655209757454129105445924052644535803723923515
+lcm:373077837411940479742523640303846004174658252010,174968689985940718533112057941120724001834591,0:65276940474755009773288570940982140032743912931132908824689438802225554298870445697213277910
+lcm:69447921082122879577796325457481062492384026062297,4859735149388070292660864796695584862286590039960,0:337498503134721348480339150893268639814027256856202938192556796481021571996594857372873378679388120
+lcm:97668956744134573191931364533568770116368809990432277,32650097939706033583832290610502297382443475332059,0:47595537363655312568235002972649323651425354794543144885024534520500637904064737938316663353067559229
+lcm:-1130623853521736649164698623052358825973875071086,97117938880122601762963490311393663414262844,0:-18300643050455451520453923979067578852655453746004433917321519890785213164382247444464754764
+lcm:5196766948376722446473792182397797566282488000645,612809465745222737408369151997835003504928829,0:3184627977237170791819733844305891092484494030274488141848280463948439552688134126307231094705
+lcm:-260800009832764286426719551521843883719112476,-4764630548313512861236355180550436291099515479440,0:310653923462413311921327308749420033511079033275390302805253842034181828205601401085106373360
+lcm:446884272848375074930942162217302913946161786743256,21042882325490620038960351129083746002919260315816,0:1175466645832599956073813923052542976086932578597582904412735700346940000639354255670643544083517112
+lcm:951599922613172445123982155673072679115439437787116,170174123089259663169419228763721448308107859122519941,0:161937682362503977661236466402707947708915167258582987092600978773889146161299886218655580651394622880156
+lcm:21383950451514823653827321489681070470148156716394,474049024111864801681311013604155672359293053819708610,0:5068520421598536425525321235142815292646675811310319106405942660104400045766803347060423723469744976170
+lcm:-470414357544256461922663993336752968654129573423633,9062081906619161788388889503790336651084511675587,0:-4262933438115683672713863671510520101815219800470041585560023172590216986734948687990123769014947571
+lcm:780091812513073375693179028189802313142318232500,3497278556984926411479728842600230671778387696053,0:2728198368381477015989505443597065418103138169441425077910216137727395317905388139191010186322500
+lcm:-1625948018138433921639232759767284243608022009577,842118879046315463699452834842435152085239651627,0:-1369241522422316177317692449844295269090380811960323302423745772493265931792379448342891937631779
+lcm:25026283351500865895404594716390919370787136725638,193605742569640932386538365909397399503766353419,0:4845232172025567337840956469216133356563858466840983726314706900481952782728859639508827146256322
+lcm:4935030558829975380051283297334807636335988292915939464,826975811338155401386754284486847375740824437795565,0:4081150900367009340504991854566589470179310873827349635534175745385923686159595506846989467997551147677160
+lcm:692976306506130156561485116659173381923120836885557,770158528298664593632506223863839610768381103479684,0:76243087480657930190487337287128939416904506467283930926671128904847462858452992556512523992854646284
+lcm:79877139216893064041018839082816187503862428735,7269106113282857654532427145534479409503583394410641,0:580635400993063264937521052415287406491591842310757481379039941960972027583729569639227998188169135
+lcm:2539745404867281753796678186777103230989134057269,1232562503892732555700624680547460824244298064,0:3130394955473278587381949607908298163614591827039064669019870794477245183817740184883281827216
+lcm:-12342369542383197426854745694214905543911988477283,900468407001638487525579769577535461149066925224901,0:-11113913840455339589057682433788692760910363591045622111658103604207392316252364497138359285304423983
+lcm:25508383419230789798346692675791795579961116333703,-3196912743165527117167038251788165837584914845275,0:-81548076010491152335265692912387445585857263580983374333387917442921969005827781555255165512803325
+lcm:-1299528036083269250543034346520127753461072609198859,600594652353551219594047525595273354045086799190,0:-260163196351708086868697255894653649721720334580389492055788614848359699200918752705348100836708070
+lcm:2299157394917175882710807816574923359426328448491205413,-72838172890838078649390158065336999589794176457016,0:-167466423834226138899695762647031472841630725693307898812516233189758231307075087592787449022731421027608
+lcm:-7349901043851956691882158234459042155688766310737050452,38963935506607940884321914070762438994955796523516,0:-71595267563149505923669861270167245818680944504703982056789830331584906867289180261861884773409374107308
+lcm:958387014018743982544025716556283287504010616036,1443504353635051762579994152447131178181054158,0:691717913601677162440619033523279055938959283051812778789604206481811449086596467058729638844
+lcm:246125390054194220242986809766512103907648232140291,244701030143825150512131468437935457382757506654,0:60227136490812102782907271910174306533407908424359655603867506529129414912591634812915769093996314
+lcm:-704660850546084071765145007935951186831012905395382833,5588984198927622386999113229239134076765551765835797488,0:-3938338359304962728083277304047487715370320826599483665593576088149516002866532798742909925478892863619723504
+lcm:50682657377075501007405908966255159073041913889268,-221227972486061875975200412557047324616212536548,0:-2803105382934039975715503660314214227088117486692399200394931533988665689815391470714606568741716
+lcm:-65153936048938235385603864221810574284616709045012408,2620409042204728497893539911547700871421142555353,0:-170729963157866373963111608067452447067616052160696883002411341925443387533862472832785201804711820024
+lcm:2124140486540339235997181873057458560557130144031198,6337118390151757487365380009696068490770095523526655,0:13460929740520685472324728914077419222468164771987370279610883339996690538208206652608006128131304582690
+lcm:70505951289040282645383932312380844925860919298,7547000534925894125969206219651626162975048702546706065,0:532108452093846047616616850898050963751081524640768880912328456268423081073299532380834291122692142370
+lcm:-41539404414450841529694974131865311088044938789,-87120273993379326877611820290578462959192080166852098,0:1206308098036249351756945897983313304106264694400442480326890301234582878846035432318850625075409774
+lcm:8365100924146743906263010309561180555381451232169,64464903694507870558459227754837948332608708108908133757,0:179751808489986211172946844019445427528755317573706157771373596620024395670275172869683254867277971076311
+lcm:-607028381550248615720149092346152462853976790359415563,-638047705393414341349283089715056902457142563666819,0:387313065956814142347580416821601619522788233833564805598190281345003710840619549824608697022583095304097
+lcm:9617834842433276206013447576300042077483363020815285,528061422615472570377974310003284316297281680382590494,0:461709777215997755037224920599333096287843157872778309854711289206537291450554735917549911763077470081890
+lcm:86576571095874523146332767288469633576872568596,28806568894922815646464384363885717260300665904363145435,0:2493973959959492744618741686252959362351894366493500719340778231935540767761675386859282345646361759260
+lcm:307009198563449723583109556832166934014223122475324,138726608616028283757694379054230076836833023549,0:42590344930632202620089538756907194977499968842538325319841912047531571749213635995957120063404876
+lcm:950446831200123302940271854492691726825599408858,-72101792770002156123347099210449392040964040896942,0:-34264460231048255033825169994117823623249265283681750151900757832396404944731172193421125649956118
+lcm:981208671446974342191660850214776536471793694644642,42331603864003005956059961823201488180622810810249336717,0:41536136787617995005181391797616187316701801094427498210675495592371812354190764162938589949104015517920314
+lcm:436034751789860072246023599184144455891992330310990,72833959249163120346712529298424162613591559886645,0:6351627468616324890653950471065605238944270582911744198034275769361278389558892161259769728399545710
+lcm:90712859511805773491925085535825623597765615019643547,-747515802065477997196092836504038150570958532540685162,0:-67809295935620517600810302668580552577312402195771262364310764109361834590609187219719805153318608391949614
+lcm:397399782669545823592934194763075791833495372998,-59196779886291303828419299835113054892183602687860135035,0:-23524787461549105672926147613053790427130112546635830152219683595731769479837306026216856302451972784930
+lcm:32400956990211215478801690694170683149459902468,-4583955972534683626923454093368608704790928252299,0:-148524560311118107934748825020984325384128831537817042673475700215519245003301091136794236773932
+lcm:987205647053507741802554416690401353287928887038,99876648283232575129630115679242229378848334523759990898,0:7042770799570301963626168264039468160084000109548666284236360269531859091326565782062357924306725012866
+lcm:613843278686603793281546390730144010908586402122774247,-5096436233192165525303465082471737429087562092805456864,0:-3128413126999883739898127525581773020068974144641842702264583891275711281299548031054626111037897411968581408
+lcm:-976952961430926103170472845979881570029763109667,935178486322270132160329332160301439376977149568344208099,0:-913625391679032626735612276016819847879751832378461622543415386714525380228017439645010525807254806593033
+lcm:-14766907052440196735362466027665124699631240785562617,56185497908476101017098165076418921931361374576783903,0:-829686025309539659436877109175759992995713482163632861241130851163598589293178881677705053185350284154151
+lcm:8086945629611784458016532027184114429962417844094,915144274243273504802165174453120299631299876477769004475,0:7400721989055888996136233798580013159529233408791044035035967083245349723159601722480356017380766138320650
+lcm:78088762763327100616786616097147636046671948600444,567540241084477255158834032762283528860020033647985833,0:14772838414895737660959188658560357264170049117788265097974792165237624507227111109881234062081296503284
+lcm:719986964333569855824423695658491299542433105292,-615276910378191482694097418592439439457014608822814,0:-221495677463866003861265966742219836258928444486382973104855851549896711750780958155476829316865844
+lcm:45518095176552517046254533808850801860612235127698055,35562211507032265793347677842985571735031362689772443740,0:323744825613157159148934641716894736150323375120651628592606014999068335232090157998718113595333671638985140
+lcm:9347651927739244225461883666785850681796998039204,-49878021756813856103391637115956958358002286487531,0:-35864798940530846688181260694471898202801103161830397888280327472734771199678233550132451645781948
+lcm:-918018144578664428004161449615771398954961013294489,-670699097650597095681408528960639081653596263477957,0:615713941195785615974127065795375976710193022314921690147944271007135254397488569454896629925801078973
+lcm:27390700201762535100035783959539579449610388231,-1589447744597072139866306928627083981945967837919031841,0:-43536086658626030220375532900736667658969827278059194645833847995230392704902546272550528175660663271
+lcm:2277199840598187516900058221233481999025368188568,9608219845154413235861538421470991851896216584568613,0:7293278899939323922333519302858351340649305819231682068123769660826907879720133355526830831172738728
+lcm:-384224188940171310851587214747099156035618205974037811,-365155157346205326208918238248019306559191342503,0:140301444168666379290296176915045491501178018946537404762619540722359114634558549786149744296773380933
+lcm:286446854858822908871115682474835177238732522628,-57158496101544373650727927690968913495792599007869,0:-16372871436747676262278174307506297592132492975051635951931260785772478739228382233254016392559732
+lcm:-381089856197823678538852020226946248080829424869589,-3010621081997078653311455126099557341287585438919,0:1147317155204403033538417293781061706820038418656862236980125391331092308923135144143540086900134291
+lcm:116824003493453841699155925492342665434851317689062,-23510392931055495213857939210838689217666922526899551035,0:-2746578225910099677716238357776888697288117665636655886289546239917490129557481316738650939508921530279170
+lcm:580076669302513896163920831671903321718154827187111,57642903862300589084685292813271561699366462736142,0:33437303681368339826568875036607309078951222489453540109258834689115591802250959764588162866456265762
+lcm:5760449410973032312996903274730533429280588604119,54924391723347076414566698417788233810196808558058264,0:35154353327867417497336892157787775216597147261438145141426040243888036287697412053742388607203598824
+lcm:5657781195595763129830083459999757852112323789572340704,692061618840647789470644193517118113508111433346167161307,0:3915533213270179560961108305159334536041508008965034741386030883311266330352593550098270684221170821027129940128
+lcm:-411686824144764716061907353842274549877341843077020461,64596348790121485579427789661619008385819947602752810318,0:-26593465684752629063594295950004957994828988051383949912582218957039523707407380651277297287183402393737916598
+lcm:632256394728894097701649213009572878755743290206395156077,831219707790000649838963373434914934485492976701321111,0:525543975674910659026260706288720204381515414601996591588570479429744161463440855422928774392151685316940041547
+lcm:1670481530219772906326138470230000469885289884882422,468290338328174403769157221534943442214405575737600,0:391135180478791974386986543598623230679031886475719459105679828323568651046861349186906657695962233600
+lcm:-5940255960924729598832299636442321100271324046668226,57672031765846684220194592702663453624777841860734299817,0:-342586630475711125183923927161946766514304847978409032225317328682383801381008087781458635612556537811514642
+lcm:1070320750308710183653165839089007570013512879851785,1457798154372592051774290334996812066679847800239,0:1560311614386725640264706359282306460222595994684719021358994107802507336028163090509939936607576615
+lcm:4878833860261622243309660185570248437064542060170266009303,2713399212910344466363698742990679778889654409261764714,0:13238223956354223315835115083131058404743853065832322244195207641759173433600815039556809272534689440156121134342
+lcm:-153727669883775746511963322850970227020812560900211022,967696702028565741720227898697068313091723784217356354,0:-10625839939790418437169093271198280114670637344943720676814969693439380312693668799845699120787148112323842
+lcm:-540592613733911579302709730020084890208422708295834255759,1487237786400760689794761062671094249214728767786149324317,0:-803989762194224119099880670025468825040986939150865705871247661626924722104597624198557832395582009863760415991603
+lcm:6147134348286513705872901614503400707429078163757093529,477008107151085089956583728568535862114663515203848020888,0:225556378452274534034927784413743699904109572650798922040352209009358253405098100518908280809464240096750894904
+lcm:7614680849639684551334463800131196276563566036683927,25187069984138015151555984154271413618496480687947851,0:191791499466750257309658251576197471575523021858632537910036998866329759048429339136517641910254745890877
+lcm:34751974072174908316243318351151710272413759348773,8306602488518142539700335965542308143538343391985,0:288670834308846061096235572592461254734354939539314534410107250770305649520412166539742961467784405
diff --git a/polly/lib/External/isl/imath/tests/mod.t b/polly/lib/External/isl/imath/tests/mod.t
new file mode 100644
index 00000000000..7ca2635d1e9
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/mod.t
@@ -0,0 +1,754 @@
+# Modulo (remainder) tests
+
+mod:-52,67,0:15
+mod:-54090198,1,=1:0
+mod:-76,427,0:351
+mod:-84,576007732,=2:576007648
+mod:0,9268611,=2:0
+mod:0,807,0:0
+mod:8268,487413,0:8268
+mod:1146574,836443419,=1:1146574
+mod:68387,38,0:25
+mod:822,3971,0:822
+mod:6236,52183125,0:6236
+mod:3339,8463,0:3339
+mod:-6911,492807317,0:492800406
+mod:38291,7924,0:6595
+mod:768,7974,0:768
+mod:-753573,5272420932,0:5271667359
+mod:422,509441099,0:422
+mod:930,3648323446,0:930
+mod:2427,67,0:15
+mod:88,9301062895,0:88
+mod:7238405237,35596,0:29829
+mod:791480,518904571,0:791480
+mod:451304532,47,0:4
+mod:92202398,405459259,0:92202398
+mod:349,6205,0:349
+mod:-4,9246262,0:9246258
+mod:-5200,499,0:289
+mod:605,411571,0:605
+mod:343980431,136,=2:119
+mod:-5765,7596,0:1831
+mod:43599271968,8373850989,0:1730017023
+mod:41585052,17623,0:12395
+mod:-2409446,38,0:20
+mod:181096791,3565,0:1921
+mod:424266851,9078599,0:6651297
+mod:8187966,773,0:350
+mod:2,628566175,0:2
+mod:5095350857,5051807279,0:43543578
+mod:-93,65,0:37
+mod:2833717,10804793,=1:2833717
+mod:3929,893,=1:357
+mod:-8433693,960816587,0:952382894
+mod:79150,8266,0:4756
+mod:8999807,39604219825,0:8999807
+mod:71019,11742958502,0:71019
+mod:62049796028,8668788,0:7280312
+mod:663,501536125446,0:663
+mod:9405339512,4946,0:1182
+mod:8398326144,695282,=1:14866
+mod:2040205440,4831,0:1675
+mod:80471943965,888059767,=1:546564935
+mod:69485028101,554070,0:217541
+mod:673,944658680,0:673
+mod:670561,90183207,0:670561
+mod:87072012,7500022,0:4571770
+mod:910888567055,779049027843,=2:131839539212
+mod:963684578354,34003127,0:1956047
+mod:909044,302,0:24
+mod:5117486344,275346901,0:161242126
+mod:946663509903,66919981611,0:9783767349
+mod:80280109,35551,0:5951
+mod:92755422,4885132452638,0:92755422
+mod:404434561,300368787584,0:404434561
+mod:7641992913,2639,=2:464
+mod:4268,10435873,0:4268
+mod:-16867245244,3938443,0:1106125
+mod:7471011989,656899,0:99662
+mod:10540460484,86682087637,=2:10540460484
+mod:284094,8671306,0:284094
+mod:9452633,5574,0:4703
+mod:87858,294942647,0:87858
+mod:-6925741,254505734568,0:254498808827
+mod:5567849,8785,0:6944
+mod:5715920872437,47382,0:30681
+mod:-7228582013,17846758280596,0:17839529698583
+mod:-4825967237258,629489737727,0:209950664558
+mod:-97364920350289,7307271,0:982130
+mod:-5267574,1302960,0:1247226
+mod:36680428,6651498734,0:36680428
+mod:80778366511135,18049323,0:11222506
+mod:5246691699374,70706752,0:38580718
+mod:-76528261247430,881359,0:586489
+mod:2510155,9882180356,0:2510155
+mod:205710633,89629157572,0:205710633
+mod:38304,635189,0:38304
+mod:61339988670,8789855847549,0:61339988670
+mod:-95895,39680647996348,0:39680647900453
+mod:3783159,35551417,0:3783159
+mod:434657,27849425,0:434657
+mod:-922645,2692809,0:1770164
+mod:9973857,61929174655,0:9973857
+mod:491931072,76925934085,0:491931072
+mod:36870777851,79112622642,0:36870777851
+mod:38419240,600490113,0:38419240
+mod:4286489,4746879,0:4286489
+mod:-5967532,617005,0:202518
+mod:-50370862538738,6877482182,0:6694444412
+mod:948978223,306059033,0:30801124
+mod:1939139989,7192751179579,0:1939139989
+mod:871928,56723606527336,0:871928
+mod:5777442393,771454160,0:377263273
+mod:-2052133016,7833337,0:201278
+mod:200227,787554274823,0:200227
+mod:3616468166,851332729232285,0:3616468166
+mod:-48554766181,2252075,0:2222894
+mod:2085689725679,557651117,0:74548099
+mod:2079714930,6441707850091,0:2079714930
+mod:-464256354428,40650020675934,0:40185764321506
+mod:-209095689322770,332963733020,0:5535013790
+mod:92840725060170,4953669615741,0:3674671976832
+mod:6233198674119,5752924138093,0:480274536026
+mod:-94439733,73783193078726,0:73783098638993
+mod:524856,25938632,0:524856
+mod:-3642534,51609507988,0:51605865454
+mod:556443616571,195489997,0:79085109
+mod:747271697917685,801669727071100,0:747271697917685
+mod:4017563378374,1995926813097,0:25709752180
+mod:-13638096565,3048867,0:2534393
+mod:304947884525,888510602,0:188748039
+mod:5378877455085643,43074731164862996,0:5378877455085643
+mod:89177886913,4817647675701342,0:89177886913
+mod:-865014493293680,219168754644,0:44581286188
+mod:6321573844,258781732494,0:6321573844
+mod:1400577334033142,14009914614715892,0:1400577334033142
+mod:-337804687,158388274759,0:158050470072
+mod:-3733377356597,469670806,0:35880297
+mod:51974564129148100,903237315049451,0:490037171329393
+mod:56996153270005410,2396515,0:7985
+mod:-67091637443329,19220071611,0:5632550672
+mod:9064750093935233,171857609,0:35046324
+mod:-71156951211655456,39266481994,0:466181614
+mod:4362072502442,7301990213272,0:4362072502442
+mod:-86003145010044,116261682333982,0:30258537323938
+mod:56216118551114756,455637223,0:305042665
+mod:262802582,8458718157713811,0:262802582
+mod:364016243349347,542092606375782,0:364016243349347
+mod:519321257779118,727275719430783,0:519321257779118
+mod:350650081861106,54037636428,0:53896716242
+mod:-342917424075566,19042847036414481,0:18699929612338915
+mod:3486471961809,6003086967,0:4681520949
+mod:693821889,68575560399616,0:693821889
+mod:3401139672999,693846027567975612,0:3401139672999
+mod:676404815653530286,614916221034390945,0:61488594619139341
+mod:4874055499517062,6434678789,0:5095928388
+mod:-9967718379562,6518969637,0:6305165048
+mod:10248458540,38512788750888978,0:10248458540
+mod:934811913,2221199202368,0:934811913
+mod:-6684245035389913,2828258378747,0:1757771967995
+mod:970708744192,5063581816300,0:970708744192
+mod:8778023537730,865180741691,0:126216120820
+mod:651572737854772745,819932061443536802,0:651572737854772745
+mod:31675213895884,13227242908836,0:5220728078212
+mod:-977172760207173,171558790519620575,0:170581617759413402
+mod:-45853408229656454,238503345091356,0:177737372975254
+mod:24097409593,335638746639,0:24097409593
+mod:13695822253044092,1732994051411821,0:1564863893161345
+mod:33933477593,3772615655961401,0:33933477593
+mod:1359484164716016,16485762808614,0:7651614409668
+mod:6194976547,9790288403118,0:6194976547
+mod:35165676304962247,326491511837,0:255039534488
+mod:50698603380253,837874905080656658,0:50698603380253
+mod:-6677472401203205,206803331886510165,0:200125859485306960
+mod:-2753237124185,71096000432140,0:68342763307955
+mod:1652954342334,4660678399996257311,0:1652954342334
+mod:762003770264,58114453785466092291,0:762003770264
+mod:83319117929825,29022700876993701,0:83319117929825
+mod:-437222911638931,2017017077397633602,0:2016579854485994671
+mod:50533577363426220,29452376981671,0:22750839860455
+mod:9775773078526862,883620114446,0:283752410764
+mod:86103820030464773010,9526822249,0:7814958303
+mod:472571956027154222,812207565469535,0:679360489354387
+mod:383374451459403337,4477129646684214,0:2818431491245147
+mod:7081720213022716854,503311092329338,0:133143948931194
+mod:4630128377779,800171178832441,0:4630128377779
+mod:54693593051710401,980996545405933,0:738783054384086
+mod:150482763687955095,749819481017,0:742223172348
+mod:593450696047000,13586015736,0:13528698520
+mod:-730500097181725110,728537309580,0:620447592990
+mod:-767181280549335,8336534436990434,0:7569353156441099
+mod:42981969692069,6887667892543850584,0:42981969692069
+mod:-28591748475152,101365562837426064,0:101336971088950912
+mod:-7968036669154,98303283928623932,0:98295315891954778
+mod:494411386598,8574532520081676103,0:494411386598
+mod:68913463428,37113484763365761,0:68913463428
+mod:79048317647131571,4246788999212,0:2834004798615
+mod:-7998703715314196040,603932675107699279,0:456353736193593866
+mod:37189110674330836953,371484075669789573,0:40703107351879653
+mod:4919085789477,6627653096140609,0:4919085789477
+mod:1124829404566321352,1113121353192745,0:576837841648902
+mod:73970998780022288,690593097938779270,0:73970998780022288
+mod:406559451598,291528733390141,0:406559451598
+mod:8337041054557098684,144564322413327450,0:96874676997434034
+mod:33602045710930,3944255323850,0:2048003120130
+mod:36881013741727574167,2358692215512,0:2217232253623
+mod:6055783116809477,665900361366484113746,0:6055783116809477
+mod:6874334379769379421,7685349776541,0:4194447198069
+mod:4114973877055494,6202439146871230,0:4114973877055494
+mod:3926099959854080246,275452944727,0:275423967496
+mod:4029793101439201031,660396995221451032884,0:4029793101439201031
+mod:301872874428635697,54874102367289078,0:27502362592190307
+mod:5569303592565,237882890299906,0:5569303592565
+mod:-5030250164815763124,20652997723024,0:14613601685340
+mod:228359514067103,297994781044164,0:228359514067103
+mod:-424197230384775822561,35518873718705666052,0:2029254239692170063
+mod:264447937587468968,14314680638460766,0:6783686095175180
+mod:6394566749820905145,9683844165303,0:4880613879246
+mod:-8688948887808654898,734279103507671775,0:122400354283406402
+mod:-626916205862869883,94382847154774,0:69047786293799
+mod:1626914326860229332,7062310571812316625,0:1626914326860229332
+mod:54001071080896262095,42490007593568841,0:38761437063834025
+mod:24728563187886295882350,709499139923539295422,0:605592430485959838002
+mod:-1107994585324963758433,26155793492434894341,0:16704534849736698230
+mod:654008549965770,51389913007264,0:37329593878602
+mod:-519456375679038,4624572350871880932563,0:4624571831415505253525
+mod:-82236922719413533430,72103334739677626,0:32982218558637836
+mod:-323874523758275336,8012542519209926,0:4639719529331630
+mod:28055503703579420,59306141019480998333,0:28055503703579420
+mod:331202177649495634,20031374822914022410,0:331202177649495634
+mod:-130081790443955,81911619024148257,0:81781537233704302
+mod:12392000130570253028635,427646582276340386,0:85115948737663513
+mod:-3408044901060955810,3826012386295493550,0:417967485234537740
+mod:-2520566214354390679555,7522956445489849326,0:7147151330198693981
+mod:1980291342375366442,2779172585704919,0:1520461353464114
+mod:81051547602981,72198401841564,0:8853145761417
+mod:-92876397580264953214156,67027595927289169530,0:23850374957835754424
+mod:5011749939685736607,233831869913631792,0:101280671499468975
+mod:-809134913749137460747114,775995673975034727,0:431478675099304148
+mod:643341365602570,69924772710009984856,0:643341365602570
+mod:27791967964909927,59009798124981438889038,0:27791967964909927
+mod:-113914260724456,4611599197279102,0:4497684936554646
+mod:363308545066340586,9662463842692591834,0:363308545066340586
+mod:27756526116505105,3891223619279919535107,0:27756526116505105
+mod:704802873683670599667791,7264024574741209,0:546567259370500
+mod:787136088375328,120969078621542,0:61321616646076
+mod:7670850065383883511434,877940228500467933,0:286288975295180813
+mod:702943840459603392464,184873925058119829752751,0:702943840459603392464
+mod:346820606266075751,258033318226999763369665,0:346820606266075751
+mod:-19738877253014425,881986541366353479688437,0:881986521627476226674012
+mod:43236561155260520835698,38481338895759451581,0:22017575322656710235
+mod:482681206446127491983,75672199144043749590770,0:482681206446127491983
+mod:-9003595768210252773151956,24542596402501089193,0:2977625686803835252
+mod:500595090938893533,22068045096454773348,0:500595090938893533
+mod:2380288714663108486927735,564958976857884405,0:163611608764475305
+mod:-61794208268134898961577,163988560200473972889023,0:102194351932339073927446
+mod:-801112647021780575,5997315269791230838613,0:5996514157144209058038
+mod:3375858304586431,650460337591609485545992,0:3375858304586431
+mod:8320311342983951,42251663165732904527,0:8320311342983951
+mod:7459256407267723209637006,417970890631288166,0:349337361754478408
+mod:848180762170013347,7469835660313775,0:4089332554556772
+mod:8089787096351751904254417,50129556268942208341,0:29694338665148808860
+mod:-34903538093781704569582,183184852451752183835379,0:148281314357970479265797
+mod:48619014890072452,80354799021914778903,0:48619014890072452
+mod:-815988375058446388,8738660656145657284,0:7922672281087210896
+mod:31813448306518054090072,207434655868203321566266,0:31813448306518054090072
+mod:-8633600698002819419017,586048397265776638134,0:157125260983830152993
+mod:-857216833834708698,9172367193130972108680,0:9171509976297137399982
+mod:5504547056103565303478,13822143042666022,0:2988649206036176
+mod:9870113591998328200,40859674965133754765576,0:9870113591998328200
+mod:5384435851045720977148,202201600690593374,0:9426255910020902
+mod:-2551078867778519184089893,60228847348701786402454201,0:57677768480923267218364308
+mod:91679210346975867109461657,9997426629350491363488423,0:1702370682821444838065850
+mod:2292649799687862201,546378248247723870,0:107136806696966721
+mod:588814820029030818332181,8113490218013508525654874,0:588814820029030818332181
+mod:65454498830100158031,780288548110175467735,0:65454498830100158031
+mod:4709646238170145522365,55608341104804744,0:9004980917338773
+mod:-225535148248500667,8159132039306813709871312,0:8159131813771665461370645
+mod:76763315297183633054184,85934198951388076635,0:24075633594080619129
+mod:1133129576897649900,54644763452092731277,0:1133129576897649900
+mod:-67382808234452914542138,8955363760101370992534,0:4260101846358053398134
+mod:-90953375293336830190945,6853448055620747690936,0:4994897485353637482159
+mod:443616999780543985329,602650474818987637619854235,0:443616999780543985329
+mod:-32726760956482080293262442,7257539124551086281136,0:4740495243318834660918
+mod:8064248346280114405840575,2215292120106396321855736,0:1418371985960925440273367
+mod:-7028166529953061572415,793014187917784076,0:318217562258693173
+mod:-24801752752631583807972,746849063653448560403834425,0:746824261900695928820026453
+mod:866033908626319182842,6382377566902718089,0:4412937094452240827
+mod:-5696109440363786526866,467357847433239609373,0:379542576268328394983
+mod:-10407234425686004311,628564472015312749963777,0:628554064780887063959466
+mod:209459609329564838657,2486115412259790740945969,0:209459609329564838657
+mod:83211005582689134709,427365949717166750,0:302011337558785209
+mod:522043226813009221,84636707853907370269,0:522043226813009221
+mod:505480107359090528100756,628892849069663750,0:562098008522737006
+mod:-310708269201043467381433563,29010904881853615009335053,0:8411684499346297721252020
+mod:945016205353589874668951,176007434590298672,0:79677746280043975
+mod:3611093895058265247,4523612444279050027926505809,0:3611093895058265247
+mod:2248073915672967969228420426,417993946449832515848531,0:102471665768698995020708
+mod:75483556005338850007382,767992806236118220580991044,0:75483556005338850007382
+mod:349175730044864846750,194542620085155145157549,0:349175730044864846750
+mod:5214057366956683393,6766485378347583109969578772,0:5214057366956683393
+mod:42801122269815033051372,76491121430284940146293642,0:42801122269815033051372
+mod:1504356843590479398148441,98825538637920229212984,0:21973764021675959953681
+mod:1422956549105294508549700,73999528905391695937,0:19607783517587377127
+mod:199912292615681783148398065,5625251527460055267035,0:2103832806339068508235
+mod:8738762075990650132321428,8066858358673855106257,0:2354473546865052245097
+mod:8744971293400903575143822441,2181608008778482293077393,0:1086394216746544489631297
+mod:63912100585682096593583,11361184476808394745245,0:7106178201640122867358
+mod:64684262754316464701,22376578863907224393672,0:64684262754316464701
+mod:13792618112420611117,792966702790880958054,0:13792618112420611117
+mod:1114011944265093423883128,24116689971306070038294352,0:1114011944265093423883128
+mod:39678469855084024947237050,42142535719623301934525721,0:39678469855084024947237050
+mod:83034763665077760046967629,82778559778204667638,0:4244359548962628019
+mod:2396471122363838882513850900,59747356384740003525,0:57225475716145829475
+mod:864549729107840811638,74264623502102569648,0:47638870584712545510
+mod:293471055432367196531,95629011563915920942031898043,0:293471055432367196531
+mod:805770771235800281066969751,444417493982143896834,0:79401739074580625355
+mod:99254856446162105637797829350,101981775402621358245361,0:73717806842511917782490
+mod:22541739862903307325,418383569773975023302632076,0:22541739862903307325
+mod:13599043000903587396023017,686395340986063801303,0:178505287691364607981
+mod:-921575422288638694625782546,2041485695291750177603,0:216222744337548474126
+mod:-489269754337315502376167081,501875735917569336224,0:368721212244829894711
+mod:-80044798953445460081243,6139390882382293287544714,0:6059346083428847827463471
+mod:1697244421022884241204,9839911566031781174211,0:1697244421022884241204
+mod:940445668109981090346872,1166998590007295684475234,0:940445668109981090346872
+mod:399066130721328784362180646,2466979168009327704701836,0:1882484671827023905185050
+mod:-48110448286951664808938217,6924833390360325487794,0:3294109271876680254495
+mod:8202438083226798875527459,2712253233103808901251657,0:65678383915372171772488
+mod:5450714727456153005642027367,100450439174668838374882,0:72996960272497744180283
+mod:409375235483978782700540,154442023996251499419641,0:100491187491475783861258
+mod:75895449457418931569869638,96657756211092917375958176,0:75895449457418931569869638
+mod:-337896716384821901508,136332254359196503233175760151,0:136332254021299786848353858643
+mod:286597911534314020993735125,8939960441559894748118849,0:519177404397389053931957
+mod:-3629523279922780081559669,47176221977787068435634953,0:43546698697864288354075284
+mod:721006898368058427667864053628,560134433649198454347279482,0:113882261540016922915360294
+mod:5816434052384442045783498,8295493150888286278058,0:1293353611753364864840
+mod:609810757121108447302938155,91911350135942492551802190,0:58342656305453491992125015
+mod:-19105264771397651242810,62812840189408438467870,0:43707575418010787225060
+mod:-3384023484275449303514510512,36865912947085723132571998682,0:33481889462810273829057488170
+mod:794103148636604290205719396698,60830693353207800202838586376,0:3304135044902887568817773810
+mod:-872647162068256604091329081711,7171269767341809905452128,0:3142110266217873424018225
+mod:1741864928041849080630509776343,4019228270224295025021,0:3953212345502485484813
+mod:46472481719179435494357769,7926074597166240368807886225357,0:46472481719179435494357769
+mod:-8260893021299279875407235,8110427213374126288611,0:3632309128954812687374
+mod:-12778559515327410738082,60133073412668338924778,0:47354513897340928186696
+mod:-33979239742647553347892336,6474568036342863013409,0:5767880116134609491505
+mod:983404512267124852163233,80477942869108029021719,0:17669197837828503902605
+mod:3832523396251835150772,9395631266939763227204675100039,0:3832523396251835150772
+mod:88670226724007548654482766,32452353295811216769641,0:10397519851304439823554
+mod:96278532026543994019519712307,129820052877663606606885,0:86210882333451655589757
+mod:-5810653163494420168043,36986477497409060096423733207,0:36986471686755896602003565164
+mod:3126207974581460571577891,32180478067769596422373325424,0:3126207974581460571577891
+mod:51956357441149158122167659,1003490769172375032993217,0:778328213358031439513592
+mod:-561702379847624714751550,53922991187327968536105231702,0:53922429484948120911390480152
+mod:446077868534077880774451137,67277848506923282427435882416,0:446077868534077880774451137
+mod:1575047464232207678249043,70194506692490651832280909556,0:1575047464232207678249043
+mod:814270662793297992963934,403564259479336969832400620632,0:814270662793297992963934
+mod:790699201198504136904045859970,68724106656555736601709440224634,0:790699201198504136904045859970
+mod:8110552276797224689344660171,3909333328494414590072213560549,0:8110552276797224689344660171
+mod:-65870994230220283146814283,3379239242265180710762324,0:1713790615083331068432197
+mod:4019795295333902960419848174,50295832366163431551511941,0:46424538406991867850404835
+mod:11568598680110024328705699675,22452048595187151195492,0:1025051083178018882739
+mod:387522780739724474268318533074,9155092309434144095404353111490,0:387522780739724474268318533074
+mod:2391972635448121089016589,39976990962848470908868,0:33330168640061305393377
+mod:866848655025962221176014879,40996252765546194841051793,0:5927346949492129513927226
+mod:9039212181347754641685676061753,1413755859430626067769418378148,0:556677024763998235069165792865
+mod:62309693047935174482238300219097,1448468173515469111051509167,0:937627820239732135530382258
+mod:10235771277419233732197767436,47759815237747782490291,0:30955110842232226071189
+mod:4510445237186840834301611,9536931548375816882114508,0:4510445237186840834301611
+mod:32374689605351221312665153746,773865694054081649089543,0:18294598715523004122341
+mod:58121462593501432960291,544699189690679924713807,0:58121462593501432960291
+mod:487815493709763477417262324977,100467558757425018298664228901,0:85945258680063404222605409373
+mod:98070875983658870659113425694,60099405211091721761658040174,0:37971470772567148897455385520
+mod:918364128985502035087214237,2299858822935844817555228747,0:918364128985502035087214237
+mod:98947035094409552251212724,2825141475757917666304644602636,0:98947035094409552251212724
+mod:1526039375858118801195007,9842198071310595711976222424051,0:1526039375858118801195007
+mod:956310510459469197042596,12660491958158211655462388289,0:956310510459469197042596
+mod:712022876493637494246773,6907620845496782089063213,0:712022876493637494246773
+mod:-127487606866501768951687217731413,97214150491566835275008318146,0:57358578433918929123695676139
+mod:6751815551565439795678949,31071725936607844864896266530950,0:6751815551565439795678949
+mod:207247716655973517840426399106,8676153294057052584605417,0:442920832702751956803227
+mod:-966202956730918757628959,506872112425906694585759,0:47541268120894631542559
+mod:-68170698773654086579499859368,5144430238993385147152349982479,0:5076259540219731060572850123111
+mod:183149199419924949681672,26683244363440548441986070029128,0:183149199419924949681672
+mod:-9975221264569424411536101126696,74192946761934634594295284416,0:40826548291751258693762269464
+mod:225922343593361728051942267585750,5683400149678094053656150,0:3825868296308226483712150
+mod:1590802748651151308839006,37444237944901366482969738035104,0:1590802748651151308839006
+mod:9067619839451785696827107956190777,87355497973165371903530913,0:84293482668838694674156358
+mod:-86293581881377444715621610358507,7692884519189179893063221146996,0:6021032348892714001137043405445
+mod:797270639908743442539388404065,246054564304506055627938724988881,0:797270639908743442539388404065
+mod:205038144424990428525674376,85234961390603945529096075,0:34568221643782537467482226
+mod:35844939430843764162712556,653126866666115633914185924567756,0:35844939430843764162712556
+mod:4259287602245499035603599602,50729589724528668468977995092499,0:4259287602245499035603599602
+mod:2261834480876028227185763,424795020529636248111781917,0:2261834480876028227185763
+mod:39152906040428126999262088,4297272364540702463008576,0:477454759561804832184904
+mod:-5930922183829543621704345694286,197786250025515478569975835009,0:2665316935920735394929355984
+mod:13648638091639720241268467,60685727322075123781463007100346,0:13648638091639720241268467
+mod:-668319624482464990058154959802,710719216881033542598449292474287,0:710050897256551077608391137514485
+mod:642021199249584712913865808325586,543227057645582873078752689,0:152765287910622645761540601
+mod:-2656447484733675418860019290432,205011691602629984379183426293586,0:202355244117896308960323407003154
+mod:-76116380282907702927282762504,936328544643249459199496754,0:662560377838752727075971324
+mod:8093358695607350358964677676389573,829984096904096704239626252,0:340210087590552445135735881
+mod:-9278168173113556399784725246186,4280082896252256282175389133291,0:3562080515643212446741442153687
+mod:2802211761443428677828547316,747494545678197065832762122247199,0:2802211761443428677828547316
+mod:23492204756311184079845536545,337250910922702955980510700463272,0:23492204756311184079845536545
+mod:64710301838085669236316870323,868170439410850659865082898,0:465689321682720406300735871
+mod:2741127245480801383259770751238076,74176417788834011756636699109536,0:70776205082776960020849583294780
+mod:415065500982033616775933433,28746890219519286864975018117944504,0:415065500982033616775933433
+mod:-89217744891275021874139963535100059,3290121624016777142908239971,0:2829430817460639915155471175
+mod:-9317836992515247957659739610258,361276376419354526411745198556357,0:351958539426839278454085458946099
+mod:298421168958661320791582460540,9311321600116774390269301187799304,0:298421168958661320791582460540
+mod:5274155275590071857725575099101060,98122204238639783506999069,0:57734636536655754953174064
+mod:865783349805109330441131327,162630826994678660982290958,0:52629214831716025529676537
+mod:708516761779855069848378277411149,35904666994288818268923584882788350,0:708516761779855069848378277411149
+mod:6609496417442545300703371471487286,5902561608289411469926303,0:3737357682418540243913209
+mod:206488861625670348490519145948,55768433595490812270050489117,0:39183560839197911680367678597
+mod:235462255567476370046316727231771335,90122239517029363511961434219818206,0:55217776533417643022393858792134923
+mod:7378753800396502033389928296562,22504168678875184770299793837483,0:7378753800396502033389928296562
+mod:2757925654768646392546972258732,66265998215956320290751023811589600,0:2757925654768646392546972258732
+mod:-4495627928966379121510140686227227,4292233509252118764895120750881,0:2632788729841344099945860696061
+mod:60075078241755197289597987901298258,85793760621445664196834659007562403,0:60075078241755197289597987901298258
+mod:640202717640040770302982685361,1043941556622236018146973420441,0:640202717640040770302982685361
+mod:981675333306953772484178502284,14989243876208586685329510289358317,0:981675333306953772484178502284
+mod:87715989707184594635823373687043380,2924631585179762875239333452363500,0:2901673736971471253882703568501880
+mod:-323249437311463874466227132752562758,54630285509683054247993598313342182,0:4532275746634451021734457127490334
+mod:-14647356048136737851231147317,175677379713875589633642881,0:109543847828811677994854687
+mod:-6268327123157272100193046712,31032884392623150618360081127,0:24764557269465878518167034415
+mod:8830187989453831993186309990340663,959494270231543012302622845163608617,0:8830187989453831993186309990340663
+mod:2102106468815389931443009975417,244048361348982984508269787947,0:149719578023526055376851671841
+mod:767756521870180222085097228863,5629352943535035124861550483062,0:767756521870180222085097228863
+mod:852449392775158289272424932198,564809949353895492950864832457,0:287639443421262796321560099741
+mod:-94075133584459673485423491471,7078005136840583876255761330997303,0:7077911061706999416582275907505832
+mod:94026202014853579487205142874162,363228855132321701963096787271215,0:94026202014853579487205142874162
+mod:78501236594767796495670623879783,7018641410498793931533837751986,0:1296181079281063248798408607937
+mod:-83121914354650984352606847805013,52556446964608987755585827141661,0:21990979574566991158564806478309
+mod:554612894627846154817277112226378,90600992903463982226644139632,0:44217065743119607988333538906
+mod:525293194961196331029028416806301039,736093318498847487453110088942,0:72734093290490277635805244173
+mod:157610281371549009553406136918536,976813980235355373377808309891,0:343230553656794439578999026085
+mod:-266509790805154856208324746487,7013639425300014015101241233380,0:6747129634494859158892916486893
+mod:59653129021803829007632144466094,6178618914324116986866641510962341019,0:59653129021803829007632144466094
+mod:-1025495993097568795964701500702,857271481493597231020277064636,0:689046969889625666075852628570
+mod:481051936536536822112378933191985353,9466673918671293738127743696345889772,0:481051936536536822112378933191985353
+mod:848825342321881584621547504882,5509051479604448499464250938005578,0:848825342321881584621547504882
+mod:-26930177732304779325732093789608,5553144086178691095750038113040,0:835542698588676153018096775592
+mod:-930412667133937228253381813097,66449017645940693043271729675,0:66322597555173167395694132028
+mod:393034277242496542604957925805,4799386565947366109662393955284617,0:393034277242496542604957925805
+mod:86603638626688955985063356610183,1769014799372327392140745286156481,0:86603638626688955985063356610183
+mod:40877446922338785512028664714,3627227112486512731974346137499409882,0:40877446922338785512028664714
+mod:951744546236842962508833599628258421,802365455425080101863813995676143,0:139116102697961698350200756352823
+mod:30829284319654404192904595052,1296652777164452508914199335388219666,0:30829284319654404192904595052
+mod:73660971721825840324689412056336,5684533154366812172288342524757974326,0:73660971721825840324689412056336
+mod:8127358843185844147904557106702570660,3688282607387577967901654384422862,0:2072259111009884617212497819005674
+mod:36532892525294324678919117123848496713,92715061891153280227822277460692,0:5828075633057629393846902185185
+mod:-8597748351805543505111910190253821104,9557218184864474744270904051127420194,0:959469833058931239158993860873599090
+mod:774575051270128492444548860406,78181627397979349461399043516039569227,0:774575051270128492444548860406
+mod:71412172829277670593171097931971081,734737459512775442295997263661678,0:142639256538452690459363356788315
+mod:6184659289209085822436564762850,90249969123878877878427941364168671,0:6184659289209085822436564762850
+mod:188404876454609678788443725411,6011866633368206495263558549515721,0:188404876454609678788443725411
+mod:81043932065078534018074416730418,8372433471866735006229336375535354,0:81043932065078534018074416730418
+mod:6912342702093810814710065121185782090,79053815437751598622884440565862252,0:34660759009421734519118791955766166
+mod:-3169060990465931351414443670,3481005717923100913496633725151171,0:3481002548862110447565282310707501
+mod:-3677873239878011216446421508552,39945867794076672579972752013115,0:36267994554198661363526330504563
+mod:-88408316452809240011823526997216147179,430749395485673956071441817182,0:247080945638127516958667217647
+mod:-7006029462687996724256881439538686,5752004602477767685988190527369919519,0:5744998573015079689263933645930380833
+mod:172663755283332370937921725543,6631081406973798665639408060368,0:172663755283332370937921725543
+mod:877725872115390827864622867155990409562,3246622975450958412670313198657575,0:1350702224220999203693898915008312
+mod:1162325904966484479085618134964501604,9810351533284785336335637682672874,0:4704424038879809398012888409102472
+mod:-67246779579026319613494857580231,4479147727625713736723230094972,0:4419584062985100174076823939321
+mod:-83311824891620553984522523676903100800,570821292295355560082171193531,0:517563010884629547920243561062
+mod:25686998142667809989182628560877290,2025104174001151569408893055981534120,0:25686998142667809989182628560877290
+mod:-6182593212766128996183974088677690094,21672462542175162551645329360574,0:18538952890500736647244660057756
+mod:-294700116350712193407358863563690,47602175104818483716891162778987,0:38515109383017192610879275889219
+mod:99318338781646049264027201614,31132733056517268309209622249797280421,0:99318338781646049264027201614
+mod:-2566422039368713945896870934278082067,3422938407926845108634793366952796,0:781766576419885579224090936514933
+mod:1798229479312127271076623168674216,146420794203382070378885907918865097585,0:1798229479312127271076623168674216
+mod:-10575907960389417493180423047371,548554000428335526399148116041,0:395172048177293034802539273449
+mod:-41585237394069668771815671048852049750,6620785900949628605472441451228089,0:6539635695898127762206147762805348
+mod:1375415227799292140480888477226023092,123029527135707896415325486765764221416,0:1375415227799292140480888477226023092
+mod:-2079331025811185903148784604677,95045957198248711390742316452607286039,0:95045955118917685579556413303822681362
+mod:-212508186835656490444057415261195182,4829012565342247873891632422752490038715,0:4828800057155412217401188365337228843533
+mod:-560425113540022327972433105315966740,96209074671864129929198408439658600,0:16829334491162451602757345321984860
+mod:878336664644268081456398188824415429,932061958650634766658892044044056328852,0:878336664644268081456398188824415429
+mod:28882941735745195429234419733039022447,64140280097846201870647655651438569,0:19815691714404587442974689891666397
+mod:88232952784596907289907603989240788,93349243418019298106177761581992320992,0:88232952784596907289907603989240788
+mod:792301762499682540474009585487691810,421120400044388668787389960907,0:367290969121964719876967770219
+mod:76111941484805465095241888868932546,2831856059624821529741336978732478,0:2483683934560105321967127421888118
+mod:-5427708288474184011690247672955482270191,671682251167994228841481066017358827,0:155983214377351577760821530794410796
+mod:-8530853102666682143315062468746465,213498385560089813626810097876341271155,0:213489854706987146944666782813872524690
+mod:968866609367366454712369109246988,628634209852159542629660518990065356620,0:968866609367366454712369109246988
+mod:96097393485358514676281731274665078,3957833123075932141830397414925844074923,0:96097393485358514676281731274665078
+mod:-81978182783653208012914682683646556932,972774031969126613105009607688574,0:403212480999053283791985092639770
+mod:313104324214756365552882262334038,5945062360867852334605007338592823936,0:313104324214756365552882262334038
+mod:2735884017629695152167391129737071822780,3290205739029218948898407572995748,0:2270894901924122540569416928458576
+mod:-97466756197931651810599360815010262,3315237020945784440159312220994155,0:1990354430441881394180005814814388
+mod:4287211941100891093508540048565501812,594177978658290517920278334613052052,0:127966090492857468066591706274137448
+mod:5617959241381925678540184778777695094011,4078448937249847013764977403503471090,0:1935054788886340585810894153415403081
+mod:-3548112469563645005797230889810299281193,34963401912331074261420878238937,0:23794960044874975729481854354116
+mod:4922552264219521070158559671565380834,5646798983979557962421505933015709,0:4190349173326084889428003908698295
+mod:32565692680193961073474123363666015,878047053403499712307729237883224199,0:32565692680193961073474123363666015
+mod:768830069274599347793505224871406391916,49256101034975375638954310064864965,0:40844320703684820706353378994018196
+mod:642199331170025417801554157178084,71675957995271890601200242650759107386,0:642199331170025417801554157178084
+mod:42268335126087027949341092958250555849,386269043855800901191675132738936,0:72464078302734639658208027006177
+mod:61951474950542877141809186776499309394,1575592140257546405587708780583660678216,0:61951474950542877141809186776499309394
+mod:-50372525688338317312158892618403161,479484240404243987384900356318490043390,0:479433867878555649067588197425871640229
+mod:44683217172537023841274434066246364,58011321282881808274541027575827116208550,0:44683217172537023841274434066246364
+mod:114588115678254964728743791898564,4589417972133701399012552730584485633,0:114588115678254964728743791898564
+mod:787749081823153927726813864184041,31678364830089024747329753309219782268,0:787749081823153927726813864184041
+mod:-4210686607729439615194829247147791999288,202013476656713406344999304149677576978377,0:197802790048983966729804474902529784979089
+mod:-201317765219861856053478772267939948214725,28008182775029748896931627041800444,0:11094152473662864315215654119177355
+mod:-232349757997193586311539481768342879244,86500898319812757120814118782924774,0:78155788143292072088055401375988494
+mod:3459368213898794108935715830804259,645307545853931027509103766501511211,0:3459368213898794108935715830804259
+mod:-28214486245399572630623366879671715,4787018465719437691521185074756254,0:507624548917053518503743568865809
+mod:3106180109929449357402363559818380895066,469482281886594475593365429169214,0:356674718833276575481292181443332
+mod:770130766600035002140959295669804,926634653367571574740533619678875292928275,0:770130766600035002140959295669804
+mod:-6708203696875914373713983952300480,1838061152155611054471652207874138,0:644040911746529844172624879196072
+mod:-7022023536539325666545120950542389888,61599165978198027775591136704700507491129,0:61592143954661488449924591583749965101241
+mod:-3443533443745355681222242435436421990276,114311172439204299235358268154904366,0:90625985673833242925392730072035474
+mod:110440434921544638432764637319049273043,85855605443431360697149818939494456029,0:24584829478113277735614818379554817014
+mod:46258128333769427123848668553344812866281,2571328063101410768335059965106947440246,0:2545551261045444062152649146526706382099
+mod:363228842811153324360949224721752071886096,519776907108357809938962249484450996075,0:424561649519573023553574581605276625746
+mod:-7481133759236874924421451125199442,918037057467449661018383366170845,0:781199757970172024743999170338163
+mod:150233345756076313394229291485865,5605171356421762519368513553022673456091977,0:150233345756076313394229291485865
+mod:3185172342747413751304414848146001953,6651506504167945767766564692832116791091,0:3185172342747413751304414848146001953
+mod:605932275764163370707058593099297764806358,14520707105209378213724439334671383,0:12284018060727065660013089171020638
+mod:-47981623369556624178550389594061247212904,9181422689232628129475009481374015950,0:491604373090426086009955599360141796
+mod:874599738760971500384056236606682756504,44920344543206332304195675515171507,0:630504744210421366434326293515214
+mod:-5100339758640008895519382671699671,18538376885121966053582708191078256,0:13438037126481957158063325519378585
+mod:965966374431724388594710850103760963,51329769618720367882036219795372158,0:42030521294757766718058893787062119
+mod:55365396231165487163722749393764963,742461596124505780223115709313334341,0:55365396231165487163722749393764963
+mod:6538244814994833769942887762335568415335737,235589470700074178427678879883234150432018,0:177329106092830952395558005488246353671251
+mod:-19650261899708426741119367893002798,8812987996700889285483125610332533544693,0:8812968346438989577056384490964640541895
+mod:97698921976137171810654806439140172,2150746254976033978038152730412247,0:915340502215642798937933570589057
+mod:89923455582480950213180680168369292947024,990694177649308076053947944961089214039,0:760979594043223368325365121871263683514
+mod:723635984996285778841783493422287881642264,32276235065854550279733766315134173,0:19063611098078828395533076621443386
+mod:-5037258901456714281661245286129845002,306535320966797925963773461282861033272807,0:306530283707896469249491800037574903427805
+mod:166532365585666920632121582151238444,4667090491545163201419847209865957,0:3184198381586208582426929805929949
+mod:911936886147819373421198830106569057199,5615756921004609557346343726386068926525410,0:911936886147819373421198830106569057199
+mod:86811484072885033355160274493374615256,37068107901315780002032584004147872592,0:12675268270253473351095106485078870072
+mod:900473503013044141279558739534891246414484,563077317551901922040540262359036981493665,0:337396185461142219239018477175854264920819
+mod:296206604339420484011101863526048420,6943888401750337638037748772448658766,0:296206604339420484011101863526048420
+mod:76766227336308707540545234943801585701916947,862719523018962547718304126230369079803,0:581458558401082022815487697114611966204
+mod:82054010479033741262889658973891816396202551,74207348922359582189434798229625162234441019,0:7846661556674159073454860744266654161761532
+mod:5755949428068825531208655649279932079247416,534856249135883824768051408128323875,0:303149412971297936011710552241756791
+mod:-4452928490319786360637181545589562421706,303160457106458311370564160984723696,0:195464116979775085035415115043948838
+mod:-33234789698150515963593845391683006297003,247588244673392242851888266520387546,0:218325582291755629376064681215940307
+mod:45977596818262545665224859936336489390180665,27112842992285248552330285939262767,0:7978970070244814382475981419198853
+mod:19746632039239597257084558812475187,78543233940000315537304287419172400279725,0:19746632039239597257084558812475187
+mod:5238660120000018347305860723869512579464,9519590072642166905656304842744016323,0:2885580046826549194893060360303601814
+mod:421929309968572623211165422203258159204,6170672461209605966222290081308608002126042,0:421929309968572623211165422203258159204
+mod:97091659698518128542501333936202976578952,9041846719954776582047878587371155342936,0:6673192498970362722022548062491423149592
+mod:23139165317306380078171479574331055567930602,3235715510499720116696692085743763585,0:687224054572373129244754482756731812
+mod:7726755134733624542969321051092429534,137447273592584087361585543516012636379,0:7726755134733624542969321051092429534
+mod:-8035318446247202234206121089089275957949,1797181404653889821209194311109353672704806,0:1789146086207642618974988190020264396746857
+mod:44241982166867606755367641125284961693,185309069767665166238795112362391081,0:138423562163297190534404383035884415
+mod:-65785436012415799791107145824395590258329666,325370594025067544378522706736314963998472679,0:259585158012651744587415560911919373740143013
+mod:821027673057722511274869415993294010068508911,57940761411167592399099541246011867856,0:15088585564533356226393273829101110479
+mod:-897376592880832081463108433977538716243727,63994684847881571668961590693909662872,0:20872741011198050739952323156486210329
+mod:191486322813809144772467638907874658537,8919158359079954072103703171632009622394,0:191486322813809144772467638907874658537
+mod:163217130341378273663281863598861624,6240813543901974803730523328640195566309,0:163217130341378273663281863598861624
+mod:642113355959693728339535203311987630159829,323941666913544410706066077917137340119619,0:318171689046149317633469125394850290040210
+mod:90922298984492607133074207595203967287,4174997092394433838709995127446401945171627,0:90922298984492607133074207595203967287
+mod:-56138446847378331284150081036618044197,841578896703894278645078028402014609956835,0:841522758257046900313793878320977991912638
+mod:160326346782265576182652967313761281,561264601142183384980166754221561305236177968,0:160326346782265576182652967313761281
+mod:62576995621135938138768719119421725807,52496992618170687901372956534626144856655,0:62576995621135938138768719119421725807
+mod:-810322268830690053691854099385548648,520427764614796522518452921164896518986058,0:520426954292527691828399229310797133437410
+mod:-7946357739653867559456965124148378449835470,5327876492137615168373368729394652862957684,0:2709395244621362777289772334640927276079898
+mod:51331569935780141651744430445423490878343,752393011036235424760251760776480444081267,0:51331569935780141651744430445423490878343
+mod:6390091523604851953175389451017692789149570,538026068781142884378652825927355725561390604,0:6390091523604851953175389451017692789149570
+mod:50795967128946679209456313061694178754547719,2799907523414076596435050064346492259123881,0:397631707493300473625411903457318090317861
+mod:931794725698638185508827954509566305382537413,188887874108390274677254477767965547955941480,0:176243229265077086799810043437704113558771493
+mod:45956761520600045904065879294257993751858393,2754559558487710326209328606488100503,0:1112021195932856302477743058115163232
+mod:86998056199797702223316805148045842457568,853454763663288996214888780372138920872593497,0:86998056199797702223316805148045842457568
+mod:-20704801388339426733036642845379116124827,1435867681437150310057862989648368134,0:410577984280737997741465350352367453
+mod:2856130129221222388492861978859662650626462,3415046666744379998032348811600467386135912906,0:2856130129221222388492861978859662650626462
+mod:9174094790970904280083488936332437588,80223089031357892324412497824961233579,0:9174094790970904280083488936332437588
+mod:4534642237573685930694951916760916917,1687939078118830937441972536472082033553313,0:4534642237573685930694951916760916917
+mod:4953285485878049171718509399492969344,8438715605646215951383851878799856179,0:4953285485878049171718509399492969344
+mod:-5473561371563615410812461706913472604,214334897451541211570930222077036158481210,0:214329423890169647955519409615329245008606
+mod:32314040316433349581573558346471215798,854672171304077635036322002646520921344854,0:32314040316433349581573558346471215798
+mod:984601652834979681176881179524440398165232732,6010771562748020948016078628902359752985473102,0:984601652834979681176881179524440398165232732
+mod:698822785190474223385164957713213782961023671,150442537951079536547656264208689393334480936,0:97052633386156077194539900878456209623099927
+mod:-832138567182782528876254228044578514024849,377042837783032738781722401918006460405664,0:298989946166315687468912977709440867192143
+mod:-271707131793885697341132963275474633346,74513535025253601112542022792779088685,0:26347008307128707109035127895641721394
+mod:44640484386299773856766873434498216561663,5213123770976745902224829213477542076627816299,0:44640484386299773856766873434498216561663
+mod:-8174713099269176537506457338358109028363056209,7202185449263765965193807505095247595858978029,0:6229657799258355392881157671832386163354899849
+mod:12355340492830472409960851629397705304982,6132966232951258768476406645904988676022226517,0:12355340492830472409960851629397705304982
+mod:740672577198687499703984527131597058855628260,62988497968425244096425380714180031243,0:25908678444459756553419138341753752738
+mod:319004336538265669049369604224595570722530952,61211042298242370348907837021107959589032437,0:12949125047053817304830419119055772777368767
+mod:4806439359677487573544166219831820280885,5343125957234791643541038079815655996180160,0:4806439359677487573544166219831820280885
+mod:323024441762812965484474248139147756931591832,5765121910212312442407559411924073985538984,0:177614790923468709650921071399613741408728
+mod:4723337975870144045814369863570042890658212,89287300568064096399722912162338068807417604,0:4723337975870144045814369863570042890658212
+mod:4046612007916961296580001696582058791225882326,5729739966517853346267035412515108513431626770,0:4046612007916961296580001696582058791225882326
+mod:540533121775179300141141525507624112998,4914658151314087364162157813143111418270829,0:540533121775179300141141525507624112998
+mod:66280283111826907749579181590044353153733,204172771634272898466853823821147342141093,0:66280283111826907749579181590044353153733
+mod:925538924182292886302889784301398233703,1123951844806914762874832168405952076336884530,0:925538924182292886302889784301398233703
+mod:-9277230270610927782719268661989105709153,55678956296429757152650874683611007657644,0:46401726025818829369931606021621901948491
+mod:50293591559684931942237588278999569425818428,141131236033928957276244084171780508793074,0:50871531606223151894694313845708295484084
+mod:227536874010521150326799753293426594405370122100,5663713263329817356263170887251834777947840,0:2857369509067856283126068971384036093597940
+mod:-159636069245107191231315124801771805922519,5376563717710166640876235141463100221226553282,0:5376404081640921533685003826338298449420630763
+mod:296211412518831858845632004066852419532092957,9193193936667373505606545836126920558776593,0:2029206545475906666222537310790961651241981
+mod:86602967441811929071383589926953279497600400,29113787967675780279817029258848956369351891,0:28375391506460368511749531409255366758896618
+mod:935808235992985547250049168223094462501588,823359169504337998748976932597778859831206424,0:935808235992985547250049168223094462501588
+mod:1241588731631743791569571581848113730164929826,171962803446046629060145060037355991426961,0:17290751287129755324248378403472062271406
+mod:-74403542912395173151108580799350125207208,117394870062241902513223079179473780570881,0:42991327149846729362114498380123655363673
+mod:-97438192951192117314716964768364222640372905637,8024586066648229541713894611454280576509407,0:4355656117334010314857498525106400180823564
+mod:-737958699044282011354135601107494488027530,158340104707707507507946829328121909848911613226,0:158339366749008463225935475192520802354423585696
+mod:7238206747053249220557962252149262130217519,26583927802751023597693302694515406325578,0:7378384704970801985383919241071609660303
+mod:-76298303799498407827228786401180081621564,305509547184311996384274460275527665616703456,0:305433248880512497976447231489126485535081892
+mod:8484126595409899812717896552747684329372,304175476902105667248597679191320877778921077,0:8484126595409899812717896552747684329372
+mod:16618292546225677123057630920609252345178704453,1759703193372771615772702336566528721798637962,0:780963805870732581103309891510493848990962795
+mod:-86688490323412015602068918712338617474038884337,68055712910244091518751770267361236110795,0:60113101985245418861232982916749058457123
+mod:-2147105590126324395866565651207583306108779,8080551616254563514320925568870382437821720942,0:8078404510664437189925059003219174854515612163
+mod:8351518777266745029929974668820179263529631715443,175331741086869721483946575985451578498971069791,0:110926946183868120184485597503955074077991435266
+mod:-1795087841202144142663615322625965929380012985,35306979241856773462781084288773766694122468,0:5568100132551303938219976101496172020232883
+mod:1223266620160352395848150839920704951768,4664479506170256011858225502160377500533300400637,0:1223266620160352395848150839920704951768
+mod:39982725086518866718673198942063749137891,461771175994919359694841662569213792123219861,0:39982725086518866718673198942063749137891
+mod:357581778914196308302086292874528466152700626874,3109407409714291140644239657248083936467914372416,0:357581778914196308302086292874528466152700626874
+mod:149499532166554918559602886813953835372516,4116995844742979208794059184185312557100182485,0:149499532166554918559602886813953835372516
+mod:30162948061054933954336062823716515388316534139,210277285976133726432524140550436988594139754,0:93296166467811074485110725004026019354549317
+mod:52810485653680320320369005564031524621022350,82825120387123890672981225414839234585635496,0:52810485653680320320369005564031524621022350
+mod:7208022814700388108567430430861339898438,2633586073486065955736662183793128252475,0:1940850667728256197094106063275083393488
+mod:1133096693748508212236566391854344691508408508,2601250202595579849376374699877144432325855432,0:1133096693748508212236566391854344691508408508
+mod:24110493767768334678283829225780182918079966113,62617472892345734441670381366941494160023,0:11535407963705925298902727562240728070101
+mod:2029154393292042830677214368668639182381808222081,82610125404955917046846600049858255083588,0:65547351731225346301018769765882024339145
+mod:950870388742015370309491008506921827067333129594,9135792372038219712944984119888962386493530278645,0:950870388742015370309491008506921827067333129594
+mod:646334826846693204541658068926128186360010,54407099890316510058892785158311428336873182,0:646334826846693204541658068926128186360010
+mod:428552882985823327962705708694562616508577,141639571156330467462518777812629657176255,0:3634169516831925575149375256673644979812
+mod:21509351141318679646739001694607822320768,21896381149810489046647085552887947819439418684,0:21509351141318679646739001694607822320768
+mod:632728454831941197355087764542806015137812368262,222724285350635099362081058306677746403035965,0:191484436137515166777558951841215353190227662
+mod:29001858864232179857863618818997005925607,263069727005942155120496500688512817218817,0:29001858864232179857863618818997005925607
+mod:2833859942689944963761411216780529093075213667,24836085579076290404924895501933094503621863,0:2546186675247857599973129560156319662321285
+mod:87503819229335363919830481339117453040132756753,7265931585748836565776184592881080221565467,0:205142162125158187890287050603931819837672
+mod:3785119298527941754940929232952910144091163,384452066294060303214343786012747535262261,0:325050701881399026011835158838182326730814
+mod:38179577399511020742387225982022507255362,265561978107157383888631215376392729015255,0:38179577399511020742387225982022507255362
+mod:-42541955629872910052396184385091366868620,7073377596138431111003761711368230096543870670658,0:7073377553596475481130851658972045711452503802038
+mod:962822498059104139629105773638997541722777,291785910412123339651738662863457030701079,0:87464766822734120673889785048626449619540
+mod:-610694008008712552303733816313602703956727091,10013831675645158459604313031569589122775,0:9530562183081513694818229700258284829059
+mod:25840001817997722382069756182552718470600133,8684986931293242801082346374758755111010579020,0:25840001817997722382069756182552718470600133
+mod:65515204463103763906150928285942229386532511441,6904523147545678419356084749116545717835399,0:5088839190367063300396186324443615710245729
+mod:88029876839939054322959996030895683781141381988805,87155086119890274408175255450625302996948,0:42833542489532412926993261659835596440801
+mod:-140728222219088662551331451181555518857060,85465120005353614253381442147197316880331584686,0:85464979277131395164718890815746135324812727626
+mod:9386187660146534186830943256786039971200765327416,587965300048494341491681576852042742249853,0:156828577987386328282882864848506418512778
+mod:8015087164840320324802166753130112000577091656,6127305412955855242353538605784472950012242,0:571684694061667803738256764021381961079120
+mod:200585481998602232012071307195117379072828517,688377212094972591154108498471394888446887,0:267713278965207986225734139941466534784400
+mod:-2500594129935211199120603938323647766148423982331,1361156037555715012439087715972060812276689,0:599374805963096380934653500844754016423148
+mod:117111132825449273925221124600613715199470024967190,6687987114639191794225780163327374060501630866595,0:3415351876583013423382861824048356170942300235075
+mod:17302923664832474983271296805121649995183106066,41453082247135300103242413890739246798747574758,0:17302923664832474983271296805121649995183106066
+mod:804590820827842054650903665300245592864154,31922670356859924926370586627082780796917147,0:804590820827842054650903665300245592864154
+mod:1419527821402660938221344683778268760948333788257,28865159616287527805126478593002688908873146865,0:5135000204572075770147232721137004413549591872
+mod:-6349296345256358340236015836865079291052256775642,178072362342080585886203440168430935242413913,0:51806412867030122454025780494135951253706286
+mod:83483775554984848270591505226690350944356856326,500899723948831224438405152518791040164077250979465,0:83483775554984848270591505226690350944356856326
+mod:-5202440839318488047646864687648754749799822,423723177170085295356066936482198199652980649761,0:423717974729245976868019289617510550898230849939
+mod:525675600985546172797713152878987836214364203032,52969787195069967379407272322490869598290122,0:3432861671816524475382350588446320933032304
+mod:37858860128097787570803474618858008892810909590,5748777360917412753508983838083899279156995949,0:3366195962593311049749571590354613217868933896
+mod:45957868400560169903622579655897442394944091417163,62063277048172505864034466895124800993363976911,0:31043384912515564237074153505089659854748503023
+mod:18051383988929839561139635711444280609605686,829384533321617231836740782712342923300954,0:634308789175877692568079274485079220285652
+mod:2455769442319397759077734120262920951648644195950,902538521133892788023206849882232725042383975,0:864664835209375654611488583247939533359783950
+mod:4589658345087491870839566381729330015793440,513428177661658876831707141329481947688426657,0:4589658345087491870839566381729330015793440
+mod:-3573981672918561820060475190255839052046119,6138097283471921734295336167784166932835047133,0:6134523301799003172475275692593911093783001014
+mod:651620293244411254456830208908605775265324147,49737728886554678175954115600491082303192404,0:5029817719200438169426706102221705323822895
+mod:-16650974859063823766693159687850998551426028,945869854077417138401154817030148430752804974724,0:945853203102558074577388123870460579754253548696
+mod:-965598273519770488416791785443027019154228220991,58147062667685853263523283369280759917430291182,0:22901791830889017063104031834745899442086729103
+mod:28701469969197750610229907539580754650086642,3909053247766771922418857228732717683752395675,0:28701469969197750610229907539580754650086642
+mod:-8748391241949190130773015442145843092096091103,42809713885017092071880308569574525272117288,0:27600104479313743962447814616934588687952937
+mod:-6130419437464601359973583052365059560631450,2868142672962642021474985766046232299028848,0:2474008581423324704451374245773637336455094
+mod:95640797562953613006161464063899219827371659541,19819192346118145486800692560690336691790893,0:13194492933561032348122458568345289480600816
+mod:-5004080847919147880779643424152795003888630787668,21840420756428944369875564516044464145680642454,0:19215926059509324291736414537431749617916976752
+mod:2939482810778921033958889604777113454839240320170,566855177384622843277537161088088916192047616362,0:105206923855806817571203799336668873879002238360
+mod:291726867119014526479710686475643665173438062,202885774177743860764627132154911476520592335058005,0:291726867119014526479710686475643665173438062
+mod:8683025332039408014362977905935333328608348,78614799730964514801510410033797138266803757860,0:8683025332039408014362977905935333328608348
+mod:869468342614628804595566251564864548106595266,73624620788538462644074114115939464475401814111645,0:869468342614628804595566251564864548106595266
+mod:4728910553503250598863512353801889257516953314,648895113009231703768170210292430028966664779037,0:4728910553503250598863512353801889257516953314
+mod:760566451760297307988377549048192013905533937,2697105353808446098263423690773776969485171497,0:760566451760297307988377549048192013905533937
+mod:918153477317716353524438631647119722202588746160,40888243303074949046907063669422917592190788906358,0:918153477317716353524438631647119722202588746160
+mod:-1473776558819659703245310105293049377337981709,31054248040311137303584740614306271791161270545,0:29580471481491477600339430509013222413823288836
+mod:905086443229432348861962052611640110347186013855,16319880347082113262021644716353623982591699522702,0:905086443229432348861962052611640110347186013855
+mod:-3948357993060778828570152166999624499401960763170,77670033625089877508398637915359376482388910,0:75836304290184446800990065584763456761865590
+mod:-784992783303820924306757780883007042021257440780615,463574560419641941889185992215306604381633902571284,0:142156337535462959471614203547606166742010364361953
+mod:3823677606013902933129598925384688189274201201551,99529942495899622221328610053601822241548249,0:35805148927146252817712955466984220642119718
+mod:12254504447986771204864826285146960991558427605699,6125051499311360686388425114933437945893268599,0:4401449364049832087976055280085099771890407699
+mod:-2580894945525990910646902811077109168493411986,572510241156643657546678509117136144990147708808871,0:572507660261698131555767862214325067880979215396885
+mod:343089829587091844514156149817937152291781907,43377295017128784286263228943698366029281236815,0:343089829587091844514156149817937152291781907
+mod:7853011116124010483217978861490662971029642862525,552677408447001109928623269020934228695696472,0:17819500571712242170831972208515492491691877
+mod:887815431705947711841094597810602130602260715,8486574430538892118817816797303238023509341587403,0:887815431705947711841094597810602130602260715
+mod:67620759311796073899200379294956624554814285201520,87303800600842937580229698689028406709310049288843035,0:67620759311796073899200379294956624554814285201520
+mod:-38490591886267408374352863050032614782701178357,66475506278603268018635318767149490286581760362179844,0:66475467788011381751226944414286440253966977661001487
+mod:-544395011810833021655729041737889469872310533646777,731611503205277837707380015577043727374026342728599368,0:731067108193467004685724286535305837904154032194952591
+mod:8890962095194591840604729292735591304316116728,517571143480065164208802281191733497859755993101179949,0:8890962095194591840604729292735591304316116728
+mod:40588319468481766273347382652716318465741545598763,1536971037850601936767123301111618687777305090,0:1525271960920929137957640261803777606250087133
+mod:48235707095020151632145028961335649832134676937,794868261145529770762797624857872107306805378170,0:48235707095020151632145028961335649832134676937
+mod:-9523841594085891512065672092684699107288546273626439,473487777070786775175577792880772873295554421457750,0:419401724400630766621461557811531231918096576986311
+mod:90074633895471637214960779532906651648038212359500386,820079595762158387084577717033680869242497989232,0:371415339208611139101404795279693919203214214434
+mod:502553209306579947121167024397370721577297298727046100,52494082558436951205873151813775449908847817944715,0:27356974663013227343342084098339599897137542289405
+mod:5790702792462693399581381818523043045468711777,48910417508813857701976328940621637734412004053009,0:5790702792462693399581381818523043045468711777
+mod:8115756631582685507536476067391256503367264361488762,84450889017264877905314659939101106548473815858544561,0:8115756631582685507536476067391256503367264361488762
+mod:8194219075070331821784044970434313099982993771,652282608320462546135364960046755034411967968039334154,0:8194219075070331821784044970434313099982993771
+mod:75033785162139990322256697516355737268216190660,50448201882288504062521017516515948614320857837,0:24585583279851486259735679999839788653895332823
+mod:-310420971441772166248782136661913235149811988,52251157147894938842540415683732209931823110303,0:51940736176453166676291633547070296696673298315
+mod:-465851374976907401549861928175506333511972756050,404205507663774789620852323466440811463681452434704718,0:404205041812399812713450773604512635957347940461948668
+mod:86727934051201027780798621123886995870064920795,2623457841745489387377116124239592088889194223622807,0:86727934051201027780798621123886995870064920795
+mod:-2164209564341937597697994551840383739114494141322,5822096741927098565898057075974774660691292113200355,0:5819932532362756628300359081422934276952177619059033
+mod:-21572594290097356729450557279398987661535311983806,95173892429181732470545230031265828462190645462413613,0:95152319834891635113815779473986429474529110150429807
+mod:896154498632105428944035878874928031422856104434543133,2920373159440158169043176499665564441266475422,0:603088578315357918226288933626857244348602913
+mod:-28106796449976334513237948147051254770072052831429,8250476728385872623793527898989079209376092358,0:2577763634333516026601404804538096272293832277
+mod:-5910781525258418818015395848760618489911223430349957,51598547888760073234245679451691550056130732598,0:38529590602611260383715148455335218776511681335
+mod:7727963353453460964292856120418469526804141877435331,9692488255114907303703797109203796514048948603078,0:3050214126879843240929824383043705107129840782165
+mod:937009697498591315869575189938875974899784631458,9231715369857992569685209191243252034527233388658,0:937009697498591315869575189938875974899784631458
+mod:190934454146310086697642361797951041146551500749,10448518118997830258656577725632025806308987954,0:2861128004349142041823962736574576632989717577
+mod:716842295935464600709869948911248187992875653195892447,401547841844896246538515909881184133363330747247974,0:79398242324800638619049773334509939330269358258857
+mod:-538446228722400194015060345964154302722009578079,57520540642458327434814547831209263785958735384,0:36759177702183080333085132347938335137577775761
+mod:96967488061013453069137268213397106742518252838974707,4323900098433218426906897807465481156203036443592813,0:1841685895482647677185516449156521306051451079932821
+mod:4248753403571933538992485400308861658493364877663,939067422305299585909602271217318347813010825877,0:492483714350735195354076315439588267241321574155
+mod:-107460187565073890428227205420824162161759055432,282612401032124761876915123928433707969500860981828349,0:282612293571937196803024695701228287145338699222772917
+mod:6649481706449462881752315195565911763474357952858741,659725471155847914828668487679599556025560898493899721,0:6649481706449462881752315195565911763474357952858741
+mod:6305756385410127441079092163742836866873755879,9919320027008577000539126363765101039097548804251,0:6305756385410127441079092163742836866873755879
+mod:-38180683008697554526126494541279186939566773312,4697678019691033242250502480954454444789783096,0:4098419168521744654128027787310903063541274552
+mod:627353070533528810361133250533207881585454632738,247981734193053924842956535127898645616700024063945,0:627353070533528810361133250533207881585454632738
+mod:-977100235060594126432793245647088458561713536019153,711683384963018548537977961275571093400571875056194861,0:710706284727957954411545168029924004942010161520175708
+mod:1498139275498305618541952433970427820083740864078175,3957896946470021688374936335906211866428578229500974,0:1498139275498305618541952433970427820083740864078175
+mod:597201805617750253952058296204205724608800648357149,4978798146323419820714075023507404888549551451,0:4925562548693297046425284539523037059050912601
+mod:-56676822442119009829407208281675487240867001784809049878,6406684614200209335872193933373288202798878241606,0:2690987740863316857560626374071228113763853811606
+mod:8685426845950882129513316465433060160017749608742,5862536885517747336130664930278619887073507404339873116,0:8685426845950882129513316465433060160017749608742
+mod:-758552875949625615550950682460830448030408807239369540,6928982530621565423313581311775944174511467885237190,0:3635202418746581013543261834523411165852660136721360
+mod:165930319304414878413873653644927162776703980852674518,70941371417197323006528137030561117730233179743191461,0:24047576470020232400817379583804927316237621366291596
+mod:-30974844728461949004845422334486602888821195017,323336199778314705263073710488111629703644763021,0:292361355049852756258228288153625026814823568004
+mod:6133073724222023714159452874993644151837626947339205812,7463402457118308536507525382128605388905979122243374,0:5620306927892405686774536266059127545818087977395758
+mod:45342828302867171033162078210088228770176829233725,826633934789479436275857854693648185626420538347806062,0:45342828302867171033162078210088228770176829233725
+mod:-26272751936716551812042161754718676251990474722,3726791277147420607688434457942745910700285747248,0:3700518525210704055876392296188027234448295272526
+mod:-39318997476790646356737814318350583742657677501,1994697821466452959618065249537163794020403205602,0:1955378823989662313261327435218813210277745528101
+mod:8027107780836872755806128697397537471698261298622,1333439935985760787392296885353944866764267524928758610,0:8027107780836872755806128697397537471698261298622
+mod:-55936499409386931117510358618192060334282485918550322,398438202364094320499957997907168092925880758462,0:239820508270537478744707995268231581913761929858
+mod:4986596463362462090356441596215520136635434728102133698,904796510225702345660178949801987674355175932951442952042,0:4986596463362462090356441596215520136635434728102133698
+mod:206550560537111820336709370332003111271041434735753,8863245846520291116010486302557366093750491313639489405,0:206550560537111820336709370332003111271041434735753
+mod:576258003770289338613512178842212632031473801519,112928562274312812079466249863533328301249309332,0:11615192398725278216180929524545990525227254859
+mod:5044250943493799862304047991036206572453520324334513,35881021726135630824830413448736592392545545812443121,0:5044250943493799862304047991036206572453520324334513
+mod:905588871665990684975164361624636275705950128546215874,53243625735815790460446478875365074647441813141773592808,0:905588871665990684975164361624636275705950128546215874
+mod:5991116388159027989458739990542641030328044128925695503,721278676327052740788584942208715418345142864101,0:431868180450652741834416094047706629629986812960
+mod:-3474677351996973979038623915159768162722810109611432906,763685814389121867002329466465821059768201256128129,0:93103473530515821975157259717659222505605771554044
+mod:8460371705356400367952890710394988728910116421931757,6311797752969747892862660456068082967585770509045488820,0:8460371705356400367952890710394988728910116421931757
+mod:-264756559717037431451787362436705748418817738411460,7816554223015299624827224356467518163226383802462318164,0:7816289466455582587395772569105081457477964984723906704
+mod:84752881980947180661815959615676455311403364453605403063,52250068596287507582088091160391730925462299132305704,0:3270717768843363669075753521067750303515261005551175
+mod:64938454622435247872445936607970411171632403906819,964092617858022639258083183616152671542900110410,0:344249225947731042154363305688182178258096509349
+mod:40144089093980612505699952982513757457937212093962271,10902061466143734099157856887908326325446558980281568,0:7437904695549410208226382318788778481597535153117567
+mod:107130104935801948815478025681375166396055326914961974,6641641026382469722494881921027536542476581953333157,0:863848513682433255559914944934581716430015661631462
+mod:375770000201081420238670197853908213239792155799109438568,741847952379716980656595421052880669705080727039,0:186232142856874724410035514392651753500883140216
+mod:314494472877016149904621158951181139298853721401432703777,2289213676835383723493513562354885152593212937649884,0:8739694298587358772241304662150445534814153989973
+mod:491754906560818931573946605055051948215890543148276100,5346198427406770324055146743032112633140429155293,0:882811089383626706097337472163994367588586115374
+mod:831402402931313770942586028473722467913682852291371107996,249203176454681279672468752353764682559981472637056324863,0:83792873567269931925179771412428420233738434380202133407
+mod:-927301671513394245404756806010463865731294755475136031104,128994162476254345599482066271274174336327781183511925567,0:104651628296640519391099724159729528959327493992959373432
+mod:49063903583376380376914162724558461583861450724317254,941774744692403469242853096809411489238020290379296849870,0:49063903583376380376914162724558461583861450724317254
+mod:95814446741364664911508702682923954900446789248313,2444989997188453542574239416826458624894367967952,0:459836851014976751113365426692068529566438498185
+mod:96634339550441353817958772505469549255037435683448,78081012036785909772650615373227006202901241216144834,0:96634339550441353817958772505469549255037435683448
+mod:930319417728873563211760140268194907413484971952354004,89121326206650943149280333205573781193492882117302434,0:39106155662364131718956808212457095478556150779329664
+mod:296149508458734377319788304412051836966914377456545014105,5775874526745986573435749392656102466476051398568,0:3756015598637200337676470424188468229410269716225
+mod:42844020401978935822457442747009223068912783208882,70773879393663215011878508613578824050038059978191899,0:42844020401978935822457442747009223068912783208882
+mod:-90593635206751701986722625420716592016545661236480979772,6587808211180976790034063002169935351319078136248018,0:1903313409090829825808985124358934794301293201763764
+mod:5733125812846132405536083211632006878958607745362254467,12605191511011498307650361584364883404677231252914573,0:10368866846912173862819052330349813235144756539038325
+mod:95998165422977408040950062135290204359238945742902842,40371405656826836301445165513921557692353024588296,0:35334176700018152414903708698661724515806296523250
+mod:95998165422977408040950062135290204359238945742902842,40371405656826836301445165513921557692353024588296,=1:35334176700018152414903708698661724515806296523250
+mod:95998165422977408040950062135290204359238945742902842,40371405656826836301445165513921557692353024588296,=2:35334176700018152414903708698661724515806296523250
+mod:95998165422977408040950062135290204359238945742902842,40371405656826836301445165513921557692353024588296,101:35334176700018152414903708698661724515806296523250
+mod:-76855972323011457703707050993748256077521513979037807,1910956865546821689289334552684591792222791353473,0:801852416163817820695380673341213886931466292780
+mod:-9872019059197505082121902831056682448354872822219660550903,908082149115602660075723278246449391327542696231965833,0:650065987327038221360650038715334158171371214271985473
+mod:595855064966654171339977100486303810714342893653637711,594549781214651234933649045428169123584477791281395609,0:1305283752002936406328055058134687129865102372242102
diff --git a/polly/lib/External/isl/imath/tests/mul.t b/polly/lib/External/isl/imath/tests/mul.t
new file mode 100644
index 00000000000..b113018c569
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/mul.t
@@ -0,0 +1,864 @@
+## Multiplication tests
+## Generated and verified with GNU bc 1.05
+
+# Regression for zero-sign bug
+mul:0,5000,0:0
+mul:0,10235,=1:0
+mul:0,-58382939939929385885,=2:0
+
+# Basic functionality tests
+mul:0,0,0:0
+mul:100000000000000000,0,=1:0
+mul:102328632557663,995533253464107,0:101871556492663391138178301941
+mul:1099511627775,-65839281,=2:-72391055023845629775
+mul:424417695707616156,78196371461084006246,0:33187923788210071918733291062874510376
+mul:8785533773682081,509516924811454802,0:4476378151193669633826349848802962
+mul:3149810015499242805866,671806182669824281823,=1:2116061842647726364810477474851492861573718
+mul:7004291671016071522932056033,291108610609315306035746008,=2:2039009616651887991790118373228449729743842556412066264
+mul:62479450738832647,8434970263250341371151,0:527012309046267948145296885851102766697
+mul:9472845009207216089,8603477481125780254532680,=1:81499408718909018140819102866811806472288520
+mul:8704164997261749,601100642928524,=2:5232079176009991665860326228476
+mul:-18665805686013,-2922920804055208139127600955,0:54558671764099393911694170691186688942415
+mul:44144326678357949,-81195051773905850760614924,0:-3584300890173486959579517806592053823430876
+mul:9685579959286825,5953064636346354,0:57658883538135357049439528986050
+mul:-7,328492456,0:-2299447192
+mul:16522181,930,0:15365628330
+mul:844378,24,0:20265072
+mul:209,3,0:627
+mul:70522336,34102,0:2404952702272
+mul:32557663,995533,0:32412227919379
+mul:641,701,0:449341
+mul:290748,-233,0:-67744284
+mul:-95,4770,0:-453150
+mul:6839092,7,0:47873644
+mul:787590783,-6789049,0:-5346992417735367
+mul:721,15845,0:11424245
+mul:-37028,-949534667,0:35159369649676
+mul:618,-3,0:-1854
+mul:16657,-544851,0:-9075583107
+mul:28271,6,0:169626
+mul:-35357673,5207718,0:-184132790120214
+mul:99,-565,0:-55935
+mul:9311525,-5,0:-46557625
+mul:6221599,7764515429,0:48307701428550971
+mul:21590339,486739392,0:10508868477933888
+mul:335,3699183948,0:1239226622580
+mul:14,8755508782,0:122577122948
+mul:-5302,9,0:-47718
+mul:8236,9462435,0:77932614660
+mul:43040,2766705,0:119078983200
+mul:863478587,63,0:54399150981
+mul:8874055124,10,0:88740551240
+mul:8204,-89955,0:-737990820
+mul:3303887262,3,0:9911661786
+mul:75504,-62,0:-4681248
+mul:436,2123372,0:925790192
+mul:3361227,943089540,0:3169938025265580
+mul:37340421,223177728,0:8333550321343488
+mul:-35694701,238293550,0:-8505817017478550
+mul:4263,15500547338,0:66078833301894
+mul:1493,38730799,0:57825082907
+mul:-635007,298501,0:-189550224507
+mul:4968,-98492710997,0:-489311788233096
+mul:3367542606,17576297,0:59188929003209982
+mul:232155550,3921719,0:910448831390450
+mul:4860966,700,0:3402676200
+mul:2323372237,867,0:2014363729479
+mul:4268,-29035,0:-123921380
+mul:8,-73804207633,0:-590433661064
+mul:395170,26163606,0:10339072183020
+mul:-70027196,6945032910,0:-486341180815020360
+mul:5871172260,26773591,0:157192364779785660
+mul:17125540,836,0:14316951440
+mul:1988202315,-68060596,0:-135318234527479740
+mul:554434367524,-909419,0:-504213148079308556
+mul:-40457802353,3398,0:-137475612395494
+mul:410791452776,4492144466,0:1845334551267808737616
+mul:135751970,7417878752,0:1006991653805141440
+mul:9593,31047471995,0:297838398848035
+mul:-18387143,50226,0:-923512644318
+mul:413450673851,-124,0:-51267883557524
+mul:-618513698871,-318914624,0:197253063714294189504
+mul:37416674596,-8817,0:-329902819912932
+mul:6242382,-943205,0:-5887845914310
+mul:-4949666413,1501091102,0:-7429900210422557126
+mul:-6385784303120,899228089,0:-5742276615660794337680
+mul:6308,-79643949,0:-502394030292
+mul:2421,136928,0:331502688
+mul:333180111,442438,0:147411541950618
+mul:723761305,611024432789,0:442235840862251429645
+mul:-91289,-9223787613074,0:842030347409912386
+mul:10944,57098,0:624880512
+mul:57145099,-94544476,0:-5402753440923124
+mul:9327105307,88173695233,0:822405340745514901531
+mul:73230770347,67182928,0:4919857571607036016
+mul:4810254287,-4310,0:-20732195976970
+mul:7200253992,9893,0:71232112742856
+mul:-92709373682,-664752121448,0:61628752833224878931536
+mul:-2236424417,-69570761,0:155589748609671337
+mul:781963714,61084006246,0:47765476390121357644
+mul:78553,-3773682081509,0:-296434048548776477
+mul:24811454802,-26314981001549,0:-652912961735421705488298
+mul:805866671,8061826,0:6496756880801246
+mul:4281823377004,2916710,0:12488837061941336840
+mul:15229,320560332911,0:4881813309901619
+mul:6093153060,357460,0:2178058492827600
+mul:624794507388,3264784,0:2039819111008224192
+mul:2632503413711,-514594728450,0:-1354672379322310051777950
+mul:7216089,86034,0:620829001026
+mul:112578025,4532680608704,0:510280230883694129600
+mul:-972617496,-1100642928524,0:1070504569131119855904
+mul:86658,-56860,0:-4927373880
+mul:2292080,40552081391276,0:92948614715315894080
+mul:57144144326678,3579498119,0:204547357129208422518682
+mul:77390585076,614924,0:47589328137274224
+mul:685579,959286825595306,0:657666902604804292174
+mul:346354116,451435163995,0:156356427156803253420
+mul:443946215999,260668,0:115722572232027332
+mul:640447120070,-441698,0:-282884212040678860
+mul:1253208493501,-8521171736,0:-10678804794135860887736
+mul:8507343,62395589,0:530820677310027
+mul:81126006,461820852819773,0:37465681276782021316638
+mul:87891707090,40954510522233,0:3599561842834425768731970
+mul:-767589,-991593,0:761135879277
+mul:86229155,43027930,0:3710262045299150
+mul:-431963821,48986055721,0:-21160203804962069941
+mul:101557073166691,-74080192,0:-7523367479146517284672
+mul:-34269048183,250074,0:-8569797955315542
+mul:7650667716360,-959482143,0:-7340679055874008959480
+mul:-176432105527291,712269105001105,0:-125667137897384071121162656555
+mul:91973525400419,-52180215632622,0:-4799198387886300095948868618
+mul:9054526,-21388581343089,0:-193663465874114270814
+mul:19326311972,3180878,0:61474640572871416
+mul:501569850634,39035351302,0:19578955321989857425468
+mul:-3470290487760846,622612793613,0:-2160647255233400713100276598
+mul:827793089252612,77591849874263,0:64229997108241062748844324956
+mul:19866668332,4414961,0:87710565885715052
+mul:136274450771,8659380001,0:1180052253653656430771
+mul:952660786088689,171372582380,0:163259939044179413638699820
+mul:429415374,9140880954,0:3925234813551386796
+mul:-368107346,2945634,0:-1084309514027364
+mul:2147845929,79983807840463,0:171792896056056736025127
+mul:77885771608,-51236668812562,0:-3990607485089940493339696
+mul:62272695670,208399244,0:12977582699470073480
+mul:61973019,-1405255816878779,0:-87087945439289091663801
+mul:286206733986,212837117931767,0:60915416394244148267933262
+mul:-131938894,1048695278656631,0:-138363695208977699906114
+mul:27109492,306933238851468,0:8320804183177960934256
+mul:-314477095129839,3837918787896,0:-1206937551761766779621628744
+mul:4116345,9101435151,0:37464647076643095
+mul:63853435249810,902940229903,0:57655835504559765637068430
+mul:80076033,14791385,0:1184435433375705
+mul:-31038678,1454704764,0:-45152112754861992
+mul:20638192722,-14267370499730,0:-294452742009605188965060
+mul:8065790684,-1977228453431,0:-15947910839823487636804
+mul:362687955673,99742877979696,0:36175540507397430642015408
+mul:1235326072088,201675880263044,0:249135473000235948746315872
+mul:568009735,49546482048450,0:28142884138522341660750
+mul:849579042,-3197920541,0:-2716886269614901722
+mul:1808291492597692,96814519920612,0:175068872732372459073494427504
+mul:6275712123233717,739880208952795162,0:4643275197065752315694969352877154
+mul:774075573665981,7523229210171,0:5823547966683781965601892751
+mul:2944466357361,497012903828640,0:1463437774497728631346619040
+mul:282862415058866,-6240991940068,0:-1765342052530551975764042888
+mul:571225883598025,189932649930728,0:108494445780794463607647612200
+mul:815309478,-371377784,0:-302787827213836752
+mul:320172590239,777220834144,0:248844807655600692320416
+mul:654332382,7919190746613,0:5181782944743642722166
+mul:-5094673003562,268414312780910,0:-1367483153094548874555601420
+mul:-77841790209187781,35267718271550,0:-2745302326850733800658699930550
+mul:735762990564598234,-32739891496,0:-24088800477857417959993218064
+mul:-5999905013129575,144027889596460,0:-864153656820273314848441304500
+mul:6861193105404525,-4725324526382425,0:-32421364061213996907214475473125
+mul:859748569384694164,98523184164,0:84705166636223755282588018896
+mul:570460270963,-54720108308,0:-31215647812506387460604
+mul:61750383079701,3452251304617,0:213177840547497299540279517
+mul:-1738716695,8560399484936237,0:-14884109500328036282376715
+mul:9953417006786660,90085339160,0:896656946857288287863605600
+mul:188523146978,954842405502,0:180009895153280621872956
+mul:198834734074395695,171072375577893,0:34015130305505499211880376370635
+mul:-102893613303732727,155104650554,0:-15959277935713870085148480758
+mul:90836124710855,-98332551310,0:-8932147893931708201470050
+mul:10512242068892,84377075433,0:886992242016856266730236
+mul:-726835478343584190,29339956106373,0:-21325321031155383354737721042870
+mul:5033847480079150451,-69469662902517,0:-349699687543783241256712189585167
+mul:3869558083241,-8770208065,0:-33936829509626159538665
+mul:46079368203995132,23609959311256,0:1087932008384708532422296805792
+mul:979137194422864421,-1378816153373947,0:-1350050180039492392646639294639687
+mul:-72618673468,-244198092166982349,0:17733341516582659732950616332
+mul:529564016606,376298866055896536,0:199274338952843762914521876816
+mul:554186920892,-629719688885314,0:-348982415408420361378580088
+mul:3455963977845612750,271884481278417471,0:939622973433450671239608280300355250
+mul:-41270780965441117,-4124462824121691009,0:170219801814430998805436931657817053
+mul:47581683736,9394210662450,0:446992360690054950913200
+mul:8196306676684,76732052476696223555,0:628919434030412315441895170091620
+mul:2939970750639,-2013582768244,0:-5919874442628068251907916
+mul:70476757656499,-100957934015971,0:-7115187849144405009597945529
+mul:3674841030712174173,540185467629182772,0:1985095720638163814590166671314947556
+mul:82915322420038008,123799513890,0:10264876609633323785723931120
+mul:466513077506,73565730651787738,0:34319375405342972915054421428
+mul:-38890216282311653,91459939591112,0:-3556896831865504089438972828136
+mul:576595981539992,20909590051109791,0:12056385599118501431228849261672
+mul:956905636477652,8381376662473,0:8020186569762664723411553396
+mul:9187294026565993,54295427509,0:498828056823282593136101437
+mul:8866081281165098,6545042142269515,0:58028875622012459166053127387470
+mul:338772425501,-750860960783,0:-254370988898468150127283
+mul:6750486296504,8609697533187,0:58119645214823136262078248
+mul:736067207074328,329259058372493427315,0:242356795500164369960320250670469320
+mul:680100030114145,52232423165123,0:35523272567534917195872964835
+mul:22697310250913136791,365228836596285515,0:8289712216805950219366224267686882365
+mul:30594845950075862222,37349482121506846253,0:1142701651822614557685156508694964954166
+mul:866936756424,-1765396942933391,0:-1530487499507519421423353784
+mul:6939438360479781,24559856763503,0:170431612152541518812930232843
+mul:927595346004843560,7670228140092963222,0:7114867925545619902286593484943550320
+mul:-357321286444971587,7925597841132985664,0:-2831984816439127983772762412958328768
+mul:6673370692769029,520191499051311630305,0:3471430704396611186160057152801823845
+mul:9013236794945,1008467412252240244,0:9089555586614859880726704766580
+mul:406532185466775673747,9519149309169118189,0:3869840572441069484183117712436347484183
+mul:548046408595014443,777065152533771,0:425867766090470284154159790254553
+mul:23897406396584,-8555442893510156172118,0:-204452895728978731648341501271244912
+mul:54729344028716311850,2026849525600172204,0:110928144981012274062113279423765817400
+mul:-7936445752013,-98698488318151151,0:783315198342695407195996516963
+mul:6309028281362257922,271678876766048827,0:1714029716965733695518439315219557494
+mul:6357785774765671053291,56936125648067424,0:361987689715553942195290680512665092384
+mul:11095109588014,9104811531028000846,0:101018881714969199044361103459844
+mul:-921590308699737078,472826384755153630,0:-435752213887882691328892986497293140
+mul:652120832633171211942,-3387083844442113181,0:-2208787936835953406166467995677302807502
+mul:32731949302549,335896184427699,0:10994536879607092557766904751
+mul:3635516318567409721998,16713986701316425,0:60763971400954533716595371769881217150
+mul:6746198240933100303896,2007405485449,0:13542355354775500078274959306009304
+mul:-19072614334803913032,-240759760944833349,0:4591918067840391824783380728329304168
+mul:828472954262165857,127978158379025077,0:106026442953302260750986298136195989
+mul:8306750095431507743,6378030328941226919,0:52980704043597587430846783712468533817
+mul:7938532173109072,7646615157112938170608,0:60702900440124541070347993363328555776
+mul:25274397567311,3125247753747112,0:78988754224550174717491855832
+mul:400327281633151431,37147489147345586,0:14871153349853852722430493627433566
+mul:28164658061513141691,818613450005821036296,0:23055967903969532636848840948464301816536
+mul:476291935913056166817,170589720180888384,0:81250508071821874441129615756761553728
+mul:84130837655605609,16051948347568699941145,0:1350463860485469013094700782617631882305
+mul:438146043336536562159,-2206822496905640873917,0:-966910545365262749689560255553699552306803
+mul:8120293725815373571,24028314574527126,0:195116972081450718759827878362986946
+mul:-667658265953408,8440015504605457600699,0:-5635046116424757633428637247402232192
+mul:53314441150262832895,283247085055963859,0:15101160047199676268547968068076341805
+mul:6658153298145442,2140281300389057549,0:14250320999144418995877331910041658
+mul:213046498706732967,784948480361985741,0:167230525406291802914352434748623547
+mul:-3857522843819,419578526133778265155,0:-1618533749336956944635887834826945
+mul:-4948941087660882967,-779517282262677550602,0:3857785106731510951136294197380142396134
+mul:4277076043224464,448010594023993,0:1916175378810781677476700564752
+mul:-644113523059324254840,-71225587742718143,0:45877364252933205602125580469623562120
+mul:264902435468141506,-823887292259809475,0:-218249750270876020336340975899569350
+mul:1538706915662950684,448326823774496344436,0:689843584219022500302744788239345794224
+mul:2036808313025110180,30422160628736748027,0:61964109668796220999356441366572614860
+mul:7385426850078311,9871854919284839,0:72907862380963907579111265026929
+mul:804644713550364054117828,8379163811459445,0:6742249864863361798556496920366673485460
+mul:981008037679996757191201,-641409668917881464,0:-629228040654107304092567432937180101798264
+mul:64201713053871850,879119102660231895102,0:56440952369169517073431323344150678700
+mul:1033957429367195,1113485105415049436,0:1151296197233604656037339121652020
+mul:14455075580451942850,-1885962875546302716,0:-27261735907948286986307866636431780600
+mul:2615475057635555327591,71606675442458157933637,0:187285473579953754910128144228132079173078467
+mul:596676024530775,2621192750454214313695,0:1564002869869908372861756951031463625
+mul:71665682789483848832034,351563529541544408090967,0:25195040388475655750558432995602321242575636878
+mul:5092055214749737510271,-1833800774226189505,0:-9337814795210574311088704576082129905855
+mul:600508413963341945,5057063373752305154,0:3036809105884103889579068197287884530
+mul:-92318043858914149,958444935645415778103,0:-88481761605267642819033271229511079347
+mul:385447683586530283,1775981280157037775814,0:684547870529570889684189390051875975362
+mul:80717517906672139,362327909576030289130356,0:29246209529290308450092391020660324351484
+mul:31249856290116188,7875872084416640,0:246119870797357830310409800568320
+mul:5339381130045070,-287550419156538713298378,0:-1535341281980973219291224752615497896460
+mul:-28993892995370333046,698005135756870427,0:-20237886216353643864566444205658230642
+mul:9179674525723481348,81469928617693608886,0:747867428344352459523920577957828058328
+mul:7522547789649675160016,285918417200326088447794,0:2150834957330446680178114494867165936012204704
+mul:-901774653467788803,236000195734098992,0:-212818994726447447848669649751186576
+mul:142671415131788790,-2583777714764598301032762,0:-368631222951444570172731660827393454337980
+mul:951078283105727024828,1487627587101952300275691,0:1414850291441640178530450466337072693601856148
+mul:19185476025869672486,2445736876347152429980675,0:46922626206743672591769434078619109559208050
+mul:6741226163186521681303,2568160083399218078514720,0:17312547945462088421236893499979478635434280160
+mul:3987919571578399660412212,9884144363611069680876,0:39417172755950910755988046816263833157453257712
+mul:99431631881940059268,-291965406586754754564989,0:-29030596829995156232729757591886192217768052
+mul:36727416735327035,-1612205593089728906670,0:-59212146680431557459581110615442823450
+mul:19590774006340220367562,984968880458891391,0:19296302740348077288926838014277057458742
+mul:70695613219926859099201753,62591913993270611799645,0:4424973742363186825608316839246937058962268777685
+mul:77425442645246583405,-296832015660977965,0:-22982350203831985042851014697239670825
+mul:807971872592227526408,40230405885131399744453603,0:32505036378154987781247713889763216622213248024
+mul:965370212546292322,92058451234918953535616,0:88870486635336197062343410079373774340352
+mul:418561885926860582,239657399821326936,0:100311453245542262612436139913236752
+mul:4657697584188823828175,78713797195009784682708,0:366625063037526091489561582727843402285697900
+mul:-38091455008728662,5763777114003492300442812,0:-219550656618403959076635804481627756277544
+mul:54943065861736600767,6268390929335695219433,0:344404615677603400985934681975925581105111
+mul:-697639190379957186138,2936028900796584636,0:-2048288825283884939792000285015322975768
+mul:96018089280939789090187,29566309848085271814423786,0:2838900578701380961562729671686086004548591987982
+mul:-1112368751522257152114,1995174854903534746993983,0:-2219370162417645509690181099382354083873730062
+mul:-84342841213955171500540,5699084396809137598518,0:-480676970345002579334276102870293770140199720
+mul:225675029492277024520800,92998377812004114915728728,0:20987411655457949896280985578493804059256993542400
+mul:7655269162163547244,594548791001649285,0:4551431025156545678791700910016320540
+mul:17608380663675562604,264448308193844308642824889,0:4656506476542203967645749547080047894928850956
+mul:223093179893694063251643,17908241494426478956477995,0:3995206541295803079022953995876886965688677095785
+mul:-9501451313199296478183,164266650410143061944307590,0:-1560771581254303549338241248628058185171476308970
+mul:4558730178677382262,3122005086984557462,0:14232378808020807989791594528678539044
+mul:54440882483631228680923933,4478571958703194374379,0:243817409698246737082188977425300200477623112607
+mul:36855929355558415329723,308635436762628905,0:11375045853945367585945011810669865443315
+mul:28683868680975381560,42902583850929860163229,0:1230612081254607193977374775224312156657240
+mul:24731088466679335541839144,81462858536522998396,0:2014665161215334180518726488874060847202013024
+mul:-72335534127835253275,-227166439208550011362,0:16432205716068881729381218555965397710550
+mul:474777034176054735892,839001319154604024448982,0:398338557978020441829154570519593836838261944
+mul:6299666296143449904,797331145004636509,0:5022920141051174455685525850770945136
+mul:8540885149755672764459236,41765710483565552588310,0:356716136438079846570195465527416281897285131160
+mul:385990739803366398,2963466700114736836981086,0:1143870703959928224960974233605962253948228
+mul:-37246197932269024,3005402223074948482,0:-111939806066730874158935454164421568
+mul:-751622018429096822596,3003864133422104297,0:-2257770423049491832679123307914818295012
+mul:-6108319432277782804,-82931541043539126216389,0:506572343704992558730984950135146447174756
+mul:30921518942393713547539642,721143788088068568685,0:22298861303554770289882384831917605974237310770
+mul:570903751254308471830202651,-564896588437884119958,0:-322501581409949262735089396741686909437933608658
+mul:1054271475454361570597270062,16484741384321323400,0:17379392621732016481140067393169300655040050800
+mul:6529831639822170310307759,85346429845722052312845786,0:557297817952459046702350223377401463955562766253574
+mul:-754058902141939454006,69516695016006129145191,0:-52419682724305615903366455441899934040585146
+mul:976193241125104191848393,33823563038032982713854,0:33018333628496693179640404511073605465668736622
+mul:2920092456500658009757,8895875497550350532901302605,0:25976778934365816392930294156133718389132099516985
+mul:9994369499844252132394601638,93334243646132127297454621,0:932816917987935116609350111907831170748502078677269198
+mul:569015432462996733746,16322837154963292812416483,0:9287946242754509292015515862839485902412735318
+mul:192500272569416024937360278,-235265435750733300361,0:-45288660508178593749288683427056889794244460358
+mul:5267095375035104443898399000,-764192677627393558125306,0:-4025075717966937142285931052847299736560774785094000
+mul:51025753118541843018,-1664207936338749988204,0:-84917463297539057165628056384027919759672
+mul:-62402848465899883613105,12900108782353988220438351,0:-805003533538860189408921682314395887504788189855
+mul:-8212641700259728565,297115088713153106682478,0:-2440099767342009818056382435156531921584070
+mul:-5313586393962705049080,-76998532453336088964044527295,0:409138354399142425739761358816694829939838374638600
+mul:463290189242313601142817059,969769350842083604500926,0:449284626073024525963512524360298740721467414096634
+mul:1917277332460964412252,-708614825339303498360550,0:-1358611142068832022550567351649418376333458600
+mul:99562752968815530108,23844471852654970991199350,0:2374021260737762056439185654671360472955029800
+mul:3003923448532254675001,7732856831499478812681071,0:23228909960284118604870886637597256802569606071
+mul:5794073936773633607324540860,-76553654622431077040278132,0:-443557535012598304414911912958839564575760243598473520
+mul:-644932980169883872037968349,42642515095105038480,0:-27501564342225351457715028479060110852667069520
+mul:41892582203464757978762451494,68041907390182959305068217308,0:2850451198623775837247177391258991797607621147282401258152
+mul:-5550794996398648089925,-61773015425098686639107,0:342889344934094297210650346841878123357696975
+mul:26506218374693057900,-167675112099207386871,0:-4444433137302729109790367830963302830900
+mul:145568384864275126584,40072954892382195328941863291,0:5833355320423028246614959434448834158605847827944
+mul:3161170925861501561771687,413220145707787390821,0:1306259510591710846827739981054213899841485027
+mul:723440854928237000349411,-71208223609049472714282072,0:-51514938165651820551744112187918120977634013059592
+mul:94994080481292730137,4307839512004666207932600136,0:409219253303864061854413637026462925940577498632
+mul:7821178378958515500742,3087104738440174209004586,0:24144796833868673714228905443995252515164402812
+mul:869891649236864909625695,991848579874131467931448097,0:862800796939950559315938082847205513561495590052415
+mul:17628160996789341122894,299337591195948255548811,0:5276771249993287502058785568793774940966579034
+mul:99527056994641754235498057471,655773087035017085668857,0:65267165408886313115258469743139728285489416260880647
+mul:596721281791001887739,-328175786669349585798669238390,0:-195829476074104675040288189805440291150559409100210
+mul:266802917073126657350936,148259550527207353925931727,0:39556080564609535241696861668682911763097415546472
+mul:297095531532857951877,8071469565512676957784213778,0:2397997540817274789320989692996853463867804361306
+mul:-64574484904487858142015156737,351049851111701482889769,0:-22668863311335277552737854676715612712147868228723753
+mul:9213606993296693767546,-974475310790221342435,0:-8978432538291752468015873684497297955614510
+mul:-6506246525097752180174,-95653949321972166356216836249,0:622348175387957895590333791334216293967024502327326
+mul:7211807452760603826715508,25981532388511222064867790,0:187373808913606243431674903539484028735353962687320
+mul:244358078258267292267766114,6788410077941126965241803849,0:1658802841074748272013529977344553715539817794996972786
+mul:-84498071017578145227329893,51359077717175899950414794158,0:-4339742996343244440353286358071234877760977371555165094
+mul:315675121566194900458712010,607326754590110945679173086,0:191717947085635889541757875305524761525955701416962860
+mul:3336777364604897112789890,24326442512123908471776,0:81171922735817348191862980575095189973683144640
+mul:-631164366791648249399815693437,224085205047080377284686,0:-141434596550917146771849565583627819691166316250805782
+mul:-9374071452933990971885163627,-8124264246742383054580586,0:76157433551480046450059234199385450235104896467545422
+mul:-8986611810629266612086889,39090932189616079255587,0:-351295032903711635666432166463380265071682698843
+mul:131042125952122412011234961669,-603299752062616670818260436,0:-79057682096673636704088945577099341952975178863719227684
+mul:-5931135084197112120929525527383,817854717051260202081870677650,0:-4850806806078831488870903900854502497422338114185819841089950
+mul:37076034350171687718404493,6575825691817817445639700141386,0:243805539230578902066220627976270126208617978926437647298
+mul:6586877468189252639017707825771,813151310907233772623665199797,0:5356128048043411806613358165516537614499231407192441180568487
+mul:2933337084774328653741904208050,516673656644156545121601676651,0:1515577997760262602679690085554979355436376363966312331240550
+mul:-9902991686684787357658450,173313993122814232472956,0:-1716327033081373752497961221272672144589109878200
+mul:9274522469490915283112908394363,44864081129175577116760112,0:416092928505602244504563614588785724831758965222564048656
+mul:9608655195311416270604257657,65867528105907714734959487,0:632898366137150893335309426569727530606624485604541959
+mul:853239911600142024011098491,17829323361272785163230303,0:15212690288662738268179355293062413175232317048772773
+mul:23972081642808055559504902,-4501717580058722285684735,0:-107915541362031999704526719592126415237678659070970
+mul:5314236376598680151908105,3994830160691915764873,0:21229471758282529614266075257916580301482995665
+mul:4935319583093232012062136782,881389216056886912824752493825,0:4349937458332745712903267792817007035077166975812760371150
+mul:580231659494763900889556,96767644291944525456085901,0:56147650832913989511127904567807102400387849749956
+mul:303622305001319462939309066150,-27984889540977885375442171280684,0:-8496836667639022536327520662086169404630681920995637573246600
+mul:8908131273613694428163643,418798812110676949375564324,0:3730714795515386967446577233797553865021052144672332
+mul:604960317372762640669451812,820482420778387317631260055,0:496359305672865772215202726749222319854411791662969660
+mul:3125355862613621420823337,52123353846012574000878521623,0:162904029521719649924422263486125418351967284017515951
+mul:35876668588605457895900,-237986271303986771473105323,0:-8538154584211078670353490608427234416302669875700
+mul:-43001262189486935668928474222321,75601013836677651900921245468148,0:-3250939017782005364312622194873995196088464819832369459876131508
+mul:50360054222226284955381499,-7538629547593198554710875138,0:-379645792778070687264466482409787805710036592944271862
+mul:16303655607623383537122,23252538460647040924816117157,0:379101379065406527294500251303186510479764610602154
+mul:29876051059586965106021953,26235768232838079362376,0:783821151311760139992194729309972935608098240328
+mul:29623076251397963944271763623335,47441755805615786352682527,0:1405370749729958481398420374857049608464886735734463967545
+mul:9892811422980328964557595259,603482574014084208448431822759,0:5970139301776104093120254749814895923385575422031146699581
+mul:-2549498483308845928405350,2555383871703609992631017913548,0:-6514947305180240206124780570855709347291338943800681800
+mul:-935906971037827073384146870,879641356065373793312781,0:-823262477154750723009760282203349336801144752145470
+mul:19597038710644290533555897021,2985160892106475439715913026,0:58500313560112043537702497574448903543850923995448495546
+mul:-5608937456930306694772980,836399586633606428927522624674,0:-4691312970430260182524580697490183025347068206176508520
+mul:7718522069758342120350478031,7389561033066750535580836572,0:57036489919551968141273365317951375124662579683087349732
+mul:718875898101761373218778459,686314096776480574628984874102515,0:493374662700091643313347796063672168629137876643552239724385
+mul:1300200863593962819188902,525922101427424561614551608409976,0:683804370459089120916221427942950472299573480614205286352
+mul:539220635752920237029329058,29487916769600117002583914582181,0:15900493227532973069876042371837383552914044277544832315498
+mul:5654437789656914341120143121414,6765853316633901505298664574837,0:38257096672850301023676847185295792977091707859763702380259518
+mul:103114174998937498500059583,920095995082794389728025430890882,0:94874939452788796816569177101730218978113456477925771422206
+mul:29882936700790118228421849,-1860889369990333700884198092,0:-55608839250594344207705038774209133311036319056912108
+mul:8909623809613954310018698,-462806578041198407432067106139,0:-4123432506961820007043026316146032423296431299840587022
+mul:7230230288816368650543810,22162946284655819337870476,0:160243205516728709182606639762736983481104743553560
+mul:734442358589456361847988629,1647427465162259118128391711,0:1209940513118819039348215846845414818873067603985854219
+mul:47616626651192848094181030316,2182277257935167463613810412,0:103912681440487744288228839398232844775482481328848450192
+mul:294703827229370598691617,63046555168872062038888853,0:18580061101894254060770213008323255399294285845301
+mul:-533653415261740333749397,-51216937243134223196656339350075,0:27332093479044801759907744737948616465079304814903154775
+mul:784368839220787531616946253680351,39613735771181195550018240677,0:31071779944040382951244796866071327091341523727977793343837627
+mul:5770744507580580048400572,231937913382367374762373686161,0:1338454439750996843543440906327507234975603867940884092
+mul:388816489715059942531589642,82051838197217717225950877,0:31903107702510265086302832415272579698669593814016034
+mul:60241729629297025142644618709,85181464884435369517497693388632,0:5131478776995614297555781224894400552133266197008401795116088
+mul:1560786485638020475934392460005620,8850527081981124295638445,0:13813783060329443326853456039031810473529482812666188060900
+mul:8296622334734688413856037840,-83875508267086319614619277276,0:-695883415225932360550627205972534406741559721529708123840
+mul:-45794179084517723375284971259238,-49063790774577780701852303,0:2246836021296323435311993617164824492625064891225000325114
+mul:1752071933321291709931075226933,57773126045256149501100162,0:101222672644126613791673432521136796654007466067313063146
+mul:730668796977177255106481634556,938608337106204028806933670639254,0:685811824506138940332211187860302311716319126763710711336461224
+mul:921730456287198291208119641693911,5458708493078803375257300,0:5031457870064330030425732359718797657583243087557468300300
+mul:213400535376420556914942871216081,4183995847570912793889135547893162,0:892866953884353287726737673843872033409506009951957939872404338122
+mul:32806047880829491896013320805772,753489056993475245589087354,0:24718998081409010820901165463298804748196865416365375407288
+mul:15218771998961411533589410518,23457061020403160442042221,0:356987663435240813815179640133949762707316007457480478
+mul:9046617676720978441798060,7479379807328977629621989162,0:67663089575892274970250788865795328564433781112625720
+mul:2219170169044655639393672927,-5391273013704097527490654785062,0:-11964152245187612169646728984856115656974060298999913416474
+mul:277590531551034474232270111103,579362077865358674190909581933,0:160825427155156738840764040270546509814277905470205191502099
+mul:51422590325724235826789079575,2121952875387495603452158,0:109116313401543756339172704192689685091698905367472850
+mul:511034032165016743768820348,458982236103828060996895790272,0:234555542808254978695571194131402867112895172492654054656
+mul:4440454508740215531301617636697,3258309525326637800581711028116821,0:14468375222607860310511042523813260258037478238688128668452580237
+mul:6330009746329830092300048092,-6167250670699283492360751201828007,0:-39038756853585645999814749830700965509494204090781844412512644
+mul:-9374602262965156933926707655416,-30595740075402425097079774283,0:286822894147961315557763521486314502763707907853113422466728
+mul:83645893910576549628700447097824,49931389572768584324081547829643,0:4176555715011469153471691311085610269167538819874387285307996832
+mul:8030747712125824227213267818544,63329417394086865663449328880556,0:508582573847824473759474520875716327252822949675048995657830464
+mul:378845361147099357535431194,38180105668041356349238612217040,0:14464355920443542823460702653769947519591239573552714345760
+mul:25958762365949818177158173188075174,40582859445868015162861781,0:1053480804486029724349686454924029433193919106275980799524894
+mul:95871031013239291309686124,64936572493882710890460913285902999,0:6225536155454490886042480192744349881519233810545112600285876
+mul:455128054133718561191432952712,39088645380524987234419335395029,0:17790339110761304357582067458548970370146644724724054396868648
+mul:1307047523348091088814812136,44132853285705545682051355847561,0:57683736585366097743814172916945483114493512756215268800296
+mul:1418285824252402530993393665755,636810955908181043849421782278,0:903179951493194917152704617449910466299855863874287914489890
+mul:3071172872783184341780369192882346,-58125204065109316437571977973,0:-178512549949750604044117019967590439630943828607057692292564658
+mul:56958148205198214736866933854,4922289245511311172745764679844,0:280364480354686563048707584335842453616735148517258235038776
+mul:4836813580368584281452577588,-5400032605107989894617874622172581,0:-26118951038819470026364723997465834517846139303988539028714628
+mul:493001845960066187429806680791,4028800209124423703294502145421185,0:1986205940102641576976415454897329744147895770653902923543957335
+mul:71197215106470682909632132625,70077573297929109151274279,0:4989328060232124924682056253101608707528304143079252375
+mul:486722080146274783096432055886,505595939085965376271620470551,0:246084707185430303071142220010478564391091338964955649213186
+mul:-194536785271632924316130857883181,8276525052027013498990299177664024,0:-1610088576841469642302988316918048088947156051499250583217058380344
+mul:241211965193448971857220311,2710726738427327769580581757190,0:653859723678484041534242084550730982398579984949338286090
+mul:667013805494915469984846976421,118549400818390788595763048,0:79074086979016886300666397440542951393124558234159091208
+mul:507926799850267721181735296662204,67253859677995358015731931706714,0:34160037723823138942875018762752046517503606503615202081256837656
+mul:448088677681619431331494894631309,779948091351174817338856782981850,0:349485908913850840791957607115202038571061594442475706481388741650
+mul:187408370748924381155985806145,495794563709904959946586644094587256,0:92916051411047078205447640432962006059741039970472932758203488120
+mul:868633158815673181555237006,836615025635832190680248872,0:726711552430708313445938158474307639167624319024157232
+mul:945386362083356835627622353491,8230893874122803805176630038821,0:7781374816351144698349349350957993282560652485452042714874111
+mul:5596932048341890824814087121,-2850793263280920843358756089,0:-15955696178454147555303366966824500182482049050635229769
+mul:92079468846004092188293849,65000203344267255501708018874742834,0:5985184198822387758738668838849529371861013959766705099028066
+mul:284485059147524530505559245415623974,-52174853366891975161102679787418,0:-14842966246093682947479966058631799163262087269510590574706144359132
+mul:225019940499042054289943285,88057001889802818516938839002453179,0:19814581325767463952213083138864703402608880611447063777953015
+mul:267625311635136684363577960127905,2364801628264216400078340665206601706,0:632880772719489569595591177205490383145217286350462293583250151205930
+mul:-43414374537943144129863577734786164,-7033210862612719519352562332,0:305342450593798787132468697152495746155227469781974603501174448
+mul:32883132771659855270849300682688,359989040176539024964573548207106,0:11837567404467526702781425500654503476701270135055701604212780928
+mul:8225754994306229461538669946760,79816684330375527507314556065816,0:656552489759550261552969973902237676399765161631722139775956160
+mul:7425838080456254658426507595,-1772612320788255147892065709861,0:-13163132073595363322916797538873046375619972048032782894295
+mul:1660461221569443640519526747903779,1120888096894032723781619067526671,0:1861191218611314482654724970474950053651690424934372619599424189709
+mul:-11718764104457037189982579964973,581785925357694644406822708535571,0:-6817812018560073163564614103438500661271133223665021341304554583
+mul:6811677000322905212875962023,8457366124986245338105030092893823455,0:57608846316878860294885890656152159404437095902874498977846649465
+mul:234277964462994083732538315234,60350281492645017737168270090,0:14138741102865579012895614202346087042625169063690873551060
+mul:4183588612759663468880479337,-629574038019737820951243554610835051,0:-2633878776348494576596482359410905898287329191507888206720841187
+mul:2509727174403533842481294816277585179,366325095871570289922697736369296,0:919376047774859744204436335735246570640422606903982773682501840263984
+mul:9652053493694317708921453500950,-91539642994112368354952933916454,0:-883545530972852858614086011262208634456937177997222533109631300
+mul:35148593969489612322148628595,-82585065708416968121031576511657,0:-2902748942528768024032450841226352229253814757005116581031915
+mul:2800741702103544119527140802733199,46761480207188283686223358035,0:130966827668361702581651174249923174168745185881158323957903965
+mul:441336276433669766301405280032,2656936104993980830437872804,0:1172602287300221361851343901576358026321010825668017049728
+mul:19746122571650880858695931178058857,104545112367422664420669962306,0:2064360603074142331524120459909153582079341868724637548439444242
+mul:74432478600289091913597803372,1021411507303737809729230605483660893,0:76026190159474490029899083115858462446496838080724392481739931196
+mul:37218119790882940825047165121,-9786692593914842780007874460688,0:-364242297316869514078703840625474873421751340567491159263248
+mul:68400175404962139133336849460667620753,8111497426974768586772111911266,0:554827846801973241521975237100547882976582048728649063209959676103298
+mul:-36411507888779255237781266679960702586,288273015425729999064058691683,0:-10496455175296151796260705657513107808386313037221881095512634792238
+mul:-93804297004149089553676142929158,72597578405766612297542242292431,0:-6809964806556531666828055851398144826196098989021186645152603098
+mul:-82026709713179475197473688526642531,5827788603588390535677091203646382966,0:-478034324056320484117325267961249121989480834362662252362566162209526946
+mul:545760067487517393173385480028,42151112506666653978439280505,0:23004394006312331510547051427125022225825594077610367254140
+mul:-697412421088675986809554647004214,6926944054264140642234974161460,0:-4830936823630163298372038105376868436739545586561249485736392440
+mul:57812799959867792819685059219,779735108345604313576941265627654,0:45078669840470262146069880262711457187904686148856378194042226
+mul:1472311567166258003445083977221663144,83378953824849274359711951741465,0:122759798174546897063619713853094843283254982730610656163694407065960
+mul:570337459673916278308389115966167469,6333660822968779197930730584647562275,0:3612324024208219493962639588959668872206678635128690773184462125256631975
+mul:-388785693105293562593219349398,820248784628021659491960244881371621,0:-318900992250380064850834487637248605290643186101012034699480634158
+mul:11679788667362042415563834445557578,-5819547639993570526822921884507,0:-67971086574770424077123666817486620774164160205639229582134644046
+mul:-3982959591737356792197606403519482273,-333248358612381656382679653253,0:1327314746365915910353403610458733118195746910957791963061720284069
+mul:17221610285774362123428353448280602,11458184790118982447972303969280231679,0:197328393037816418804445305069398144307419769226493492273326450761590758
+mul:772738633297996807166456840381926971,785759122171938805714543081571173360415,0:607186430168577693296664258953260658244617930008242877365346151059192252965
+mul:125784145401376536208808801528812039333,452055550313139515567680226389953055,0:56861421070087227190049678638474498681709153815504817562127254516683512315
+mul:32903571905950760393177782893378791,6631740924411766007832465757451477,0:218207964368018909275497254276866261100277667630506488424913763424307
+mul:8742677352155721160009371273251,25083360125803108633092433384973055,0:219295724487824718593455764107115931859507036987734897375677251805
+mul:36273669132247708836176424212020,533102320793846929600697481505030771,0:19337577198109381261236591896304826004083902938845516133439528067420
+mul:11965144674509690079804137520044857,9349045655011350274674885782216185552,0:111862683830807014974569906953845003630437520055543213513177982475306064
+mul:3321305668226664033356712162893,-403949753985171409898849824686029161,0:-1341640607589716272160331793818630136041627867704613639659980122773
+mul:7395363159337411027760652209127419265,44729331460301249556947662501414682,0:330789650023303701714182934884591650253917627482713804287730858240648730
+mul:871058047335719958990871843414,28094200616974302760918376942978068402,0:24471679530879615091124208710919171690581838289918159716462725204428
+mul:7704699734056436938779166257084,546898541513497897846722209401,0:4213689047354900490455012376163453543698919981174872047646684
+mul:950290435067652970604023856243611,4001208123591666075058892234775,0:3802309808564151732408385790073534886035212910698424588605772525
+mul:3119293215232541154035748455321571,808684220462127868482572087900610,0:2522523202153131986496862299093703760338669354068320189935837058310
+mul:432360858532087298548744564083197299,240846574096518547683557847064319535,0:104132631550882737065113576806715978014672912813529852776264204584935965
+mul:-310788798729818682147559678302,-2172955391250831365155305151397888,0:675330195740329036485433048145632383792009398152531758882226176
+mul:649283478652713472152371045373000641269,9179675498867400603641823155076,0:5960211640807708792849652271953975864417053692073644908051640832431444
+mul:79980532708199255123596245351024866045,35273005660545430889304120342364,0:2821153782949751307464444766122322349363016295719088889624882638630380
+mul:-83351007958684418946822288153831314277,-51634644710916030743119182132599855,0:4303799682243404417092087784805566131916079838838464861475411381589629835
+mul:4992915740405389949821656927954249501,4523923119542484578579105473053048,0:22587566951947525817523244050874662178528093089821507414350736000529048
+mul:-801991401381703662108108758716412,1462655905419442096496214673085035312112,0:-1173037459326562975110029005457912568568341236188108696496766994916782144
+mul:679369055865583831572651301119431385801,6364653911974833953564963906049365,0:4323948919089537646576384302944771028193868888345656961053886629066066365
+mul:32178714589413433072024739357148883,2182815001928827996341206621079833349525,0:70240180948557688497445546843414635161913878682156096078900633584002330575
+mul:604754886257955637472038235002006997,75686581968330008368600832791867,0:45771830269510850321052484315153573724518799356687777800355778693399
+mul:287068066584060661996114628597630371136,52011890293701406927883275870768865,0:14930952785995133944874986127466642449246463907028312778992290363623480640
+mul:3979837024286745384581666788748758,7350136706945206821986896298939283,0:29252346199869589826241656345690372038181000414430037048634183660514
+mul:7385865195603313817759905903511277,1520983986703891701713359953638,0:11233782690466247146504034010039435409908987896556224062130175726
+mul:764457193068206149728854992613,27858021258550102776458498820919,0:21296264735745627187463264202183322605488975579352986954871347
+mul:-4155789385717252736363125208379519,513716864065732253356348104577569642,0:-2134899090948322867217472161243561749004221362611724116686910188962198
+mul:97365354260983249124725672833811771,5020029690975786355406829440294084209626,0:488776969262511703376009046688465573304498084561257966650740834323390307646
+mul:83139160308299020652846789174256754,3913486804605023733190361150860684,0:325364006812469954155078345060732025916284724658136533980363100059736
+mul:-17691166446369130975076403772363811082668,94600134419678935394632555907142,0:-1673586723867433503807220193308619446302933297119631426540241369893614856
+mul:634823647473707443708903538054380,3956996255499668253479385484122050809317,0:2511994795956101788922355113644864677876582447280810271598141786556658460
+mul:-3637804742599340390876015169076139565692,783241759542604459838225899706055858717,0:-2849280587465938677344529171806295752584262014073034029610817921718004492337164
+mul:585812248650822285457691267576462,21534520461947113931625020852108318,0:12615185855430383092677209963435811738114410942221928457106971210916
+mul:11281432653044672416448534028211038025,711109480140515578563170257201359462,0:8022333709146834455095073412796362253303159149746025747385289864175542550
+mul:676293649029453415159585825583394,97280549393475973449516311017466882903,0:65790217728903847286239146189723168106268785797184624412977724659312782
+mul:-60552656313655809329731693060696763524,493007935144068742422888317617165,0:-29852940056683907903878516926766558721475796609356660329816267168289460
+mul:499127054152037037035927375386500,1203956412395744650060889503126393,0:600927217446543074982206780295985557213897685478460386666725894500
+mul:50094686288665713475507184834256049095574,-832478827433992238527275985275884802100,0:-41702765702262121589947986555938357521572244317029059068815991395850316975905400
+mul:3587136855297236649460183411772356035310,-712398604370738955166219235841134498742,0:-2555471289400592763904206892884230251721266867884706454335385263422835302580020
+mul:-8101551106022390770336067301182994,9185799272249263720169676176910186035467,0:-74419222253790694721684461955969753328255728462706287902254787547941248198
+mul:68680574795029722620883183609775450677,-84158462638889794851250260034014551972363,0:-5780051587904985041122626676950144438458787116758152359160332249952887573639751
+mul:155258118178686765062886673806448566,-6850017870177195667059084688029341396610,0:-1063520884014087259630275993355034425232292561277443357397796113750571761260
+mul:285166743996114296479394289968524943,559627723033455856754700399288311,0:159587215627409862324848662934458300983070878875254327058667651841273
+mul:97635198013817214038209538637709608537616,-43337611052093405089732573050042882425535,0:-4231276236516932968241697386864918819022381398914657632453889680479868318366424560
+mul:2025635628106428290541842218677337,8363403252785996217814021695187802,0:16941207601064506909583426911328603088283663942724754575178256243274
+mul:39403341320445818916772945982544618,-3081545887974055895915003777735743,0:-121423204418458019221260007112987567988534380636151689137057510881174
+mul:66538675039876745133366881210395320367369,385523580015310377616062750074359,0:25652228210848657783496179630561675959121693223651695460689142031947191471
+mul:568797587304724025372575349953868,-809993079501337508688725757864677957,0:-460722109353884289924314758764698126555664169725436270804746626487676
+mul:87438670031005707662235517162074411507878,762858503307630620547057859718065131261504,0:66703332951062790053116333011119262791723282159398794542887647524305430508974128512
+mul:-135539991676075663249711183869449098,3187117064807540583340853903135708355720,0:-431981820434692750842384830628518023465403828254323238040947018231817140560
+mul:3623316226168035106420698863103708,281527696822113339094642926844583498510,0:1020063872011278433648537926576161108003887115843314376248917259593475080
+mul:462743256592937700094228107961335,-6269566498572477078237555404177435,0:-2901199618975409735420400360180614855892286694850259916640459475725
+mul:-685484600842741055621576203380446857767,871551172534175305655069705808532,0:-597434907618612100896516584776549623778036010575252420692205107539068044
+mul:220964518681325411201409247135357488007,-5641829172229111635876189209726787450,0:-1246644067523866218886679493927269969586873926750864717926006590010013112150
+mul:302531333113895329527974519952510,186535245939488501803212618851457571589,0:56432756626801787093558631197271214562205468328076903171812192205238390
+mul:817537141270922830542026664184986,7821981713799768623509532856543951,0:6394760569373296513276094902257760475138670289320772774910103319686
+mul:8468979244486855292413811013010058,-209488808243349961649691393540068,0:-1774156368965217661234169339486871316037510280452325791205110003944
+mul:879852422051274089521663230058530,49497155404087571445757965616479604,0:43550192066934760013905050742361301523530318780622661179293471222120
+mul:21764922287301916637920770938954126,164044760066720848860497915166650797335,0:3570421454491268052799273529790558940088345201564664677181891708888054210
+mul:59469732179854673335933541543666124,33859516881008254191737434099260638598,0:2013616400652829114516768709001157871422263380461883882597878170339454152
+mul:5622782096444522942366700649751601671560,1818924766888381565955786591467033096941030,0:10227417614039519288793528427282183495313347673374396346064272524023191670748106800
+mul:-83658234598433632746857009684831849359505,-29016349811234824466750396183186748,0:2427456599698498400779164525993522755993904434491695109250156524973603839740
+mul:7054089120269602821498711515003074,4095832337673576318592596805192095781914,0:28892366331631588775096150339023452623512261839491078775396601042143603636
+mul:990394898068553803695514279851854605418847,-7739084020331097221051527297005947155388,0:-7664749329459790605184280312841813382942964148487855083039273635724968309932797636
+mul:54075935489906064661012070011939942732,7918292813066039667153314788962651008581,0:428189091349545982631162674290883455991732907828213951097897291399359180583292
+mul:8772115771437424285869834799732506658796,-932849018789404004804426567212331569,0:-8183059590092457014103801212671744691867340048481623621821910552497102330924
+mul:-474373401937043543973615567508636867124,-23736477393422078122335330115520892673,0:11259953531119359125561737495585820068714950649943932579707916447562566182452
+mul:8436352086792195283692976718955932574,-24226347745891111460405966918193715809620,0:-204381999361401874523255301520944469344779076416596720733502946611674540561880
+mul:814519302031186083731939523439915121,55324835095437197264275880684820442585,0:45063146066925974240276350660152502606985477063819725670158134818053827785
+mul:-237764758709584162016066869681905512952347,27730963225107998869867496093972168,0:-6593445780002155177144945210712636481509108047897422208741783636396128278296
+mul:7518474854158787395750001309747813,8381114315785290417935232114225100106214,0:63013197233061936586019793610222181046567760778431006705881553819854209982
+mul:57926271609377407522025180011097851547,-460438760475654775684236043340437433561,0:-26671500698797845620038488129522785806400814035581845817517898599701653568867
+mul:6638349918167655693810387712273716693403,55308325418124425819340246954531134649556,0:367156017513396353523080763860964198057435071526450849007117311720362229502079068
+mul:-792096039638367514268257857215475476214,17985352918594429617981644232595132,0:-14246126818317002183748026216030950300744414227976528547481286648758190248
+mul:17523605051927467343416676052611136060682,32818776862511079287568864844380549,0:575103284025979425337961066906823946761256491065774387656701755680364474418
+mul:435598204136143930685119666237820390,902306362378699323196514142749053448065695,0:393043031032778127896845207627557199195066578791333475705362867607698330521050
+mul:7246625600474134146152993995542881524104,84045078681310625106949990828070364497,0:609043218765848459070950953243439359310276390319003636791153856018486171335688
+mul:-787638361574460696958641849383712843152717,-98972482600264920015196417920239935812005,0:77954524036229481100840641198098180090516196148063542559493953965332234357616967585
+mul:82374608290966933640517911377351376793038534,3375365592517566879211534105358267232412929,0:278044418522442081159379773928407521481969102832422171826378968402371349113290496806086
+mul:-65869507968457359071511077346860349916,233541308077986424091233056554170108328607,0:-15383251053406881762895333316227673851604711244588922960984017463587249932847012
+mul:434965647854018848199731601803786298508849,6881642201690537465635377223216241,0:2993277958557881269328249998872265799210459572563672559065439071522179016609
+mul:719612999193225374224745692059996056358,-315519530953816852193901984099603790510,0:-227051955973715854947761029625296545846391976119186350945960831820908385562580
+mul:3371856558784507755414140667220962994794,-46940188151078159734582108552804551252391781,0:-158275581287791729316741990876515371668219778704190560942981767461139678285151388114
+mul:4803433840417804894873156694592939602852,-72456645795090954873268375616538340122311,0:-348040704375306339795449754303228838077133852627838127804760032434988381444430972
+mul:48568835567133010333265540506612310476167,-10706367926604784868082114989212135746648832,0:-519995823348494578419271225922535589824979430677892239954987805560794580396454386944
+mul:-640514959144433868933444881224466486263623,495227035072426375802319189512972514543836,0:-317200324136634298803490410310491121240672331811889843420769547754733113081885677828
+mul:-6488859550432975345382980598094012298,1739553070312394609661279054142037504040,0:-11287715553781586837699646244863276062209616974051919639534825980076984683920
+mul:62439762329215278757554454849955204768025718,79602289985731119990152260854511851,0:4970348067570324615570705607275557501940237030878572771873031709232361903784018
+mul:6054057220822234921996955072468282902047103,-41461621564455176604944655360416823,0:-251011029419288750464457350960394818104993744337372045669164809905502059613769
+mul:41593335543156355768394832800525873230,751910447000975730197547607815241920,0:31274463520516267130210975092154781101937166708024981308551550511701801600
+mul:994454253731718339598418586069934146007,674502407982587721309172287657440910774,0:670761788770571291425639315014529979293655007270270606543282922218043975379418
+mul:467599304203676521904495847137440151064429,1065364075426775111107441639016359411726,0:498163500393153194363286906417357715847233221784448787935167388300077631164094454
+mul:-50006834540638623993722097585899096403763,-5313099491095445109561808031972399857647,0:265691287149161199757555723574229252417144350517780818574650795718178070835125661
+mul:80633786527554906657368596063180401716797,60423064130048311342811193512905633441,0:4872140454403075663557443919045087358815687394738194780627830508431609174608477
+mul:7515721962363288712694440724080300383839,847957688242291310060264069657345589412622,0:6373014220677391433202574116816230429840218559515683152967957040454035241151415858
+mul:27726212382161724111674518621229053817654,844465139764626291093420179330707907,0:23413819814445912412285655292812080594927908481755534067419056195692713990178
+mul:-9817131728229141224738800156068771165515,5514447437310670168515402768125807553,0:-54136056900474458343818772029658956395718462850811589025376047345570400134795
+mul:1101490427405231724327190816394483390794764,-1715150116840413365727028822839059671039358,0:-1889221435262680048398395651544618017331159617034111717493189130934881187657544321512
+mul:8714614705512806124985108394035361802445153,2277516152797095323407597912040972562623326,0:19847675757208518019561453963926275072330819370134031638574421823784137713762913438878
+mul:-40241069975197162607015133362864260639182295,92350494843755720369837991386076354459722485,0:-3716282725251658699531715999828990669514311285221505159677424152232919613685003025403075
+mul:94926798565178929705057494111757110129555,654944641739167114202854904453615515658738188,0:62171798077717196972382133382107571708777354355494810646721424261049356268684505946340
+mul:265280847975099333384365084677641815670787,79159871617113409657206914064640126799879245,0:20999597868187843053561037716605216806384147652131248848290439305459650098340274115815
+mul:116347226264838928071222153238640922289035,68573180747149861177662470447052670907671443,0:7978299376088341437815459477697033179544362328591411544546002100709937766389261527505
+mul:1040609825768545533315151293676302487896884,-81323728160947963681253577857302080515,0:-84626270592412620351087782103887368619510384932135633101731317980537259985615260
+mul:995902591817252306534602024050315471330353754,5332558356879676808399004303967153306,0:5310708688633218425617462275294145725219682434631220640352375632798303313330610724
+mul:2001969035383918099033090062929650143669765948,4190101466247488888803682714062857957220,0:8388453390544226191569030306431481670502667642604288098765832297433783873766796744560
+mul:520711239532941932960582838954921846930386522,-3853096594619017503346777573808512971,0:-2006350703824226084150485654917370322708059670415383459171549901585565143080576862
+mul:60199373689261241651972446393273631317362,4966864098864732001544113870901038040,0:299002107951333794206101094825317104561273941185545981038605377956818474450480
+mul:945149245494027792287917914515672725163081263,8902933189066222709145663761457459365794,0:8414600586329679076832097202813182563472890369046719691038445973643576962794864517822
+mul:42113632082774519107063284261972952560637120,550965713086089226514793739995356299364345,0:23203167331131067949789906196648817037171886959897217039074444030278552245924211486400
+mul:699130208513509445029837360613055447835,1388996167624703080432361535173321299212301763,0:971089180295924181746449876683106046223557368848629195863225292564207370057125033105
+mul:2708864861499120155181972404884433662661130826,-9669434874243213781569557549324652869447,0:-26193192361391605615558952560977409140576479476697591006776382263831361618654765273222
+mul:-2663320619224926510783240759799877830,-9288856838720796348912703146202293649985994,0:24739203947593564658057633395520384609185233542510185477275313665703022411113020
+mul:129339208558322679510730678747389994722,12274162664070343010820636150243461714,0:1587530484686971608662198892455480803480746517693529713477405341441469073508
+mul:7927826382521640149002540477963715500150746,169024688202278131082480706237325364215068990,0:1339998382427514783636289070847268513301546686442820771818201284402167398586309789966540
+mul:136906526225769628858637915191370345692692,539213183682016621647404279498623014328141,0:73821803873042744699575963663268898393281778327505656899589792517391459419633645572
+mul:30681142365936990868501835461428152495,-5027491490146180677917496407674117704,0:-154249182152711677657936575800296045756593757870287279358854312185891271480
+mul:-971981137022757867271162004648718096950546,4334305792750860480761829171455584581712,0:-4212863472642307283763302038750775419855652449217026116602685720873585162160014752
+mul:578802014801938809246604894083179003839,4755521418153118560811649969223227339815203,0:2752505378260798366799002210776469662264057939931455802132200174149940527887564317
+mul:-85637729865865539531457719920611651870241486,974400175977421869121902925057819107693817,0:-83445419051606298238772725013236132640041467317129471694684769066837807060528339092062
+mul:-168964790731095355351979412256338118430524648,170138331609580398941494555432555720911428772,0:-28747387595750458102364942972192784965490845982185971055009388748528499591310207242372256
+mul:790938498909251314495722876378080005340582079,5214770204816378474402582970231763702140978,0:4124562517954155419865932563949638361261784041659784084183845034248536666456801038333262
+mul:3097935765451813281781983641770574025792276,42609404056306319259222360596281494320705429231,0:132001196770618914910107580782114196079241607233335405092295156225025350707315539424419756
+mul:-98485087154927525975034391790808080098982,19775664577849930783360381707025488283978,0:-1947608049496163493701638026379883534026679881243207339494650490437933823564710396
+mul:25900464334299058097279910365875929228,58255952834922520501042331752256379575,0:1508856228661518846300670852569471328709790883165326524402490612694204718100
+mul:79400185595521899110261406600117591081721314118,201740226840130845073877991057259510967,0:16018211453189077537841902603464990449906833086676810898799136608951219916977272932106
+mul:981167299738316185980724229187020822277,8133607419206585086507618470282084549435045911,0:7980429628634459820355488852068596406179426323528568158104015662222056961076466559347
+mul:81466412463591236560961446462245299836549126707,866192944729287017177690246604876328497,0:70565631708368782955079491721185650392800025979803605094852603626778749894901807869379
+mul:6534998388738554052417315288897046254899165842,46609611771478693989087838979597248775,0:304593737826342807250457708401174251945994165789414852595908172190369819865656343550
+mul:948084924179221265735435784532032916982,31095014697784883179376411641933005719333,0:29480714652101151829666949589520351343767111464822561182540749953951625181413006
+mul:2750322192684776089555518232723747026,16282797711115835147148988819960931175880625768,0:44782939903878757031458893908209207556974070715102965333536520996427288006608965968
+mul:-916832268194684002726682872945582785046,80175456371164380904577325966825746198033406059,0:-73507445518318567912336331397416597212835389484585058461161628079009895397414630993714
+mul:282231592138255672195189656428026230056,96673996679717919403145753072968455552546,0:27284456001285230898827449612784823590027283270261564593974508775341064792522576
+mul:550580097204590201609373226827993784219420731,60517713169991893657707958780297059239491,0:33319848399733645437661395589377990023027893949147177182635468091834964459423419287921
+mul:31526794192792048622410273704705620482050682,70537996848502378104686898733501905256490,0:2223836909414548601160467423600948705201515061075175410087937767675574150990389426180
+mul:-923613180033278870451470473112995033306843225,62635452857298067541908563173475507759656054707,0:-57850929796353591491544159777994055136678493390586182701070726329142717640752659048072310075
+mul:469196843768624413897755875308788890398465291232,-15296277161521766221056511754171865009042943213,0:-7176964965596105854796051880140430745806790021143791822882675477990460153884190250962482808416
+mul:2628065716223500508449356215564412668664236,713708318009199991674271791693482010536664884,0:1875672361943518042666230150625785628379941211629586909201716940601968915751182647888624
+mul:604553604369312265623368647573085123221252020,990982890678004704551740474471789043760433700479,0:599102278427707884215998875763263404402845043498163599628915781601939770631217226224053717580
+mul:97586462652371414650265963064033775148721243,969409880443270812997088798402379069080662,0:94601281092717085428971288705993159426354381047162321909314102361504796669908919902866
+mul:-765406874969209688613302257358735487317,687488505077706911028822098735771705823765697808,0:-526208428248781293790355829561494931467780389995278558390525263117575307179181438701136
+mul:85075624707999635862443444914978287825359,778046486301986342411165862027907781749497,0:66192790874005569505967522431892177262190586520494284537342391004284567008622094423
+mul:8227248806783006644129224253415431417213104067,-96883503079217553138854609209329008354340832050,0:-797084685105450364093424636607878440722968607757607323583949926033112024630877523264018947350
+mul:5027554007771258456873599804445876368468,9124875242153734630106913217321584664013715,0:45875803094102741048036279096734905134493820588179489085096405521013297169145538620
+mul:39245745484403729199058188063461104557810253,220067769421357576954105356315871937975114,0:8636723668031045203182769468262937482316831571209371261835666035163932603354648043842
+mul:12265626358518464602956912462337886264411404165,-62808539324142868756473505816723401975937,0:-770386075474250281180131471535743658895165686987724121596740049447065305055237711577605
+mul:-12272356051659726939876917766506363796290,17656166644036956054896242696928896080969790493,0:-216682763563059549497954402078347159387989008283715984882662478463368364976841430670970
+mul:637223594292638303876168193085997138882431056,94504571343119776477559774058446419793557358444,0:60220542628347848605902201201551563824536878839327823946585532875841535294872255080309436864
+mul:5571012420064356266635359647247635200655740,-21295217227115690481188602248443089551209070396,0:-118635919660229953125503640983379408558760574394740036184511552934026350143637375021473040
+mul:5263843748978600609740419748581371970418448276216,5384845751134428162699702180820131424931650492254,0:28344986646322936927200214104061116351020656649291842992510958145976963325938398674483474160430864
+mul:886573921242233631853410597832339291851986573,91564665302299543163193474542608720062467,0:81178844364292397724319168352869382688643286956887488649289119221530204376834605255591
+mul:26539751625701457124278640373644598585396,2325338527842485879693477585982320189921160388553,0:61713906974613847646349243530903967347131153357438117664659209426320342893497093511371988
+mul:353508003643539157483752498296868928280378,10742495675871104458509832622060247315860,0:3797558200526546039055152211123089222303048576306814689403594641262243620006195080
+mul:-4734613561112436559828705330418786656799216681,5767402184612349878575526105980302509419976764,0:-27306420595655124123966761566392172844463942752586247604702902500841784311547866248421200284
+mul:82083010698635736174070971617820650592649198695,632174562080517027772509374721051956918078145045,0:51890791342660440565464109942127261004470910227369112903142988666567956432456853670311234716275
+mul:6173991144338684494350090118957116722781373,-738485502817232028305101940854863776286515,0:-4559402954616091182455382994371638790076884277447195239272169152306248043072153085095
+mul:-493513047233893983448577482415236886372545860,510358065314512191744416886029069217313650,0:-251868363993759605947955962960713974503486770964450697668654217509298887857540628989000
+mul:326654054139623246358073868314669601484091,-749350879522921841553744544029160051092161118734,0:-244778502769254807928944561265310682694306143662100245399456722534220714864996773263060794
+mul:1402621524995633967650615579165227953957890517212,-4307813373241246419295301377872133252586,0:-6042231762972223192990082937904905510649229289208158235372604963773370709779387376510232
+mul:429404746005804957738561594094664667352987,378882853314853204091011966904771925997210303,0:162694095393619197081345508962117529189396776805991399292350948184192266104441374225061
+mul:332341701384724523211310134953299492552149033413,851224516641538736779656410258860743437969813415,0:282897404121038737349436193561640178534459124296792792204901752510516940857699900180164210635395
+mul:8093542646198882950722808884458624246299608906958,-36537804019444103265563497755234936603188804846,0:-295720275029827809269384782284341360404517553913401964795999699888915544660313719313212433518468
+mul:22659814113479956892126670971189905912120035824,-7769923990496178313173088170032841760727,0:-176065033300511807783943084226119789640585676482818345603663798333554090985834476284048
+mul:-66431972193306385702365512934093484764859082,36581996652652744665199423002405565247156,0:-2430214184404654414022013017963434105734980396584113694039713331126873558134841270792
+mul:-888473800362239868616054745127669042022317,142999759078860850560633007783677610020527766,0:-127051539399680213509691775061090749319492899786422897068862876191428383442448290153822
+mul:5971942663513046812876552589351160577576206860,5155119487765712370432570496238254289228130147,0:30786078004495581876769132581215368897074670048309664867385023649025961965929287514674208420
+mul:36328343589972083920724771391132711614346,626466814451530915421088090957480792070888316,0:22758501683110503999668988831411680352271666146548027818547320776153981900886629381336
+mul:5293116409600323220539205506696278195160522774280,-89478075685508708042860880549625934136374,0:-473617870710425832617232568229956765445181004360727395884348946714817018728737310339660720
+mul:79576614103508536656978289576589750212587261,852468870734033057111244131505440601392558836846,0:67836586361655850604287977041894979998590061103440929502231721634765812139562797406437018806
+mul:8225066772418695359596812838151452668642167,32895491347247919323385073727832554930053,0:270567612842635564451661105276011053846580530826552326236219991362408128533171344851
+mul:6163942593967174125699747500635651388266851958125,35785148285967657728202559017385960485415693874,0:220577599751307459197829958073417379960145796516327396960366172323789774042408250526882467026250
+mul:2768453763718344802615194690925869147682838954,295289393573622382700104229276698254424111309,0:817495033025002504068133964169976601685138884223266625508984010676066936521469461617130786
+mul:543530772918490900335995207569824317804903920459,3816523263571207729432080444412751436592123632,0:2074397839310259902661375133149465196577634869313509399704184579022798133468044005917222187088
+mul:1092477340633785505464776554395206472561372312061,-80145274095041381989361699268630409045305877,0:-87556895907716629238600642139851536991533588781637223712321645442750907264691471870441282497
+mul:5221300639042222043517187865188827094681806,28716457589092549537459686031371792838180039728,0:149937258360957795852063558466179437205735302066386407915731516706048526458470970598788768
+mul:-468871256127286679587501070578429844680401783,7709908112767006788780052051800778651016113933,0:-3614954301459024712014678778499413536274302047069226791616378154943247688691115133744342539
+mul:60187668034435065431875732180204005950423,6575730301760601160210842777500398231559661,0:395777872486342581314679269175741080629857948827943943881264571589081297075932686603
+mul:85750547893356514086330287277441673045104762,79743140579005364490235586620393656130064,0:6838017995386660810928499954451837697514688360722982501737493782122901963128377764768
+mul:4548581293372942515724176487253593549214930,4238661184062900689214356649238748109095650,0:19279894970774516775564064389921196824376868554446937886047574519905039195049778054500
+mul:870890539340345883811990618518239041519315472381,-326492148393756245001717974027772662339968,0:-284338923205026619246910784734503794029639825911870769385331694156076881647046490736423808
+mul:66987553698256227716875714961629477167428173612,90975165679807773385648454136069587671757554212,0:6094203796183880252983468130806830185765137990039968456622459271312350291704985779779237853744
+mul:55214217278725852504312036656428464058159216571,-38639629611220548541845337991516346077285504,0:-2133456904923420705886788529419803172916228952081562524788395230166386012381289930934886784
+mul:891217139364757949280558543150622433360536923866,30525879876993440244467275213072433106397646327,0:27205187340566323080358381531226152260280933712987740283334272666071747659070919682319193540182
+mul:-27569366446500582408824975793718887457276922405388,634666021153562229559368735956062829411322343,0:-17497340108325047390655423017206758097517868311360137049025654413974571287769192246265387984084
+mul:502864235446447920785714797929749621810588808385,-661761137717295415776353819805381820532626437501375,0:-332776008566379289514058699683955504618562833566935527415040692964912956262842183217462238049029375
+mul:846540274257645306570757431119674434472851673,8616613565185012233547219046445322085886975,0:7294310410643867160484254450457795378883045914986526511813394090546583372432655817659175
+mul:-3309007371119113533010968742743901666008447,-54456422219293958622124113256532150483182055,0:180196702528418384342054817105817441009885252753576126005393548812004572770935068818585
+mul:3808438337556464123872249539607274641406985997532,8958313515020597801994910602927304472155060964765,0:34117184630454650095284221741033298990688190756311433174116017572873358206925691228892157828959980
+mul:3966980856734279836284487724100931405197679196,7991199588345191911654938564028578389298180118364,0:31700935789308233758627957773360639061582894143974709760939541889270491143844984071481380355344
+mul:65639444382189527381103754239686068124303248439,57344187472963481946737524023690750337279473205806,0:3764040604273435895633212274119116479837782295002539485107922790189834206416168312084346995236834
+mul:415167227201847402226579925485934896345892,586575228633844519664975226407615633553394085108,0:243526811217202913688658430933411830761556037052309989639490972226539908815021715654176336
+mul:61619333876398280418219395631027787927517659829394,919912829682211281138193507951318719985265,0:56684415789370483176959265833922690931907142380410669255035534110985337015940545738093879410
+mul:-868753784405826481862596863379498777711457154096,545880080147628730834302628389405153791727839,0:-474235385460008330984602458660116725933386690418517481411723635621365531412330794841516078544
+mul:9429941770445780812848883836626433106364646270218,13789105660912116612159357433833332620650429,0:130030463448925543470092963482754387029792169816829218586198208779745648441067644420051623522
+mul:43608475425036256086742701999180132009804867174088,26543470249142438881834938827109299420258184885237,0:1157520270054909035662868646857940204973664076401942399990577391349752558661122837219065938780138856
+mul:57684506610503798187871631196324475714333617510881,471695506003883133237678946411955700467360,0:27209522534225930626068350341042360052253774045631066166444663548471852016504199451585344160
+mul:45545031179301366913301053296868047362176530184,-91968879037454375774626628433933013352182139387,0:-4188725463286255430640627639956152535588659815635253627540812068959602079281136816961500757208
+mul:-390021533721654785753654976920878586915091,77031076759836910371783959035306703983828680,0:-30043778702102109808680236214798858402330647256427091328746624712038248759912250609880
+mul:423541795082126371645621560317104281087986536944,8300998559716429411460238557591751288655280830676799,0:3515819830956442096665703788765672916368036936505243022506012528660536007280216565165558183737162256
+mul:-22004254439719621882091733525180851819037175217519,99335356922776842325949741933027888097618837,0:-2185800468589145609464205476226975010639204222945574205629223171319215468510436674371426805403
+mul:-568617824838411255064542027229734991599889058339286,663945656360600870466864889023341282183894393751666,0:-377531334930676137341317084292560605510952651296593454952813714006651559679453405651218795949055750476
+mul:79416546968775553905606945911160893343240489,57823044209535496953371020115352329847370545,0:4592106506344161115031398878073106718740642471142046845754411556618094588197446229996505
+mul:944931014689390846530685010237152128723129879051,9132010491010578008428313272813386452749469110941235,0:8629119939424787805155145456276331139041940822281098763310858175298740567987777487797475766318567985
+mul:10724730362623743957337791385603755532922863,72480373654893123070601266938859686093303005387292,0:777332464030946381953104911976964384403745616151494866542937429270491850221347238960076456996
+mul:7713352208339235603081099644445084271357860,603624463205826416829628929324533190899935786563381,0:4655968086276246859527680228796939930213380744965640764495096069501972383741189048259822524660
+mul:-374652992235609318781751374140306949494493761487551,-8211631925711097443824357620157273567158306960781,0:3076512472105121389035620380499987642797429799314779956051883946663228512561940943539675904376737331
+mul:148033237001979427358794216800322662159772216729882,-2761071692676096788505988250569937615812882,0:-408730380261377140975921158356878339630350304768292968573861638003660928294552005391249939924
+mul:8799836897423935827052239970797993642793054321869,7294647877437509677171255169879966954414823484,0:64191711545589794049942507329622817162690486075145161653225201426081306037945865801824955971596
+mul:638050122120135743843926357476168630346968836720976,-521011870575614667006902791543319211035082259559038,0:-332431687646811297131860656825650731646114948863860886066225973078382224501114486836618755307604981088
+mul:-17589569754541719055752617853886490778777621596833622,-757763302557856615098419826290170728613135917189,0:13328730467773320372749612468589169429951770262414798041479922130537436948993914504659373603202928558
+mul:-9391500830250456597029446286855934735787373415653,28432489383197015180933073382445953529667174,0:-267023747648382060661246943486871855039477521250741910116209365765385119618211444260651874622
+mul:597671128380217947385553643776956963479914986403,71727950226724858021016384499343090206442916,0:42869724948406755644439192851387407923848606069058040508413206852418378147081162495135671148
+mul:220524861586728547654066186650842017022514113,99830670175055229565653522851124444573641171168883370,0:22015144722464404290431089740908195479979690191563438782672166808199720494718314317705872276000810
+mul:-19711747183549435340491469077888147043386014913558,-1141914280129478236596364286858351511269528735,0:22509125595197123566803201916751380078133670163026469768611121772532745591006866402480422089130
+mul:-8382072953685010521572064715326232892979307367,8986558828596332338706049003428573784660004270,0:-75325991703876567601582024901200837475422482663143278160590315962341962045355062611862457090
+mul:8502152308582607794375019565844324676023491104593,10470050208175536662422671560468368371690332,0:89017961548415452362336397742460566038542969501801207576446421265423116103719862689218894876
+mul:594601725521916181847167140525593251441576703983,963458725567603941710493681498226412426881800,0:572874220691643607273440473752072791294210386705034629979437739545297813514469057230330209400
+mul:7141961266638507042734562322157608790427840009,-4549724799885066646710284284349071123364728193387,0:-32493958294643778569864068941415075147150500523994618476463881411873140452414616492271247820483
+mul:-556279059738139499395948604306347001411150129841210,96265906951839620646630096006130967227739083772932,0:-53550708204008570858552227539689352744237572475214571815802430633001465739150610790161193168856127720
+mul:9097507009232650355633416767082868346314279788737,-12952310876092402836370081770801404571317963729609,0:-117833738981010925067125768441840140051091195908538031159411055746004033932320364747308545111613833
+mul:4268792759888467657870170840963084681877952381149,45230992824683770972952637110379461673717665076497477,0:193081734692577312252243894972856695658000409843190512520961090560296517492619302198905276169040861073
+mul:-14981624589272129153412283534256311120144659052,-3422881033749335138988900898217088225431538419464,0:51280318661372243898623018770432573729075192413326291326269850897282594874283136278341240588128
+mul:1220927142068793741881867214403185329458765760024,30622524744504892825380221509502752145574896,0:37387871619239277065352340275615230576537543517582369985500557751663316964285147851854757504
+mul:37912807996403481194979034824173466165481184382714959,-90878397829297201187948170371749592240094934625,0:-3445455247922915696812807051659782073986976942393793434021443082292576682286942256582247061114555375
+mul:11421510093950565340830017403217629128966938056,2237414009357389011349863244579333296452235392013656,0:25554646692221823247642416835188193586733448912454167957899665467614560251117634306180050458092736
+mul:192657988036570687555057992620686662908295387946910176,931495134488306662235768448970442482109561110,0:179459978476371988595767318602181178186396303909063154620374484681111185009707914339840931952855360
+mul:3406199971289940059753501832956133340637816361746774,21717729758322757474808809344766892648120530501033,0:73974930479281653383172304844520436444384314366038505444774962096871058594711397484185935845291417542
+mul:6909979467876024377878180024452018966109074368033,842722308262405734840545048662350517397572773044955,0:5823193847214313361590850639006414894786757219881236880655209757454129105445924052644535803723923515
+mul:373077837411940479742523640303846004174658252010,174968689985940718533112057941120724001834591,0:65276940474755009773288570940982140032743912931132908824689438802225554298870445697213277910
+mul:69447921082122879577796325457481062492384026062297,4859735149388070292660864796695584862286590039960,0:337498503134721348480339150893268639814027256856202938192556796481021571996594857372873378679388120
+mul:97668956744134573191931364533568770116368809990432277,32650097939706033583832290610502297382443475332059,0:3188901003364905942071745199167504684645498771234390707296643812873542739572337441867216444655526468343
+mul:-1130623853521736649164698623052358825973875071086,97117938880122601762963490311393663414262844,0:-109803858302732709122723543874405473115932722476026603503929119344711278986293484666788528584
+mul:5196766948376722446473792182397797566282488000645,612809465745222737408369151997835003504928829,0:3184627977237170791819733844305891092484494030274488141848280463948439552688134126307231094705
+mul:-260800009832764286426719551521843883719112476,-4764630548313512861236355180550436291099515479440,0:1242615693849653247685309234997680134044316133101561211221015368136727312822405604340425493440
+mul:446884272848375074930942162217302913946161786743256,21042882325490620038960351129083746002919260315816,0:9403733166660799648590511384420343808695460628780663235301885602775520005114834045365148352668136896
+mul:951599922613172445123982155673072679115439437787116,170174123089259663169419228763721448308107859122519941,0:161937682362503977661236466402707947708915167258582987092600978773889146161299886218655580651394622880156
+mul:21383950451514823653827321489681070470148156716394,474049024111864801681311013604155672359293053819708610,0:10137040843197072851050642470285630585293351622620638212811885320208800091533606694120847446939489952340
+mul:-470414357544256461922663993336752968654129573423633,9062081906619161788388889503790336651084511675587,0:-4262933438115683672713863671510520101815219800470041585560023172590216986734948687990123769014947571
+mul:780091812513073375693179028189802313142318232500,3497278556984926411479728842600230671778387696053,0:2728198368381477015989505443597065418103138169441425077910216137727395317905388139191010186322500
+mul:-1625948018138433921639232759767284243608022009577,842118879046315463699452834842435152085239651627,0:-1369241522422316177317692449844295269090380811960323302423745772493265931792379448342891937631779
+mul:25026283351500865895404594716390919370787136725638,193605742569640932386538365909397399503766353419,0:4845232172025567337840956469216133356563858466840983726314706900481952782728859639508827146256322
+mul:4935030558829975380051283297334807636335988292915939464,826975811338155401386754284486847375740824437795565,0:4081150900367009340504991854566589470179310873827349635534175745385923686159595506846989467997551147677160
+mul:692976306506130156561485116659173381923120836885557,770158528298664593632506223863839610768381103479684,0:533701612364605511333411361009902575918331545270987516486697902333932240009170947895587667949982523988
+mul:79877139216893064041018839082816187503862428735,7269106113282857654532427145534479409503583394410641,0:580635400993063264937521052415287406491591842310757481379039941960972027583729569639227998188169135
+mul:2539745404867281753796678186777103230989134057269,1232562503892732555700624680547460824244298064,0:3130394955473278587381949607908298163614591827039064669019870794477245183817740184883281827216
+mul:-12342369542383197426854745694214905543911988477283,900468407001638487525579769577535461149066925224901,0:-11113913840455339589057682433788692760910363591045622111658103604207392316252364497138359285304423983
+mul:25508383419230789798346692675791795579961116333703,-3196912743165527117167038251788165837584914845275,0:-81548076010491152335265692912387445585857263580983374333387917442921969005827781555255165512803325
+mul:-1299528036083269250543034346520127753461072609198859,600594652353551219594047525595273354045086799190,0:-780489589055124260606091767683960949165161003741168476167365844545079097602756258116044302510124210
+mul:2299157394917175882710807816574923359426328448491205413,-72838172890838078649390158065336999589794176457016,0:-167466423834226138899695762647031472841630725693307898812516233189758231307075087592787449022731421027608
+mul:-7349901043851956691882158234459042155688766310737050452,38963935506607940884321914070762438994955796523516,0:-286381070252598023694679445080668983274723778018815928227159321326339627469156721047447539093637496429232
+mul:958387014018743982544025716556283287504010616036,1443504353635051762579994152447131178181054158,0:1383435827203354324881238067046558111877918566103625557579208412963622898173192934117459277688
+mul:246125390054194220242986809766512103907648232140291,244701030143825150512131468437935457382757506654,0:60227136490812102782907271910174306533407908424359655603867506529129414912591634812915769093996314
+mul:-704660850546084071765145007935951186831012905395382833,5588984198927622386999113229239134076765551765835797488,0:-3938338359304962728083277304047487715370320826599483665593576088149516002866532798742909925478892863619723504
+mul:50682657377075501007405908966255159073041913889268,-221227972486061875975200412557047324616212536548,0:-11212421531736159902862014641256856908352469946769596801579726135954662759261565882858426274966864
+mul:-65153936048938235385603864221810574284616709045012408,2620409042204728497893539911547700871421142555353,0:-170729963157866373963111608067452447067616052160696883002411341925443387533862472832785201804711820024
+mul:2124140486540339235997181873057458560557130144031198,6337118390151757487365380009696068490770095523526655,0:13460929740520685472324728914077419222468164771987370279610883339996690538208206652608006128131304582690
+mul:70505951289040282645383932312380844925860919298,7547000534925894125969206219651626162975048702546706065,0:532108452093846047616616850898050963751081524640768880912328456268423081073299532380834291122692142370
+mul:-41539404414450841529694974131865311088044938789,-87120273993379326877611820290578462959192080166852098,0:3618924294108748055270837693949939912318794083201327440980670903703748636538106296956551875226229322
+mul:8365100924146743906263010309561180555381451232169,64464903694507870558459227754837948332608708108908133757,0:539255425469958633518840532058336282586265952721118473314120789860073187010825518609049764601833913228933
+mul:-607028381550248615720149092346152462853976790359415563,-638047705393414341349283089715056902457142563666819,0:387313065956814142347580416821601619522788233833564805598190281345003710840619549824608697022583095304097
+mul:9617834842433276206013447576300042077483363020815285,528061422615472570377974310003284316297281680382590494,0:5078807549375975305409474126592664059166274736600561408401824181271910205956102095093049029393852170900790
+mul:86576571095874523146332767288469633576872568596,28806568894922815646464384363885717260300665904363145435,0:2493973959959492744618741686252959362351894366493500719340778231935540767761675386859282345646361759260
+mul:307009198563449723583109556832166934014223122475324,138726608616028283757694379054230076836833023549,0:42590344930632202620089538756907194977499968842538325319841912047531571749213635995957120063404876
+mul:950446831200123302940271854492691726825599408858,-72101792770002156123347099210449392040964040896942,0:-68528920462096510067650339988235647246498530567363500303801515664792809889462344386842251299912236
+mul:981208671446974342191660850214776536471793694644642,42331603864003005956059961823201488180622810810249336717,0:41536136787617995005181391797616187316701801094427498210675495592371812354190764162938589949104015517920314
+mul:436034751789860072246023599184144455891992330310990,72833959249163120346712529298424162613591559886645,0:31758137343081624453269752355328026194721352914558720990171378846806391947794460806298848641997728550
+mul:90712859511805773491925085535825623597765615019643547,-747515802065477997196092836504038150570958532540685162,0:-67809295935620517600810302668580552577312402195771262364310764109361834590609187219719805153318608391949614
+mul:397399782669545823592934194763075791833495372998,-59196779886291303828419299835113054892183602687860135035,0:-23524787461549105672926147613053790427130112546635830152219683595731769479837306026216856302451972784930
+mul:32400956990211215478801690694170683149459902468,-4583955972534683626923454093368608704790928252299,0:-148524560311118107934748825020984325384128831537817042673475700215519245003301091136794236773932
+mul:987205647053507741802554416690401353287928887038,99876648283232575129630115679242229378848334523759990898,0:98598791193984227490766355696552554241176001533681327979309043773446027278571920948873010940294150180124
+mul:613843278686603793281546390730144010908586402122774247,-5096436233192165525303465082471737429087562092805456864,0:-3128413126999883739898127525581773020068974144641842702264583891275711281299548031054626111037897411968581408
+mul:-976952961430926103170472845979881570029763109667,935178486322270132160329332160301439376977149568344208099,0:-913625391679032626735612276016819847879751832378461622543415386714525380228017439645010525807254806593033
+mul:-14766907052440196735362466027665124699631240785562617,56185497908476101017098165076418921931361374576783903,0:-829686025309539659436877109175759992995713482163632861241130851163598589293178881677705053185350284154151
+mul:8086945629611784458016532027184114429962417844094,915144274243273504802165174453120299631299876477769004475,0:7400721989055888996136233798580013159529233408791044035035967083245349723159601722480356017380766138320650
+mul:78088762763327100616786616097147636046671948600444,567540241084477255158834032762283528860020033647985833,0:44318515244687212982877565975681071792510147353364795293924376495712873521681333329643702186243889509852
+mul:719986964333569855824423695658491299542433105292,-615276910378191482694097418592439439457014608822814,0:-442991354927732007722531933484439672517856888972765946209711703099793423501561916310953658633731688
+mul:45518095176552517046254533808850801860612235127698055,35562211507032265793347677842985571735031362689772443740,0:1618724128065785795744673208584473680751616875603258142963030074995341676160450789993590567976668358194925700
+mul:9347651927739244225461883666785850681796998039204,-49878021756813856103391637115956958358002286487531,0:-466242386226901006946356389028134676636414341103795172547644257145552025595817036151721871395165324
+mul:-918018144578664428004161449615771398954961013294489,-670699097650597095681408528960639081653596263477957,0:615713941195785615974127065795375976710193022314921690147944271007135254397488569454896629925801078973
+mul:27390700201762535100035783959539579449610388231,-1589447744597072139866306928627083981945967837919031841,0:-43536086658626030220375532900736667658969827278059194645833847995230392704902546272550528175660663271
+mul:2277199840598187516900058221233481999025368188568,9608219845154413235861538421470991851896216584568613,0:21879836699817971767000557908575054021947917457695046204371308982480723639160400066580492493518216184
+mul:-384224188940171310851587214747099156035618205974037811,-365155157346205326208918238248019306559191342503,0:140301444168666379290296176915045491501178018946537404762619540722359114634558549786149744296773380933
+mul:286446854858822908871115682474835177238732522628,-57158496101544373650727927690968913495792599007869,0:-16372871436747676262278174307506297592132492975051635951931260785772478739228382233254016392559732
+mul:-381089856197823678538852020226946248080829424869589,-3010621081997078653311455126099557341287585438919,0:1147317155204403033538417293781061706820038418656862236980125391331092308923135144143540086900134291
+mul:116824003493453841699155925492342665434851317689062,-23510392931055495213857939210838689217666922526899551035,0:-2746578225910099677716238357776888697288117665636655886289546239917490129557481316738650939508921530279170
+mul:580076669302513896163920831671903321718154827187111,57642903862300589084685292813271561699366462736142,0:33437303681368339826568875036607309078951222489453540109258834689115591802250959764588162866456265762
+mul:5760449410973032312996903274730533429280588604119,54924391723347076414566698417788233810196808558058264,0:316389179950806757476032029420089976949374325352943306272834362194992326589276708483681497464832389416
+mul:5657781195595763129830083459999757852112323789572340704,692061618840647789470644193517118113508111433346167161307,0:3915533213270179560961108305159334536041508008965034741386030883311266330352593550098270684221170821027129940128
+mul:-411686824144764716061907353842274549877341843077020461,64596348790121485579427789661619008385819947602752810318,0:-26593465684752629063594295950004957994828988051383949912582218957039523707407380651277297287183402393737916598
+mul:632256394728894097701649213009572878755743290206395156077,831219707790000649838963373434914934485492976701321111,0:525543975674910659026260706288720204381515414601996591588570479429744161463440855422928774392151685316940041547
+mul:1670481530219772906326138470230000469885289884882422,468290338328174403769157221534943442214405575737600,0:782270360957583948773973087197246461358063772951438918211359656647137302093722698373813315391924467200
+mul:-5940255960924729598832299636442321100271324046668226,57672031765846684220194592702663453624777841860734299817,0:-342586630475711125183923927161946766514304847978409032225317328682383801381008087781458635612556537811514642
+mul:1070320750308710183653165839089007570013512879851785,1457798154372592051774290334996812066679847800239,0:1560311614386725640264706359282306460222595994684719021358994107802507336028163090509939936607576615
+mul:4878833860261622243309660185570248437064542060170266009303,2713399212910344466363698742990679778889654409261764714,0:13238223956354223315835115083131058404743853065832322244195207641759173433600815039556809272534689440156121134342
+mul:-153727669883775746511963322850970227020812560900211022,967696702028565741720227898697068313091723784217356354,0:-148761759157065858120367305796775921605388922829212089475409575708151324377711363197839787691020073572533788
+mul:-540592613733911579302709730020084890208422708295834255759,1487237786400760689794761062671094249214728767786149324317,0:-803989762194224119099880670025468825040986939150865705871247661626924722104597624198557832395582009863760415991603
+mul:6147134348286513705872901614503400707429078163757093529,477008107151085089956583728568535862114663515203848020888,0:2932232919879568942454061197378668098753424444460385986524578717121657294266275306745807650523035121257761633752
+mul:7614680849639684551334463800131196276563566036683927,25187069984138015151555984154271413618496480687947851,0:191791499466750257309658251576197471575523021858632537910036998866329759048429339136517641910254745890877
+mul:34751974072174908316243318351151710272413759348773,8306602488518142539700335965542308143538343391985,0:288670834308846061096235572592461254734354939539314534410107250770305649520412166539742961467784405
+mul:1973284924569393016522181930166284437824113120930085705223363410232863255766399553325346410701486329074823374249547700471683909277697787590783678904983357211584574690370289495346677331618312561665754485123402827162476353576735207718451299565526093115255556962215997764515429748902159033904867393928929335369918394864191487555087825530530292436823694624357846430402766705368186347858763649288740551240105434820489955559033038872623623075504620415436212337263593361227009430895404467373404212231777284568356947010238293550872942631550054733886261493387307990754063500729850132294968984927109971586336754260617576297578,5023215555039217191451486096670046812323372237867852342682903508090873804207633443539517026163606065770027196694503291009850587117226026773591715017125540836707619882023150680605967194554434367524090941938814045780235333982097410791452776449214446635671357519707417878752761895933104747199582531838714305022614904134506738511247696618513698871318914624938137416674596881724436242382943205716649496664131501091102879563857843031208992280893614063087964394912022421136928015233318011144243860597237613050611024432789921991289922378761307428111094457098264457145099945444765267932710530788173695233378407323077034767182,0:9912235527621363370177765461045903296757346464251250997934314384765381968455767811674327750035883028560327843635490083086230089733649800500491928845965808260177110097000550870708488183060088779215210481900113545281854124601490142211180660492441361405426298053896802091578235012988730731854809702026093664780523793649405978324745399501432045298507869343282835244908856693641856464415460033802080004246708824900236489959461486545994943320360059459917374730418136788819890973086342429995201653932338829740545718352667527142958499428354077966431655595175455785104618218647409782931121099857213491801531717606789462812743975739913830932552436532349361163108142395102143904119547756730321871557900417573185916761969667939077354954258105548072267528998411702020631497735552158986372677452750936969993423245268272976429454770189221077520557005286622417163333812030510164503314440581497599501417407932697447376958591635071781976491704916693799964449632893911830806101578411062044010045678256608720149155356874608716245388282176400921764516344436742619757576145128777884235797616593795005421758664915151768829194432974835591116318659671888399376705850603804666493415116788205809451378581533592708248188469927900316495904963905315042780485196
+mul:5693930165221819,3016628443782411,0:17176471693318822194099185625609
+mul:19732849245693930165,22181930166284437824,0:437712683949801303830876080256140560960
+
+# Power of two multiplication
+mulp2:7328492456,15,0:240140040798208
+mulp2:9301,45,0:327249844798226432
+mulp2:221819,104,0:4499023815872409881769555333012783104
+mulp2:1,3,0:8
+mulp2:28443782,108,0:9230534995215592279593651121258540040192
+mulp2:131,76,0:9898080148094776367906816
+mulp2:93,36,0:6390911336448
+mulp2:85,4,0:1360
+mulp2:522,113,0:5420757920310360044185838167705780224
+mulp2:634102,29,0:340430919041024
+mulp2:86325,31,0:185381525913600
+mulp2:6639955332,101,0:16834286724196864462774406457915724529664
+mulp2:4641070,109,0:3012226647655029057743003824831688867840
+mulp2:86329074,43,0:759358565425078075392
+mulp2:337424,112,0:1752005575194255677729274193390761672704
+mulp2:477004716,31,0:1024359827628883968
+mulp2:90927769,62,0:419330320984095270608306176
+mulp2:875907836789,55,0:31557905658990701020815818752
+mulp2:983357211,56,0:70858354704507043363946496
+mulp2:4574690370289,41,0:10059850511215301155094528
+mulp2:534667733161831,94,0:10590185513519716577933182844778629828706304
+mulp2:61665754485,104,0:1250730090982990067823267062394063169781760
+mulp2:34028271,97,0:5391994769734856490537202784887898112
+mulp2:47635357,28,0:12787018778017792
+mulp2:35207718451299,38,0:9677823956166718317920256
+mulp2:5526093115255,15,0:181079019200675840
+mulp2:696221599776,31,0:1495124500903360462848
+mulp2:154297489021,86,0:11938189976268266978253598864697196544
+mulp2:3390486739392892,71,0:8005560469361491387429364912321724416
+mulp2:35369918394,31,0:75956321382209421312
+mulp2:41914875550878,28,0:11251438731683187130368
+mulp2:5305302924368,42,0:23332969016866530784182272
+mulp2:694624357846,102,0:3522163936626521236224897501281415419920384
+mulp2:40276670536,50,0:45347499604413458849726464
+mulp2:8634785876,54,0:155550473814310487519657984
+mulp2:492887405512401,103,0:4998472123541838661247665060074167267342942208
+
+
+
+# Multiplication by small integers
+
+mulv:39,34165,0:1332435
+mulv:1331169483,45488,0:60552237442704
+mulv:967,3873,0:3745191
+mulv:4609944,12208,0:56278196352
+mulv:-9187510646,-19674,0:180755084449404
+mulv:-9187510646,-19674,=1:180755084449404
+mulv:-705904,-32646,0:23044941984
+mulv:-494,61105,0:-30185870
+mulv:31884502736,41742,0:1330922913206112
+mulv:124758920,14754,0:1840693105680
+mulv:1578359,-34693,0:-54758008787
+mulv:66733360927656,-31832,0:-2124256345049145792
+mulv:25747369,-31317,0:-806330354973
+mulv:241723337947,63112,0:15255643304511064
+mulv:7902551,11307,0:89354144157
+mulv:-9354271604,39887,0:-373113831468748
+mulv:952191019,55813,0:53144637343447
+mulv:809248646915194,9772,0:7907977777655275768
+mulv:-2633237043,16406,0:-43200886927458
+mulv:764186567812009651,1311,0:1001848590401544652461
+mulv:866541923,29701,0:25737161655023
+mulv:-834567728673833890,4681,0:-3906611537922216439090
+mulv:332307463075,323,0:107335310573225
+mulv:27691642758,54832,0:1518388155706656
+mulv:2202473525085705,16772,0:36939885962737444260
+mulv:2202473525085705,16772,=1:36939885962737444260
+mulv:-16583738845087,37131,0:-615770807056925397
+mulv:9196926997210,10181,0:93633913758595010
+mulv:514078180671038315,62002,0:31873875357965717606630
+mulv:514078180671038315,62002,=1:31873875357965717606630
+mulv:-3412120508850357,36908,0:-125934543740648976156
+mulv:549214983476935,10691,0:5871657388351912085
+mulv:651367312269732,44154,0:28760472305957746728
+mulv:-9584205879196113,22814,0:-218654072927980121982
+mulv:987433915942054416876759,34616,0:34181012434250155694605889544
+mulv:98036280382191791,23951,0:2348066951433875586241
+mulv:80662726244584753,2712,0:218757313575313850136
+mulv:47866183268822904587301,56393,0:2699317673078730058391665293
+mulv:-6912574313961965048871386,30037,0:-207632994668475544172949821282
+mulv:-6912574313961965048871386,30037,=1:-207632994668475544172949821282
+mulv:727313511777411140493,-48518,0:-35287796964416433714439374
+mulv:465780278683330104360026,58793,0:27384619924629026825639008618
+mulv:9089195999415213350558115,62437,0:567502130615487675968797026255
+mulv:9089195999415213350558115,62437,=1:567502130615487675968797026255
+mulv:1956713589673152168482712,-63098,0:-123464714081196555526922161776
diff --git a/polly/lib/External/isl/imath/tests/neg.t b/polly/lib/External/isl/imath/tests/neg.t
new file mode 100644
index 00000000000..6feabb3d71c
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/neg.t
@@ -0,0 +1,9 @@
+#
+# Negation tests
+#
+
+neg:0,0:0
+neg:0,=1:0
+neg:-0,-0:-0
+neg:-0,=1:0
+neg:-1050000000000000000,58392:1050000000000000000
diff --git a/polly/lib/External/isl/imath/tests/pi1024.txt b/polly/lib/External/isl/imath/tests/pi1024.txt
new file mode 100644
index 00000000000..204ad8b5902
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/pi1024.txt
@@ -0,0 +1 @@
+3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989380952572010654858632788 \ No newline at end of file
diff --git a/polly/lib/External/isl/imath/tests/pi1500-10.txt b/polly/lib/External/isl/imath/tests/pi1500-10.txt
new file mode 100644
index 00000000000..aa774a008fb
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/pi1500-10.txt
@@ -0,0 +1 @@
+3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420198938095257201065485863278865936153381827968230301952035301852968995773622599413891249721775283479131515574857242454150695950829533116861727855889075098381754637464939319255060400927701671139009848824012858361603563707660104710181942955596198946767837449448255379774726847104047534646208046684259069491293313677028989152104752162056966024058038150193511253382430035587640247496473263914199272604269922796782354781636009341721641219924586315030286182974555706749838505494588586926995690927210797509302955 \ No newline at end of file
diff --git a/polly/lib/External/isl/imath/tests/pi1698-16.txt b/polly/lib/External/isl/imath/tests/pi1698-16.txt
new file mode 100644
index 00000000000..7768ad3fb95
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/pi1698-16.txt
@@ -0,0 +1 @@
+3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD1310BA698DFB5AC2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C9045F12C7F9924A19947B3916CF70801F2E2858EFC16636920D871574E69A458FEA3F4933D7E0D95748F728EB658718BCD5882154AEE7B54A41DC25A59B59C30D5392AF26013C5D1B023286085F0CA417918B8DB38EF8E79DCB0603A180E6C9E0E8BB01E8A3ED71577C1BD314B2778AF2FDA55605C60E65525F3AA55AB945748986263E8144055CA396A2AAB10B6B4CC5C341141E8CEA15486AF7C72E993B3EE1411636FBC2A2BA9C55D741831F6CE5C3E169B87931EAFD6BA336C24CF5C7A325381289586773B8F48986B4BB9AFC4BFE81B6628219361D809CCFB21A991487CAC605DEC8032EF845D5DE98575B1DC262302EB651B8823893E81D396ACC50F6D6FF383F442392E0B4482A484200469C8F04A9E1F9B5E21C66842F6E96C9A670C9C61ABD388F06A51A0D2D8542F68960FA728AB5133A36EEF0B6C137A3BE4BA3BF0507EFB2A98A1F1651D39AF017666CA593E82430E888CEE8619456F9FB47D84A5C33B8B5EBEE06F75D885C12073401A449F56C16AA64ED3AA62363F77061BFEDF72429B023D37D0D724D00A1248DB0FEAD349F1C09B075372C980991B7B25D479D8F6E8DEF7E3FE501AB6794C3B976CE0BD04C006BAC1A94FB6409F60C45E5C9EC2196A246368FB6FAF3E6C53B51339B2EB3B52EC6F6DFC511F9B30952CCC814544AF5EBD09BEE3D004DE334AFD660F2807192E4BB3C0CBA85745C8740FD20B5F39B9D3FBDB5579C0BD1A60320AD6A100C6402C7279679F25FEFB1FA3CC8EA5E9F8DB3222F83C7516DFFD616B152F501EC8AD0552AB323DB5FAFD23876053317B483E00DF829E5C57BBCA6F8CA01A87562EDF1769DBD542A8F6287EFFC3AC6732C68C4F5573695B27B0BBCA58C8E1FFA35DB8F011A010FA3D98FD2183B84AFCB56C2DD1D35B9A53E479B6F84565D28E49BC4BFB9790E1DDF2DAA4CB7E3362FB1341CEE4C6E8EF20CADA36774C01D07E9EFE2BF11FB495DBDA4DAE909198EAAD8E716B93D5A0D08ED1D0AFC725E08E3C5B2F8E7594B78FF6E2FBF2122B648888B812900DF01C4FAD5EA0688FC31CD0 \ No newline at end of file
diff --git a/polly/lib/External/isl/imath/tests/qadd.t b/polly/lib/External/isl/imath/tests/qadd.t
new file mode 100644
index 00000000000..5a98e52d89f
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qadd.t
@@ -0,0 +1,803 @@
+## Rational addition tests
+## Generated and verified in PLT Scheme (see imath-test.scm)
+
+qadd:3/13356872859954085399,9/62913230326443414581,6/70815656362754309351:308951546718917012334/840324018679312348674627422530435802819
+qadd:-1/10707768797352318399,-7/98320256665411314243,1/73359800109931088847:-57758212748959181012/350930192156520858413194622860526552319
+qadd:3/8871935578221811012,=1,-3/4866674049828142891:3/4435967789110905506
+qadd:9/4322444789227983625,0,-1/968244430692371869:9/4322444789227983625
+qadd:2/225379267690226671,1/650264369025696376,1/34848592015687152:217986857963088489/20936586756579823441422616437606328
+qadd:-3/68292234169742612,0,=2:-3/68292234169742612
+qadd:-6/86190045205685135,4/67524620320880421,7/25266746450126878:-60387541102541986/5819950077953408572132977712241835
+qadd:3/32384565517809325,1/12077081878824172,-5/29092772826669868:68615811154281841/391111049368729137348856297003900
+qadd:7/8696576917665055,-1/7581339998976754,3/1629599527000648:44372803075172223/65931706440072050529006903131470
+qadd:2/2271361357023875,3/7926992193500824,=2:22668068458073273/18005063745747695119878000173000
+qadd:1/149242689846961,=1,-8/422836348382141:2/149242689846961
+qadd:1/8658078704679,-3/951317712555992,2/558713214761595:925343476441955/8236583628464972469619886568
+qadd:1/16676404623347,-5/33326850326497,9/43833507346994:-7150738970034/79396005838055435322703637
+qadd:9/79221016041680,=1,=1:9/39610508020840
+qadd:-2/2334176395033,=1,3/4196164230632:-4/2334176395033
+qadd:6/8258476677649,3/2022168438715,7/2650901397286:36908440665237/16700030889405718666781035
+qadd:2/89237876621,3/593210741974,0:1454135113811/52936867002527677989854
+qadd:-1/86244958313,4/307620567537,7/284049788408:37359265715/26530723023449966085081
+qadd:7/30268895338,4/83657377701,8/72832717953:706677225259/2532216409883104057938
+qadd:-2/16397609979,9/46846025410,=1:53886438991/768162853739503566390
+qadd:0,1/192040267,0:1/192040267
+qadd:9/9089766539,=1,0:18/9089766539
+qadd:2/331584881,4/272560309,=2:1871460142/90376877625088229
+qadd:5/832601742,-3/639383129,=2:99872917/76050215287258674
+qadd:9/36166996,3/22041145,1/5580628:306871293/797162003050420
+qadd:8/17901539,=1,3/89155358:16/17901539
+qadd:5/5040389,4/3388433,-1/7168517:37103721/17079020420437
+qadd:-3/1713461,=1,1/4488431:-6/1713461
+qadd:5/516179,-1/59578,=1:-218289/30752912462
+qadd:-1/244201,2/201199,9/174458:287203/49132996999
+qadd:-1/41212,3/27175,=2:96461/1119936100
+qadd:-3/13547,4/29889,0:-35479/404906283
+qadd:2/1907,0,-1/9340:2/1907
+qadd:4/1341,4/9919,=2:45040/13301379
+qadd:3/160,-1/799,1/705:2237/127840
+qadd:4/85,2/265,1/5:246/4505
+qadd:-2/59,3/89,=2:-1/5251
+qadd:-7/55,9/74,-4/33:-23/4070
+qadd:1,1/2,1:3/2
+qadd:2,4/5,-9/7:14/5
+qadd:53/70893980658822810696,=1,9/9193530480905424214:53/35446990329411405348
+qadd:86/71933586324624884067,0,7/18408383381035284932:86/71933586324624884067
+qadd:35/378921420794267711,24/6551623471410322667,=2:238400935598423718409/2482550474295871845608778066489505237
+qadd:36/3722553911462108789,7/3244440092917636530,65/8189167080175627777:142857720725269676603/12077603158395035547949185323620462170
+qadd:74/204211327800791583,=1,-4/261650327849481535:148/204211327800791583
+qadd:14/190596241295804639,=1,5/7319468293717642:28/190596241295804639
+qadd:11/20832946214725250,=1,34/81808092645053823:11/10416473107362625
+qadd:-2/36273895397703103,21/88730391521225765,-11/10905700152968561:584291020309313633/3218596940638185709301052104048795
+qadd:39/8019234291976340,-41/686183563094027,47/1842385817838468:-302027447010362887/5502666759754131835671079321180
+qadd:27/3512663969871511,=1,-21/6043832798535571:54/3512663969871511
+qadd:-5/2985747324014,45/607698145828948,29/712218076096765:-1452066049782055/907216556358525513388378636
+qadd:19/46107312122174,92/20099305290153,=2:4623759515752915/926724942451947423255152622
+qadd:17/10280669487307,=1,29/71287679743652:34/10280669487307
+qadd:7/48006164806589,=1,=2:14/48006164806589
+qadd:-21/5174158635853,55/5726484671487,45/4364076509257:164322546870688/29629740116054290765023411
+qadd:2/515061581267,81/3885600123095,62/1777317903213:49491188328817/2001323343572560546061365
+qadd:59/587566787929,17/530520857961,37/408187963651:41289366014492/311716436441482018352769
+qadd:87/16848388346,=1,-29/793777748404:87/8424194173
+qadd:13/40356316605,-16/35824973661,12/36053750683:-59992136029/481921326476367313635
+qadd:62/58964244603,=1,-41/7476886656:124/58964244603
+qadd:49/2379119051,-9/250852979,16/749619475:-9120275488/596809101339002929
+qadd:35/1381737807,13/332249103,=1:365324816/5667668480949841
+qadd:-29/262819147,-44/212418643,12/429833273:-17724183115/55827686560157521
+qadd:14/189466127,31/78740185,-7/602930208:6975812527/14918597891213495
+qadd:19/15866903,3/8919802,67/8901141:217076947/141529633113206
+qadd:8/44756143,33/6935255,44/26346673:1532434759/310395264521465
+qadd:9/9886228,0,=2:9/9886228
+qadd:-31/5061520,-19/3104202,43/3631883:-96199571/7855990253520
+qadd:-31/302786,=1,31/132480:-31/151393
+qadd:10/50561,56/854269,-17/764873:11374106/43192694909
+qadd:-12/40781,=1,83/13428:-24/40781
+qadd:-7/5458,17/6090,1/14614:12539/8309805
+qadd:85/8919,25/1261,=2:330160/11246859
+qadd:25/2609,3/832,-17/7121:28627/2170688
+qadd:29/910,=1,-19/91:29/455
+qadd:41/715,2/15,64/97:409/2145
+qadd:22/3,-3/31,22:673/93
+qadd:35/29,=1,4:70/29
+qadd:-14,9/2,-20:-19/2
+qadd:-60,=1,43/2:-120
+qadd:375/18696391582109365451,-131/32949770573031503434,166/56750232802998421883:9906936667630486913669/616041813174061083543307811398267458734
+qadd:615/80348516296708248277,=1,=2:1230/80348516296708248277
+qadd:-150/1530888833706527119,136/9537020524274172927,=1:-1222352197257038250866/14600118227441300399114525155221107313
+qadd:89/1394353050192727085,=1,819/2322159924711043043:178/1394353050192727085
+qadd:62/46458468892037221,813/119745041246081149,-121/356270572095961665:45194927766483291911/5563171273706775007904337294446929
+qadd:809/639945078105944091,400/118384885068174771,-713/209608760084814514:117250467754177008713/25253274840505439393971462380909387
+qadd:1/576267190309129,=1,207/61006148560056413:2/576267190309129
+qadd:-515/3615716945775737,83/23367471127892459,454/27760785001119423:-11734143124365230214/84490161337046038094355667467283
+qadd:73/835205561268243,353/4576154733864164,=1:5197412055370031/31587023826011126162743214412
+qadd:159/1356415561313968,=1,610/1188572111871663:159/678207780656984
+qadd:17/27804219463543,=1,480/45536329454957:34/27804219463543
+qadd:-313/103858729128189,97/192554775266034,53/819834763511200:-16731782644278103/6666164748898110732454544142
+qadd:-497/99654168988628,739/9692326546155,144/61549637278907:68827344589157057/965880747523495532712125340
+qadd:-215/35851399647701,309/1276360474687,-79/2088545670863:10803664989081904/45759309472532992928244587
+qadd:-121/9491608537990,-109/8274027606869,1/42153880273:-2035742671072059/78533831076922767571453310
+qadd:513/9899067246839,413/3814421378956,43/320124503991:6045112940348935/37759213738065792812120084
+qadd:371/929964631846,19/164386836347,-347/394487184823:78656844289811/152873943743766506506562
+qadd:149/158337939815,305/905893441427,-73/931434015171:183271194416198/143437301207471553716005
+qadd:601/39399444858,=1,100/29792912589:601/19699722429
+qadd:7/24017912572,-55/47728203251,=2:-986887768703/1146331812901164171572
+qadd:497/5699936840,-145/2007901849,=1:171436377153/11444913720219217160
+qadd:-307/2244804442,112/2757559041,399/2539679446:-595152528083/6190180784314060122
+qadd:-15/24574214,=1,97/256299894:-15/12287107
+qadd:-79/117243052,17/136766977,280/170126053:-8811459299/16034977796293804
+qadd:245/15098288,971/75107317,120/16937981:33061730313/1133991902973296
+qadd:431/62180997,-385/41204984,-169/77089643:-6180335741/2562166986489048
+qadd:-917/102195,=1,=1:-1834/102195
+qadd:63/1841195,-479/6792243,=2:-454021096/12505843850385
+qadd:-164/387359,-783/642485,=2:-408669637/248872347115
+qadd:203/17726,557/813213,584/477219:174955621/14415013638
+qadd:696/29969,-780/92741,687/81050:41171916/2779355029
+qadd:139/11350,57/11570,949/42570:112759/6565975
+qadd:116/1819,288/689,=2:603796/1253291
+qadd:101/1329,260/2321,-115/2808:579961/3084609
+qadd:-995/559,-419/64,844/991:-297901/35776
+qadd:98/479,83/90,-941/427:48577/43110
+qadd:502/31,531/97,=1:65155/3007
+qadd:895/7,457/97,-217/22:90014/679
+qadd:60,=1,559/8:120
+qadd:842/9,-78,=1:140/9
+qadd:4707/49292519774798173060,-3367/70976135186689855734,4680/92255023230843683243:84058377121001851123459/1749296273614329067191168098769082663020
+qadd:1609/2121030704455118221,9004/45879979595713054965,-1909/56276212991908059822:92918647632416189900569/97312845442281711047521870162146017265
+qadd:1595/6629759211105345266,=1,=1:1595/3314879605552672633
+qadd:6064/3080056685556987183,4508/1637245998798276241,4554/192867820573257707:23813155275203645346388/5042810484500057739317394353730419103
+qadd:5984/719002302690645499,5551/827085169170104629,-1133/281319473813875339:8940459434549679264885/594676141154587307208842285377914871
+qadd:471/5383706422635043,-1059/135831330372294919,4069/661509955962879771:58275211503780396312/731276005720386541831883100246517
+qadd:317/23905256796561588,9403/29217659230012136,1579/93558964298111076:58510781908495614769/174613911721967007022035077857992
+qadd:37/3959930712621791,-553/29796300050913566,-467/11895602422350163:-25287874004559267/2743983341723415461995269514342
+qadd:4808/5483375732140019,-1167/2909491781718641,-442/1776182590086113:1084248143870831965/2279119518390974491600667770597
+qadd:-3671/9168542776331636,-7/406053390120221,1769/5947573797737151:-1554801794565652743/3722917876791723943159405611556
+qadd:1006/103477396982149,-8126/225516229246559,265/155176584822067:-613988001254904420/23335832379663506318642675291
+qadd:2623/84239743205954,3169/121906161822547,-5709/26194735454912:586715608680209007/10269343767154832537421844838
+qadd:443/2686896931288,3316/28495742324937,-3677/558065798916:1266668474946947/4503830741626282579878168
+qadd:4417/89265364740400,-7113/54425110575655,-7945/40916976250387:-78909765197159413/971655469314488996726992400
+qadd:-597/8004050520667,-963/5824074581732,5137/5348060857045:-11184873176696325/46616187188315454846655244
+qadd:5937/5559132885590,-4758/7557504569075,7304/2395270970465:3683710071392211/8402634436588302845425850
+qadd:4329/271647765458,626/121599326283,-7069/977356121708:696454984655815/33032185265975198932614
+qadd:3644/7586698567,-2933/927690827006,1427/63030966192:3358253586712853/7038110667865465100402
+qadd:4385/67179997993,-2494/15819866041,6466/4511530241:-98176802404757/1062778568883908855713
+qadd:-3914/47589537237,7583/20994047283,5647/65572699238:8445477569773/30275666513020217487
+qadd:1511/1463679102,1175/4782029924,32/176197467:4472735080007/3499678632448724124
+qadd:2671/2245073493,2492/4004524047,1097/1196765648:1810089652677/998938976666754019
+qadd:-6310/734134819,2131/871643491,2948/276012457:-3935629128921/639903836497813129
+qadd:-8499/333851789,1381/107324058,4694/778673201:-451097848333/35830328766039762
+qadd:7387/32996439,=1,-2169/53667347:14774/32996439
+qadd:64/927251,1425/83805722,-97/55678833:514222991/5977610733094
+qadd:-229/212766,841/1773874,-1644/3034871:-56820235/94355018871
+qadd:649/6801849,=1,6442/1282895:1298/6801849
+qadd:1093/555053,=1,=1:2186/555053
+qadd:1472/313297,-4055/65502,-988/274137:-1174000391/20521580094
+qadd:7186/53795,8849/16267,543/16231:592926617/875083265
+qadd:1855/76431,9227/21314,9319/78236:744766307/1629050334
+qadd:3649/8263,=1,2945/1888:7298/8263
+qadd:113/5086,-588/193,=2:-2968759/981598
+qadd:4457/114,=1,4229/115:4457/57
+qadd:-1210/279,18/101,2941/205:-117188/28179
+qadd:-1529/14,=1,=2:-1529/7
+qadd:1447/94,=1,=1:1447/47
+qadd:3859/4,=1,3307:3859/2
+qadd:2680,-5349/7,3131/5:13411/7
+qadd:26355/1842957535448256407,=1,=1:52710/1842957535448256407
+qadd:-23972/10860515422884440037,26937/77294406487002446441,=1:-1560351808360184484806983/839457093754789179857466996851368558317
+qadd:-40520/1003897140843598099,=1,=2:-81040/1003897140843598099
+qadd:53983/154204493365472465,389/90815930118883934,89726/3798744434445137383:4962501903526880198007/14004224493496648610131716407877310
+qadd:6730/8025480371035471,=1,=1:13460/8025480371035471
+qadd:5789/275109143231142112,-70061/298583162637001399,=1:-17545923755411446410021/82142958056310217788247049711814688
+qadd:43609/16618250357288024,=1,5530/63408107485667383:43609/8309125178644012
+qadd:87785/73225998153574891,37715/66514284957194283,=2:8600675025329377147220/4870574907461862714813485677548153
+qadd:29071/683129957825918,81512/615183458604239,24291/9113716458411940:73567287447390059985/420250250131516159851218866402
+qadd:59555/7990017410441913,=1,78329/5337044591694823:119110/7990017410441913
+qadd:5029/36615500243388,=1,-5844/782117748680987:5029/18307750121694
+qadd:-95034/708404684023045,7237/43582118287425,962/306992443764355:196988333789525843/6174755346891655642926741825
+qadd:81727/59355557665587,33706/37108442588563,-69327/385353327593:5033400114111763723/2202592303945575671784881481
+qadd:18580/8202880287033,=1,=1:37160/8202880287033
+qadd:3529/570956288395,51454/91669081267,72122/5210249411885:29701485050867573/52339038400785943996465
+qadd:1795/316792972368,=1,=1:1795/158396486184
+qadd:-17887/290287394860,-22309/449346280424,63263/662079031487:-3628369602468957/32609890283578494055160
+qadd:13131/63340483459,30113/382543142829,=1:6930545986888466/24230467610714148965511
+qadd:-14617/14636593116,1341/3731854192,-18413/12969994431:-8730210338977/13655407844135735568
+qadd:12677/16187316610,-88834/43865688355,2573/8033027431:-176379750491281/142013557143595015310
+qadd:66701/1078856211,28387/6472397775,-25495/5284061884:51371210583548/775865171069036725
+qadd:2351/2179309208,4443/1189508696,5983/1449971042:779950359715/162019203386804548
+qadd:98854/387184463,34645/227217379,11339/75650021:35875352504301/87975038872382477
+qadd:46993/558998125,79614/180403205,21187/172641639:10596352907263/20169010667798125
+qadd:-95664/49177319,32505/7903417,=1:842436270207/388668858999023
+qadd:7609/4376152,=1,-49134/16441549:7609/2188076
+qadd:-39475/6548191,9273/3028760,28453/1580168:-58838925857/19832898973160
+qadd:-71284/2152619,22629/219994,6307/1044349:33029563055/473563264286
+qadd:55471/884276,=1,70589/439282:55471/442138
+qadd:99253/702279,29725/193293,77332/452861:4451128156/15082846083
+qadd:4672/13301,=1,99701/23262:9344/13301
+qadd:11647/36600,-12718/86193,48531/86404:2942137/17238600
+qadd:81747/4862,86325/5233,34995/6364:847494201/25442846
+qadd:-12670/7457,-5355/1898,51394/8063:-63979895/14153386
+qadd:-23034/127,37704/779,-22033/804:-13155078/98933
+qadd:21121/777,88921/734,23573/138:84594431/570318
+qadd:93724/99,-81002/97,-29731/3:1072030/9603
+qadd:46063/35,84170,=1:2992013/35
+qadd:-53,53087/6,84985/2:52769/6
+qadd:6484,-25157,36395/3:-18673
+qadd:502735/93903639167159766403,=1,-182075/14327482370605034031:1005470/93903639167159766403
+qadd:964341/54574070369775729943,105355/12364735662003164536,891428/78644454680386798849:17673472736839515719955541/674793954121836196578645015875330901448
+qadd:395315/2495365929584166774,465224/7310483990485507083,179846/4219676087482572977:1350282699307880878594507/6080777559542678797435646824476753414
+qadd:484689/8598175504270279871,=1,455252/2180188091947909803:969378/8598175504270279871
+qadd:721437/15467677986707891,167201/325770348193492422,29365/5095805222384074:237608993916724138533505/5038910843474647501780261636102002
+qadd:305023/828712715944217373,760576/326121435327718203,856883/159328170084137681:243257847069985220706839/90086993466019930569059540240313573
+qadd:552495/79059081794978678,739237/4377984896396103,=1:60862213214209017915671/346119466021360760402283927291834
+qadd:-324714/14566706981425225,=1,898113/17904108312665273:-649428/14566706981425225
+qadd:678715/9330341670794893,305282/6752459700030591,-181029/707344352338564:7431381051249869095391/63002756119558606430363386571763
+qadd:29371/8832474155792490,=1,139981/1228293392110586:29371/4416237077896245
+qadd:-410473/489580012740170,138771/888182189776802,26594/728753620910729:-74158825009071779069/108709061946629702972179884085
+qadd:159641/107674771231896,751942/36141035619445,=1:86734773896978161277/3891477742407545118101817720
+qadd:74575/96461557770386,689363/40797971566422,=1:17384884394708131192/983858972792245290555894723
+qadd:82781/8818234639538,=1,755413/85622526494566:82781/4409117319769
+qadd:540719/4870455998403,227043/4599456084178,=2:3592816235626056311/22401448474575913801567734
+qadd:252638/766528476245,158438/3053066657539,180745/2135691256678:892767892946643192/2340262532877784911661055
+qadd:-110463/878079093193,79446/268839262339,12485/16768131207:40063080202058121/236062135689304156158427
+qadd:-173279/107650733329,=1,-23166/462291939529:-346558/107650733329
+qadd:227603/47564019356,=1,-433003/39021527209:227603/23782009678
+qadd:-488093/80889009444,323575/34893143332,-148268/9979738867:1142820277812053/352808975064124203426
+qadd:-39438/15658613,=1,973663/6699939467:-78876/15658613
+qadd:881284/8851714483,166494/3388645931,694663/5162409252:4460116791788006/29995326265191718673
+qadd:-114870/51892709,-65507/276496014,395733/970026370:-35160432816643/14348127194161926
+qadd:805009/674975377,-21652/70238877,=1:41928361272089/47409512483131629
+qadd:531750/53640289,-12447/5407124,-742474/12677537:2207577509817/290039694018836
+qadd:737071/19678454,-571315/70114882,66254/4831011:10109262560903/344938120038107
+qadd:-19051/242105,785139/2763106,252071/1451468:137446145189/668961778130
+qadd:-233713/2488948,-648637/4197650,196342/374913:-1297734569163/5223866286100
+qadd:122954/95949,-26357/1232,-122201/117397:-339635495/16887024
+qadd:-223119/635008,418877/230651,-13963/37538:214527625547/146465230208
+qadd:-350850/61369,36223/4210,=2:745890787/258363490
+qadd:-126959/62232,284090/70243,-7211/92126:8761507843/4371362376
+qadd:-711695/9271,-22121/1677,=1:-1398596306/15547467
+qadd:861190/3059,=1,=1:1722380/3059
+qadd:346850/883,=1,244382/179:693700/883
+qadd:-130222/837,34787/12,7523/70:9184685/3348
+qadd:59611/13,=1,284730:119222/13
+qadd:-312539/2,=1,264288/37:-312539
+qadd:25774,76897,818889/8:102671
+qadd:342195/2,=1,=1:342195
+qadd:-9963421/64053026836845890001,300354/3200175405137875241,1526802/10904004442804863547:-12646112012680203626199107/204980921107910491468445220168747365241
+qadd:1544746/18424173097448569597,=1,=1:3089492/18424173097448569597
+qadd:5502939/3595837892490654503,6889036/866793862132267183,7407877/6872500389210051386:29541770440420524774479945/3116850214433526564127456310938075049
+qadd:265311/258067740607743460,5963570/5903711115389815401,=1:3105324535591307979606911/1523557388749470699660729400565027460
+qadd:60563/46036455525940547,=1,1505826/654445038221898587:121126/46036455525940547
+qadd:-954257/72800654329359791,6813983/869337311132906228,7975903/926820989228750004:-333508793520619681655043/63288325083401809422309080476678348
+qadd:9224701/60870194897007141,=1,1821883/30701883983078087:18449402/60870194897007141
+qadd:-472292/38402815300459203,=1,516735/14385919705031017:-944584/38402815300459203
+qadd:289537/1490184116945967,532162/949630593545417,5373871/9041027854950185:1067972553205559092583/1415124427467351741680749483239
+qadd:235368/2501151346101235,-1497627/1230306186302420,3634873/991873798011092:-691243416109985255757/615436394797394918565529097740
+qadd:8661005/52512373464448,1561891/832613630894407,9705649/42723536578103:7293289423747373650203/43722517937117159639456542336
+qadd:-4730153/288796071652629,9865756/808268774461965,2287239/939894762570958:-324681130548077552707/77808282301366757649284251995
+qadd:1610793/18198109357633,-4540937/36733999418553,1841325/14250960840026:-23465598986712679592/668489338562054530332365049
+qadd:435304/45838403876965,-4386838/12812518890187,=2:-195508311263843424822/587305415569635079893842455
+qadd:8986417/9112103484695,8469481/5806694255278,4459/11976141472:129356163303090652221/52911198958077101695970210
+qadd:3544217/1265421249547,238276/343196380555,6363702/6030500114467:216840279994080201/62041141817416547622655
+qadd:4182082/59852165789,=1,21252/891696437201:8364164/59852165789
+qadd:-2035517/202890303722,1349377/178781840567,3182749/193387650969:-90137966399936945/36273101932616810690374
+qadd:-2767593/32666510356,2043425/57040767333,-2433227/14327142465:-91114064461230169/1863322816797631000548
+qadd:-1069001/77822361247,7895459/95688698401,=2:512151948229509972/7446720454217853266047
+qadd:1842385/9174964821,5302182/734041147,376177/387991044:2941159983715001/396164805934793511
+qadd:9881884/4806155721,110617/6086759637,=2:20226765065368655/9751304883906477759
+qadd:249851/7404273,698298/65948941,8016669/79629599:21647797885145/488303963224893
+qadd:3895008/857366795,9035727/613001216,2322321/896685634:10134576938814693/525566887893022720
+qadd:-3407547/17228942,84529/3672798,7629340/77644423:-2764721642047/15819605929929
+qadd:-540110/78141351,1842606/10051715,185431/9635562:138554690412056/785454589966965
+qadd:-1238471/9333511,=1,=2:-2476942/9333511
+qadd:1535971/4556655,3336373/6869142,=2:2861500402133/3477812248890
+qadd:6488119/859164,3475243/436240,3474202/209253:1454045177353/93700425840
+qadd:-1099325/87072,898870/374541,6289012/998611:-111158625395/10870677984
+qadd:-1328010/3161,1029437/61682,=2:-78660262463/194976802
+qadd:-9495731/39366,-5924095/3668,-4200041/90360:-134019132539/72197244
+qadd:8057514/1165,-3725111/9551,964934/671:72617561899/11126915
+qadd:6949552/3251,=1,2473528/7057:13899104/3251
+qadd:-1375009/860,2567011/520,-893444/341:74631239/22360
+qadd:777497/375,3031933/307,218759/18:1375666454/115125
+qadd:3512451/28,-4974729/35,-98751/8:-2336661/140
+qadd:1033229/12,=1,=1:1033229/6
+qadd:8918304,-107206/3,=2:26647706/3
+qadd:3773925/7,-2087107,1743275/6:-10835824/7
+qadd:91004807/59072744843943270902,66857083/90169331108143216589,49327406/40230329853973228555:1105024907262273351275240199/484231808118216434486399701089462490298
+qadd:23684903/30280432954739902140,=1,-97033093/13835661280927216350:23684903/15140216477369951070
+qadd:76895129/1344620316434429450,6943146/540322216560075233,-26842834/4119156804632661773:50884041715523364389289757/726528229807560676143208003430811850
+qadd:-3500080/5785508369822968503,17193686/1077431321752969609,-11569258/210771686269137723:95703118440466862159403338/6233487929911229465420510455923225327
+qadd:64737803/21853152068853546,1344114/484446976408948829,-57693827/360425471050724706:31391406050348051744010931/10586693444761065095093481009197634
+qadd:-30681157/96481087551474991,3533117/67968489447438645,-14011465/246504080723880149:-1744472925183103649335318/6557673781119831941716936724427195
+qadd:10201843/20635577001553626,=1,96155350/58811028695386393:10201843/10317788500776813
+qadd:-1930287/1991695532199008,-21005107/15139766280889058,85232497/42294449858268301:-35529935900150302716751/15076902430091964207158012827232
+qadd:48012711/4771810484651750,562029/68126124683089,-87432667/1413385161729655:5952815810837457145029/325084956041456469467279255750
+qadd:5866387/534388661369540,-74280761/494786664687655,6822321/9629582541211877:-7358437275760743013491/52881676681187080549726205740
+qadd:46722374/986410508713539,=1,21676529/310079888805331:93444748/986410508713539
+qadd:-56303815/448280769982579,=1,57376103/953365009027015:-112607630/448280769982579
+qadd:1417269/10344858882164,-51156177/69004831036706,=1:-215702512068721225557/356922619631147062206355892
+qadd:80037569/9275345057228,18450452/20021432962757,-15521502/12373106437439:1773601130997360284789/185705699269729891757657596
+qadd:6101405/2640485648371,-20543668/306400835399,14230627/825967431997:-52375784929790929233/809047008519944563485029
+qadd:27037665/2725847596723,3212701/7881968418975,3465591/735049950650:221867354952665272198/21485044672309587701018925
+qadd:4834099/48161095106,=1,72181809/308298507595:4834099/24080547553
+qadd:2911944/163084814009,-10109608/403642872445,-7803617/736030226402:-473338099824915392/65828022778751336082005
+qadd:21969634/11650585561,=1,-2791714/5600760747:43939268/11650585561
+qadd:78829897/49012267358,=1,-7604951/47216367175:78829897/24506133679
+qadd:19445492/1297091607,=1,62885411/4219108918:38890984/1297091607
+qadd:52380328/2810974779,49183495/4765727228,-4976759/496257510:387883919349243389/13396339041501582612
+qadd:8745425/897077767,15774302/979761841,20884293/386716906:22719209312471059/878922564516089047
+qadd:-57659740/421464991,=1,43283156/421488827:-115319480/421464991
+qadd:24026071/1736369,39164903/1294124,-6554987/6925344:99097438564011/2247076795756
+qadd:14218249/33339177,82993699/83617031,12153/57562:3955829388244442/2787722996723487
+qadd:87835945/5064396,2236259/32882,73177891/4440892:7106761339027/83263734636
+qadd:64270453/747130,52462151/4978177,54483440/786411:359145737780811/3719345382010
+qadd:77515742/83997,-78232069/771459,=1:17742985902595/21600080541
+qadd:16151167/91103,-68440793/300034,72464239/286942:-1389262325001/27333997502
+qadd:-47905567/27277,-20089455/87101,-96050621/89657:-4720602855302/2375853977
+qadd:-2982404/49995,=1,88907825/1729:-5964808/49995
+qadd:-98481971/1315,80677685/7857,20839038/961:-667681690372/10331955
+qadd:-6211399/6793,57937621/6057,-3438577/359:355947815710/41145201
+qadd:5865679/34,1860899/8,=2:55097999/136
+qadd:23345429/165,50130524/773,=2:26317553077/127545
+qadd:8189395/4,-30602711/48,=2:67670029/48
+qadd:31167001/15,26011293/89,=2:3164032484/1335
+qadd:87715029/8,57210911/3,8398329/2:720832375/24
+qadd:89586337/5,-20657924/5,4144685/2:68928413/5
+qadd:45374053/1934947640595205378,-878342702/35405417199994412197,25786213/6017346122507972907:-93059862349259521226926915/68507628475418090621542740789603195466
+qadd:866238635/23517962979026052651,140081155/7113881091341386771,591317773/7502259793356123703:9456742063465083425960989490/167303992143360186992226567080400879921
+qadd:187264688/2749316430368891609,74030301/204048834975005675,777410733/9632694272612564641:241743864302812512377748709/560994814594413644669245568234881075
+qadd:313283613/6685249134338162957,-295002604/168462092705930067,83793911/3114652596872305375:-1919389489962049170976247957/1126211059431114336488157420891928119
+qadd:622725611/642973530889486819,466130322/105261688931011189,-110468698/89768733490717633:365258608545449316873087197/67680479799363075510639822957017791
+qadd:172273567/735309213392006870,178508035/382275018951483603,=2:197114483889767511301022351/281090343484629926962696208068352610
+qadd:17553367/48463183083977111,292467608/23785726423353699,43459439/32702598236409962:14591430817907573630275021/1152732014440382376433523573183589
+qadd:72973408/18357258425372587,1146729/70850265929795,=2:26220985959472511209283/1300616641179617610304859529665
+qadd:201183991/7736480258952282,409452756/699726655055405,=1:3308496964840732241410547/5413421453498853777223961184210
+qadd:588622837/3660268385543296,96365803/346258205753288,877283956/8025277960045801:69567523696677926868093/158424745469213234294102294656
+qadd:928254321/705783785204222,=1,489283333/807148845748726:928254321/352891892602111
+qadd:152397935/976211791425421,-226290007/366059549380471,533087429/48259007602879:-165120253702526748340562/357351648469091954890550353291
+qadd:459988615/27514620962218,604652543/83262415165680,99455011/26970436598135:27468274284051179676787/1145466896841258418745139120
+qadd:144022423/2685255995458,33922842/6738872265491,=1:1061640226826987556329/18095597153535342866139878
+qadd:501792430/5780638369569,90233731/2388030172166,=1:1719904030652463235319/13804338840911244605216454
+qadd:464061973/6928147630370,-406560643/292003731780,-29850340/7482218860353:-268120432750896392597/202304496239080406215860
+qadd:29675674/18924786675,93377112/3121810099,=1:1859783743715414326/59079590163435630825
+qadd:125587910/783335021243,14748484/85895896271,-115687727/148918581825:22340490117693729222/67285263730130309484853
+qadd:-888517823/89522905525,=1,28721/1399760:-1777035646/89522905525
+qadd:994205969/53771940024,-568804915/41456863842,391201703/96086803818:1771819618833375823/371535999349193035368
+qadd:-84977861/360134264,-218217210/484944491,111762569/4111268304:-119797039864397191/174645127347139624
+qadd:-701405341/632889150,630062610/2192126171,-791346445/5983383139:-1138809214795597811/1387372869056944650
+qadd:-234546662/963657213,=1,=2:-469093324/963657213
+qadd:-452856/2789081,8372197/60736948,-242353549/286862486:-4154355742531/169400267664788
+qadd:-187052767/74234724,166350269/20205255,=2:952168605650019/166659058697180
+qadd:-274903712/23604721,38495599/2095174,-791027856/11974547:332706764236991/49455997716454
+qadd:-404894266/6164955,157832653/6403878,463040423/4614886:-59994899225479/1462208136870
+qadd:-540899545/680681,-21287447/2541780,2338951/144008:-1389337606201507/1730141352180
+qadd:78913331/78528,-590670400/833879,-8890225/542326:19420004369749/65482850112
+qadd:177364406/602109,=1,99001438/992219:354728812/602109
+qadd:518975591/39351,286741895/4956,-6511822/1385:1539513704349/21669284
+qadd:568231946/63665,697042925/7473,688346609/54619:48623635152583/475768545
+qadd:294003077/2932,799278104/9869,102543194/2815:5244999767841/28935908
+qadd:164683586/4895,285199167/5854,=1:2360107634909/28655330
+qadd:384813481/51,67752725/82,334380330/11:35010094417/4182
+qadd:-371677859/928,302076121/569,=2:68841938517/528032
+qadd:63675311/26,781198705/94,76504922/27:6574161391/611
+qadd:305503526/41,-254218383/23,-132508301/80:-3396372605/943
+qadd:642014667/5,421175863/7,-384744890/3:6599981984/35
+qadd:-20761287/2,278595273/5,413571671/8:453384111/10
+qadd:3167550432/27903875703136810681,-4353020263/68180687168471384344,6171494422/98306365101160490945:94499628742560480702887407505/1902505420103480375489882725653115378264
+qadd:-3183422884/37568196826955204211,9427961279/82738779554479999510,3089033603/9902435878598192629:90798980778421373608402959029/3108346755524761642315503554707229936610
+qadd:-5214220143/7727885703296351326,9213475679/2261661519763659362,-7239565223/2154991508915553068:14851971481103269456702367897/4369465431069270378226759286135253503
+qadd:519540517/134490908117547849,304460068/27850900631653987,987127340/519856570607360343:55416782343935509070885011/3745692917842731715413863484123963
+qadd:-3438305188/54619481101719075,-8594462002/390499828982107557,3593936628/135385731106207271:-604027547599991619791064622/7109632676437584813745363082849925
+qadd:-3992299182/540033726318821255,1110234925/68696689237726709,7386509615/931861031447596258:325306567387162498253078837/37098529074815619108104756710399795
+qadd:7394803302/93918095118354223,709650140/69209592401912969,-1612636291/26972979365753121:578440311773013525199364858/6500033082305387937149168159618087
+qadd:-3798450956/49564671078478937,8201952752/84323457683098803,=2:86228571904512932003378956/4179464444262829754322889925412411
+qadd:-9219410394/2493025593271873,=1,6505447590/7492751055706253:-18438820788/2493025593271873
+qadd:4539114361/8367641580192862,-1348803394/4603788574100933,=1:9610819468569602203625185/38522852699063773959572394140246
+qadd:2699722113/384212226724151,-647713391/102207743232507,1954070238/94962673621469:27073100289464582521250/39269464615811789500145176557
+qadd:168180211/23676230652675,-2799553761/104480802434474,2701278780/97731939901727:-48711277171120629966661/2473711577215174081940317950
+qadd:7857451474/65235454327413,2128537376/31498366243961,2221032207/18007954017209:386352987048442714936802/2054810232496045180328002893
+qadd:857071657/98686012424000,2073820807/52588250038741,=2:249729004524185769231837/5189724696679612807318184000
+qadd:2786190922/1961053446085,-4894735831/5462640499350,1754691331/2787361615253:1124224160076048145813/2142505995194760540508950
+qadd:3344367971/2002173783671,2783409797/7740436696732,=2:31459738694869961195559/15497699428361765200663172
+qadd:1886117201/422471806113,-7056920135/27481905959,-158290687/733655902149:-2929515699483111484496/11610330445926347327367
+qadd:5224375095/163575252188,=1,2792946472/109584621039:5224375095/81787626094
+qadd:8503914901/50951147588,5076419507/35985026241,-4565632313/3078383356:564663000383475116257/1833478382963243856708
+qadd:724347429/20249465581,3428823/41714000,2510643935/61823728396:99647261975147163/844686207245834000
+qadd:5343861871/442016043,=1,-5208128746/2708679643:10687723742/442016043
+qadd:9071089245/73007971,5216095151/4614034969,1604438701/1558498304:42235139506867257026/336861331209737899
+qadd:783186604/763828989,49730609/83655528,4913761943/765103417:1045490602777487/645439569459608
+qadd:8924999897/754869543,=1,-9645157610/502961879:17849999794/754869543
+qadd:-7684261227/59813341,=1,-2457478286/10588905:-15368522454/59813341
+qadd:355855462/12114485,2701511099/2628520,=2:6732557777029051/6368633222440
+qadd:3297355561/5434460,=1,=2:3297355561/2717230
+qadd:-992155139/1824719,-5941097341/619600,-1877283138/586285:-11455572523096579/1130595892400
+qadd:7275838099/179284,=1,6914524937/272956:7275838099/89642
+qadd:6041862082/922449,-5732991383/202771,9340070011/437822:-4063277752027745/187045906179
+qadd:-1436667881/18842,1512607713/43240,8383142315/71207:-16810482323047/407364040
+qadd:-118807714/9521,-9807321655/32654,1426332047/6126:-97255056570211/310898734
+qadd:3925687044/7783,=1,-3015747667/6013:7851374088/7783
+qadd:-2562020810/4693,=1,=1:-5124041620/4693
+qadd:3975212101/482,1639405105/322,-1189434281/368:517552889283/38801
+qadd:8766298199/223,-3219733643/528,1656354148/249:3910604846683/117744
+qadd:-1513168265/81,3248422098/35,2306426618/37:210161300663/2835
+qadd:2780622344/31,-2851908379/85,7370056704/83:147943739491/2635
+qadd:-1219272487/5,3254817416/3,6042779700:12616269619/15
+qadd:668084801/8,3276722729/2,8177104324:13774975717/8
+qadd:-28066364019/27142028496153875629,-83994986165/97945022620202828816,74560676951/94359392114426445353:-5028754966732282316332384444289/2658426595013981116986784879127641325264
+qadd:-3000528509/8658875177266760687,=1,3036743401/4590071950395407738:-6001057018/8658875177266760687
+qadd:-19793548593/942761710813665874,86192869057/7249541417045877905,-119695723/4978025286900417400:-62234813623148059219131076847/6834590068948699455368850293669113970
+qadd:92023085779/187292712323684346,26983243077/439795491723853676,-11509377282/6925087095539221979:22762551521651139809665123123/41185245256344513090796650857877948
+qadd:-39019146867/246528590445069470,28418521119/84449846740292087,98982289401/711557146503937079:3710816981145410193486195501/20819301680186352926550356806283890
+qadd:-42497869768/371989720063193939,-8478338149/81277488191100360,=2:-6607974742863148859707195391/30234390079646974039120816492718040
+qadd:88261843372/63085394341751879,-44784460532/26919006654835821,-41422100021/1786615630050841:-449324203944898245335311216/1698196150108560878202120263257659
+qadd:-24150972023/9515359277743228,42712236280/42853813844399797,35309213749/14159032046882283:-628538985474890673067967491/407769435150990797236812341324716
+qadd:5724825303/2203041349747678,27488395054/5646217321045969,59293151082/7082646499343447:92881678727922393840538219/12438850227925830110937189009982
+qadd:14619758075/4936846021982826,-16036864556/2323794990231661,39713546516/8749338469186367:-45198210415282107094702681/11472218053428795611140303453986
+qadd:14605450543/139939857109890,10799789228/278879311148721,-67807143038/835875361732289:1861492982610600772490141/13008776984352189991676650230
+qadd:65048626819/249759029072891,=1,16664913404/344763311872831:130097253638/249759029072891
+qadd:-16329783973/23223035673496,26102319760/44353999342379,7133401053/27271403075635:-118116124652153584810807/1030034508990285641359886984
+qadd:51518424902/90611385027845,21848929639/25416816549026,2259015995/982451260279:3289196130594630243043407/2303052950505897517817628970
+qadd:9823437047/2983803001614,=1,-86833764787/3363958851767:9823437047/1491901500807
+qadd:-98079469262/7501490848143,12931722520/6785167928089,-18159475732/2680006300059:-568478471106008568619958/50898875115673034643188727
+qadd:203196757/744982367287,10110532199/185236774284,56534913639/177096148301:7569807723954107571101/137998130614702004447508
+qadd:18053774608/289402099045,573966551/105073103957,=1:121357250637861762803/1788728049313487965945
+qadd:-87887709416/27708207675,6077181331/13094753558,5647506134/79889599187:-982480093181655186703/362832151038009157650
+qadd:84536683600/44724539921,14048255833/19894148141,62917100482/62400348937:2310087085710674796793/889756622726442436861
+qadd:-30706897551/6897893812,-35459830323/6252261713,31231362485/321173596:-436585704042722426139/43127437381107219956
+qadd:855281852/92743035,59782619892/1409591731,=1:6750019835289018032/130729815243843585
+qadd:-92900956537/439171163,11759229380/445905849,-96227598684/119216995:-36260765454744715973/195828990293832387
+qadd:82493426014/179464353,31442888876/890956139,-20219675248/552201081:79140902042897837174/159894867037013067
+qadd:23749016299/14965184,-98465907028/12423329,85060246231/4151941:-1178518573492073781/185917404377536
+qadd:9492555875/3149752,=1,10314585429/20597380:9492555875/1574876
+qadd:10417790685/234262,=1,28830989839/9136194:10417790685/117131
+qadd:21932976869/2808786,-13004555792/3211065,28289083248/7503535:11300400041688991/3006398139030
+qadd:-66836200744/46967,88530220745/490268,64385021287/164152:-28609651588628977/23026417156
+qadd:-77417153575/956591,18725852581/31923,43130968451/307644:15441594252736646/30537254493
+qadd:97474118123/10596,-23947620716/12055,49384521647/13258:921301504866029/127734780
+qadd:18734763309/24325,21131785949/50033,10659403415/5989:1451387105848622/1217052725
+qadd:-1439500917/9212,-33183518225/4942,-6451501592/4165:-22342898815751/3251836
+qadd:10232528693/1811,2932687043/798,34761925483/737:13476654131887/1445178
+qadd:14228896673/466,=1,-17513625375/892:14228896673/233
+qadd:5540039685/212,-15534067884/379,=2:-1193547350793/80348
+qadd:63449652064/71,828572732/73,=1:4690653264644/5183
+qadd:23839394581/78,18502903317/17,20062169746:1848496166603/1326
+qadd:98566503851/9,36994496837/4,27511550439/2:727216486937/36
+qadd:1606910501/2,-3681246287,65435551585:-5755582073/2
+qadd:750601900272/68617053518286344873,392311613561/52425272355238879732,-189516578487/12053234670522747307:66269776035679860138095215709857/3597267718910163826199560785077521814036
+qadd:728582633219/15054433453572577856,62100633056/55101558283029999661,34066971933/506753729147298419:41080928276086479104683504546695/829522742360026001203093417822576106816
+qadd:-579689114306/6008640125920920437,29545305921/385791954401533340,=2:-46112285663876043987863954563/2318085017474507283487811656942869580
+qadd:85157683276/9984413431548073099,-194463047535/4351994325185158469,110987855747/722945613070544238:-1570993709385158332729520696521/43452110594399688796381640689910925431
+qadd:-333254398312/3739752515251807,-222688186129/229969682138676072,343987180862/318762259733023233:-77471206755319178027151175567/860029697209772394782614685662104
+qadd:228232045087/269100475905208142,29685295504/987729914318359197,296390204576/285221182007931887:233419945485999538709461908707/265798590008880921671259700204981974
+qadd:186728741043/8484893283352760,907466508351/17668153885239362,242986408459/13685130290283387:5499454306559858179393716663/74956200115055216722781241669560
+qadd:167007555005/37196512845456713,32846177456/14691839559620265,643735617275/76387090563153388:525058780720595868923519779/78069314128972040645085253584135
+qadd:-406143410794/7443920130626979,569165220942/6593136079301147,=2:1559061670746557697064613500/49078778384672842351253263844913
+qadd:288899664973/5110051533246567,475174065413/4997103188916189,=1:1290608466212034033663878356/8511818270770826983316411657721
+qadd:285552853103/243786904599060,51739173381/25270326775286,-567539816837/84226741155405:9914673417298061239217159/3080287371376859806273415580
+qadd:750126891973/878577129895100,663130172971/179676426138219,-920208514541/740079136878614:717391123215580915464958187/157859598786325375229570826900
+qadd:318766376313/3618419265449,=1,34811188877/1841753199622:637532752626/3618419265449
+qadd:254236024269/14780919746920,-844586040520/76436593404511,=1:6949177131533900664879059/1129803152840031671306356120
+qadd:706710361987/1301067543579,=1,84203887945/2012418539922:1413420723974/1301067543579
+qadd:195640325029/3728726838817,603560861264/8341120578151,829455171841/8240881232572:3882373123270122662726067/31101760165560405628887367
+qadd:-70222263648/919970997005,-140598797839/277541553572,762482298447/448122269015:-148836412373857769622851/255330179749949459051860
+qadd:183632938397/738585229043,230841150433/35550437411,546670119297/439718525656:177024095248187490795786/26257027957782270927673
+qadd:-284412871457/19847149579,=1,71954251519/4976484407:-568825742914/19847149579
+qadd:80467423648/24677301847,35760826979/13928733407,-87061643423/13617181915:2003290013600243538949/343723558630931702729
+qadd:-271527910651/69743572,727102134527/552678311,235157903923/742370011:-99356886977216080017/38545759576066892
+qadd:594385696266/5016006577,171921164870/1559514399,=2:1789310745599888884124/7822534482310202223
+qadd:-274331202943/376136849,249566712436/202764467,=2:38246616684759927783/76267187706544483
+qadd:-177762749877/158322013,679117341835/140151101,=2:82605579510477149278/22189004434486313
+qadd:438527654989/19442480,=1,473198805899/30758263:438527654989/9721240
+qadd:205749903939/22577983,488255989076/24418833,755328978737/79282170:16048007965058596895/551327996353839
+qadd:-276465269559/4305250,=1,-6551354097/249518:-276465269559/2152625
+qadd:-77677567229/1108443,=1,403947412538/8640625:-155355134458/1108443
+qadd:-26363673381/34468,-404935701883/545635,=2:-28342266697745179/18806947180
+qadd:161513177189/516563,=1,=1:323026354378/516563
+qadd:63971909733/10957,29722925483/27477,-254713864821/72353:2083430258250872/301065489
+qadd:431338979813/33787,-14639411201/2198,=2:453461291380787/74263826
+qadd:604394639929/9703,-130898313877/529,19351109647/68:-950381575026090/5132887
+qadd:-436971275441/1805,-45135172974/143,150879980149/913:-143955879606133/258115
+qadd:133419066709/724,688077199855/411,308833205069/124:553003129112419/297564
+qadd:-752571481496/159,474015196916/845,-32200650919/727:-560554485554476/134355
+qadd:764385897608/49,-511836952661/77,814778276083/89:4825386205061/539
+qadd:320831977021/60,65509179103/10,=1:713887051639/60
+qadd:619010459321/7,670048524077/7,106364585881/3:1289058983398/7
+qadd:-966054954552/7,26919072829/6,=2:-5607896217509/42
+qadd:8601789733890/36226606798446835733,-9517603014260/49701591537140834451,5475796113274/19588834568871216561:82732177780862722364959957691810/1800520013873013869891754119384144237583
+qadd:2152113882697/44696374362534467140,556748656281/15909675605329183742,=2:29562040053204167968772348309257/355552408421137678797712040098560618940
+qadd:405932999909/48559005322063228,3790369457927/3702874233536819343,2557162633138/8338270525184407851:1687175416585403236677748248143/179807889613245206691727609459419204
+qadd:-6087806259569/972879120187377883,=1,7399937003904/6443577898545254653:-12175612519138/972879120187377883
+qadd:9620990949187/730309117665819684,7567489620737/569889108783714498,1735576396811/51095649586994799:1834917437585674959063670400039/69365868700532477556648779567429772
+qadd:8651924819461/863956468553652350,2187645516348/235829108485821557,=2:3930406211611089677582520538577/203746083749566560575560722713708950
+qadd:-4336348697751/46994132323169285,-8481317196881/25836479901410330,-4173835305205/32784713158384997:-102121625719989497206007233583/242832591050356154167841367542810
+qadd:9803783744995/7173215879645536,1461730234625/44252775572438103,-9376571794387/92339718365720632:444329948358750525431287428485/317434712454603074916166940258208
+qadd:1451028299837/7491788861639837,3708310594713/806013004930241,-8365440578715/8478738861000634:28951427689162292314899052498/6038479252673234548881051610717
+qadd:106500181351/1880557932860660,1907360387663/8006540878394810,-2341315210208/8571856456239177:443959976338708048693922589/1505676396363851684553219717460
+qadd:4027452706139/119900758316566,-4327345628086/101821781711479,-7365940733989/364587320094438:-108769612007597347818603095/12208508840350183550358061114
+qadd:6083358310044/255539217667673,=1,390223928059/413168482858447:12166716620088/255539217667673
+qadd:91210522789/5821394937509,=1,-2769366574049/39367880017274:182421045578/5821394937509
+qadd:1597250023359/36013018587610,665933164918/3231381509477,8810376679036/2323736290015:29143587637791868491339223/116371802364454460369779970
+qadd:68049078655/7615630087369,4706208009519/4980776034536,1596034611713/3058679589429:36179676534846948814094591/37931747827058819041375784
+qadd:1937588720533/7799363656349,=1,=1:3875177441066/7799363656349
+qadd:977734823551/117979135196,-1952291322312/890529662717,=2:640372220786512478954915/105063919473737223687532
+qadd:-9025156691504/937177282499,-361352397466/257871708085,-3807710093346/955531800671:-2665983829654588301357374/241671506616475707304415
+qadd:5896871870580/77613420173,-1845035969569/26828471132,8388653136749/65162440481:15004504808501131381123/2082249402567116945836
+qadd:231439434868/1670462139,2207560874293/16523176383,-2335974950174/54347294915:2503920488116666405057/9200446854606821079
+qadd:1929296372726/4735837665,-9028612240726/8555200715,-6233988999387/5091294091:-1050100968196714241828/1620641671109277219
+qadd:-269105387231/230611014,3594113298975/2873349794,-1154532309875/4520020294:13902050835756457559/165656527392757779
+qadd:2346217941151/799817318,-4884282294533/960803076,7966051335112/524910443:-826140075172001171009/384233469686235084
+qadd:4064314284160/311969293,199296652936/441645007,5304117147258/554326453:1857158546391753483368/137779680590770051
+qadd:815037963837/2968034,1418934409295/75864896,-339052747818/1710509:33022107966551620991/112584795367232
+qadd:7244018124286/72201723,6446019776692/10593765,7229442366932/73382069:180718386677888105702/254962695352365
+qadd:922615490114/3707093,59605234097/120775,-4190680399923/6307528:332391031902868371/447724157075
+qadd:-1218581321862/9688639,8211974626650/9377609,7971851835717/1568942:68135478463646641392/90856268284151
+qadd:-7077925805906/637155,=1,-2581658464835/734183:-14155851611812/637155
+qadd:217345331728/72451,-7227574835869/612249,3818947938173/281665:-390575562428408647/44358052299
+qadd:-3974762894203/14013,-1180890047119/1669,166220351784/5539:-23181691500703354/23387697
+qadd:-143792410986/14239,-1333280413059/7621,664497465190/6971:-20080421765671407/108515419
+qadd:5469270207451/9406,=1,=1:5469270207451/4703
+qadd:-393435064451/9103,4634513061154/615,1392205495718/1811:41946009831047497/5598345
+qadd:9578810210563/843,-4536594375665/136,4023125278157/374:-2521630870049027/114648
+qadd:993337628557/102,9593218874931/536,-4264424459806/127:755468647074757/27336
+qadd:547147143651/2,3730254823821/5,=1:10196245365897/10
+qadd:4901257128118/35,=1,5319057215527/23:9802514256236/35
+qadd:-6031845023279/9,=1,-1602500231005/7:-12063690046558/9
+qadd:-3297542082233/2,9743508972017/4,284781600324:3148424807551/4
+qadd:40957392574416/70276993727723336737,-10014910049617/17689665613055704872,-2779499153404/26725645738443989647:20704808283422464958622124875023/1243176519334238965594276156105347482664
+qadd:45844224448349/22079296648506779147,70206864303623/53740308116805165169,=2:4013800930951401093187151667305562/1186548204893097943291939751481539930843
+qadd:27961919364631/8718044862129208525,=1,-8519896737528/6252014363663191811:55923838729262/8718044862129208525
+qadd:-2067336322439/584317644440385925,2723713099539/473511695651648882,73786916799403/8182802497184968644:612605694933716051550733725377/276681238618144405533343878674785850
+qadd:32025894755248/66303294333949585,80751708273853/638681646107513563,-64873077706462/49077538736861797:25808455461998285269484001129629/42346697167557898041297541745721355
+qadd:19660637614444/956621220581308491,9683558119459/148734533812110639,10732473730492/212642830728841369:4062570985946694749593020498695/47427537092644392555022031027378583
+qadd:26463069132061/34590442491713868,1778591564927/1271271116297649,5452080117585/10453906972591852:31721334893010603543531044075/14657943479890240114084276365444
+qadd:26232104044847/79502877559485212,3370125338191/2578727156176402,63787406469289/92688221566095237:23970007227600682942443887999/14644016382629427726576098740516
+qadd:98696102763974/908742099728443,-35107937305612/133127339221267,-19866428041535/3060805116764176:-18764911111759790278837687058/120978417775194877383790397281
+qadd:-37908147551011/7228589226446608,-65775689566867/9504572716351133,=2:-835766185905903522330926482599/68704651939394172248397204806864
+qadd:-18185796452231/303760253880903,=1,18122968385557/178311473629270:-36371592904462/303760253880903
+qadd:14892304197019/46622881145226,-5611369712763/826515187978603,26394608317645/273451712601507:12047097379653626883559665019/38534519373850532904623599278
+qadd:-54139396579777/32007668492293,=1,1733479907912/25396380277249:-108278793159554/32007668492293
+qadd:-63788344296331/37589271154908,50915695251657/90027727110574,49591638223605/35445794413654:-174037989922283184534946429/153821665719064918309036236
+qadd:12071763393847/4649104873226,10020556788045/927371358623,=1:57781627015265173305975851/4311446702664405796927798
+qadd:18238074461897/2396590395463,68187595826700/5705685211381,-78696625586088/9509272732285:267478448989293363689511857/13674190377130981538364403
+qadd:-13345085506196/75622603113,-97672417230952/129165419515,-753859024931/4781291931:-9109966011214978026968516/9767825255906989950195
+qadd:3709838273470/57134914859,-5914995558694/134539418847,35401578919795/686522759833:161166717691666830854944/7686898241002684947573
+qadd:50811177302193/40048826548,32735197100597/82993263421,36780634570867/8850752755:5527991653268441530231409/3323782811400102100708
+qadd:-6542615556879/27016465451,76463178253406/72959925957,45891539817416/380667753:1588416066961789560067903/1971119318924808611607
+qadd:-21080435888478/3413079223,=1,81032696758521/2284760788:-42160871776956/3413079223
+qadd:96607459901/40160793,85203204881021/833797549,-4433713970891/1573415279:3502379337443843592302/33485970769296357
+qadd:16594106768116/498044839,23534220395438/517318473,=2:20305534981917169251350/257647795597010847
+qadd:25304409260441/118009964,72369014966310/788591957,71991883509399/461244341:28495118470309795185877/93061708456259548
+qadd:24936005724654/48277589,=1,=1:49872011449308/48277589
+qadd:24088512125936/40097553,-37235147981069/77180983,-72573429878023/38036452:366136725253403050931/3094768556434599
+qadd:32272280755220/7617329,65546010555974/1144891,-33329793981457/2504062:536233770828451454466/8721011416139
+qadd:95637195200652/7212125,33652777588976/3406657,98881012460311/8766053:568511159059561074364/24569236116125
+qadd:92571834195973/96535,59689565610747/775016,98663660317905/721679:77506784867459672213/74816169560
+qadd:78835501537635/372197,46671694263162/529757,859020873535/3702:59134723377739011609/197173966129
+qadd:20589023961027/22664,-69820834854036/30449,-24367466631311/33338:-955504210542560781/690096136
+qadd:-91531024180004/69325,1402659330981/806,21471287770931/22199:23465352631174601/55875950
+qadd:48834248870857/7428,16091745523789/5821,=2:403793648427963289/43238388
+qadd:89161018973989/1000,48863562276307/5136,=2:63349319465839313/642000
+qadd:67440349641709/582,-25644394065531/125,72123784494178/345:-6494993640925417/72750
+qadd:98894870521648/469,29922116846031,14386819758147/956:14132367671310187/469
+qadd:-51033784779973/2,=1,-595583264213/3:-51033784779973
+qadd:16012808775283/25,6902989657994/65,=2:242681462368649/325
+qadd:68123975569655/6,14855844433571/3,3396209893164:32611888145599/2
+qadd:31826754876396,-5624708171537,22269353475089/2:26202046704859
+qadd:989539922242669/82345437022131993998,-129844086283131/1228275122105070002,264019311827057/25912304890942474571:-2369160190225845180087828586083100/25285712928288631715150750102408461999
+qadd:458886340685990/45233073912526242751,-178745004976918/2119200954833746507,13324270929603/4608288006661132729:-7112713650273889105018361873484488/95857973425491043563396362893480320757
+qadd:412133102761216/1699197444312646113,134603450929112/552586191322068273,374607145779807/1505793782999860840:152152300462325569979931157947208/312984348018972438363137729558024283
+qadd:996107656472793/1538223134855538644,744500995880956/9784839986634291135,-657762555721801/3044920577968213070:10891962683834633525215962650253719/15051267238300426155470196651539120940
+qadd:735500231252758/172429147160677843,157779442625545/116184147677115296,167157993204247/685504231666635064:112659242215832711691135511285803/20033533497555240149484858223586528
+qadd:-809798210635595/265681969632351751,315376974249563/452100583295838976,-147441203225015/637765515904619836:-282320267684963796331611659915907/120114973441973604125868871487646976
+qadd:197530115746410/16154772056586701,805221852820256/61863667133511779,=2:25228112816673602730686944978846/999393441126437183906946118251079
+qadd:411518791826609/66555460731929013,73839516309311/29351284060524212,-941248859041399/40678192937974455:16993027983335510295184953297151/1953488233721913143499638751762756
+qadd:-44838693896353/4828879954536720,-214608302698603/905841390888158,945153758378794/1752566248144451:-538467237911556730436461644967/2187099667224743806751112080880
+qadd:159386221465363/4011294024192533,=1,-762687138435905/9496408082934519:318772442930726/4011294024192533
+qadd:282181219877794/834796594900371,-521732855952853/336927589199157,-509894079886271/627419469371216:-37829574829598341107104487645/31251778243494142409565798583
+qadd:-168247676776493/775628684714855,673499386955615/114978736437813,502043901819392/813501396039933:503040538376286093357421431016/89180806113436869664344812115
+qadd:-201804504690605/26153756292047,85735155596543/849483132120,546053722691518/68002507655451:2070866842412214685073860921/22217174811671243006249640
+qadd:-578160618834941/32832087076522,-257251067168429/84222664665342,-767269979542346/64606844680255:-14285079340160980125721709690/691301465027305293568825131
+qadd:682356166873497/9733351318990,138039263801749/4525351638292,=1:2215743124028395589742030317/22023418668731497795382540
+qadd:58719414801037/9289988230905,841010929365368/3284665753905,-902973183034592/8703989774549:11860526350745264583518663/45206675846272813400643
+qadd:446558621707731/443226736633,57828945916797/134385109829,-908538462064135/423200304851:85642164404908478623312500/59563073681574962665757
+qadd:-85597540319717/430995215447,152252722498749/811556745487,26984142839919/361403086885:-3847066307821160533891376/349777074368635709937689
+qadd:518235731671330/34633881143,=1,-927979812597974/20035419799:1036471463342660/34633881143
+qadd:23532022732187/25812132498,=1,=1:23532022732187/12906066249
+qadd:384857284291123/2633874476,313185874888348/8412878237,14688795975121/1210141392:4062649753475859805995799/22158465258130178812
+qadd:350680888140817/7696173335,-273757008800698/308695203,41351671290449/282932970:-1998627883448442480586979/2375771789971012005
+qadd:177593161287595/783161477,675923932791229/349011889,38454414011850/16453799:591339710238892839502188/273332666479800053
+qadd:-214254215144366/468801353,642094736898653/672467862,622095989308793/572560927:156935807429647724912017/315253843554617286
+qadd:396292476888376/40820787,78144967762423/8506238,572072869094153/34215214:6560897210173761576389/347231329569306
+qadd:-990761108038976/66972235,199957304336881/31214504,391113668586297/44776622:-17534528993910935008869/2090505097296440
+qadd:129684204888411/435077,76593779471978/829233,794637299697182/2210281:140862614063561491069/360780205941
+qadd:-316924088772521/8106207,321543746152208/2861707,=1:1699556282556306801709/23197589315349
+qadd:-273436429936583/946788,=1,209148812266786/332615:-273436429936583/473394
+qadd:-11329905072416/21011,546335249793749/483215,211883734808434/150249:6004269853848962799/10152830365
+qadd:516486908449729/1259,=1,278592054186065/36029:1032973816899458/1259
+qadd:675867112050751/79570,32097018416251/18680,522495180002645/78606:303583148169782415/29727352
+qadd:329176312670383/3138,479733224022673/9258,713130808296677/5238:379409763307129474/2420967
+qadd:-590917948306039/2612,816884550900490/4193,586769063997713/7174:-344016510295141647/10952116
+qadd:30172372558544/23,306945914193323/126,=1:10861474968822973/2898
+qadd:508708694453393/132,994695576147517/309,369736266501912/373:96163600879190227/13596
+qadd:140754426286115/21,=1,936716007464871/86:281508852572230/21
+qadd:851135198263564/93,-329349905996065/59,=1:19587435439916231/5487
+qadd:869963899450784/9,129438400763333/3,509437343941782:1258279101740783/9
+qadd:154547978608621/5,-497290343697757,216897795092209/9:-2331903739880164/5
+qadd:9731985466163977/5512338322751860171,556192589204029/57909174483790815689,-2632702504578039/18742877028358340228:566637166158105995162688554656064112/319214961745924282983965333270161022819
+qadd:649650388871168/3992465323969551173,=1,3565435999230529/84697466077371826772:1299300777742336/3992465323969551173
+qadd:605861655156859/2232205883730936795,690635835332709/557617629319401191,126519874372049/3918127150315881558:1879480514989199709022928131546724/1244717353038863867397627790868722845
+qadd:-942787630105114/2000750159815160879,6984110317895009/2298603201956044128,-1258842818920025/4276881172498189494:11806365169370987723241751703682319/4598930723665195806685719802743268512
+qadd:7833433836634319/173628534804912798,-279606913169869/51244112549651791,=2:352869626519730853604034544331867/8897440179374084695171531019521218
+qadd:7799997395732343/425865243834023704,9146433465939454/231677503759473387,1415892823490823/620146895568068431:5702232044157642641957254148473357/98663396629386077325737960315165448
+qadd:1103157747790413/55167635654497700,-8423319298239707/88661359798471577,=2:-366887144055470035037200946582599/4891237593994409584782505661872900
+qadd:-500322660362609/4271749116788519,263022279423891/3828812275602968,=2:-792076353933982410819593516083/16355725456656018147722464724392
+qadd:256405572619155/2602216073605499,2786963243737596/3122526924111005,7018660290695751/8853212585895845:8052913853397103348918187941179/8125489752187595377205654416495
+qadd:-4368184742676481/4675799278313048,9534128992433354/6253368044316277,=2:17263806580640358427509035221755/29239493788639924359785127882296
+qadd:2104015488715397/853633108483362,2250989455424197/214830172967862,1713791260754447/4504214438916:197793761447068078680364356794/15282179028881197103432309337
+qadd:2995889241927464/698314621089197,1530024756319507/462119541131685,6069020753402648/565006088361631:2452897619727218797598520162719/322704832263286198576707906945
+qadd:5394634397912672/14716326174237,-5034418169062420/75667401230663,-5368809838944386/37114054397355:334109825606166663739353787996/1113546157267298892365029131
+qadd:1863023478221507/7872199669441,183894543875548/37986075021761,94003419602892/2702656613089:72216604178533377861245942495/299033967229667971081705601
+qadd:-8112425603423209/3805513596434,-3425559927153486/4012067294371,9145612321513257/132453047192:-45583612319694234728476725463/15267976638537011973873014
+qadd:213689004449671/1644968610003,=1,1668412523740720/2790599079591:427378008899342/1644968610003
+qadd:6951530900384110/628329527679,=1,-5187804123446287/513799284482:13903061800768220/628329527679
+qadd:134541450167501/70194339817,=1,=1:269082900335002/70194339817
+qadd:1098519078141892/19462539993,1327840931140871/19058669129,=1:46779468868871976696405971/370930110136516976097
+qadd:393599031927369/19486752872,1205956039337142/5742832021,5417998674508339/69422174015:25760540437045892884254573/111909148378635314312
+qadd:-2774295194854405/200465239,-6897371711869624/4786302327,71942449286325/102497912:-14661298815608340389700571/959487239908311153
+qadd:-2018443788406565/3597931718,-2000020310248678/3595186621,784424627043279/3431202205:-14452618614207756440335669/12935235975825144878
+qadd:-1405824660836226/850566097,-4116287804839619/468886657,4256120357736763/794325993:-4160347277838789277433525/398819093779867729
+qadd:-2568463849296119/68653552,170163282864808/124349217,4853614637538325/536394242:-307704154764128593790807/8537015435468784
+qadd:5570716669286833/56389954,5139391070061720/86846191,321475980040349/37564864:773605549896559300463983/4897252715565214
+qadd:3347504025095300/41242589,8372336127620525/73791909,=1:592315530278270954466925/3043369374412401
+qadd:4075983457906123/7454814,1012312766726638/2012887,=1:15751097500406757342433/15005698188018
+qadd:615527827347805/803633,=1,-6945777364445267/2690675:1231055654695610/803633
+qadd:4703769450007771/437089,-8646742616442323/773872,7633024022889843/470014:-139280611661744758435/338250938608
+qadd:-1157040382968040/87421,=1,778971535469672/273235:-2314080765936080/87421
+qadd:7393810122090184/81127,-64368795434817/4927,501992012340776/76641:31207255204297937809/399712729
+qadd:1814818937088177/50093,4023822663774357/24016,=2:245150040289558524033/1203033488
+qadd:9908501657883705/3803,-5660305521631728/9565,2557272552018733/7891:73248676458892176741/36375695
+qadd:1377747830693440/3541,1463897897659346/1125,3757698108232021/785:6733628765141864186/3983625
+qadd:3772470251348881/322,-7016532949646302/455,388436705580099/410:-77549949346052627/20930
+qadd:334577361872867/32,=1,-5943062864162214/29:334577361872867/16
+qadd:2891305771316359/53,3527889195345726/85,-3763343617650326/27:432739117915213993/4505
+qadd:157402323585140/13,13773830296553/77,3582569222451484/75:12299038709910969/1001
+qadd:-3257588133523091/3,6604850595588048/5,=2:3526611119148689/15
+qadd:109197760602583,=1,4169449356780290/3:218395521205166
+qadd:-3861717767275060/7825274794195216053,16565852262776959/88858046256514809458,1031551014323301/4042869958710944726:-11237492096729581651889648474747087/36596769980659890200362549910023043646
+qadd:23543644363949797/98639149864308555901,55730679379575088/70634154829730489785,48139816814712375/1330063664360761159:7160212256620979254852952806236317933/6967292983788559769917597132102781971285
+qadd:41977719284209529/3751208484710673761,33643459441010377/4194025619262446095,=1:302259260626319542881502707310457152/15732664488071225574728266592393413295
+qadd:-1144293144120949/1098190461076821110,-2402308164750526/582336022019013435,-25203695452988903/938005039894823361:-132182201146680605942090063054147/25580634580908088582093143527264514
+qadd:8034042612751913/97483447149280005,=1,2973340210414523/29561736054695294:16068085225503826/97483447149280005
+qadd:60674693832444605/936779720392078057,21951623942977712/65677242692581337,9097858504748373/818881964501261360:24548782731586239427877568624602469/61525109045678996656110378925422209
+qadd:1302350266814895/5681021273569801,-6236914506844097/7270414939487546,94223237947234379/79008878766068900:-25963417158520815055488814517027/41303381938908446247501001198346
+qadd:-11497844255386016/8204893553520709,7432210588726085/14197957440789783,-6910737086418109/19876126699691764:-102265406650952939625835597880263/116492729479097473986005206116147
+qadd:83714996362880378/8618647846387783,=1,7515078968456230/3062009508291991:167429992725760756/8618647846387783
+qadd:62679487423356388/9001151280591673,56594267794644456/5882920271561917,1634168066276183/300039595214940:878151993207885545835175648690684/52953055335988261889639614117141
+qadd:83131003631837727/747131006183503,=1,17129603086958644/379709519880211:166262007263675454/747131006183503
+qadd:12501751630346081/788796894918041,-21129992690880754/254284308858567,-57956809836544559/534410517601146:-13488273351363624099898642556987/200578673254017756079725707247
+qadd:14059107156579494/6975563866089,37801476305972056/48622905291735,=2:315760415988492217755116230358/113057393739098097672824805
+qadd:23369025294115791/55396441570853,15495067710884335/11665951387764,-3995320971632302/75709901608329:1130993526142997139892946869079/646252194420679895483242692
+qadd:23916091038454111/4545952132054,4689829346138151/3614025441053,-85746958882796523/8521123688083:107753101178558963579755411037/16429186659052283048812862
+qadd:36133728528919771/1785997287207,85398862837628707/8358840780430,-11562670053745837/5200206297232:64936888705012721610457704697/2132695279720460390708430
+qadd:2214561180442189/33997391434,36979053972484369/162888179275,91720233502172759/335502577054:1617917211336886663944928121/5537773190783741330350
+qadd:77386819146397237/20397632304,-5108066159735617/907423591944,32886890778350867/330998714751:973867124217134726941645655/257073510728453452208
+qadd:61459176891343089/21824932076,2685806673289617/2388630617,=2:205420819832094399137810805/52131700970678970892
+qadd:17677723892339211/42474225106,61979558493207868/9941645861,=2:2808279389977180084128489679/422263704224247186266
+qadd:-69708713419564832/6145206843,80609591382825001/4848452972,-78928998060128503/231637472:157383193823784636159601139/29794746381498087396
+qadd:88237221032149171/9534767920,-44968975337449001/556184382,12982666497195442/788160233:-189846289596808310283200299/2651544501549312720
+qadd:-38677387896784223/788948329,9340381978275373/50293174,=2:5423870154623606862407915/39678715587406246
+qadd:26537170671851227/590770266,18034613855208113/484568177,28604184788975171/455924538:23513382039645396684971237/286268470821425082
+qadd:9355751715852854/52744199,-484818910468440/5805289,-50172393950328279/68610859:28741457430061116365246/306195318268511
+qadd:36415297589875947/29546624,-56431669004414295/28023964,31517851668463121/32802117:-161716079264478302849043/207003381824384
+qadd:22971653327178907/4250474,=1,=2:22971653327178907/2125237
+qadd:12746116741017752/5218893,725501139000903/48970,-48129279516836173/1863661:4410490152631478975819/255569190210
+qadd:-88067684618536709/385212,73238199971779517/895372,39724956709082291/929816:-3165069089046207431759/21556752429
+qadd:49757444137808553/108115,26265082097157139/107499,=1:1169789262614917960276/1660322055
+qadd:10749049993334979/14455,11334875189797027/234,77927344912508075/2392:166360898566956410371/3382470
+qadd:1195996993464494/4213,45875551157589131/5270,69424135139802925/44053:199576601182480892283/22202510
+qadd:3520647688460679/2036,2261968838807066/381,34281322264491172/471:5946735325114705075/775716
+qadd:83644190506134287/6033,55464798606172681/8524,67985855300849238/2989:1047602209865328446861/51425292
+qadd:-8698786374318557/422,=1,=2:-8698786374318557/211
+qadd:1118529795834147/2,64597983578878272/755,=1:973685963012537529/1510
+qadd:33377257316975885/26,-40430802589313980/13,97778637401253684/49:-47484347861652075/26
+qadd:82705834958465143/99,24938695531635533/58,-74579422882928086/77:7265869285222896061/5742
+qadd:-32270725150155926/3,=1,-3544924711445815/6:-64541450300311852/3
+qadd:60911268114686151/5,80821489004159773/3,4534056378518212/3:586841249364857318/15
+qadd:-969085346219845449/53998644227029731584,1246624309530693/107133612642748177,-772081460522893303/64669378244722644671:-36505591524565947914216726766988761/5785069833852173313379335508415322368
+qadd:276516649995371231/15574713369274151317,906182816129897588/83697559064365646467,750261136246505381/40984550246015537241:37257306266652922286275605079793914273/1303565492135388561581093647071484447039
+qadd:-140672089095897969/179764890360901598,555145526681662554/1124929648758424561,5984750631146458/28478509146741215:-58450529038488266189701503004255317/202222854972785735655957430027348478
+qadd:-91743425611973129/1107094290508801764,399222195217559278/8079799590284695019,-114641110490499569/4406882677696803466:-299291879701184741517973742167178059/8945099994859541614229671597869213516
+qadd:787379889340800499/956625527086654593,-285703704338782123/459459292066701282,=1:29485849930128206284237638735099593/146510162482723096999644580814762742
+qadd:70749404862883911/495750154649066152,102340090236266554/158445453266377071,27037741921079909/605403590162096:61945037083254592502710474876284889/78549357960247816623822130455000792
+qadd:424824527328220007/23301022216991169,=1,67711743764689990/11333924060290899:849649054656440014/23301022216991169
+qadd:-6663229010931365/88920552753855031,134776639101635638/5309079009270841,366231415498310197/74626301054129981:11949037637948372264801755088366813/472086240118252220339551129451071
+qadd:-32510210684122177/1231828288285445,76160397879785044/676677566334687,-672775726216560223/5675307994591383:71817602308634310869101932830981/833550568259218150148260730715
+qadd:-268284492174317874/5274188879184443,649062356676662391/7205197273636408,231369253089740151/660306726485266:1490234771907975806226632438826621/38001571332943211163847952000744
+qadd:582099480882485529/700067254239488,989829037297761831/930885508478467,561464185181264678/686338297243911:1234814867553904104143762394986571/651682461931850019474109104896
+qadd:184995254328058087/463884296042206,313384341252881473/372141661203466,996350678876136763/997053196652451:53554628948286149849685574294745/43157668133836737280672371499
+qadd:8377174919585897/71232491917440,535206177263043113/25679501875292,746828700553904237/1616624309526:9584797843777708399725583136911/457303727443905678209973120
+qadd:-996273291922997387/44830395380570,-634598527946819886/29124087104801,366443615185294376/48189152110425:-57464853049935846730538932170007/1305644340006389055869116570
+qadd:10766817872037711/8299561973528,60868128026713114/266071146523,-227636182703270761/704789537906:10368235517264478808183285205/45066815712965051739656
+qadd:-61525671534270701/3970810675288,-811892456616177891/5068701282778,-89068223096904603/546438576974:-1767863242073427178167323472493/10063426581750431012295032
+qadd:550334687546784844/502931729895,-860005583438026402/162375660659,358668116551573116/644883640627:-343163137323871850866714435594/81663871908074365700805
+qadd:260849523709491673/297757912904,692166926358108721/802149515516,-997204026651783755/55271345816:103834624609928804772316783513/59711591394249731154616
+qadd:505448870437825193/71845789337,=1,=2:1010897740875650386/71845789337
+qadd:159638929481820528/13739032115,=1,507310009865603761/12553274018:319277858963641056/13739032115
+qadd:-133426952279941451/1589703572,217840769690702699/4142491527,735044017796589411/3007360763:-206417769588551377033244849/6585333577451634444
+qadd:-101118601209663559/3745310451,885199546740371601/9397717537,-459446735274124418/3192681599:2365063061722212098564767868/35197369706872079187
+qadd:-12152036723542051/235562910,891926788712621059/872286523,697897009879673835/130239658:199504811995153362474243017/205478351711661930
+qadd:400891792612792759/54587710,697440729090382751/929044415,-386357311385415463/638053959:82103594641605549540396239/10142881420627930
+qadd:167013298876326173/1918052,47488502066189029/1167594,759419503750021473/53966266:143044571026631590544635/1119753003444
+qadd:676855379766713425/63269998,=1,-714573170617706497/94972518:676855379766713425/31634999
+qadd:409288543596204392/5585379,130886150841077932/843311,-107608169043445049/3162805:1076206289287247740778140/4710211549869
+qadd:691213642440502645/22737,=1,=1:1382427284881005290/22737
+qadd:960631875359803053/230030,228919423015609883/333487,37946707333060033/44234:373016577094395382122301/76712014610
+qadd:251068611473963959/515543,94841287315376536/22327,-479143444821261102/650503:54500370674810358811641/11510528561
+qadd:-108350199223779473/51984,111736989262785999/14705,=2:4215245970250990221551/764424720
+qadd:88108619904503621/81260,154844354458466755/2207,=1:12777107967424248002847/179340820
+qadd:-486724060444092739/5751,-246250309508757077/2993,449147573438373443/1564:-2872950642894031517654/17212743
+qadd:-850389260078463631/6276,-954710858838119571/8792,340877365239969027/584:-3367096931169472667837/13794648
+qadd:219904330718240359/222,757977245624505558/967,175510199184903827/581:380918436333178661029/214674
+qadd:318243239218041752/59,767069919224699682/347,=1:155687529242917769182/20473
+qadd:697074341020289390/53,106833670515931911/11,44958754351960065/23:13330002288567574573/583
+qadd:516501254786898965/6,-164729804637666233/6,=1:58628575024872122
+qadd:82963845478413593/7,55644033089135156,233198647629741003:472472077102359685/7
+qadd:164451756488343692,271265725719237343/8,=2:1586879777625986879/8
+qadd:5043821125454793265/5618281832502940151,=1,-543884583593009413/8012420875585043886:10087642250909586530/5618281832502940151
+qadd:1764906175362120158/31402243297654667473,2229661152827134119/6508891977220041701,1894248816526157489/7307308465166355047:81503945637767463543703614619050520045/204393809466816291062044346462348291573
+qadd:-1362907275103916799/4719984305032890358,5677647195374925883/7969616636801670538,-8231092261190079885/5235441156455608811:3984139289399363012151226105338442063/9404116360708223470362017252248218151
+qadd:290807472633374281/1258837033388879519,1699792368148991135/4469792775816725417,=2:3439610722427910580290181520680864242/5626740677772171640401250773318034423
+qadd:-9803615938594182209/179436612901884445,632531485773805909/24631423728192118,1107916995642111584/51994977769890891:-127977710890922943063734246473443157/4419779244737900457684595195804510
+qadd:212099052410103851/14112064685928255,-1546460633714174323/543797344189345181,1466382576090755442/798177433526983523:93515148908475176743400909755195666/7674103297236030685795513595989155
+qadd:2231031722816738561/15236183051646264,2143589106723393457/20940609306247892,=2:19844819918725746241023330019364515/79763739150750040606892869918872
+qadd:-9575590803372574182/19535794897504279,=1,8043316090192509079/21730235406706349:-19151181606745148364/19535794897504279
+qadd:5016235407304247978/3059319382797913,=1,1013119725862020638/1523223220476823:10032470814608495956/3059319382797913
+qadd:2894078389438839283/1569075282041943,-2665448726814208207/4452815285777552,1242049344845007051/681162286716620:8704506777937400951911781308349015/6986802400412087425201031863536
+qadd:-2761359171647944304/524718540633809,640460627361693124/51241877637449,24526182054440865/932662203109421:194564336936009885784577260588820/26887563253258451827973913241
+qadd:4377034106342870447/284491641803297,367444739727332559/187288898129576,4771977529029312743/237034833694131:924304852129543576890267568687495/53282126120413516875010012072
+qadd:-1084950831949751089/12896572149034,1068560037854748158/52652358693733,3302405312908713775/34972953328882:-43344458745114066006755621245865/679034942710545208837803922
+qadd:908971092109438313/2042877065884,=1,=1:908971092109438313/1021438532942
+qadd:7969199262095318650/6376127197957,=1,903887938076097336/594071493169:15938398524190637300/6376127197957
+qadd:4839349064327340004/3805686625309,4317900645018438773/5983979445459,-689687038324621568/7626332987577:45391142064495823172086675547693/22773150541707282934521831
+qadd:-1660640044482828405/123686665162,1468015760631904370/154714309067,=1:-75350803253335844678902090195/19136096941340209623854
+qadd:3359844750012921/70716653,290023334833820440/24901328071,446648123840546873/44205337621:104174075919044820029792711/1760938576436066363
+qadd:-8524152918701542873/27483319743,572629374273579433/1843500145,345801513474448186/34748134655:23479045766334416148429134/50665503931301862735
+qadd:461532154960869496/88629445599,-3067104818016109135/42934967742,-5658191264987110039/23622515075:-84006643809882954201032549611/1268434129261469622486
+qadd:2107778483720627369/79151569,4539993449270881832/8042518085,=1:353289677127684406239691077/12991386227318885
+qadd:-5200199645684863958/1508061869,1037044821661150583/89359314,574740187726215359/551649888:1099241478989643929419214815/134759374083397866
+qadd:6429669718772297/246412472,7129345785374382275/462920354,2455561683986174279/1566173:879868071849600067014183469/57034674384127544
+qadd:1738227802075055570/327533141,=1,2601403037612548877/229872139:3476455604150111140/327533141
+qadd:3436599097095658763/14598030,=1,958841139244535864/69388675:3436599097095658763/7299015
+qadd:6575572376501646299/89845794,1883123242302019558/2079573,=1:60955028559399331030329793/62280295788654
+qadd:8246990382353771761/1153985,7360354913817962691/3109420,528293916457716807/6436589:6827419199984137333012451/717644807740
+qadd:5939937149370464031/3123809,3641790392665278283/8453885,588122952232762701/1541615:61591803172727055602650382/26408322047965
+qadd:270376064542116947/102161,=1,=2:540752129084233894/102161
+qadd:131163854733041727/323971,3502368174871763808/31573,108739692256458838/855:1138806956366866519088139/10228736383
+qadd:2295686487125757632/9399,5192247177653340310/74391,7756262792928856511/14718:73193448228845327191934/233067003
+qadd:-1157668445283763977/98255,-6862870187854810458/92423,=1:-781306501026135719597061/9081021865
+qadd:331518036234256523/2056,815887256529953349/482,196168905129502546/4049:918627946445247864815/495496
+qadd:-2035788783736026328/8319,8303222045592699428/9011,-1864379673211519106/1401:50730011467040333299924/74962509
+qadd:2843403596885438497/227,3405071238014843037/907,410871865808099072/31:3351918233404462086178/205889
+qadd:6888377466446373262/559,-4233882656695844123/346,=1:16638198297468283895/193414
+qadd:-8544001908785450503/61,538024038063863901/19,-359823220116074567/8:-129516569945027861596/1159
+qadd:-2873163532076118107/33,599376533960103224/29,603524459540653533/83:-63542316809524018711/957
+qadd:1063922232492764301/2,6854581919241901325/6,6969845457837372101/4:5023174308360097114/3
+qadd:2352628464632327696,=1,-2926879886747018505/4:4705256929264655392
+qadd:38750299973229623063/36181224711595653198,95066204533556190887/4815411929001685731,8874164143102558897/10732317260440182753:402912262827843733479506682549361735631/19358611231345364982923389088229013082
+qadd:48742220039338674056/67138210285692216649,31818042798992490898/21353165712067248083,5900286084455262748/49045932502167224591:3177007149991956505876862526845604395450/1433613329842003680672466022985665933867
+qadd:87217932340221331903/2665309420727136089,1273107818123651579/33738995536126310,55551725128033095975/2650789751926588423:6335871691143231965413514248993402461/89924862648308245613767543263401590
+qadd:-54380689308824351360/1703471436980462073,=1,-72316980450522981244/8351933107679217397:-108761378617648702720/1703471436980462073
+qadd:37029624832139894565/54555708192540067,111936754529639081/4842509306811346,47780458168088681783/99817190816504869:185423091793508942579252306927292917/264186524662059269844548115200182
+qadd:-22582885555171871569/276061047279571597,37882169208497878632/62669917022723249,38915003092334150861/133381815208219710:9042523741043587572300262155802007623/17300722926216831696081927011958653
+qadd:33158690128759394124/27845156068309087,20040091306620091462/93471893000203813,-2800433644018142872/303526659689803:3657425005798313102460083146020310006/2602739448590962875785441279948731
+qadd:3197839850448851481/15625985746620581,=1,1644265406502320897/6242254024865644:6395679700897702962/15625985746620581
+qadd:1923674921668264769/66091808607807,47645418789767983519/2547180528667403,-94362350068612539221/364341393607160:8048919203651352698528804054357740/168347767990218650522372215221
+qadd:63079152525440745698/2231593339592783,3556320317878822237/3926878376870658,-99040920722967906187/1600307564553594:255640420818316291470533856441044855/8763195631215478802223581261214
+qadd:3155815575082653608/30192877351261,11795128154822010181/20651109856531,31816014676979512957/70387620365646:421299951848929855087786504702089/623516427065657629001935591
+qadd:23991887334900651603/96699483325270,3750668873805896041/943821328748345,=2:33586485731135365147071981775333/133236547213627390084100990
+qadd:2309692393299313895/92991584939154,13505703402565112683/18557182710305,94620445875012570863/90668308130179:1298778148869711868710408754878157/1725661832236727444233781970
+qadd:57594369573165928157/93091121490986,-8216395801314141034/4528867987769,-26450061693998675351/44029529374639:-504036203122513874440040155007791/421597400066041276891750234
+qadd:24542791235970972879/2344787306732,-64933302597803670427/4342923289956,=1:-5708415507036463291655594663905/1272903925549950743347974
+qadd:-172272128642878525/1253023290162,-56946438418624682181/1249572807253,19174037020580911223/8107587302833:-71570480197712551233049111945147/1565743830241120717144986
+qadd:3028920190202346838/805608849389,40089795752860144393/372471218723,15183822811879905592/111683851673:33424879823361049021005735273751/300066109945954583910247
+qadd:76500387765072442325/775493963262,122900265147567688/16725267965,50834815414479646533/248262732319:1374797898502481981169162896881/12970344340796815501830
+qadd:59590674910838495728/13005850369,86406272304132657397/74890842311,37835029633787556154/89471413727:5586582886484287970785818176901/974019089105240162759
+qadd:-1540621953597844070/6475929139,-8097002238368386377/33525625058,4994696033629226613/9124261493:-104085926706442851563193645463/217109572216290765062
+qadd:1020455924950028825/71307089,-15027123384295411453/4869731824,32588900069283614833/4623109762:3897806268140576872049136483/347246400580100336
+qadd:98927709935781735893/4858671845,14545842510003768295/485475574,36811564317330662262/7963827409:118700462230738581230190731857/2358766502829014030
+qadd:7968100306775934624/24002777,40497155380044030991/145085209,58654545110130593822/33483457:2128097688063097717151438423/3482447917625393
+qadd:-23611980270981239714/420152229,95487639446075722616/816419473,-5579567954544211437/617972198:20842064065896139239707560342/343020461379955317
+qadd:-41034887738055776999/13333375,84899158825411622388/47895653,30327216586322045860/36885673:-833400422192101699131885847/638610702318875
+qadd:24656093429908250495/27564561,2208448163081784406/5010537,=2:61471724170872663319500527/46037750926419
+qadd:2133095351837200006/1310507,=1,-21206650272439533589/973111:4266190703674400012/1310507
+qadd:19180784354554459582/1180789,47269383367680368601/863423,81472957723316044010/8522997:72376298287102409915675375/1019520380747
+qadd:57138477662354817611/225222,46133836132900735393/499504,97630303852343664772/247381:19465626493890525121323595/56249644944
+qadd:29853842167305129575/324248,24424888107355543894/33291,-23582416174010240026/335387:8913585378625575465223037/10794540168
+qadd:-420456923149560733/537,72302352874036923083/70362,23736761268395718034/5245:3080724488902811800075/12594798
+qadd:539720131536363641/89712,-47388649478839966234/1133,4570686076693373255/1613:-4250719019136660350779355/101643696
+qadd:-35074948988121263785/1743,46439113742337125259/3968,66374900563777261496/1307:-58234022331971565372443/6916224
+qadd:-28803141465771759543/4526,54869054724564777023/3954,1798941140485680569/657:33612430081929660893269/4473951
+qadd:725551877269445969/431,=1,32744674741853348893/693:1451103754538891938/431
+qadd:91879409948684343784/517,-92515200339135325921/86,41625165280534848151/424:-39928729319746109935733/44462
+qadd:-29166863008492740086/27,-62979221821453932179/87,14020736369187295840/17:-1412652023639374852105/783
+qadd:68001809592817590555/61,-7705962877958413589/4,38853502652707551384/11:-198056497184192866709/244
+qadd:-79744407268013845618/3,-17168463782676239957/9,40182413433838316451/2:-256401685586717776811/9
+qadd:-61204110018146728334/3,-31052192278051565633/2,=1:-215564796870448153567/6
diff --git a/polly/lib/External/isl/imath/tests/qaddz.t b/polly/lib/External/isl/imath/tests/qaddz.t
new file mode 100644
index 00000000000..584ffcc5ebf
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qaddz.t
@@ -0,0 +1,800 @@
+qaddz:1/54620799347511326707,-4,5/50425624798430340799:-218483197390045306827/54620799347511326707
+qaddz:1/212138780821487407,-4,-1/2172160838694653181:-848555123285949627/212138780821487407
+qaddz:-8/2596450420794466343,3,-5/33209689038794936:7789351262383399021/2596450420794466343
+qaddz:0,0,1/7506665947113966172:0
+qaddz:3/301921530103952791,6,=1:1811529180623716749/301921530103952791
+qaddz:1/47796551294919635,0,9/408623107847915846:1/47796551294919635
+qaddz:0,-7,3/44304529385671853:-7
+qaddz:-6/59168527940606359,-7,0:-414179695584244519/59168527940606359
+qaddz:0,3,-1/1803043485158662:3
+qaddz:4/805996063056383,9,4/4602479413908539:7253964567507451/805996063056383
+qaddz:3/908244468147226,-7,3/60173056873814:-6357711277030579/908244468147226
+qaddz:0,4,-2/385639438244941:4
+qaddz:7/59007802744210,-6,0:-354046816465253/59007802744210
+qaddz:7/80088880526056,8,=1:640711044208455/80088880526056
+qaddz:4/1915432332283,6,1/975133146111:11492593993702/1915432332283
+qaddz:-2/4374674512379,1,1/1450918107984:4374674512377/4374674512379
+qaddz:-1/176293450395,-4,=1:-705173801581/176293450395
+qaddz:-2/150047873621,9,7/862965342703:1350430862587/150047873621
+qaddz:7/90154985532,7,5/5122907862:631084898731/90154985532
+qaddz:3/35150061317,2,1/39676293318:70300122637/35150061317
+qaddz:2/865482845,-7,1/6059793299:-6058379913/865482845
+qaddz:1/7111641188,4,8/9256455537:28446564753/7111641188
+qaddz:1/231395954,2,-3/198206266:462791909/231395954
+qaddz:-1/5342717,6,=1:32056301/5342717
+qaddz:-1/1255946,8,7/39589307:10047567/1255946
+qaddz:9/48244018,3,=1:144732063/48244018
+qaddz:5/7367079,8,1/3896866:58936637/7367079
+qaddz:3/326524,0,3/4328111:3/326524
+qaddz:-7/836910,-2,9/919579:-1673827/836910
+qaddz:5/887451,6,8/592505:5324711/887451
+qaddz:-8/94183,4,8/66975:376724/94183
+qaddz:2/33127,1,-1/14729:33129/33127
+qaddz:-1/1132,-5,8/8763:-5661/1132
+qaddz:1/4973,8,=1:39785/4973
+qaddz:-5/71,-4,4/875:-289/71
+qaddz:1/125,0,=1:1/125
+qaddz:0,9,=1:9
+qaddz:-3/29,4,4/67:113/29
+qaddz:5/3,9,5/8:32/3
+qaddz:1,-3,2:-2
+qaddz:31/75290504490996366117,-89,80/87349767408470122133:-6700854899698676584382/75290504490996366117
+qaddz:-1/2025002780262471319,54,13/33364955876728529603:109350150134173451225/2025002780262471319
+qaddz:5/226091118641865964,19,98/9684762482985042665:4295731254195453321/226091118641865964
+qaddz:-1/3269119415472267421,45,-31/5732304804177650236:147110373696252033944/3269119415472267421
+qaddz:-52/674837392469005073,-1,49/926152724308138640:-674837392469005125/674837392469005073
+qaddz:-33/233752284775146865,10,1/34021154309272456:2337522847751468617/233752284775146865
+qaddz:33/37915766989934257,32,9/20112346122968212:1213304543677896257/37915766989934257
+qaddz:31/42388535088021265,-6,=1:-254331210528127559/42388535088021265
+qaddz:21/134052208089341,-81,33/306549029392024:-10858228855236600/134052208089341
+qaddz:1/2145839249313809,73,33/3181662864206624:156646265199908058/2145839249313809
+qaddz:3/712097424282067,61,1/54860371983348:43437942881206090/712097424282067
+qaddz:-27/242055520851227,81,85/884187769743491:19606497188949360/242055520851227
+qaddz:87/75610348177252,5,-63/45006979682459:378051740886347/75610348177252
+qaddz:91/22460567019277,-63,-4/5688629009171:-1415015722214360/22460567019277
+qaddz:34/5611315344227,50,-26/8764714566551:280565767211384/5611315344227
+qaddz:2/1448323251689,48,=1:69519516081074/1448323251689
+qaddz:-13/507312090741,87,-31/36494655847:44136151894454/507312090741
+qaddz:35/695649048043,32,=1:22260769537411/695649048043
+qaddz:-22/53469298165,50,-41/44921870282:2673464908228/53469298165
+qaddz:0,-42,19/22231277127:-42
+qaddz:44/1990669661,15,88/2011535859:29860044959/1990669661
+qaddz:52/911062095,39,=1:35531421757/911062095
+qaddz:7/125107130,-87,86/274603713:-10884320303/125107130
+qaddz:3/56375633,-47,=1:-2649654748/56375633
+qaddz:-1/1856173,10,71/56499774:18561729/1856173
+qaddz:7/6626238,64,32/20302401:424079239/6626238
+qaddz:15/1633807,4,52/1107445:6535243/1633807
+qaddz:99/7321367,57,26/2807871:417318018/7321367
+qaddz:-10/101833,50,32/474687:5091640/101833
+qaddz:47/89673,-41,31/421155:-3676546/89673
+qaddz:29/67933,-9,-24/68509:-611368/67933
+qaddz:10/7473,12,=1:89686/7473
+qaddz:-65/3001,21,79/2243:62956/3001
+qaddz:8/4983,-5,=1:-24907/4983
+qaddz:3/230,-4,16/53:-917/230
+qaddz:16/377,66,-61/214:24898/377
+qaddz:-41/23,96,5/41:2167/23
+qaddz:-5/9,35,95/34:310/9
+qaddz:72,11,45:83
+qaddz:13/6,16,=1:109/6
+qaddz:-277/80983188935181565796,610,=1:49399745250460755135283/80983188935181565796
+qaddz:79/15192291024925486394,143,=1:2172497616564344554421/15192291024925486394
+qaddz:-231/6313238620833887902,481,325/134903344527041052:3036667776621100080631/6313238620833887902
+qaddz:935/1485416466862593748,222,-565/6248719316822480264:329762455643495812991/1485416466862593748
+qaddz:-967/626150835751553604,-409,77/6043113279368884:-256095691822385425003/626150835751553604
+qaddz:-191/672212197195743189,906,301/296825083216628537:609024250659343329043/672212197195743189
+qaddz:323/65375330562542722,876,935/31091316170043549:57268789572787424795/65375330562542722
+qaddz:-143/40251685718424887,46,373/18639328341468821:1851577543047544659/40251685718424887
+qaddz:130/6295699493323523,-390,-174/17530058264063:-2455322802396173840/6295699493323523
+qaddz:579/8145570591252371,-21,40/2232149554773023:-171056982416299212/8145570591252371
+qaddz:265/47192654250488,316,536/603327182103531:14912878743154473/47192654250488
+qaddz:71/34035968910103,-744,327/497134848511328:-25322760869116561/34035968910103
+qaddz:254/93818137594343,-487,83/17550216682523:-45689433008444787/93818137594343
+qaddz:-824/19205768158351,727,241/53745460287591:13962593451120353/19205768158351
+qaddz:-758/4519346718465,-718,=1:-3244890943858628/4519346718465
+qaddz:75/64951063118,573,-139/8704353659601:37216959166689/64951063118
+qaddz:-187/758236499162,224,294/841106266507:169844975812101/758236499162
+qaddz:-34/37119383027,-857,=1:-31811311254173/37119383027
+qaddz:-441/57312007072,914,=1:52383174463367/57312007072
+qaddz:25/18513015668,-567,50/47247431347:-10496879883731/18513015668
+qaddz:343/904828730,-386,84/2415081317:-349263889437/904828730
+qaddz:-15/705578962,85,67/15485401:59974211755/705578962
+qaddz:-671/597940315,-297,-38/36423405:-177588274226/597940315
+qaddz:141/16827008,1,=1:16827149/16827008
+qaddz:19/1823825,304,152/12228673:554442819/1823825
+qaddz:623/94768157,753,-15/53060492:71360422844/94768157
+qaddz:5/30576,-780,515/3838063:-23849275/30576
+qaddz:85/456198,-545,278/3171433:-248627825/456198
+qaddz:-61/154737,175,230/373207:27078914/154737
+qaddz:784/22467,-975,221/842081:-21904541/22467
+qaddz:264/26219,577,=1:15128627/26219
+qaddz:648/86443,318,-751/62582:27489522/86443
+qaddz:-736/5001,599,73/1531:2994863/5001
+qaddz:58/1057,11,163/2848:11685/1057
+qaddz:265/416,564,33/505:234889/416
+qaddz:603/8,39,155/119:915/8
+qaddz:51/43,341,-3/53:14714/43
+qaddz:89/68,-261,42/5:-17659/68
+qaddz:316/3,138,=1:730/3
+qaddz:-157/4,778,-242:2955/4
+qaddz:-1220/24425361794374611191,-2739,9923/58596476391899748982:-66901065954792060053369/24425361794374611191
+qaddz:4756/68889234195734663973,9499,=1:654378835625283573084283/68889234195734663973
+qaddz:-6740/6193173096605308887,-3748,-1774/1349471376636973063:-23212012766076697715216/6193173096605308887
+qaddz:4951/5273171148713492245,2850,73/76840073320949141:15028537773833452903201/5273171148713492245
+qaddz:307/50758090271672590,-7992,4023/144759202361690600:-405658657451207338973/50758090271672590
+qaddz:4507/193110223350280382,2550,-4697/807940924231898113:492431069543214978607/193110223350280382
+qaddz:7135/87030719499305628,-2633,=1:-229151884441671711389/87030719499305628
+qaddz:-4425/57492072202943332,-9695,8774/1065824219401905:-557385640007535608165/57492072202943332
+qaddz:-2171/59546743026218,-2275,3354/2713497612422239:-135468840384648121/59546743026218
+qaddz:-420/497459043701647,-2485,6408/6394215912846235:-1236185723598593215/497459043701647
+qaddz:1796/82252594594341,9198,4191/934791612378541:756559365078750314/82252594594341
+qaddz:6624/484898002393549,-2338,4534/518674030101081:-1133691529596110938/484898002393549
+qaddz:2261/81693124807278,2477,6397/30033270473277:202353870147629867/81693124807278
+qaddz:1971/3597019637272,1116,3989/62351952484275:4014273915197523/3597019637272
+qaddz:-821/2973214305299,7102,2099/3415351232644:21115767996232677/2973214305299
+qaddz:3455/5604793125537,-4157,1475/8622435080543:-23299125022853854/5604793125537
+qaddz:-663/231000718186,2230,1885/90136214836:515131601554117/231000718186
+qaddz:9841/907754978407,475,-3707/314368976315:431183614753166/907754978407
+qaddz:388/1661926713,-9986,-4927/71849157859:-16596000155630/1661926713
+qaddz:893/2494453262,4917,6805/49826778773:12265226690147/2494453262
+qaddz:-2393/1820211958,9429,=1:17162778549589/1820211958
+qaddz:3478/4373863243,7552,9147/4954348655:33031415214614/4373863243
+qaddz:-5135/74721107,-742,4898/141314343:-55443066529/74721107
+qaddz:-1789/88275441,-7193,5814/533915795:-634965248902/88275441
+qaddz:3322/13291911,9390,-3263/50883910:124811047612/13291911
+qaddz:4577/34396558,-489,=1:-16819912285/34396558
+qaddz:8903/3869879,-4634,-3811/2146853:-17933010383/3869879
+qaddz:4014/1153681,4901,802/351473:5654194595/1153681
+qaddz:471/442073,-2998,9329/562186:-1325334383/442073
+qaddz:-893/461068,4168,2066/986911:1921730531/461068
+qaddz:336/38503,8872,653/13211:341598952/38503
+qaddz:8000/86117,1965,=1:169227905/86117
+qaddz:-8578/2779,-9006,9377/9189:-25036252/2779
+qaddz:-211/1008,-1599,=1:-1612003/1008
+qaddz:-1675/366,-4872,=1:-1784827/366
+qaddz:209/137,651,2717/320:89396/137
+qaddz:-5333/38,8162,370/67:304823/38
+qaddz:1729/8,6131,-5099/27:50777/8
+qaddz:3528/5,1915,9521/3:13103/5
+qaddz:-1303/4,104,-2439:-887/4
+qaddz:9256/43175436158473507749,-33340,=1:-1439469041523506748342404/43175436158473507749
+qaddz:43562/48013284592061748195,-32389,3543/476829824739261233:-1555102274652287962244293/48013284592061748195
+qaddz:31781/970330955234841076,25523,=1:24765756970458848814529/970330955234841076
+qaddz:72455/9090210348118255617,89034,48363/241345568170272728:809337788134360770676433/9090210348118255617
+qaddz:81871/335292796101778469,36100,=1:12104069939274202812771/335292796101778469
+qaddz:4031/299114846145519512,11847,48460/472966149918742127:3543613582285969662695/299114846145519512
+qaddz:70081/4000940087930231,28866,-48187/41751383598706590:115491136578194118127/4000940087930231
+qaddz:53565/36491429482144547,3583,22780/40933313880950073:130748791834523965466/36491429482144547
+qaddz:71053/3239886404702374,6327,5499/820365894600107:20498761282551991351/3239886404702374
+qaddz:1901/1115077430717827,78838,32029/643930274853778:87910474482932046927/1115077430717827
+qaddz:13107/6867073713490,67883,12163/313820861435242:466157564892854777/6867073713490
+qaddz:7612/71978407947133,-35439,47880/289218281250503:-2550842799238438775/71978407947133
+qaddz:487/93536104647,54212,=1:5070779305123651/93536104647
+qaddz:24139/22092733596669,7166,12083/20662610330153:158316528953754193/22092733596669
+qaddz:3756/377555799673,-90845,-6186/7949435140837:-34299056621289929/377555799673
+qaddz:51740/5334618145423,33038,30992/9506692645181:176245114288536814/5334618145423
+qaddz:-19431/313093258328,-29145,73759/467815221180:-9125103013988991/313093258328
+qaddz:45134/532171216165,-65154,-98921/239496530364:-34673083417969276/532171216165
+qaddz:-10586/5380332719,43778,-83869/38492047300:235540205761796/5380332719
+qaddz:-64073/25839289167,56469,-20852/44667409353:1459118819907250/25839289167
+qaddz:83896/6875621201,-60135,68147/7560028407:-413465480838239/6875621201
+qaddz:14947/3229243360,20054,72954/2728010911:64759246356387/3229243360
+qaddz:12569/138044852,29541,4251/162658732:4077982985501/138044852
+qaddz:28489/894461083,-54474,99821/372230979:-48724873006853/894461083
+qaddz:461/1016937,67128,-5113/48518554:68264947397/1016937
+qaddz:16058/28261309,-81920,5223/49399519:-2315166417222/28261309
+qaddz:-19094/531145,82677,89232/5738845:43913456071/531145
+qaddz:47358/4287503,-45771,=1:-196243252455/4287503
+qaddz:-44068/383233,28914,=1:11080754894/383233
+qaddz:-84061/931926,49385,=1:46023081449/931926
+qaddz:32731/30919,93827,16987/24520:2901069744/30919
+qaddz:-21037/20727,69534,11467/44693:1441210181/20727
+qaddz:-47647/8209,-53576,=1:-439853031/8209
+qaddz:50277/5119,34616,=1:177249581/5119
+qaddz:-45615/49,-81078,=1:-4018437/49
+qaddz:938/11,60282,36405/461:664040/11
+qaddz:35243/28,51616,=1:1480491/28
+qaddz:-44031/10,33851,-23233/67:294479/10
+qaddz:-40623/2,22693,=1:4763/2
+qaddz:50400,33578,4505/7:83978
+qaddz:44296/145305576996331809,-672446,887487/74206063873608800927:-97710154028875339590518/145305576996331809
+qaddz:641331/10728482754302259559,568057,480993/26722669314559144651:6094389727960678658948194/10728482754302259559
+qaddz:-10499/172183973129275356,938689,261219/9688984711512627413:161627201552746354637785/172183973129275356
+qaddz:-220611/2078134078025492204,-247650,=1:-514649904423013144541211/2078134078025492204
+qaddz:-93245/773599326123432094,810506,507053/740092254069402604:627006895418998452686319/773599326123432094
+qaddz:41051/5604661525608694,512095,417153/767762014998995362:2870119143956584194981/5604661525608694
+qaddz:256857/23764638432843923,-937980,-101171/1839317653823037:-22290755557238942638683/23764638432843923
+qaddz:-332573/48056484575068455,801985,51624/28399631222945227:38540579781936274550602/48056484575068455
+qaddz:555886/6363636074566197,531487,-826671/4672965611688254:3382189846362964900825/6363636074566197
+qaddz:-563124/5236412248020907,-719499,-431679/3372450157381352:-3767593376038795128717/5236412248020907
+qaddz:701612/201096646211621,852450,410105/341513117509976:171424836063097023062/201096646211621
+qaddz:44341/596871824184687,-222953,40264/891060847151681:-133074363817448476370/596871824184687
+qaddz:10699/24587438378106,344946,=1:8481338518774162975/24587438378106
+qaddz:227237/49603690945178,672137,=1:33340476020819332623/49603690945178
+qaddz:597973/5184695092393,114662,356604/1911748822639:594487508684564139/5184695092393
+qaddz:641047/1530353811852,785653,=1:1202327063343600403/1530353811852
+qaddz:597136/70017180317,618996,296751/321064961965:43340354548098868/70017180317
+qaddz:695839/510312151846,171207,205001/260822503888:87369012581793961/510312151846
+qaddz:809905/71504572844,73808,693901/76175273098:5277609513279857/71504572844
+qaddz:255273/62347365151,-84966,-374235/27650351674:-5297406227164593/62347365151
+qaddz:713594/3263659443,510765,=1:1666963016117489/3263659443
+qaddz:295910/3582838971,-154033,-25081/64948294:-551875434924133/3582838971
+qaddz:-630478/469725959,648937,2485/978731798:304822554025105/469725959
+qaddz:857939/546600623,-325885,374369/469544259:-178128943168416/546600623
+qaddz:4621/225308,181124,-720337/99151657:40808690813/225308
+qaddz:763904/62700883,137970,229231/94941727:8650841591414/62700883
+qaddz:65347/480512,137371,214509/5722910:66008479299/480512
+qaddz:-111067/738339,649352,84919/764118:479441795261/738339
+qaddz:171027/450233,-6580,9836/486877:-2962362113/450233
+qaddz:913138/821889,489239,134731/100945:402101065609/821889
+qaddz:701114/19829,-614638,-23827/46967:-12186955788/19829
+qaddz:326257/29870,642576,=1:19194071377/29870
+qaddz:106159/1985,574591,-569660/4723:1140669294/1985
+qaddz:148129/3938,47925,860775/3839:188876779/3938
+qaddz:887330/711,205135,-45802/45:146738315/711
+qaddz:42863/18,-93194,208961/276:-1634629/18
+qaddz:4012/29,-93697,20725:-2713201/29
+qaddz:22117,453874,196189/90:475991
+qaddz:-612637/8,-695084,609247/5:-6173309/8
+qaddz:57845,-697681,-866863/7:-639836
+qaddz:4360261/62036756574194097073,8366924,9603243/52038505911108171230:519056827462782371462773713/62036756574194097073
+qaddz:122203/37104707293639154664,6618642,2840782/70804511700211559411:245582774091386441903768491/37104707293639154664
+qaddz:2975379/3405105441588501638,1224553,-452223/338247701671728355:4169732083813524449293193/3405105441588501638
+qaddz:1236750/6927456590095070879,4061575,8656635/218877078505884724:28136384499915387506611175/6927456590095070879
+qaddz:5514100/889151389478456273,579914,4385513/526230054850522272:515631338878009496614622/889151389478456273
+qaddz:4769436/180047856472105135,9133872,5104049/860727869521825524:1644534074890579878402156/180047856472105135
+qaddz:1129619/13834516044696008,3200844,-6235960/99099205495661801:44282127674568950160371/13834516044696008
+qaddz:-4436473/31680301433353002,-5808829,2360562/31638389601284341:-184025453694802489691131/31680301433353002
+qaddz:3832873/3686022654332134,3511591,2148425/643043583198782:12943803978748836598067/3686022654332134
+qaddz:-7569910/152442797410363,8827549,=1:1345696263837044920377/152442797410363
+qaddz:4372465/567281920816919,7607995,=1:4315878017165520039870/567281920816919
+qaddz:5998833/480252391591963,727708,1934709/45746184416396:349483507380610209637/480252391591963
+qaddz:3161338/53726702330731,2061828,-609862/19212003746435:110775219213169597606/53726702330731
+qaddz:131113/3229582131545,-2913645,-2325146/23074994508107:-9409855829665300412/3229582131545
+qaddz:4389212/772304888811,-9008024,4662292/1333533763161:-6956940973722430252/772304888811
+qaddz:815149/899391465210,1866152,-3495177/4058839242973:1678401181585387069/899391465210
+qaddz:6099185/812281384924,516393,3627307/291261495421:419456421211158317/812281384924
+qaddz:2706122/517440388607,-5819,7950079/252677744377:-3010985618598011/517440388607
+qaddz:3534256/50461476673,7199887,=1:363316929902270207/50461476673
+qaddz:-341422/3319030425,9477224,=1:31455194800198778/3319030425
+qaddz:1777807/3107794205,-7728298,-3370724/3708129283:-24017959737135283/3107794205
+qaddz:-5327233/9277787037,3319889,6246449/2731964013:30801223123151660/9277787037
+qaddz:-9819076/309587449,-64284,=1:-19901529390592/309587449
+qaddz:5932665/955345021,2160126,2378998/340986557:2063665624765311/955345021
+qaddz:27849/96378415,6447655,-1830047/14377112:621414769394674/96378415
+qaddz:452633/3628007,-6184207,2601894/13372759:-22436345832816/3628007
+qaddz:1646531/1203794,-1799977,-2372416/1725139:-2166799866207/1203794
+qaddz:2641959/511223,1901148,1953355/2249527:971913225963/511223
+qaddz:-10086/1165,1012800,-8266052/33291:1179901914/1165
+qaddz:2434418/167529,2764968,=1:463214758490/167529
+qaddz:6481704/22457,4174437,7094833/47337:93751813413/22457
+qaddz:-3250889/26779,7463010,4107129/47161:199848693901/26779
+qaddz:599335/1376,7764075,-2794121/1154:10683966535/1376
+qaddz:-1446188/1023,-1120763,=1:-1147986737/1023
+qaddz:-6355319/520,8873579,-4229533/845:4607905761/520
+qaddz:-8333079/502,4777754,-2211765/838:2390099429/502
+qaddz:-664681/39,1853000,7994519/83:71602319/39
+qaddz:-6686979/41,-8893574,-1077101/12:-371323513/41
+qaddz:-188498,9478449,=1:9289951
+qaddz:-1148991/2,3210266,=1:5271541/2
+qaddz:13593663/25788635148712130170,9749642,73140616/63308113773746847799:251429960368560030228492803/25788635148712130170
+qaddz:55138471/984284327092850808,71726057,45865951/15569580966066839785:70598833749268461402242527/984284327092850808
+qaddz:-93458416/3876652721819618213,38189554,-59813819/4844052168542685795:148047638459177287911288586/3876652721819618213
+qaddz:-13202403/1193328009457250122,10267890,1513303/582767321730759548:12252960735026003941980177/1193328009457250122
+qaddz:56178208/35416123641813139,77841322,6805923/142304130637208152:2756837884394189272907966/35416123641813139
+qaddz:91725073/281875811815728492,-75791628,=1:-21363826671335698322939903/281875811815728492
+qaddz:-87952363/35128220892663058,-95959069,-6580898/40762262950663657:-3370871372486296064325365/35128220892663058
+qaddz:1593208/1779268204772945,57788357,=1:102820986216168051194573/1779268204772945
+qaddz:-40115057/1844576541622880,45148647,48149671/4721486463692100:83280135142212176128303/1844576541622880
+qaddz:71660059/7908261305514706,46408705,87309016/9251884131271557:367012165990546935575789/7908261305514706
+qaddz:12899069/900901725436207,-53144602,-36141736/346358215988697:-47878063639420484505545/900901725436207
+qaddz:12859471/415241177014271,71268555,-60349912/357890988024495:29593638662306321407876/415241177014271
+qaddz:6490779/7687148332738,-56678219,2747770/29442703192421:-435693876688402742843/7687148332738
+qaddz:-60847891/99630307357354,88116713,-98374273/39412545202138:8779095199509690009511/99630307357354
+qaddz:-25941332/4772253631053,-67231252,85813662/2010665859491:-320844586477265209688/4772253631053
+qaddz:4828372/85755227179,10688383,10501313/2337582857089:916584712345989929/85755227179
+qaddz:57153058/801923397935,80676502,=1:64696374617406976428/801923397935
+qaddz:33518641/130632158802,75978846,54844171/383744120637:9925280676298221133/130632158802
+qaddz:8437861/17969987688,54020652,-71865526/87734026923:970750451346170437/17969987688
+qaddz:4070024/3913628749,33427821,512282/796504041:130824081286095953/3913628749
+qaddz:81166629/3135890000,93859365,56814645/4127270728:294332644191016629/3135890000
+qaddz:75095946/6594060085,92035409,-11381306/3866199715:606887016968645711/6594060085
+qaddz:-6201133/708702298,47074908,22887883/94448148:33362095471537451/708702298
+qaddz:6027874/49969387,18501816,-9130290/81894907:924524409934666/49969387
+qaddz:13827470/4398317,50518578,62727273/34158559:222196734260696/4398317
+qaddz:-89138866/91998795,18780715,-35130848/77386067:1727803060099559/91998795
+qaddz:1174985/377026,86316466,16615749/3874669:32543553085101/377026
+qaddz:-9292539/4656085,1624786,65325863/1600219:7565132430271/4656085
+qaddz:-2336639/845282,-4069510,8089655/167446:-3439885888459/845282
+qaddz:-31078338/91681,89417696,2569245/159973:8197872708638/91681
+qaddz:73383631/12053,83445739,19141505/6087:1005844875798/12053
+qaddz:22853974/63407,-85636132,-6290341/12816:-5429907367750/63407
+qaddz:21369191/1915,48981131,5257100/483:93820235056/1915
+qaddz:-45229274/277,6529852,80452675/6632:1763539730/277
+qaddz:-17600350/527,60401374,37082689/442:31813923748/527
+qaddz:85256283/467,-24966013,67067455/319:-11573871788/467
+qaddz:80505325/66,13054914,=1:942129649/66
+qaddz:-4197971/62,-58438955,9669086/33:-3627413181/62
+qaddz:45758807/4,-88423268,27591403:-307934265/4
+qaddz:48139065/2,43301388,-36531779/2:134741841/2
+qaddz:-746260196/20472817142129557823,982354175,32526895/10440994669702430816:20111557393582539517581700829/20472817142129557823
+qaddz:-29549747/14838788589925929214,634211818,-74451525/12916990835817929011:9410935088534580052120701305/14838788589925929214
+qaddz:-448318501/7278955030505777603,769108616,=1:5598307029438536391798808947/7278955030505777603
+qaddz:59483976/2793541975287617267,-163303460,314082880/1773468794441614937:-456195070219702394797359844/2793541975287617267
+qaddz:-39988340/60152702435264949,648519691,73804544/228852852664255579:39010211996132972188622419/60152702435264949
+qaddz:-729061405/768059604671461839,714606502,-471314823/354142770917954234:548860387421776203265215773/768059604671461839
+qaddz:-248555917/7165349396837386,582365762,-82300902/5346138197190155:4172854161485444439422215/7165349396837386
+qaddz:543269507/64494661180201173,690548092,897863403/18149141182810736:44536665222174388734581423/64494661180201173
+qaddz:318338239/8630148497550833,845781111,-235304841/3148342727645078:7299216584353524632053702/8630148497550833
+qaddz:859971543/1629667855750118,-528676738,-821484768/9266342092322843:-861567486001426067383541/1629667855750118
+qaddz:-374749715/8438356773884,291407771,-932095108/907679125024843:2459002738379912702849/8438356773884
+qaddz:-105904217/719249349028152,954350873,-483804897/722878772519704:686416244149698456872479/719249349028152
+qaddz:215809489/24453042701551,949038292,509810695/60521395527768:23206873879683242600381/24453042701551
+qaddz:150432367/67777562170303,451848420,463171069/798174121745:30625184378103331903627/67777562170303
+qaddz:-8493914/1778903924623,-83428918,=1:-148412029657258941828/1778903924623
+qaddz:147732646/368561418133,316756885,462378256/2791638842869:116744366739139328351/368561418133
+qaddz:-66012899/43799234004,-321281986,982505097/911502425047:-14071904886149864843/43799234004
+qaddz:169940076/279466336907,-71525240,15350688/150338991023:-19988896819024092604/279466336907
+qaddz:233355217/32843819415,72601264,-758317611/7873649159:2384502804350095777/32843819415
+qaddz:285149260/19453167983,144991594,-201126001/42622707256:2820545834490084162/19453167983
+qaddz:940581418/5616720353,-615369286,215195096/2354964241:-3456357192346696540/5616720353
+qaddz:-396923483/8795362315,114388371,116424557/500425708:1006087167170715382/8795362315
+qaddz:43457937/310448072,540792846,48194518/73220787:167888096435550849/310448072
+qaddz:428882054/550113049,-311285439,56137087/291468974:-171242181528711457/550113049
+qaddz:-286703423/15020682,237972794,95770627/88535037:3574513376622085/15020682
+qaddz:-672536805/72578564,-454083180,-450947664/92210965:-32956705813490325/72578564
+qaddz:-842687259/2802968,164043467,877832687/5847351:459807745922797/2802968
+qaddz:9656746/198233,-84422497,=1:-16735315191055/198233
+qaddz:236817273/916726,899428028,-92124131/51259:824529295213601/916726
+qaddz:-32742959/6896,967049226,-375835070/139297:6668738719537/6896
+qaddz:46021278/1013,797203137,559435694/97037:807612799059/1013
+qaddz:495550757/63198,245997332,948028412/39911:15547034938493/63198
+qaddz:-760591485/8548,-293617711,573012945/8054:-2510604785113/8548
+qaddz:268239779/2820,-917135865,-106555829/892:-2586054899521/2820
+qaddz:301095018/37,-382369768,-77751485/296:-13846586398/37
+qaddz:3850763/277,-710988721,-86297861/101:-196940024954/277
+qaddz:195470025/41,-660449973,225753766/29:-26882978868/41
+qaddz:375745961/37,910651525,-88347614/45:34069852386/37
+qaddz:-91575821/2,869025199,629588221/2:1646474577/2
+qaddz:436219553/3,113713165,=1:777359048/3
+qaddz:-844868513/21771218036213010780,986546099,258641158/22466107297036584855:21478310224104386517209078707/21771218036213010780
+qaddz:833503855/8069616060533418368,463027937,-193589362/1951752452419151303:3736457676890855827326450671/8069616060533418368
+qaddz:724738643/11366387107722525,376750281,4819705753/4712039757409798110:4282289536789239288518168/11366387107722525
+qaddz:508814249/2088448235503890884,845043285,6799873277/8328817117516288610:1764829157482661583405728189/2088448235503890884
+qaddz:7996084039/717257384492120308,2419507504,2667813745/128249445552768127:1735409624078098322072875271/717257384492120308
+qaddz:7585030779/180538136040165892,489184216,1064881163/655356926166745922:88316406536909903972991451/180538136040165892
+qaddz:3584540521/91456981705312186,-9911261646,=1:-906454075034784339973677635/91456981705312186
+qaddz:3050007448/41294095103098713,6024934948,=1:248794236732695102097529372/41294095103098713
+qaddz:5293029102/2042882846608867,1387341294,=1:2834175731904754348683000/2042882846608867
+qaddz:4856278727/7671234032065848,-4714174847,-826015688/342674325919645:-36163538519415207233046529/7671234032065848
+qaddz:-1287980783/264067516251600,-7283705114,1474901722/155847550710807:-1923389918563058318663183/264067516251600
+qaddz:-5319461421/224860303990304,7455512951,889923834/139644515373281:1676448908565503130965683/224860303990304
+qaddz:2092800065/39695887391801,-8479055683,1732884799/61967662266203:-336583639581176223855018/39695887391801
+qaddz:1206911087/46584702098976,-2120326658,1346835184/16267372805513:-98774785715446160391121/46584702098976
+qaddz:569792579/414501273499,-8640944572,6673457161/7160564523311:-3581682529327701704849/414501273499
+qaddz:9313961147/9034962045642,-4887430523,6725061071/3300706280530:-44157749276007915969619/9034962045642
+qaddz:-5240204781/952774687199,-8153058385,806610703/7522631755:-7768027652488799318396/952774687199
+qaddz:1072533129/47749905913,-2190169028,7000962285/325419804967:-104580365019494129435/47749905913
+qaddz:539059499/15953197306,2833840907,3868176763/46023931661:45208823123724056041/15953197306
+qaddz:674514633/2185964591,-3939960534,6112848571/51458323114:-8612614216586936961/2185964591
+qaddz:3187633456/3615599831,3078822354,3648967863/4642156796:11131789585989055630/3615599831
+qaddz:3613164783/790101889,5924355725,1093627703/4194434934:4680844653043629308/790101889
+qaddz:7839467059/761810399,3436300760,2070395267/976614917:2617809660899070299/761810399
+qaddz:225690899/491794201,4884762823,622206155/258312784:2402298029837480322/491794201
+qaddz:-7725783503/84500941,-1043559105,9836874767/38034734:-88181734087401308/84500941
+qaddz:1162986782/14963043,1957888112,-8677864987/68949839:29295965172031598/14963043
+qaddz:-2073053051/3932529,3953921935,9300508123/4505890:15548910600070564/3932529
+qaddz:-2553049553/6593625,6886901572,2612889293/3618567:45409643824628947/6593625
+qaddz:157807783/17000,4402443990,876550711/970248:74841705637783/17000
+qaddz:810075291/750871,-6494923353,1278293443/275880:-4876848782915172/750871
+qaddz:2989273314/56921,-2790577575,3360184275/44087:-158839476873261/56921
+qaddz:3268425371/11550,7335374991,2237230499/48036:84726849571421/11550
+qaddz:-3154163419/9858,824560371,4511685191/5191:8125361973899/9858
+qaddz:7027175150/7267,-5589392198,14743439/42:-40611085927716/7267
+qaddz:4661020509/730,-1409612732,-472504172/703:-1024356273851/730
+qaddz:550638145/104,3388785600,7616106439/471:352984340545/104
+qaddz:-2172843710/11,76395123,736231113/29:-1332497357/11
+qaddz:-6453196546/63,4130453785,-5670101997/64:253765391909/63
+qaddz:1769225059,-8164754222,1531642609/9:-6395529163
+qaddz:7580730244/3,-8295939153,-1516372895:-17307087215/3
+qaddz:58423769119/50643850140797602406,90335026336,=1:4574913536225388721450090733535/50643850140797602406
+qaddz:-42124546066/6087273228356965143,-24064378632,75472938387/29014055899155453086:-146486447803619008497702570442/6087273228356965143
+qaddz:85077906583/7059686186393838266,-86403115965,=1:-609978884239495412773574610107/7059686186393838266
+qaddz:2409771251/78123085616637683,15985845324,=1:1248863562901179163797515543/78123085616637683
+qaddz:52223576739/412739442713673226,-46190346315,31453828195/12849072264316598:-19064577796804669642459685451/412739442713673226
+qaddz:-44585554037/157326507974173406,59214099831,7574929311/32876530728519241:9315947549245321588003740349/157326507974173406
+qaddz:-47861969231/60513239361297573,-63013076957,=1:-3813125408790805542688294592/60513239361297573
+qaddz:-31901636875/33882731297200408,-55696719345,31284269910/21963113061657589:-1887156975702218940497129635/33882731297200408
+qaddz:1727465561/671724526279818,-68558893487,=1:-46052690249823572892279805/671724526279818
+qaddz:17391142729/435638497115449,79866074338,=1:34792736595117065793390491/435638497115449
+qaddz:-14607124051/752098365273835,79819155439,34961447441/234817885230781:60031856323210021057514514/752098365273835
+qaddz:-33882594912/853897505052767,-69441770727,68892865654/360632311106545:-59296154770231603933546521/853897505052767
+qaddz:56393173391/95959531164605,80334900495,=1:7708899387655450534152866/95959531164605
+qaddz:76008103374/82690250931395,-41801579607,72201983593/77462511255258:-3456583107031437979958391/82690250931395
+qaddz:42873865571/227802171757,96248926412,=1:21925714465976151611455/227802171757
+qaddz:2188733045/317649531592,-27294537694,-13503437379/778368702506:-8670097113517099095803/317649531592
+qaddz:-40936176209/483902341255,59864812412,-30132933091/131952074240:28968722884917247480851/483902341255
+qaddz:29030847755/204795623153,98812754244,=1:20236419580893256259087/204795623153
+qaddz:7022832233/85729381270,286720337,65140586861/51219438458:24580357095558720223/85729381270
+qaddz:83478631598/83831440713,2447203008,78651932717/87841022347:205152553961305896302/83831440713
+qaddz:70410742832/4854173541,25635871440,41240688913/9691426040:124440968914936311872/4854173541
+qaddz:13133061735/215660389,-54580960568,73195756378/2318826503:-11770951174955479217/215660389
+qaddz:97316922721/33728456,49150998791,-43302763720/346667451:1657787397395219417/33728456
+qaddz:42314512205/91048434,3019543575,=1:274924756213023755/91048434
+qaddz:9911778891/3761798,99193069336,84599064764/16160639:373144299753805019/3761798
+qaddz:22143440303/71908,57401237223,-44550917147/46946156:4127630309671787/71908
+qaddz:13575690632/9774495,-56625307968,27090428376/1406293:-553483776030985528/9774495
+qaddz:65452607896/5739831,88854202629,=1:510008172182823595/5739831
+qaddz:-48594032321/296227,26116980382,90351957100/631949:7736506153586393/296227
+qaddz:38854983873/478381,91268688211,-37086942845/919397:43661245190050264/478381
+qaddz:-3289168101/2633,39943120731,86275372528/65091:105166947716622/2633
+qaddz:71226110755/74802,75928864342,-681828710/6523:5679702136621039/74802
+qaddz:-11750464340/9973,3631010522,-10917246741/3869:36200317471566/9973
+qaddz:15180336658/9543,75388205179,42003176179/4581:719444822359855/9543
+qaddz:37691546351/502,-21661824585,-16098775076/329:-10836544395319/502
+qaddz:-35885239812/857,34474662009,=1:29508900101901/857
+qaddz:22416794298/37,77595160739,19551745221/79:2893437741641/37
+qaddz:6506889348/5,89218535043,42795404175/52:452599564563/5
+qaddz:-17539280423/2,-76893365070,11913582381/2:-171326010563/2
+qaddz:-18732975933/8,-68638332129,=1:-567839632965/8
+qaddz:752606019983/39088539215799132539,78330421475,375459572044/17732255158454998643:3061821751615612031471862895008/39088539215799132539
+qaddz:-87137756962/6035494303898759827,-609859506482,522818453593/79286344644150136171:-3680803577550619796673205455576/6035494303898759827
+qaddz:-421506353201/1519073638798046220,841569835268,206505393657/3285765743903619005:1278406551963233090464143733759/1519073638798046220
+qaddz:313227767819/3667276491812736850,-527972639267,112687878130/8071994431605454933:-1936221648304195391507820121131/3667276491812736850
+qaddz:45625693955/874183546628376789,86870332839,316926200883/622490420207251454:75940615657984567948357767926/874183546628376789
+qaddz:307191711010/592741905927742817,469188479690,640816126728/494995852882629881:278107673690790651608739597740/592741905927742817
+qaddz:-15083287151/7156847089669175,536288677413,-968335381430/55030206560476363:3838136060165760061381557124/7156847089669175
+qaddz:494377643469/98558071038934628,454517393920,719586404719/50508704469542694:44796357598398794466182305229/98558071038934628
+qaddz:45709637656/3099309256090823,-330553962257,-99912647867/433025093788036:-1024488954860616607596429855/3099309256090823
+qaddz:-666357878153/2095670070843359,757413983851,=1:1587289817194775273218717356/2095670070843359
+qaddz:126425902111/416943810772372,-678980645165,678919705009/106535794783049:-283096777635778691091479269/416943810772372
+qaddz:585263176259/851781334135526,22092528056,485539073651/458880186297433:18818003021966803924493715/851781334135526
+qaddz:-873682780814/76616993618553,693272108938,956115786575/5882428371192:53116424746422652551145900/76616993618553
+qaddz:304885366516/59327405229613,446589528583,-184321844164/42141769957411:26494997933545783426894895/59327405229613
+qaddz:227263949507/3005012215064,-970992420883,944562884485/8363349411634:-2917844085487752336832005/3005012215064
+qaddz:256051015589/5849799282523,145771147218,425125619888/7082715872863:852731952408667058486603/5849799282523
+qaddz:922332758083/714594213406,203681203456,751751042693/26386109479:145549409370150101489219/714594213406
+qaddz:54459784009/28808646278,-878737718814,-508120353933/475490279255:-25315244112394691890283/28808646278
+qaddz:-75343229837/18301076728,-18822576757,-5004528638/1010757283:-344473421523869640933/18301076728
+qaddz:455494735961/31781276434,112071922031,-828539887333/78026709049:3561788735012400453415/31781276434
+qaddz:970291731117/7275020519,-637559590581,=1:-4638259102591722400422/7275020519
+qaddz:-982813942861/3854475224,783494985089,=1:3019962007170985992075/3854475224
+qaddz:892057818224/861585953,-595915633524,-949622564162/410937589:-513432538125316470148/861585953
+qaddz:292775249633/706174681,844137005926,193717693265/82462566:596108181172863409239/706174681
+qaddz:-4493924646/5798807,-582307144826,-746783726287/48847174:-3376686752060947228/5798807
+qaddz:-90281739197/55430389,586184656508,420537839926/78274081:32492443445788082415/55430389
+qaddz:-53911496672/874759,873541937929,=1:764138618169337439/874759
+qaddz:994025741513/6110189,974615575614,-72802324373/849950:5955086363371072559/6110189
+qaddz:624261056662/482529,-97311267314,=1:-46954884244700444/482529
+qaddz:-39993733292/46881,-841794041874,216763126337/306248:-39464186470828286/46881
+qaddz:792871375475/84839,12838795021,=1:1090023402162094/84839
+qaddz:54064516459/38317,126266853725,=1:4838221098697284/38317
+qaddz:157148550179/2580,316644803876,=1:817100742550259/2580
+qaddz:-892971311861/9503,293701366371,267061134465/5464:2790151113311752/9503
+qaddz:56861735925/22,425609853419,=1:9420278511143/22
+qaddz:975604652373/62,798330121028,9837445133/3:50472072156109/62
+qaddz:301936419421/8,401226430058,642908142507/92:3511747859885/8
+qaddz:960812431491/91,821665693935,184158030746/25:75732390579576/91
+qaddz:-288196323271/3,-6851210649,=1:-308749955218/3
+qaddz:27950016152/3,811526852805,=1:2462530574567/3
+qaddz:-1239949810170/37215316493340542309,5084146392476,-296516594614/47057875211140309013:189208117094469900857215847456914/37215316493340542309
+qaddz:-9982761144683/86065596803955058468,2050494075451,-6484572703254/4884291350957415781:176476996346664368103513547324385/86065596803955058468
+qaddz:6263655072498/2824969489983333169,5441993837821,2221750454035/2194218699041801277:15373466556521632295955651057247/2824969489983333169
+qaddz:-5989792323571/836318289746974211,-2931974130042,816998017476/3394736245988200951:-2452063590019098006588326670433/836318289746974211
+qaddz:-7698578874730/344070437345848791,6704395369109,=1:2306784246788816955726767522489/344070437345848791
+qaddz:4466480763133/830946743248529621,-996598272615,=1:-828120088956544529460779865782/830946743248529621
+qaddz:4485142594172/49082393942890253,9197604183793,-4770331797107/16903008398062353:451440431879703596984582863801/49082393942890253
+qaddz:-134312893516/16006607498131703,-5249882281532,1583762956049/37750476556875940:-84032805091878883507373502512/16006607498131703
+qaddz:2427070778131/1995258741120055,6244907615189,3514628161072/4284871651689771:12460206506693051427861293526/1995258741120055
+qaddz:5325619193316/9866683016060977,4027295598641,9237993735817/7374034428483561:39736049083768285110593525573/9866683016060977
+qaddz:4506791224955/98740859078376,-2433647151513,7230124153235/24547192761813:-240300410434031792022757933/98740859078376
+qaddz:6263613039105/662686345538291,3241626331560,6974592366933/417432893529050:2148181507262199091454803065/662686345538291
+qaddz:-1811100007460/13795113510661,11776226228,=1:162454377540672125809248/13795113510661
+qaddz:1928373998137/24092133222096,101879503692,2556288163059/81191221300450:2454494575550613661976569/24092133222096
+qaddz:247425249267/4299310767884,9656652793497,6941336412649/1087093561201:41516951336799008176899615/4299310767884
+qaddz:4375335748035/3738750520588,3905049802371,723270679177/5043873825535:14600006981541018102462183/3738750520588
+qaddz:7794911344062/83950994789,-8243600514425,-2603543493997/10276127701:-692058463821295982987263/83950994789
+qaddz:-3095785250121/322417942963,4195151544235,-8472000440819/880146461714:1352592131307205816218184/322417942963
+qaddz:-4517167531751/11212303539,1754468949877,5238909223466/69391666005:19671638411254333182952/11212303539
+qaddz:1112980425235/45979665716,8827854965263,2125854079037/42150601594:405901820293236512448543/45979665716
+qaddz:563381672458/1066429293,-8418949099715,=1:-8978213935648672279037/1066429293
+qaddz:2857062479357/2065941250,6427518036538,3720687400259/8823089384:13278874649659923871857/2065941250
+qaddz:6660515562878/864868567,3023828885557,-2827547445095/772367393:2615214561765405149697/864868567
+qaddz:3112189653770/430887893,-7852737661995,-86959631083/81894801:-3383649582346582072765/430887893
+qaddz:7683412484443/95948152,1332390320090,2759996778764/6533551:127840396638736458123/95948152
+qaddz:159684374850/3723623,-1974161463836,3321588400449/53889098:-7351032872769022978/3723623
+qaddz:6040625454008/1761191,7333833752524,=1:12916288041066950092/1761191
+qaddz:212485296160/215857,2626911385981,255098287490/595687:567037423528996877/215857
+qaddz:-954041238820/149351,8462499450675,-3418839060974/6081:1263881801416523105/149351
+qaddz:2631178437270/289589,4915496549364,-7382060007604/607303:1423476361412208666/289589
+qaddz:-4190078661321/81307,6205900529843,-4545813476917/72302:504578964301283480/81307
+qaddz:3075448966277/10503,8355956941265,3979238326369/89488:87765691203072572/10503
+qaddz:-4159327490855/1442,9824287076936,-4853919949437/3400:14162462637450857/1442
+qaddz:2105555375170/7889,5827815981584,7350815564091/1621:45977745834091346/7889
+qaddz:-970057756335/134,5386054563891,90106168024/673:720761253805059/134
+qaddz:705786323151/74,863825635194,-8448597370801/341:64628883327507/74
+qaddz:677223680197/15,1191619181913,2784760197168/47:18551511408892/15
+qaddz:1250102070269/12,7296468619064,-8785308120663/49:88807725499037/12
+qaddz:815291444846,-8875650934350,-9869792677199/4:-8060359489504
+qaddz:8187166853148/5,9378339124723,9909614166843/4:55078862476763/5
+qaddz:5422808604175/4005553410506916322,59300928198551,=1:237533035191931723527928367253597/4005553410506916322
+qaddz:10175385793742/12145808688724905047,-50946207146217,89160661571041/31082940158416923936:-618782885414101287608920784463457/12145808688724905047
+qaddz:-66447228282594/5132267228812337113,-55179117587940,46405635667194/2000839741729635683:-283193976911366915176041931499814/5132267228812337113
+qaddz:5047791146973/4721169311443187453,-99279491905591,13672396382858/7559676837928609713:-468715290440348563665526200602750/4721169311443187453
+qaddz:29394169412845/154033282520525053,-29623023279395,9504860273065/124604054480863853:-4562931513907140557523146770090/154033282520525053
+qaddz:4067070745921/152576293456659409,771698149382,82888271738589/108217943144539550:117742843300069025816248581159/152576293456659409
+qaddz:75868597092083/18545709845595165,82562069353348,62428349184891/98682364625908466:1531172182479096917186342454503/18545709845595165
+qaddz:38258707804725/80482758393493951,26694314420345,16108158643166/21949554170590857:2148432057972588200266536637820/80482758393493951
+qaddz:46555640927056/1709747501026629,-16128468753166,32141736958103/3736469425292601:-27575609146111592776953130358/1709747501026629
+qaddz:45370445351363/7110877719431711,86735990625964,-33565334246797/6384179688851649:616769023215005197115686895767/7110877719431711
+qaddz:9475910636228/981744732543279,96180861167731,=1:94425053822896329193346366177/981744732543279
+qaddz:91004040702465/936897618249146,45878038637853,=1:42983025129746861152661226003/936897618249146
+qaddz:7213181652898/7450266621563,23288667968005,30404125827566/4549937716875:173506785622698280708744713/7450266621563
+qaddz:-89229843161908/67491130269077,87276718571732,84273766896387/35434923631324:5890404382582247110442769456/67491130269077
+qaddz:6912185841959/2387122535810,95367158366052,16820307441286/172628433269:227653092911770818644164079/2387122535810
+qaddz:18631413455311/5393632894857,30541536678945,67884298820845/8941925270968:164729836891057997564141176/5393632894857
+qaddz:95264142661666/640329051433,33493375919635,26112952504575/900465490172:21446781632004027732248621/640329051433
+qaddz:26873236385920/167838163737,63857215148601,48278558616779/606456030301:10717677731926604660867857/167838163737
+qaddz:4401103056499/2897755980,-11052252274481,89598593400912/9441413885:-32026730116444816089881/2897755980
+qaddz:1318889016693/4307161820,-79377185552021,28715124462201/59240718095:-341890382987401586021527/4307161820
+qaddz:76790810847961/5450577611,68261418218311,51631448908695/2088035198:372064157912624257682982/5450577611
+qaddz:21126534617963/8738346544,57900812244090,-48117757406954/4100802105:505957362589063270542923/8738346544
+qaddz:54005121935732/492299853,-95310437087251,7343525049871/87207576:-46921314113414293538371/492299853
+qaddz:65465816406636/92490709,85963247914764,=1:7950801813045110334312/92490709
+qaddz:-1567974419029/2146031,73885253968091,=1:158560043890421877792/2146031
+qaddz:76063102421737/23698475,94901902098254,36870175818609/29433536:2249030430391022384387/23698475
+qaddz:21982490259259/3028082,35729075461978,-48666061360318/4739221:108190592265547525455/3028082
+qaddz:44090802588674/2725087,-59617101535954,4729707469385/5642703:-162461744282505689324/2725087
+qaddz:31794415201437/483367,88454206922687,23449145143186/104191:42755876432013648566/483367
+qaddz:21120858803723/196745,-97469888172037,=1:-19176692027548615842/196745
+qaddz:6353568582461/36133,71560599712641,-9946843698401/1669:2585705502985439714/36133
+qaddz:37008170564675/36399,98738162943972,=1:3594007401168201503/36399
+qaddz:-19046004662298/5177,97280021451374,27910156790976/751:503599625049100900/5177
+qaddz:67988194828572/3833,91182292091517,8505334994139/1301:349569713781613233/3833
+qaddz:-27835175210909/97,-86045963939656,69384812566415/607:-8374293677357541/97
+qaddz:-66933996037605/499,-26758226932551,44077986933749/138:-13419289235380554/499
+qaddz:-69719056900661/20,19918523107231,=1:328651405243959/20
+qaddz:9273298009097/11,72385368670495,71790012014913/62:805512353384542/11
+qaddz:21941955990125/9,52544189533470,-12392727415391/2:494839661791355/9
+qaddz:-6780461974136,98345436504870,=1:91564974530734
+qaddz:-84540612076693/19951779938951892435,-646908420217313,96551072703477/9551882373716321942:-12906974440830846345093795912803848/19951779938951892435
+qaddz:-83364626051404/25732505849792137517,-259790031036174,=1:-6685048493356028415791438435591362/25732505849792137517
+qaddz:-897066937584389/9348251282430626623,601658334644890,=1:5624453298429168053199845947322081/9348251282430626623
+qaddz:-205588700127652/1395648197045308621,722142436485815,631381416931617/2014178604201247978:1007856789491333998582718663583463/1395648197045308621
+qaddz:271688711340751/180941683917606723,-804877924901239,356634127117981/581970885207340397:-145635967079739188257214306089046/180941683917606723
+qaddz:-150593304294442/751040562206456283,-252704334790286,580538958605443/761261694295334982:-189791205672904947390115336361380/751040562206456283
+qaddz:-33791007514234/9931544134782813,644114592405109,-28689348856389/27441863478469573:6397052502328982483214019077383/9931544134782813
+qaddz:571363848651239/66311445792999286,-10840446958246,29259414259102/2538648211395449:-718845710843613051916101161117/66311445792999286
+qaddz:911329771312150/9119213968348277,389930802134286,44063137011973/945363924228012:3555862417512229944211542037372/9119213968348277
+qaddz:304065915990821/6933490862650654,-179336341462285,23446882001027/1428507361849985:-1243426884869950368991555593569/6933490862650654
+qaddz:13794668675671/40367472899842,-309167092058184,502787291762833/565691523820858:-12480294210181685647999731257/40367472899842
+qaddz:-67226439568370/155342790290953,-999058912984495,463385115124522/611519522742283:-155196599208057935177067342105/155342790290953
+qaddz:959309013745217/47174481901345,384897898127779,=1:18157358929095601304695707972/47174481901345
+qaddz:65775323516640/39878078972149,40619665002388,983890817704139/3521649399512:1619834208787531337994008452/39878078972149
+qaddz:256671220274850/66938758003,-730244708478110,930955533204827/6929373391761:-48881673823530816492539480/66938758003
+qaddz:-893936101636063/827048331634,597691527840677,-126588969738553/668190758507:494319780931514439309440155/827048331634
+qaddz:234866720760362/249576871361,816339748530719,745271148727983/265090084030:203739520406157211340598921/249576871361
+qaddz:21197614731825/513159868888,-383505627380083,188859267143231/81431113864:-196799697464152377607825879/513159868888
+qaddz:964492287424130/65578382813,954893437672646,-807333982742123/64002138636:62620367402282827454057328/65578382813
+qaddz:-177007104279849/1974354920,357812362625802,199235392833781/39880047906:706448598410069193365991/1974354920
+qaddz:91059156010499/3926511496,80812106334647,889997682906405/8258270479:317309664630025024612411/3926511496
+qaddz:451880285884181/1898972562,396985801563335,-25588857743575/1369245348:753865145124230156098451/1898972562
+qaddz:-31366502392369/134800936,883517312779341,385458521261359/159439811:119098960703493425870807/134800936
+qaddz:-10128482818698/70545329,960042254669295,158648344293111/128796202:67726496699418719154357/70545329
+qaddz:335395247847445/29367757,-244136374073097,-48337710344902/5085513:-7169737373244565085984/29367757
+qaddz:122530580993759/16204629,960637241145668,=1:15566770218879665890931/16204629
+qaddz:817780076457530/3494021,283630218235935,3662113752156/4047877:991010756531016302165/3494021
+qaddz:-217463590706488/7914657,312381371588143,-746462040054419/4436039:2472391191846106405463/7914657
+qaddz:100306351636824/211229,-198763366297580,-307504584166445/361449:-41984486793319888996/211229
+qaddz:144895746707409/536491,670873254269860,-454046918862603/780899:359917607952238168669/536491
+qaddz:334763841889403/29410,-358386406501860,411931926070123/15800:-10539809451377813197/29410
+qaddz:177232274198821/12516,750894264493456,79990853919389/37735:9398369846674294117/12516
+qaddz:179909139835812/1979,408538585432232,499794975465566/4363:808677769710222940/1979
+qaddz:374051483837827/3284,-984497815753029,=1:-3232716775449109409/3284
+qaddz:72651383395505/137,180883369883715,=1:24853673057464460/137
+qaddz:-795240710923177/87,-266514612085555,-145736783502361/320:-23982011962366462/87
+qaddz:293684182859578/93,-548418457694218,115702982878171/33:-50709232382702696/93
+qaddz:-775889557419502/17,435575409934841,891608394581532/29:6628892411472795/17
+qaddz:298220230000324/3,766606056221642,-153273190527374/3:2598038398665250/3
+qaddz:249679021051517,393498225268690,=1:643177246320207
+qaddz:3542672594684587/23493960223203744626,-8259187214851748,=1:-194041015901719887360631082447021661/23493960223203744626
+qaddz:6602377363368086/26756588963267146371,647903723659326,-14331599050621/14088246371426023870:17335693621722809158754291144574032/26756588963267146371
+qaddz:953643270036373/672267077222382067,2730834301717412,=1:1835849994394189222848787000486977/672267077222382067
+qaddz:4732337125860764/6964537546610955687,1462613230096260,1598512177911468/1847092196188952335:10186424757175331839719046730291384/6964537546610955687
+qaddz:392871539920454/124667933854771591,4222301184211601,4921205597352118/360784888091913307:526385564748215632593338807347645/124667933854771591
+qaddz:2490987481558645/273236967005544791,5809366131098920,-8409430808361398/118474537825945987:1587333581886205001306049593284365/273236967005544791
+qaddz:4255269445550164/45737089432737585,4857866077021042,1465698613834409/6912785090125613:222184655216973491505517154813734/45737089432737585
+qaddz:9210797969401333/8163980149744856,9750466506961289,6445568175713494/15481234020450335:79602615013584036398759188280717/8163980149744856
+qaddz:414318154924738/4286466178431057,-1529884082696356,=1:-6557796377397951866564056203554/4286466178431057
+qaddz:1482835316159491/9227279017181664,3761016398994804,217567654667999/4259451401870992:34703947701720897607169976233347/9227279017181664
+qaddz:-859552591107487/51274074663284,-418382458987624,-4461813189832442/202453728783091:-21452173439940648539914304703/51274074663284
+qaddz:651597097619645/119852979164632,9814527719768623,549507364552128/130838602558483:1176300386308132636435962561381/119852979164632
+qaddz:3062835747588459/29244354985217,-1153612952589391,-1697694605519151/20613920170229:-33736666701065396523928444388/29244354985217
+qaddz:-3555234895468573/82553845875899,9556279680346194,=1:788907639878281506316585509833/82553845875899
+qaddz:-3430655994829779/1022475878060,-3861606915733328,23919352405729/346214612268:-3948399921890433631600813459/1022475878060
+qaddz:8941063770802759/6431761572186,-9248680430430457,=1:-59485307385862346247287666243/6431761572186
+qaddz:-1458085892513495/865768190522,2913463648461976,2967255557005217/183961790972:2522384151079091183948077977/865768190522
+qaddz:309596223775083/196561317238,1984332827634766,-56866515384243/60782960375:390043074438804409147671391/196561317238
+qaddz:9692793587023183/17106658395,1171032202882506,9344415493288159/22347599779:20032447873948158050561053/17106658395
+qaddz:1297322765335855/78060494353,2404633388766311,=1:187706871066125196217477638/78060494353
+qaddz:8963645561434168/8924489269,421621279944751,-927728264088899/2108513434:3762754597412620773811187/8924489269
+qaddz:2904608103864485/1444422187,-8951359589722050,1306658433557061/999915185:-12929542392305138079258865/1444422187
+qaddz:-6451464021043383/499665577,-9753719382757790,-1838096568039957/168375724:-4873597829733219012638213/499665577
+qaddz:-7656575927425727/878618401,1131218876361418,9338726624701012/366586573:993909712673109853826891/878618401
+qaddz:4172728002376239/19479743,368831988655257,-6420008608192074/55268659:7184756521911324335190/19479743
+qaddz:6161530173305165/99639697,-1432201837180119,490175175009028/6720087:-142704150937940218278778/99639697
+qaddz:6918228969049918/4185569,-1641939400683084,-9043134997963566/4283597:-6872443737148726164878/4185569
+qaddz:1451717795705836/141415,-9179648440127908,=1:-1298138532442892403984/141415
+qaddz:8140278576768419/808479,112313592852123,1026877402176763/31094:90811321514068319336/808479
+qaddz:5643486834069101/530944,1715393818673080,4580531049699971/438581:910783699148393856621/530944
+qaddz:-1028760789941125/31581,6778845120322328,3983036171498424/29225:214081678984109499443/31581
+qaddz:185311071775543/30749,3825266581520702,-9282766742556431/28854:117623307426251841341/30749
+qaddz:6239950654595061/6550,297809616078377,958337836911634/1219:1956892935967964411/6550
+qaddz:1051395142542259/1190,5736372693566227,843234486155860/5981:6827334900486352389/1190
+qaddz:8170656479179803/377,1507295266275575,2218120930173065/774:576420971865071578/377
+qaddz:-2473414150338949/204,-9581413081720714,-4722755512692772/455:-1957081682821364605/204
+qaddz:-8681518748104826/77,-3407099061618709,=1:-271028146492745419/77
+qaddz:8708666762588363/78,82065604323195,16011547616829:15109783899797573/78
+qaddz:-9527121546851805/7,5686511086561176,-10800792278755:30278456059076427/7
+qaddz:-3156505883016239/9,8703260342529372,-186440241608063/4:75172837199748109/9
+qaddz:-29299633375857887/9525577839119524640,19394264263578925,11770323744387737/9435334262616904973:184741573875175155232312577746354113/9525577839119524640
+qaddz:45414752276742165/12207900549477852191,73340302679712901,-1762362316527451/5610201133037246999:895331121382539119649801382270558256/12207900549477852191
+qaddz:51287924597675777/9802415152761834211,23795752241231275,26808795167323503/4767990503572354769:233255842340811827381416634655824802/9802415152761834211
+qaddz:-11478523036790/4661848726590019,-92346960041294475,-99921528151340483/9725949381928447460:-430507558072968016697671897881815/4661848726590019
+qaddz:35557351930961/1508286209602511,-81125561093339512,267345760579243/34391099339971446:-122360565043349990608741738783671/1508286209602511
+qaddz:-4793426675094793/37007904105416450,60895517302185125,11894447435691093/106928191679495960:2253615464768995346344506445211457/37007904105416450
+qaddz:31586795072540784/44373236784764585,90702169150810719,18513292834106234/37597849772411799:4024748828620693789339255382127399/44373236784764585
+qaddz:-1049981287826468/21587060162890651,71326478095880873,17797674000912830/41386390390327551:1539728973862882607828674533591855/21587060162890651
+qaddz:7766969806666613/5323521507239637,-31539639298859404,=1:-167901948138058494538892792329735/5323521507239637
+qaddz:28336169012562031/1963339938986121,36117112871692963,6517543421786160/2515812174582889:70910170181864535729772042928554/1963339938986121
+qaddz:51605249327254279/329660326356162,44496912384848741,=1:14668866658630834332811390546321/329660326356162
+qaddz:95776204572834299/360483541928559,14896033753227230,-634271284568050/59231390665489:5369775008050814030088926295869/360483541928559
+qaddz:3199790617176713/2044034589474,61554085339919034,86943016409024831/69267518528772:125818679558232164197205824829/2044034589474
+qaddz:63207445866080934/73630340098063,62781346312315459,=1:4622611880790123804296516936851/73630340098063
+qaddz:-10562032121106923/7562195446113,2371574008330945,-12004106935992565/4243540006504:17934306165909664170696759862/7562195446113
+qaddz:74286029526835348/6426144147769,-56596118082865321,10556610079748403/5666686062526:-363694813004573972309622783501/6426144147769
+qaddz:7784837673853468/63315839471,36983417562905989,24368105233273509/482119525015:2341636129509702481462345287/63315839471
+qaddz:41230861520352699/248615826076,65301921451058132,21820151723088751/772186719402:16235091145946112952997802731/248615826076
+qaddz:7868735455391473/2376142635,24220945772157046,42112368834645777/38165511736:57552421917114088371647683/2376142635
+qaddz:16212068555703281/21768826663,22486544931183098,31430506824676803/88055986181:489505698872898192433045255/21768826663
+qaddz:18990156909977866/4288195941,41076064025528634,4353887544365053/451796487:176142211045518165608052460/4288195941
+qaddz:-52094180225299371/8295443431,97662863401423145,-9449635278901807/4480020195:810156758603891764016311124/8295443431
+qaddz:70121165050790582/884849671,9294106339201909,871866453377042/132524629:8223887006602988632012521/884849671
+qaddz:89800859106311942/275630735,48525545845357510,-21376168718994863/279135020:13375131957432945925381792/275630735
+qaddz:65595348623886377/41322369,78674639156794339,-7330652418059047/43068742:3251022535774253157155468/41322369
+qaddz:4765824965091103/13071190,9760309664863845,=1:127578866854096607216653/13071190
+qaddz:-6087229416296351/2127106,89049693910575358,21234009428205913/420191:189418132128118891157597/2127106
+qaddz:62215823394518468/8207157,27553281434116768,-10639236075124883/1311092:226134168810804865827044/8207157
+qaddz:-8994816719328305/35983,-81534831740246875,=1:-2933876845326022631430/35983
+qaddz:33370840040824831/471708,31379166699519941,-3805555942820402/57901:14801837336337193154059/471708
+qaddz:15270801632993512/43891,62114435487940553,91890892291173796/96141:2726279958802831805235/43891
+qaddz:52066031635427411/80207,79948554826885018,-32268139784894785/9291:6412485803031602066137/80207
+qaddz:30138851628256646/2271,8808985720955931,4132024812310306/403:20035345423919175947/2271
+qaddz:-48704579394955369/515,96280004013075991,96197516817859731/8348:49535497487339179996/515
+qaddz:-76138989019830581/163,-7824132792666947,84793723224519789/121:-1351472634224542942/163
+qaddz:14262406418152892/23,45957936069739248,60434066726939490/989:1071294936022155596/23
+qaddz:34014765103829171/5,12306267367411447,20552835074171214/59:95546101940886406/5
+qaddz:91849502756698141/20,-82945870135128988,79066927763083824/47:-1567067899945881619/20
+qaddz:21965479380351319/2,66229223349934130,-87992715521815677/8:154423926080219579/2
+qaddz:13175376582771327,80435538108007231,-11481476371288002/5:93610914690778558
+qaddz:233543544528899097/29308688028184850696,-313371565494318136,-546211686884835394/64310476577955517625:-9184509449976866806361166554956123559/29308688028184850696
+qaddz:615655938896447797/54625270368834900652,952119518403165605,-481883729818516183/20964479862538317110:52009786116217798007515677541374922257/54625270368834900652
+qaddz:-306096577466260199/1563899474881584021,-795305085572154223,-267651228746045877/3959443707942409072:-1243777205696945233963124085010730882/1563899474881584021
+qaddz:303249287074462526/988120532724227499,996970552281399322,-597979414385274083/1415816308850447338:985127073230663601717735166266818204/988120532724227499
+qaddz:952339724809160651/584399533289204739,-621203230425875224,-89809265051648755/476952842063426958:-363030877938627789190802770194325885/584399533289204739
+qaddz:-165153711870868787/63787766852635668,255678391566014218,=1:16309153630469804511357374991058837/63787766852635668
+qaddz:-170282783383418995/92637597632923627,745590434716695858,727513707271968617/97034490370058355:69069706690241882092088302517817971/92637597632923627
+qaddz:402676307184383008/54079780485931177,-833124989932029446,616876399608513026/73463803299685963:-45055216572867773936309791509054934/54079780485931177
+qaddz:638546632762921290/5700920505461219,866490174226616488,=1:4939791602029182823423545032900162/5700920505461219
+qaddz:490462229342420061/2997315021629032,-794115458808160581,-232736090223412025/6604604996597921:-2380214193593530011634172725167531/2997315021629032
+qaddz:989191334948063646/238829798613001,932376780689163706,-297260947715156566/95515827924885:222679358763432156823484377005352/238829798613001
+qaddz:733917544080141979/846584851419104,-407471079015324208,-856462825746108845/144065790220028:-344958842885769496528467364727653/846584851419104
+qaddz:-776150844455451188/60437639060267,140648215789491479,110557086596050071/2940144395374:8500446100355055871518908513705/60437639060267
+qaddz:40423809761966727/80515282319291,-896056243874632922,993643995036126943/67717664005426:-72146221449529496100479662331575/80515282319291
+qaddz:241416851638718491/3382660773031,667600506773221104,972636880608985845/976751193229:2258266046317632867918161964715/3382660773031
+qaddz:-311949759477562509/5272945258477,790859608208962462,=1:4170159421226114570459102727865/5272945258477
+qaddz:901115730770569756/737757545883,-294335029298267342,=1:-217147888881589502127194883230/737757545883
+qaddz:18952440190304626/427387361229,-871562962990980105,43270210830528697/42201089691:-372494994897624619964197044419/427387361229
+qaddz:368767126618980087/13867934102,408207198365664686,-388533375692412433/38881769599:5660990527265847091495502059/13867934102
+qaddz:185955534050890250/81788514027,9078725197697519,6436386921261961/22246601990:742535443365117414885489263/81788514027
+qaddz:82375478298045903/9517446343,433517004473691938,-26962495372093825/2304101598:4125974828938829453324728637/9517446343
+qaddz:44007143033079188/7383992497,504540760833169168,449177596957809274/5425450729:3725525192466799748276811684/7383992497
+qaddz:224818172747147/390111499,962172118291046785,59451455054756859/215170474:375354407362750397748227862/390111499
+qaddz:666309089683814939/682581559,-650419141072050333,2300719817124450/74245723:-443964110650091957941794208/682581559
+qaddz:542166078934696959/86595368,203399832612491739,620419080726846107/28244360:17613483898383202470361911/86595368
+qaddz:297894210502629889/46145547,12817895959056372,-291344707530390547/39774025:591489118313956392405373/46145547
+qaddz:715463509593675473/5054643,203255281666377882,=1:1027383602151494890281599/5054643
+qaddz:-658143668234554099/5196064,-351454032197965311,885876617433980026/6310607:-1826178302502356660290003/5196064
+qaddz:-864175272258886331/214462,-113193172511339576,664419730196309649/256429:-24276498338399167034443/214462
+qaddz:554632290831706045/878862,789543599984323318,=1:693900422001713191610161/878862
+qaddz:150056203172522033/10088,195421727932292330,-430213757895224789/5107:1971564447584137547073/10088
+qaddz:649664968382611201/15350,341314581999530333,172494507042296540/811:5239828498661173222751/15350
+qaddz:5864597320149566/905,489601633652276174,975732764347807769/9424:443095343052630087036/905
+qaddz:-178366641538470155/6144,334923469737215876,171402458096874349/1678:2057591431423915871989/6144
+qaddz:783919995622849413/623,278317030520011920,784978030394811864/577:174175430009590275573/623
+qaddz:-749742866135544447/698,79278627691587063,696350994873672899/683:54586739262592225527/698
+qaddz:344612331720575876/25,384322240275621066,-573701559443193526/77:9952668338611102526/25
+qaddz:99948350225973980/79,433526372044256631,233613544663506071/70:34348531741722247829/79
+qaddz:-813485941375813961/5,-73645253545358755,182695807997160858:-1181712209102607736/5
+qaddz:109732737408333914,661611874779880732,190730815184312667:771344612188214646
+qaddz:4439294254467838396/7399413423727575529,-375832621848838675,572455588779808659/2231006844433926946:-2780940947183026582974366027530945679/7399413423727575529
+qaddz:7401374720469772972/86040177417213246183,-4800899289575736825,4427571953719739521/79545327171368379:-413070226637269428522568343871874016003/86040177417213246183
+qaddz:-8281164336639608343/9930865450361852117,6652240436187019086,=1:66062504715229724855994090627548896719/9930865450361852117
+qaddz:2289593814998925046/2242678823806551791,1233211911037543012,8805138183115340751/6847414846976791820:2765698238149906948783491675567059538/2242678823806551791
+qaddz:58801253288456253/38080076339475325,4579333826855732576,-4512504820594295629/667425159645398768:174381381710607976743900573639143453/38080076339475325
+qaddz:1716963717527421640/225107768198324627,1976152916296866074,-8003061483125113466/474882649845647945:444847372606198139049564734922426038/225107768198324627
+qaddz:1034271517993599571/34228782689291755,7928647196076102620,=1:271387941894551313583006246493497671/34228782689291755
+qaddz:-43641059638095731/1029053223531219,4223820009592786988,4164140830282395355/41576160555557154:4346535596487121765588673396882641/1029053223531219
+qaddz:84297032713892287/207039580865947,440521401243831520,-6509343821181533355/9783431747165674:91205366276002625631486487141727/207039580865947
+qaddz:-100413440983654438/8617388967629029,-6540040006542842669,=1:-56358068600234775154346511687892839/8617388967629029
+qaddz:1601279569975518578/576041083643833,1520282279789457956,=1:875745051894437875280462407703926/576041083643833
+qaddz:1171909659900623927/396276655723830,1432202312057184673,-8716463823146798000/535782069662653:567548342541959482379720697481517/396276655723830
+qaddz:4919734080771991528/21359215600941,-486806183295567418,9601757988490006002/10830396257143:-10397798224876307889797677748810/21359215600941
+qaddz:-3738648400400330743/50301136962499,9954014077000284556,8872351197089153189/16636866534142:500698225413830641940352100534701/50301136962499
+qaddz:167898860851405426/29985611753,3092079056219981783,-9747501808202416505/7849158986817:92717882089562932366622101025/29985611753
+qaddz:7674883887123290368/1292702782951,7265216107539444345,5305342163772150486/5832447092447:9391765080964346281672802652463/1292702782951
+qaddz:9423076605657351418/240889071441,-6059127953500151569,-9218210247853014151/104806977658:-1459577706451435060703511889511/240889071441
+qaddz:6906236673658662814/140167346995,5953302177726308344,6858441000058123625/723669979514:834458572118358858467470489094/140167346995
+qaddz:559876427517689463/32071119551,-5256353831354881895,-4515947459706955400/25152550949:-168577152127179433134512739682/32071119551
+qaddz:4068672547617525067/1548794000,1708587743626678397,-207685545846576256/11174851881:2646250449871210288820743067/1548794000
+qaddz:-5137896362067916551/3635693101,2393661747677268624,-695423398519672103/878721119:8702619497019951948732646473/3635693101
+qaddz:234276694270475397/294461381,-3074163560486378221,-5996024834040014309/815688460:-905222447206419268373507804/294461381
+qaddz:-1281564341537166075/106650493,148338290500462844,2961154916731862131/237638921:15820350531087237503616017/106650493
+qaddz:-6081903223358942866/140515995,8576558583908287121,10228381531459438/108952997:1205143657011760730194057529/140515995
+qaddz:2904197618588220738/91768927,1341853265056004046,=1:123140437229833704797299380/91768927
+qaddz:8444844737047959/6508337,-3121162187991725782,577600780863107469/77886268:-20313575342662659863796575/6508337
+qaddz:-7581658318588584115/8539308,1829695701216611407,=1:15624327557306300932102241/8539308
+qaddz:5686384777950870687/5180266,5725674667424296916,=1:29660523493104170838730343/5180266
+qaddz:-9349000804660487281/169585,-9931090441642768328,9282213820882713035/676238:-1684173321546793527391161/169585
+qaddz:-4987687379036548499/415933,-4529830725292970964,-2701909210096535388/203425:-1884111070750660328517911/415933
+qaddz:1296987410190297797/20878,3549166774468354520,3245395317975795443/28657:74100800904760495966357/20878
+qaddz:1416158818097070767/3904,7994210571119010019,7360059100347464896/48079:31210814228466712184943/3904
+qaddz:9709919947974007131/874,-6830730629919228709,2205443246566180090/303:-5960348650601431884535/874
+qaddz:1925917894957464961/685,-6027249478829109060,-5343051367134373712/1021:-4126739975102982241139/685
+qaddz:3125021296756461042/505,-3536767182227478666,1332510672665779772/45:-1782942405728120265288/505
+qaddz:-5071777645997131741/514,8260041058129029864,-531041568629881135/103:4240589326232324218355/514
+qaddz:-2218822602969636376/29,3585630033488142992,3393420876741550072/15:101764448368186510392/29
+qaddz:880044572043278916/11,-6109313865580717394,124212297019093925/14:-66322407949344612418/11
+qaddz:6248985291450346275/2,9493162199953532306,-4130466083733148400/7:25235309691357410887/2
+qaddz:1986241673445749321/4,5178416138859731379,2046732894250340779/8:22699906228884674837/4
+qaddz:9979832122548221402/12717137847146036559,79527741365413786355,73831860449336535169/1514391878508936732:1011365249616145076974769500777993573847/12717137847146036559
+qaddz:7935653883386524088/43702671649323180779,31726785951925090635,-73129402153480840711/23070283018861257208:1386545308945341622873014968339451428753/43702671649323180779
+qaddz:-93473235956409121974/3521849589372767293,14176089406854262878,86358338521892655661/8513932339338708236:49926054656441321879828060404133327280/3521849589372767293
+qaddz:-75776234900005146680/1934924867434433667,58779385165176736174,=1:113733694048607113038507934157157223378/1934924867434433667
+qaddz:10754058131593805677/10119651272346505,54504300977159159643,95585489620287220450/323814423064533371:551564518731865556391884682101903392/10119651272346505
+qaddz:-26320122648161591867/118955488311945989,36439044282055136810,19850642639958356517/200120485264504867:4334624306192492122600675236564163223/118955488311945989
+qaddz:21672449029428526941/15150265559827046,99277026381166669676,18730584597709492865/69655516304512819:1504073313664630491063919887801384037/15150265559827046
+qaddz:85792494086863781236/50064798708777621,-76374367048497097864,-76196863606569205097/60267456232905085:-3823667312793305504369462034586320308/50064798708777621
+qaddz:82198870205394916580/3448850359841959,92122854365946272671,-9499119469817233118/381994720733569:317717939429662268414058202075719069/3448850359841959
+qaddz:6940206776533138781/442725248202698,52972508975617224025,5617429131950608687/3366289783208936:23452267184149790024086119808558231/442725248202698
+qaddz:55599986966946799564/351405696052723,81353132501416252986,2145222144601366685/198829739629804:28587954152729636171116544308980442/351405696052723
+qaddz:94458271410973778847/361353862043500,54761990849557223858,-14653194369734462194/40666523642913:19788456886678404891313989807601847/361353862043500
+qaddz:-84180062330049702321/10106997571532,34216878817519062264,43542034768301689369/65407469845390:345829911113985714017035852166127/10106997571532
+qaddz:-24742695506396929785/17404029796744,41450961372253719353,=1:721413766826363551856884212256847/17404029796744
+qaddz:34674970696505269672/434120698329,90706045368333568168,4047354904123103766/5628094003009:39377371757997599606800990460944/434120698329
+qaddz:16761364796027525373/5854257789796,65993384007951488766,2006868112336026267/163736160281:386342282403565536077626910957109/5854257789796
+qaddz:13213233170358417707/28953389411,-84133659565012740924,38441120866807154861/611830462605:-2435954607945105525978669538057/28953389411
+qaddz:-64998396976150810447/657173799966,68741723486105419807,29966320909708913126/113185344833:45175259639510928939657721516115/657173799966
+qaddz:-75993621747015299032/49530111977,64950591439466856818,=1:3217010066893177413628750610154/49530111977
+qaddz:-20552895783534231165/77134912822,22987772657101552827,59095027841080059905/57879333453:1773159839856930680727938416629/77134912822
+qaddz:23575585295873866365/354640952,10572907047388947403,63974647548865514804/2902818571:3749585844269110717151714021/354640952
+qaddz:-3423087053862335915/3563944811,14776086984480635327,87473419453510292251/150143797:52661158531801310749782602282/3563944811
+qaddz:20175953575026075815/258856713,-707977887059042238,-88657359408605704674/445245889:-183264808544835335630767879/258856713
+qaddz:5641506401094150499/81605428,27796153257209226730,-31152461920419370958/183221007:2268316988949659433944840939/81605428
+qaddz:64291966735347840169/1472255,-37813006182818155116,58751143690989021203/3131508:-55670323125718207612466411/1472255
+qaddz:-40829665387689228845/40252968,65646528058726294873,48548143291840415697/19567973:2642467552429346280592204219/40252968
+qaddz:84643493739932974309/2975141,-85925500041436529739,29931128280261616739/3657301:-255640393475285778591243890/2975141
+qaddz:49533459783522540811/7076331,28143218875743097472,=1:199150781703665812199676043/7076331
+qaddz:45584750001594149227/984336,41115590339049176247,15975001635513275306/154305:40471601316728311544416219/984336
+qaddz:6418669402794912089/164220,73293587179171456413,-2508617797150506151/19201:12036279305232939367054949/164220
+qaddz:9535512106815022878/7681,28863162607332458363,16912585483283156773/19761:221707487499027427709081/7681
+qaddz:31040563813369589503/9684,-10330625966877227525,58520741913037533005/66343:-100010741299425701762597/9684
+qaddz:25406696906821168845/637,-96989536360380372540,89275628731812608081/8978:-61756927964655476139135/637
+qaddz:12530150187862657939/1219,40341242697614742420,=1:49188504998580233667919/1219
+qaddz:80569150582987599935/2,-15179790697208915754,82993038152425243161/355:50209569188569768427/2
+qaddz:36661516357580891535/19,-66347692158873159944,2979405734116612133/33:-1223944634661009147401/19
+qaddz:-77628572518590925665/92,9553267737685350880,69073840554559304981/47:801272059348461355295/92
+qaddz:94231430591775515069/83,1462408193524266778,-64327046129355071262/11:215611310654289657643/83
+qaddz:-6524291256793749081/5,46538712122784125243,=1:226169269357126877134/5
+qaddz:1240850785353652095/2,42205460810156144332,=1:85651772405665940759/2
diff --git a/polly/lib/External/isl/imath/tests/qdiv.t b/polly/lib/External/isl/imath/tests/qdiv.t
new file mode 100644
index 00000000000..f0dd12f9996
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qdiv.t
@@ -0,0 +1,803 @@
+## Rational division tests
+## Generated and verified in PLT Scheme (see imath-test.scm)
+
+qdiv:3/8827981081671378268,0,3/3926508931624275206:$MP_UNDEF
+qdiv:-3/474373049650626538,-3/30777320180374251050,9/1226655408788630648:15388660090187125525/237186524825313269
+qdiv:1/1306590006879123716,=1,0:1
+qdiv:4/687201385528545547,8/9869825196514386591,-3/5975430289097816269:9869825196514386591/1374402771057091094
+qdiv:1/61423611473194332,1/15455670029280858,9/557484359857054244:2575945004880143/10237268578865722
+qdiv:-5/979333377476953559,1/99869524971840393,=1:-499347624859201965/979333377476953559
+qdiv:-7/30691138649930912,1/11634392715914207,3/17315717048169457:-81440749011399449/30691138649930912
+qdiv:3/20309884568576860,5/77811383120554786,-1/10721697997657271:116717074680832179/50774711421442150
+qdiv:9/5449666303362005,-5/2861847982830984,1/1826459823357042:-25756631845478856/27248331516810025
+qdiv:7/8847841671787170,2/1586192862907947,=1:3701116680118543/5898561114524780
+qdiv:8/289082769132563,=1,0:1
+qdiv:4/404037054778449,-3/231560563043393,7/849880896656765:-926242252173572/1212111164335347
+qdiv:1/48469516794680,-1/28088185111303,2/21754840126411:-28088185111303/48469516794680
+qdiv:8/50407054689999,=1,=1:1
+qdiv:-5/3164747219031,=1,1/3512888487599:1
+qdiv:5/5486024696808,3/3947571370957,4/5612399333251:19737856854785/16458074090424
+qdiv:0,1/41619742838,3/808926099199:0
+qdiv:-7/908640056265,1/159999865095,4/624715801203:-74666603711/60576003751
+qdiv:3/31854541511,2/14382200067,7/81824133981:43146600201/63709083022
+qdiv:-2/53726093607,2/89209379771,=2:-2175838531/1310392527
+qdiv:-1/6605722316,1/2540812616,9/2982865172:-635203154/1651430579
+qdiv:9/9991323937,=1,0:1
+qdiv:3/179688887,9/702152629,=1:702152629/539066661
+qdiv:3/404963252,-5/696394373,=2:-2089183119/2024816260
+qdiv:1/6333273,1/37207089,2/31767299:4134121/703697
+qdiv:3/90875674,=1,3/86752486:1
+qdiv:5/7636188,2/3416475,-8/1655405:5694125/5090792
+qdiv:-2/244339,=1,9/4733791:1
+qdiv:1/107213,-1/229854,=1:-7926/3697
+qdiv:-1/191856,2/941299,4/169459:-941299/383712
+qdiv:-1/11772,1/30223,=2:-30223/11772
+qdiv:-7/11960,6/95509,8/90341:-668563/71760
+qdiv:7/6422,4/4147,0:2233/1976
+qdiv:8/9005,1/5326,=2:42608/9005
+qdiv:1/665,-4/217,3/278:-31/380
+qdiv:3/140,1/227,1/100:681/140
+qdiv:-5/27,2/11,=2:-55/54
+qdiv:-7/26,1/5,-7/78:-35/26
+qdiv:1,7/2,8/9:2/7
+qdiv:1,1/4,-5/2:4
+qdiv:55/20700362000632320869,=1,69/80225473900126748965:1
+qdiv:14/3091014050673014971,-28/81380133061144194395,84/40859471274765910171:-81380133061144194395/6182028101346029942
+qdiv:1/314668662662881104,98/4475605721586782695,=1:4475605721586782695/30837528940962348192
+qdiv:3/1845567143863582553,11/786490044553073944,18/1855454337971843903:2359470133659221832/20301238582499408083
+qdiv:63/385333292496806971,=1,-1/32472264092720881:1
+qdiv:3/149509460292616220,=1,89/655644037836531409:1
+qdiv:59/60850170481238094,=1,31/16962204174702505:1
+qdiv:-21/11323738586240236,89/72739976921345915,-68/47763887738600551:-1527539515348264215/1007812734175381004
+qdiv:42/8561938043647535,-93/6809871846010066,17/9985561445050651:-95338205844140924/265420079353073585
+qdiv:74/824445644271491,=1,-10/462004715375339:1
+qdiv:-91/158705946232261,66/377268980338471,1/180572218716832:-34331477210800861/10474592451329226
+qdiv:13/294374634105374,17/137508734190942,=2:893806772241123/2502184389895679
+qdiv:60/52806122696123,=1,25/35647894318199:1
+qdiv:2/70084255188433,=1,=1:1
+qdiv:-11/522366309775,29/712593081308,89/4408829724580:-7838523894388/15148622983475
+qdiv:84/102632540711,61/53857049409,15/1404297586412:4523992150356/6260584983371
+qdiv:70/902531223717,92/698425518183,18/41071684813:8148297712135/13838812096994
+qdiv:9/100549718122,=1,-29/262025912406:1
+qdiv:5/78979980317,-29/15117078653,65/7124115824:-75585393265/2290419429193
+qdiv:31/30756865282,=1,-11/69831756369:1
+qdiv:43/1638160013,-9/6652991074,36/1999878215:-286078616182/14743440117
+qdiv:4/7372173731,11/274587688,=1:1098350752/81093911041
+qdiv:-75/216042979,-19/338590753,33/292120913:25394306475/4104816601
+qdiv:5/521918956,74/512764585,-35/161566463:2563822925/38622002744
+qdiv:18/42121601,28/26500085,65/84650518:238500765/589702414
+qdiv:41/41853940,11/85956056,53/26801053:881049574/115098335
+qdiv:96/7914185,0,=1:$MP_UNDEF
+qdiv:-18/2408419,-29/2331289,39/1991248:41963202/69844151
+qdiv:-21/209413,=1,38/45091:1
+qdiv:73/941827,31/311506,-28/306503:22739938/29196637
+qdiv:-80/34347,=1,76/60617:1
+qdiv:-27/34016,44/3123,11/36759:-84321/1496704
+qdiv:45/4447,95/7813,=2:70317/84493
+qdiv:31/107,16/1959,-2/1335:60729/1712
+qdiv:7/6,=1,-72/455:1
+qdiv:82/415,5/846,4/63:69372/2075
+qdiv:95/28,-25/38,28/19:-361/70
+qdiv:89/43,=1,79/14:1
+qdiv:-49,8,-71/9:-49/8
+qdiv:-10,=1,1/4:1
+qdiv:808/45524274987585732633,-72/3230580501556764385,69/50585273432898431555:-326288630657233202885/409718474888271593697
+qdiv:319/66978137654707641182,=1,=1:1
+qdiv:-669/4359545352267142613,389/6178257053522267612,=1:-4133253968806397032428/1695863142031918476457
+qdiv:991/3477727818712482910,=1,529/5027018252141619996:1
+qdiv:3/23180871072888724,592/673665479785224825,-596/518946796253532009:2020996439355674475/13723075675150124608
+qdiv:179/793396855429515116,931/387517624716045840,-695/566279872123894778:17341413706043051340/184663118101219643249
+qdiv:221/3427690629405359,=1,598/80947651271959489:1
+qdiv:-724/52750058649448927,153/12336232443953527,67/55314453014305481:-8931432289422353548/8070758973365685831
+qdiv:575/8856014113088424,77/1046092009770736,=1:75187863202271650/85239135838476081
+qdiv:639/7628460189090482,=1,3/187674005095612:1
+qdiv:167/57172907255471,=1,458/490173841920009:1
+qdiv:-64/133181712979849,571/541047169178329,495/108993178847291:-34627018827413056/76046758111493779
+qdiv:-527/33346321735789,13/1536370494056,616/27148895576567:-809667250367512/433502182565257
+qdiv:-600/42483246609437,177/7709155575481,-274/29153462781241:-1541831115096200/2506511549956783
+qdiv:-891/3797928330707,-557/8539817631461,44/93582862751:7608977509631751/2115446080203799
+qdiv:30/101373302507,64/912736019917,127/1421964160402:13691040298755/3243945680224
+qdiv:95/811213545591,967/271585517890,-221/724077624393:25800624199550/784443498586497
+qdiv:482/121409952851,873/176693357788,-173/379909953056:85166198453816/105990888838923
+qdiv:211/83869812582,=1,425/21426470616:1
+qdiv:89/16604301838,-370/14168930881,=1:-1261034848409/6143591680060
+qdiv:357/8146855082,-657/9471809692,=1:-563572676674/892080631479
+qdiv:-21/2562596293,903/2881728821,156/164990119:-2881728821/110191640599
+qdiv:-579/609663644,=1,157/25380668:1
+qdiv:-39/383217583,929/665052497,817/218315394:-25937047383/356009134607
+qdiv:937/74356752,422/14604731,959/48789395:13684632947/31378549344
+qdiv:81/64759993,-169/12649693,-554/43474193:-1024625133/10944438817
+qdiv:-277/389415,=1,=2:1
+qdiv:251/2232087,-151/728262,=1:-60931254/112348379
+qdiv:-61/65749,-207/485432,=1:29611352/13610043
+qdiv:363/228754,227/70325,569/103195:25527975/51927158
+qdiv:159/83267,-157/2354,327/82759:-374286/13072919
+qdiv:41/1099,471/99860,201/1723:4094260/517629
+qdiv:14/23,27/70,=1:980/621
+qdiv:775/8954,916/3399,-956/2393:239475/745624
+qdiv:-16/17,-337/37,753/524:592/5729
+qdiv:680/89,955/296,-767/913:40256/16999
+qdiv:671/29,69/71,=1:47641/2001
+qdiv:45/7,227/47,-588/17:2115/1589
+qdiv:309/4,=1,477/7:1
+qdiv:995/8,-542/3,=2:-2985/4336
+qdiv:709/12248686694307459921,-359/3012348473905143856,3209/3205529400054125663:-305107866856963856272/628182646179482587377
+qdiv:7039/48532814476573486698,1842/19665238977050464607,-686/59623200188183875815:138423617159458220368673/89397444265848362497716
+qdiv:451/329309233590151305,=1,=2:1
+qdiv:809/682008587763566662,8909/1007199215258353342,2888/6648659691864956039:407412082572003926839/3038007254192807695879
+qdiv:7143/477997774542113905,8817/680997252822749635,-1905/134302220820939382:324290891794193376187/280967091875854553359
+qdiv:347/219003978754231945,-8579/862605866526757805,1879/749017786570395462:-59864847136956991667/375767026746511171231
+qdiv:2252/19919238262742963,3008/30104309448888197,8998/18293466522564645:16948726219724054911/14979267173582708176
+qdiv:3132/7632328378838467,-7891/65522084848474051,-6375/16422802718592713:-205215169745420727732/60226703237414343097
+qdiv:3091/6666475760056275,-4948/972687207365139,-1089/869334750550498:-1002192052655214883/10995240686919482900
+qdiv:-1181/1328394658282401,-4449/5267675168926367,2101/2626633098162958:6221124374502039427/5910027834698402049
+qdiv:7323/118964685899438,-259/116805460794557,9535/306412793639648:-855366389398540911/30811853647954442
+qdiv:2433/121526971245398,360/82851643972451,-3062/418315498791959:67192683261657761/14583236549447760
+qdiv:6067/57796241878231,964/16961015496389,-6693/83462416525900:102902481016592063/55715577170614684
+qdiv:4159/18938105171021,-3304/15702563734975,-497/5886368665864:-65306962573761025/62571499485053384
+qdiv:-2339/6560171909556,-3315/879777839282,1570/7171072558101:1028900183040299/10873484940089070
+qdiv:1225/584214253087,-6283/3835506609411,1613/7130518143781:-4698495596528475/3670618152145621
+qdiv:608/483278255319,2413/247017404385,-9588/346021249721:2634852313440/20458779475171
+qdiv:5057/839656743164,-8443/6430957362,3191/797476829669:-16260675689817/3544610941266826
+qdiv:8/2915377743,-2073/42761112191,3028/25982265273:-342088897528/6043578061239
+qdiv:-3080/48285456271,7722/56966382901,4950/16693686061:-7975293606140/16948195151121
+qdiv:2506/7829482533,3738/894286585,1315/9318157842:160077298715/2090471836311
+qdiv:395/539727584,3101/2435581364,8543/4140459726:240513659695/418423809496
+qdiv:-2933/85901348,1075/31492019,5089/657510451:-7105083979/7103380700
+qdiv:-109/7944981,1560/35171599,8205/374231336:-3833704291/12394170360
+qdiv:351/84445888,=1,-972/45463937:1
+qdiv:1896/15952037,1648/24133709,-8841/97126097:5719689033/3286119622
+qdiv:-7849/786920,8468/8925921,-3114/6765635:-70059553929/6663638560
+qdiv:245/566264,=1,8221/9131472:1
+qdiv:79/17927,=1,=2:1
+qdiv:1970/222369,-9680/117859,-333/53716:-3316889/30750456
+qdiv:1255/31098,5871/80299,581/4346:100775245/182576358
+qdiv:2551/88863,310/16021,937/5727:40869571/27547530
+qdiv:8096/4615,=1,359/1549:1
+qdiv:4380/6089,-1293/32,=2:-46720/2624359
+qdiv:4841/137,=1,63/127:1
+qdiv:-7195/394,1026/73,2871/383:-525235/404244
+qdiv:-2123/25,=1,=1:1
+qdiv:4877/72,=1,=2:1
+qdiv:2059/8,=1,1797/2:1
+qdiv:4309/5,-928/7,9812/5:-30163/4640
+qdiv:1276/48998512603828859815,=1,=1:1
+qdiv:-87759/12642453185607565556,61169/76861786640093390298,=2:-3372656766873977919581091/386663109455214588747482
+qdiv:-73621/3641518581487027232,=1,=2:1
+qdiv:30239/2864992309604629419,69203/360791977688831821,48533/7318731980981091051:10909988613332585435219/198266062801569169683057
+qdiv:3258/375353145849458519,=1,=1:1
+qdiv:7705/911649391027518118,-4527/523603872108693505,=2:-4034367834597483456025/4127036793181574520186
+qdiv:80183/27684870128356298,=1,31447/10044082204150725:1
+qdiv:55812/2242876918063201,273/5987187297553853,=2:111385632483691881212/204101799543751291
+qdiv:4768/1013825352338725,547/51853159734450,13214/1209874359544049:9889434624554304/22182498709171303
+qdiv:6676/2650290894306779,=1,41501/3206334096847699:1
+qdiv:28681/68017529704052,=1,-17941/468955454103104:1
+qdiv:-19043/55558808816913,76696/93211283557235,37794/88565241121255:-1775022472780426105/4261138401021959448
+qdiv:58963/41164814718796,37371/41375121127588,-43794/48988525394521:609900316761492811/384592572714031329
+qdiv:12779/2181401551509,=1,=2:1
+qdiv:9529/1314170728394,48148/4767551174553,88486/9446535741037:45429995142315537/63274692230714312
+qdiv:45171/1935400244048,=1,=2:1
+qdiv:-8055/796756979512,-40221/581590215415,13256/244193996163:520523242796425/3560706941439128
+qdiv:73154/947174782947,39139/519633159803,=2:38013244172228662/37071473829762633
+qdiv:-42235/18400469972,3745/6423311093,-18889/85101890714:-54257708802571/13781952009028
+qdiv:63068/11796773127,-31/59107640,90784/7564528991:-219282390560/21511762761
+qdiv:16431/9543805406,42548/5364916925,-5126/2217017905:88150949994675/406069832414488
+qdiv:57923/8084487099,72400/4961088589,979/745380355:287361134340647/585316865967600
+qdiv:51393/552384269,8157/339410251,69420/934416791:5814437009881/1501932827411
+qdiv:16234/493942565,93863/203157564,58764/900515657:3298059893976/46362930978595
+qdiv:-43437/39051397,12197/12032365,=2:-522649838505/476309889209
+qdiv:61845/28993019,=1,-30098/34003047:1
+qdiv:-21977/2530949,7118/5886975,89761/8051121:-129378049575/18015294982
+qdiv:-67667/570818,24964/4493829,77381/5174833:-304083926943/14249900552
+qdiv:80188/494389,=1,88457/134084:1
+qdiv:15689/433436,13517/141762,7082/140371:1112052009/2929377206
+qdiv:10873/14999,=1,95341/35511:1
+qdiv:66107/92401,-30477/19660,82518/86557:-1299663620/2816105277
+qdiv:91501/4959,49360/2327,1601/402:212922827/244776240
+qdiv:-1728/335,-29231/3035,23678/2657:1048896/1958477
+qdiv:-31582/403,6626/71,-96811/384:-1121161/1335139
+qdiv:1149/28,16127/136,1326/875:39066/112889
+qdiv:13158/11,-59582/45,-5678/35:-296055/327701
+qdiv:83796/5,15431,=2:83796/77155
+qdiv:-50168,82697/4,27476/3:-200672/82697
+qdiv:43313/8,-23369/3,37118/9:-129939/186952
+qdiv:343272/40939026292046552549,=1,-149188/1630670088822528293:1
+qdiv:7090/17394546172873749111,806868/84886259115708426355,977287/27695656418221378384:300921788565186371428475/7017551340707148098847174
+qdiv:273653/494417711699854970,520824/6619891999027460951,385411/1812431346892436901:1811553305209861771624003/257504610278365264895280
+qdiv:30655/71199858589215198,=1,684829/6532276093969322272:1
+qdiv:181927/723554427646445064,996115/645768630995539314,80483/188550933731713724:19580458288520913463013/120123903115839770821060
+qdiv:72786/190019706414733673,37703/744879257576358133,926598/93783057457592441:54216781641952803068538/7164312990954703673119
+qdiv:6030/34221301230292789,254491/329459713137161,=2:1986642070217080830/8709013171398442165399
+qdiv:-374458/43126191217786237,=1,896258/14496576313551015:1
+qdiv:564923/3144080096402171,794248/4739399554899871,-434642/3276748536360521:2677395814752699824933/2497179328407231512408
+qdiv:199922/1178376836454579,=1,83513/1610790739884089:1
+qdiv:-268911/54100968009644,28397/60052294389392,81027/47026501432603:-4037180634136448028/384076297142465167
+qdiv:893838/55403243375203,986288/2293797524067,=2:1025141695658499573/27321777051021108232
+qdiv:18303/82870490401642,913885/30405433858676,=2:278255327957673414/37867049060352299585
+qdiv:5047/32151410465425,=1,176188/13701013860219:1
+qdiv:187835/1220654728179,405949/2196086232716,=2:412501857522209860/495523566249536871
+qdiv:378036/6357059248081,114851/4050423226594,862111/3515447797224:1531205794888689384/730114611701350931
+qdiv:-294719/147652614747,104431/366828548330,676351/724118840846:-108111342935269270/15419510210643957
+qdiv:-331898/628206486043,=1,-177396/338495728537:1
+qdiv:177685/26330782667,=1,-420269/95383974662:1
+qdiv:-318696/28047340105,197485/16144733252,-240020/96906119801:-5145261908479392/5538928960635925
+qdiv:-576953/5244331985,=1,2965/50930228:1
+qdiv:370624/2877285795,5441/59491598,666008/8960730819:22049014017152/15655312010595
+qdiv:-902401/154074924,-583513/621607888,790132/568175569:140234894934772/22476180282003
+qdiv:220793/55445126,-127133/589508175,=1:-130159278482775/7048905203758
+qdiv:992605/96130864,-338301/47600647,-268171/7895145:-47248640215435/32521167422064
+qdiv:200098/69076309,-713974/36753541,226577/9980229:-3677155023509/24659344320983
+qdiv:-24613/302985,301411/2633942,57255/1357249:-64829214446/91323011835
+qdiv:-224679/8931277,-609222/9892805,231393/5325206:740901844865/1813710145498
+qdiv:374358/364639,-31343/26526,-293019/312248:-9930220308/11428880177
+qdiv:-390237/256456,390385/933736,-349530/445567:-45547291929/12514571945
+qdiv:-871638/36751,61626/4051,=2:-588500923/377469521
+qdiv:-87914/16631,783263/70173,-431150/88143:-6169189122/13026446953
+qdiv:-128/2205,-668595/5258,=2:673024/1474251975
+qdiv:405269/1719,=1,=2:1
+qdiv:123781/830,=1,356120/629:1
+qdiv:-130038/131,640786/467,214577/394:-30363873/41971483
+qdiv:940928/95,=1,934701/79:1
+qdiv:-468415/11,=1,79087/4:1
+qdiv:170049,838068,204415/2:5153/25396
+qdiv:937045/9,=1,=1:1
+qdiv:-895965/11817608522407410412,1662758/31138269586404741097,1787239/8265484069296678539:-27898799709983123856973605/19649823111501100921836296
+qdiv:9485555/29939758418824763622,=1,=1:1
+qdiv:3256189/100080959665237165,9746921/1570372596135540846,7102111/7910145060985949414:5113429973437990611795894/975481207461253093518965
+qdiv:8443036/2594663966536136217,6210896/4467012950800475059,=2:9428787789018659935059781/4028797012775855571405108
+qdiv:1180903/105749612753261488,=1,5874507/437668716132551285:1
+qdiv:-96672/840052608584629,2690215/425934540850990364,4714612/192754505384388189:-41175943933146940468608/2259922128403497705235
+qdiv:2821007/83364576953405163,=1,582088/4860812540794867:1
+qdiv:-797070/17849830777864213,=1,9498931/55689637536119864:1
+qdiv:7021411/6724756422420817,852445/1318535168793131,5879850/6896277416986789:9257977338050946727841/5732484988510513347565
+qdiv:2862688/9366273253135011,-2712503/6212570364248993,6269770/1992362624741777:-17784650630891221273184/25406044297948476742533
+qdiv:1770043/227457000705496,1050787/653965284988262,4665931/732005792365452:578773337468239117633/119504429700163012676
+qdiv:-6397271/15882716560575,4689255/783371764982764,2301170/95355180815573:-5011441474343051637044/74478108045259121625
+qdiv:1734439/13086156486143,-3265601/63043422188314,8065931/40472250566091:-109344970136877145846/42734165707305066943
+qdiv:2779319/3703679337417,-2792251/56401900482152,=1:-8250467034008116552/544294859662208193
+qdiv:8906654/1989823550291,5015729/711711398937,350071/21519066915:6338967178187826798/9980415686077527139
+qdiv:1342773/5863720123828,8311991/8825950349708,1394645/2412447722267:2962811957232115071/12184797223944305387
+qdiv:4499434/306371176997,=1,3752751/959913819173:1
+qdiv:-3583690/490293948611,272623/13035328183,8190059/637847763742:-46714575256135270/133665407152176653
+qdiv:-1213471/56665475600,3817747/17865032159,-816041/17280339528:-21678698439013889/216334449475473200
+qdiv:-2100116/20836208549,4331/50448644,=2:-105948004442704/90241619225719
+qdiv:36713/12904114,883015/6814675799,7851017/3608793001:250187192608687/11394526223710
+qdiv:5022803/2809898795,8967230/3296219033,=1:16556258847609499/25197008771487850
+qdiv:781841/201099058,85007/147631535,2241175/183484024:115424386955935/17094827623406
+qdiv:3699468/393449053,829829/358610807,1152449/409680870:1326669204950676/326495434201937
+qdiv:-3463205/9915829,9661223/82242321,503777/9897306:-40688859614115/13685576456981
+qdiv:-1589921/41367712,9942811/90188714,3708164/23097593:-71696465175797/205655670959216
+qdiv:-5779163/4536533,=1,=2:1
+qdiv:2210759/3222751,5205241/5080834,=2:11232499493006/16775195637991
+qdiv:2183333/139811,5752077/430948,1225681/247001:134414712812/114886233921
+qdiv:-8070429/171845,128419/37928,290524/56769:-306095231112/22068163055
+qdiv:-3211584/2153,3758472/791,=2:-105848456/337166259
+qdiv:-6466794/31769,-3915902/42711,-7456369/21580:138101619267/62202145319
+qdiv:3729205/1518,-260137/3841,2483611/6182:-622777235/17169042
+qdiv:6860802/4649,=1,5289160/3861:1
+qdiv:-83438/7,571053/190,-1052132/281:-15853220/3997371
+qdiv:8063462/909,2183491/660,8119557/104:1773961640/661597773
+qdiv:3049687/87,-1582395/16,-1200911/16:-1574032/4440915
+qdiv:352110/19,=1,=1:1
+qdiv:2962406/3,-3345297/2,=1:-5924812/10035891
+qdiv:7149844,-6647775/8,3754198:-57198752/6647775
+qdiv:86792351/49133761328196981964,83681596/94733888541192208399,45540422/93887740620391683883:8222176905862032109831156049/4111591565426603253130734544
+qdiv:37275015/45938947789509093778,=1,-31078003/24048804548446901925:1
+qdiv:18714228/278784499974669995,28535131/7442575198888787547,-18894836/167878993350595593:139282049179150116798118716/7955152227546704989094345
+qdiv:-24811360/2159236580309869299,44687068/2174509444305355231,-2185967/982469534126187980:-13488134161515029641056040/24122487973098647608881333
+qdiv:38561291/399479362141639464,73235730/642777863686427933,-44021955/503809548217143929:24786344249970680274941503/29256162706377329542848720
+qdiv:-9532213/318095670778469600,28369139/87482667379251144,-92704577/641723560262485864:-104237927408396710637709/1128012537451580286209300
+qdiv:12970933/24974407644034125,=1,7781491/55007097983499252:1
+qdiv:-73795622/62522679678898791,-40287452/37729183605206197,10065628/1450024137592451:1392124285849196872934767/1259439728237505227635266
+qdiv:45877577/2870321629840685,62804508/3060757957189363,-24942819/194614932107914:140420158859317704613451/180269137763902339807980
+qdiv:27765340/1722659366920429,-49740100/4392314052861681,32854898/4914960185867565:-6097704653224127296827/4284262458827941525145
+qdiv:31840878/650549338557053,=1,82034659/746923000065290:1
+qdiv:-3799624/89718613403123,=1,68910040/992826933898731:1
+qdiv:31394779/66096039231279,-10511385/62803293159157,=1:-1971695509203945841303/694760915335077611415
+qdiv:86839209/60474989629672,50531989/58732772835419,-863777/980850237675:5100307535404473143571/3055921510741699577608
+qdiv:27323066/1973122068799,-78173848/609142108427,75125805/9127401261224:-489518530350884623/4536663079168781428
+qdiv:36867962/1416533338363,635443/97562183222,98853338/2812167235847:3596918863665733564/900126194129399809
+qdiv:47352329/413811029048,=1,10407191/442238417413:1
+qdiv:68800501/774974238286,-2280234/152962980017,-48441105/249265282913:-956720878147508047/160647509751258084
+qdiv:65729629/84892894017,=1,-25288745/76133875626:1
+qdiv:76580386/41315133127,=1,-96951946/56344054531:1
+qdiv:16421575/8944123642,=1,956371/8341427945:1
+qdiv:3853661/95830379,49444059/3207768145,-6661391/2303483651:1765950142489835/676891844752623
+qdiv:55380577/150811366,32344153/137899626,37704187/990478015:3818480427982101/2438932948021499
+qdiv:-1819205/194369638,=1,1770897/587958251:1
+qdiv:27198033/94223324,1701651/36639143,-5208757/47970432:332170873468573/53445071169308
+qdiv:26144007/33885110,94294868/78704229,77077115/11515724:2057643913905603/3195191974615480
+qdiv:7734047/454358,41930099/1017254,26486906/1535151:3933745123469/9525637960721
+qdiv:95593715/5378931,77945657/2828365,15099226/479451:270373917725975/419264310752667
+qdiv:64278733/781984,-55137203/906657,=2:-58278763225581/43116410550752
+qdiv:2755454/91023,-44515162/293371,53356021/607819:-404185147717/2025951795363
+qdiv:-851882/63,-75090427/4230,-20131985/3239:400384540/525632989
+qdiv:-4882658/14371,=1,60992107/31701:1
+qdiv:-11263333/2311,69417077/9812,11529690/407:-110515823396/160422864947
+qdiv:-23572979/329,15626746/7287,-22762379/5404:-24539471139/734457062
+qdiv:45146947/609,5802442/59,=1:2663669873/3533687178
+qdiv:48034468/31,50219011/517,=1:24833819956/1556789341
+qdiv:6524645/17,-58706702/87,=1:-567644115/998013934
+qdiv:334487/34,84187235/74,=1:12376019/1431182995
+qdiv:21060395,7521975/2,89723525/8:8424158/1504395
+qdiv:49115243,-71749933/4,85184626/9:-196460972/71749933
+qdiv:309597727/33672758861109919384,-177164051/55601420918529748854,895889621/23670804105482899489:-8607036767173531213539627429/2982801184090189837176432292
+qdiv:48916804/2660589522598316323,313914094/34752378183509684779,904253494/34791426109034240319:849987636068309641218063158/417598274746171497229978181
+qdiv:242729/247715169151474017,221774365/420531110603394201,93370673/386036618278885054:11341677327294585668281/6104097148826193214908245
+qdiv:16768055/4024792916152716086,-311564292/4024075770824349991,76507261/4630876961864888130:-268828381869920701148755/4995943248477037255823112
+qdiv:23219936/109884862578864265,380304636/829661649046413301,-237169652/48494008574580541:4816172598128044469692184/10447430666241248898558135
+qdiv:516810898/660599886600041083,74020472/119618011649135401,=2:30909946008682063757200049/24448957704640758091525588
+qdiv:189691986/87372198519829129,649602410/62948713754669759,162659075/29230871469718464:5970433264134411679425687/28378595362739717493300445
+qdiv:14774898/4079300020169327,819672300/24627820907020229,=1:60645590310581894568607/557281538320373108590350
+qdiv:71574531/9911187558077269,287480027/3692301867467201,=1:264274774474389069457731/2849268466798117360206263
+qdiv:719634375/1976359498657996,6512606/19580323447829,2020281/463180107697268:14090673826676267521875/12871250729117056697576
+qdiv:663048253/304000499307584,=1,26624410/650833137359949:1
+qdiv:248932257/31572538733168,-3297144/159684389656921,453206117/278240003582858:-281919117198331916317/738292245736400512
+qdiv:693286598/13147402069069,20606065/4637179960822,588199091/60290317447874:3214894719352057663556/270916221616370303485
+qdiv:1279088/487824767579,431725597/47207595894190,=2:60382669417107698720/210606439014430019663
+qdiv:78549245/8831126280331,541356457/4279964344475,=2:336187967885431171375/4780787234439578947267
+qdiv:110033578/47682346357,-152259539/1111037317327,-766205582/7952747013871:-122251411317011206006/7260092074755149423
+qdiv:47060001/489637479337,140861141/250864895102,=1:11805702214365015102/68970894015773743517
+qdiv:109248031/51582112839,562377671/23862568900,-27370055/52346954108:2606938666926835900/29008628483656017969
+qdiv:-342511511/53452279775,=1,547211519/16341758885:1
+qdiv:340877767/26494707436,-719326026/7059828707,32400255/14657164768:-2406538645044657269/19058332609970529336
+qdiv:-932440839/8204417554,-57679385/756117222,189301605/4430094677:352517288432014629/236612879398962145
+qdiv:-980924395/4737725778,96878060/5344143499,-563492138/260341141:-1048440145709951621/91796336436926136
+qdiv:-748092457/68521924,=1,=2:1
+qdiv:-72010946/931437,38577842/94683927,-194004572/356767967:-87413835311089/460677300243
+qdiv:-99158610/59323363,528264721/50347358,=1:-4992374036452380/31338439803976723
+qdiv:-273698543/89114428,65593727/66452645,-456099010/45664741:-18187992114996235/5845347461993156
+qdiv:-434183749/4880425,227158395/799133,696633020/1207589:-346970561889617/1108629509917875
+qdiv:-950455305/243592,-458911412/6191101,201783811/2324399:5884364789240805/111787148671904
+qdiv:699903049/451554,-235876093/487743,-158455564/246001:-113790937609469/35503597766174
+qdiv:220813028/437657,=1,735013805/653689:1
+qdiv:7685509/196,754004453/40926,-707049919/17530:157268570667/73892436394
+qdiv:222143479/26751,391098157/28855,193987153/3253:6409950086545/10462266797907
+qdiv:129843395/733,174902609/2529,586864566/2891:328373945955/128203612397
+qdiv:318016269/2750,486693651/2170,=1:23003176791/44613584675
+qdiv:199207703/783,697191979/15,628918929/959:996038515/181967106519
+qdiv:-822112671/383,700601486/287,=1:-235946336577/268330369138
+qdiv:702853697/90,57317887/96,6934229/20:11245659152/859768305
+qdiv:236859557/10,-12598119,-844214996/3:-236859557/125981190
+qdiv:666692788/3,837163259/5,-44955282/5:3333463940/2511489777
+qdiv:-267890720/3,994822169/2,306713231/6:-535781440/2984466507
+qdiv:8971865945/84652096998217220652,-1766409152/949158554479936975,51683336/978028041559081475:-8515723311343973731748816375/149530238873642626243696207104
+qdiv:-4783142107/20353559370672239325,1489328761/30130844818064603669,9037981957/29934040642660151619:-144120112568767560055460590583/30313141359463225930997726325
+qdiv:-5011919027/9589021627165778205,6908330432/8223014240433381075,-223144684/369584710951584897:-2747538768728001022382280935/4416275328003700232170922304
+qdiv:3264032212/4288823609663243543,127527384/8323211793086562335,3176342735/6939281510473238183:399518108822541446555675515/8043271402614567205789434
+qdiv:-4588453891/349300703246919169,-4621109572/563134654578914825,2946587906/489244399145625531:2583917396959562695328834075/1614156823280669651376185668
+qdiv:-2433362101/159409638288916225,85838756/19437108683105947,7818956051/899163746350160639:-47297523622488030397514647/13683525045130537342216100
+qdiv:4804263237/27326781078392456,875410347/26595379067270065,-7249537521/50005537812647291:42590400642321641076700135/7974048968742858036380744
+qdiv:-2132504576/319379206557339,3197623346/47180453249202543,=1:-5589585136204360627685376/56736355950816859668683
+qdiv:-17110179/337414992862541,=1,5637859401/8456872970863411:1
+qdiv:929796549/785511765727417,-8659917002/9734288265288811,=2:-74800889554022586414159/56218733018957846081354
+qdiv:2024811003/923122484568110,-2213327573/685808753095771,2505827052/382175752770445:-1388633109222027433568313/2043172448350864859497030
+qdiv:4321265761/608661263330203,-1955439753/18999520283666,1985116091/422495636527147:-82101976477230893359826/1190200430427080111759859
+qdiv:5403084171/20759093453216,1272181959/3497884340798,4111729721/4478504823638:3149893918959073884743/4401557362729400955024
+qdiv:4169845699/5710332227959,9148517943/2081193666800,=1:8678256460292019093200/52241076847974077768337
+qdiv:4493194533/2604354754064,-3502324668/5226679118353,4603317541/1537717259387:-1118308859063283788769/434347423780067640512
+qdiv:6987915227/4137866098763,801022943/1354532951118,=1:9465361434590718873786/3314525680171066919509
+qdiv:5294179409/20297663855,-1916636849/2091902413,-1119938671/198399693697:-11074906680542013917/38903250493108392895
+qdiv:1295990518/61239499731,=1,539185569/58234040869:1
+qdiv:2091734371/22379348546,3771243501/14969120476,-1020067815/19323989012:15655711901644540298/42198986380358149773
+qdiv:4013255624/2622410663,2585175687/49776501221,6260772357/9422047988:199765823468221116904/6779392287317150481
+qdiv:27739307/489082696,=1,-1635872773/284162212:1
+qdiv:1004677799/8383863362,3327131707/4220463949,234611693/146976367:4240206431040168251/27894217618865818934
+qdiv:8434446327/446741110,305497651/332988425,9725313826/929456845:561714599634952995/27295671942026522
+qdiv:344714653/17732695,=1,-3209292581/367817366:1
+qdiv:-6843554898/34497445,=1,-2081199716/16214703:1
+qdiv:5803347322/79453889,1102662623/8094456,=2:46974939550646832/87610833652290847
+qdiv:8712618248/2572733,=1,=1:1
+qdiv:-4833921086/2762331,-7642479217/5423409,-1583615993/2873706:8738777041034058/7037019085991609
+qdiv:8518925689/40191,=1,6550456120/871279:1
+qdiv:876819073/100630,-902089199/140111,9433117031/258480:-122851997137103/90777236095370
+qdiv:-110986687/426,3857966128/39887,1189959236/13549:-4426925984369/1643493570528
+qdiv:-7975883597/55733,-1666217426/13007,9979667239/98463:103742317946179/92863295803258
+qdiv:9307983176/5287,=1,-4477921884/4391:1
+qdiv:-6231410261/9293,=1,=1:1
+qdiv:4528426169/109,644958250/991,-966669111/247:4487670333479/70300449250
+qdiv:4728746197/670,-3092342009/975,5344313590/51:-922105508415/414373829206
+qdiv:-9298448594,6025771347/65,230306877/25:-604399158610/6025771347
+qdiv:8659053685/17,-5401196332/59,5062434592/49:-510884167415/91820337644
+qdiv:-9777515257/3,4806469000/3,2254605905/4:-9777515257/4806469000
+qdiv:51777408,125752274,147067434:25888704/62876137
+qdiv:-50627047179/45073388301558717898,-39488625025/47733211534284913713,32711658675/27270403149344569493:2416591552351429302575995065627/1779886129246473834093878197450
+qdiv:-91204883678/4376981341885366059,=1,92252001911/64145968577542202922:1
+qdiv:-6468661773/3340956703659991393,51917096173/4290285077565474605,-4184909817/2082344794208597768:-27752403076520125481965774665/173452770493744834242733238989
+qdiv:79042137253/2565404331216876095,46463876503/9217979332756333154,-71237527399/9032839782059615122:728608787615043443963462385962/119198630025922238587532895785
+qdiv:-71497371020/911351878610216589,35308340296/356473827680782925,64081379374/293532001774391069:-6371735379153120728201458375/8044580564842102716669092586
+qdiv:-59711844557/491536178108971083,-80079287644/210346837810811533,=1:12560197682415668432518875881/39361866994220711332435198452
+qdiv:82691530516/13829489779198215,-54368150702/41857898377267367,-23138364722/2016009305137557:-1730646840499715679485735686/375941892223608628924698465
+qdiv:-2532396359/43747227235758060,281496679/79780911611953,49395555307/46061856818743718:-202036890083810598079127/12314699182324243937482740
+qdiv:39329031241/771013386869700,23150277229/3870964064839779,42048700955/3103108290222419:50747088879624005983511913/5949724551101261166687100
+qdiv:36630047839/8265775107927151,-17088940048/166471968138409,7720288135/2420444961206493:-62864702647035107663383/1456219951233173329798384
+qdiv:3233508452/61288804249597,1009629177/396153232886351,-1862094182/304377258983311:1280964826825140313938652/61878964993834721691669
+qdiv:39400418349/280335370062674,=1,528864863/5327344259528:1
+qdiv:-30978168489/22888879909274,18822952031/21160004002172,1575282546/5389019145925:-327749084603599268979054/215418144287792067017747
+qdiv:95503923490/49551349663127,85560857352/20589539380841,30851800131/2025645536851:983190896861090417927545/2119827980062941250629852
+qdiv:37807143/340515189301,=1,-2818312259/743193551514:1
+qdiv:-83826099190/4358399428931,4772431013/6348630185134,-853009636/374419764711:-532180903619670747441460/20800160601671793837103
+qdiv:58301964846/768140939347,8148193743/65129075956,8259717541/561157474998:1265717698946391947592/2086320398576455968607
+qdiv:19788341553/40137672403,17083972289/174789239733,=1:3458789175625802525349/685710883077812040467
+qdiv:-10973954453/10832242662,34763618831/810622373,6976849061/881334394:-8895732999884776969/376567954986664768122
+qdiv:80042291705/98079883084,86963751533/70819982692,25719162328/28990442539:1417148428294028792465/2132348645725666441943
+qdiv:-62862242431/5180961911,-26432627160/2693765641,79398909214/5912386617:169336148776840113271/136946434523624102760
+qdiv:7346613183/88310017,50873662935/5009376481,=1:12267317097974916341/1497551346214039965
+qdiv:-8864563721/49900586,47950826631/18964907,-17937545168/328567993:-168115626564338947/2392774348071305766
+qdiv:24094021571/450614802,84569474563/64046670,-12933174970/817622387:257190308088453095/6351376172575046921
+qdiv:3494981654/23432223,-89282047405/11919821,48429893805/30458672:-41659555713963934/2092076844690531315
+qdiv:33495688780/3147047,=1,37167537331/76683481:1
+qdiv:5470526576/1258187,=1,17782212381/952621:1
+qdiv:1485833227/309723,-22316021107/3171654,83073086566/5001853:-1570849632582486/2303928335107787
+qdiv:-9654830/13783,68644421742/595891,6668182574/31547:-16070464535/2642810237067
+qdiv:-18629056304/310987,33795740865/249491,34685999906/394187:-4647781886341264/10510036064383755
+qdiv:58031794382/46405,-8325673530/923,7246189925/58537:-26781673107293/193176440079825
+qdiv:42752677499/79662,68629448895/67033,10722691188/21005:409405747255781/781022736839070
+qdiv:-14745678708/1589,-18308273147/872,-7354773097/844:12858231833376/29091846030583
+qdiv:36286205520/4483,16203338783/1827,78196029593/7698:66294897485040/72639567764189
+qdiv:5973900741/238,=1,-62903827999/275:1
+qdiv:15604013335/563,-83645760588/407,=1:-6350833427345/47092563211044
+qdiv:47070101778/5,9828239935/11,=1:517771119558/49141199675
+qdiv:14795131351/62,84397328746/93,29769038089/50:44385394053/168794657492
+qdiv:4462854035,72133672643/6,79206774199/5:26777124210/72133672643
+qdiv:77933302681,-41096015935/8,22243311204/5:-47958955496/3161231995
+qdiv:569473516504/74989462888441761347,16884022641/33541962454158520316,-961841214350/8067206202574290521:19101259309214790462605845295264/1266123789244879955792666657427
+qdiv:239854097519/52524719736478674886,106866734141/32499507073759497471,89805916001/5326340692191230017:7795139938988940832361667874449/5613145259908802128558135482926
+qdiv:-677983905959/5228931513669930017,90555544897/909803638402840864,=1:-616832224420067701296618308576/473508742449475516893291473249
+qdiv:200250717/41414149596190990,-189493590347/1507829061340539502,775951232712/5167695853317665663:-150971925323440008221161467/3923857949074995465316186765
+qdiv:-630502736561/79958533096752240,-705956121098/327213288587355799,256428699470/80995134791334257:206308873893452061172472667239/56447215873669265291942759520
+qdiv:660718319453/697816356986416684,128827317994/37354325475235679,331980136084/301012355599229933:24680687152298103397985363587/89897809722903725688255011896
+qdiv:545833880297/25947106528604223,8458087019/90279863958356590,720827317409/51875766695198665:49277808457075055538901107230/219462884910197530744881237
+qdiv:44847037444/5916668180191961,258200335112/6285554319853929,953656869133/47501466102410949:70472122484696276618379369/381921426718017882672108658
+qdiv:-160898376199/4244945324446856,927280098477/5862228193719167,=1:-943222997277410780922906233/3936253318482561347233038312
+qdiv:176768268366/3002473163637239,48101070360/1068329140204261,=2:31474448693140808084117921/24070362149687771109189340
+qdiv:951576739240/465019676388521,207183722946/207969918137525,-162267142743/832527824784031:98949668280657886691990500/48172253898658956359351433
+qdiv:50497726912/167462116853589,561688826809/565768492770317,-23899967761/571729295367736:28570022843329314205671104/94061599950444071831067501
+qdiv:769692991889/77684301794679,=1,667256125514/92489368710909:1
+qdiv:289207008385/46369327373772,-371984422048/18704673822691,=1:-5409522759077686040264035/17248667443887083093725056
+qdiv:584171767751/2720004210686,=1,428825886595/4631070272424:1
+qdiv:820600220165/1539493346318,780404246878/3986857306711,59567377973/1411194292060:3271615983653485532027315/1201427145506990824295204
+qdiv:-398300561149/618514875987,-626035084114/392429382255,852340023938/456860499943:52101614387840641003665/129070670804760607923506
+qdiv:91238813259/372867824401,672788008343/125652609006,163390268350/18360751511:1042217720782234146414/22805545541266931543413
+qdiv:-448368178212/59572694995,=1,525642488427/25427754721:1
+qdiv:180771359707/24203640124,257130797261/27852202428,-904507763905/73268882369:1258720125936041692149/1555875320425612225091
+qdiv:-305344025090/2609111987,165179438933/5095448550,471583662827/9986485010:-1555864769896004119500/430971654126024789871
+qdiv:18656226690/3750570061,49208551961/1566294696,=2:29221148911920636240/184560121730089439621
+qdiv:-507207818414/660318275,441940040115/475326707,=2:-241089422091380582698/291821084942167601625
+qdiv:-117224089919/84114141,716572188281/615080131,=2:-72102208583734299389/60273854081746581621
+qdiv:32648685593/8729669,=1,404404757551/92590568:1
+qdiv:11283539119/1423144,673710725321/52857428,175857709907/93503240:149104714141931483/239696844119057306
+qdiv:-783312088280/1307187,=1,-999024378776/8099417:1
+qdiv:-335550743735/9259612,=1,110401498541/2695293:1
+qdiv:-969453169592/714537,-142206723743/5688,=2:612694403182144/11290218418127999
+qdiv:915427154883/429041,=1,=2:1
+qdiv:33170923218/1141,492375916059/48304,-152255782445/12013:534096091707424/187266973407773
+qdiv:66307453504/1149,-380214630350/90741,=2:-1002800773067744/72811101712025
+qdiv:115050365732/105,-356906258167/6917,133352622384/2245:-795803379768244/37475157107535
+qdiv:-936999502170/2803,-22830683342/699,653640693595/4907:327481326008415/31997202703813
+qdiv:299176277149/342,240000696411/4,755800068407/466:598352554298/41040119086281
+qdiv:-182582420949/29,133253307768/5,-631023253657/163:-304304034915/1288115308424
+qdiv:936258791901/32,-530850202731/22,405531901705/82:-3432948903637/2831201081232
+qdiv:407182068269/13,170897351552/27,=2:10993915843263/2221665570176
+qdiv:148775056789/4,302163295511,99960897446:148775056789/1208653182044
+qdiv:-337133478853/9,213727099090/3,=1:-337133478853/641181297270
+qdiv:2931561288588/46490752158254610139,-8202572289073/5477030782824843748,406508166805/409333849870858141:-16056251419334141316586635547824/381343755351460032640212424711147
+qdiv:8659279723725/77988438020199829427,472793658484/11699334077378093301,=1:101307806357325053531850553266225/36872438931022959247544091408668
+qdiv:2933595046594/2949357762979009185,3563536035074/8149803984266631315,4953133863743/4139113595975136772:796940819965221171181561483037/350338088956698021793464271823
+qdiv:-4417286673431/7291794623128083428,=1,5735393868933/1602164499207861679:1
+qdiv:5248399908431/133410821320193982,4294585586137/263895726266579654,2738534220357/842657575741413097:692515152786424448774583831437/286472095138201924171005013767
+qdiv:4823557797176/919788364227952961,4539296003171/202991457794647718,=2:139877289857927988799859320624/596455949357591266717470691333
+qdiv:-8420302353377/39920399284053083,-5878820386633/66459700639056554,-57753189302/1760668157424275:559610773695778812487195882858/234684857153620681793355639539
+qdiv:7389413759263/1342000762039062,5356497784623/12667867863288484,-6593133123716/2889567465913753:46804058544754751951948113646/3594212054412306699594471813
+qdiv:1110445958551/1731649423193452,9842168648143/8566872566929873,-784869046327/167483466404282:1359007002766958389525956289/2434740808932786168687079948
+qdiv:1750996678106/4784358421053287,3800412570471/5372315012242984,-8798822160864/7712445715859279:9406905740176459704104908304/18182535885009697370933688177
+qdiv:2392372723343/980802467194173,-5448032534257/790892614293517,-6821479423957/326036850666889:-1892109917529246153239467331/5343443750953388433293284461
+qdiv:3989933324048/125562720671257,=1,3984983239471/152537155573207:1
+qdiv:4001595047662/49753925398623,=1,-9759772064070/51453270252949:1
+qdiv:368358730412/8572667880419,939557773577/12062683819407,8877992040917/39600926316690:4443394897078137606705684/8054516747341535313888763
+qdiv:1215069339240/989318778961,69044090164/8028108572887,3367060670233/4440041254459:12767943166236631504170/89406564104085955811
+qdiv:1791644247845/5689125725259,=1,=2:1
+qdiv:5606399066403/368046160633,-3784609207827/3426986245,=2:-6404350828181307542245/464303629479008974291497
+qdiv:-131513275529/98691678493,-561412154288/53531566077,-1122072538634/477295425653:7040111598983370629733/55406707833053807327984
+qdiv:2966189201493/3188846587,-765990729969/28303317097,94779711197/8832856319:-27984331179851201608607/814208974978428088601
+qdiv:4487898063908/86671538827,20575135814/82013021801,-4824743345930/15244374571:184033040877976247629154/891639341286949625089
+qdiv:6640651737996/5578359755,-1524912145445/1866824798,-1206385524772/935902225:-12396933339372731624808/8506508542061094565975
+qdiv:-1670244987890/2390269259,211444100122/435503801,-4113147761077/5387610014:-363699020413646984945/252704166259267374799
+qdiv:3616096167490/89600697,-3281988440649/45164705,1140366335303/460713772:-163319916656316440450/294068451828093532353
+qdiv:75228599651/227555070,4602761483680/8510461,8893663369183/844450330:640230063414449111/1047381711612106257600
+qdiv:1795848602659/48671731,2894778221972/9864249,-1468924406276/60038807:17714697782930438091/140893866924479473532
+qdiv:150328765525/5091087,1032046096177/24250562,1454940060232/550925:3645557048747475050/5254236463647474399
+qdiv:5125626061499/940322,9381566963714/9633539,-8717701934147/1648464:49377918562867014961/8821693810453475908
+qdiv:-2858213327627/534239,3443629667062/7382473,7810993394329/9751719:-21100682719446481571/1839721269701535818
+qdiv:-1463079225989/126068,=1,-6765832125078/62359:1
+qdiv:1136379360139/124039,-504843410569/55521,6082255198462/98425:-63092918454277419/62620271803568191
+qdiv:-5785459125301/48585,-980138141280/17669,6000542902487/97411:102223277284943369/47620011594088800
+qdiv:-7679165118448/26823,-944998596479/5462,1824880606740/11483:41943599876962976/25347697353356217
+qdiv:3243495212743/8274,=1,=2:1
+qdiv:-5971611956701/476,1643325077002/3767,475412157786/739:-22495062240892667/782222736652952
+qdiv:2952006102878/561,-2920328989442/43,260516724704/29:-63468131211877/819152281538481
+qdiv:9857529529369/141,664372705021/114,-6783178462275/902:374586122116022/31225517135987
+qdiv:5524525978566/67,4357728100577/48,=2:265177246971168/291967782738659
+qdiv:2336151251737/30,=1,194224488061/2:1
+qdiv:-415797686927/8,=1,-3430578037345/3:1
+qdiv:-323787783182,2111647170213,1892571894592/3:-323787783182/2111647170213
+qdiv:19507584899771/19602559368642654516,-98762473989467/63334639758731491371,-3928554750602/4788014258733220903:-411835287396622150572883462125347/645332419924184274699173167994324
+qdiv:55521794790863/72416102594186986653,6390012176892/15510036414312966041,=2:861145058994297080790192816083383/462739777379915195047434279022476
+qdiv:61284142285049/2628054567745986049,=1,-44698994133307/3227806563441401147:1
+qdiv:-85595920452185/5755403767929246941,45867122342099/7759255048184778135,45612340440994/3866169183382889141:-664160577872639158424643100974975/263983808751788330415801251269159
+qdiv:4740740764385/24661806310764913,3530577952996/95659364762369765,-69284592611657/403777287873565361:453496250024140373610112819525/87070429641844221178520029348
+qdiv:20986114241917/947849730677321165,25408740172553/922531137812244018,42932138005871/490205905567788427:19360343849853428823690688102506/24083667529404391955545898984245
+qdiv:45088960299948/94417228575271127,50050142431591/43572012598861909,20043424278442/2756764567254895:1964616746258918695428071880732/4725595738188403692879874973057
+qdiv:21661156181730/71263658579336941,45008374468118/4277846527853817,26745019699809/84174122749515532:46331550880656462369663081705/1603730715653453519692992073519
+qdiv:99154176787717/8705129313567042,-45151880678379/791205466934650,-22406681696383/1924187101524921:-39225663371923231697880847025/196526480028019185473628192459
+qdiv:-5609307442339/94365505564204,-14842593099555/1569343315609241,=2:8802929139831877689263054699/1400628801723273247416329220
+qdiv:-97037008499074/756578572377141,=1,503224365293/860417586944670:1
+qdiv:85000145508250/380984289349707,-15377953570116/246971712665843,27541060282194/114009089402725:-10496315756509182254824852375/2929379356281716958334278006
+qdiv:-24399306423841/29748858502501,=1,62060968306792/72768955027007:1
+qdiv:-4232559885721/1925922878561,864465944283/775519705501,15493915917617/18579937913849:-3282433596089696135051221/1664894739831468401216763
+qdiv:15584390849814/2278161614515,54457886654043/1079434289611,=2:5607441955329714560494118/41354622327616490710744715
+qdiv:11500059385610/2919980131561,41696366394311/9941918005064,-32114194968938/1137740395947:114332647465101300708729040/121752561429675892981949471
+qdiv:-31278600650774/453275229047,-28532854752978/575231763625,-3852037577017/756431205514:8996222308033400370647875/6466618136760442777675983
+qdiv:44062310842317/210587042386,-55360722545765/100402527517,12610888787411/239675278392:-4423967376808340040536889/11658250825264599879795290
+qdiv:48958684754698/12723573349,4149226003351/3090304164,91252399807903/12674198651:151297227361406547962472/52792981395214568292499
+qdiv:-88974567840351/35825259835,14381460656143/10545670717,97792216817499/5521151606:-938296494631719471701667/515219564813152563916405
+qdiv:-29910765212475/3946907284,=1,36882758665041/2632441948:1
+qdiv:12047819336467/160596922,21879038061983/8612278458,-76714046143249/572675448:51879587468665298963943/1756853084537657508163
+qdiv:78772359143669/473800927,10721848829934/52677443,=1:4149526458766152558367/5080021914776594548818
+qdiv:18817085731832/220202645,46482990078371/128558081,30334199853605/727511244:2419088431696802534392/10235677362766051491295
+qdiv:1071383129760/480581,=1,=1:1
+qdiv:59583931345369/53336138,-86968002500/590691,-24368993907767/80312012:-35195691990327359979/4638537382924345000
+qdiv:5688670904574/472795,75880902224492/703611,-80911142949749/9592736:2001305711919108357/17938055583614347570
+qdiv:34034170400721/362423,19314454819243/6528148,6009826067910/6552391:222180101433125994708/7000002658954505789
+qdiv:83460851334154/339967,65893345957783/584029,66032371258108/62613:48743557543834626466/22401563145229613161
+qdiv:696783133091/32893,37868822555967/926246,95224409497087/888005:645392589893006386/1245619180333422531
+qdiv:37717285918991/12822,-1013012164984/227,-18964497863773/15698:-8561823903610957/12988841979424848
+qdiv:-10788708465143/1210,35785601092532/21011,7989331652889/78460:-226681553561119573/43300577321963720
+qdiv:88903457578888/8873,3656416213577/1396,=1:124109226780127648/32443381063068721
+qdiv:12369335335111/1726,49037936736719/2202,=1:13618638203957211/42319739403788497
+qdiv:12617072789709/796,-14476116805342/121,77649458159946/637:-1526665807554789/11522988977052232
+qdiv:67256470760364/343,93944013181019/811,37737599056319/358:54544997786655204/32222796521089517
+qdiv:-91036418449252/85,=1,-14624790219589/71:1
+qdiv:90733799845020/23,12126352178876/15,=1:340251749418825/69726525028537
+qdiv:16289285460967,75541729906965,31946672959257/2:16289285460967/75541729906965
+qdiv:531095972608,-5291079364402,12305754948727/3:-265547986304/2645539682201
+qdiv:160966533905511/4967535563229348506,-442581751532572/8984740788208442429,495627298842758/79806562952710497373:-1446242582717381874997643569326219/2198540590374386626354894598537432
+qdiv:846754392871971/52993412627792440100,-675514445173562/91617804931552670537,27007423378808/1709931290008410469:-77577778791079552140504662184818427/35797815729116844431852155988636200
+qdiv:45614023605550/1179336166017880593,811804712592947/9699287451192063895,901835327286365/3950301615799586609:442423526755689695993353876617250/957390657304613583282558459977571
+qdiv:464881279654941/9833448339137766220,1646029459597/2342068146526146209,-832981812917597/18521573988396140:1088783636996150710534902035268669/16186145655645954516040321413340
+qdiv:4229214776561/171585302869236077,295560300000344/195031349213283619,362544544704566/882044098766689437:824829463985447643862206454259/50713803591681301033130117210488
+qdiv:-783158820408286/503902970658703793,28022392112882/393792758740011325,-148579890099548/819284251472506133:-154201136210076013184280381919475/7060283315322135516614328780713
+qdiv:60027070722089/3527765978642153,37939143520707/1586793930078527,=2:95250591462205287902363482903/133840419771172027935698562171
+qdiv:141700790775610/12344985164771471,448607065704321/72973195171472846,-244344912157487/80621772408426809:10340359461220627648694394086060/5538047570931503297279622226191
+qdiv:-444095239925813/951645354772783,-163717942365872/3710144267118465,179957355330809/2863453381499460:149787037133214031805625676095/14163765395040027237637605616
+qdiv:490326069822452/448476138248369,=1,-236690894605813/2698259084215151:1
+qdiv:165158943072602/623311238414071,-597025041348600/83514840703301,-552484980244026/127678064255807:-6896611410716957117792029601/186066208943603905731528075300
+qdiv:-325041244622487/131017693842736,498210461660640/209968722758669,429274286710968/922035781432495:-22749498325757227956037196601/21758128578367297773853703680
+qdiv:-238357795569557/66187456271695,39950248573653/1546335570925,90339128985173/5004173134412:-73716227579295071828866045/528841066102400696597330367
+qdiv:-359791068917359/63265515095071,-994683695475560/28650227587657,-399535391547415/31717531716704:10308096008488719777261437863/62929176350930046925956964760
+qdiv:308293748883350/6238067591429,78244308628587/806222876113,=1:248553472912393419138418550/488093285869757029225580823
+qdiv:682129460838697/3097305982387,225155835658909/2056462894529,-875562120758647/6664025303008:1402773925479852984592788713/697376516755683065693635783
+qdiv:359301682748683/2940702974,268231011568139/65687387428,-14850805009387/192019789638:11800794419122542088878662/394393866718727380472693
+qdiv:-241203400501853/332337903488,235227035230030/173322412037,846432442456450/482763093159:-623969480097129824597083/1166788951224568448049920
+qdiv:248519658251861/276786224,=1,-394213812698198/83455587503:1
+qdiv:182875910078197/27817962639,=1,=1:1
+qdiv:110911658388961/383629306,687630093841477/2420083617,155379288838024/9875847499:268415487401425129751937/263795055685120695524962
+qdiv:573112467958159/9872133118,-489234981147827/3619910406,238846563705977/489924762:-1037307893285040668351277/2414896429936784290217293
+qdiv:888923070376622/668668973,33510462457835/119313137,507394628224328/514868127:106060200078306542283214/22407406516435585253455
+qdiv:-55229371022605/427082953,265672135996511/172307189,286493947193530/652156591:-9516417671143123007345/113464040371207515576983
+qdiv:86350760735383/34763061,166332560995049/10808478,409535214096212/2843497:311106765897216992358/1927409654719036361663
+qdiv:-526887225315220/62364781,379859437167168/29483203,31678687276584/32988215:-554797250788406080345/846066093204060453936
+qdiv:726480663971978/9429277,621839044883483/2484303,282821010941771/7377203:1804798092947576861334/5863492603621793931791
+qdiv:-266940245547361/6815452,381659084362202/6793379,=1:-1813426258356285722819/2601179169834538345304
+qdiv:-52306849857668/413037,=1,851795607859277/218365:1
+qdiv:-955560519915196/876763,600541379064812/884807,258058491132109/283242:-211371659236151206793/131633115283250440889
+qdiv:83188488364775/7428,=1,909855616022861/57814:1
+qdiv:12513129780980/65681,242195762149522/26907,733634580329507/67945:168345391508414430/7953829926871377241
+qdiv:102024066442285/634,54104883041557/6299,51186522023145/1582:642649594519953215/34302495848347138
+qdiv:-26631109318613/1062,404096111387523/1555,374428590131443/4870:-41411374990443215/429150070293549426
+qdiv:963930172849509/556,429505950038041/339,=1:326772328595983551/238805308221150796
+qdiv:35409769648583/190,402498581379988/269,142263070810850/29:9525228035468827/76474730462197720
+qdiv:979207315133077/41,=1,277675341412115/12:1
+qdiv:729890422328468,-207010622708828/13,=1:-2372143872567521/51752655677207
+qdiv:664184931453977/5,263094792374994/5,612770715664829/8:664184931453977/263094792374994
+qdiv:386777398336118/9,-203562236005259/4,280368609411177/2:-1547109593344472/1832060124047331
+qdiv:846748198636336/76773803058781380969,1801233601495438/43951036051554528101,-985640234538135/13669939898764919281:18607730302427229122582057095838968/69143776892035130477190634596759711
+qdiv:3891890618737276/6895557650428977805,=1,1111068254412479/16589207394191005337:1
+qdiv:125869026052733/9512475498663033351,1424684423763397/9653552384747479895,1477787248473387/726686337264726454:1215083236617203328243121127303035/13552275674376176199352055144053347
+qdiv:-2561702659033141/64484986154218090,3571827544304442/1907338065210223751,-257437056062343/308468989548243692:-4886032993324156667740785934331891/230329249739726743799833423755780
+qdiv:251427380280479/17080042626196354,-8498494882766151/431225536698454495,=1:-108421907002135971034718918303105/145154654856157445334163190813454
+qdiv:4494233115621053/420999973410664205,8502817658603234/225118720507724895,769427242578913/224964781616403409:202347201730411498629276398842887/715937201637537517148588100207794
+qdiv:1082573471098327/16190062236884916,-9285142983057539/68911329784144138,=2:-2869291441631632483178789948351/5781809337464493137192021122374
+qdiv:-54148197646247/67087793059307529,606637391147105/10211716656528727,=2:-552946051825190099886939237569/40697963759315177457206273053545
+qdiv:1552820047883756/1409852829677289,374732588752648/1411748879243035,946186753596337/2784600373889665:548047990566502118911738159865/132079450156304156086221052818
+qdiv:-622450586504533/2629689473880042,42458393126567/46859716926298,=1:-14583929142105291235301954417/55826194741396982866540637907
+qdiv:3985435662577/336228049466,1092888342910160/28572447705111,2326116659781853/93785125130264:113873652051065741394331047/367459715820812046873974560
+qdiv:7163492071774727/830515940073459,3657279442118065/897414555540119,5964135597835892/909513080742871:6428622053706882865266378772513/3037428873982020434994650936835
+qdiv:3607952451488590/49193513780067,-3043939406564413/65486757325344,-866352414070632/19967852787311:-78757702210671087993244608320/49914025047505139104450318557
+qdiv:9495052294801966/38526321702455,6497122364756042/67241074266611,976932655859167/35062261580861:319228758260067099260465478613/125155113182403225758093741555
+qdiv:-8635923474747691/834091522151,-6012381717476054/9878110045469,9959093802197859/5095796016470:85306602427806718417312762079/5014876618482445518753072154
+qdiv:2821313461694584/702859941105,=1,3985236573834282/7019306492603:1
+qdiv:80074080855208/13358267917,=1,-1127102895421894/492325215749:1
+qdiv:2903637249590617/66609940717,=1,=1:1
+qdiv:1317275961025638/30056701615,1903028147618023/12972309420,=1:3417622271590487337781992/11439749839580218061441429
+qdiv:162369131285203/29375345061,1123696767790/4238363,580047582726290/4797152503:688179318381346842689/33008980297761640385190
+qdiv:-4786042110917887/821667120,-223845848166680/444195731,4201261485857429/7441612588:2125939474055953896940397/183926773387073235561600
+qdiv:-3647633785553978/3264747911,-2590574647212125/3171736042,1034451358224699/9321063772:11569331545658450959075076/8457573167775347067620875
+qdiv:-1182656408586511/263603111,-3183826575455972/641377267,67932666203435/9814518:758528935139251758245437/839266590174670462728892
+qdiv:-1010164506152201/73078179,1003381341185915/606903468,8716869883166609/714842540:-204357447344759374244356/24441760418814789549595
+qdiv:2146746992979571/54021,4486129793037235/14014464,4736792350294185/48933406:10028502816740150171648/80781739183221490645
+qdiv:174759124915340/38909873,808299936999437/3899591,=2:681489110687735625940/31450847894556094741501
+qdiv:1331080173593011/170345,1847682196363704/169667,=2:225840379813005397337/314743423739575157880
+qdiv:401756500827695/5268383,=1,-1785129473905456/1874737:1
+qdiv:9588863636181187/514679,-1885957167516959/372023,1236604399361407/932066:-3567277816523033731301/970662549020460941161
+qdiv:-1948318799147741/361624,=1,2127325154839916/20417:1
+qdiv:1427781136273691/76759,-7623865373435316/42907,1659481401097244/10649:-61261805214095259737/585200282199521420844
+qdiv:1719870896249226/12205,317200077044831/19050,=1:6552708114709551060/774285388066432471
+qdiv:8138959322580502/8221,-1163751251034425/1383,7539031083296853/4651:-11256180743128834266/9567199034754007925
+qdiv:169053135509582/2079,8384337995393067/1027,1100360786228606/2923:173617570168340714/17431038692422186293
+qdiv:2884372934790855/473,-3411772457185025/498,7754693992370393/59:-287283544305169158/322753674449703365
+qdiv:9645445945124801/694,=1,-928157555471025/697:1
+qdiv:526455353835711/2,6821493510127697/42,-8165061988695477/61:11055562430549931/6821493510127697
+qdiv:3494561591012431/18,1579558097950769/68,3011416104352409/38:118815094094422654/14216022881556921
+qdiv:-1075752344316397/2,1031504762905937/4,=2:-2151504688632794/1031504762905937
+qdiv:3510047439829528/3,=1,8531234312015747/9:1
+qdiv:-68345423328108071/30673713062451046410,84635933116432261/52124678834577315684,11829641732143217/15648982195593167418:-593747206798476915089200913572547594/432683054531040224143843344222038835
+qdiv:88353531187611591/15437715341399284739,24211922635091389/65206525720651916247,4391301426749866/9028296670139901087:523747891263219677852058701936219907/33979706318956630192030846045273861
+qdiv:23319878514419521/3762815638844579088,1735842457506851/1043622756122083662,=2:4056192647941777068775888487994317/1088609190946197612434792161888648
+qdiv:-44931766141664776/660272913423169311,-20934212682408103/543885314267387231,-15811898876311121/1155697907525944754:24437727748548095710058962184875256/13822293598033858379756137767327033
+qdiv:6078883422776446/585720619063886603,=1,1045243009859441/415511111781051358:1
+qdiv:90440439133569617/948175107640141387,42133680477668241/92268692005881214,845568841006347/5611357858009690:8344821023291981428329461501475038/39950107022188408181066157319590267
+qdiv:4186499515356231/14864815583978242,-18423317485074290/7509262009862299,2871933150211711/1349599950356374:-31437521764971471895320241635069/273859216860711138847895113598180
+qdiv:-29582635046879003/50061021370846352,10045103192105828/55898368325607727,-37052174592310080/96357604503422813:-1653621029892474317451914610856181/502868125572366763986389511739456
+qdiv:13407277935430429/1013601685235852,=1,12172330844000900/902390153283673:1
+qdiv:27360619531891829/446629134514741,4131082115213588/1108810664462473,1247084760967392/7561950200172275:30337746723261895886437065833117/1845061629727170372539949500708
+qdiv:61461830136885063/892616617339285,=1,33738741342160459/830691355475130:1
+qdiv:61440064505101811/137342816799395,-4711908842636087/41515812949603,-24218275768586906/186742521237115:-2550734225605349400573727031033/647146832949617421060066767365
+qdiv:5758080755122561/15095071042602,29045716031779306/2037705119057,=2:11733270630656838625131744977/438447146982952474786587994212
+qdiv:54526928002573683/59702858549279,92640788780483269/77681659329590,-71811590482866045/83384156477179:4235742245385010165548357179970/5530919908454825601037871513051
+qdiv:80792214616474631/6644270819756,63735176539398861/9296933147014,-49380745622098487/1490898600966:375559909044285990116562200917/211736886836362524703961348958
+qdiv:32030499525154974/3954323046161,31366526470107724/1768190715343,-49495147706919681/3289020191827:28318015934088697649997283041/62016689249383006938747323782
+qdiv:9328741686632077/243149745260,2480495311675799/1003030744,2895546265991266/48368547577:2339253678631596761893822/150782950788148707639240685
+qdiv:86704861543195229/19495202697,-67726887612055909/399405679895,79366554520762433/427533781579:-34630414174861729349465220955/1320349402033968246851586573
+qdiv:44938705263692416/75214947649,13088918735108810/42829053903,=1:87485555912259650621649984/44749197156510201930394895
+qdiv:44904786185636646/96125537099,24798894892177726/66253590239,=2:1487551651856539065713149197/1191903545486115802757228437
+qdiv:-40789888748879566/226781493,92548538546533322/4980935825,-18457923779643496/7489800193:-101585909083529329449925975/10494147873275438368704873
+qdiv:69711578560849724/2839609701,-17832323142587131/1317413634,70780014264413677/5219758825:-30612994681241841674245672/16878945929019074475119277
+qdiv:-59818087210738392/689533643,44169679860852171/464682497,=2:-9265472710283227069441608/10152160088199043518029651
+qdiv:13285049487986594/299383163,66537912712814595/528333412,1270866798654711/67428626:7018935524576810218278728/19920330767380344083663985
+qdiv:1503810128215281/2257159,-70775598572813631/84477811,-63395967835353025/15198273:-42346195930418758543297/53250593099671147511443
+qdiv:8428754085692575/2245416,-22542294434269243/25119135,13783461291888720/14173951:-70574337253437786640875/16872276199806368846696
+qdiv:9563262734920725/514036,=1,=2:1
+qdiv:53451507046231654/9484455,47537920203789693/4546483,-80647128625430672/4405781:243016368110072428972882/450871264966434172722315
+qdiv:-44159999533489381/113642,27485426878029480/364853,35852359000720457/949621:-16111908309792201125993/3123498881273026166160
+qdiv:32853589059772384/503717,40780321841499481/989824,=2:32519270937500140220416/20541741377034594070877
+qdiv:79928002171125410/57963,8207223112140364/45757,6211993052732583/4990:1828632797672092692685/237857636624495959266
+qdiv:19663131964133109/36425,71845241352937178/25359,86972744437274535/81994:498637363478451511131/2616962916280736708650
+qdiv:14435384562180968/755,72009011268495388/5897,49643107641306868/4273:21281365690795292074/13591700876928504485
+qdiv:24454205396414067/6880,69532248800465987/6162,26996222231515961/2920:75343406826351740427/239190935873602995280
+qdiv:-1788783461774743/10,=1,=1:1
+qdiv:2169480921871575/32,24356653728462933/275,=1:198869084504894375/259804306436937952
+qdiv:55640518711168835/32,-11942433331158949/2,49472052316509365/97:-55640518711168835/191078933298543184
+qdiv:60550088149390965/4,18432938626319732/3,-64770809459825588/55:181650264448172895/73731754505278928
+qdiv:-7803681495846471,=1,-17883711462854096/3:1
+qdiv:50341568785662927,62590376897604859,80681563059961663/2:50341568785662927/62590376897604859
+qdiv:-203151633689699473/4601599975290251067,525611526456048199/10684809311118564881,-92007105653918839/5233554995228398975:-2170636467216648863175567911942007713/2418653987152422537498561743363178333
+qdiv:65298869984225348/19019228638839514289,56379757376977511/14055232146718391290,964945810921349082/20809092926836677025:917790776546668763561146735400418920/1072299496155034051021485798116154679
+qdiv:-145588071893096095/4173101898033488969,950865051078788090/1909232631512562529,503871559562682707/9612144818358151944:-55592299523459199702887019418644851/793611349886120203227511154180715842
+qdiv:-416108982689762077/6607155238394910018,110992754943723449/1849236166477509591,-268331055516600845/4522919721232620152:-256494593328690673619763717091860169/244448787416768310712157092743870694
+qdiv:25569109100431274/108937408231316295,-72437832965809993/62540068610663445,=1:-106606255830300730275789651105262/526079318745889626493211550315729
+qdiv:877324076175281223/214264808883890725,42146916770679749/32999264126549449,285006538829039936/192084798661860001:28951048914289093786435738190696127/9030601066914945269923974086428025
+qdiv:53167133313707651/16126281481928302,=1,866634487225725687/8471335588786562:1
+qdiv:-404441666294175709/28651204642462452,737283168872077719/15929980120269742,595275127996297901/911315023660732:-3221373851937494010053214312048539/10562025475398550561404400841653494
+qdiv:-696867039120140351/7944197978612428,305556608949512209/6106076808329836,-21961011512486436/271929687123929:-81829301270403260762717504246393/46680811445545827264035485867951
+qdiv:-680855634912930787/1356189151638221,76800812974773809/4396449080201477,115900299432052362/915351235529267:-2993347129862947189365178516172399/104156429393384168102319274153789
+qdiv:858455835027039516/181700684219717,276128875832819233/429408279720099,513501697172110895/688533497518381:368628043334642145377689092432084/50172805671644532495814915417061
+qdiv:316851319525526256/292918890269407,11393663510588707/7832467998606,183243936246901525/329030327691009:2481727820499768843861224399136/3337419271624680006372401786749
+qdiv:425938764355509261/38431838740736,51646287499025181/14744319169037,61598803394948627/2198532513800:2093392362707622954000159317219/661620597573408443663531491072
+qdiv:-32900087887779412/15187739925135,-77577586584555989/5103062080335,20798656203711947/4200421664287:11192746062654396148286870868/78548547271058557114805058901
+qdiv:486662144374613085/7279800587764,370935209793408403/1211133632516,-89246445251861285/6389412265973:147353222681112795182018767965/675083589569104285293074145223
+qdiv:-964120868211092407/359784141044,-101341301532555954/2823707878015,-3905142618376867/213434004577:2722395690926323209655048732105/36460993124171644711757975976
+qdiv:523113306979362837/776795904043,-598929472099127320/298887489003,374389526725869791/822603563483:-156352022787117273091784381511/465245960737238351450759754760
+qdiv:840479323018514793/77550808147,641898923324106797/94049021855,-530841733088610489/198795819997:79046258219243902336497801015/49779780252473669714285675159
+qdiv:128459136724688363/3656348195,=1,=1:1
+qdiv:117942267177399129/15104768300,=1,673568920447088655/16579651733:1
+qdiv:-380358764362707601/4878763095,26907876636599267/4680009378,46112939804078386/9100681911:-593360861407321255383960726/43759051833151076714550455
+qdiv:-687756860919714982/4983016997,810697365335247161/2657532848,-767797307972200547/8201158600:-1827736449331510055462728736/4039718750888655206458995517
+qdiv:-671538226625519919/488528633,212340873444231067/18548520,903467856142920989/292805725:-12456040227327988727969880/103734596633736204897641411
+qdiv:264766040442810006/105576217,906671624054033815/16237552,-17400397472077592/73576121:226271176290748973607648/5038050533098478619883045
+qdiv:198599362591258655/32652407,180852394942204767/534302,330626253412331177/39365397:106112036631234681883810/5905266006577611529424169
+qdiv:193437965129974007/33032327,=1,-712641084972416324/72668161:1
+qdiv:5650691886191629/31580,778039554898468719/522286,-85572216893806154/638707:1475638631235740571947/12285244571846821073010
+qdiv:255988566078185670/3226711,=1,=1:1
+qdiv:119176135632936277/90407,742203087602826989/37340,435710884024344205/699587:4450036904533840583180/67100354540908779594523
+qdiv:601345588172172775/239872,543493254518268378/505985,-428607861122460011/847997:304271847431296841558375/130368813947806072367616
+qdiv:-384629861853292408/8659,25928764268860430/2863,=2:-78656806748998297436/16036940700290175955
+qdiv:16969933057999661/91390,899168628900829159/84974,=2:721001545835231596907/41087510497623388420505
+qdiv:-338452503566548909/60,-471242201877785904/1471,571852972365820021/8097:26203349091915444481/1488133269087744960
+qdiv:-67208679240212206/7945,-147655843020220929/3895,247227362702367322/3545:52355561128125308474/234625134559131056181
+qdiv:372479537607215503/364,287530886573098995/616,172294866607452652/419:8194549827358741066/3737901525450286935
+qdiv:182710333561165768/213,510797940135310553/999,=2:60842541075868200744/36266653749607049263
+qdiv:579561523155053213/54,988155654509496101/36,200878090425916240/7:1159123046310106426/2964466963528488303
+qdiv:515113236713830593/61,-312166546603055389/64,=2:-32967247149685157952/19042159342786378729
+qdiv:292464149557005921,89917333945444994,81421444399876118:292464149557005921/89917333945444994
+qdiv:296110466389461193/3,109472330812647154,=1:296110466389461193/328416992437941462
+qdiv:4092114512174117006/26116630455695638973,=1,-447003756121465797/20917550324131376672:1
+qdiv:259937566541134655/4158701589393004579,1547780345841112833/51410910398305904707,938595196927633599/39410655506871762710:13363626942599952654588701490085321085/6436756584280690243327152586824662307
+qdiv:-1896779359348956490/1347192914723660737,1473868522523514384/1232156863222473595,-5707768245722740379/418206171177904664:-1168564852820271637019025039914440775/992792615388954378876171247477770504
+qdiv:208447940832270699/9600679647480708145,2870404120011924515/3559456450102995519,=1:741961367506113511552059562591997781/27557830415043255728392135816485674675
+qdiv:-4297501973500096783/204423371799318060,2877397514219613038/539249559830239969,8324733346597146387/157919348439263966:-2317426047579514781946227871614919727/588207301863749530458354605484866280
+qdiv:93720929235782808/55293543050375,-7894380025587801253/181187413116917545,3736135546224315869/181899903281616836:-3396210544629034994552431212913272/87301648360171916529438973423975
+qdiv:81994885389922697/294916754436330,9443771936591527133/5056845538523172,=1:69105911727624901444765437205814/464187761529411335843377885990315
+qdiv:-1327130679702964642/1750505879782173,=1,119824008643752477/44623528623225535:1
+qdiv:3879822966686063981/3001133305530870,=1,863100334242503747/3064363459719574:1
+qdiv:4471609326841143121/3136394938408391,-2100659771756104576/2883761130954275,15497169860790465/125833380421061:-1172277560868827200679819871072025/598954425041270209782934871990656
+qdiv:-1428825541118510643/189287913101264,333610284195481532/220738789477061,670131441507861203/870560425567724:-315397220320406686290969132860223/63148394484482295041093957856448
+qdiv:8591262769553056858/438853613359311,2189525401934819634/71978219024849,5936949921650810154/230960129719523:309191896663460373602599905932221/480440567090546674289419809756087
+qdiv:-4064523795777485/244411410943,4019762771700340189/48942084942433,1825370830820857864/84013901689297:-198926268863481870604702521005/982475890687424536786577288227
+qdiv:3308449940543897586/24769809780163,=1,=1:1
+qdiv:5505516603567201356/4103863380997,=1,9200863431181416289/2198737928697:1
+qdiv:299025438242526319/7174665063033,2342598970518801198/2840711341985,-624920076676181455/1731259940133:849444953957579679543172203215/16807362990478315705960265913534
+qdiv:-1317323502669839257/383434104838,1699132754315376723/126762068816,=2:-83493326249184161811746154856/325752723325920927661123442937
+qdiv:801340903278936479/656286066237,2305646751022168759/405803179528,9784332106348628477/2005196814:154924576672907071866862888/720897492310842731598125817
+qdiv:-7034488704242870267/26137866450,1404864734358647884/61096984649,8568167552998854754/11743533017:-429786048376690545870597531283/36720166806981064794567091800
+qdiv:1957064921110117593/22698952475,-2877695287391612383/80652467816,-6543222962701862213/80347703614:-157842115563656338161407886888/65320668566033676195338497925
+qdiv:2797239636828126649/9292862128,4813087393853254410/1395246169,=2:3902837887059395018464057681/44727357561093127896237984480
+qdiv:-4315815575872328781/941797525,2364548726161022722/1932241689,7324535609142564031/6044609444:-8339198777736056212162751109/2226926138040353951048363050
+qdiv:30859738907627663/2542365,6600947823086520511/563823249,2650371430256452002/735290035:5799812751396779944979029/5594006237413787239649505
+qdiv:1239632473056172538/39020573,=1,4893570761803052153/806566500:1
+qdiv:4340355836717522794/84976723,=1,4177413596064433650/4807901:1
+qdiv:5251208912622866942/60282373,1588514721403315667/15272978,=2:80201598195892969102093276/95759436951625758474837791
+qdiv:3180027096600073679/1131489,1551586490431667735/1426711,1709665203917621573/6158822:4536979639017387718639769/1755603046472037293807415
+qdiv:8243752949511560636/648121,9011505934664251587/2857664,2654767072043691455/1609529:23557876028713004413314304/5840546237880529402818027
+qdiv:1059685344014955483/517268,=1,=2:1
+qdiv:7618913893338931327/87339,2570669407313338666/518057,289391906262782051/116872:3947031674841486746471639/224519695365339685749774
+qdiv:700273840899540863/79614,769420078468545381/1045,649456732765994158/34395:731786163740020201835/61256610127194771962934
+qdiv:-187558807564904619/362,-9545050345452388419/23068,=1:721101095484536625182/575884704175627434613
+qdiv:9871582247297764418/7063,1928022567530041238/3221,858557805597948211/218:15898183209273049595189/6808811697232340631997
+qdiv:-6853417837322192169/596,243646027011694943/64,-2802878255693787218/3819:-109654685397155074704/36303258024742546507
+qdiv:6270595962911796812/909,6451237634004612584/717,4154473691343572326/653:374668108783979859517/488681250775849403238
+qdiv:2859818002359754548/881,-978746824548811382/135,=1:-193037715159283431990/431137976213751413771
+qdiv:-163677610836218181,1125556291854647923/21,-543556322760873342/61:-3437229827560581801/1125556291854647923
+qdiv:-2743247019285632266/73,2721276457623268991/11,9892328911405524379/35:-30175717212141954926/198653181406498636343
+qdiv:3970324237073990007/4,2239223157773235406,146642702970818545/2:3970324237073990007/8956892631092941624
+qdiv:1833757668733454039,=1,-8814196290971390691/2:1
+qdiv:41577911849641052701/99022939143770450788,29562744466456608111/56837407285672400044,31020970526416154186/17913773857228432749:84399311067351185113571896143048525673/104549637365170333914120618648568826481
+qdiv:11645154448997394881/94761538126264735491,88207691494542159651/12578224627720796822,25570027647696327707/17624189500133230570:146475368483991438069574417703503868182/8358696520589854489200399496481407873641
+qdiv:36037910341862609485/5084165437585712934,14803543978704731158/4018809000761174679,40592658881592860140/1875002057807619289:2540868042991257484177217842751705795/1320415204391415532618346800916375396
+qdiv:-6362828133579539977/1405399076052451953,=1,-79310041992515227141/9766031882584814055:1
+qdiv:18995499865084840909/132084112242521874,40315757995363267494/108424549445496181,9141557851421924653/395183670085599750:294225502051972481196626700993152647/760724443457415783589919753058309108
+qdiv:-20679072031164937/331072269490614784,60303816476959382024/820747184142174667,32412125947207417888/849382221894135357:-16972290140251822462187296540050979/19964921379972472722742560644478242816
+qdiv:342025503923893090/638329775416737,6081856724756077351/10064175190260298,-12635294626204723652/12747811376654893:3442204591027121039210818623540820/3882230237230318511251099432023687
+qdiv:95772012363596472232/93464593843091931,=1,66811795410951517976/57387498829697707:1
+qdiv:39150280549083930478/221651102097297,27527655361557153686/8200729391818537,-10566813759037632949/1540621706438105:160530428198407079993270396049835343/3050767574521854917099344177093371
+qdiv:775796793430257737/1824356921264078,59648355674434946375/4234888027379937,-48407842369116658019/8912961054912311:3285412552177544656250926732822569/108819890516676835653288543143817250
+qdiv:28476387945046958277/999638881195952,58250700361065854943/221262414969004,29643575123794329851/477719531693567:525062863859610263002381953020509/4852472078151375703306701265899228
+qdiv:366203441988870367/188565554272086,94732323070906583248/862962947506991,=2:316020001685920962364670925235697/17863253007347820007476928001615328
+qdiv:8483230698254754551/15259557038423,23368061392310636478/85223679281645,32515807430078447491/85784287822340:722972132300268572088173474516395/356586265693334541919071831394194
+qdiv:49879409479136730807/66163096356056,-38087887001526926307/13816595584511,-1454659694645612910/17634310154753:-229721209589152224414677275243459/840004179226866288683545915055064
+qdiv:62960436874158600601/6181269755427,-38093682298270231594/6182059511551,=2:-389225167629298487685523755042151/235467326263142673710199028360638
+qdiv:-44149559729162857485/8838649113689,-92868732768946894695/9715947205117,7772268284865525232/3917639152071:28596986097180394710634075583383/54722276171844870774524704398657
+qdiv:2160674978760021747/440085907262,27830441916338793631/444373630892,57774193577066913529/985831440387:480073492744542921823635504162/6123892640127175948232611124161
+qdiv:36779826517186231622/593017430523,19227595668423969206/337403938281,11416362949398192276/562802104127:2068276386031765079995376420297/1900383229737324483921166079123
+qdiv:26089630323225357334/95419525743,10301251794111780015/99138956899,91414665551775455692/70400356165:152146984477946008199958796898/57820032985492584056520319185
+qdiv:-29243000664559124719/43374840118,-10759429621437816793/825473183,449211716437215496/6016537709:1270490149423407156499311083/24562554715302029930281605346
+qdiv:43740120582679037273/1380740386,-10453142250046604709/682904599,5705113158551362448/866195241:-29870329506726074294624118527/14433075665242257503894077674
+qdiv:52606375144331115549/7041068780,44326164670224665111/2919045833,89932878257209865497/5189085588:11812340011868808955042304409/24007967245896760392232102660
+qdiv:18724901946698874513/497209057,618446872748526095/146164963,15390306579353612360/304964183:2736924600217868965334288019/307497386403893657834842415
+qdiv:-73271009353030104361/888009485,6268171386817340605/445545539,-30294808731792985583/748195570:-32645571355269839130747995579/5566195645099402419715638425
+qdiv:-6170226889332372331/27347419,92903445126985172210/30514679,3697622268386381476/88810455:-188282492885145865988946749/2540669440431171711214025990
+qdiv:22447257099357853357/73571392,96930598757046526391/75068541,=2:1685082839900686088401942137/7131319077949382755350606272
+qdiv:18405537170427326117/869259,=1,-1420857565162351747/93018:1
+qdiv:49104082785088634230/2249621,37173384714202722705/3494738,82295002552935357721/1027368:34321180812839016682336348/16725205378829888650868961
+qdiv:31797840681830305220/155259,1587139799259633659/9846,26303565519013168528/557087:34786837705922353910680/27379748677027940251409
+qdiv:49251043005944454115/458557,12656810517669387971/114174,-68275280158906352129/488558:5623188584160702104126010/5803869060550921539817847
+qdiv:-64285887839653334497/93042,15579348394621354273/8674,59955417746039738115/74473:-278807895560576511713489/724766866666180022134233
+qdiv:63842413368795633893/62393,-87956339382997486493/5714,7858337204545049957/43385:-364795549989298252064602/5487859883123362174757749
+qdiv:-68051470229786982728/7677,26179928923183325293/1125,86355329936141165696/9285:-8506433778723372841000/22331479371475376474929
+qdiv:-50081439194849732369/6752,5504600376647160870/1069,14173817213125628066/7065:-53537058499294363902461/37167061743121630194240
+qdiv:47895210529721192309/101,=1,8891562052096223369/598:1
+qdiv:2023765290182261065/98,-3528906224032626601/8,210162627484795020/311:-426055850564686540/9100863419873615971
+qdiv:-55071290496801275816/43,-14530504979971463081/90,41799056582024748637/60:4956416144712114823440/624811714138772912483
+qdiv:2952763925816064856/9,-2794894328282573619/22,33252147556814701294/27:-64960806367953426832/25154048954543162571
+qdiv:-22874728508743973476/3,-97353210331533196276,78585121833788001065/3:5718682127185993369/73014907748649897207
+qdiv:-18829566175245957052/3,-20433551292296144981/4,=1:75318264700983828208/61300653876888434943
diff --git a/polly/lib/External/isl/imath/tests/qdivz.t b/polly/lib/External/isl/imath/tests/qdivz.t
new file mode 100644
index 00000000000..b4f010d437c
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qdivz.t
@@ -0,0 +1,800 @@
+qdivz:7/14189789968569496825,-4,4/56970792418717696577:-7/56759159874277987300
+qdivz:-1/18980926711980671485,-2,2/34538922161232588701:1/37961853423961342970
+qdivz:1/2252731937540774329,3,1/1284950176761593374:1/6758195812622322987
+qdivz:5/5990342115257096507,-5,=1:-1/5990342115257096507
+qdivz:-2/184808182320120951,9,1/93245347658569125:-2/1663273640881088559
+qdivz:-3/953191474882739911,6,=1:-1/1906382949765479822
+qdivz:-9/58755486411564677,0,4/31278777005155811:$MP_UNDEF
+qdivz:-1/6574102725079796,-3,-7/53860936069380022:1/19722308175239388
+qdivz:5/3092518668717267,0,1/1348431717766123:$MP_UNDEF
+qdivz:1/1711104650637484,4,5/891266886610953:1/6844418602549936
+qdivz:-3/752256450310990,7,0:-3/5265795152176930
+qdivz:0,1,1/221073922196749:0
+qdivz:0,6,-9/20067002597087:0
+qdivz:0,8,7/58718030529726:0
+qdivz:0,9,2/620702207617:0
+qdivz:-3/2637082492171,9,6/2399598811007:-1/7911247476513
+qdivz:2/989821160739,-3,1/35099223664:-2/2969463482217
+qdivz:7/596707899127,4,-3/111426253072:7/2386831596508
+qdivz:-7/90687746735,-8,2/80220574745:7/725501973880
+qdivz:1/6207705905,5,=1:1/31038529525
+qdivz:-6/7404342365,5,=1:-6/37021711825
+qdivz:1/669923792,4,7/932900852:1/2679695168
+qdivz:1/447676458,-1,-1/780010677:-1/447676458
+qdivz:-8/632835687,-1,=1:8/632835687
+qdivz:-3/34120079,-2,8/62163153:3/68240158
+qdivz:0,7,0:0
+qdivz:1/4563667,8,3/4687252:1/36509336
+qdivz:6/9767093,1,8/1612033:6/9767093
+qdivz:-1/44242,5,2/127465:-1/221210
+qdivz:3/442637,7,-1/427529:3/3098459
+qdivz:5/99573,4,2/18535:5/398292
+qdivz:-1/92756,-9,1/2349:1/834804
+qdivz:7/9020,7,2/4657:1/9020
+qdivz:1/619,0,4/4281:$MP_UNDEF
+qdivz:1/57,7,0:1/399
+qdivz:3/497,-4,=1:-3/1988
+qdivz:7/13,0,-3:$MP_UNDEF
+qdivz:0,-1,-4/23:0
+qdivz:0,9,-1/7:0
+qdivz:1/2,6,1:1/12
+qdivz:92/54148884014131151533,-84,=1:-23/1137126564296754182193
+qdivz:-19/23897843385077955493,71,69/61266965124498535070:-19/1696746880340534840003
+qdivz:55/6196267973202090504,-7,5/287457924210607772:-55/43373875812414633528
+qdivz:-48/83164040244933491,-32,5/1047923356026875081:3/166328080489866982
+qdivz:21/587480004246184118,-57,15/677609340847439434:-7/11162120080677498242
+qdivz:30/104315744428261859,21,33/4537728827744434:10/730210210997833013
+qdivz:63/43591673951063050,-60,-72/62642630564846123:-21/871833479021261000
+qdivz:22/49235810624301237,22,=1:1/49235810624301237
+qdivz:-67/86699263349277,68,-18/1746465712913311:-67/5895549907750836
+qdivz:4/662982233689325,-70,3/223690708572257:-2/23204378179126375
+qdivz:48/30832308107873,0,-78/969311075733763:$MP_UNDEF
+qdivz:-79/719541528020900,71,29/227964213458863:-79/51087448489483900
+qdivz:46/99191502629977,45,=1:46/4463617618348965
+qdivz:-45/94030959875366,-49,1/739436814946:45/4607517033892934
+qdivz:85/1156056884433,21,70/1021249005383:85/24277194573093
+qdivz:-45/3343573640758,81,-23/371241990007:-5/30092162766822
+qdivz:9/908355558094,0,13/114278107776:$MP_UNDEF
+qdivz:37/482896223634,76,=1:37/36700112996184
+qdivz:0,-62,=1:0
+qdivz:1/224399171,-96,1/829119227:-1/21542320416
+qdivz:34/3276847561,-87,0:-34/285085737807
+qdivz:8/447224053,-69,17/1706735282:-8/30858459657
+qdivz:58/337629635,17,14/309654075:58/5739703795
+qdivz:19/143535299,5,=1:19/717676495
+qdivz:89/21730150,-36,-11/3380230:-89/782285400
+qdivz:14/11625951,84,-75/90670231:1/69755706
+qdivz:-35/6938168,-92,40/1158419:35/638311456
+qdivz:81/4813535,4,7/2110299:81/19254140
+qdivz:17/267858,-12,51/311648:-17/3214296
+qdivz:-13/119265,96,0:-13/11449440
+qdivz:5/42218,84,37/8213:5/3546312
+qdivz:98/47455,48,-49/28060:49/1138920
+qdivz:-1/1148,56,7/2357:-1/64288
+qdivz:89/566,3,8/7135:89/1698
+qdivz:-21/746,-21,=1:1/746
+qdivz:-38/319,2,7/698:-19/319
+qdivz:21/11,-69,-1:-7/253
+qdivz:8/31,16,=1:1/62
+qdivz:95/7,92,-22:95/644
+qdivz:23,55,44/5:23/55
+qdivz:1/60738652894409193768,-551,107/57758377963603747061:-1/33466997744819465766168
+qdivz:110/79622749216992783521,579,251/88218014233937017256:110/46101571796638821658659
+qdivz:83/4082129227447654187,15,18/1341986384427533683:83/61231938411714812805
+qdivz:993/372817934005169,561,163/3344274496871800764:331/69716953658966603
+qdivz:961/240704079603040791,598,=1:961/143941039602618393018
+qdivz:679/875463698688215197,414,-683/864641730477058828:679/362441971256921091558
+qdivz:661/48034471229067507,803,-793/39170031634988712:661/38571680396941208121
+qdivz:301/29669334975743711,779,-15/1858966466467087:301/23112411946104350869
+qdivz:-376/9004373296401219,353,-206/1302368237251547:-376/3178543773629630307
+qdivz:-311/1125853364758500,60,219/4621090656923606:-311/67551201885510000
+qdivz:890/98890870399971,-103,=1:-890/10185759651197013
+qdivz:-368/970340921930931,911,320/23157236509251:-368/883980579879078141
+qdivz:153/17403469351714,-174,1/10019300229250:-51/1009401222399412
+qdivz:-45/41421091188493,-796,=1:45/32971188586040428
+qdivz:285/4042719934577,918,111/3917056138984:95/1237072299980562
+qdivz:232/2392703971997,-223,29/510798153426:-232/533572985755331
+qdivz:-288/16825025249,683,26/102920443589:-288/11491492245067
+qdivz:57/859553008166,-596,384/457223544793:-57/512293592866936
+qdivz:241/26996988926,711,402/76733915611:241/19194859126386
+qdivz:113/64370447211,32,654/51387222133:113/2059854310752
+qdivz:37/20055174,-333,266/1472467541:-1/180496566
+qdivz:-41/1427473740,466,=1:-41/665202762840
+qdivz:331/299809977,756,-955/46378116:331/226656342612
+qdivz:-29/129229071,339,607/422149878:-29/43808655069
+qdivz:809/62921676,331,358/1765487:809/20827074756
+qdivz:-23/2282319,-417,85/63854587:23/951727023
+qdivz:19/1064117,478,637/1700008:19/508647926
+qdivz:418/1515977,194,736/128183:209/147049769
+qdivz:2/2337,714,=1:1/834309
+qdivz:765/922036,-964,997/935249:-765/888842704
+qdivz:-574/71689,948,617/3930:-287/33980586
+qdivz:-407/558,960,817/20918:-407/535680
+qdivz:6/215,99,-59/760:2/7095
+qdivz:-916/8789,71,-23/237:-916/624019
+qdivz:192/103,-275,241/262:-192/28325
+qdivz:-641/520,803,-980/299:-641/417560
+qdivz:-808/23,85,419/23:-808/1955
+qdivz:30,160,114/25:3/16
+qdivz:99,883,92:99/883
+qdivz:249/7,435,=1:83/1015
+qdivz:8669/47763182821761519000,2612,2570/33173836138961742453:8669/124757433530441087628000
+qdivz:6761/57372086615909714512,8060,=1:6761/462419018124232298966720
+qdivz:1411/382658058312182873,825,-3109/4771378321641389271:1411/315692898107550870225
+qdivz:761/867527777386531139,5053,2023/1270134890218434390:761/4383617859134141845367
+qdivz:-9176/793276121303032795,-6985,=1:9176/5541033707301684073075
+qdivz:1369/360850321203415946,4395,-8748/566863280507933113:1369/1585937161689013082670
+qdivz:-6215/67983977826422952,-2039,922/49515404491925443:6215/138619330788076399128
+qdivz:-316/10499786595298753,2815,8687/66197583183800979:-316/29556899265765989695
+qdivz:1606/5305463362124029,1731,112/3026842383841497:1606/9183757079836694199
+qdivz:3055/1662027684799994,-4034,124/192242800980443:-3055/6704619680483175796
+qdivz:-5787/765368742920927,2169,7724/706366155708607:-643/184453867043943407
+qdivz:192/253214519977831,2403,=1:64/202824830502242631
+qdivz:-9511/57149625422873,1022,8816/23226399448707:-9511/58406917182176206
+qdivz:4230/77042165665729,-418,9283/86186701790732:-2115/16101812624137361
+qdivz:1097/8661587667062,8556,-1294/1841284483249:1097/74108544079382472
+qdivz:5073/8529249706045,4830,-1957/777278713702:1691/13732092026732450
+qdivz:3288/146119907411,9777,3763/497379016899:1096/476204778252449
+qdivz:8321/215917327006,6435,4949/764334137352:8321/1389427999283610
+qdivz:6030/96286272709,3144,=1:1005/50454006899516
+qdivz:9082/62592066789,7051,8147/63758112020:9082/441336662929239
+qdivz:4051/1918506696,-1174,7400/4885927323:-4051/2252326861104
+qdivz:-3965/8753839922,977,5991/7987170626:-3965/8552501603794
+qdivz:-5834/689611533,6425,-2453/364281564:-5834/4430754099525
+qdivz:1124/704967041,-5270,=1:-562/1857588153035
+qdivz:7944/57190105,7680,-9489/89859484:331/18300833600
+qdivz:6843/70048130,4671,=1:2281/109064938410
+qdivz:2533/9359236,1758,=1:2533/16453536888
+qdivz:1385/626883,5784,157/3146564:1385/3625891272
+qdivz:4688/160917,3538,9758/811127:2344/284662173
+qdivz:9463/781649,3734,5600/250357:9463/2918677366
+qdivz:691/30478,8036,-841/15767:691/244921208
+qdivz:7469/16264,-5140,=1:-7469/83596960
+qdivz:7515/3959,6138,-6065/3429:835/2700038
+qdivz:13/274,3740,4679/7583:13/1024760
+qdivz:1229/24,-7646,-6995/619:-1229/183504
+qdivz:687/823,6221,=1:687/5119883
+qdivz:449/4,7444,1039/12:449/29776
+qdivz:-994/3,-6901,-48:994/20703
+qdivz:1612,1197,=1:1612/1197
+qdivz:4205/3,3230,263/3:841/1938
+qdivz:2417/5769966068557054097,-28966,58670/6149020325783377203:-2417/167132837141823628973702
+qdivz:30796/2288360383424599467,99939,-42281/20938438853892364104:30796/228696448359071046132513
+qdivz:8506/579725899434273775,77119,-37442/962475407368879243:8506/44707881638471759254225
+qdivz:-61035/3482034023582042798,77561,-12752/1085806378725747165:-61035/270070040903046821455678
+qdivz:6403/315592922992076985,33571,65893/416723435457372548:6403/10594770017767016463435
+qdivz:42598/69939063133387941,43735,4765/30061903416091521:42598/3058784926138721599635
+qdivz:-8062/70710522833104625,3389,=1:-8062/239637961881391574125
+qdivz:29201/20949143115498720,38501,-83185/22636843869370839:29201/806562959089816218720
+qdivz:90114/2645706758131727,2395,39560/6948564113170771:90114/6336467685725486165
+qdivz:28967/9011742303197945,68899,70841/1427120257870104:28967/620900032948035212555
+qdivz:9374/952169153467751,15363,23536/955542414786031:9374/14628174704725058613
+qdivz:51148/254739984446201,82728,52657/828166332061258:12787/5268532358316329082
+qdivz:81421/51545697474492,-58001,7295/10940115310379:-81421/2989701999218010492
+qdivz:30074/21203238537003,-89481,-39057/81001965285511:-30074/1897286987529565443
+qdivz:68431/7698279661359,47986,=1:68431/369409647829972974
+qdivz:-65063/7943806973855,-56338,70937/1359955225665:65063/447538197293042990
+qdivz:64467/215908405691,30481,-35757/415900569994:64467/6581104113867371
+qdivz:-89549/201351835302,99827,23735/207632772853:-89549/20100349662692754
+qdivz:7871/103822521,-89272,22388/34036415431:-7871/9268444094712
+qdivz:-5548/6399177947,10277,9825/12940044851:-5548/65764351761319
+qdivz:9159/2485995284,50120,15415/595065179:9159/124598083634080
+qdivz:9078/1432788533,-52955,96908/495178011:-6/50147598655
+qdivz:47557/12504243,-82563,37658/472974143:-47557/1032387814809
+qdivz:96527/90426700,48323,75980/494535141:96527/4369689424100
+qdivz:-33033/11045147,3862,=1:-33033/42656357714
+qdivz:22621/19382503,89975,19721/94899651:22621/1743940707425
+qdivz:-3547/8566286,16505,-23598/8026213:-3547/141386550430
+qdivz:-74521/2199771,-55243,49586/7659031:74521/121521949353
+qdivz:-1886/42955,-46801,=1:1886/2010336955
+qdivz:16475/254131,5428,8394/88357:16475/1379423068
+qdivz:23/68130,-87120,49568/89377:-23/5935485600
+qdivz:46067/8205,87890,=1:46067/721137450
+qdivz:-17041/835,61576,25568/1097:-17041/51415960
+qdivz:70979/7890,-71592,-52925/7919:-70979/564860880
+qdivz:69860/859,77846,72800/971:34930/33434857
+qdivz:-2713/19,33421,2857/197:-2713/634999
+qdivz:23292/25,-64396,2263/19:-5823/402475
+qdivz:1446/19,14512,=1:723/137864
+qdivz:-4428,48879,-30206:-492/5431
+qdivz:42445/8,-64598,-238:-42445/516784
+qdivz:725105/89205530254624460472,498415,343423/44377628962630043366:145021/8892274872371730093230376
+qdivz:48277/129907785767997567,633952,44806/4308907194103851519:48277/82355300603193593594784
+qdivz:40582/400024522521846161,924653,693295/4356572124867623097:40582/369883874823392618307133
+qdivz:931685/4908062338032376156,-81098,140947/4372557097040418764:-931685/398034039489749641499288
+qdivz:766956/116055603158859563,-526495,91809/510346928234219477:-766956/61102694785123765621685
+qdivz:741603/132214366402214038,479618,515977/280622060822043768:741603/63412389985097092477484
+qdivz:-516699/76045719725268866,99626,233591/68059428628090678:-516699/7576130873349636044116
+qdivz:220269/518413710467221,624520,163971/21127267464610397:220269/323759730460988858920
+qdivz:-28142/1957881267309015,181534,320653/2331263900982418:-14071/177711008989837364505
+qdivz:-690794/3288684236568943,143025,2357/9370516939377:-690794/470364062935273072575
+qdivz:-859112/140095463625325,816822,612219/121557578324606:-429556/57216528394682608575
+qdivz:220971/363994210767806,-560494,110590/4404890122781:-3027/2794747550275214468
+qdivz:-18965/505806570474,717219,-43623/93798137994313:-18965/362774082668791806
+qdivz:-173609/8550763730716,-693162,-19411/825399841571:173609/5927064489110563992
+qdivz:183202/1439642401317,469971,=1:183202/676590178989351807
+qdivz:455279/3670831046834,369898,=1:455279/1357833062561802932
+qdivz:-278149/271832786844,243731,780869/789593611916:-278149/66254076970274964
+qdivz:-106981/327902270288,456307,146862/152267328143:-106981/149624101248306416
+qdivz:-177325/26201489293,232388,327906/60969287669:-4325/148510041312724
+qdivz:387294/30547191461,840749,353120/74968646269:387294/25682520673644289
+qdivz:302341/5821897743,177341,-55465/623909789:302341/1032461167641363
+qdivz:998005/7400105717,957579,-133949/4820770760:998005/7086185832379143
+qdivz:-143240/188037809,86894,60337/619625170:-71620/8169678687623
+qdivz:-288213/115013614,232366,=1:-288213/26725253430724
+qdivz:227311/82086188,230582,831983/50818067:227311/18927597401416
+qdivz:379211/28238460,-975706,454719/36515711:-379211/27552434852760
+qdivz:281082/1807583,231844,196945/2033663:140541/209538636526
+qdivz:14670/147551,989329,416446/5701543:14670/145976483279
+qdivz:691512/671245,324873,482828/621975:230504/72689792295
+qdivz:-112163/289428,737146,786171/133222:-112163/213350692488
+qdivz:10835/598,235729,106069/97042:10835/140965942
+qdivz:584561/52856,65410,-46519/23887:584561/3457310960
+qdivz:352640/4817,820728,289214/4691:44080/494180847
+qdivz:320159/3132,320681,-404140/371:320159/1004372892
+qdivz:-180226/529,-13347,343684/89:180226/7060563
+qdivz:-95731/17,317981,-401174/3:-95731/5405677
+qdivz:-35074/93,-199642,705874/89:17537/9283353
+qdivz:-483824/3,208717,=1:-483824/626151
+qdivz:-33504,640890,558617/2:-5584/106815
+qdivz:29565,707439,781129/7:9855/235813
+qdivz:531715/4028736917662068622,-6375863,3168443/14968317395104615452:-531715/25686674650055629830470786
+qdivz:9312820/86437123986635347829,-3647798,-9921787/17852839666224243529:-423310/14332053091100020388178661
+qdivz:4905097/1681959789098950192,8490550,5024043/8545615644430661068:4905097/14280763687334091552685600
+qdivz:9734997/1577074521689225743,-6832621,-1088972/709315347360105245:-9734997/10775552495458759285362403
+qdivz:-5219429/637213619457793955,922999,4000516/81347433120051823:-5219429/588147533545924362671045
+qdivz:-7759663/763271482741194316,5893021,-7904753/307331388791664740:-7759663/4497974876494995669268636
+qdivz:-7637867/8373635589819800,-9864736,=1:7637867/82603704453776614572800
+qdivz:-1227995/24598537455164863,6580218,6299290/38542781724475047:-1227995/161863738936150024480134
+qdivz:6988198/9489671176695433,-7796211,2820841/7357436554413976:-6988198/73983478814135878404363
+qdivz:4655307/6278254340914480,9462770,-6281733/6153291637649389:4655307/59409676829575313909600
+qdivz:-3031228/480320878032225,-727330,1226393/130648347238455:1515614/174675892109589104625
+qdivz:805552/214495438615263,1327196,-4903014/270461362054651:201388/71169372037105648137
+qdivz:-8334607/59169490017165,4126493,=1:-8334607/244162486369401252345
+qdivz:-2740096/62311500192201,5879218,=1:-1370048/183171446768495789409
+qdivz:6018950/576700070291,4317824,7475008/942911804001:429925/177863528878869056
+qdivz:2223856/5382329849761,-3906006,252260/533340995361:-1111928/10511706343572782283
+qdivz:2243556/156929905105,-3830812,-2435277/814377058247:-560889/150292240908773815
+qdivz:857583/89117603081,-2195895,-4700762/733917585385:-285861/65230966339184165
+qdivz:3208465/408709893,1515642,31276/1253645275:3208465/619457879646306
+qdivz:-4098989/29766939365,4871162,4547567/76483554090:-4098989/144999583891092130
+qdivz:344051/517335170,-8077846,=1:-344051/4178953833643820
+qdivz:-4130140/2212436731,2194454,=1:-2065070/2427545317044937
+qdivz:5542680/216220363,6891467,6087552/929545577:503880/135461408758411
+qdivz:6509555/836740618,6251993,662482/133872459:6509555/5231296486551674
+qdivz:1638179/17457984,-269806,4370443/34189662:-1638179/4710268831104
+qdivz:2432741/2349231,8748014,-5489595/31977161:2432741/20551105677234
+qdivz:4969351/8828308,4450547,-456455/409972:4969351/39290799684476
+qdivz:129047/5679221,7992010,=1:129047/45388391024210
+qdivz:1678079/404405,9368845,2425353/203762:1678079/3788807762225
+qdivz:7313393/106210,5702,=1:7313393/605609420
+qdivz:9380792/29837,3628650,8349541/69163:4690396/54134015025
+qdivz:141835/4553,1259021,651103/91477:141835/5732322613
+qdivz:3409832/4613,-6381406,6023255/7573:-1704916/14718712939
+qdivz:2693799/5507,-7732579,-8350784/4419:-2693799/42583312553
+qdivz:-3649678/783,4922666,1776512/359:-1824839/1927223739
+qdivz:1703289/146,-1364856,-1170358/5:-567763/66422992
+qdivz:6835207/52,5452267,85397/24:6835207/283517884
+qdivz:-981009/94,-4341899,1154647/19:981009/408138506
+qdivz:868414,-9170184,=1:-434207/4585092
+qdivz:-5109118/5,8155944,7055834/7:-2554559/20389860
+qdivz:4096180/71083460296902382853,39235251,45336611/9448238468873105562:372380/253543400608863592157777373
+qdivz:723497/26326545620806342541,54557113,2864637/65009482842561827395:723497/1436300324333986781126044133
+qdivz:-63087064/6014746604181337631,-68334633,56994111/8777928731228646479:63087064/411015501784727972463474423
+qdivz:-15440050/5936703417482625609,25638172,511239/234669451493331560:-7720025/76103111665203681187573374
+qdivz:55799712/219797647434406031,-82812681,79904323/310979304902953074:-6199968/2022448051281770563297679
+qdivz:11215136/271404723528588829,58952266,-21266387/195173683249926450:5607568/7999961727556913625918257
+qdivz:-22341476/2415590020263023,76303502,87999410/29375584889000487:-11170738/92158988971159808003273
+qdivz:-9005355/4510812860318998,21169081,-4695729/14923894399821824:-9005355/95489762815934554500838
+qdivz:41169514/1040429180028139,-24136462,-77184226/2867050860263675:-20584757/12556139683720167952109
+qdivz:28884631/4498836022940958,-17445318,1608549/1242177333646205:-28884631/78483625050060307534644
+qdivz:-517692/132391467827,83742505,2257283/308472757896032:-73956/1583827593779983805
+qdivz:-87141668/980473328502441,-93910964,=1:21785417/23019298863988227665781
+qdivz:75617477/37806359301546,65166173,-65048788/54754409331605:75617477/2463695750744705803458
+qdivz:-24133097/22580980458390,10165227,24383811/20074325876549:-24133097/229540792242098404530
+qdivz:16320192/467694969529,70126387,=1:16320192/32797758431143861723
+qdivz:44162765/6257622442932,44975330,12453293/412188313732:8832553/56287726877254573512
+qdivz:15976849/142509128422,56335860,17374141/76416816576:2282407/1146910615357687560
+qdivz:94840195/85872967721,98955334,4372523/2906959178:5578835/499858129553104342
+qdivz:1591668/9284581411,-66619034,59299561/82774915363:-795834/309264922347588487
+qdivz:1206823/809723910,99568171,1851220/576842863:1206823/80622728733668610
+qdivz:-85914081/8902612534,-35845304,-66045896/1499799717:7810371/29010622970494576
+qdivz:13440820/2754320367,47651570,48865911/5397347182:1344082/13124768977052619
+qdivz:15805143/461814313,31959348,=1:5268381/4919761446849308
+qdivz:-4439951/41512358,63826,=1:-4439951/2649567761708
+qdivz:87711692/59173359,-37321151,18983077/41260334:-87711692/2208417866416209
+qdivz:-79532127/7010743,44205966,=1:-8836903/34435185188082
+qdivz:-31040649/5929246,53863539,27344212/5421485:-10346883/106456724387198
+qdivz:15254977/1604492,31565106,47169776/1230755:15254977/50645960056152
+qdivz:-1314702/219071,-5786594,-13876970/230949:657351/633837467087
+qdivz:8333867/53036,72209074,=1:8333867/3829680448664
+qdivz:93469648/41061,-48263567,-83507719/46190:-93469648/1981750324587
+qdivz:78818449/16510,17504351,-32862423/35033:78818449/288996835010
+qdivz:-32873138/4311,1836189,-5349604/6389:-32873138/7915810779
+qdivz:26267095/2366,-19100210,37380469/1095:-5253419/9038219372
+qdivz:17021179/187,-47068270,11903833/362:-17021179/8801766490
+qdivz:59271380/219,18844882,10502917/263:4233670/294787797
+qdivz:71210549/59,6207655,57674913/28:71210549/366251645
+qdivz:-88171581/4,-27356653,40019704/81:88171581/109426612
+qdivz:70970263/9,44199944,72907200:70970263/397799496
+qdivz:45786297/2,18148519,62016757/7:45786297/36297038
+qdivz:96846563/1680143679448519441,128223531,=1:96846563/215433955166221295447166171
+qdivz:641178113/23637084788031433889,-195838510,-844127047/52534148496309477764:-641178113/4629051465631741845985265390
+qdivz:432203304/1867790824623873113,-180265683,581867535/6107364102548849006:-11082136/8633297146203992431289261
+qdivz:791492251/9077194570872541382,410301713,-39018983/764723471732454519:791492251/3724388481663303633697987366
+qdivz:401598712/629101484430298745,-116768810,-611873995/55698849613345913:-200799356/36729715853079756199071725
+qdivz:94055155/646161833837700334,-56357955,=1:-18811031/7283271910828518545411394
+qdivz:-31209883/602537298237104,372029853,=1:-31209883/224161862490166960265712
+qdivz:223196803/16862631810833754,64519940,21514940/2113398483862313:223196803/1087975992677085158054760
+qdivz:496016327/1750744187829919,571978386,-693142337/5039438258199861:496016327/1001387834853837912130734
+qdivz:839316921/1836121482811279,660441273,801742057/6619092013304984:279772307/404216803163509573839389
+qdivz:-526011832/776825418638849,171589931,-366007747/149875306848853:-526011832/133295419983286213829419
+qdivz:-874798883/297936367252434,15988665,127117837/184563922509306:-124971269/680514966759448237230
+qdivz:200287712/43891754665843,496594818,=1:100143856/10898208959992477700787
+qdivz:-120118254/85593269819273,351399480,-442093373/20946701297219:-20019709/5012905084332037696340
+qdivz:943959960/9218804756549,151648398,=1:52442220/77667609600301992139
+qdivz:62828073/540741708646,-657515815,53734217/983237183903:-5711643/32322384114987930590
+qdivz:45950159/229199443824,6790963,402982057/868439427968:45950159/1556484942629362512
+qdivz:259555952/42104910479,-302245151,-940909904/528170775119:-259555952/12726005025566837329
+qdivz:869315042/36645934999,382102853,163056126/74033612173:869315042/14002516313970452147
+qdivz:-77018238/88942920247,19547868,-610583685/26308049452:-12836373/289774077420480566
+qdivz:22065750/1532507797,132662602,274310661/2637894122:11032875/101653235967653897
+qdivz:648770433/2675318534,168008014,=1:648770433/449474953714731476
+qdivz:166804597/152419962,935573693,-497815717/166801044:166804597/142600106735259666
+qdivz:933126893/254794607,178086796,-10735069/659294666:933126893/45375555198709172
+qdivz:51397159/9285767,107706490,=1:51397159/1000137370527830
+qdivz:178105895/27030313,-834305485,216521075/14478702:-35621179/4510307679433361
+qdivz:401130268/4003281,538052518,=1:200565134/1076987711155779
+qdivz:-25708379/923800,928600130,113823997/4498353:-25708379/857840800094000
+qdivz:332976289/259940,255080279,848673264/268067:1184969/235962874460
+qdivz:-936148364/84001,-905995411,-39958671/407233:936148364/76104520519411
+qdivz:854254667/15661,-901412190,834007367/56:-122036381/2016716615370
+qdivz:42260654/5561,616640749,207309077/42644:42260654/3429139205189
+qdivz:664619865/9433,509452304,203966830/4141:664619865/4805663583632
+qdivz:259028563/2828,364316648,406720073/2225:259028563/1030287480544
+qdivz:130594031/195,97865363,=1:130594031/19083745785
+qdivz:295389723/478,-625249910,939847596/815:-295389723/298869456980
+qdivz:665547887/87,961350652,72648508/67:665547887/83637506724
+qdivz:434992091/6,68620494,=1:434992091/411722964
+qdivz:222412585/2,301910131,=1:222412585/603820262
+qdivz:-448528340/9,676248718,364885727:-224264170/3043119231
+qdivz:-7851824870/97663123831315122169,4309784371,3802633873/30968200362702972301:-7851824870/420907004711239553899911820699
+qdivz:-6597972451/80277297254646055387,-4726423861,614506788/44782747244718572081:6597972451/379424533240948909290644389207
+qdivz:-631085275/2899211669922691298,6256200760,1109385858/1477376676238012019:-126217055/3627610050554242087958597296
+qdivz:8122235215/7961846503387897018,-3385709171,170279399/599714842989628708:-8122235215/26956496724614685504246152078
+qdivz:8261293608/498905904925989803,9279441956,-5669550521/863022032183383926:2065323402/1157392096566594213196593667
+qdivz:4361752127/48434501579131773,4643568393,2837826733/313554877060481877:4361752127/224908920663564889484850789
+qdivz:1238532920/10342162106427481,4398535564,97283990/2793043923274571:309633230/11372591958443607041358571
+qdivz:1061671387/8926232998705307,-2409354436,=1:-1061671387/21506459072200213677191852
+qdivz:-478800359/400345400504704,4108770541,=1:-478800359/1644927387818574327124864
+qdivz:2240956275/37562621401834,-2396455893,4846367786/7863206958381267:-746985425/30005721804984336769254
+qdivz:-259707383/982049805001181,4636408668,6879601421/49291522336164:-259707383/4553184228315185338636908
+qdivz:5932730501/332075016507041,-3894649593,2459475717/779834134547543:-5932730501/1293315827884615512284313
+qdivz:-2057182763/13014783789192,8587041446,-4768423874/14397276670449:-2057182763/111758487808520630851632
+qdivz:544766933/18794715195475,3843484670,1238159/14363532070842:544766933/72237199730824215868250
+qdivz:8675465767/2586185536443,5059401119,646332059/108654428878:8675465767/13084549997021329479717
+qdivz:3854967983/5468883986994,6390198126,-6884594048/8486977568151:3854967983/34947252205000467173244
+qdivz:541574464/220372973361,2389280993,-4542506150/573414247061:541574464/526532956622332627473
+qdivz:144295607/6358031172,-2226616241,1616092046/415267417411:-144295607/14156895468359464452
+qdivz:1715167848/17579438791,7716353084,2811755179/17556657680:428791962/33912289182480520361
+qdivz:-1808697444/20783950595,5667762702,=1:-301449574/19633083330425284615
+qdivz:5251262150/9823505053,218984165,-2695819927/4710996795:1050252430/430238410280897149
+qdivz:122042670/3353616721,1385474924,1555979149/4749223195:61021335/2323175935826302102
+qdivz:2041370077/380755116,8288872003,=1:2041370077/3156030421011417348
+qdivz:3260509647/206408810,9791591411,=1:3260509647/2021070731150730910
+qdivz:7724750931/66875293,8447158841,-620411053/9335500:7724750931/564906222509415413
+qdivz:706240133/12748079,-3365211444,-4450693274/12511769:-706240133/42899981339816076
+qdivz:-4328713944/3919369,-1733697840,45793219/349446:3403077/5341982365930
+qdivz:818576409/220484,9554360290,204076967/1272406:818576409/2106583574180360
+qdivz:2094971528/577573,5542056593,1522762903/828023:2094971528/3200942252588789
+qdivz:299769258/28325,3451090138,379284289/47694:149884629/48876064079425
+qdivz:2123785501/46271,2031913159,7477551790/28249:2123785501/94018653780089
+qdivz:6633067290/30347,4413188467,5089795320/58789:6633067290/133927030408049
+qdivz:-7112896220/5109,-9041858703,430997275/23:7112896220/46194856113627
+qdivz:563583963/22,342636729,1107784533/167:1479223/19784798
+qdivz:1874300309/184,5945511402,1330452647/672:1874300309/1093974097968
+qdivz:6102614776/341,4776190614,2538216797/925:3051307388/814340499687
+qdivz:283161881/17,-4413775423,9396385745/58:-283161881/75034182191
+qdivz:7062815342/5,5942475325,289745847/4:7062815342/29712376625
+qdivz:5072516583/5,3510162870,318579195:1690838861/5850271450
+qdivz:2105745668,3143294016,1921002976:526436417/785823504
+qdivz:-1047110342/1520484401571884685,33570074404,-12800824587/53544087850846460:-523555171/25521387245444791714979051370
+qdivz:29090953702/20807090234619537879,26907026532,343923157/1724556694370271427:14545476851/279928464498313005317916002814
+qdivz:20274428231/782012114750379463,-88508960784,2548101185/1234460670163112687:-20274428231/69215079597054243839785978992
+qdivz:364228775/25798969587651672,93590422630,4800580791/290037163980705493:72845755/482907293425367362341227472
+qdivz:30300488563/217177830796613151,808037800,26450907691/304742055273554844:30300488563/175487896605667537985107800
+qdivz:84660469437/541808431985810570,-91050654470,6869670021/226059831962560205:-84660469437/49332012329672534151943747900
+qdivz:13781377279/60189448291173846,-36341022321,81142451811/20267863492743986:-13781377279/2187346083838224044777416566
+qdivz:20924076749/75205484440042707,-68511555523,28223428025/76572972653264741:-20924076749/5152444722848098485121720761
+qdivz:46695010459/6765513820287504,19044605306,=1:46695010459/128846540399663729123896224
+qdivz:-66175030565/5858633997091474,93479386801,-6761739565/4747871813360411:-66175030565/547661513539602607025234674
+qdivz:29131927391/449117587317440,27430643163,35826296405/904412982359957:4161703913/1759940610847455863808960
+qdivz:12733873489/203020759589798,68338967211,-7646512609/133308860316557:12733873489/13874229032759519332113378
+qdivz:-645828418/378314206231,91802202116,11814523540/19896454006763:-322914209/17365038611886184292398
+qdivz:55466225485/59966137745571,70085230918,-14564033191/25111688968965:55466225485/4202740611158939466764178
+qdivz:-14856273101/1292859110750,39649293376,=1:-14856273101/51260950175961225392000
+qdivz:54049381867/5879084180264,10563421937,-8536204093/2085088741998:54049381867/62103246799270400051368
+qdivz:10813111460/44728598989,94458376818,34307963680/466563642229:5406555730/2112495428922087918501
+qdivz:93261299995/267442344697,9903554506,31033940419/872316913124:93261299995/2648629837919179554682
+qdivz:12549853509/27452668204,73694908624,84554555332/43906568651:12549853509/2023121874778770191296
+qdivz:8281869761/28644261980,6672638864,60920170655/80750564561:8281869761/191132815718345590720
+qdivz:43507585065/1174891541,-53678216040,32027177949/130065692:-2900505671/4204405464091101176
+qdivz:25929389985/1191490339,67589366380,-51298542/1154628703:5185877997/16106415412180280564
+qdivz:78073658759/979680027,6317031065,86759420379/440052299:78073658759/6188669164319038755
+qdivz:-1688695990/26584499,18370342534,=1:-844347995/244183176362390233
+qdivz:1093701401/17134573,60199324609,4846366/2474809:1093701401/1031489722063606957
+qdivz:-49418541321/28244834,85425839011,83976874051/40710896:-49418541321/2412838642176419174
+qdivz:79131936038/3214193,-5558256386,-26510849221/5257598:-39565968019/8932654384043249
+qdivz:-44020502387/1517047,10832005700,-20237312053/142503:-44020502387/16432661751167900
+qdivz:99090532609/635608,91162874201,92103313957/556384:99090532609/57943852145149208
+qdivz:-10413698662/166089,-12227395873,-37758281071/634722:10413698662/2030835953150697
+qdivz:2134574971/96453,42160589664,-2962999062/10723:2134574971/4066515354861792
+qdivz:37471609877/76548,-10791609390,96390037129/790:-37471609877/826076115585720
+qdivz:34436605878/9079,25235264504,-5473970461/203:17218302939/114555483215908
+qdivz:-14044198283/2389,54080143852,-29150502929/8884:-14044198283/129197463662428
+qdivz:-32522069000/223,48339047086,=1:-16261034500/5389803750089
+qdivz:-47657246803/22,33211359811,15968947072/113:-47657246803/730649915842
+qdivz:40172527838/11,-82213794272,61587574503/76:-20086263919/452175868496
+qdivz:27802957568/21,79643351356,9332219979/56:6950739392/418127594619
+qdivz:10869296351/9,8043862316,13139931706:10869296351/72394760844
+qdivz:6168104465/3,-35878945212,9249477620:-6168104465/107636835636
+qdivz:855395000587/50302555595400936176,-739889806971,934181630371/48600397687605686625:-855395000587/37218348149629194642613330882896
+qdivz:484488645113/10462406400933872953,705670704066,-83884715081/4591650339979326617:484488645113/7383013691171631206651704526898
+qdivz:-60021930656/539548570059923399,866917492648,964805949204/3786090076085699239:-7502741332/58468011689770319521503208819
+qdivz:-323220399515/1857859825012903162,-788928410025,301006918611/23405385204846061:64644079903/293143679559350883341190999810
+qdivz:392310421262/286746574017601209,468810964000,-451125775206/166219155256444865:196155210631/67214968894444487879427738000
+qdivz:36808331478/114061000248894023,792934455019,322932243230/14273224315648399:36808331478/90442897071278805484991451437
+qdivz:-854660221869/89384740128760649,-840396118326,47272992199/15238716217232049:284886740623/25039529547262898284245517858
+qdivz:364501470786/21056530096076939,437727978403,-169280538543/19694582326526369:364501470786/9217032351137685869618348417
+qdivz:71356988859/8140449733588631,579541019218,69993159032/6814665237998029:71356988859/4717724535496851778477310558
+qdivz:-237216301461/7153189855202122,-161521837361,-24951260167/8892014308929978:237216301461/1155396368404312289466080042
+qdivz:431477529919/178167681211025,-114268327380,=1:-431477529919/20358922925156879565364500
+qdivz:136650073403/64126482201233,196314646772,114459442486/14287429741873:136650073403/12588967702066001417869876
+qdivz:254431970614/7700634905305,510462127446,-344404274238/84068115219161:127215985307/1965441238223458525750515
+qdivz:557911675619/47397240043195,418224715021,-700096857791/79702988081428:557911675619/19822697209847158605332095
+qdivz:509038039199/6767048040929,-112750471412,-57732832309/349479521105:-509038039199/762987856682395820421748
+qdivz:314926419471/416369156102,370112646694,101848419292/3456057303355:314926419471/154103490366658460226788
+qdivz:669453679465/415999590924,504198456391,-678536387896/77061621151:669453679465/209746351603168253395284
+qdivz:996528817883/413322921728,812027139903,=1:996528817883/335629429987139374512384
+qdivz:492391623289/48007797318,7318358317,3301219779/801312566:492391623289/351338262783035593806
+qdivz:477172365974/23061409419,-801074911982,627397031659/99184274295:-238586182987/9236958260253145379229
+qdivz:156485412607/5990175067,451647154411,916340057749/8763032403:156485412607/2705445523434271270537
+qdivz:-4814205663/243854698,67090415688,2686305709/2020120843:-1604735221/5453437685430567408
+qdivz:-549975755753/904821260,98226499545,752428923516/928266565:-549975755753/88877425083696326700
+qdivz:-309048114689/24846497,-1027875635,-731863243448/852411331:309048114689/25539108881400595
+qdivz:735435298793/17969395,-793419545872,=1:-735435298793/14257269220494587440
+qdivz:112260296237/20255278,879986635350,=1:112260296237/17824373935298877300
+qdivz:849848647754/9226151,940056683244,3943593549/6913084:424924323877/4336552454084156922
+qdivz:156304200464/4695153,280896701707,=1:156304200464/1318852991709726171
+qdivz:12581766711/139577,982981763154,=1:1397974079/15244627283971762
+qdivz:863623603829/424182,672081287592,=1:863623603829/285084784733349744
+qdivz:190774034338/47111,-939969971749,-882099739304/68161:-190774034338/44282925339067139
+qdivz:-293504193833/44336,348399896607,119682154283/44562:-293504193833/15446657815967952
+qdivz:608003901167/1524,473035881782,-7627832953/121:608003901167/720906683835768
+qdivz:66826129837/54,-738128447998,=1:-66826129837/39858936191892
+qdivz:221009262571/863,-39203245082,38984729793/29:-221009262571/33832400505766
+qdivz:828342264708/529,709893608236,400041569779/479:207085566177/93883429689211
+qdivz:221541593/3,-88280231556,238738747697/64:-221541593/264840694668
+qdivz:11413495397/83,431669407366,283046372607/77:11413495397/35828560811378
+qdivz:148010319127/2,283123647274,766433621663/4:148010319127/566247294548
+qdivz:-219763168201/9,403340924550,-394706926259/3:-219763168201/3630068320950
+qdivz:377661739960/407441308456322857,3965410406437,409422859704/8533399553263788433:377661739960/1615672004565010305438863030509
+qdivz:-1577626903713/27731663323669186172,649610924029,=1:-1577626903713/18014791436549869335907349326988
+qdivz:-1441250962158/8452258866175538849,-2826627450251,8230910671546/264485663157889397:1441250962158/23891386927759171604534865301099
+qdivz:7298594401893/3589655286076871768,1676532872705,4840525305175/826954630150879953:7298594401893/6018175088787146414664952292440
+qdivz:9145310463313/352206858008877943,-9694904568093,-4656627107317/287736322428206292:-9145310463313/3414611876623953391939969272699
+qdivz:3287696310569/218686848623222483,7362954795926,-3636594668023/794551016990788636:3287696310569/1610181380876299151381760004258
+qdivz:599942736859/30109315615210643,190070517001,-686708523847/586022538036179:599942736859/5722893185529369294527641643
+qdivz:6159561616093/1221874427807450,3318286558379,=1:6159561616093/4054529489820493155396123550
+qdivz:-7739149193382/3880813118083787,6945256949005,4243108324360/3938879550941241:-7739149193382/26953244276161183291576281935
+qdivz:1077598865290/1420892515750957,-8741057903714,-2560579494365/3856299969810329:-538799432645/6210051877566485960454677149
+qdivz:9251474975963/380092713862583,-3533706170376,4397319568897/444497940948049:-9251474975963/1343135968291168939649441208
+qdivz:5170689991479/478812422664503,7425515194305,=1:1723563330493/1185142973239084926623751805
+qdivz:7874754009227/86289133604325,567464832332,=1:7874754009227/48966048732851832955035900
+qdivz:82573188125/1723837997186,4858404577211,905066106196/67917513655023:82573188125/8375102415898705337728246
+qdivz:-9462453261891/6333904291327,8882376900652,-1608766513594/2059986591551:-9462453261891/56260125168223520744245204
+qdivz:-8513062446331/9309761450169,55542992537,551347179830/367528742439:-8513062446331/517092010747987064388753
+qdivz:-2148550912058/152802731413,9178119603028,=1:-1074275456029/701220872288938832759282
+qdivz:9881319422543/919461731150,9752261044456,2668885280159/266136830885:9881319422543/8966830822562220870004400
+qdivz:174799529246/781938781,8700555467056,=1:87399764623/3401650867966327149368
+qdivz:-5466205515503/29452452729,-4883930408328,8925441835689/10852340635:5466205515503/143843729483006087927112
+qdivz:996316459693/238035368,996971641405,=1:996316459693/237314511547403212040
+qdivz:1902828237558/232472863,3969221099083,431690216313/4984136728:1902828237558/922736192783831684629
+qdivz:-700150402156/107303867,8389748159752,-2823896211587/556014406:-175037600539/225063105174380840246
+qdivz:3646364186929/738179758,4245401666232,6967936345729/416110377:3646364186929/3133869574591934531856
+qdivz:9885648196055/10155847,7815948425404,9809097272675/14454357:9885648196055/79377576368293937188
+qdivz:1619034630643/74258174,9375949496558,-4811471214059/75060117:1619034630643/696240889130616365092
+qdivz:1807183853299/633460,119735977641,=1:1807183853299/75847952396467860
+qdivz:-57391852197/471910,6490287173297,3578414422277/7633819:-57391852197/3062831419950587270
+qdivz:-8336245595520/207563,8055731289499,3690368841008/41405:-8336245595520/1672071753642280937
+qdivz:-8756280094194/474401,2163225064362,2304316378414/178391:-1459380015699/171039355626399527
+qdivz:-6768110876428/4537,3853268548159,7478518386005/7254:-6768110876428/17482279402997383
+qdivz:7491881449711/45820,9360962689034,=1:7491881449711/428919310411537880
+qdivz:4479515335651/4767,6272480778873,-2550653613043/2315:4479515335651/29900915872887591
+qdivz:7706167334141/6871,-8364277232473,-1312275143305/3942:-7706167334141/57470948864321983
+qdivz:-2426531262302/211,-896936798776,=1:1213265631151/94626832270868
+qdivz:-2687168859651/241,421602999976,4265602937489/57:-2687168859651/101606322994216
+qdivz:4672875535991/32,303500575463,7776212095088/97:4672875535991/9712018414816
+qdivz:712016736313/97,-6773597996516,5238170108147/45:-712016736313/657039005662052
+qdivz:547412039147/8,6440922645756,=1:547412039147/51527381166048
+qdivz:-1428482346861/7,-8578332426693,-208991442483:476160782287/20016108995617
+qdivz:25213882136563/37677676095840232484,64266404189577,-44312529469891/58632890416616303769:25213882136563/2421408760899231901491771289619268
+qdivz:-45348211232/48259765821376689,-86097912542683,25703493789011/20122118862740312269:45348211232/4155065097019252383615533716587
+qdivz:-7699657076461/331713197807190681,69957368331562,36084589185595/8895782428451727263:-7699657076461/23205782359437922808235364573722
+qdivz:4499486281079/570447738950937327,6819787346072,41829452180703/8951562452396016457:4499486281079/3890332271692985934718131629544
+qdivz:9448778776929/55266922938454378,-40211563540804,22791382037077/589181316944364437:-9448778776929/2222369383444376336380695439912
+qdivz:-80693445937604/625638820483329699,65119781059396,28243613851117/411802455862213751:-20173361484401/10185365753033296882775942450451
+qdivz:7104789360034/25829280707927279,61192880702082,50820501919963/43237529502234417:3552394680017/790284046490391045278259947439
+qdivz:8521395225131/866934246203151,-82917276854296,50387683303757/41145275653408716:-8521395225131/71883826906897082331043086696
+qdivz:3654753854813/686472765655654,-56741825130219,4118082438861/3391784320237708:-3654753854813/38951717625490926599463608226
+qdivz:-53486312991974/1510968952191653,-40818569959148,56568646790883/6563654620617722:26743156495987/30837795940567768880638295822
+qdivz:77025810489670/955683320748827,16606084180096,99547352892542/681947908769761:38512905244835/7935078836934353698524373696
+qdivz:74081757285323/779580189169978,71513450124198,62733533615096/994702038569703:74081757285323/55750468976020063538632927644
+qdivz:-90918473901171/23110032090851,57668788153374,33840460487482/35925709609791:-30306157967057/444242514954987040163393758
+qdivz:-12377636482606/6273569332391,52950805470840,6788467435942/28776860168659:-6188818241303/166095274663631704608989220
+qdivz:93826301723233/2510365316368,8687161712184,40792305870208/5978756664845:93826301723233/21807949459946763720227712
+qdivz:754174119367/993972659135,93465132406737,=1:754174119367/92901786194729238278592495
+qdivz:3107915597273/143157120432,-70507843259804,755175597775/219130414:-3107915597273/10093699808944340692715328
+qdivz:44648757800580/573796175549,60618257654342,5117941512382/33291591973:22324378900290/17391262205252667597041879
+qdivz:-66400850026133/11907331494,74065123644406,=1:-66400850026133/881917979378039620722564
+qdivz:62277709926279/87663640784,32094657146865,=1:20759236642093/937844831736137230580720
+qdivz:26142101996176/1749516045,84074622586348,20940287104039/705860031:6535525499044/36772475298033805988415
+qdivz:59312790288505/3662730144,48869114267557,77585738312243/4878987018:59312790288505/178994377938361505138208
+qdivz:73640138898581/622848187,-19896806552263,18788319190513/316012039:-73640138898581/12392689888166730297181
+qdivz:19740823110531/278732932,24473700094823,58579762311988/962128055:19740823110531/6821626184318692811036
+qdivz:-7512635132051/87400601,56390496123957,=1:-7512635132051/4928563251922012298157
+qdivz:-59462887076699/29087597,-98512108079751,-53172761880889/67978482:59462887076699/2865480499444240948347
+qdivz:17522488582105/961216,-76067863891111,-3856252477211/1860688:-17522488582105/73117647857958150976
+qdivz:36565698728205/302902,21351159032601,-36216528579083/54119:12188566242735/2155769591097636034
+qdivz:54644193228042/614773,89311395526262,63456896848754/648461:27322096614021/27453117280933334263
+qdivz:19396300373560/247,-57733371755730,-58481097237257/238727:-176330003396/129637662033321
+qdivz:26129074926522/54241,-57172817810638,=1:-13064537463261/1550555405433407879
+qdivz:-47857708640267/48873,-84095778752769,-78411459424021/96980:47857708640267/4110012994984079337
+qdivz:24471666012555/2128,10834057048867,19163873777357/2355:24471666012555/23054873399988976
+qdivz:63633303713482/2687,29541404498726,953013369111/994:31816651856741/39688876944038381
+qdivz:4028083282444/441,96229912034129,36156251433089/641:4028083282444/42437391207050889
+qdivz:5620157071221/38,1464098099632,45826452102283/555:802879581603/7947961112288
+qdivz:44121126176093/28,49295425845300,-98014359584905/87:44121126176093/1380271923668400
+qdivz:2550244740088/11,7860358429697,32007329912968/13:2550244740088/86463942726667
+qdivz:10610786242282/3,-19942871503520,30442870787715:-5305393121141/29914307255280
+qdivz:-10891422163510/3,65100387657340,=1:-155591745193/2790016613886
+qdivz:28206974750888/38115226610958658587,-233840177846781,184067617831263/10199552995144872193:-28206974750888/8912871369376932568520833775958447
+qdivz:239195932154190/21076639992981349247,-514159353179396,914824331702763/33476179921636595855:-119597966077095/5418375792993139989042719660257406
+qdivz:-66879959134324/1938245828723753153,209078692564075,380314134341760/3263898700497131471:-66879959134324/405245903737334354397466935778475
+qdivz:71631704547265/1127077312973478953,-677425993025946,-808670179854036/6156571467702669689:-71631704547265/763511467958073910363035213914538
+qdivz:369630784942559/118575247636594640,613604398763706,556292057837293/356846295264834699:52804397848937/10394041933472886416968552305120
+qdivz:-86151087673799/115845793068186375,862616462453012,956063729712120/826089658093596013:-86151087673799/99930488206542589968510496111500
+qdivz:305051097653790/20518755287717797,895836082087101,-207160117973632/3362842864667699:101683699217930/6127147115417699363488953945499
+qdivz:-963596685314854/20268707545342331,-188056921260034,-12535707088197/650540922052135:481798342657427/1905835369448549878334199349627
+qdivz:-361781987716599/9794167747947700,61965144850569,=1:-120593995905533/202299007730783467390975747100
+qdivz:189992621219183/1819811590183344,793680743322061,618571148115319/5988770433957028:189992621219183/1444349415602818312690629951984
+qdivz:856347688913222/833832195611433,218162022813457,-653168377938073/524530934347885:856347688913222/181910518481576385943015453881
+qdivz:49096910346166/27167376161979,245243955457352,15314702197043/62138236025303:24548455173083/3331317394680752204689209804
+qdivz:-18418259567905/83404618779589,692976050847437,=1:-18418259567905/57797403344315565768168563393
+qdivz:-505057419418589/56875557275862,337407904218594,63663406245825/3267267474824:-505057419418589/19190262581713202780407778028
+qdivz:107117033307349/8727332158297,-351480699835352,-603596441776797/4327920729574:-107117033307349/3067488814693802582700715544
+qdivz:929542050791479/3668117137877,663512077337021,67789990327315/790180646928:929542050791479/2433840022068296146453444417
+qdivz:198372512149532/147050745673,-256607148991758,-639475502955856/973546370361:-99186256074766/18867136302130312015581567
+qdivz:-186632417034836/209907050713,808174748926739,886289373295672/873782379281:-186632417034836/169641578007931045594714907
+qdivz:-433532847360621/40950919442,-576406278836993,=1:433532847360621/23604367090516689792517906
+qdivz:426046356532532/90956948929,290346527980677,-331137473378042/8913098829:426046356532532/26409034317250907387844933
+qdivz:98321029610961/463670608,840238741926244,-202415965355421/170277763:98321029610961/389594008334096646636352
+qdivz:-8445364920981/3222384187,208373591158613,326878150369073/994641488:-8445364920981/671459765137917540052631
+qdivz:-12366828657410/23205153,25335150548712,=1:-6183414328705/293953022380447956468
+qdivz:182273448529439/333188695,-870663173311865,-167558565067223/158996098:-182273448529439/290095126500339127366175
+qdivz:-841149634523738/46300587,-648674774105803,-8859347501816/2523457:841149634523738/30034022813191079006361
+qdivz:-556504745441829/86432147,-538986011588748,=1:185501581813943/15528572728194123560652
+qdivz:302832240895229/9849955,168669637931783,925930262366551/701582:302832240895229/1661388343494355619765
+qdivz:27790516823081/1265414,-488301813246538,-597901356054121/7828129:-27790516823081/617903950707554636732
+qdivz:-155301832641753/1177,299291205321873,288662739041159/190030:-17255759182417/39140638740427169
+qdivz:372814194432298/771897,-14946141179470,-1945868184959/21200:-186407097216149/5768440769004677295
+qdivz:24153012223489/97155,-97727981983126,=1:-24153012223489/9494762089570606530
+qdivz:488549717772225/7997,385195948307290,57330617868723/9730:97709943554445/616082399722679626
+qdivz:-511124198199268/703,508244053643154,-24599890934580/757:-255562099099634/178647784855568631
+qdivz:-571545380467859/5484,706501320657340,-7318997946516/1867:-571545380467859/3874453242484852560
+qdivz:-284559894164173/378,663811328424393,203252169231125/424:-284559894164173/250920682144420554
+qdivz:-109817805722539/89,-620669084280112,39821179505019/355:109817805722539/55239548500929968
+qdivz:11285503834151/3,347837157467787,135711185047364/3:11285503834151/1043511472403361
+qdivz:483084770349435/13,381226764584849,-76288343397587/2:483084770349435/4955947939603037
+qdivz:465649032901606,218384912976294,72781764311433:232824516450803/109192456488147
+qdivz:2587491587702,-476034210750545,547126738337031:-2587491587702/476034210750545
+qdivz:-8100465584109756/15951781239270673877,4434864932667510,-2144439357097081/43731124302263504971:-122734327031966/1071878715630681611032444680055095
+qdivz:2420885235857233/35605779901295929638,9928092538101335,169386594008780/70879024157212713427:2420885235857233/353497477751334607275098664273866730
+qdivz:-4826446325397187/4335807137383577415,623898962956291,3104677505409659/2952033752437342756:-4826446325397187/2705105576592098688280821859767765
+qdivz:3460717723437681/6443180553972666128,8557703279186741,4156537546937142/3658329170710024787:3460717723437681/55138827355124127379787243357408848
+qdivz:6418458390147775/525897417578055896,8516136495382838,=1:6418458390147775/4478614190664069842626272283112848
+qdivz:4636780176511991/360039743434849768,-1921496410524246,1079563866860541/62772477295468231:-4636780176511991/691815074656134293438079131474928
+qdivz:-1880397818415029/25639914407226400,-6097850633731512,4908502670581090/24912440236773367:1880397818415029/156348368316927228082170198316800
+qdivz:9061727133564523/34045084539204615,5247972528183639,6748794006344619/18625898906279159:9061727133564523/178667668381435363770511716293985
+qdivz:2823293208362365/2802436154127691,4344250613703671,=1:2823293208362365/12174484982434577158035769453661
+qdivz:-226020206421378/2415797606868827,-3145163610465586,3727841238983986/2416072176043039:113010103210689/3799039361686841134188549843811
+qdivz:7567999278230394/732026114358407,-3551640041571087,-7309583636430426/277839170663653:-2522666426076798/866631086410337974581762192803
+qdivz:5055638466899535/704743836609472,2779539095014541,4752310879883735/726255451787449:5055638466899535/1958863045826567351435978332352
+qdivz:9361673562558585/20268733803869,7535815261448418,-312199448698385/81273711157128:3120557854186195/50913811176477152039890776414
+qdivz:213432378367195/87716207315137,-9593838267023732,-844717112346841/14374978538996:-213432378367195/841535106378148359979581831284
+qdivz:1415632181545693/2202115097784,3788146011770250,=1:1415632181545693/8341933525129513693692126000
+qdivz:497714829654563/1407922386147,-4578675319921841,-2297925204832173/1152646493548:-497714829654563/6446419481816736986261136627
+qdivz:7238175376569958/872602199065,-1798229516982452,1067716420123708/311724963591:-3619087688284979/784569515471240189107903690
+qdivz:738345515106893/400467504556,-8952340232264677,-3533763215436655/727067491856:-738345515106893/3585121352751316634695368412
+qdivz:4439193856281818/48510248187,-5941306515090639,9229814236640615/58818462063:-4439193856281818/288214253602086958690421493
+qdivz:1236698199957439/43126617136,4908265726375467,-9469441985248292/19058730389:1236698199957439/211676896783145702292202512
+qdivz:-311681312393881/449133469,8687512018285914,-729773020888143/39573781:-311681312393881/3901852409751943988655666
+qdivz:-6619381459773073/8173378245,7168326441455265,579725052503743/3234923130:-6619381459773073/58589443389648729091709925
+qdivz:-81712138569107/178893283,-9704334752710585,-7534731886719068/64598471:749652647423/15926975259113666967895
+qdivz:-2039906652413491/230491475,2966890829958620,38485631968165/38014698:-2039906652413491/683843043561136512764500
+qdivz:1307529988460267/97135692,-255437889763972,9189367430908049/30495394:-1307529988460267/24812136185243136888624
+qdivz:-2353939854827795/25170878,-7155659041948110,478284130849579/21650202:470787970965559/36022844150894551828116
+qdivz:5285315302178007/3864043,6787737381344610,-6416436174036663/5502097:1761771767392669/8742703038074323619410
+qdivz:-1620957348585296/705477,-6328720613670438,-397716845432416/1806409:810478674292648/2232383416185189794463
+qdivz:244904073732822/142115,9255574655214839,-3718997235951973/328812:34986296247546/187907998875122406355
+qdivz:6808168673302291/647890,7830240386186476,203370328672627/153273:6808168673302291/5073134443806355935640
+qdivz:672164644892723/10287,-2016544002156618,820674735348423/173:-672164644892723/20744188150185129366
+qdivz:-4941575984804663/35536,5225959626506022,-1182801330040787/90307:-4941575984804663/185709701287517997792
+qdivz:2600309343681884/9179,3312191343161384,=1:650077335920471/7600651084719585934
+qdivz:5790050438041746/2783,6180418749108229,-3626128271180059/2055:5790050438041746/17200105378768201307
+qdivz:107486754622047/8,8496429460563751,7528748815319577/995:107486754622047/67971435684510008
+qdivz:257452794220597/45,9163478257322473,=1:257452794220597/412356521579511285
+qdivz:4203249688209209/58,2060439753326067,626942582428365/16:4203249688209209/119505505692911886
+qdivz:543611975572423/6,1815241525016751,1962341163379185/19:543611975572423/10891449150100506
+qdivz:-7648363691373965/3,4559746429342130,=1:-1529672738274793/2735847857605278
+qdivz:-918087881293513,5561326460996979,=1:-918087881293513/5561326460996979
+qdivz:51876939499714691/40566929845814543304,-89899615206821411,90157161726220241/15742168992505626198:-51876939499714691/3646951383260846475079804250453881944
+qdivz:-92711941104471994/57341166703993040251,88283676761336977,-83588601643014818/86753416972940797783:-2261266856206634/123470464058859999703545311456967347
+qdivz:79135269280147891/2531825814704286331,70208234934351669,3930634830491194/3988582117396219449:79135269280147891/177755021611614851116084128823736439
+qdivz:29633672003664449/2815846487521571106,99099377722862940,5605342417119218/208728995495935907:29633672003664449/279048634676497041224317165102211640
+qdivz:2100328802578405/93877410719555637,81107589989236009,=1:2100328802578405/7614170537892827983896229599332733
+qdivz:8852742285354040/39609437377376719,94466432126141813,-67648481041296353/37350723131289264:8852742285354040/3741762227564622406488872518651547
+qdivz:20443075139781274/87402553055221425,-87873934817191987,=1:-20443075139781274/7680406250030691855905267020721475
+qdivz:1452523479130/11854581599599,-35488163365355406,78636907153845391/29302687132551467:-726261739565/210348664217252759959311041097
+qdivz:92799074911223618/6644370845911803,-52469970294585343,-45890868424331740/1359965199072733:-92799074911223618/348629940911201190718038634503429
+qdivz:34907583570918158/2475636741287023,94165624835942786,=1:17453791785459079/116559940305054879266393616133039
+qdivz:15873033385646407/99383771605820,73196542989966161,3460464368471384/198333558453857:15873033385646407/7274548510850381916754430657020
+qdivz:1205053067450735/262488203376077,30733894353467375,53421057721886303/633789433238185:241010613490147/1613456942318361773929214997575
+qdivz:-373343591218193/282481077944,73439972957893897,12246923120614379/86081958852861:-373343591218193/20745402725324078148538907768
+qdivz:98454579819453042/381442416277,-37303102933686841,85678232948136701/93297430238089:-98454579819453042/14228985717655155931079110957
+qdivz:28585002988764732/467382454421,-37834555341081422,-25757017600863353/6081527848100:-14292501494382366/8841603668620894913382433331
+qdivz:-45530451111310855/1372526430242,-40793761192434411,=1:45530451111310855/55990515425596635347551857462
+qdivz:23497143673035545/674205230796,-82036200658508885,23227625077965886/378696171279:-4699428734607109/11061847119719389998528324492
+qdivz:-5439825078047807/781667528452,-36280770053733421,62043822362915397/125125654100:5439825078047807/28359499858237138428340794292
+qdivz:52872401646278523/59676713378,67021996329285655,=1:52872401646278523/3999652464964148140921992590
+qdivz:27899585299889689/9025464642,20767876354773754,31681740022949549/49333571558:27899585299889689/187439733729438364636606068
+qdivz:1612507427821399/412205953,7689706161876916,60532795827702091/8889697996:1612507427821399/3169742656746446428480948
+qdivz:-2370552431010137/60156297,-51229313115187306,69322269011837461/8761285893:215504766455467/280160524987563890033262
+qdivz:-72331493811733128/886163875,-64577202816965274,7822570842692148/107135921:12055248968622188/9537664047490477158046125
+qdivz:4366277947142681/145491389,-13081234312671287,-56811447013180333/377612058:-4366277947142681/1903206949985005846047643
+qdivz:8486006017858987/9980479,-24529516802858110,=1:-8486006017858987/244816327331072506834690
+qdivz:28765525203974723/18854856,63876884071748580,=1:28765525203974723/1204389450901513144104480
+qdivz:50689647321811649/4174791,-88774599859715468,38991799931837226/1986029:-50689647321811649/370615400522941398367188
+qdivz:4028476261308141/506452,20953755384460338,-14414987917829359/8085713:1342825420436047/3537357107323569033592
+qdivz:-15211724165753775/479404,50635361545852096,=1:-15211724165753775/24274794866527678230784
+qdivz:94548235714131649/113748,19684972847420899,15048888921861289/28846:94548235714131649/2239126291448432419452
+qdivz:43163174224614713/12275,-67469365909284359,8363004649561645/2984:-43163174224614713/828186466536465506725
+qdivz:487376363804060/24673,74326537358419014,=1:243688181902030/916929328122136166211
+qdivz:23590462962759737/3701,35930020296127129,-81369453202826375/8982:23590462962759737/132977005115966504429
+qdivz:1287959610890411/751,-2752233067297776,=1:-1287959610890411/2066927033540629776
+qdivz:47419841749950097/739,17294603489855144,13019548234372720/81:47419841749950097/12780711979002951416
+qdivz:41222280346047241/236,-20868388796109651,-65701770111449667/440:-41222280346047241/4924939755881877636
+qdivz:1277752625943784,37792680427691834,-6412847033615904/47:638876312971892/18896340213845917
+qdivz:67522291597229246/85,21305635915392026,=1:33761145798614623/905489526404161105
+qdivz:4778080537828640,39298543484658950,5712499781249450:477808053782864/3929854348465895
+qdivz:5230198800503153/5,64523362154424947,-8862961476704027/2:5230198800503153/322616810772124735
+qdivz:892228662088796613/55871131066606758934,-874654732190677980,-36329885559726251/4321287510517614884:-297409554029598871/16289316393417734432300732645294024440
+qdivz:19014600443315842/3635806154264505107,541063770937137802,551834048493969267/73475868368583023383:9507300221657921/983601494111403049141592316295877407
+qdivz:960011603483042729/5573258293787849080,883388531252731256,=1:960011603483042729/4923352458441350993032321575526844480
+qdivz:-8376282180171729/7720902655804022308,-800983354073748858,=1:930698020019081/687146056191424567616374972113502696
+qdivz:116917619245235244/358157856258765917,570339576544638471,=1:38972539748411748/68090533358253348864814413793930969
+qdivz:320704389821337359/41927154801173284,-360426920157069569,-15910915765693733/13475685473321241:-320704389821337359/15111675275935579272421848412194596
+qdivz:-138439708845709407/32918991643825253,-940108679873295360,=1:46146569615236469/10315809925678866587700717698575360
+qdivz:970565625200394526/38338183236067883,631903906064227282,146768067456204299/9085366117028492:485282812600197263/12113023869138686327460801246292003
+qdivz:-237868081084134539/1372485474016210,-358431791982152326,-311316021142488176/2766391185298279:237868081084134539/491942427921103914038343213204460
+qdivz:332386869754970911/2877063091007380,502102596500253116,-436556878102354567/7463983139447194:332386869754970911/1444580848289849529363513423996080
+qdivz:106788340885301441/156094902691284,997093725815999582,150197112369503143/3864734454843:106788340885301441/155641248105338263941318419043288
+qdivz:17951502946479831/18686629102921,-914598187042218818,-383890255715028479/297113456238268:-17951502946479831/17090757099461910397356724967378
+qdivz:61985927342201863/6333741907873,555288860578968755,-665022931937982622/73070869666115:61985927342201863/3517056327224061861672555508115
+qdivz:985136746217353770/810626219569,-532891374649286107,90081452985518108/33151508539021:-985136746217353770/431975720472878440142083227883
+qdivz:143995044786248406/2685894875017,382397533219560186,365144521255985214/1875114894173:23999174131041401/171179929115593285232696545527
+qdivz:-668702556701908142/4219524530635,393298966987097359,-770735308573122464/4820919926275:-668702556701908142/1659534639075462343835523092965
+qdivz:148895105999031617/190301395132,758758290981884265,977117467972369255/294292572918:148895105999031617/144392761341824589767658397980
+qdivz:-159087329306615872/225087429725,785549672595251591,503557620532730284/373822340619:-159087329306615872/176817356725780450857906942475
+qdivz:-264022644302396773/2278029929,-94916617158321237,547322042930742335/21894307611:264022644302396773/216222894646090709282302173
+qdivz:93285450160979197/42311784283,977744763769178683,521203752538227113/68917709707:93285450160979197/41370125528434282439178039289
+qdivz:535979926641145527/7557767498,-195852721847511858,=1:-178659975547048509/493403111857986544187330428
+qdivz:497372041980721506/7001070781,652079344505507428,-957979276256614831/9655170879:248686020990360753/2282626822855570473874630634
+qdivz:-308477546715083617/648505124,-322354321277070579,43631988559711523/304411310:308477546715083617/209048429091722494191146796
+qdivz:229255530959827383/245022904,-929912624059332484,-557747976237829033/297792845:-229255530959827383/227849891613277913531213536
+qdivz:85541435254879863/96620519,-637208165779243712,-502341106189163895/82331053:-85541435254879863/61567383688628566880926528
+qdivz:-781828043684967758/50968901,-514071001383910979,-568353562372526923/25358389:781828043684967758/26201633976507421681464079
+qdivz:-13517195129753927/89604,354643244723994523,-137336510066384067/3891763:-13517195129753927/31777453300248805238892
+qdivz:-421164540114456588/3586045,-739455098265925151,509210588483978045/6456831:421164540114456588/2651719257861029558117795
+qdivz:-879920640850630235/133271,18621800712996172,-357671116753856630/910903:-879920640850630235/2481746002821712838612
+qdivz:322932399357668253/730313,627619261687036063,=1:322932399357668253/458358505860444368277719
+qdivz:-364883615147378315/33847,666046695114786100,13578684277466669/25549:-72976723029475663/4508736497910033025340
+qdivz:795558880287747297/61163,-462149548616214218,-286678576882420657/73369:-795558880287747297/28266452842013510215534
+qdivz:423565867626533294/3487,663348607243920780,-268080787907842069/600:16290994908712819/88965253594598144610
+qdivz:463684384112493971/66,9600800466060656,494151647146512593/1842:463684384112493971/633652830760003296
+qdivz:272532100018311708/11,236412793340595928,-232492590540804763/131:68133025004577927/650135181686638802
+qdivz:888837359363262418/647,288183337717513478,506854295189807838/361:444418679681631209/93227309751615610133
+qdivz:65038385358943464/19,219207500423093598,-571150506348571411/29:833825453319788/53396698821009979
+qdivz:122838851344159513/4,178669373587933922,=1:122838851344159513/714677494351735688
+qdivz:75127173364928321/3,-719408551485655001,184094967898684200:-75127173364928321/2158225654456965003
+qdivz:332631009005835885/4,255241857170957110,-440453245937965789/8:66526201801167177/204193485736765688
+qdivz:8651470154378974507/17855010711510236057,7926925697505572502,2359552014591739654/44197656807230847567:8651470154378974507/141535343238307746317424286970948104614
+qdivz:-9258523409855044611/72817011870762460894,-9836632014308325438,-2001929228208721648/26641513880861526269:3086174469951681537/238758050051403796832749165221700140524
+qdivz:2243990531384570717/4903143680262418520,513680509693509864,=1:2243990531384570717/2518649344777710905795876032116281280
+qdivz:3229047086296059355/1050027622905630278,8584437716830130217,-3362919728113850665/830531783816835201:3229047086296059355/9013896729784577725673410081197910326
+qdivz:1683852085488062225/4857420952010518,7164575837264288367,7898318645722989656/613199579838648691:1683852085488062225/34801360784195853683892011169044106
+qdivz:2826288843276183739/128602532883722306,3829393882550729957,127913369503544038/812393212269404395:2826288843276183739/492469752705455283388475363583320842
+qdivz:3267515387857773576/19788818533922063,7234907474289428118,8550140884041497495/89127291303108631:544585897976295596/23861711853071649439652573975461239
+qdivz:3591918287029728077/26158481474501713,-158972065062790868,=1:-3591918287029728077/4158467818908295918993227426756884
+qdivz:4798456495725994078/330079170984695,2736684033993685237,416706803708991651/565680585712340:4798456495725994078/903322397187686493123625174447715
+qdivz:7907479278535852409/2240934380307407,8862559007732946109,=1:7907479278535852409/19860413177931857471235489184529363
+qdivz:-333158333301384053/63917873172107,-6335880101587543826,=1:333158333301384053/404975980766949041296129503261382
+qdivz:2512095977043224818/186022607546865,3143294313990366846,1041287894968201417/730622989945241:1256047988521612409/292361902287861129299814743618895
+qdivz:1274272592636105089/26697305210030,-2195064786710266047,681737259161578753/53927973677595:-1274272592636105089/58602314566593376440660512851410
+qdivz:435567843178733800/7824464301393,-1530121566691353530,108560750121051577/2239246150016:-43556784317873380/1197238157536802415656503446729
+qdivz:8594280929749775777/7218293710841,3358259648255124921,-1654228833035760850/3200131211923:781298266340888707/2203718590761007005154646088051
+qdivz:2666142904810159355/7661408856438,74495464765250039,8914192677969935341/9257821421719:380877557830022765/81534316216707374773732128726
+qdivz:-2813129058989480351/107454595872,6627104473551194269,=1:-2813129058989480351/712112833006966892878357457568
+qdivz:7810650428805644969/454117323713,-4146816455262026097,6439502069195252290/747129258447:-7810650428805644969/1883141190592620687327602938161
+qdivz:2811634895903387877/51784821665,6857012694304662549,-988798368309320691/15871152061:937211631967795959/118363059843069370425989774695
+qdivz:844641921898571653/10223671754,8695453332203823704,-9669505387765352006/55085569839:844641921898571653/88899460620677410973380456816
+qdivz:1280215145483357467/3963886285,-9844640072994781020,-4883072007726792453/4475614424:-1280215145483357467/39023033766105411361756310700
+qdivz:8508531253450917863/5170848284,6541528151885306706,195667348757972251/193073972:8508531253450917863/33825249618913829545533792504
+qdivz:5090255825205050242/938312789,-2249350715632037117,5726029167151411771/608233380:-5090255825205050242/2110594543423842645003789313
+qdivz:6901648669928190531/404204557,388389149829747057,3901523146891681931/452461991:2300549556642730177/52329554750179844865579583
+qdivz:9627420596709784057/83296898,-3895759694963765953,5505547607500595567/18124602:-9627420596709784057/324504697943907926282913794
+qdivz:1174645111081751713/56929752,2346454010752872977,=1:1174645111081751713/133583044911566391868111704
+qdivz:1162048514429174393/676516,-5892528680047690487,-2798438907700034207/778641:-1162048514429174393/3986389932511143377503292
+qdivz:2802096388147231635/3081196,-8573957939952598135,970876650595882421/4869143:-560419277629446327/5283608981750037112633892
+qdivz:4679180719452784893/441080,304160869162181754,2151119934944642187/178355:1559726906484261631/44719758723351709351440
+qdivz:8915672976425207388/574061,4193291428000099624,=1:2228918244106301847/601801267612291297563266
+qdivz:233328281895908391/72184,4033877823255275355,=1:77776093965302797/97060478931286265408440
+qdivz:670971715759982761/58495,-1227774851840231708,-617885163678792671/7645:-670971715759982761/71818689958394353759460
+qdivz:1582888827826888415/526,-4801669718395979914,-8104940476272206965/8931:-1582888827826888415/2525678271876285434764
+qdivz:8026229622881496370/1921,-5372178278550968118,9440287299726019407/6073:-4013114811440748185/5159977236548204877339
+qdivz:5824855751154958045/228,-4324004042888845516,-2405077946267326653/169:-5824855751154958045/985872921778656777648
+qdivz:2255437467774544874/267,3199447325094606021,2771405119280841611/270:2255437467774544874/854252435800259807607
+qdivz:7543826031595607035/52,-9104546088044346141,-5010810875416710359/35:-7543826031595607035/473436396578305999332
+qdivz:7512950202725008087/52,-8401436384345753975,3578777756405806355/83:-7512950202725008087/436874691985979206700
+qdivz:-1398241246515482350/9,9068233703219211833,-2193751108198388733/4:-1398241246515482350/81614103328972906497
+qdivz:1221529554903080379/7,2438945293435843068,1698434551175058380:407176518301026793/5690872351350300492
+qdivz:35763638816437199755/2954907322691529008,18266557204434993168,58451171309683368843/18764957235832345259:2103743459790423515/3175057861396980374605962360114930432
+qdivz:-24539890933020861364/63297755114471972871,42384166620484371822,18890782875418251817/33137608653031131951:-12269945466510430682/1341411299737198460228945187043730420481
+qdivz:-41296371891007796845/1613315363510257239,15249898379502770099,=1:-41296371891007796845/24602895347621994343929388600567496661
+qdivz:26968473073125515519/4145542541499550935,90024588359492067484,=1:3852639010446502217/53314394403608519170705602182959328220
+qdivz:-9108355348050007705/76661950335475401,57055375045772530625,-2298296977286102063/15036407448001952:-1821671069610001541/874795265626187255366630363241331125
+qdivz:28017281112559674142/994247002684615355,67802491332771845215,17786655481004019427/236849374499644614:28017281112559674142/67412423782158018128691815375872276325
+qdivz:-49891914618525842453/68768611655263204,-56174819664217997775,-258643868421169477/1911028715949526:49891914618525842453/3863064358293050425485529901511371100
+qdivz:15475896177646886296/49664524240516277,35025891777986572339,11898387681595445269/681838705009854:15475896177646886296/1739544251253513882654242570967461903
+qdivz:28737321045177790751/2199012471009842,24823078729899234245,-40602612518778238915/4253179813373998:28737321045177790751/54586259695907565418964937658439290
+qdivz:-82233023866669302835/5439768388360516,-73950538660865410929,81261743259100627124/9245809803784267:82233023866669302835/402273802509607867490064466938479364
+qdivz:10167079364078493161/151110174756962,88181742728859483214,16304278265161179899/143495911599289:10167079364078493161/13325158554131419669540551368635868
+qdivz:-6087130765566978973/5927625468935,65819308108627037451,40718993650318423604/883073647363335:-6087130765566978973/390152207092377590789503682084685
+qdivz:7330732280399983999/37205998622295,20406176085943153899,13830294786103284155/92667712731961:7330732280399983999/759232159339910159481881157578205
+qdivz:-48332340643030107345/92304258311717,35076831981288534479,-73321763690952610021/86494140631565:-48332340643030107345/3237740959957552893702829684190443
+qdivz:98273075027659873937/84269635133,52859353248248533455,=1:98273075027659873937/4454438411596262285555193874515
+qdivz:20915233355720477899/1963896569345,62221892038256747576,-76661712514256465617/9116980669558:20915233355720477899/122197360312087396058804044657720
+qdivz:1656128732718013893/12013991167,91363850016657817300,38483305820933684114/470970043279:1656128732718013893/1097644487083239819903699789100
+qdivz:11764945144680543887/509229952865,93152505052059419404,-49961035800951489551/291905091165:11764945144680543887/47436045756916892514278186392460
+qdivz:-7317867086622619121/13130133210,58387376454076686929,-27069412842327211975/63749547479:-7317867086622619121/766634030624444346933235812090
+qdivz:94954386229766199286/91332072561,-41015693032911100387,=1:-94954386229766199286/3746048252221538781607839181107
+qdivz:49271375056669735877/3964274332,27367616211878761468,=1:49271375056669735877/108492738476778047583543039376
+qdivz:19003279723108075157/3672679837,-87707256449781680395,22197086023892167841/2380460690:-19003279723108075157/322120672321701380638694695615
+qdivz:11453151955554782667/792819445,-44970402143698368284,43746116839109616727/406009345:-11453151955554782667/35653409268993750590326482380
+qdivz:66060084310215517861/632772858,5686208043365730020,66618392442628601603/239006406:66060084310215517861/3598078114783120924011797160
+qdivz:15607406135041638145/12850627,92675124740491579124,82466968677513464623/33726515:15607406135041638145/1190933460218529079963510748
+qdivz:-84968644713302015482/30765501,21907086830543047075,=1:-84968644713302015482/673982501792158945328959575
+qdivz:-75708685189598590459/7543159,87636428496926088857,99286949010117671967/464174:-6882607744508962769/60095955849494954499679933
+qdivz:19413781778784807559/7455,70419417237119401006,87759888274980374477/7600561:19413781778784807559/524976755502725134499730
+qdivz:-44073071620584783758/137977,97178052623075418323,2336605012039492891/4902:-44073071620584783758/13408336166774076993952571
+qdivz:25141254449395000414/853567,48818099403147552704,72006961628028408314/367953:12570627224697500207/20834759326623223559447584
+qdivz:48044965246872284768/97133,69155615859736994978,-45313300536339105253/86233:24022482623436142384/3358646217651916766599037
+qdivz:-4395289710243518173/8350,744289141150282917,-29095078709708260253/88548:-4395289710243518173/6214814328604862356950
+qdivz:-92303054169340161069/4319,6791173325830567613,=1:-92303054169340161069/29331077594262221520547
+qdivz:64997783212580413369/6291,44933069571459793043,-20474362763124554371/1858:64997783212580413369/282673940674053558033513
+qdivz:93945477444073241773/141,88011071920496381723,23904352473973528984/197:93945477444073241773/12409561140789989822943
+qdivz:-25808752242439690169/552,-34114701969246980307,41196336212393917073/475:25808752242439690169/18831315487024333129464
+qdivz:16573231794217629809/25,80794581544602285996,=1:16573231794217629809/2019864538615057149900
+qdivz:42187260212039274209/87,70929718370679041273,41380731918827034219/13:42187260212039274209/6170885498249076590751
+qdivz:-34161590626563013397/4,-31069588081719868852,=1:34161590626563013397/124278352326879475408
+qdivz:60823156242773368161/2,-90388088707709016642,-91947828450656458545/7:-20274385414257789387/60258725805139344428
diff --git a/polly/lib/External/isl/imath/tests/qmisc.t b/polly/lib/External/isl/imath/tests/qmisc.t
new file mode 100644
index 00000000000..2005b0f8519
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qmisc.t
@@ -0,0 +1,49 @@
+## Miscellaneous rational arithmetic tests
+## Generated and verified by hand
+
+# Basic negation tests
+qneg:0,0:0
+qneg:0,=1:0
+qneg:1/37,15/16:-1/37
+qneg:65/18,=1:-65/18
+qneg:-6/7,=1:6/7
+
+# Basic absolute value tests
+qabs:0,0:0
+qabs:0,=1:0
+qabs:1/37,15/16:1/37
+qabs:-592384293849818/1000001,55:592384293849818/1000001
+
+# Reciprocal tests
+qrecip:0,0:$MP_UNDEF
+qrecip:1/2,5:2
+qrecip:-3/2,100/995:-2/3
+qrecip:655378011918000000,=1:1/655378011918000000
+
+# Reading decimal fractions
+qrdec:0,10:0
+qrdec:1.10000,10:11/10
+qrdec:1.01000,10:101/100
+qrdec:1001.001,10:1001001/1000
+qrdec:1001.001,2:73/8
+qrdec:12.05,10:241/20
+qrdec:-5.00138,10:-250069/50000
+qrdec:-00000.5,10:-1/2
+qrdec:.5,10:1/2
+qrdec:-.005,10:-1/200
+
+# Rational exponentiation
+qexpt:-5/8,0,0:1
+qexpt:-5/8,0,=1:1
+qexpt:13/8,0,0:1
+qexpt:13/8,0,=1:1
+qexpt:509252236125428/47889593208724507642867,0,0:1
+qexpt:509252236125428/47889593208724507642867,0,=1:1
+qexpt:-5/8,1,0:-5/8
+qexpt:-5/8,1,=1:-5/8
+qexpt:13/8,1,0:13/8
+qexpt:13/8,1,=1:13/8
+qexpt:509252236125428/47889593208724507642867,1,0:509252236125428/47889593208724507642867
+qexpt:509252236125428/47889593208724507642867,1,=1:509252236125428/47889593208724507642867
+qexpt:509252236125428/47889593208724507642867,4,15/39:67256115255216568118287656956157205834289880165948820377856/5259743820161714626344840164714583399959974116151536869550562774750827767486998189660536721
+qexpt:509252236125428/47889593208724507642867,4,=1:67256115255216568118287656956157205834289880165948820377856/5259743820161714626344840164714583399959974116151536869550562774750827767486998189660536721
diff --git a/polly/lib/External/isl/imath/tests/qmul.t b/polly/lib/External/isl/imath/tests/qmul.t
new file mode 100644
index 00000000000..db1f3908f49
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qmul.t
@@ -0,0 +1,803 @@
+## Rational multiplication tests
+## Generated and verified in PLT Scheme (see imath-test.scm)
+
+qmul:-3/26206484091896184128,1/693472590887743985,-4/70335584174882085859:-3/18173478421265693438940076224084470080
+qmul:3/91130421678723294601,2/1511297448571716895,-9/67416878129472613559:6/137725173770319192750843847801453983895
+qmul:3/3660941890584665578,-9/8380105656182991401,5/2848423294177090248:-27/30679079844245810042603985831234694778
+qmul:7/2164077499217694058,0,-1/333401876099655555:0
+qmul:4/904017211204226053,=1,-1/248448496161174245:16/817247118153466254734904646723958809
+qmul:0,-4/100568637457389843,0:0
+qmul:2/73650052097202983,5/4552230994414799,0:10/335272049897152087881722802145417
+qmul:7/999642011115757,=1,7/12191208784714605:49/999284150387555241548053683049
+qmul:4/4748171647596839,7/4194009713619088,1/878273774653032:1/711209928998281855823737102244
+qmul:-1/3272725541181013,3/1299116858075758,9/9062356618866682:-3/4251652922403362359365945182854
+qmul:1/107669261142969,=1,2/427008086776155:1/11592669795072854172258134961
+qmul:9/886384410786908,=1,1/143876368001899:81/785677323686054067227784200464
+qmul:3/35807911942040,=1,-5/90295680789497:9/1282206557648890844319361600
+qmul:2/68986921725007,5/77598287457417,3/43453045339831:10/5353266982819419037696526919
+qmul:-1/1109481330540,-4/9404058215555,=2:1/2608406755367394881137425
+qmul:0,=1,5/4715212234981:0
+qmul:1/68986716212,-3/2931468080,=1:-3/202232356519496512960
+qmul:1/26808054670,=1,=1:1/718671795189708808900
+qmul:7/43068832781,0,7/19211808304:0
+qmul:1/9608906275,4/5041381803,=1:4/48442165241517513825
+qmul:1/1228681579,6/2225293505,2/749381381:6/2734177137461844395
+qmul:1/8574959114,=1,6/1956551185:1/73529923806771664996
+qmul:-5/861495024,=1,-2/67979545:25/742173676376760576
+qmul:-2/140727827,1/692019033,-7/753572629:-2/97386334756731291
+qmul:3/95516372,=1,0:9/9123377320042384
+qmul:3/21198931,1/3432139,1/3530668:3/72757677843409
+qmul:7/6222866,4/1833695,0:14/5705419134935
+qmul:6/615053,=1,0:36/378290192809
+qmul:5/568461,4/392783,-2/643261:20/223281816963
+qmul:-5/510613,=1,0:25/260725635769
+qmul:2/14663,-8/93277,=1:-16/1367720651
+qmul:9/49612,8/73143,1/20024:2/100799181
+qmul:3/697,0,=1:0
+qmul:-4/2403,0,1/2247:0
+qmul:3/196,9/422,3/424:27/82712
+qmul:-1/309,2/257,4/233:-2/79413
+qmul:5/67,9/11,7/8:45/737
+qmul:1,-1/22,=2:-1/22
+qmul:0,=1,3/8:0
+qmul:0,-4/7,=1:0
+qmul:-85/86153854226096021421,=1,-17/21068656717268700162:7225/7422486598011403290090823970405290859241
+qmul:-5/43607938850040716426,27/16056333585184134128,32/52338799857236448113:-135/700183613138564743562274537293596786528
+qmul:17/1822698577891414141,=1,-7/8417742332722538862:289/3322230105847383502431373884774767881
+qmul:16/4598825929956443605,49/4847943197216974161,27/3451375546922816345:112/3184978126045337954130178471819812915
+qmul:-13/308229631559916894,7/23027204844472228,=2:-91/7097666865066408240206510971019832
+qmul:9/407734736332167529,=1,=1:81/166247615211862175599509955321965841
+qmul:85/4942792842537911,76/69829540258955019,-91/17762034363033874:6460/345152951789675772143408751225309
+qmul:54/48159800199427181,=1,5/15794694767846184:2916/2319366355248746342818800521606761
+qmul:-1/11155623059888,5/2213190858263331,74/4478858739544117:-5/24689522974375729479887366928
+qmul:28/7444112023597965,94/2835981424363017,44/965216022716111:376/3015909059971602514096088922915
+qmul:61/275448071365986,=1,39/801040431549668:3721/75871640019241316559957752196
+qmul:-16/122979260248953,91/861294833601044,69/330950567465674:-364/26480350373125364764230176733
+qmul:-5/15361734038378,-4/21146843499433,-42/41820111648961:10/162426092794746228321619837
+qmul:31/27515949153680,42/8919478678031,-31/98260871319338:651/122713960891016949829402040
+qmul:-96/7797764223407,-71/8834811164017,1/1862795966742:6816/68891774415328515707545919
+qmul:15/5131534941574,57/7059500713061,=1:855/36226074579139089973698014
+qmul:99/412586992259,-70/740258455507,2/72307587241:-6930/305421009651925904920313
+qmul:79/741601059426,-1/218034913785,-91/880841444516:-79/161694923054812571587410
+qmul:-31/7229094496,1/4120337146,=1:-31/29786306583812948416
+qmul:55/83518896547,9/29598222046,-49/35480447526:495/2472010845035008675162
+qmul:-70/3176137243,=1,1/170734393:4900/10087847786371641049
+qmul:19/8816510816,16/688207893,1/526411545:19/379224520768191918
+qmul:-3/77923064,=1,29/420820637:9/6072003903148096
+qmul:7/886358404,71/63529999,3/267607006:497/56310348519761596
+qmul:1/2981721,46/37858403,83/6367099:46/112883195251563
+qmul:-31/938629,-15/8290882,1/1023462:465/7782062280778
+qmul:37/410302,4/1757463,=1:2/9744467349
+qmul:28/8167855,=1,81/7643948:784/66713855301025
+qmul:-97/992628,13/93468,-47/39726:-97/7136842608
+qmul:-23/674165,7/523911,47/942664:-161/353202459315
+qmul:-7/19181,54/85811,=1:-378/1645940791
+qmul:5/7653,=1,-76/63829:25/58568409
+qmul:11/4265,=1,57/520:121/18190225
+qmul:65/6957,41/389,96/2993:2665/2706273
+qmul:-23/297,-9/83,14/891:23/2739
+qmul:2/31,86/985,-4/905:172/30535
+qmul:-12/7,-10/3,62/67:40/7
+qmul:-28/23,16/87,4/15:-448/2001
+qmul:37/2,=1,-16:1369/4
+qmul:-20,=1,35/4:400
+qmul:437/75577860178450821941,=1,572/74570847326022239185:190969/5712012949153462506928348371418487007481
+qmul:-189/57565050795595180562,-59/2655741179562929534,963/98951958258639716842:11151/152877875901493900051494486844412518108
+qmul:392/9223441830913061231,10/126887593668291297,102/1854286196997300457:3920/1170340339264017235848151367305406607
+qmul:255/3855767718884073169,129/2905792024958436842,-235/3219625969384677757:32895/11204059087625523831085398908193292298
+qmul:-47/35122532617610421,-117/122052767037802280,319/272062018205952087:1833/1428934097118272207801649688519960
+qmul:979/892962159830670377,-375/273191235681889997,70/47294962936566903:-367125/243949435861310195658594938880518869
+qmul:117/20991277911775766,=1,-92/47578690454158995:13689/440633748369405163321411464886756
+qmul:-243/11407352500485733,587/76385498874294444,-614/81454021700493267:-47547/290452103861510956341405887722484
+qmul:174/900283464250993,229/9496538222605715,-274/3248450234623149:39846/8549576329439440824503236224995
+qmul:-690/8145214566421669,141/5752215623742809,71/3004747651790415:-97290/46853030487708234314403900528221
+qmul:226/102973529231733,30/68951726615689,=2:2260/2366734212079704520104819679
+qmul:-815/885459835828344,37/163413072330166,-43/147651688219350:-30155/144695712197674089868869025104
+qmul:75/6638760558632,-138/35179390065353,413/82329576156442:-5175/116773773621297956634138548
+qmul:147/95595835551176,6/10399082254439,189/19869218037638:441/497054478539251611118835132
+qmul:-610/7116766665669,370/6178271155283,-170/1991438380331:-225700/43969314209382356444079327
+qmul:-22/3906839603439,=1,495/2629172214638:484/15263395686999402780626721
+qmul:145/9760768489,529/803913134519,3/3085831861:76705/7846809991306273371791
+qmul:30/130533848429,-291/232962676405,413/647890196158:-1746/6081902938292888923549
+qmul:218/45496969487,53/7721267751,312/52099708697:11554/351294283268204113737
+qmul:277/88084217182,-643/95570881719,=2:-178111/8418286301611629495858
+qmul:97/9657661098,472/161930139,400/6505391099:22892/781933202007016311
+qmul:137/1394596885,923/2175332507,-63/538078336:126451/3033711938101440695
+qmul:-99/123912484,299/998630381,359/807136797:-29601/123742771107576404
+qmul:281/377026117,-970/10165277,80/672610947:-272570/3832574915539409
+qmul:641/45327247,95/3702049,-31/16613945:60895/167803689429103
+qmul:-737/25452329,363/67508236,825/73130323:-267531/1718241832881644
+qmul:51/7250464,112/8927185,903/6361594:357/4045389591490
+qmul:199/4639977,588/7971809,322/8874233:39004/12329670136131
+qmul:665/703012,329/294996,787/209117:218785/207385727952
+qmul:133/29650,307/137037,809/690522:40831/4063147050
+qmul:553/42863,161/16139,552/86389:89033/691765957
+qmul:-568/72299,-953/23177,798/52267:541304/1675673923
+qmul:-907/7588,47/7619,=2:-42629/57812972
+qmul:37/1428,-161/1853,-140/3279:-851/378012
+qmul:69/659,194/7,-183/238:13386/4613
+qmul:-365/824,264/503,-421/698:-12045/51809
+qmul:747/74,-15/94,12/19:-11205/6956
+qmul:12/5,113/37,=2:1356/185
+qmul:-807/7,943/8,199/3:-761001/56
+qmul:591/7,85,-156:50235/7
+qmul:853/18759654468263598130,-2841/40750915886836631585,=1:-2423373/764473101302328863323172599481304936050
+qmul:-4752/16314480916934323241,1675/15223840982975523171,=2:-2653200/82789687733065614038692540422933105737
+qmul:-877/6101604969629738233,=1,3917/3506403215407013175:769129/37229583205410318824680729796101962289
+qmul:3511/9447760616772726092,2633/1439700094583390479,-1093/3530171944589695778:9244463/13601941853568925322985028756947678068
+qmul:1947/430992381411198689,=1,6905/150990131770718358:3790809/185754432834496165241461379835318721
+qmul:8719/646714849991103264,=1,5786/734533820409647257:76020961/418240097199015197424619951911453696
+qmul:-901/11042787574357099,-1492/25943871895296763,2003/71983717831437714:1344292/286492666196095454208761540770537
+qmul:248/45424964911300681,-2828/10155871660092285,1922/24482631313347631:-100192/65904301971909291827634263335155
+qmul:2932/167088922177995,4285/8315956341564334,=1:1256362/138950418199124701072469163033
+qmul:63/96864941445455,1217/536600078187501,-1363/813397840648021:25557/17325911717752953043818085985
+qmul:2028/952222976621975,=1,-4447/132247057152414:4112784/906728597206814347382052900625
+qmul:-2672/564653311125411,=1,593/245849676591157:7139584/318833361764890193787369918921
+qmul:8811/12688709770015,-6995/78357482492503,2405/8730288903721:-12326589/198851070731280426018339509
+qmul:-6216/89020593811217,2073/8676827195515,-43/383215257478:-12885768/772416309342061967459091755
+qmul:649/679490122076,-1037/2294439110154,6125/672996983517:-673013/1559048711054490271159704
+qmul:4001/986338046878,5/3558981731,-2511/3763709597086:20005/3510359089429023585818
+qmul:-1523/69241899473,=1,7123/515464482213:2319529/4794440642629037677729
+qmul:-6869/800191115742,938/461384295473,-3029/66737130644:-3221561/184597807090188234817983
+qmul:3554/16260606585,-2909/10951382696,=1:-5169293/89038062790716326580
+qmul:-8706/24347671943,-2333/75528831647,6568/10275254341:20311098/1838951215179232380121
+qmul:8843/2387867375,3806/2482665293,-478/3437714583:33656458/5928275456199515875
+qmul:676/469237349,=1,=2:456976/220183689696547801
+qmul:4381/415783140,=1,-9189/160372247:19193161/172875619508259600
+qmul:5209/647900590,31/76532430,5022/774082651:161479/49585406551133700
+qmul:6785/98653728,1643/10927961,-3657/22982951:11147755/1078084092088608
+qmul:-131/3707540,-3070/95931603,8132/10434367:40217/35567025538662
+qmul:3495/4205702,1768/4495963,642/2009179:3089580/9454340290513
+qmul:-3081/1925708,-557/52210,=2:1716117/100541214680
+qmul:1824/515329,4783/215399,-80/428083:8724192/111001351271
+qmul:-1259/116291,686/450649,=2:-123382/7486631837
+qmul:2158/8127,4919/28127,=2:10615202/228588129
+qmul:-8479/13630,228/39107,-6607/63539:-966606/266514205
+qmul:-3929/4639,1292/907,4288/3241:-5076268/4207573
+qmul:-2277/9067,379/5790,-503/3539:-287661/17499310
+qmul:7172/525,4813/272,4472/631:8629709/35700
+qmul:759/64,=1,1976/105:576081/4096
+qmul:3255/4,-1567/13,4881/26:-5100585/52
+qmul:3089/89,=1,-8984/35:9541921/7921
+qmul:5031,-5481,=2:-27574911
+qmul:1479,6716/7,669/5:9932964/7
+qmul:-79907/42073633953804470386,9649/39994826473890828375,-32061/69201000109873943624:-771022643/1682727689108411078225149789999696002750
+qmul:7869/4137317017220625920,-46300/94718332275370703049,-79642/60022119059401889179:-6072245/6531329466094147648450013992237207168
+qmul:-29138/1677259660137772757,55969/6796400935123913154,-10129/967130263887253020:-815412361/5699664561302987764528483645927572789
+qmul:63296/9530224706297545807,2348/322614345457502213,958/9427355800897598701:148619008/3074587205685099009151203658171370891
+qmul:8775/40604046784024133,-33221/144310822954936081,=2:-291514275/5859603406703248409743984976442773
+qmul:21115/310091896403808544,11297/311633467720059450,=2:47707231/19327002597641657788985081219588160
+qmul:-7541/568197224156233,78686/80834506129161047,=2:-593371126/45929941998629309750410745855951
+qmul:-69371/45833711711077260,45306/56585412779622335,7626/54270702558063797:-174606807/144084416466306503713223267033450
+qmul:-47821/557744909539529,-35381/1596080991630467,27735/4832267108379043:1691954801/890206048294696559875897230043
+qmul:39463/2836203973039415,5893/5755385978253006,39369/9842567552327876:232555459/16323448577896515754725680231490
+qmul:59563/93078116326943,=1,39162/530318464795213:3547750969/8663535738971933065667725249
+qmul:-6422/219350698334991,12009/451668291281128,38643/184068500609632:-12853633/16512292518047925598650058308
+qmul:6353/29487362288887,18649/10109618056586,-739/5084432721670:118477097/298105970236825097644959782
+qmul:82991/13932554844361,44258/40391647302859,-4103/3232141273561:3673015678/562758841301169080175328099
+qmul:68609/2797606749368,71293/8880170450370,=2:4891341437/24843224787493384272866160
+qmul:69352/1282840784633,51360/5155457119681,=2:3561918720/6613630656553360226662073
+qmul:19996/284659901481,91975/649935845164,992/22386886571:459783025/46252668413338677571971
+qmul:95164/291066123381,=1,86173/926768430166:9056186896/84719488180043514871161
+qmul:58599/35278850458,=1,=2:3433842801/1244597289637926809764
+qmul:16793/50880968745,32965/31422146373,5133/4972604243:110716249/319757849501085622377
+qmul:10537/861910652,22310/9378414407,=1:117540235/4041677638131781682
+qmul:79317/9648480088,22265/3941357964,=2:588664335/12676037945111406944
+qmul:11221/182565205,56092/543156657,49073/666425232:629408332/99161506432319685
+qmul:85751/945688766,15325/126345977,14001/74129827:1314134075/119483971078194382
+qmul:-70533/6456184,-11237/1159737,36975/90043007:264193107/2495825154536
+qmul:56162/84955139,=1,=2:3154170244/7217375642509321
+qmul:559/4445450,87073/9891852,=1:48673807/43973733473400
+qmul:2247/126982,=1,=2:5049009/16124428324
+qmul:87205/903493,=1,4007/74486:7604712025/816299601049
+qmul:20400/957959,=1,-9955/111633:416160000/917685445681
+qmul:31836/73595,11609/39450,46021/33218:61597354/483887125
+qmul:84969/75326,-86068/92037,9321/65618:-1218851982/1155463177
+qmul:49337/4359,71033/6220,-25745/2781:3504555121/27112980
+qmul:15077/1290,20527/9232,-259/71:309485579/11909280
+qmul:52867/502,-63033/451,83228/635:-3332365611/226402
+qmul:1852/17,45130/359,67421/50:83580760/6103
+qmul:57233/78,37817/35,-23454:166490797/210
+qmul:9693/26,82259/68,46811/66:797336487/1768
+qmul:-53957/7,=1,57497/7:2911357849/49
+qmul:-95413/6,-29374,-4257:1401330731/3
+qmul:-198736/12940720433326325129,125852/5925853683093665567,12760/97357765177854120733:-25011323072/76684815841712259623316096046234133143
+qmul:921572/61142247716597287729,-236568/70364185507196351425,204596/87367262923771962827:-218014444896/4302224460657604084043267617199724163825
+qmul:-175852/3759159397994001893,12753/21663430571600165,=1:-2242640556/81436288626021332583545141049112345
+qmul:-268026/6357464651647716983,=1,8534/1795261387346998395:71837936676/40417356796950227447969273156066622289
+qmul:841695/829965893010784622,-533003/287367841069761182,-70387/77776025771352596:-448625960085/238505506836045568256258975978143204
+qmul:285995/137908752412413419,=1,=1:81793140025/19018823991948344014771004171269561
+qmul:523332/10397730659818265,-637807/84218842967037343,38109/5089543807331942:-333784812924/875684845652784039249421848469895
+qmul:331806/46798346659133905,390599/19460297756850316,-839360/33343052356070147:5891049627/41395898205229409605128422071090
+qmul:-618133/4917065118673735,=1,-92527/257257853329058:382088405689/24177529381277951659005378850225
+qmul:821668/9309756380607047,319410/1721325229930259,-409819/4033682794066002:262448975880/16025118542443120997155893935173
+qmul:-463245/974985643441198,-676781/102650194991381,67531/763750320751138:313515414345/100082466413036044472790314438
+qmul:3292/15168814078843,786853/187996862965898,126658/126696595422875:1295160038/1425844730867715885896148007
+qmul:-108514/9407475910099,31445/45805965278381,209927/522813819096:-487460390/61559787842171498837752817
+qmul:206519/25307336797263,439291/97571104143841,-52486/22231146494461:90721938029/2469264794249007720607107183
+qmul:755819/4678998804414,132779/513422592641,-154155/1796861274557:100356891001/2402303697126375154717374
+qmul:-610422/8953796367011,=1,34600/946679301111:372615018084/80170469381899382209074121
+qmul:-168796/96200349399,=1,459815/414314841334:28492089616/9254507224489679661201
+qmul:448040/938638294207,-940391/987312987781,877652/581123018277:-421332783640/926729778699174474084667
+qmul:367299/48916956722,-234746/31600745479,19962/10415742905:-43110985527/772906149489590079919
+qmul:540492/60952022291,=1,=2:292131602064/3715149021362560888681
+qmul:48241/1850039638,600695/993394588,=2:28978127495/1837819363974679144
+qmul:-73469/4702579939,910622/7776354127,71768/6903692213:-66902487718/36568926916190058253
+qmul:165889/228901970,3743/140713319,=2:620922527/32209555924338430
+qmul:208098/645461621,-637539/213089255,-987707/763332694:-18952941546/19648705135711765
+qmul:978743/66626510,16328/1482253,=1:7990457852/49378672163515
+qmul:336035/68124509,=1,245361/31402036:112919521225/4640948726491081
+qmul:191473/9297613,135059/7858162,-384667/8715020:25860151907/73062149167306
+qmul:-118451/7012982,-685529/5952631,=1:81201595579/41745694055642
+qmul:142154/901271,422448/305711,332653/165374:3532510176/16207556393
+qmul:52759/177236,850321/697129,72248/85023:44862085639/123556355444
+qmul:-88178/95391,=1,277011/11863:7775359684/9099442881
+qmul:-466226/55653,24107/11550,-273396/37003:-5619655091/321396075
+qmul:825492/3685,102991/306,60368/1041:14169707762/187935
+qmul:166834/1709,340151/1908,=2:28374375967/1630386
+qmul:-212681/290,424751/190,845448/971:-90336467431/55100
+qmul:134907/163,-69685/79,=2:-9400994295/12877
+qmul:-539594/3,15173/4,-877571/28:-4093629881/6
+qmul:247756/31,94120/29,-147220/11:23318794720/899
+qmul:910742/5,63428,2990:57766543576/5
+qmul:132140,=1,214219/9:17460979600
+qmul:-1882407/73787858412488449855,-434970/15504199196668297319,7152438/32357487418268793473:163758114558/228804331024555497710598988747312487749
+qmul:697417/2168456434664834658,1334383/40514117254978695797,1660012/19534585395934841435:132945912673/12550442608046308674759866845069218918
+qmul:767157/4500296443907797052,4954462/555593595680231401,3839270/8356753330266434437:1900425102267/1250167941448845883802900321752814926
+qmul:3855435/1910412651584231024,3929628/9286414633188139915,6450211/7279093857125478452:757521266409/887044200154977924360507801609786148
+qmul:-713297/2131510505574811,=1,8006203/547537770085302559:508792610209/4543337035375786395109517685721
+qmul:-3176335/541746203963633741,-438253/349884327285711674,2546202/81167937975645853:1392038342755/189548506133403938761872538263992434
+qmul:4172837/3155683016816501,1634359/1130730609779385,3449963/73677939584796131:6819913706483/3568227381875371425040637631885
+qmul:1250071/25258841326965282,-32307/1353739173264256,=1:-13462014599/11397960991859667942696774520064
+qmul:7965329/6993004096201475,2973773/6634186275128268,3335672/4941418095538311:2153370937847/4217535617903234884469745072300
+qmul:924761/7142709941575765,8302365/4849337439058259,=2:1535540671953/6927482147203397401610419498627
+qmul:6563249/71417076489085,=1,3793878/305677884396037:43076237436001/5100398814247817470124137225
+qmul:123256/2387254101849,6673623/563071687944596,-2966203/120995731224497:68547006374/112016266390064743737763167
+qmul:11601/9690796184885,-313729/29163002094366,=2:-1213190043/94204236478625099184285970
+qmul:-1548191/1118347883822,693213/16160970245026,=2:-1073226127683/18073586874035135921369372
+qmul:4730021/1257111596731,45335/50784818897,9472521/3164110107311:214435502035/63842184773302332225707
+qmul:8511317/4540489631064,-6359369/2005086337073,=1:-54126605478973/9104073722868052915635672
+qmul:-929873/867693641561,8138971/698148180183,9405551/179909067138:-7568209380683/605778736812172445385663
+qmul:9281874/795726121805,-9968150/721200783579,4661824/364533493543:-6168207487540/38258553504002986522673
+qmul:3865094/4084662077,4259784/19883113093,=2:16464465579696/81215798023679274161
+qmul:-416924/286477113,826597/6309334211,-9773164/19019652193:-344628127628/1807479849719412843
+qmul:-9662220/20572447,=1,1141747/1832358244:93358495328400/423225575567809
+qmul:616787/710447851,-5149637/86667498,5336551/335300034:-3176229156319/61572737705646798
+qmul:-9976984/843714569,=1,613447/59557955:99540209736256/711854273942855761
+qmul:-6026602/975541545,9908792/76315713,9315535/212827209:-59716345684784/74449148567796585
+qmul:317525/4130814,-794909/3724657,-7514646/67549867:-252403480225/15385865280798
+qmul:5284147/75357219,-2845520/19763971,1559210/15974883:-791376103760/78387257418771
+qmul:6632185/1141092,2427283/1559559,=2:16098189903355/1779600298428
+qmul:-1099211/2368184,=1,4294432/3557597:1208264822521/5608295457856
+qmul:-90319/172637,8164133/19492,-7639232/876753:-737376328427/3365040404
+qmul:-2193898/79229,542172/63719,=1:-1189470066456/5048392651
+qmul:-3656336/69523,1911911/39486,833550/557:-3495294509048/1372592589
+qmul:106251/11335,-7809497/82381,-4910754/43655:-829766865747/933788635
+qmul:656544/4345,-9528986/1963,2350355/5553:-6256198584384/8529235
+qmul:-2189554/2039,-5393104/7563,889038/2857:11808492435616/15420957
+qmul:3890213/508,186330/17,-1198413/262:362431694145/4318
+qmul:3102225/578,5898937/910,=1:522852280995/15028
+qmul:-1156863/5,-8420942/61,1460661/13:9741876224946/305
+qmul:-2254787/5,2862624/83,3361/52:-6454607381088/415
+qmul:-7630885/4,5547065/8,=1:-42329015102525/32
+qmul:3371673/8,1927246,=2:3249021651279/4
+qmul:-14442357/30313364574216985165,21011896/19717180229164582119,=1:-101153767759624/199231357554069726942322822323082421545
+qmul:73015500/34914714923282785961,10709547/16405893500986887200,19061786/4299472658767378545:7819629289785/5728070946486949421088979169452505992
+qmul:-5213601/648973976600394322,95110449/6292591997485345693,10223157/1491031081544864086:-495867932016849/4083728451731883302073525200284355146
+qmul:81716702/9420867468902388767,-3659716/561353788976535007,16436845/12448406189105001:-299059921776632/5288439649114135016294765892899066369
+qmul:-50829049/681481015656967334,78493193/406094838848924705,=2:-3989734353163457/276745923231817683251713267210586470
+qmul:-70639608/210570392897683795,=1,32857499/484390875545236076:4989954218393664/44339890365084922016231475805602025
+qmul:-42306075/32432310313264277,-86992166/48265729471703217,59197803/99727495871692084:1226765699736150/521789705240781269523990077359703
+qmul:98949619/2882304121717510,-30259679/61942044859153494,=2:-2994183708112301/178535811205149016934639997479940
+qmul:-33943246/547508652618667,-9155497/325768016112482,3909688/9222108480297609:155383643461631/89180403784000610709262450747
+qmul:-4005853/831711723057253,-65053249/3453104157068793,=2:260593752666397/2871987208371849027864998605629
+qmul:30466505/131811990296054,80480517/129751865511763,-66851989/905703806093822:2451960073583085/17102851637731408230589483202
+qmul:67778441/221052041028359,31145967/736730375785315,=2:2111025086697447/162855753254933795304810748085
+qmul:-27930623/83735524881404,=1,26062637/38713631506284:780119701168129/7011638127164228368265011216
+qmul:91874289/55178817284824,2081222/10998714287097,=1:31868465250193/101149341002618103726185988
+qmul:-81097913/23224035213,86134633/913902046268,-44110346/4612785602109:-6985338973320929/21224493303760787235084
+qmul:26946729/330400702820,-5376007/957000244373,72609687/3803755771964:-144865803731103/316193553339750950231860
+qmul:5847347/83932240013,4198391/162033797450,41563965/225583428284:24549449018677/13599859577791227366850
+qmul:19548965/189470438789,2465153/48226118390,-16293845/384490679461:9638237943329/1827484762488712445942
+qmul:-55395086/15848355167,30834213/24733216753,3746720/49399574807:-1708063880877318/391980803523938512751
+qmul:-58079954/9010951227,53522457/51897896711,=1:-1036193946842326/155883138682234904799
+qmul:15721758/4667399077,-40891342/1328104821,=2:-214294594406412/2066265071898216739
+qmul:70233722/7303211237,8646406/3990640707,33916940/2735563757:607269275303132/29144492054192024559
+qmul:6933207/288152,3665663/23826937,-56545561/920522000:25414800371241/6865779550424
+qmul:41800997/62123962,-38919041/683603632,-76160505/964998499:-1626854716083877/42468166057429984
+qmul:-30010802/20468051,19506739/20221851,38792870/36677751:-585412881794678/413901877582401
+qmul:11813175/26779288,=1,4038299/10717148:139551103580625/717130265786944
+qmul:-54308089/3363111,6223152/1333435,12297998/2068949:-112655830892176/1494829972095
+qmul:47572280/4867129,99908399/5832503,6381834/2396879:4752870331579720/28387544493887
+qmul:-62682614/784029,8201676/813035,86261045/879573:-171367496953688/212481006005
+qmul:-52450671/559382,31930301/348148,81333805/486957:-1674765712681971/194747724536
+qmul:53187047/34080,40744921/16199,37085536/50799:2167102028238287/552061920
+qmul:11558111/11033,48139409/27484,-90392545/80713:556400632696399/303230972
+qmul:-25583995/4897,-94434044/3561,2921273/9343:2416000109525780/17438217
+qmul:-5090656/611,=1,=2:25914778510336/373321
+qmul:-13641055/103,35989446/451,-35512409/41:-490934012305530/46453
+qmul:99505255/181,-312642,12835678/5:-31109521933710/181
+qmul:25097277/5,85216417/47,73513489/51:2138700022396509/235
+qmul:64784087/19,-41764336/27,-39313651/72:-2705664376921232/513
+qmul:22866666,9187561/2,-79296567/8:105044444370813
+qmul:32433429/4,-57952559/6,=2:-626533402564937/8
+qmul:142379769/6580458265088042332,=1,829632764/47313440042888292183:20271998620493361/43302430978565528007566299412223998224
+qmul:952160697/53449785406826630773,=1,123350541/21685565106900565733:906609992911525809/2856879560035817059690375116110870577529
+qmul:134379194/7288875631759851537,262306997/2039219084637508550,=1:17624301418710209/7431807146916983147195344504784070675
+qmul:893718997/892104296345812908,=1,287136425/3171192156119780019:798733645598686009/795850075558657977797692103339416464
+qmul:148747375/98802457575041086,24743438/63078605847781653,=2:1840260725487625/3116160639084092662997866715997579
+qmul:881257471/447180652093139622,=1,467458692/434203794165327853:776614730193315841/199970535606445577794662077186302884
+qmul:-328833244/8368942920923449,71377107/4810747268694941,=1:-23471165642145108/40260869298696343876296794571509
+qmul:158379101/1326421417689989,-189428893/41659788909099497,196884323/11300332885720816:-30001577776765193/55258436265473435094327901835533
+qmul:10782829/45891552641500,764396030/8166229459391987,-237359023/5307605981413862:824235167976887/37476094911825545799378366050
+qmul:-176383510/8720957474390283,=1,969790455/2816113324098863:31111142599920100/76055099270123743567802604820089
+qmul:153319337/75604684811316,-66073159/9855025487116,=2:-10130292931375583/745086095760891109449004656
+qmul:-152252295/92990423831326,58928296/433772431956189,=1:-213618293010460/960397197475024603484708967
+qmul:968728976/89630394861017,122952071/77095083081384,=1:14888404229613662/863757842303419891847500941
+qmul:421854586/98110047748469,777827572/98264750833133,=2:328130128365445192/9640759396230087578575223377
+qmul:321360259/1519003205844,=1,648154609/8326351267679:103272416064547081/2307370739364349435752336
+qmul:-623994359/2983440638275,548017609/4525469063166,313238822/1462111109367:-341959896648667631/13501468310305737332278650
+qmul:105901696/125767654005,11356251/3169320047,37580987/3123470749:400882080367232/132865982367402112745
+qmul:257717002/338572086809,=1,-516598417/866703725253:66418053119868004/114631057966201031802481
+qmul:-315718685/10965934391,730969133/99436604662,980080011/95127007262:-230780613446350105/1090415282787296730842
+qmul:357633989/52052235576,=1,499101847/17405036021:127902070088052121/2709435228459400051776
+qmul:83154971/2959266631,=1,=1:6914749202010841/8757258993350090161
+qmul:74008543/143708417,-38807917/3997329896,49374533/1136791926:-410302484862133/82064278797276376
+qmul:147247586/394684533,-46611929/47003797,417377757/202754149:-6863494024053394/18551671668171801
+qmul:190874443/241889832,65505550/154148559,=1:6251667684829325/18643484519776044
+qmul:-494401746/19681,407904654/21651245,69321355/12439911:-201668773139125884/426118152845
+qmul:365885228/56568973,4250982/8521637,960401966/74768881:1555371518293896/482060253368801
+qmul:255177714/7055753,814922797/4572404,187054293/4701449:103975068212473029/16130876620106
+qmul:-588905892/5841913,=1,832554893/1175043:346810149632315664/34127947499569
+qmul:135837085/706833,-289514879/255430,725428338/928723:-7865371445497543/36109270638
+qmul:122186761/430279,=1,619259689/728443:14929604563671121/185140017841
+qmul:775073757/30757,695907415/51279,944630725/67207:179793191556069385/525729401
+qmul:95477167/3960,-871735667/38397,-714770441/33262:-7566441078001399/13822920
+qmul:-884857813/4929,70752241/2056,154069499/3880:-62605673236108933/10134024
+qmul:229619449/1615,957611614/1161,10452182/285:219886251162680686/1875015
+qmul:111146789/136,146738413/445,169865033/157:16309503427905857/60520
+qmul:9871622/41,-808689707/803,=2:-7983079102794754/32923
+qmul:-288336467/9,=1,850175175/86:83137918202042089/81
+qmul:558230684/47,805462654/41,167574699/11:449633968278875336/1927
+qmul:339929608,29235627/2,=2:4969027612872108
+qmul:881780865/2,443292701/9,=1:130295673778655455/6
+qmul:2838001100/91389568002455572881,=1,1986643253/20570864960839080487:8054250243601210000/8352053139675451489580240654173902640161
+qmul:3251591241/344636720089928137,-1113406027/3139375771816261090,-3172679089/93012796738201713479:-3620341285069809507/1081944169128542879223598266129289330
+qmul:2151380941/4425085028680839366,6291439247/670381381077695674,-1225149433/257062097818706652:13535282487455191427/2966494612913295666228911591427102684
+qmul:6158301795/2455047697567864031,-5798372309/5521291989057645588,-157042968/9556961002892580965:-3967569622065888295/1506115020592873902921765927885671692
+qmul:-8451954373/975723814918920513,4784366210/605780426352481313,8465359637/69665667013568159:-40437244910642936330/591074388603853235233268628964873569
+qmul:5825412784/511571458045271039,1008046458/332866639017254645,1740022059/196312276491243337:5872286723299119072/170285071856685864496671466706726155
+qmul:1850720900/45716430562358967,-3131316310/52356049605863119,539696323/19977050509485334:-5795192539427879000/2393531706325862841899110744238073
+qmul:-999008939/40305492823224241,-149362865/49775456964489,4606037138/47949128805635417:149214837289650235/2006224323454918453607620977849
+qmul:-4057348745/579860156310338,1212653237/2742714067824482,-3833477943/1278732708982538:-4920157089262137565/1590390608083267111519706094916
+qmul:9177815341/2326648645173174,371635999/876014400872787,-2149851912/2031850250792911:487258081841437237/291168245563265658397194145134
+qmul:149460870/500654885667917,8207530879/259222934708685,=1:81780313715146982/8652081915938573470536383943
+qmul:1089507559/134057483313428,-7987532800/42390827366211,3382946045/262278399004573:-2175619340840108800/1420701908072059536662445327
+qmul:6048157042/13712987352923,=1,-2693371451/4466222589529:36580203604694189764/188046022141426146556643929
+qmul:2603227553/49609180587155,471640162/92076035059005,-663933503/13520440154956:175398094974254798/652545235855913432995725825
+qmul:4393500955/6416432605233,-3583476841/7979065549803,441355864/1454382446413:-2249144131879126165/7313876621863906114274157
+qmul:64145470/8127876011853,-4488303205/666124315584,=2:-143952159293615675/2707087922773595548308576
+qmul:2220237721/64548387245,-703263819/579214597702,5697314686/589964874375:-120108681442947423/2875951396186583316230
+qmul:7022991149/836362149630,-1984639629/975088070,-1171252556/150772930335:-663719359448649701/38834607347798472100
+qmul:7911754989/73811019085,=1,8326854813/74451049034:62595867005966390121/5448066538366234237225
+qmul:8670773721/75336074123,7789940197/98427175582,=2:67544808748309163037/7415116995363087664586
+qmul:3813777004/9138760931,3878060903/1782466818,-496564577/8664398681:7395029745986437306/8144769058571143779
+qmul:4360854339/9648497864,=1,=1:19017050565975126921/93093511031612562496
+qmul:-1306392307/687643073,-9598905761/422850143,4622499059/88598595:12539936641788380627/290769971751009439
+qmul:4779917420/76898307,1792785739/166010625,2225422443/217138286:1713873556834734676/2553187201302375
+qmul:-7341873007/81873962,1385231861/3699454,-4877758523/40734069:-10170196408712276027/302888956216748
+qmul:908541847/68126894,3798368094/17436611,175898188/3762149:1725488181854314809/593951074658117
+qmul:-7938465013/6277994,-362880881/3869862,=2:2880717177705116453/24294970416828
+qmul:6036183652/5477115,-1788527459/1739644,-2727500049/825193:-2698970052292225067/2382057561765
+qmul:1659028493/577907,1961575125/200776,=2:3254309023535036625/116029855832
+qmul:2324185733/425376,-6101126398/443667,=1:-7090075464730639867/94362646896
+qmul:158821375/2278,5716179055/50437,-700123827/1726:907851417261300625/114895486
+qmul:6937745972/64507,-657862356/10135,=2:-4564081910469430032/653778445
+qmul:-688655549/3844,5925620489/6516,-2612322997/6399:-4080711431017943461/25047504
+qmul:1356483025/6163,=1,2367819633/2590:1840046197113150625/37982569
+qmul:6911498420/997,-520233898/887,8567846181/167:-3595595764057441160/884339
+qmul:-5665580795/223,245568655/53,520214901/133:-1391289055621980725/11819
+qmul:6848382683/88,-3930604705/78,-4380032639/66:-26918285195440323515/6864
+qmul:7058656941/92,-2614182743/76,1606422009/16:-18452619163919369163/6992
+qmul:348409636/3,-58882183/4,8721866869/5:-5128779986478847/3
+qmul:-7530659939/2,=1,6943419397/7:56710839116859483721/4
+qmul:5479036571/2440360696983602620,49554857924/4707522136067292695,14037572034/1860137811841092895:67878219709076284651/2872013000259729052687425327777215225
+qmul:-90287321301/55986373996879974676,79056497918/57955348234225101999,68036645565/23598836282510831821:-1189633238075717258553/540784966893457334425356770707772829554
+qmul:-31154471814/4775267091317819455,20452466931/8265429859332817919,7980554951/34755849271476873:-637185804528606582834/39469635202867679038129686483630814145
+qmul:85271504414/7465316608452879443,=1,-10606469222/1904172971848733911:7271229465026821483396/55730952064442402518704478477891990249
+qmul:-16339852699/127321792148125915,3040615183/55882163298738283,-51110404691/61653999585316250:-49683204204562928917/7115017180309586101368162514903945
+qmul:-63804908144/277883532447300683,-720647040/27229766739402803,14615586307/46658500039754383:45980818191445493760/7566703769261267728805752794014449
+qmul:10341018519/94245221741052416,87590141171/60174320543406768,=2:301923757310378448583/1890380727576845520968582099050496
+qmul:94172173704/61262926143770059,=1,=1:8868398300136349079616/3753146119697024991735097864863481
+qmul:-27044253543/1053895278738638,=1,-26863808373/192367352651581:731391649698068052849/1110695258547591485248314095044
+qmul:13955551844/8914953109146301,65978266931/1477260665198022,38242091460/2633752121605511:460381562366420635382/6584854780113319521064766908311
+qmul:21380540693/46366763004112,4413417248/3293403036539,22792743143/98178838808334:5897577941628254554/9544027379514164158953023
+qmul:54517956885/536986169058356,53087744133/624679940801624,-12768510380/23381528319939:2894235345764805705705/335444488298664683363875570144
+qmul:15631958865/98900123425043,57461678219/38736535635779,10636904565/14357297124671:898238590233274461435/3831048155437119617055413497
+qmul:11306366194/20614966646301,=1,48649167285/72083597787241:127833916512826045636/424976849828102699236982601
+qmul:-38850808449/5270347545016,-80555988964/460100649873,=1:260805441388343496403/202074194209869310181914
+qmul:2473793897/257329894608,35125602539/6570210827640,-58955090604/1845404251483:86893501189425904483/1690711659828941653365120
+qmul:8389450307/94247305842,5879374061/445968667154,46708714783/778418252722:49324716521024286727/42031345369212137713668
+qmul:10005721251/317400686611,11885509039/202069710332,=2:118923090370474887789/64137064802662680764852
+qmul:53843304483/15517809130,-37493619897/27992722981,-69059984171/37850731407:-2018780392284038098251/434385732248122616530
+qmul:4936875434/5558111491,-78071231962/38058507841,11261412306/45256951175:-385427947175313421508/211533429761375700931
+qmul:-51013899132/7547986135,18679893598/8111901153,-1770753005/1840835446:-317644735934954852312/20409505810444837885
+qmul:25767898320/6199052159,24344608263/317305927,55665198980/5479278553:627309390361215818160/1966995991832846393
+qmul:-7303061735/68386022,=1,=1:53334710705221210225/4676648004984484
+qmul:20359304675/219624604,16344153007/211704953,-82591435031/427080722:332755590724330407725/46495616467463612
+qmul:2652747256/1352133,-25367065339/52123374,23447425715/95023951:-33646206485402479892/35238867028371
+qmul:48463976225/65809761,-35504206691/75941530,11794361717/16873414:-49162143684574569185/142791255407838
+qmul:82320116481/5180912,-76359077209/9271893,46566602503/1634915:-2095296043408850793843/16012287235472
+qmul:-730645673/7142476,-70390135745/551403,34012585939/9989481:165370572681565535/12663609948
+qmul:-51855352987/140641,=1,21714825731/757834:2688977633406369822169/19779890881
+qmul:-59100071699/229458,-12541528262/72971,17155877720/17761:370602609749617428569/8371889859
+qmul:19150460726/80285,98656519537/34995,-82017816286/22501:1889317802757170203862/2809573575
+qmul:56611908394/98549,76064158111/38373,31178576993/24120:4306137151046664083734/3781620777
+qmul:-96850333567/5969,-11666596495/4102,39126150628/3881:1129913762132343047665/24484838
+qmul:71357908657/3994,7273127113/380,-93120031916/8579:27315533693694953539/79880
+qmul:5232641313/278,-1351690114/51,-35248603917/754:-1178818255481679947/2363
+qmul:22060731824/219,89417675500/637,-9595385874/103:1972619359530955112000/139503
+qmul:37188356744/5,=1,=2:1382973877319010281536/25
+qmul:12414356869/26,=1,12979259021/2:154116256470887483161/676
+qmul:11782172818,32822292611/2,46218809976/5:193358961912883223899
+qmul:-13859731454,7084622496,13548345935:-98190965247527189184
+qmul:321169783966/82442472722749202597,728527457037/49184101549953208178,-116751888207/19107774656803205945:116990502994936318234371/2027429475212472071101744494655719619133
+qmul:554171781160/81669314174466653821,=1,-943011129301/98221859405082497556:307106363034046930945600/6669876877727739897311710883496653900041
+qmul:908239534764/8881960367460059525,321942265297/2978409748429418777,=2:292400693254215542284908/26454117343606783848277419057572700925
+qmul:-293031348403/5516820790390895330,=1,278931224397/2151761313912895609:85867371146880370650409/30435311633289223066668620559015808900
+qmul:766830499115/867319503385856977,853658890931/417340410748453263,960525534527/690526698684531078:654611673406576077026065/361967477793198051355224772486965951
+qmul:-197174946287/216799088567900459,769225126373/927398327060743836,=1:-151671922975207062127051/201059112046164919860050113345820724
+qmul:349764090584/42391126842026521,126613453358/49564405785108583,47812347985/3864181199117983:44284839369460570981072/2101091012486211034301711750729743
+qmul:794966910230/98579318608567187,107830796401/4405388705587841,856324471442/41561939350641701:85721915042543174082230/434280216802727167073601578773267
+qmul:-179910941947/302835045319248,=1,206545791527/3108222449901933:32367947032256804150809/91709064673510989994239285504
+qmul:390922759353/8379914783143840,539029053922/2783352468162407,377026177321/4659432906395457:105359362565312633416233/11662128247327024341591580811440
+qmul:-30764803124/12561782256971,-539449006376/482535642547081,580743800830/469238701287641:16596042476595060718624/6061507672904022859307951651
+qmul:-569617603186/169437350142461,73746787167/436340763191759,=1:-42007468148734603114062/73932422674350728263711178899
+qmul:869918621105/65172531895443,=1,489477033911/47131389526667:756758407345224551421025/4247458913662535154284166249
+qmul:-8609389849/44096958877799,224885883076/88640280149647,-627519969739/56922930432434:-1936130238937915295524/3908766788675566748905986953
+qmul:471174356951/3605083055021,-674320263703/7196435655733,32653595707/4448011615939:-317722416629289771049553/25943748239031977053085393
+qmul:-321789321980/1418987991609,661459092590/3534157194181,275403065624/8396219756123:-212850472922042142128200/5014926619001395811627229
+qmul:239520095411/796512451093,194140409620/80232450203,352671980162/687407449757:46500529435313022253820/63906145568388595421879
+qmul:2337932296/15976804799,891988698331/936480654559,185442793337/376858000885:2085409185495046197976/14961968615928892428641
+qmul:935302241221/78956895643,-101991808861/3724031317,979935584834/36290437707:-95393167413877147259281/294037952067632851831
+qmul:961545851/11884552,=1,185080005240/12501042413:924570423575314201/141242576240704
+qmul:58050869295/1757344829,=1,11607624876/16788707:3369903425905173797025/3088260848013039241
+qmul:363276341759/9253851473,=1,406409104036/7111288491:131969700481801767214081/85633767084344269729
+qmul:939766494010/411615661,=1,=2:883161063263847365880100/169427452380466921
+qmul:95392761314/73563601,412095417791/369293182,-720870043827/236439997:19655459913964986068687/13583268146334191
+qmul:-283241870542/75087435,=1,-46818914283/44014963:80225957228131087373764/5638122894879225
+qmul:443163826526/66515353,-29122331797/35808847,186565142908/1472243:-12905963996518321847222/2381838098727991
+qmul:-24774947444/1227689,-306928083461/7644000,333533328161/4876266:146233214169883088917/180470283000
+qmul:113920584697/1429782,163887873152/2653059,=2:9335101167111804177472/1896648001569
+qmul:90035464372/14941,-388195481621/80696,941463087781/51880:-1248262873387818796679/43059962
+qmul:67426970975/82846,-112582136156/206687,205395396001/267511:-291964324111311925850/658584277
+qmul:588160655449/37102,68128342139/34512,685450911404/43621:3082339259009843589647/98497248
+qmul:106389170475/11959,10438395803/2811,-17763245232/3457:370177423523630505475/11205583
+qmul:957920630589/1100,-65200663999/4804,-495801128911/3213:-62457061172743590465411/5284400
+qmul:86819672583/656,170251645086/1615,-548605083301/1646:7390596041541820438569/529720
+qmul:945486048523/580,28855850251/335,140898494269/717:940786338985841645837/6700
+qmul:-942729414451/606,-155199725039/485,483080000839/479:146311345908972673138589/293910
+qmul:581542707907/80,200631032151/4,19978821934/5:116675513727268918917957/320
+qmul:122743007281/50,559800662157/65,225369102329/50:68711616751045272165117/3250
+qmul:35327132396,=1,-649864145447/7:1248006283324512700816
+qmul:308054644516/9,-604402431775/8,119532524081/5:-46547244066263391973975/18
+qmul:3861743183656/92552781226942245973,=1,114427276291/73077495457803798401:14913060416513578545526336/8566017312842233033877184833269634716729
+qmul:5469306927311/39880346228597657723,5296888632971/77121945726781675037,-3329987784143/28763591448200709046:28970309693503183254970981/3075649897407170819117742626456739360751
+qmul:-4797915047085/1960347615737482622,7417719670675/7273127653602457926,=2:-11863196274329991106244125/4752619484897976601830464968970387324
+qmul:1723762402189/606999775863219192,-7434692936637/9420435145331634673,-763069528725/1760517742915668356:-4271881385331661962366131/1906067340583431653778258276488748072
+qmul:1247346376719/305242807686295279,-8174066739160/92487214707299057,864841572942/954533768467866835:-10195892530150517269616040/28231057092341186368611708660251903
+qmul:8115256720883/749493161740626651,7922190030123/83578659421247020,7349631862907/82560331952121241:21430201962022657324386203/20880544567891147401285999555443340
+qmul:1753584378376/56804157255787803,213889152627/40140349321665607,5387174104820/22251532318661783:41674741861198575821528/253348746130016489574409435021269
+qmul:3381018621303/55670925159235316,-1242546983419/8405146979568516,2994898998212/76089681788376449:-200051166132548046722617/22282014688187220091206580424336
+qmul:7888297086927/3953740879862848,2176178614605/2418237546542311,-2065888373875/9727383036996952:17166343426221456116768835/9561084644983571534390308961728
+qmul:1741311395143/229412472933092,2666488500577/3024227444254530,9874403395326/1841428086863885:4643186811072502030497511/693795496698556358912507906760
+qmul:6845501734987/168012430428203,3889846647591/491851863425965,-3888780746586/199780562527063:26627951974917556063966317/82637226984836948219538490895
+qmul:-1284195095943/549849541303853,161668973970/13553314165481,-1448576168827/183855043551637:-29659214791201502800530/1064611939576677294763556899
+qmul:-980146856483/7876738616913,817692682927/16494848113266,-6731998495411/30165003479004:-801458912740049493365741/129925607113876840407267858
+qmul:369161816291/12273827592821,4261359385017/20241923902166,1173948411280/40404643959651:1573131170441574491911947/248445884122187978887950286
+qmul:621724265513/2926458480357,5890921582229/3168077061735,=2:3662528893906004858368477/9271245983738877773839395
+qmul:4707387599849/1922231158856,-798328469963/4676681253515,5101926004665/1755468911768:-3758041540110251059835587/8989662425544269173378840
+qmul:9303566596976/14895662221,171128850459/80855092303,=2:1592108656909253425611984/1204390143793264984963
+qmul:-1614421541843/173435332903,8142990982280/901238217503,804529656112/153754860089:-1878031436689446098791720/22329507182505589485887
+qmul:-5960114035004/31883313095,1873973661895/29899945043,6761957056543/92101155065:-2233819344697646018194516/190661861865852447617
+qmul:258875168272/22951320927,3271990041276/1787602169,7831605696304/53881261029:282345657506544241865024/13675943690173430221
+qmul:-3741159259/841057,1140691661765/3674903711,117686209034/892146331:-4267509172076226032135/3090803490462527
+qmul:20024244473/524834174,-9933799893095/4311996268,1282763801711/933012946:-198916837605195544613935/2263082999606862632
+qmul:9690216301431/721938703,=1,6855538744648/1038547:93900291968519089052647761/521195490889322209
+qmul:9772645191158/606342281,4046423002077/832945094,-9924558382428/71076263:19772128146319455948017583/252524914121859707
+qmul:159522763697/46674038,=1,-924733338517/15943657:25447512137528901107809/2178465823225444
+qmul:9885845356901/75377901,=1,5061603222137/99444337:97729938420561060068323801/5681827959165801
+qmul:-3014509110363/533159,-6677531265927/3294029,=1:20129478835870717944501501/1756241207611
+qmul:278495797709/459094,3008292413757/8715826,=1:837796795511188800682713/4001383421644
+qmul:9263458041541/380854,-749140991886/18803,9474188106647/58449:-18166586768414575214493/18746591
+qmul:-6233175654833/507607,7036736213809/354450,815399146191/197662:-43861212857395998672188897/179921301150
+qmul:759911289647/22797,-4620304106965/4804,581754997430/2403:-3511021252485103785091355/109516788
+qmul:5617203937033/39335,3723507511221/6193,2744191857630/46241:20915701051602548624947293/243601655
+qmul:6420686828307/451,=1,-1838097053444/3113:41225219347195003296486249/203401
+qmul:-230435506159/3050,3395048403224/1759,-7515243692907/841:-391169848615613583728308/2682475
+qmul:9537534272745/521,8952214414132/843,5712074011478/809:28460683930581916956810780/146401
+qmul:-7519755017367/994,-1817484841018/15,5714574669259/496:325405732196037376760943/355
+qmul:-6778271913655/47,1098941771956/15,59404867523/3:-1489785229518322546491836/141
+qmul:-2383271627938/37,=1,-1307389832067/19:5679983652534244702131844/1369
+qmul:6051325942003/3,-2529633865827/2,819845568100:-5102546345349420428543827/2
+qmul:193126426699/2,9833682493639/8,3235704083583/5:1899143961289011867267661/16
+qmul:92112640764600/11163413455400457479,51791476178419/14329005607185776493,-13205225377669/4458612884103206586:1590216546630349267393055800/53320204665922099816203131218014747049
+qmul:22529406302098/17968547726331516709,90921027222753/2166236440992021142,=2:1024198381852757628328617897/19462061438241829125530785318127130839
+qmul:-53737977727933/7683225139372625170,82909671587883/8352188215577205409,=2:-4455398085219896100673435839/64171742466694571547497029664653544530
+qmul:9092501686631/9417724412639248549,-76436516279586/7751295678592549727,5796309029559/364193213335723936:-694999153192333594154414766/72999566541866165880702093299195096123
+qmul:3136955253055/79379115811095793,2712229195967/40950870811518088,74321528780980/800208315081442781:8508141623777819670429185/3250643916712716666840937120203784
+qmul:-15679427832242/304946032535805217,39088311244217/271842618581639769,-44522979753228/676520091746633939:-612882355237913950168644514/82897328010615208848930336644874873
+qmul:58297984629025/79211523461014146,62851948787804/71793418809815961,70122280069093/70263603402410591:1832070972167832036692205550/2843433039200075640773122338792153
+qmul:3395759457623/8856655409516280,80356132877828/35186041698707317,16595221216126/25184750109463717:68217524549473731850570711/77907661637580389256034066655190
+qmul:25595373885269/2107431405075994,56934769844557/4108548181624632,88071750654219/1721697405597152:1457266721243175200282130833/8658483467223618408882342284208
+qmul:5741950765088/69374989603141,-20852939430084/837468342763903,71732839501654/4900087435552233:-119736551514904546484107392/58099357572205493945030219323
+qmul:60636029091157/828828822290712,15933414624847/515795094226125,=1:966138992713689089520177979/427505840490766008807415251000
+qmul:68154525908584/447018537159783,-53054791972077/814484661933752,-70920570409331/22166122764311:-150663508084810679482608707/15170405921529425529107695659
+qmul:3803110014020/54088464597551,8401206536763/81355553929736,20928341840506/38139684449589:7987678177453412143854315/1100099249635669192942919134
+qmul:-23763903446216/81519641545907,=1,88937586611085/34349668275946:564723107001076681204718656/6645451957773166616788452649
+qmul:46601565963875/3780648692562,-40570846513055/430918579048,82143257528821/7547555659366:-1890664979988380613845888125/1629151762478496046640976
+qmul:-14254006674106/532459447725,51813993717043/1845962555644,5112664309595/4080729032211:-369278506127408636439494279/491450101449616910854950
+qmul:18869803536517/528732466966,25637726635604/291934133291,-45103838882314/248345183985:241889432368388223683175634/77177527243265749182553
+qmul:14394788665063/18929691934,7293379245648/106206553763,-1412717946745/2868209191:1418738552638642755032376/27168342487910789833
+qmul:19814466847315/45927017182,31387249087211/83776988054,866410007468/44667970667:621921606466960354656188465/3847627169812266743828
+qmul:-84789189148688/68506660259,-2668232889482/7021853339,31544016021473/26570873119:226237303159039621969299616/481043721083397754801
+qmul:47144909009231/2853410746,-18254711672997/1611442139,47906136756089/4532570474:-860616720813190565726435307/4598106315979825694
+qmul:-88984055558977/5497567684,-29028728538235/9008297936,22366306780529/477338571:2583093993052764435041985595/49523727620797500224
+qmul:-22301781837379/314747366,-55932418652881/999474189,6168064682011/82717920:1247392598433499880191838899/314581868372736174
+qmul:-69455755003925/425627363,69330030826593/45004450,36456142539195/445137553:-192614785420256450548375101/766205015070614
+qmul:43441277702263/29813565,11503955305028/11366299,=2:977977528532569481665124/663150477585
+qmul:-63910040173409/12354709,-70800414587599/73292555,34497242288193/35625551:4524857340587464687180954991/905508188891495
+qmul:-7828296754760/3568223,-2036289302690/840627,7170972735213/4627145:15940676940000630338304400/2999544595821
+qmul:21326380201837/9337727,-17663536047163/4880532,26768558322470/1065127:-376699285450651185091238431/45573075430764
+qmul:73980502263403/962358,-21947232844793/591723,21986948107511/9185:-1623667309149641199103010579/569449362834
+qmul:11206027962511/331874,-1256483151365/547727,36460011888012/776539:-14080185328620131358477515/181776350398
+qmul:24401059998574/37451,=1,-59473261910475/49718:595411729054008176882033476/1402577401
+qmul:-60818257728179/86203,31465212303166/90637,6184562112579/9476:-1913659391325818531369114714/7813181311
+qmul:71004965949889/9037,7059443197743/235,3055009450153/4139:501255523880917233655900527/2123695
+qmul:39294675031972/2789,59869119724423/5716,9542643866131/1571:588134401005356710838563039/3985481
+qmul:-41787574848379/366,64572657701526/571,-32471089957981/546:-449722461143545734347821059/34831
+qmul:56523234971544/89,91170129020768/233,58883776410491/503:5153230625026852353065025792/20737
+qmul:22661601391845/32,=1,9300929081980/9:513548177642871241232504025/1024
+qmul:31371000692905/28,78617790969393/17,23430144401503/6:2466318774975488254647256665/476
+qmul:-97166077882733/5,557907250924,-67696293193377/8:-54209659394622846477895292/5
+qmul:49131886852510/3,44123944198873/3,=1:2167892633865493233459221230/9
+qmul:11078630778023/19971767689676985138,5498810148139/653213547400621899,-28047430739573/8529087351247312093:5538117031788903405049927/1185984474585002385862227360780030642
+qmul:225961652216941/7065181247481573942,-551303465095893/52284679786625043776,12334914241622/807684136438179561:-41524480615330881905534707771/123133579719680720019267336626376961664
+qmul:-140752952779551/667166575947606995,=1,=2:19811393716162513576803761601/445111240061654052498343266972930025
+qmul:97203673992431/3238422544888880032,=1,810591359275652/4195094984894633475:9448554237626806783045289761/10487380579244570205870590527288321024
+qmul:-167516702376095/716105586249718324,97868227848619/242920547738562082,=2:-16394562796592961287264362805/173956761250425686574425765286990568
+qmul:-709927885497849/861328058843025997,496445275118167/289296738986245691,-290819441307632/13291786866431071:-352440344430038207159099322783/249179398620640561552626620942228927
+qmul:425323787423127/77722671910833479,317441925005700/19142048058380233,=2:135015601830312569987786823900/1487771120942893870562005728220607
+qmul:268865886927957/35135976545503325,123771762953727/25295982530865037,276904755282677/20891637935797169:33278004823190660692373645739/888799048899935778999904809748025
+qmul:-28086740887571/7601230497184463,100947908107803/430543690291880,118463785601217/2540243084118529:-2835297738166190579370816513/3272661829016980468206671060440
+qmul:-103171508624837/2023211396120145,142320636082678/1434318582636373,-735609507967093/4547494153253362:-14683434733096301226416273486/2901929702056803783817555034085
+qmul:-220041868728731/487356763210567,11401923921896/63654265331715,-621742292531267/238183796053545:-2508900646876817363255193976/31022336716611231326648232405
+qmul:500876116381607/333341742549014,=1,236931212585485/143461697112113:250876883961521120142447902449/111116717325613130586192372196
+qmul:27571394309122/1874139359093,126354562695342/663284435945,=1:3483771470829951376257509724/1243087467678324311797885
+qmul:1227588316119/3212397849532,273285780765847/3937050058645,177000179976745/33792263075573:30498402857237483359526163/1149761012899184771436740
+qmul:935605828517486/1504497672649,142177975023733/2313039446120,394962145699157/847510134854:66511271059509072349527747619/1739981231716436016585940
+qmul:848730874297608/1142939979439,56376353318381/3143925208632,-237516636617763/1280813501326:1993681318400848339723780527/149721575554650494388227
+qmul:57281039318273/114674810495,6245708686714/18061176617,39223096410155/17868534091:384275708758478900851262/2224663808669387965
+qmul:-154031591323851/83034647227,983277618862577/807648489169,313967727668057/230581524944:-151455816346529785816271424027/67062807381567445384363
+qmul:-926888573138874/48704635267,6005840682571/273079429,81726441309104/13903294547:-5566745100767635280134365054/13300233988365622543
+qmul:169804184361113/49086554885,384285590061633/44857652581,=1:65253301182144623556398477529/2201907625429518408185
+qmul:-225793750988921/2498217360,=1,171352487415765/2208376327:50982817985646863065464744241/6241089977805369600
+qmul:-929534096793899/9204730148,8408973696/70382485,=1:-1954106942368753656070176/161962945392664445
+qmul:-27418637405473/910326852,=1,81707725335094/491085905:751781677172803165010353729/828694977472229904
+qmul:-223297515785450/193612253,-474964608127809/679335356,=2:53029208540474751774311289525/65763824408858534
+qmul:3933126433661/878772,9000930134181/1427513,476332935917525/79251326:11800598746094380908355547/418152818012
+qmul:703078612387607/27834381,373006385325321/46624543,=2:87417603935414581043747898949/432588431270961
+qmul:28193205330738/1040371,26659473685633/1938099,=1:250538671876152577201295718/672113998243
+qmul:449065926671750/1450887,=1,153785599009868/2460537:201660206497557548032248062500/2105073086769
+qmul:108938909775878/133591,917154127926373/709564,=1:49956885396372608707157715247/47395682162
+qmul:987814971089463/782828,=1,930147796775719/981962:975778417108476622509149628369/612819677584
+qmul:175113052851196/12305,-227591234473631/6533,64742021370129/15710:-39854195870849886350828812676/80388565
+qmul:-161174581471221/66310,=1,=1:25977245712423255688851230841/4397016100
+qmul:-1469325465654/4457,=1,582669979881900/2099:2158917324019343933647716/19864849
+qmul:102435434692175/7466,-187593100206263/1358,174025094651948/1265:-19216180764881294058412092025/10138828
+qmul:489625099725000/347,-332985825161621/684,=2:-13586518154314174697304518750/19779
+qmul:-832879871119661/546,=1,817644952915049/828:693688879716303117501780754921/298116
+qmul:810059612480081/97,-378237813607713/41,=1:-306395176716377100781960464753/3977
+qmul:-534858850780477/21,-597970346506983/25,=1:106609910777842848826760190297/175
+qmul:950469485177429/4,=1,423712356772633/4:903392242253446925539611050041/16
+qmul:463433346779246,599836163536496/3,225455874511593/2:277984080786941465486776362016/3
+qmul:2132350013169985/49772441764072596049,-6499905025666569/10288915167781867756,-272858606518027/93421129408183888508:-13860072567083760096603328731465/512104431003906236530336497276926096044
+qmul:2042725727410133/27578306884656676115,=1,-7376907052537410/47153921627935428199:4172728397423256990351591077689/760563010624301820302156974840011493225
+qmul:1904035906025563/789989122373815219,700724530060177/1554126856272208244,-1373172495932670/1505401488389199241:1334204665467465969877290304651/1227743311244058254809898816344465436
+qmul:6705450642041083/4046641113087645351,236666376333371/9320552548004534960,-6289242797407739/4040540787026624125:1586954705134139142713085880793/37716931137448960379165612296160970960
+qmul:-5772878945452494/146823071716041731,=1,-1872446183124785/135874056483712011:33326131318848699195882410820036/21557014388133933331867562533476361
+qmul:3589764099796053/928994578492406984,1705996612666706/892580995601505897,4870605263289071/654751374199986585:1020687565754102262148510551903/138200484296525657161313541766664108
+qmul:2824552679707636/22642111815107669,8553369491681540/46601368890320207,-8526667827191440/6342142386526223:24159442718258634195461218239440/1055153405151710120834997591367483
+qmul:35430767900375/179014168662113,8330204183383419/90063013345106792,735637729618171/16696810462910716:295145530984190781866218882125/16122555461179081195997749371496
+qmul:-749012909078762/116545251178673,2437513877538073/992308910607094,-4884979809735527/4653837505135631:-912864680167322642003505352813/57824445616769571297747653131
+qmul:4715463621576807/1060495506862783,-1063435887535687/201313562930691,8544123110589389/5820955775073193:-1671531080517925550574808003803/71164042986178638246892124351
+qmul:8571923230143950/770828515798001,731727930435031/3506899807300,-1965908269773871/252650249852419:125446312900823969405125054249/54064367470267094252504146
+qmul:9586220341682297/144114066713962,8236658921505002/167483669474359,492069171252854/82950316475131:39479213650415110088905890174797/12068376358063466929473150179
+qmul:7229812835375017/5756294662713,905126544819761/4153935003623,-5202620176105898/3258193118931:6543895511376548680891107310937/23911273890611781218009199
+qmul:9842204333944723/52899600131954,1723939662409201/39238775342850,4378255309793533/73130188348848:16967366416823040750958140596323/2075715525304341221590428900
+qmul:-4908316732166843/1357513064850,1991070604269898/8806978369757,4254810663841145/2351480888682:-4886402580931743595080769296007/5977794099398240809870725
+qmul:274318025224231/1931992361708,-3590098558074758/5846677514951,57908255856314/1134380359933:-492414373405713403344305530549/5647868150127621484948154
+qmul:735894125946707/55761889279,3377584488978728/61428633213,=1:2485544585328156063980584648696/3425376643783608023427
+qmul:-1690249237930933/34238968152,3446531515472379/225376230292,-428431726758614/563113867237:-66959738707265887616299668961/88697121507880524832
+qmul:-1626151698227417/13809511809,3803324818338850/20014571999,8945616470363923/70396608712:-6184783112252203187079466250450/276391468372271236191
+qmul:2032027608247493/71600869449,1568676792624142/1225766355,6648151008356102/92054212485:3187594551029383836749262776006/87765936759331588395
+qmul:8570254081381348/584635199,833484957898327/779308020,=2:1785794465549524494136774551199/113902724838748995
+qmul:-51136063956207/124926985,237718332836713/43997825,=1:-12155979871501058567713827591/5496515623807625
+qmul:7279740565485383/495827506,380399580451240/42684993,-8253225185096257/179789767:1384605128452256161054382112460/10582196811408729
+qmul:-3582542718233341/437814906,8075748423185005/259890457,473970333141547/96599174:-28931713707765825242358002251705/113783916001752042
+qmul:-4332079095957017/44663887,=1,-2662542824998505/6313513:18766909293627765704435111538289/1994862801948769
+qmul:3371800081330173/11806858,=1,9890158011622886/66900743:11369035788458161257397040209929/139401895832164
+qmul:-3682944955162964/2466265,-355431368138229/155860,-9055791203817172/8090387:327258541047840188915493337689/96098015725
+qmul:7504952243792624/7720459,=1,6076575545940466/7559395:56324308181607941582939516805376/59605487170681
+qmul:-538608400556109/199304,-938340266223845/397242,-646694290244130/361681:168465983322739554802492073035/26390639856
+qmul:-727793735158436/238619,=1,972430738127054/625301:529683720935867681422021966096/56939027161
+qmul:6931913813817249/19931,=1,=2:48051429122190398233188769928001/397244761
+qmul:6291923102424872/90007,5686581845796881/19366,5042254583042820/677:17889767844699633282716137212116/871537781
+qmul:-5554695053757275/6432,6945167426101948/8185,5702999642802475/2694:-1928914357464231764593229833585/2632296
+qmul:2346204224991933/394,1993188578793011/992,5657592821492399/465:4676427464769828756406351780263/390848
+qmul:10931191773819/59,9918357253026368/565,-1883501998767878/147:108419465214079847823899059392/33335
+qmul:5137390097848632/355,2441231132619748/159,3483872315060623/865:4180518882426831300124305994912/18815
+qmul:998295698183777/66,-66459889053732/5,-7667707076954093/93:-11057770224018624245927284294/55
+qmul:1731949876588457/12,7146744265770853/16,277946983627531/22:12377802849111091588166946843821/192
+qmul:4833330269678962/7,=1,=2:23361081495794907533662545397444/49
+qmul:4819457078692447/9,=1,-8437238110144547/7:23227166533358735275059214847809/81
+qmul:41244630307260683/19566167985724232189,-19443176533044379/82985325719207603055,-72237473765794569/82811331956111155429:-801926628104221886667557960850857/1623704823372057546563828915880965737395
+qmul:-37802618179190435/86632766813453833079,18052713986379148/47810592068654841423,7865481647337074/9519629220475921943:-682439853925221807159327605049380/4141963873896940191789582700970256831417
+qmul:19604614792857791/565916848676700071,25954734261578645/2626241461504040026,=2:508832567249237638495290647473195/1486234291758457454242685700381041846
+qmul:-50232902667050876/443948998116187511,-43501226416110749/2403446154007360893,1072605872716961/3220822759958359344:2185192872457833663604613633466124/1067007512097771979528373151836407323
+qmul:-14994187874938337/764476959662103704,-33213154437024890/559246869916170493,-82827329689594088/466257548265395579:249002138774046516984579242103965/213765673407031013718036719955403036
+qmul:5736891872168725/77162101379651687,62325478498146677/137153821651647001,-18320014200167058/208017523087093295:357554531025044304704709142076825/10583077090891052476054011258140687
+qmul:88925222453111571/10971132513398300,-1434252874823377/1536739410012178,-23821379824785146/29460096443622911:-127541255947683583837180699995267/16859771705805127088751164497400
+qmul:24175746316538219/53267154590314585,45382600351882515/10887587811518971,=1:219431646658389958690970919068157/115990164614361176557282717098407
+qmul:6404581190281274/1974919158789793,70447714998202471/6402341997956028,49530122164311697/8312624539331270:225594055187891770083262445914027/6322053936443940716188054611102
+qmul:92136543904285079/3155539462802804,15181471002529652/4087143424836463,25144211605663718/418936831080179:15204002929958740164475777811549/140186330078331141119949106981
+qmul:-97970673283608013/593909853478849,56972616762762010/241259986786383,19037324141894916/620131018874825:-5581645622976766094030156047986130/143286683402609773344371713167
+qmul:73158390938899175/379989099030207,71464686184078751/642455545049147,12129094284454088/244856744399541:5228241450180579956236327448930425/244126103730185933897852583429
+qmul:1586267657723262/7744841531795,15363089519026552/9850991413231,-22902559865915557/6801969550956:24369972026739044413538846052624/76294367426547369870179645
+qmul:18929755299266541/13128569349373,=1,-44651987164496438/25396774874437:358335635690109691215372562104681/172359333161296196535493129
+qmul:80561540824410061/2163952339904,=1,2086973582459110/2490108327963:6490161860003088890959828678023721/4682689729375996750729216
+qmul:78697609896523577/5434699087585,65526206295867334/2106565485155,456371042378372/32324922977:5156755821071294622615308595133718/11448549520109931362300675
+qmul:-47473161024846652/621907871141,-96761692332772358/887316304237,-65934541786023949/449412506848:4593583401150371824007100974445416/551828993796732548324417
+qmul:-14783030669421870/467861289269,=1,-23413922007662121/167402876249:218537995773067621857840034296900/218894185996450894554361
+qmul:63487097677098051/89903303933,-44532336344734228/31521473625,40321416288169527/20383337494:-942409595769175172584041963929876/944628207908139422375
+qmul:74416958364864933/47087590129,-26664478457249131/9883383278,9944734731289232/14129955379:-1984289383173946522947645546623223/465384700882276462862
+qmul:10292005168487623/3482492353,-13044085486904942/9174614883,-10587235554824230/4781845077:-618662650918986430811618914898/147237447796163547
+qmul:-6144278338130361/94748822,=1,4769179777732015/4767529558:37752156296417990780857029990321/8977339270387684
+qmul:42358656711205552/153537321,1887261908080343/399926027,=2:79941879288510016603861603664336/61403570783753667
+qmul:-46666950687843206/336186639,38668781410567001/444012970,=1:-53075121036644655437487007224859/4390330236961995
+qmul:37185667641742945/20035026,-22282077470907101/78670922,-91228561955942315/41271552:-828573927200719662619441817152445/1576173967713972
+qmul:42236447866339404/44996449,16229676747835589/11939847,15179360621924853/92208979:228494631949166233448275154749652/179083572201101
+qmul:14470604449517903/1841454,-26915603513076747/6747551,-30708091604466747/2448316:-43276116884198675180320043277949/1380589419906
+qmul:9101509000956136/4152121,20427468979289790/3465161,-3271799016139078/320637:185920792781758275773092222651440/14387767756481
+qmul:3901016944389149/228999,-12417812802023553/360344,12000955177317426/2675:-16147366050982125724725565208799/27506138552
+qmul:8669125566587600/469719,45940493589390645/423401,-42531240992326551/367483:132754635839146726987952004334000/66293164773
+qmul:5938430877112711/95612,6188074245922706/6253,=2:18373725585926676351062678057983/298930918
+qmul:21515481020492051/20064,43874545790741615/95584,=1:943981957243410623387527502402365/1917797376
+qmul:96468586146884551/4608,-79928708129965834/6685,-48993051068173945/9779:-3855304732922400319985402586215267/15402240
+qmul:-75478054000012419/5456,26589933777011524/3359,-72036212797226203/9505:-501739114369507496870468176529139/4581676
+qmul:-72899856135461282/473,5291266619094049/285,55496817136408/17:-35066597755120434743929959646438/12255
+qmul:41749939409527385/879,1093119177525389/32,-62509807806005818/473:45637659429077399966594328277765/28128
+qmul:32236549357972163/25,=1,-8149826384158677/14:1039195114508975474515043482898569/625
+qmul:24629347956178358/19,54301261705267425/23,24457116479256857/3:1337404668998534392792361387388150/437
+qmul:2790015469580797/2,17009277246386333/5,38190184436799791/6:47456146643806530617054620047401/10
+qmul:24781556873646101,42986775647721679/2,81575207729973183/7:1065279225528679999746318391523579/2
+qmul:515152885774965653/15080197507802975795,=1,-424832628935135224/94106513082678027465:265382495722274809438289573329716409/227412356874347082213525456257355882025
+qmul:846127691843273154/45393076460118791167,107731662129978485/4427725736529596013,856145822802565237/90388573766016577258:30384914205492685300912483332697230/66996030967574580526139479740140939057
+qmul:678813466845095843/4312328116586154098,456413709574125389/4100698962952630264,=2:309819772511642767874990940604657927/17683559435596311365398737033122421872
+qmul:189404516219742695/1881568644309026479,-990060962742696423/9938184412328540522,684558164600705533/1843391051573289937:-187522017676333112700620971556879985/18699376171598111009073165236722482038
+qmul:192924629174279610/915194634829559941,-505412960023216745/330833788805155829,115339652249094077/577677115897920453:-97506607892354095477504410264069450/302777308534814344556633116001046089
+qmul:530864983303082949/770272174330693891,=1,=1:281817630497382538228809007974536601/593319222548134880807536517544719881
+qmul:175427266863787420/37379184998319363,-737495252249552281/10171255350907481,433186573015158365/49314816010026687:-129376776427158427582783706960105020/380193235426716462103801903854603
+qmul:463395468161836969/36199229685681434,-381172902361185896/73861948752008031,951086817685754053/44721463664985715:-88316897770133955247493298327094612/1336872823952984931159738037798227
+qmul:388421361132459241/3796589587440279,-520242627647240191/4183488460948680,=2:-202073349549868206476119002444555031/15882988730014316745493183881720
+qmul:255643017739843159/5399110517536783,649866517463532383/2945752280295836,613430013767040536/234544931788503:166133837652459903075867976537517897/15904442118603209765181251735588
+qmul:155181948901437661/35620018080307,17101221587255570/264465563715517,-129836961434774282/466340126852825:2653800894505656514308728430021770/9420268161165298444608023719
+qmul:-839143559403582175/463688071748743,=1,-142780189059606272/172165382315553:704161913288513246519800221977730625/215006627882067436250122080049
+qmul:346621266229749718/59475689434557,=1,178397168700747228/42081103836349:120146302202715032285390908921079524/3537357633715875158385786249
+qmul:-375320695921875535/16168337083266,911110281599467718/34637020854445,777071986002999094/76066266020689:-34195854495148821384333396824647913/56002302873478088643121737
+qmul:-379308371310412479/968244496075,364865258770202694/8926182578765,249116584254479273/678952630517:-138396447051877776676786583577018426/8642727152849761420847375
+qmul:-10969933869374653/142543298333,=1,395828837569758458/4480744606673:120339449098453146428785278870409/20318591899650640578889
+qmul:357124791031669775/761802845389,917629329624700777/456858033563,774468512475077245/2887603961:327708182586752487826277715049915175/348035749907116661791007
+qmul:64954492028958167/95392360685,985096782515221787/715883047223,-29344192999567326/73661198051:63986461107637310581155676549984429/68289773848973303627755
+qmul:23618182683258131/18112927883,442655807275151908/16356517261,=2:10454725722029641395907751401163948/296264417565537688463
+qmul:732585647194345626/45048543997,=1,16467867097466398/1145670835:536681730475158241367430266345331876/2029371316249644736009
+qmul:157646812856286773/2982936935,123752181092126225/1627719293,-433800406988365539/1824179539:3901827386637546694386616182784385/971076799780357391
+qmul:18335836145139783/1476948589,=1,100294147058610519/4053918910:336202887141414537392732609287089/2181377134549090921
+qmul:-500900480985214557/585315200,=1,822543455056953279/726431948:250901291851219289979222443324706249/342593883351040000
+qmul:5430413424253854/29413111,737754500982617905/865566667,-431507384954955136/126635381:4006311945939711393067198205655870/25459008454371037
+qmul:69732083733340845/57018307,-850680479702859385/88346816,101371097024811051/77572577:-59319722440958347782449205312080325/5037385877160512
+qmul:935028252174165503/84545212,137808471873317260/91516351,=2:32213703647625121220176793216620445/1934317324190353
+qmul:350565565504682243/9619524,=1,=1:122896215717617656580228756399511049/92535241986576
+qmul:-470988077361736572/2840381,624215376275621564/9300947,748400046271858043/8643413:-293997999931687952811725899730638608/26418233140807
+qmul:238657877711036557/147228,760003504393876182/402581,40545524725498725/11806:30230137235265489411523617722264229/9878532578
+qmul:129309397398813154/103143,99499262875055329/104050,2865516124888405/1398:6433094861999752891251268341498833/5366014575
+qmul:576594622826994119/24550,764054211007945383/64450,196951790705325699/2321:440549549615502846208286120014202577/1582247500
+qmul:34307832224344795/5419,755936660033161242/53857,=2:25934548104649265347571596038435390/291851083
+qmul:-28093068552310343/6519,963611383601696677/3318,306035391422838526/3427:-27070800657309083458092703055830211/21630042
+qmul:144703609571824207/1943,353612545017871990/3809,419690158507626277/2547:51169011653965259593108361509261930/7400887
+qmul:533530159200500829/854,84950875994057867/97,561763750303203654/161:45323854393331697896795654407471743/82838
+qmul:786023983959036523/653,=1,35801962841884787/949:617833703358835705221613270447929529/426409
+qmul:977510365280960078/55,232111556352335897/28,846828806350115358/59:113445726117952006128263047051659983/770
+qmul:575356062531111409/48,127909051677869039/2,331562163778887361/52:73593248335467179491251257420765951/96
+qmul:223865459457586997/2,-255265991273068741/5,785308709687044221/4:-57145238420241926425388851168760777/10
+qmul:-89489266878597587/4,408356339430510509/2,320811062710131617/2:-36543509440864137915495881385541783/8
+qmul:6960121193016437767/41673724634003604035,=1,6854483270886536984/32457251506686121265:48443287021476560949924862262183946289/1736699324870758821080322609369068281225
+qmul:252294933101143378/671664801173160007,101031884553475048/1683990887624654527,6217560315186323017/75520308794957242947:25489832554501428241776271993432144/1131077404713826819460225518267901689
+qmul:95022283125541691/1892238412758904932,6220850886629533101/1296487687523964914,-3552806481592836635/292967787422034901:197039818077029516749136819680004597/817754601333936827050096136476518616
+qmul:-9650628580381886023/7106748638657239958,4387498480617035975/5131806125901481009,=2:-42342118233424867760904547954540677425/36470456199103234725545247832492957622
+qmul:933857454927346529/770907817024018505,2627554012834724721/741765905423985850,939220528406657553/251830131719517146:2453760903109972444306223754689843409/571833134893249499170644981258154250
+qmul:5863194086945812212/700078829279068399,9185022137361371361/111682660170098792,=2:13463391871060894578417924384075215133/19546666495663701071851276388818502
+qmul:-1393200667079143151/45785790746761243,-6119736754307708291/97236710970831949,=1:8526021328450249564289054954738564941/4452059701413814892014912979352607
+qmul:3607026924237321910/1072023164691893,248422707771439167/17526050077246094,942295846706978669/71124490430949583:448033697761760632546411047280624485/9394165834178976731308723857971
+qmul:2219105460493025188/4992146804272097,-654894851214548365/261880809182257,=1:-1453280740378971565345857635989217620/1307347444659395118592692582929
+qmul:5112830206310124118/4808519639244359,3895059152513717718/2399893258942939,2005821980379451972/672164805197423:19914776090336848562178934098195722724/11539933867717270078741058631101
+qmul:4465488275906636401/885680900323781,-1104529468377254183/50717559226303,-1531096850412298649/70636195562356:-4932263391432018452889201367737315383/44919573517776726756551611643
+qmul:5805379505512562993/802580360628120,7576393837591505509/381671212464334,827391747551350507/404055288015098:43983841510445403745585851020069028437/306321819340996990853337472080
+qmul:1568069089872115495/10344068691049,6482258105462122875/51585142886372,983293776583976867/13619011887634:10164628567748134676970172369881448125/533600261454209647780484228
+qmul:5123357244469621862/61996475985149,784192904118738215/19232930497666,7315968239528825344/72839297342337:105728957799431815835771283411022535/31378260887436578268293743
+qmul:310186678678899798/454385367511,496289849974746528/1664255858611,4370884482132758378/6990813743219:153942500225716088309659706960401344/756213509947294088987221
+qmul:6896960984221904702/8037366999007,=1,1507716158461831143/4162951083794:47568070817879184399769535232769708804/64599268276726789138986049
+qmul:4124205900530951507/699562645532,2446863765306479999/780453290054,2180063751257648537/428993105150:593609998745433301395350821902024029/32116233429666446066984
+qmul:1901990540997243863/309938083197,1828919653744696177/128932373995,=1:3478587881666366604445148811312811751/39961052858049029262015
+qmul:9909007556102284175/35699264171,=1,2257564478754303350/23996542561:98188430746892162461878914652455430625/1274437462350844317241
+qmul:7540576467990933273/59047654891,-667411621026349909/24648144492,49933771491922816/70442999897:-1677556121324992297591622679189540719/485138376555706170124
+qmul:7181294574913207518/3819238427,-5066099946607930227/3123415729,-1161733643221201723/183317684:-5197308008934802800386778397102263798/1704152767956145469
+qmul:-8059696125757072209/4595320696,6578165258606498110/3168033531,=1:-8836335508230093636747850255982004165/2426355008437709596
+qmul:1945331074426594741/151710177,23896636516777288/9647063,-8779812176082283037/763148559:46486869590364160149493061329042408/1463557635260151
+qmul:-3667612169703754992/456403523,-7174409726077474195/172294113,3512697218966135831/927221535:21444948999024227916663287692324720/64087726296137
+qmul:2801308578321040429/7008589,40646058755682747/3928091,2242284013880005543/86049101:113862153067235113557787361284778463/27530375373599
+qmul:7755272402005383603/37065862,7920705443805205865/32575293,-9791686678342842374/5250627:20475742777585438947450807922570143865/402477104982522
+qmul:-1833317998287765958/869351,2549513447231770664/4194999,=1:-4674068889686691615296143605162256112/3646926575649
+qmul:-9862573495076415071/3231099,-1012500145079952918/2881015,=2:3328619031542189525129501104301875726/3102948228495
+qmul:1848318375383620325/62739,2496061735601929291/71058,-3577860376337084987/826120:4613516772004977608237698310240439575/4458107862
+qmul:3935629218278546095/380289,272948451544220369/89992,728063154313892053/11066:1074223900981319628581080745604409055/34222967688
+qmul:1383092141504746774/6843,9725813952719193095/86512,9563731803386892083/450:6725848423871567383357583818792162765/296000808
+qmul:4310844810185467807/68701,5335008431625026234/79247,4165066621321185249/74158:22998393409766456521092748601937448838/5444348147
+qmul:-1231083168271826293/1767,2942557339085135869/5628,9747542072617181491/4658:-3622532811822443740742409486671603617/9944676
+qmul:2563045864459171017/1901,=1,=1:6569204103321259248191885398852814289/3613801
+qmul:3519211776742706458/741,3845395982348454948/319,-5561268787397081165/773:4510920942439923739354839714733884728/78793
+qmul:8737995292054242122/619,5446863961283262201/940,7037490695241026988/493:23797335825076532425122443838432315261/290930
+qmul:-6758789406646036953/11,3116671878311801932/31,40838395516557640/7:-21064928875125413266537275696088793196/341
+qmul:-2984260832879482631/3,-2187683625033562767/25,4114578793904862147/65:2176206185639821933770592463208266659/25
+qmul:228695312943600692,-8259900599013409474/7,1324126718913604639/5:-269857221767772356131493369277965144
+qmul:2275696080893255434/7,-1435737280894850537/2,294080994708276309/2:-1633650851662375193596252292396534029/7
+qmul:-84829337473700364773/56707961321161574960,-29927022646809239114/25185347367370413937,=1:1269344751844627231939227965424189665561/714104852184429966256312155357027108760
+qmul:17614709128893699831/24236675989376645657,4599289230585863713/53851416063001125139,55430594239089793855/41774891940497902166:81015141996423294341239778695297132503/1305179322688071182919814999640717871323
+qmul:67846551326033993002/4393005431010178629,-25740230532097127103/7368476450475338660,11432245987550154811/3453986965906439686:-41580615998568452669495076840090631743/770708501552589672691163995377845170
+qmul:78323538212378809869/7187022102980425966,=1,-32829495858735303110/2068874202909402271:6134576638105963615443551925372851797161/51653286708729184578994636138807033156
+qmul:12686256534955947787/123247933988654253,81930708153077686114/345994724232647617,16126072813581949987/95957301898986922:1039393981720550346819611040155758929718/42643134932647985540794888997365101
+qmul:90635825716321359861/838907685684947420,6188791645900690243/226601399055279660,-65993207203297829068/942167862280779399:186975413670826858643911432008098178741/63365885084811963416497113498492400
+qmul:4256124534146569459/8100972293435918,-36362420289668860861/78362919838311158,46047806868639334273/57305818998350828:-154762989115808645716121851999543044199/634815842442898538160822217373044
+qmul:60947370495538663/3595354440833372,20498068986391916397/59798876860276456,=1:73488435585690517250320078551597483/12646950439790760312580408864096
+qmul:57111050113208289287/8750146592672703,95339879919848747558/9349828098304853,63474468255902925315/5956909304899564:5444960659889742520776395286830698811146/81812366476457707866224945527659
+qmul:31476714111665882746/1411948296801679,=1,91546635306734179873/2545140299680338:990783531267546121976022657443420500516/1993597992841162212620657219041
+qmul:28478043672580107559/271169292774531,=1,-12639098468391030777/83575724512750:810998971417379900383655158076008938481/73532785343839310404002269961
+qmul:97963124075098523020/223158531052969,=1,=2:9596773678553147851290017119785469920400/49799729981718929459883714961
+qmul:38023234767709122291/95410827766256,=1,-80027616607132061503/68758430907707:1445766382200323790987914636817593088681/9103226055042166894572257536
+qmul:-6852061478866431364/19230239212017,31234498342946092331/39453881908226,=1:-107010351453709150647505423887409134742/379353793468927863275175921
+qmul:33119990811859699401/1776514189342,65254455762623773903/8901520474749,11459125607986399870/8150100596607:720408991763668201816403420648589510701/5271225810036644905308386
+qmul:27841303391142022233/8340519171100,=1,61584898160284417471/4425828128209:775138174517616267035460754520666306289/69564260043486631075210000
+qmul:-78679695834397046203/681862256264,22320479732932316543/573216980545,=1:-1756168556264938480239345612201392236229/390855023683251092383880
+qmul:25675370768619544394/174778199339,=1,-39853005701576084539/982343364060:659224664106082973870755584440136827236/30547418964183220036921
+qmul:-24756905032793568159/99453729989,14882817849764444595/70923843844,10502311373057494209/91914989726:-52636072589569046967201515845844521515/1007662973634739405388
+qmul:95117421914973587797/80826708744,-23193036682039936606/20563195751,-4893123371481302110/94686383639:-1103030927787525886919861317615127598491/831027716905967673372
+qmul:-80983109490183607947/8058699274,-15405016985195778462/2629510637,2177028333237582055/2780215797:623773088605123959908040865328237318757/10595217730683588769
+qmul:42899406282841568991/1560723895,-22471941706408087493/1005041792,22818416959151070688/2105105663:-964032957227532597560482503451723729563/1568592740248019840
+qmul:-10792553451566883852/995956003,86483521167692451511/50100662,91257203536302258983/95707725:-466689012441018414437879124662439450186/24949027536586993
+qmul:66678150407960284786/528696663,496074447844907103/89728426,17869991738879780164/44060669:5512887774491427594627575949932372493/7906519900407073
+qmul:96591001707842941940/16266781,=1,26004126355523142571/17591389:9329821610924518126580594334274210963600/264608164101961
+qmul:-19258452690165788842/64571275,55666814298088453153/92756359,54411077014502701176/23247995:-1072056709571980969162640959031807118826/5989396364987725
+qmul:-4640013132163513704/239663,-52209871104438592227/332773,=2:242254487553159440830522450019582378808/79753375499
+qmul:-56411630621727285797/272706,15691212266654685658/1914927,15271170464235431859/4561235:-442583435196820139258606231600281499713/261106041231
+qmul:62583023330306722367/644511,42379004056489714974/217085,=2:884068733194153019519400490169326874486/46637890145
+qmul:53067206328944584675/275618,=1,37102608540172266636/214843:2816128387558776183269875887008244855625/75965281924
+qmul:50636929045250773605/38387,30182307121185668404/29215,16057737093809242633/17297:305667868823489166641648659224001135284/224295241
+qmul:-26760988055984279099/53119,44684512572473420625/89488,=2:-108709246112676414811336722275383910625/432137552
+qmul:-17331655588145624486/2353,24408931125891445861/334,55315381482361596884/2933:-16271045674950697968739133244742498171/30227
+qmul:-9697670177570290081/926,-1158917529680599882/175,-11682447562930993064/1259:5619399982923492491507494162417185221/81025
+qmul:-24744828849467423601/305,706079506961442174/13,-12411541580915002667/54:-17471816553877228863576699595124348574/3965
+qmul:74993389160967099973/124,-20280570219362183984/677,28316389090053904551/13:-380227173716737042352800246412036858108/20987
+qmul:43291079967737078989/47,-41261412311052788301/4,81583584176718755579/67:-1786251099939557456367856008793532107689/188
+qmul:-63431471455230924013/94,=1,69816003657973600474/97:4023551570975775516902820423729780024169/8836
+qmul:10484919345725066249/3,=1,-37631393326791641801/9:109933533686359751306619094875438930001/9
+qmul:76285024187842291525,15471681970508023553/4,14287488305535091904/5:1180257633346808064019424884594192288325/4
diff --git a/polly/lib/External/isl/imath/tests/qmulz.t b/polly/lib/External/isl/imath/tests/qmulz.t
new file mode 100644
index 00000000000..233b1258c39
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qmulz.t
@@ -0,0 +1,800 @@
+qmulz:4/21116887005095188595,0,1/17609283250378275381:0
+qmulz:8/84271584737450207059,1,=1:8/84271584737450207059
+qmulz:-5/7724990270619098661,3,-1/8550465692384773913:-5/2574996756873032887
+qmulz:2/8610596429506001887,7,=1:14/8610596429506001887
+qmulz:0,0,-1/273384650324881125:0
+qmulz:1/140233715878844976,0,0:0
+qmulz:0,4,=1:0
+qmulz:-9/45090872528594267,8,=1:-72/45090872528594267
+qmulz:1/8811965128522223,2,2/1793564191974955:2/8811965128522223
+qmulz:-1/3188926048219934,8,-1/5467596237009668:-4/1594463024109967
+qmulz:6/640657208066881,5,1/137611762075086:30/640657208066881
+qmulz:3/82322597857883,-7,7/654813178322036:-21/82322597857883
+qmulz:2/3688100583837,-5,2/10618253469093:-10/3688100583837
+qmulz:-7/83059280440216,9,1/11745563556453:-63/83059280440216
+qmulz:9/6593641787929,5,=1:45/6593641787929
+qmulz:3/6450530990042,8,-3/716358093439:12/3225265495021
+qmulz:-9/518988418619,-6,7/365408602532:54/518988418619
+qmulz:-1/122175964907,-8,2/24455846617:8/122175964907
+qmulz:3/5927038874,3,-8/86686893619:9/5927038874
+qmulz:1/7836708131,5,=1:5/7836708131
+qmulz:5/498008886,-4,2/1679653213:-10/249004443
+qmulz:1/7271098513,6,0:6/7271098513
+qmulz:6/363428537,-7,2/874745017:-42/363428537
+qmulz:5/766453791,-5,=1:-25/766453791
+qmulz:-4/90120677,4,=1:-16/90120677
+qmulz:2/53848349,-1,9/89746135:-2/53848349
+qmulz:-1/58093,9,7/9595979:-9/58093
+qmulz:9/2605786,-7,-5/2800212:-63/2605786
+qmulz:-7/355662,7,-1/161621:-49/355662
+qmulz:-1/55532,-8,3/126767:2/13883
+qmulz:7/6254,8,=1:28/3127
+qmulz:7/22045,2,=1:14/22045
+qmulz:0,2,2/2115:0
+qmulz:-6/3715,8,-4/2861:-48/3715
+qmulz:1/93,5,1/5:5/93
+qmulz:2/267,5,8/311:10/267
+qmulz:1/11,4,3:4/11
+qmulz:7/89,4,0:28/89
+qmulz:1,-1,0:-1
+qmulz:1/2,2,-3/4:1
+qmulz:40/4765370066151782869,-24,3/17739079731156497618:-960/4765370066151782869
+qmulz:10/7947188161398728933,31,-29/17781982876586594643:310/7947188161398728933
+qmulz:8/970140630929619417,53,13/8387936313655403107:424/970140630929619417
+qmulz:3/1360678434809756573,41,-31/7551541168373851760:123/1360678434809756573
+qmulz:86/511769393768474807,-69,-1/14040574288485846:-5934/511769393768474807
+qmulz:56/95496257521849925,9,4/211197580286155545:504/95496257521849925
+qmulz:3/12596246629196159,46,37/18952775459563721:138/12596246629196159
+qmulz:77/94995682269709624,37,=1:2849/94995682269709624
+qmulz:13/113349891854596,-40,60/1320165562768511:-130/28337472963649
+qmulz:-41/8305688624807961,27,-89/2632217443748796:-123/922854291645329
+qmulz:50/294091273453599,83,31/297861651301595:4150/294091273453599
+qmulz:27/300155905937375,-31,=1:-27/9682448578625
+qmulz:-31/21736762942232,-27,80/61942176807321:837/21736762942232
+qmulz:59/71835777121419,67,=1:3953/71835777121419
+qmulz:9/1200430381838,-23,19/83497011269:-207/1200430381838
+qmulz:56/4578602367429,97,-20/776186296021:5432/4578602367429
+qmulz:31/25481124930,-86,=1:-1333/12740562465
+qmulz:45/421348839203,-96,89/480034443271:-4320/421348839203
+qmulz:43/18027020463,18,50/87497424067:258/6009006821
+qmulz:-23/3151206468,59,57/92709199715:-1357/3151206468
+qmulz:-33/718223267,-66,-76/2839068079:2178/718223267
+qmulz:98/8237370817,72,79/3563183593:7056/8237370817
+qmulz:37/508616845,22,72/569831387:74/46237895
+qmulz:41/364836167,-39,17/275414470:-1599/364836167
+qmulz:61/59566303,79,-1/1125330:4819/59566303
+qmulz:-97/83330456,63,73/93898689:-6111/83330456
+qmulz:-1/164718,22,-65/5152738:-11/82359
+qmulz:0,24,1/452605:0
+qmulz:-1/74711,-40,56/389891:40/74711
+qmulz:49/301825,39,54/550045:1911/301825
+qmulz:1/29,75,-29/23058:75/29
+qmulz:29/24685,14,=1:406/24685
+qmulz:8/4141,88,-12/2819:704/4141
+qmulz:26/3215,-38,11/500:-988/3215
+qmulz:-1/11,11,1/2:-1
+qmulz:58/779,41,-35/237:58/19
+qmulz:43/87,-51,=1:-731/29
+qmulz:-93/46,10,4/85:-465/23
+qmulz:76/3,36,0:912
+qmulz:73/4,-77,=1:-5621/4
+qmulz:432/74155281191151829175,472,=1:203904/74155281191151829175
+qmulz:43/114735919860201111,635,=1:27305/114735919860201111
+qmulz:301/3325247703900970462,388,=1:58394/1662623851950485231
+qmulz:47/344661002338469478,-106,860/1407842422947199591:-2491/172330501169234739
+qmulz:805/331439221582368712,128,=1:12880/41429902697796089
+qmulz:2/38222077254594263,-769,366/33431432349396613:-1538/38222077254594263
+qmulz:262/61689298838409327,985,63/11550912720533723:258070/61689298838409327
+qmulz:29/21271356349676377,424,920/27960990422138801:232/401346346220309
+qmulz:205/2415752549117554,210,=1:21525/1207876274558777
+qmulz:634/9928964068012837,847,95/1012378898508494:536998/9928964068012837
+qmulz:760/992730779954457,-482,=1:-366320/992730779954457
+qmulz:13/176143690239813,-422,349/7765280463032:-5486/176143690239813
+qmulz:-408/41555001527117,-384,-66/88241293613239:156672/41555001527117
+qmulz:27/282651453443,321,23/49707873373983:8667/282651453443
+qmulz:337/906250195499,80,-199/1511077632489:26960/906250195499
+qmulz:149/1870083861838,-448,281/4154228004961:-33376/935041930919
+qmulz:662/109646911569,763,126/297204337159:505106/109646911569
+qmulz:-887/964555633809,146,-947/9332491491:-129502/964555633809
+qmulz:188/73532880181,760,163/15869550943:142880/73532880181
+qmulz:-221/8950730813,505,=1:-111605/8950730813
+qmulz:22/13208815,793,=1:17446/13208815
+qmulz:193/637058385,-354,482/2363181035:-22774/212352795
+qmulz:921/151700978,356,-124/176851221:163938/75850489
+qmulz:-304/528635925,-222,259/831832289:22496/176211975
+qmulz:-4/3008665,170,37/7388125:-136/601733
+qmulz:52/12087973,-255,-249/6720565:-13260/12087973
+qmulz:-91/601229,444,125/4420518:-40404/601229
+qmulz:224/1546297,-262,-392/1085417:-58688/1546297
+qmulz:-184/301489,348,643/741106:-64032/301489
+qmulz:245/409686,380,356/35003:46550/204843
+qmulz:31/27883,-943,151/26608:-29233/27883
+qmulz:53/4847,612,=1:32436/4847
+qmulz:-105/3832,445,249/1553:-46725/3832
+qmulz:-930/539,770,=1:-9300/7
+qmulz:951/374,362,106/887:172131/187
+qmulz:-963/277,320,383/272:-308160/277
+qmulz:487/53,717,11/2:349179/53
+qmulz:104/5,428,263/20:44512/5
+qmulz:728/5,676,=1:492128/5
+qmulz:-100,626,218/3:-62600
+qmulz:8051/79574306408456131157,752,-197/7460413732106301606:6054352/79574306408456131157
+qmulz:-3008/38400803020121033225,9712,=1:-29213696/38400803020121033225
+qmulz:119/587342139200366012,-7227,=1:-860013/587342139200366012
+qmulz:3185/2510393047749702379,3840,-1461/382245232883802373:12230400/2510393047749702379
+qmulz:-8497/801072423164046277,7259,-2828/415904520883959335:-61679723/801072423164046277
+qmulz:2322/194611268129140181,600,-887/21344410544427618:1393200/194611268129140181
+qmulz:311/62962162974221664,-8282,579/2914497438443599:-1287851/31481081487110832
+qmulz:5073/93332615871851278,6836,=1:17339514/46666307935925639
+qmulz:2466/5537476809280789,8950,48/94598016177721:22070700/5537476809280789
+qmulz:231/1712288358365785,70,-6151/1963648192541132:3234/342457671673157
+qmulz:3639/430934070927460,5689,7044/387572482090793:20702271/430934070927460
+qmulz:1017/411489477643922,6940,7618/907239626952957:3528990/205744738821961
+qmulz:9453/75593644627417,-2623,-2593/2251196683387:-24795219/75593644627417
+qmulz:216/48287649084937,1544,=1:333504/48287649084937
+qmulz:-9415/2492316493411,3873,8599/637176704155:-36464295/2492316493411
+qmulz:4082/7751065050029,-283,128/8321097090765:-1155206/7751065050029
+qmulz:-487/249512316942,-9582,9041/750949778159:777739/41585386157
+qmulz:649/133850377085,-5935,=1:-770363/26770075417
+qmulz:6342/41044749355,-8924,-9491/43668795550:-56596008/41044749355
+qmulz:7139/68729276289,6836,-9917/81477149162:48802204/68729276289
+qmulz:143/2037944234,2833,4555/3599790156:405119/2037944234
+qmulz:-9325/7317954198,-9218,5503/6043847166:42978925/3658977099
+qmulz:7044/653529617,7307,4797/199351315:51470508/653529617
+qmulz:-673/115994640,-7148,559/911781164:1202651/28998660
+qmulz:3076/13783363,-9612,-2927/62873576:-29566512/13783363
+qmulz:-4161/34536929,3313,98/1321839:-13785393/34536929
+qmulz:738/526535,-118,=1:-87084/526535
+qmulz:2233/2825257,7157,765/8600573:15981581/2825257
+qmulz:107/83440,3370,401/179110:36059/8344
+qmulz:-1667/14564,-6138,913/586918:465093/662
+qmulz:-7994/44789,404,=1:-3229576/44789
+qmulz:-5363/98880,145,=1:-155527/19776
+qmulz:842/29,-8855,8672/6371:-7455910/29
+qmulz:2310/1103,2603,=1:6012930/1103
+qmulz:762/293,2709,=1:2064258/293
+qmulz:5789/529,7420,-6538/957:42954380/529
+qmulz:539/41,3855,-7655/53:2077845/41
+qmulz:-579/13,7973,=1:-4616367/13
+qmulz:883,5006,1627:4420298
+qmulz:3573/2,3540,4139/9:6324210
+qmulz:98250/53192196970205269513,57716,80717/96027247156109827970:5670597000/53192196970205269513
+qmulz:-6945/12166748375847716977,80289,23625/38713117494337198876:-557607105/12166748375847716977
+qmulz:-58986/296440433764715149,-18018,-97378/3396272899236095159:11679228/3257587184227639
+qmulz:-6149/262153684309837118,56309,89961/7445277782705094481:-346244041/262153684309837118
+qmulz:-15446/149480531273251391,31846,4749/106265662702068574:-491893316/149480531273251391
+qmulz:2451/55473133472349607,90444,20837/279735266283810098:221678244/55473133472349607
+qmulz:28710/35478143894265917,69724,=1:2001776040/35478143894265917
+qmulz:96358/34167706730231777,49135,-2041/69865271163769782:4734550330/34167706730231777
+qmulz:7283/1176116854930460,77815,62454/5465876769829379:113345329/235223370986092
+qmulz:99551/5426188854503002,-89899,=1:-8949535349/5426188854503002
+qmulz:7860/83586510191743,23843,-4213/144664072126997:187405980/83586510191743
+qmulz:-3898/13601562574049,-61855,4031/27837453043985:241110790/13601562574049
+qmulz:-6928/5371829731249,37664,4835/26749096759358:-260936192/5371829731249
+qmulz:76651/81457027187160,-85014,=1:-1086068019/13576171197860
+qmulz:14709/484402153529,30047,10715/9214198729207:441961323/484402153529
+qmulz:30365/5730836776783,61734,30655/2550068903118:1874552910/5730836776783
+qmulz:13241/55328034593,-80183,11617/428864198314:-1061703103/55328034593
+qmulz:35410/387788826057,45514,15158/46042980249:1611650740/387788826057
+qmulz:-41739/96062733370,-76701,=1:3201423039/96062733370
+qmulz:71383/88228655146,74491,74665/42443189917:5317391053/88228655146
+qmulz:-3181/8533129823,78945,19451/1917063317:-251124045/8533129823
+qmulz:-35563/2781995353,34546,99624/7403972285:-1228559398/2781995353
+qmulz:-46639/190543771,20318,=1:-947611202/190543771
+qmulz:57710/227557263,65393,41129/661804772:3773830030/227557263
+qmulz:-41473/34008654,19343,68754/48463157:-802212239/34008654
+qmulz:86172/41261945,23098,-67843/42705974:1990400856/41261945
+qmulz:-23642/477003,-74773,75259/5922193:1767783266/477003
+qmulz:-2299/7593,-55092,47078/3719425:42218836/2531
+qmulz:89923/436747,27372,38454/602545:2461372356/436747
+qmulz:35133/245788,37530,-26959/814296:659270745/122894
+qmulz:54300/83317,6506,=1:353275800/83317
+qmulz:-2710/16637,92724,49071/5768:-251282040/16637
+qmulz:-23308/1133,56278,=1:-1311727624/1133
+qmulz:12925/464,48445,5188/4977:626151625/464
+qmulz:-15500/139,75561,45107/89:-1171195500/139
+qmulz:68128/739,-47269,46324/271:-3220342432/739
+qmulz:-98213/47,41522,-7190:-4078000186/47
+qmulz:95819/64,12916,907/10:309399551/16
+qmulz:-1123,10413,63874/9:-11693799
+qmulz:30369/4,-41524,7423/2:-315260589
+qmulz:-269467/4029498660068277497,646984,265727/52332437650027766625:-174340837528/4029498660068277497
+qmulz:-206269/81809654998485085274,50405,=1:-10396988945/81809654998485085274
+qmulz:119347/1701867915016265609,618013,703201/8136517399464628384:73757997511/1701867915016265609
+qmulz:199044/306712361923985717,233710,201675/571526199709385944:46518573240/306712361923985717
+qmulz:267977/894840013682442654,-489375,=1:-43713748125/298280004560814218
+qmulz:12471/7140902397278600,350289,253704/144540771450708869:4368454119/7140902397278600
+qmulz:832882/5818152789924367,-80256,108955/22849940119123234:-66843777792/5818152789924367
+qmulz:494497/18234011706116519,-14822,68902/17499952371352627:-7329434534/18234011706116519
+qmulz:232520/1052550357505571,557021,32429/440602163340406:129518522920/1052550357505571
+qmulz:526093/2240655675408643,11119,-126354/4970690629417277:5849628067/2240655675408643
+qmulz:54605/174895846259434,-184199,544176/97043233594967:-10058186395/174895846259434
+qmulz:764692/11187705426133,576048,-646413/892215624306868:440499297216/11187705426133
+qmulz:593840/66545119469401,569003,81868/70640307758063:337896741520/66545119469401
+qmulz:109999/9745609238872,665854,=1:36621637073/4872804619436
+qmulz:-133443/8282237150,-495649,404461/485555508119:6012808137/752930650
+qmulz:224276/6824310584317,712269,=1:159744842244/6824310584317
+qmulz:787126/341737321975,925666,71517/134877228043:104087967988/48819617425
+qmulz:19969/20124955446,-804254,68212/739707535809:-8030074063/10062477723
+qmulz:-484342/14331066017,154663,640199/41001808194:-74909786746/14331066017
+qmulz:234567/15529177385,951383,104501/13280956901:223163056161/15529177385
+qmulz:447401/2005170496,-162639,25513/657762574:-72764851239/2005170496
+qmulz:88392/370535737,889107,=1:78589945944/370535737
+qmulz:69608/19589055,197889,391089/111921502:4591552504/6529685
+qmulz:-742188/976205903,-835265,198303/463857278:619923659820/976205903
+qmulz:30951/7100042,826901,37665/16004119:25593412851/7100042
+qmulz:-8717/23405419,749796,584744/90701721:-6535971732/23405419
+qmulz:375053/1615401,682230,-413113/4604306:85290802730/538467
+qmulz:-682135/9626652,-686085,=1:156000863825/3208884
+qmulz:459639/139961,-545993,55641/809527:-250959676527/139961
+qmulz:137069/131640,556346,=1:38128894937/65820
+qmulz:653137/44831,-33774,=1:-22059049038/44831
+qmulz:377111/93851,119783,=1:45171486913/93851
+qmulz:61290/967,223671,-198269/2596:13708795590/967
+qmulz:108931/3561,890354,99191/837:96987151574/3561
+qmulz:-566567/566,72845,=1:-41271573115/566
+qmulz:-856110/823,-344105,71629/306:294591731550/823
+qmulz:103589/16,-597818,73435/68:-30963684401/8
+qmulz:531370/87,698278,92947/30:371043980860/87
+qmulz:93564,802315,-69936:75067800660
+qmulz:254421/2,-51596,=1:-6563552958
+qmulz:5908447/27508951891576930555,-8046857,=1:-47544428101079/27508951891576930555
+qmulz:3067750/30055512795875714167,9308933,292151/5218560370048727971:28557479210750/30055512795875714167
+qmulz:5909595/1610510865059257451,1081732,8279906/1034011738653690921:6392598018540/1610510865059257451
+qmulz:7300703/4024857129457733561,-6809974,=1:-49717597611722/4024857129457733561
+qmulz:-411181/366261858643871279,-3873525,5670428/945102376345780573:1592719883025/366261858643871279
+qmulz:1840028/328098015717866549,7760,-1208094/324612123643160461:14278617280/328098015717866549
+qmulz:5902528/35455662246885099,9372866,-2383248/38025857091093589:55323604005248/35455662246885099
+qmulz:412808/8383418920359061,7136425,8412475/90427613237122747:2945973331400/8383418920359061
+qmulz:4721348/1016481387773127,-4909375,446916/600970820960263:-23178867837500/1016481387773127
+qmulz:346575/543489633400996,2082315,=1:721678321125/543489633400996
+qmulz:-54603/142207419353230,9721544,-9944420/520274639700813:-37916104788/10157672810945
+qmulz:9128453/94269601342538,-1680681,9401887/439581199104749:-15342017516493/94269601342538
+qmulz:327135/14576866729679,-981216,=1:-320990096160/14576866729679
+qmulz:-2772009/35771247225944,7269361,3999881/49166513232805:-20150734116249/35771247225944
+qmulz:7777936/4972983657531,932701,-1921805/2675875584873:7254488685136/4972983657531
+qmulz:-4107413/8839115797940,-7894930,-67679/4109002145737:3242773811609/883911579794
+qmulz:6418119/522734321117,-4364508,=1:-28011931720452/522734321117
+qmulz:-9554439/610908255599,9002767,5125943/687195405407:-86016388132713/610908255599
+qmulz:1541453/67134868472,9336624,124122/1242309641:1798995884334/8391858559
+qmulz:-4420171/60924329483,4658729,597333/76303665689:-20592378822659/60924329483
+qmulz:2321560/479530207,3712372,-8303185/3259591614:8618494340320/479530207
+qmulz:6497537/8003497458,685910,622458/2979408511:2228362801835/4001748729
+qmulz:8707355/324035343,-5890611,=1:-17097213714635/108011781
+qmulz:-6368331/430504267,6080736,2843024/389993407:-38724139571616/430504267
+qmulz:7148576/43643579,9752788,1882739/80695462:69718546229888/43643579
+qmulz:-78515/22600098,-9269764,=1:363907760230/11300049
+qmulz:6642519/3513320,6950670,4303599/4263095:4616995753773/351332
+qmulz:8291036/3791843,-6165764,187574/1468847:-4647324662864/344713
+qmulz:3378069/104710,4099164,-3130847/477201:6923629417158/52355
+qmulz:-1837947/540683,-7963396,4977946/317377:14636299788012/540683
+qmulz:-2439283/46175,3316377,4423369/90864:-8089582037691/46175
+qmulz:24851/4671,-9457747,=1:-235034470697/4671
+qmulz:-3996265/3851,5644784,2130071/6485:-22558052731760/3851
+qmulz:-8787752/5255,-8904351,=1:78249228308952/5255
+qmulz:1051819/121,7786465,-1689328/223:8189951829835/121
+qmulz:2910419/264,-4517287,4103/10:-13147197913253/264
+qmulz:1470867/8,9831206,3981716/39:7230198237801/4
+qmulz:4240055/91,-8952034,=1:-417111170570
+qmulz:327409/4,1172921,-3686633/6:384024891689/4
+qmulz:463486,9343153,-1978362/7:4330420611358
+qmulz:29585813/42067907033671980893,71292790,-70324603/70286665753964458740:2109255153188270/42067907033671980893
+qmulz:-65065601/40632930795671537185,4699856,7303041/5446641871295709464:-305798955253456/40632930795671537185
+qmulz:22287116/6961884952768846975,-61223561,47414597/4915453243825873928:-194928086562868/994554993252692425
+qmulz:13726613/4388684468226482322,5689324,=1:39047574389806/2194342234113241161
+qmulz:86674641/912048412696230206,9154212,418913/1017052367067494:396719019368946/456024206348115103
+qmulz:39606657/62493216618497137,-64895609,-93307621/528183512506792540:-2570298126469113/62493216618497137
+qmulz:-61860905/97141961244876374,29603964,95495204/34743879357106645:-915664002313710/48570980622438187
+qmulz:23026739/8268491868362646,49125662,=1:565601898538109/4134245934181323
+qmulz:74731767/2153002560742688,79046765,=1:5907304424083755/2153002560742688
+qmulz:-33040734/8080107924352231,16695468,87206576/5598768033775299:-551630517193512/8080107924352231
+qmulz:-85831719/652429006985885,-12207796,-56798629/203624822018813:1047816115881324/652429006985885
+qmulz:13811539/218314616664013,-33361377,41774225/444858687471486:-460771959529203/218314616664013
+qmulz:46578727/4151263590571,94131401,=1:4384520829306527/4151263590571
+qmulz:5864747/4619802266479,-14340682,9374233/85220400863050:-84104471737454/4619802266479
+qmulz:-20695/10292597787,19239092,=1:-398153008940/10292597787
+qmulz:-79354991/1226479246337,-85100492,-31036795/9391557241804:6753148776755572/1226479246337
+qmulz:13497139/220655551780,25874045,16158669/209860028875:69845116371451/44131110356
+qmulz:-14641436/673965441365,35697635,=1:-104532927640772/134793088273
+qmulz:42076810/47634122699,92555216,-99965382/7603386991:3894428238140960/47634122699
+qmulz:-2547044/961062465,-61423853,-64578371/3954121219:156449256240532/961062465
+qmulz:12398632/375040743,76607359,19460171/1399871191:949826452732888/375040743
+qmulz:99063929/927095607,-33074282,-31824927/5567689051:-3276468323773978/927095607
+qmulz:13710043/915838933,-63538218,-80907032/55218445:-871111700923374/915838933
+qmulz:-14266908/173792753,79812889,39774414/947866123:-1138683144577212/173792753
+qmulz:46031321/23827793,47288874,-29016530/26535747:94642145166198/1035991
+qmulz:90667631/37118866,68275195,25790129/31607133:6190350186713045/37118866
+qmulz:133784/168291,-36246595,-13384939/1286209:-4849214465480/168291
+qmulz:20243420/9836407,-29971865,=1:-86676150196900/1405201
+qmulz:55262636/961595,-79684445,-18606712/267721:-880714495779404/192319
+qmulz:18521596/447339,13342158,98234108/465429:82372686748056/149113
+qmulz:-52333722/83537,75454299,80265841/5748:-3948804307570878/83537
+qmulz:27849895/19463,2814646,51492641/14404:78387595562170/19463
+qmulz:2229413/2657,47131782,=1:105076207503966/2657
+qmulz:37693829/4546,76862997,85444575/4597:2897260665345513/4546
+qmulz:47895391/838,51616823,67901608/79:2472207919762793/838
+qmulz:94793222/407,45108781,26019479/298:4276006691482382/407
+qmulz:-28219652,28509688,-69052146/5:-804533473988576
+qmulz:89329658/41,24254853,43325377/63:2166677723330274/41
+qmulz:-28028843/2,57869496,97143787/2:-811007508936564
+qmulz:17180663,49123793,31747639/3:843979332814759
+qmulz:-440812167/25592398472985127969,-67895040,305636107/90241943612023813864:29928959710951680/25592398472985127969
+qmulz:469436899/89801410067219467595,339956414,=1:159588084783320186/89801410067219467595
+qmulz:624505646/8457866426911473529,55679196,735790506/1487411086627672243:34771972266740616/8457866426911473529
+qmulz:-530285107/6030437060176995577,933495870,999692847/7638706602391224839:-495018957307008090/6030437060176995577
+qmulz:811800624/481147127809268303,96179572,377106279/130131554630880295:78078636565652928/481147127809268303
+qmulz:-249975856/304587360170486515,826091985,851744230/630784049926628227:-41300610217022832/60917472034097303
+qmulz:-268512055/31691499965821404,202698168,125655067/11939065745546055:-4535575136201270/2640958330485117
+qmulz:52009618/27516701583858369,702923265,-368845548/80831610779378597:12186256831987590/9172233861286123
+qmulz:375702102/3296151167632583,-434951925,-521756507/7691136311577133:-163412352491446350/3296151167632583
+qmulz:-384209743/6191488089335748,227570856,78931552/6926107452102541:-7286245008170834/515957340777979
+qmulz:113980250/183755547250927,437813246,556573714/9774511713479:49902063232391500/183755547250927
+qmulz:-472996853/423024426303975,-368827764,986763127/429084644953681:58151457223675564/141008142101325
+qmulz:-23658043/2283802118115,740396103,17376279/1797109931431:-5838774280602143/761267372705
+qmulz:4078811/40918803323,-845485209,=1:-3448574370806499/40918803323
+qmulz:154841851/4593031526275,12617826,-972933704/2547790338703:1953767533435926/4593031526275
+qmulz:735542560/7626156428987,778206922,-293104268/2631653460189:572404311617600320/7626156428987
+qmulz:-457656798/567001008887,493454600,-366343915/981801223003:-225832852194370800/567001008887
+qmulz:-945200662/928772265773,975297818,34885945/9938748237:-83804740292795956/84433842343
+qmulz:104875267/28207551782,954147586,=1:50033241419577731/14103775891
+qmulz:609918635/17074425662,-224065632,-400611797/35807663040:-9761557458560880/1219601833
+qmulz:-864006772/2174255357,384303177,=1:-332040547429114644/2174255357
+qmulz:-109536551/482079758,63549943,-10441546/8480554803:-6961041572466593/482079758
+qmulz:512697337/200332783,429480437,6412690/26797243:220193476343496269/200332783
+qmulz:-789241399/555269030,318371906,755945889/20176822:-125636144246868247/277634515
+qmulz:-462528503/5399724,117919312,195760496/23231881:-13635260713537484/1349931
+qmulz:-768369531/84617918,630525111,869606481/10643699:-484476283822792941/84617918
+qmulz:881987483/8541727,899430760,=1:793286672145177080/8541727
+qmulz:435026027/9075006,667517326,-976648275/5125397:145193705141721901/4537503
+qmulz:-382388178/685121,90758124,-658289938/398425:-34704833675058072/685121
+qmulz:215727059/244359,-726765650,401344067/859586:-156783016256723350/244359
+qmulz:300168110/44829,-382517050,-848645422/63521:-114819419941275500/44829
+qmulz:240997441/17745,-160000865,=1:-7711959804557293/3549
+qmulz:497024455/1871,-967339431,891801689/2782:-480791353492785105/1871
+qmulz:159802693/5520,17435365,=1:557243656087589/1104
+qmulz:-503495399/548,350245727,=1:-176347112063910073/548
+qmulz:-10883201/487,215755629,756773575/299:-2348111877288429/487
+qmulz:366108695/3,980458645,-27946686:358954435022418275/3
+qmulz:890190708/5,-785135991,-213354065/14:-698920763704571628/5
+qmulz:10221149,961494206,348141954:9827575542162694
+qmulz:-44158489/8,918744696,-871474083/8:-5071297194015543
+qmulz:-2894598477/3168041449931268761,-3793825512,=1:10981601549038945224/3168041449931268761
+qmulz:-165305510/4444729020519250969,9650534485,2185861399/5133889833495479703:-1595286524815512350/4444729020519250969
+qmulz:-6642522053/7993901796893679282,2810456878,=1:-252277321501628791/108025699958022693
+qmulz:4075114142/2324601722262376857,7319061324,224603716/1867619918809913859:9942003435865881336/774867240754125619
+qmulz:174975715/284043772444194,6235601626,2532940399/455179300056502113:545539426482256295/142021886222097
+qmulz:9511153214/515183582083251763,8998409775,1916260097/49971689447357059:85585254052380266850/515183582083251763
+qmulz:9561479651/87091900188234189,-9070226563,-31724150/149115720086953:-86724786712084169513/87091900188234189
+qmulz:257684521/4786959313773388,7785131961,6853032479/92097657977675380:2006108000292075681/4786959313773388
+qmulz:-4787662186/3232352240839707,-4724762630,=1:22620567381476909180/3232352240839707
+qmulz:4815469783/4351554535472742,-3809867113,7127662378/9454193567725933:-1411253843068995883/334734964267134
+qmulz:-3134766359/276266993500284,-5054392552,-1084728996/261757765208747:3961084934297439542/69066748375071
+qmulz:887520891/240452975602433,8724686676,990724100/235457211073037:7743341692379348316/240452975602433
+qmulz:7273936918/90562759963967,3897937854,=1:1667844356487076116/5327221174351
+qmulz:-119387249/2501098635936,9536603772,7558585050/14605366326499:-94879074095175269/208424886328
+qmulz:1526390275/2230210659804,4788548573,9380637171/7768045927396:7309193973192327575/2230210659804
+qmulz:3728595181/1876804971571,9224083630,=1:34392873771958987030/1876804971571
+qmulz:4093958623/457077991802,1483219640,9490772153/415966894045:3036119917490477860/228538995901
+qmulz:2144803614/309751929683,2542484861,3609691879/286244057812:779018674059012522/44250275669
+qmulz:3560518143/86265554695,4399548470,-9491920365/12079543438:3132934429688578242/17253110939
+qmulz:-2249859505/6734537978,1110886234,=1:-1249668976269277085/3367268989
+qmulz:3262790941/1025060151,5749937770,122130955/253972334:18760844867269741570/1025060151
+qmulz:-4710833503/6631683846,-3411512444,=1:8035533558548305666/3315841923
+qmulz:-9032027690/956483333,9063301527,=1:-81859990354683282630/956483333
+qmulz:-266187969/112068472,6338182319,-7905751808/945700693:-1687147878646320111/112068472
+qmulz:4156902964/946699,6705660672,=1:27874780723015031808/946699
+qmulz:2651274071/91222015,-5032057829,-2464896493/13519125:-13341364445800251859/91222015
+qmulz:318661412/1743,370464187,-232620732/1501523:118052640924852044/1743
+qmulz:899914724/512321,5465209352,=1:4918222365607298848/512321
+qmulz:3131360803/353764,-2320875649,=1:-7267499035915786147/353764
+qmulz:6443807425/863022,84008208,110674088/12311:90222119078557400/143837
+qmulz:-3068580532/73491,8795547050,=1:-26989844445920030600/73491
+qmulz:696531051/11483,376305292,=1:262108320533621892/11483
+qmulz:9419114609/574,7568524581,1555156138/2439:71288800449472703829/574
+qmulz:6076760418/5639,3137249772,1485476093/6609:19064315235869124696/5639
+qmulz:3390029532/479,4688058595,=1:15892657084796427540/479
+qmulz:1638519591/92,3009448307,2877648480/173:4931040009121282437/92
+qmulz:516117057/8,8303497266,-9173174800/47:2142788285867733081/4
+qmulz:927642007/6,-2879248175,-3421337621/43:-2670911555708087225/6
+qmulz:2611149335/3,7293202790,1060208041/2:19043641615128644650/3
+qmulz:-4787695612/3,-5387504428,-8004477624:25793731309566169936/3
+qmulz:1237812305/631690268983111653,77842709902,51259842584/29388862631694313447:96354664171240944110/631690268983111653
+qmulz:5976818503/79879634485079515072,-2490419914,82254088463/65538055479070681595:-7442393911117434371/39939817242539757536
+qmulz:-17969301863/1215487409718772165,14907617468,39498072491/8401888749150831870:-267879478340623742884/1215487409718772165
+qmulz:62921948190/5765043819856032331,-39453740869,-1868833945/7119552876031525503:-2482506238860903577110/5765043819856032331
+qmulz:-15610313710/78152311777353923,92919343081,-49673392741/841288090131527967:-1450500095221527940510/78152311777353923
+qmulz:44648474983/288454490007214845,47861920531,11617817909/33454275945577992:2136961761466687575973/288454490007214845
+qmulz:-13826523213/28036931389675264,-88421093554,=1:611278151271612834501/14018465694837632
+qmulz:40547667371/53177876256600915,49909556335,9076503202/2880089154076223:404743217781153169057/10635575251320183
+qmulz:76668523587/5077067067443611,85512171223,-39577211701/3956684840165784:6556091916386158136901/5077067067443611
+qmulz:-80228153797/602596042922155,22421445270,24751353255/2432806998119141:-359766231894515638038/120519208584431
+qmulz:47062274633/166002450060687,86101072410,82448790716/626049533394637:1350704105318413058510/55334150020229
+qmulz:8841820465/21786582003342,53402955559,268303508/5469783598063:472179345353051714935/21786582003342
+qmulz:23713841211/21537439736900,-82708390631,-1600362701/2915831487207:-1961333642240894094141/21537439736900
+qmulz:56721050875/77459601877944,59578456497,32477270555/35734686972211:1126450887340103761625/25819867292648
+qmulz:8928356444/2663712341261,-3648881786,-28952940554/2770799359187:-32578517207427328984/2663712341261
+qmulz:18227203995/5958086852101,483256270,-90041196376/5523075085255:8808410615152798650/5958086852101
+qmulz:59211032239/570207052514,26723970763,-9542991461/881963470657:1582353894402086428357/570207052514
+qmulz:1776113132/40223369371,41111960068,44832213814/478452935141:73019492159034412976/40223369371
+qmulz:-15285833580/2156369081,34934254636,-90933367585/31370134781:-533999202607239476880/2156369081
+qmulz:91516992782/93740428151,-65378876169,-67776976360/2244262427:-5983278138453644812158/93740428151
+qmulz:72779505484/1621504307,-52125941410,5672754165/602683781:-3793700238707757692440/1621504307
+qmulz:11740145697/1515672656,87909174824,-48408939345/3034260044:129008315067100541541/189459082
+qmulz:79961831072/773650431,-41330850050,-74967019083/977759203:-3304890449760262753600/773650431
+qmulz:6884563893/49029205,40219988393,-23059747673/353633216:276897079867326893949/49029205
+qmulz:30501090798/47322791,28853148760,=1:880052510136961110480/47322791
+qmulz:-18451888579/10709259,11599135921,=1:-214025963626968546259/10709259
+qmulz:8926155052/4290885,75202195645,=1:134253291715621829708/858177
+qmulz:88656392423/4830649,47619732899,36734598432/8696993:4221793726972187424277/4830649
+qmulz:34368523182/239537,-72478917605,-71850709745/331701:-2490993359913710419110/239537
+qmulz:-7591160179/904815,-41442417941,84402195575/876773:314596032795194371439/904815
+qmulz:78012684294/13529,-92124971658,32782603063/49402:-7186916329549251739452/13529
+qmulz:-77476701398/48451,84100140997,84733570363/49436:-6515801511554267013806/48451
+qmulz:9785922698/313,99923625908,60518701590/3703:977844878839558059784/313
+qmulz:13272361617/790,77228020379,-14315026641/2773:1024998213435133392843/790
+qmulz:1977713551/2,92621074895,=1:183177954928027402145/2
+qmulz:-8125102987/193,40843068681,=1:-331854139338239250147/193
+qmulz:87788302687/10,73718602709,708527495/34:6471631008280390179083/10
+qmulz:-17073092947/16,82903130217,60258726452/11:-1415412847792085279499/16
+qmulz:-6943963154/5,67700561949,=1:-470110207678950427146/5
+qmulz:-86521942923/5,52316853740,74747686643/9:-905311166640643816404
+qmulz:-745167514955/75202612388076732241,992589631308,139312742559/34578187132141654765:-739645548931882026211140/75202612388076732241
+qmulz:27932224059/2111108032966941227,-779689866177,8856089863/3931386633265401342:-21778472038587689752443/2111108032966941227
+qmulz:140525061611/3407680707744152962,127477722944,169676929421/277484368047590363:8956907435367794151392/1703840353872076481
+qmulz:341584864563/1420632012141667135,55437156492,=1:18936493592077656192996/1420632012141667135
+qmulz:-999027740190/525162199932669211,400522397538,500019558441/907820980265694569:-400132985707868959652220/525162199932669211
+qmulz:-339453308372/462366486602163829,952918460297,-90778090002/71370169251458863:-323471323956568979706484/462366486602163829
+qmulz:-271650817828/7565295758442605,768776296466,16994985550/10329125142493:-208838709661769886195848/7565295758442605
+qmulz:225422010721/10111430949630829,746974776114,-168224996466/53086145704663327:24054936569926668959742/1444490135661547
+qmulz:349236361403/2805449982440828,193882264108,-1449692674/936603179147519:16927684114413345855881/701362495610207
+qmulz:-197651146031/4351789591405316,-808105729932,58049683298/4854765675888749:39930755908819394924973/1087947397851329
+qmulz:271384975109/452447489612746,354118404591,-732534914633/555297542185947:96102414415567326325419/452447489612746
+qmulz:88111433664/28798189724783,207968836059,-261683363229/138358019377265:18324432302591869690176/28798189724783
+qmulz:67604819101/43380824369659,884187650678,50163356115/7011438059051:59775346175424370000478/43380824369659
+qmulz:979853557479/27364774048301,185814534089,376723696931/23421481855538:182071032258409566401631/27364774048301
+qmulz:-129581462881/1185999957929,-649615443760,=1:84178119512510783072560/1185999957929
+qmulz:631378962263/4697504353981,356337990468,353616095948/3759830408947:224984310636568625709084/4697504353981
+qmulz:419208380799/252872515073,306292997739,313894879763/25683953874:128400591632237958013461/252872515073
+qmulz:59754817607/502657252480,-190176172167,111686020133/78750756618:-11363942481036514944369/502657252480
+qmulz:639847514587/81987662799,449279495706,76285885523/11877258141:95823456227461612954474/27329220933
+qmulz:699678831667/15232840363,-328557525533,412748319154/35151716111:-229884745600329961453511/15232840363
+qmulz:887054398617/2906111779,840756960767,-7837140210/882145159:745797160216227848059239/2906111779
+qmulz:-455315204427/506702237,-175722319764,101353072197/4927140688:80009043945732322395228/506702237
+qmulz:18629315637/336690086,163583642465,-428561144079/630858776:70870960663503295935/7830002
+qmulz:26610877449/497721338,494401478093,656965629789/571606768:13156457144137281224757/497721338
+qmulz:308447566844/63211619,626332529102,389974552910/53161277:193190744636760720294088/63211619
+qmulz:432089290445/43417161,381832677443,-993787713167/43836749:164985810665060426932135/43417161
+qmulz:259672928141/1911242,33898844506,477785491015/5001727:4401306106734735321673/955621
+qmulz:72860807605/947904,836184405122,132459766271/26668:30462535531947709276405/473952
+qmulz:8111715299/126471,73018318330,-966100886117/960478:592303809904713130670/126471
+qmulz:59136150795/124661,-183025911988,998950795145/902212:-10823447930714766230460/124661
+qmulz:-52072229129/344,24297646661,-819340099671/44129:-1265232624227073788269/344
+qmulz:462624622089/91900,463652425988,182901467689/69000:53624257088336635612233/22975
+qmulz:-12928412440/521,528884765734,937253218809/8798:-6837640384641931330960/521
+qmulz:27765652319/2634,-126780088278,=1:-586688642016512569447/439
+qmulz:-967104161735/274,750172960968,-709612304/49:-362747696286610257079740/137
+qmulz:66752761957/243,243055541185,151935508582/7:16224628683052114699045/243
+qmulz:751278773537/66,713221018437,659908640320/37:178609270664053141567223/22
+qmulz:-586344498928,-568318448089,521816699255/14:333230395676283284148592
+qmulz:161194888214,484546649439,184699645268:78106442990787850811946
+qmulz:793578182621/4,-808113765664,=1:-160325363376662447831336
+qmulz:561935468909/32803049500299178880,2101294187063,-3358814917919/26371576797557955745:1180791734323002866524267/32803049500299178880
+qmulz:-5868873358301/6442991402115355335,2339686618745,-1536954575653/43556673213605193423:-88589190087263739148079/41567686465260357
+qmulz:-7979894125724/9674261753856826205,-1852913383532,3286095553311/7067777496639467900:14786052624722387839177168/9674261753856826205
+qmulz:515507640950/169593134508951507,130457186386,9764491091569/7319120645126181160:67251676398821316106700/169593134508951507
+qmulz:-9365485392019/329669514832033195,2420807490629,=1:-22672037190376071733889951/329669514832033195
+qmulz:1709304465717/260423845962574106,2761288775682,-9625873444279/32296180368255957:2359941617703735036146997/130211922981287053
+qmulz:215090735926/98137745784701417,1193894989684,=1:256795751949495738187384/98137745784701417
+qmulz:2462657897367/2405626367061101,-6540272761466,956548940780/2817455913381063:-16106454366958522300460022/2405626367061101
+qmulz:242208253035/596343213619654,5151615220303,=1:1247763722818106293369605/596343213619654
+qmulz:228002384282/59111672575229,4689640217907,8887530790232/4265423449943033:1069249151107554031737774/59111672575229
+qmulz:1065463662219/36125337508585,-1135495312868,5987819337289/651384630027642:-1209828994480848476134092/36125337508585
+qmulz:6023110141478/670453839669919,5713937267309,1998947610187/134406089553918:34415673502497927694342702/670453839669919
+qmulz:-9838734646098/73658633070811,3898971866431,=1:-38360949586416063311336238/73658633070811
+qmulz:-2320378876107/3544145932211,-9742994143220,8635863424885/42773859269883:22607437799961906994044540/3544145932211
+qmulz:1282067863135/7152781512234,-430962905775,4287050590505/9492196607247:-184174563899134867034875/2384260504078
+qmulz:2972203649953/4110957928466,-1076925462656,6468360579859/5380802762138:-1600420895416743198827584/2055478964233
+qmulz:7745401204821/811506016039,-7138418453884,52955801256/2587064107:-55289914893229593626974764/811506016039
+qmulz:-4394166471713/351201211519,1682246763941,2661332639201/255305706936:-7392072327257235964900933/351201211519
+qmulz:242477453617/2530363014,7850634381002,-728870121674/37749087679:951800916991718980492117/1265181507
+qmulz:-4495597725068/18530739005,-295776565976,2058781523476/32738808743:1329692457130130811086368/18530739005
+qmulz:-627713346013/6292366913,8991851477846,-476950295807/2244817575:-5644305178010651601927998/6292366913
+qmulz:-4583081886485/1415176577,769919000693,-869103658209/9579044:-3528601826136720462334105/1415176577
+qmulz:-1182275059809/252123671,-904658392050,-8972966355829/539780886:1069555054567627520118450/252123671
+qmulz:4559690190362/241596515,1670678554004,7140063697224/280561433:7617776613940209657309448/241596515
+qmulz:1432554287/2209567,7757230863986,=1:11112654329451858207982/2209567
+qmulz:1106108950528/6849831,-6298163069823,=1:-2322151514472041772238848/2283277
+qmulz:5088803191704/8136929,-8625507078,-35324495791/106583:-43893507948591842880912/8136929
+qmulz:7539081819837/6889238,7284561918683,9960043148827/9194287:54918908326619940050314671/6889238
+qmulz:391441941525/125384,7929833985877,3351067478098/711859:3104069611402622309842425/125384
+qmulz:9009538508471/742821,-4924002212923,9527002197826/376781:-44362987553126188781170733/742821
+qmulz:-9259291631862/58961,4703549016027,9448940593567/14975:-43551532044151545221852274/58961
+qmulz:3476127453492/36715,3322870685572,308545119513/7234:11550722014520612585417424/36715
+qmulz:-646877695651/729,2845152282117,=1:-613488517344009605324389/243
+qmulz:-2520612775732/3305,5509026264687,4380524270328/7049:-13886121984613190802175884/3305
+qmulz:1963077614302/267,-825362596397,=1:-1620250836669127260869894/267
+qmulz:7889439316771/713,5863316933906,=1:46258283145047187204337526/713
+qmulz:8748734240327/23,6371236745698,-7157017762004/53:55740257070317659715363246/23
+qmulz:-1296384169421/6,2899800596916,464588384950:-626542598053244779017606
+qmulz:-5167288008794/7,-3300699869865,1931056190640:17055666858181330775592810/7
+qmulz:6696697914261/4,4069021265747,5631057961007/6:27249006223411589102117967/4
+qmulz:23865486379535/26918789012953275954,94873123748548,=1:1132096621302455418116582590/13459394506476637977
+qmulz:3092832570307/2006024783468333419,-69091492632924,9214275673435/28417924226192114256:-213688418746233489772987668/2006024783468333419
+qmulz:99742200190859/1397162492835988177,13135144429552,=1:1310128205228222025079865168/1397162492835988177
+qmulz:16157052816541/834217349232726593,19133269076621,18278786726642/1173386622722504913:309137239024056146385187961/834217349232726593
+qmulz:-15154486378645/471850975689269841,83584432024123,14569830702843/38977738569109946:-1266679136576350929552053335/471850975689269841
+qmulz:-70285613046769/438550102087486245,58305445024728,=1:-1366011315842564998875167944/146183367362495415
+qmulz:5620626946546/16483309748982467,18213910616022,=1:102373596810393507725160012/16483309748982467
+qmulz:-87110361266406/28658861993511733,50462053430058,8350373847003/21134055318706744:-191120334979871062479392676/1246037477978771
+qmulz:42263850161473/2487221560052869,70196784710879,=1:2966786390837768841769764767/2487221560052869
+qmulz:2305968062717/1295096854935771,89753857010368,-1448986636213/88097527127243:206969527771576926343249856/1295096854935771
+qmulz:54792800436741/962961846570596,81148189103692,=1:1111584132840379068733886943/240740461642649
+qmulz:118089073191/117603203952236,-88682518170219,8843505968368/446344763404861:-10472436378965178887498829/117603203952236
+qmulz:4370360581061/33937836375304,24828310773456,=1:13563583837330531311889602/4242229546913
+qmulz:44999946775270/77691532844719,19675574610517,90987690124989/70801686470002:885399810246118760377514590/77691532844719
+qmulz:7388469159437/80827214538,12962289697895,-39739510822103/1124530750930:95771477668585155318285115/80827214538
+qmulz:-4438357163019/354300196838,2800216938058,48604674898545/5905387400293:-6214181452518427865638551/177150098419
+qmulz:-1115976535244/90660833629,-84198411580247,81927230020875/605448344659:93963451628372333929725268/90660833629
+qmulz:-14354364205035/137076592739,-60231717901669,29779963372229/288489332426:864588015455483313484703415/137076592739
+qmulz:28410403793917/8317372959,94611442054559,=1:2687949272294801418906317603/8317372959
+qmulz:-26238968575867/81875709363,-41798837075253,94070973760679/3467355102:365586124175115989639573117/27291903121
+qmulz:49964458440323/3849731307,3475521417184,-94000433574238/5577825597:173652545407342463250710432/3849731307
+qmulz:63054816328381/8314862510,31407375891502,=1:990193159097540038129659131/4157431255
+qmulz:15690728254037/869383378,22615130488585,1475502145196/107482041:354847866925974243808667645/869383378
+qmulz:74263848858589/607431119,87079437180738,43892391010643/973943857:6466854161481322249396658682/607431119
+qmulz:23023853281324/23656491,66652947880105,-31945062874493/5458316:1534607692759273053987659020/23656491
+qmulz:3506276105087/11638761,41170764577395,440230047929/1761776:48118689355294122721569455/3879587
+qmulz:-93363094505152/3545929,76526518299725,24762745460028/9476321:-7144752560167469121292683200/3545929
+qmulz:-2458728669037/893246,74281956367289,10383331533388/299139:-182639175712408990493930693/893246
+qmulz:-5121601980421/33999,20660659077801,8112621331106/52165:-35271890816556237705911407/11333
+qmulz:25877846847031/404920,75489603155313,-38374243475879/901678:1953508388996337946045925703/404920
+qmulz:66471726351654/51695,28218300697455,-2687434510961/88806:375143832413983194158568114/10339
+qmulz:-3436425362877/67400,87107727529435,8150807016773/30347:-59867840836945902514756899/13480
+qmulz:64658311574074/1471,54380155658036,79155462122195/5662:3516129047983934816427358664/1471
+qmulz:9680963797950/229,-14929130816650,28202159724489/2789:-144528374970848369095867500/229
+qmulz:816481395175/17,-99383084980450,71300027130653/105:-81144439881633403599328750/17
+qmulz:638399693884/125,-59707159904100,34949260444218/785:-1524681304218419151860976/5
+qmulz:38337688583813/25,46682828260030,66019999840333/85:357942346408931005122578878/5
+qmulz:-4362866892015/19,43253153678106,=1:-188707752157445489971723590/19
+qmulz:80038414225429,58791342870753,-71193599831017/3:4705565853558550737752978037
+qmulz:-8931381288/7,27056505490713,37222461138097/2:-241651966858423345978344/7
+qmulz:-103292201629591/24903444183827008678,811061948698381,=1:-83776374339042161969543392171/24903444183827008678
+qmulz:-108233246344215/10921524390718392772,336628265620018,=1:-18217184999638624584411247935/5460762195359196386
+qmulz:-242546210473995/3227191274694658997,117559616638474,-200514522282738/1463600762469566069:-28513639520437479372093483630/3227191274694658997
+qmulz:346557608752347/7091232122596884343,-890608472719639,764299440148772/741441034955506561:-308647142640297959088714242733/7091232122596884343
+qmulz:752322662466430/796990587047794081,213680028681761,572521425296816/937517719580878925:160756328093765562145815783230/796990587047794081
+qmulz:34927180981080/55520878875379453,-865283782342577,989438973302993/881309897241401311:-30221923265872621723515443160/55520878875379453
+qmulz:274082612801409/53154246781994009,971799838064389,448110955601401/45559104250121531:266353438736673897727411924101/53154246781994009
+qmulz:-124555667888037/14097174308038652,829678276357628,125094809716795/35133120466800502:-25835282960979923394918724059/3524293577009663
+qmulz:505323718065074/2128598622243549,-277690520595781,914993855209755/9726536089876778:-140323606338886062971007852794/2128598622243549
+qmulz:-902895852073028/9135983164951921,833620594767907,842531169585879/9544376880879779:-752672577218593777816474712396/9135983164951921
+qmulz:811564634419288/453082972179167,60327882243393,51265177937813/73949934423745:48959975698149096053229764184/453082972179167
+qmulz:250179460716837/290886574637551,340496244659932,9798345091684/451481890082625:85185166865129977930011675084/290886574637551
+qmulz:-582653512523981/99348978999674,379317852190649,460594514303380/74887958609607:-221010878941933880917996453669/99348978999674
+qmulz:863679006697/1635434858422,924063163904185,-729545153826413/62812666295337:798093955526053605281326945/1635434858422
+qmulz:304709172702197/5457282848355,882318039223156,=1:268850399791912468175214473732/5457282848355
+qmulz:463908939133169/6691921051406,-552915136065320,-601471563981221/8781918044231:-128251137101367195825081299540/3345960525703
+qmulz:-752373946530613/846634747661,284479627123896,50536119796472/513050133075:-214035059766762852800707828248/846634747661
+qmulz:328225703018604/433509767335,197654409561196,-3782967558290/93869557971:64875257532950641256264490384/433509767335
+qmulz:184785598182871/11617410807,895346115182373,=1:55149022491561504431189910961/3872470269
+qmulz:192803285928028/90953336419,332075196148197,=1:64025188992566808558163965516/90953336419
+qmulz:-399599786249880/7362537623,-981001390019795,957969995178032/4517518129:392007945762745245102016374600/7362537623
+qmulz:82589051366095/1626512642,398617970248743,137619262887145/9949579469:32921480020321964131106568585/1626512642
+qmulz:-907650909511793/772837941,990867777654644,=1:-899362039594166707200599216692/772837941
+qmulz:-358503288380739/383532866,697173774576334,-51289684132425/110529764:-124969545379213895872305415413/191766433
+qmulz:275838241610846/67525047,469977259127432,28053789338265/5265202:129637700754795766556067327472/67525047
+qmulz:53930640918734/7001103,693055155395270,=1:37376908722499699209717988180/7001103
+qmulz:-681238687980343/5030205,-582879269862290,-990800444969909/4579368:79415981810385344493567393094/1006041
+qmulz:520602003913013/4593382,308897366106910,-466584092376547/2221166:80406293899354484531049109915/2296691
+qmulz:-405474039012091/243080,-154710965359365,-172296604865771/908379:12546256000744284661479016443/48616
+qmulz:588023971610839/411117,884974921870604,55791283769330/230429:520386468334344508549001876756/411117
+qmulz:540840030461611/7002,-380104715492010,-205957826883233/40847:-11420880328072259499071234895/389
+qmulz:-753807927054263/53929,915393419376816,35196013565764/3461:-690030815899551293936076166608/53929
+qmulz:237522311694659/6300,580421631136666,118641235907757/8270:68931543792582787509445633447/3150
+qmulz:-703556714392601/3647,26296886058971,559465758581845/6674:-18501350754406230744932073571/3647
+qmulz:240687231749867/206,-784485320110706,=1:-94407800022927047065270388051/103
+qmulz:-93887798635737/127,-575220251243142,-652322307871805/572:54006163119914161845877365654/127
+qmulz:-396521866192559/70,394474102270905,182300183108827/15:-31283521439418725353582639179/14
+qmulz:58431834428363/5,-485860188905084,792920518125413/98:-28389702113435038144004497492/5
+qmulz:94346378811421/7,897687299600400,=1:84693546022300913680256168400/7
+qmulz:606162442576909/6,95792984784316,-12377831317439/2:29033054819296832459303479622/3
+qmulz:-3880722889823905/5802853163792252251,6995189470105129,723671795237053/94804862094718615043:-27146391895292126926964647308745/5802853163792252251
+qmulz:-711255950576391/38557928701418837140,-8914163822970630,5504820920293812/83891195583846813871:634025206350065106283436439633/3855792870141883714
+qmulz:471011076275411/1268773388114902240,4280756402169772,-3446853649893419/6906782713522266814:504070920064710111468162769073/317193347028725560
+qmulz:7695205331550676/3582847162742099607,-144661167043645,1213893998753526/600058503660029491:-1113197383902599946494421254020/3582847162742099607
+qmulz:-3199289405937703/365472303862404370,5173907772378010,=1:-1655282832346770788786622711103/36547230386240437
+qmulz:2758027287264869/155052934325555752,-7564742138218573,-6257710286765285/771615064482957592:-20863765238329215589609266211937/155052934325555752
+qmulz:3955143821106077/91399737124804255,-7263645778507290,7804375725987635/91077647617338438:-5745752743913269680040361560266/18279947424960851
+qmulz:6713507007062553/74150811777510379,6266298995262737,528130351899129/2709757324123282:42068842213045420456548828987561/74150811777510379
+qmulz:-6877567017527963/1489247567416462,-4521311499760591,-115573898280262/923926913012529:31095622846723329241375147906133/1489247567416462
+qmulz:-1586799572294172/4730804077270513,2121219051102928,6786948620547679/9912102833874252:-3365949483032375529047866535616/4730804077270513
+qmulz:-9501087403079799/923245070947319,5606803416408299,1323793614080105/21826353763174:-53270729311181670439383462851901/923245070947319
+qmulz:1083936794899597/58977209646283,-8747830330029136,-4634270584400088/47878110359797:-9482095170257265523833204658192/58977209646283
+qmulz:-3719900694014304/36234265212301,-1494306375099641,-1975217081214247/65326075776641:5558671321803153433440279264864/36234265212301
+qmulz:1103608308470404/8630287542765,4527264291311725,-6050102349432119/65604233367649:999265297306599031900300137380/1726057508553
+qmulz:185603093644419/1285147223476,7441353681336558,961853358112541/9035783508083:690569132079175618373558684901/642573611738
+qmulz:7656576001713938/5697164099281,387954634853982,4891764604516329/9388026384014:2970404146976692276584364201116/5697164099281
+qmulz:-8608538284429615/24304320924,-9300930568944394,1012277413814075/307338098963:40033708441789768251278470914155/12152160462
+qmulz:-2298250489792159/192401665676,4151647369458953,4637677731066783/854611972340:-9541525600303367226221251749527/192401665676
+qmulz:-4958597485118384/18914385675,-8391716685524037,=1:13870381750888490254448674198736/6304795225
+qmulz:-8775066120996947/26819677230,8537625341965974,-8617075263155655/41305030346:-12486371148675098768666305313563/4469946205
+qmulz:8632423322860386/9616021081,5042628174507057,-6506115385718735/7975459194:43530101062127611384934782744002/9616021081
+qmulz:-3848534615760728/9274753529,2104642248786963,5619621461116310/5343995473:-8099788548249129154859453789064/9274753529
+qmulz:271301194709322/33552569,1917863106025352,-3970383512818995/409886044:520318551953609085962402731344/33552569
+qmulz:225678582778501/66976167,5457450818595612,-1586701099858817/141482387:410543255441342622436562179204/22325389
+qmulz:-5691916212714825/75531979,-3677441922214847,186124889390004/78334747:20931691298371858008446792006775/75531979
+qmulz:9683640970785183/21432671,6061708788245552,3666308965635053/8459353:4515339351909479419918957481232/1648667
+qmulz:8423905758112927/2462761,-1402202086438487,4991587911230636/4020141:-11812018229987130827123385021449/2462761
+qmulz:110629337771891/244490,5329540769616160,1715961548659264/49589:58960356597093007948570735856/24449
+qmulz:2768082072858327/11996,8431038603161226,=1:11668903406493550143637918814451/5998
+qmulz:-5632710453612631/282213,8269803080914635,-1089107539381719/990995:-5175711807020645232938163194965/31357
+qmulz:513164615298521/2937,-761654779947971,6308090089559589/34312:-390854282142280204811013250891/2937
+qmulz:2399352646293603/26699,5936082314225321,246326307317325/1064:14242754809253178957252862921563/26699
+qmulz:1917463706144480/173,2784408494403777,-5268002443544296/9923:5339002231099637846089019700960/173
+qmulz:-299651250103083/304,8512720924447435,1696619119714772/2041:-2550847466789346268098564942105/304
+qmulz:567861836090453/137,1194683804539166,398775012895933/117:678415338793138672840757182198/137
+qmulz:5855010424286591/141,-3387352251576542,-6842084179082795/92:-19832982743711308513005380748322/141
+qmulz:1839091525348225/37,4835017725039396,3258229037788442/47:8892040123028407522020743672100/37
+qmulz:689624656142569/50,-1436205069429607,1650564655275659/9:-990442427155607164133701640383/50
+qmulz:887987723713419,-3871030680937173,=1:-3437427722790206595690596024487
+qmulz:-6321481694612935/6,9155176113205281,-2076666497659035/2:-19291426070194927792191164303245/2
+qmulz:47535841066367704/25874740830854221899,20217596491741418,386741628388289/10612132664990412300:961060453575373318717870874364272/25874740830854221899
+qmulz:80223166731461168/79315578551274076339,19941312492318563,-6517563635718293/15173501904275140121:1599755236915441531514785120061584/79315578551274076339
+qmulz:-94966952144940093/814524592733157116,-8833229520058195,55047972140476464/8182255352181738995:838864885116638749899220148712135/814524592733157116
+qmulz:19023061829222254/8275414709591200245,42825769994498364,40342865387732273/6423424085911584926:271559090163131188965234998464152/2758471569863733415
+qmulz:-45164511230863025/205230894764003516,95431251431037353,9088808827059225/537242774047899907:-4310105827032399655884245201572825/205230894764003516
+qmulz:78978348840218612/30892480489678495,22023635711834354,=1:1739390383979149957558284891796648/30892480489678495
+qmulz:-148958689172671/102037781856410,18768909665863199,97201659871254553/14233090955064268:-2795792181027256577300375434529/102037781856410
+qmulz:-13899781468245877/210298830514748,-40323281693369663,=1:560484803620357867773725936629451/210298830514748
+qmulz:88175738959378971/4244405961829309,49633440309199351,91798871890211817/4618870882937021:4376465276359879854575633196247821/4244405961829309
+qmulz:-196047733461491/273753721482047,-28937490043883541,-8575700230869559/2512020324451605:5673129335167829946904412219631/273753721482047
+qmulz:-19132451907214205/25824658302078,18312961377925295,-48090033092819861/431889830006992:-350371852841826885918246052815475/25824658302078
+qmulz:69382145113501751/380297809139977,2745327554581026,12801801952051298/753948686518799:190476714776035644694264522376526/380297809139977
+qmulz:1915274245412291/3788421267711,48395753953886595,6801592121612027/29575658734452:30897047045063015615882544379715/1262807089237
+qmulz:-41044766089612839/3600558205679,20994850850464225,-35435905322101302/25097049433951:-861728742243613295588013670184775/3600558205679
+qmulz:42597494937030563/139066009314,65616555969864940,11098362865249168/1843997772651:1397550455355852172511957881080610/69533004657
+qmulz:74024369507729486/8798209628891,-48540197369243101,=1:-3593157506038970019752620879776086/8798209628891
+qmulz:-78176595124115512/936929521175,19202167121582858,-99925056698963177/191994309327:-1501160044569585652613332671093296/936929521175
+qmulz:82802252720820771/664875719702,97327360089498817,-27164056917268865/462863761311:8058924666781006338043050273527907/664875719702
+qmulz:-79012216554892489/70097745469,18109121557124146,-26372881204544091/13780169332:-1430841834090364897003709055939394/70097745469
+qmulz:-70054799672271272/45482963493,7787932643225419,22281182451081849/9895333688:-545582061182298824047255613862968/45482963493
+qmulz:38317664305319638/2445394649,31654407463814347,-43227662278819145/8020766369:1212922958982242534681702525246386/2445394649
+qmulz:91685907685022135/618530726,-65256514026907419,84454182812530114/7990613223:-5983102720917385677413600610719565/618530726
+qmulz:-9319036791983210/326561129,48383470752719549,-21563116260711314/160888617:-450887344068437052714708646772290/326561129
+qmulz:-10319092612953469/85265494,-55462305741126344,942196671950729/100675391:286160334735311815060828261043668/42632747
+qmulz:24190194708441624/10753379,88757165826516370,33675430745281060/75133189:2147053123112872034250339425384880/10753379
+qmulz:-11468596832661746/1766525,56376469108104767,96014028182502185/4186386:-34029420792098057856142633744378/92975
+qmulz:-40039747951909081/6069939,-55718774097961657,-38493857988408833/3718928:2230965671071745008018063888107217/6069939
+qmulz:-37290139983929779/799087,11981560139468355,-11746974507966646/3218933:-446794054826648164153652712643545/799087
+qmulz:41894225992589221/366814,74540431481275887,-66854308231170017/431055:3122813682061684114056083763414027/366814
+qmulz:4577566343641272/36389,56889856836673491,=1:260417093950126892755280695920552/36389
+qmulz:88284563154658136/23691,63742381682886541,-30323740102908723/9056:5627468321311120786042358530547576/23691
+qmulz:-35239011702626416/1503,-96377199381969204,-61186369864860723/42751:1132079085629190722429226942964288/501
+qmulz:6204324005181542/3263,9242869672214658,5888893248603815/2661:57345758184085853188298483442636/3263
+qmulz:13023563233102553/2092,-18292948555955590,78624947167647851/9735:-119119686119189830929040691810635/1046
+qmulz:8668988413765031/12,87487198824736036,24608302652702701/174:189606378241098583267909375589279/3
+qmulz:-88604450607713147/253,-57197213811690954,-65274907046510203/195:220344682872903450186081523772706/11
+qmulz:33666476522294146/13,67039261791546104,=1:2256975733177017899095506408307184/13
+qmulz:-19043783688556820/29,-46927274804274505,15813572639616397/59:893672870466066256149790569874100/29
+qmulz:-94396743394101937/7,29360199416108739,=1:-2771507210282078156031800042527443/7
+qmulz:32378539760159572,74380454651945304,-15922753341092935/8:2408330508326757024819007256049888
+qmulz:-515970186826451384/25959078573251600323,-481657180143660888,855482564716356613/45268895425503079014:248520745225026458245551027714268992/25959078573251600323
+qmulz:-130967478747895251/18589421418033360838,147641505075499109,-55563959724327169/34005532994986142887:-19336235678282698393435282075831359/18589421418033360838
+qmulz:-860266011517441547/2553655932637699066,-299807248907353740,=1:128956993120773018576083159450917890/1276827966318849533
+qmulz:145239559532108435/807509961508023596,576064609905367511,401973572562411248/7006133492934535601:83667370204691447066198253378055285/807509961508023596
+qmulz:-203788329869580393/934147712305627115,977955003052547263,34371785465644891/24153024504080070:-199295816759679001811043775610614359/934147712305627115
+qmulz:-305697857540446967/103403955365462673,-568720855877228261,=1:173856747180237996116028815024134387/103403955365462673
+qmulz:226166409746766031/13002990761630932,789981405518661663,-113466700430225377/10401766053678468:178667258252859769569650633510369553/13002990761630932
+qmulz:3220063708444885/86759191901981914,-436274250898667434,=1:-702415441123888629947969466687545/43379595950990957
+qmulz:-67396315446702174/385366352018695,935081661792652149,-625977217802097815/9842734508647274:-63021058646604060109741387184071926/385366352018695
+qmulz:24319453787590069/147313838530763,247065078929176318,=1:6008487769545396355634476406785942/147313838530763
+qmulz:100629482109427385/145102206127588,493200833830327566,587248475105746167/360845897573321:24815272242141808191386545620397455/72551103063794
+qmulz:68125647111849775/751431108442761,573247979073143838,74386340727896222/930067472967985:4339209947768671307372114758104050/83492345382529
+qmulz:315260234123867071/28724643212088,340944306756538261,-53419962261027213/66345800395925:107486181971265805844870978489503531/28724643212088
+qmulz:-236430702618704929/20104762237425,598324387971999776,114120042986736600/9261982109063:-141462255442126511362707327398095904/20104762237425
+qmulz:40711881042093025/722627757269,-916183636373594020,59862621134038918/36564773153:-37299559216753971995016222423710500/722627757269
+qmulz:-520309382707815761/931737166517,259750055972789770,-130681632611383930/845007490973:-135150391281522837582794926345564970/931737166517
+qmulz:-744723510370875375/104328014528,392776247476475915,645297290772722121/747416253776:-292509705810980823923192458654093125/104328014528
+qmulz:150326873930054465/220440980183,184204467758877126,446972731209163483/312751250617:27690881802141504054899212422667590/220440980183
+qmulz:115421167528373279/5250405410,771027268136349173,=1:88992867484509542530759922626948267/5250405410
+qmulz:84701761403492795/44355610023,965802039756702720,=1:27268377978159632125207673492300800/14785203341
+qmulz:894229992015313913/3163831833,-785572023936143576,681929403708376856/586412675:-702482064691871660107123412278372888/3163831833
+qmulz:74634858785325581/142443768,427912086580428045,263236478364528529/7486986306:10645719384821420242829855889439715/47481256
+qmulz:-332428641831574483/344279073,908684289900488822,-638499266082892652/390482433:-302072684345308192917372015601929026/344279073
+qmulz:415890959805425615/192542692,57300089077177939,200778229355831075/85157704:23830589043243917548894324983507485/192542692
+qmulz:806988421881608649/16389833,666714975759989998,994687425328887678/8586277:538031266133389292509645688390292702/16389833
+qmulz:99978136901356657/62362649,-421321213914285499,477860583712193259/43057685:-42122910004168208858812125922216843/62362649
+qmulz:134226773204000444/2213319,457929073299284411,=1:61466341865261143971298267726278484/2213319
+qmulz:203692403587646607/2530234,198709333320751525,654497348349770852/9852495:40475581719402713398336251356325675/2530234
+qmulz:1932413671793631/11008,605844360169614539,271988563133914698/256283:1170741924570827879369734025201109/11008
+qmulz:78300870419392545/300541,9938443225300603,474105168486707610/456971:778188755154752224021438282204635/300541
+qmulz:731791251673481239/82178,-375066073302435963,897701210637687185/8253:-16145298308367486968573476887023421/4834
+qmulz:-244865844794445459/20764,633837473482998794,-572503688932727221/18042:-77602574203395710948196720797888223/10382
+qmulz:-871079916851090199/6190,-933271236207286315,165562923533871377/1253:162590766166991424800556971016665337/1238
+qmulz:278477012608289079/6904,166601452640247459,=1:46394674827457467509510753167200261/6904
+qmulz:50351542334760530/697,74118063280217581,=1:3731958801024335445119077930877930/697
+qmulz:716113366657554965/773,292433182475186613,55790708408336567/73:209415310824688987980879304679683545/773
+qmulz:266171451721629402,838958222079312932,186531239281784779/61:223306727904647880295582119690026664
+qmulz:-191048663820313019/17,-335221912735777740,-104282880591219422/9:64043698511459908763402007212397060/17
+qmulz:918486165864351700,-754751323324354742,107963234237522909/3:-693228649141232227471800102650761400
+qmulz:-263050925547501061/9,429366864986261421,-369906620681745801/4:-37648450411354997741362101140289227/3
+qmulz:-8908762588791502798/9682457258957956871,6517968147068840217,=1:-58067030783541555611439264126370427166/9682457258957956871
+qmulz:7658247927733463351/71097873025711495885,2645904249530727710,-526743598589435636/3308522377463446025:4052598147189972001038980978729031242/14219574605142299177
+qmulz:35178382688557660/101323881670407613,7331418798392863213,232580837460702659/1407098737763013928:257907456139949700482063020643361580/101323881670407613
+qmulz:1263699762126537691/454699906557876874,-4542833552105116827,-2210388710075629538/661648401890741827:-5740777679175690401542804846573826457/454699906557876874
+qmulz:-1832647602190411445/226947754154888126,5643404261053171972,-1097284930177831457/619682865758859799:-5171185643605123184522851420511009770/113473877077444063
+qmulz:1823011844211832737/592442421313405007,-1035458481118632295,-6389536796987914382/963103956263803057:-1887653075268861046971124680746441415/592442421313405007
+qmulz:3241180647893831993/47706456259746618,401191978478284716,8203697741103525736/82629569130745973:216722612789009192825658264487286498/7951076043291103
+qmulz:669385746027781985/4358673572763459,-3232260578078726488,3369728187950184564/4211286946970669:-2163629158413418191796114556108718680/4358673572763459
+qmulz:-8416424642111725238/6365835551441079,4033684793967464839,623945245518632503/408732809111644:-4849886299779875487264451230199129526/909405078777297
+qmulz:1670670426691770676/933711771783465,4268278044364566390,-4259333158202693983/1474131926823072:475392393441177774546174414803811976/62247451452231
+qmulz:-2026621003312993155/235607922312922,-6449641809771356053,4984273563952773559/458950128766224:13070979555528254543461227718656817215/235607922312922
+qmulz:2110680248476630645/95785011231043,4324730695176379682,-1722968689643087720/615704293887179:9128123658289392651639137372596554890/95785011231043
+qmulz:-641839465597711103/9456066925611,1548277416348552437,-2507922761391944404/21340298450009:-993745549506159751964209714572608011/9456066925611
+qmulz:2741589907602153339/57948673895524,1590482362679123180,-2499147223466166660/93552475783027:1090112598435077963801396817107324505/14487168473881
+qmulz:1105127694202188183/6381230280571,6999165228541352101,-1962335544251498845/1250684067374:7734971330358035931095740815664422483/6381230280571
+qmulz:3388900892142215022/3450834628513,-921940083605878001,6734092499539471533/5162430112340:-3124363571833628263304768671241531022/3450834628513
+qmulz:-386348847054518292/323004206381,514411028349585069,3189676746121428640/214488726717:-198742107714991314988148399870582148/323004206381
+qmulz:2621996699851800211/639729174738,901100719762883014,9556760707097111231/962924737943:1181341556726180554328723203646757977/319864587369
+qmulz:-2049289271073576417/18016913114,7508216114633285941,-9469235071531039565/67942461077:-530569197538611262694579912395698393/621272866
+qmulz:1639764361637752909/49863322429,-3667535081176061352,=1:-6013893321168728538238660340400472968/49863322429
+qmulz:4212865081507184639/8422182797,5317645517552525584,826928849605057287/795440204:3200360445247176534048939736551329168/1203168971
+qmulz:4093224907870688472/8446810835,-4394239498678494479,221730631562040646/480114129:-17986610567140020861411212830180946088/8446810835
+qmulz:8729905651613329077/131452699,-9507557452223167406,=1:-83000079535201453087454918169138464262/131452699
+qmulz:4738064793602310889/451996055,4531489655540363995,=1:4294098319897772319607429689642408311/90399211
+qmulz:7744273453919740331/974912,4029995544880393387,5229428187412633641/38528578:31209387517632050003517673680169591097/974912
+qmulz:-8068802747587440815/29032004,-9849867648134802759,8503993416585326183/5318819:79476639142642740206984820735611208585/29032004
+qmulz:2861631232576326878/6980153,2635765392614151917,=1:7542588569248461690745630176942325126/6980153
+qmulz:-1779740841595132817/3012373,9922862571979507578,971621845586608480/521437:-17660123784887653006801622709167987226/3012373
+qmulz:4023122851061736595/781603,3458044068302173434,3738807635979349585/665988:13912136111164966581427463952914617230/781603
+qmulz:586647455438577923/33279,4526301832916840671,3608109198062688989/33159:2655343452827635863034403318209106333/33279
+qmulz:9196111739041159411/1211,3157226438241334248,-5764176110323692119/75991:29034207111522241973647178465501807928/1211
+qmulz:-128347641900306833/12774,-7554445682363002392,5759447892271827483/18544:161599214865874288341552651985490756/2129
+qmulz:836992725257147861/4133,-8611487193024899504,7678442646525158846/9511:-7207752134206937140419355427193560944/4133
+qmulz:8699549138022640117/5811,-6972026102209810211,549233631824230415/177:-60653483667750701802929732179724834687/5811
+qmulz:3156470757655913741/841,-6926959212561953600,-840701905979711979/41:-21864744193927041320056800380044417600/841
+qmulz:509258565369492935/912,8179603403105663140,-6092933483503672408/101:1041383273589253055649823422179978975/228
+qmulz:4260013411623757232/75,-7652070371810821485,=1:-2173194827373526007681124278141981968/5
+qmulz:-5571230682641213483/85,5687608093861986954,1592299486970268628/23:-31686976723362408587412758204074900782/85
+qmulz:1224310285715487476/7,7384878353077411745,1489674084056377327/2:9041382526430324573993691487042805620/7
+qmulz:532608537074668190,5378987672829123810,1299009834218541099:2864894755368193556998428824178603900
+qmulz:-16831183915817756170/2753858239387681579,59557538310440342273,14474171978684251754/88138472845001942881:-1002423880876383309855786104105657574410/2753858239387681579
+qmulz:-76852233908089385223/89591433315005827168,-16827322555441357812,-13261671210390977146/47829058560152879137:323304332269411910681014536231862103019/22397858328751456792
+qmulz:69150327729675178449/8650125162732904421,14293920797793407650,50884780102476306733/6026568253305189080:988429307709434226307578722449551734850/8650125162732904421
+qmulz:30499040613205460343/8988598618848438770,30570026052354339437,51811261931566266659/3748183226209013484:932356466117503990794086213419264446891/8988598618848438770
+qmulz:43819658523452866810/102194429295876731,70504335913014047202,=1:3089475924131090053789938711687559165620/102194429295876731
+qmulz:69656424488183436907/30102774811906661,984948427407800828,-39906369295800321023/155750850550041643:68607985758486503850804077075560358996/30102774811906661
+qmulz:33641878290673988917/12925928405761371,-5396171272119458800,19436319690765846760/70381750662978231:-181537337172274262921911758331238119600/12925928405761371
+qmulz:42954819767647340359/97571649192732270,38715654116595663589,=1:1663023944764940538514016228488546488451/97571649192732270
+qmulz:-99002754944524890631/7986465915924126,-97203975364529818705,12484199575939692941/2326957254470028:9623461352648180166996658939078383052855/7986465915924126
+qmulz:88352255172275736854/7933296505985257,42489727492090669013,98815810269903702196/2382358470880605:3754063245581654384182755776192399905102/7933296505985257
+qmulz:61590480972201025960/675375171340791,-75994828859228936809,-11049721719852020118/20660972971879:-4680558060840013232552967100229808561640/675375171340791
+qmulz:-27522646268475576522/580129834806571,5567162029085222334,74438237038085866509/799763096356799:-153223031245801313480018162391200442348/580129834806571
+qmulz:24148248964829892922/23286035365313,49985702383172830448,7055168644844378885/36672697526553:1207067185830748414507857319763501289056/23286035365313
+qmulz:52980189869726618341/71466611837586,38839808746354627533,32063023501001399398/95171990625945:22126241310599319846248909165943025621/768458191802
+qmulz:-80505026028619928191/8017291718590,-1533155918930949021,-3916532593760914985/326976214133:123426757159468755445689924468501751011/8017291718590
+qmulz:17292391457368334407/1571629061585,-63370707239731364623,43143296273586046143/3465594785525:-1095831076519720312454034284738713483561/1571629061585
+qmulz:-45604879788200428008/529616356051,53301018012216428706,-91229775748273485595/717004201262:-2430786519035835963440363052798417597648/529616356051
+qmulz:-50447424829663619798/988121155093,6780140438275382263,16659035028087001517/899562317168:-342040625094459896541992348672744842874/988121155093
+qmulz:3593845345146253521/41915442602,-63858823181329772213,3118916835826556491/676191095:-229498734436739670514786299133279211973/41915442602
+qmulz:16886813553311884569/11104775518,-56529259575299150290,73272925971647951646/32053123633:-477299533377423659452543589452131437505/5552387759
+qmulz:-36701646710377438096/4191403967,41311697381328283293,85676309288704030215/204223664:-1516207322295535412352618149227058530128/4191403967
+qmulz:-31991568945242380121/3326501360,49756427012706630969,=1:-1591786165245924544503303159456768567249/3326501360
+qmulz:25027541823211097487/727783012,72744111549984214188,27646550684503944351/772714058:455151573552390843680552331807189136389/181945753
+qmulz:-10660456145991522967/70536419,85257294987559072920,-49523716090045547608/476186017:-908881654340736383544975893469407753640/70536419
+qmulz:33128477737669316703/79965173,30163481878837698924,41486580218368730746/24538333:999270237913666562482186749103918327572/79965173
+qmulz:-88082268340996623207/91130108,-98498682060501497133,55248370490574572505/10033543:8675987344487603057841057039320991765531/91130108
+qmulz:-44828402098358201492/3408511,-69899774554986777317,53529539851460359205/7667246:3133495200335534468175721510741221156964/3408511
+qmulz:97775247222108446692/6123089,-93552521078990120186,-42751923423887600316/1557173:-9147120876749770652720919372526854124712/6123089
+qmulz:36516268542348216758/743177,-24090657731418051536,13560217582155473423/145359:-879700927082258851088293609160542840288/743177
+qmulz:13823011732367751421/140456,92159940210798638916,-70795417829842533145/263179:318481983697045021949324000379556224909/35114
+qmulz:21697263555618348560/7063,34463551544345103980,99869086375772085/122:747764760920293478397871020089083268800/7063
+qmulz:-40668672455972057307/50141,18865137997582967131,=1:-26455866140014285075027032694601012973/1729
+qmulz:-15581921553193083728/2673,-55246769898174604433,-17101679935689176965/8667:860850834620665736463709777467848966224/2673
+qmulz:5779320031390413993/7,19217000507739754005,25876817036248520828/8953:111061195977620116757818678920929791965/7
+qmulz:2423549793740192960/491,98696549719389277261,-8414536430516573180/273:239196002715294582270898075501080282560/491
+qmulz:27706287293558914219/676,32022217504768731686,-38742274862382707994/961:443608378981976875151437105221950621617/338
+qmulz:64017926203955613359/38,64555971256483309833,70053608548103954878/35:4132739403922228262726093720335950859047/38
+qmulz:53804889371534152691/9,-61739634189995994475,-2917407728537843404/21:-3321894187431722069404444190953042382225/9
+qmulz:-63773122944071670311,68924540068336860054,-11050684739856731468:-4395533167641640581052894142988833656794
+qmulz:91952574331161593349/4,-53703503362679036569,87690617237600059250:-4938175384800530690367847777470278179581/4
diff --git a/polly/lib/External/isl/imath/tests/qsub.t b/polly/lib/External/isl/imath/tests/qsub.t
new file mode 100644
index 00000000000..10d94ea4038
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qsub.t
@@ -0,0 +1,803 @@
+## Rational subtraction tests
+## Generated and verified in PLT Scheme (see imath-test.scm)
+
+qsub:1/6908363373906559980,-3/3282386453454754261,=2:24007476575174434201/22675918354053873847004295306757074780
+qsub:1/38717857456042735841,4/21180041959354743117,=1:-133691387864816200247/820045845495301036647051443116443956397
+qsub:5/43729125372682174,-9/5619593033754393704,0:14245763648563054043/122869944158248625198135913829316248
+qsub:-2/2974810045372038215,=1,-4/6399510259263906921:0
+qsub:5/554668526872261904,=1,-1/110568531382495635:0
+qsub:3/342789991526278043,-4/498606462885016907,-3/85472740226188603:2866979354760162893/170917305187302413099656668837873001
+qsub:1/3516821512087322,0,4/43427709377638547:1/3516821512087322
+qsub:-8/99244619430310225,9/68745482383862908,2/20174595569499161:-1443165433943695289/6822619236739570045025636310634300
+qsub:1/4158186027003720,3/1924897427288305,2/873983495405445:-2109932130744571/1600816317113127793988749498920
+qsub:7/3877179943979588,0,-3/8937193062762751:7/3877179943979588
+qsub:3/6941436021947,0,-5/715763583943883:3/6941436021947
+qsub:3/164894601106681,5/983718669019872,=2:2126683001526211/162209897529226945840780964832
+qsub:3/97536769945753,-8/56666447486451,-3/355123038725:950293502025377/5527062252129064526472492603
+qsub:0,1/69397821325107,7/899954591994:-1/69397821325107
+qsub:0,1/881101320631,1/1676161462807:-1/881101320631
+qsub:9/5714833944922,-5/2130613532867,=1:47749691520413/12176102541138516914751374
+qsub:1/416320154010,9/647850043316,8/147151224525:-1549515671387/134856514904351145548580
+qsub:1/437091275186,9/260061434048,2/56787440467:-1836880021313/56835291917370078966464
+qsub:1/40450640622,7/70939336904,8/60816634845:-106107573725/1434770811533343057144
+qsub:0,1/44837423526,-1/89874392823:-1/44837423526
+qsub:1/320712007,1/384804019,1/5470204:64092012/123411269235156133
+qsub:-5/9120926808,1/893326726,=2:-6793780219/4073983841738135304
+qsub:3/355507838,=1,-1/715596526:0
+qsub:4/397576755,2/95841397,-3/206755309:-411787922/38104311613926735
+qsub:0,-6/63950497,-1/12602985:6/63950497
+qsub:5/57474807,-3/9692846,8/51541573:220888651/557094453130722
+qsub:-5/7525009,-7/6073612,-1/1008717:22307003/45703984962508
+qsub:3/1999328,6/812029,-6/2808949:-9559881/1623512316512
+qsub:0,7/738513,=2:-7/738513
+qsub:7/320723,=1,9/571685:0
+qsub:7/14415,=1,-5/47022:0
+qsub:-1/22106,3/90671,=1:-22427/286339018
+qsub:3/1135,-9/8459,=2:35592/9600965
+qsub:5/6528,1/1065,=2:-401/2317440
+qsub:3/100,5/979,5/637:2437/97900
+qsub:1/117,=1,-6/601:0
+qsub:5/76,3/55,7/20:47/4180
+qsub:2/5,7/12,8/11:-11/60
+qsub:1/3,=1,=1:0
+qsub:-2,0,1/3:-2
+qsub:-27/133467566250814981,83/42563959651039965219,91/6397136498252123976:-1160304718576896704336/5680908104622192257664942460644145839
+qsub:45/40427972021325393238,64/9751620923778714977,-18/31750379913563777419:-2148567267794782993267/394238257869097174193626565778845125526
+qsub:2/843174797904089739,59/3829064789486601609,=1:-14029727832456030461/1076190310012343744009826655225930017
+qsub:21/135302160124707707,=1,-91/6243239679870796216:0
+qsub:33/269586386932708513,71/663560078654965882,82/347777995721589109:2756849123391569683/178886764117376127330118719865953466
+qsub:-49/381369757179978313,-79/502081482360917424,66/15964802517749773:5526218181533332951/191478693012546642471803143103825712
+qsub:50/84007949326343527,-55/90680207033049248,=2:9154447564601356385/7617858237334741132727849157017696
+qsub:7/63509973628647649,31/6358426332168578,-2/8606093719923861:-1924300198162897073/403823488675725185285863631373122
+qsub:-61/3288737806026908,52/891085361745265,=1:-225370572979860381/2930546117568816471902431590620
+qsub:-68/686724622342265,-2/87939998369281,-97/6330897213879162:-4606470644426578/60390562168923894678643961465
+qsub:53/74615069808694,19/206431401793345,8/335314245039321:9523177968682099/15402893455516996957672341430
+qsub:-41/794425111656850,40/355792921374903,84/720131909879285:-46364514242645023/282650831289974168794338035550
+qsub:-19/9948614096197,=1,-17/6019916154851:0
+qsub:26/86905243242955,5/1105886678309,85/28690254896344:-405773162578741/96107350777587172015563095
+qsub:29/1328659476658,-75/8718935424058,23/3978732114658:88124647011758/2896124044385949895659541
+qsub:89/3664660122749,39/3752130456923,31/2507346317004:191017865878936/13750282860837702636841327
+qsub:-1/111730970852,-4/53644158721,5/525620687366:393279724687/5993713934436112600292
+qsub:9/134376727834,-63/680315135834,-13/19845761250:12619870308/79081766305636815401
+qsub:53/83663624339,-83/23745430735,39/22448823287:8202588649092/1986628796780784659165
+qsub:94/82386633297,59/60658096185,-7/3139891864:280349892289/1665805442295916557315
+qsub:-56/4452532283,=1,-33/2287829573:0
+qsub:5/4288753327,-1/207457757,-40/1852400711:5326042112/889735145545707539
+qsub:31/984155769,43/889343448,-34/317681033:-4916350393/291750828323850504
+qsub:91/918406649,64/20465291,4/3347977:-56915684055/18795459328119859
+qsub:41/61159865,47/95152545,=2:205348138/1163903361321285
+qsub:76/19895571,=1,=1:0
+qsub:1/1255098,=1,83/1479054:0
+qsub:91/7916464,-7/427858,=1:47175163/1693561227056
+qsub:25/630098,19/359620,-70/654341:-1490681/113297921380
+qsub:1/23261,6/84073,16/99379:-55493/1955622053
+qsub:87/25076,=1,7/10664:0
+qsub:88/76661,-54/49307,=1:8478710/3779923927
+qsub:86/1213,99/1546,=1:12869/1875298
+qsub:40/4409,47/6632,=1:58057/29240488
+qsub:47/221,-20/453,32/67:25711/100113
+qsub:88/281,27/221,3/160:11861/62101
+qsub:11/76,=1,0:0
+qsub:12/11,34/37,-91/30:70/407
+qsub:-21/2,9,-75/4:-39/2
+qsub:-78/7,19,=2:-211/7
+qsub:716/63229225130372968755,323/1041977709013285590,-85/5331036743812256792:-87453260788697584113/292815302862361288266503618244274402
+qsub:28/28432306149803878485,51/36062569591582234426,-327/8530238148665402747:-440295665075695238807/1025342019176473906318007480837287724610
+qsub:35/2651717833003975527,94/1600682896707796861,=2:-193237574917600809403/4244559382184525484529422270531420747
+qsub:386/5424883893029166991,-201/2832569452810712705,43/716839232710423233:2183773471283797669321/15366360400439276458941965547170320655
+qsub:971/506137779607436980,-690/134579589961574473,267/104999489601941375:479911849781820329483/68115814843630618803212580924211540
+qsub:846/926665120742753771,-693/971167451265042566,=1:1463786592444954374139/899947003487953107927067006372016386
+qsub:-160/248883036705679,=1,950/1477253685625391:0
+qsub:306/15329555212551109,173/93038341559131937,683/17162719883913218:25817719465323030865/1426236393814901458412317286668133
+qsub:-625/3476582462880142,-872/8679903101365753,437/9209000641481251:-2393359530722111801/30176398901707132402666142576926
+qsub:4/92742256929161,-206/1677519242207209,-29/1920847318304748:25814981896236002/155576920564392438731996521649
+qsub:105/440859258236711,23/114084068799213,859/777590483782957:1839064284473012/50295017947446948173484508443
+qsub:234/109710309040703,435/19164872307439,=2:-43239404312765079/2102584063574743486180689617
+qsub:40/98720052152257,200/37673731641681,195/18309401204:-18237061164784160/3719152752436883045979424017
+qsub:101/8139505456847,-896/64811418546951,=1:13838950162576963/527532894928902528173923497
+qsub:339/2503418324141,=1,203/710577119901:0
+qsub:-210/2286964112149,579/5338514331377,-895/8857700286753:-2445240230523441/12208990688052313177599173
+qsub:223/305810995184,29/35011322751,41/153998316063:-1060993886863/10706847453191530631184
+qsub:212/157864593381,817/922433484280,301/424913103878:6052775079553/13238144265171023231880
+qsub:39/74199525578,=1,86/3093865155:0
+qsub:-285/57499506881,767/82446691329,5/8259783887:-67599428806492/4740644095387518534849
+qsub:419/3764128897,129/517942151,-247/7249378910:-268554866444/1949601017553437447
+qsub:245/1908967167,757/2819581996,-985/2094042342:-754290556399/5382489455028325332
+qsub:-295/48205876,431/527424726,140/594985499:-88183513363/12712485470444988
+qsub:961/845688743,-405/870406786,187/421915568:1178964862261/736093220751009998
+qsub:407/45012097,=1,=2:0
+qsub:-58/619321,49/12338458,193/39820887:-745977293/7641466147018
+qsub:575/7245689,-62/7853229,=2:4964839393/56902054979781
+qsub:95/498463,=1,31/397052:0
+qsub:194/160465,199/12089,-11/7277:-29587269/1939861385
+qsub:266/45609,908/59061,-571/590454:-8567582/897904383
+qsub:131/55938,=1,55/8836:0
+qsub:199/46692,=1,964/70603:0
+qsub:382/8669,-217/474,467/5123:2062241/4109106
+qsub:147/745,528/8207,-88/5227:813069/6114215
+qsub:396/775,=1,-877/724:0
+qsub:6/551,=1,-435/346:0
+qsub:55/24,277/11,54/5:-6043/264
+qsub:10,-123/13,556/9:253/13
+qsub:108,-709/4,-92:1141/4
+qsub:181/9,=1,-941:0
+qsub:5864/87029719866427538623,7169/77056696318482378212,9879/50543130835616368106:-172055594510838358553119/6706222694429899607884755085022523682076
+qsub:5653/86895502758062177839,5653/8154794595245621549,-1891/10149086543140986167:-445121223244401992707370/708614976242596448503974984564128652611
+qsub:661/363701500997277796,479/2983031197662645683,=2:1797570602677312732179/1084932924111611507079868138271154668
+qsub:-667/1895442338469738028,=1,-1283/8749436718472928966:0
+qsub:-9697/818740708549198026,3503/102582377391327177,-1163/20328789690713125:-1287596671870513440149/27996122783345481707441743709517534
+qsub:5593/36797958092515142,-896/400288681159053633,1503/320767765005962056:2271785564173480536601/14729806114199011085303985442610886
+qsub:6797/6164537725975597,-25/1227246984675396,-8333/22072906026109818:8495711197988056537/7565410336121273997822462311412
+qsub:5972/68776879303523725,3471/59251132058857634,=2:115123212592966940773/4075107958209196684815674316366650
+qsub:-6611/9413167004921254,=1,-6256/7532100811974283:0
+qsub:1837/782359177742283,274/89188711189557,2191/8972155631565142:-16842250748723111/23259202250051923207502312877
+qsub:553/12771753856843,7076/381142689332759,4681/186762282268761:120398976909994659/4867860612493178112476219837
+qsub:3079/80223061021791,-3585/408207816163306,=2:1544471539729939909/32747680545640939721680601046
+qsub:-9557/15580233019419,6164/45700338424117,-8859/38230373237191:-532794690650984885/712021921714050551118928023
+qsub:-6948/27781302080773,=1,=1:0
+qsub:965/554586285674,=1,1991/3124819638593:0
+qsub:745/38448222313,1985/5666404010804,403/1187780069839:4145151266757675/217863161122667045869652
+qsub:-859/409102304936,=1,4163/697719670590:0
+qsub:958/328712574179,-6903/92390217229,942/905293648915:2357612727663019/30369826134301586329991
+qsub:151/12267425536,=1,=1:0
+qsub:8671/21057436708,2207/65025757482,2889/90207961763:36954612879419/97805412326212317804
+qsub:-563/827856356,2261/803220213,9777/7547919848:-2323996200835/664950958599723828
+qsub:75/325694386,7497/1661300549,1948/1110250407:-2317133270667/541076262268017914
+qsub:3501/918304436,961/56965645,=2:-683053839851/52311804503101220
+qsub:1123/310344294,2131/431751558,2307/53942272:-4902408080/3721989790303057
+qsub:1405/9784159,2196/25867783,=1:14858221951/253094501849497
+qsub:794/7899253,-2407/48403717,=1:57446053269/382353206723401
+qsub:1229/5474993,4511/2921328,-7447/1108510:-21107381311/15994250350704
+qsub:-7372/331741,-1691/1178944,5486/4648811:-8130201137/391104061504
+qsub:5538/47579,1604/905061,-3007/385287:4935911102/43061897319
+qsub:6299/305054,917/272126,5357/926074:358596789/20753281201
+qsub:-4585/61734,=1,3775/46277:0
+qsub:419/11735,-8692/17091,1813/23231:109161749/200562885
+qsub:-1997/1968,4543/2391,=2:-1523939/522832
+qsub:2071/1736,755/3768,4076/8723:405803/408828
+qsub:838/393,-953/227,-1542/517:564755/89211
+qsub:30/29,5248/27,=2:-151382/783
+qsub:391/83,-375/8,1924/15:34253/664
+qsub:3263/21,607/4,-2267/41:305/84
+qsub:9453,3109/2,6826/5:15797/2
+qsub:-3878,309,8605/9:-4187
+qsub:11222/48066783055662674131,=1,=1:0
+qsub:44095/11229138978726519749,=1,=1:0
+qsub:32172/9931355060831305057,-22127/1443489042124973960,7360/8565719299009119553:266191022894258949237359/14335802203762393030456814478941315720
+qsub:64044/4464944802393435647,12647/913738015734848205,80458/8255357897052863503:2051280563852837813411/4079789804104601810582916593980963635
+qsub:41455/753918793466056957,=1,38552/179247636782332451:0
+qsub:70832/329222465952924851,20242/279519391122527087,98212/275893153651362115:13134796356171733792442/92024063227018458748454302122939037
+qsub:16550/9390796490643017,=1,=1:0
+qsub:-52475/54547572128706592,17578/797685580288227,7736/4761258128626551:-1000695773704029186001/43511811726801235561284074892384
+qsub:-20996/6762826792669,-44673/3665405594824492,-89646/5844908573159699:-76656740107626131795/24788503162677927378327249148
+qsub:45185/5494693252958359,32663/2723960065506187,40281/8753885671043431:-56391030161481820422/14967324993264855317568567867133
+qsub:12788/20397625645595,85276/411854703134143,=2:3527370019125661464/8400858054907910680262050085
+qsub:5182/89854258440697,64615/978522088368546,=2:-735231447219831283/87924376618197880146621116562
+qsub:14899/24106539570023,26806/37583148137177,60169/20330813693322:-86248575618236415/905999647734893551001045071
+qsub:77/5504614030045,39585/32999174301133,41462/80693310429705:-215359209958144084/181647717837917119539540985
+qsub:82526/6888246953501,26067/1462753317193,18855/1955140329926:-58840753082241049/10075806080878164174842693
+qsub:48233/7425592622352,-67581/3978085226579,41398/5449697074565:693703959744755419/29539640309572506699893808
+qsub:5505/559716521882,37907/205803582655,=2:-20084225472465199/115191665474511303156710
+qsub:21476/65447686805,89325/499062486437,-40113/803762193086:4871751334864387/32662485308453336363785
+qsub:21526/16385258133,59161/53875727711,=1:190360658300573/882767705647956223563
+qsub:-19280/22598967893,14123/12257869757,=2:-555496952467799/277015205075018712001
+qsub:10456/7458705583,-25903/4591932494,70435/2217009577:241216096873713/34249872529756914002
+qsub:19521/861174313,=1,-5154/2978985245:0
+qsub:682/74110691,2034/18404407,13571/194261092:-138189339920/1363963320215237
+qsub:17065/678911302,47417/43292069,6893/55518891:-31453158049449/29391474931063838
+qsub:66870/71491241,=1,54717/26772383:0
+qsub:61950/53770049,38657/31651038,=2:-117806980093/1701877864160862
+qsub:125/24174,61922/4089943,14863/1071502:-985659553/98870282082
+qsub:10528/5066181,69178/5064619,8499/4855615:-297147960386/25658276550039
+qsub:73667/793622,-17081/241311,14485/728923:31332514819/191509718442
+qsub:-88059/511891,4080/46861,49511/313693:-6215048079/23987724151
+qsub:96249/64877,25429/18718,15172/33979:151831549/1214367686
+qsub:-54470/35523,46889/71763,-69316/98395:-1858189519/849745683
+qsub:44983/9496,84144/9341,30612/1481:-378845221/88702136
+qsub:43297/8081,24282/8963,-12747/9001:191848169/72430003
+qsub:-14149/568,-11037/95,10139/463:4924861/53960
+qsub:32022/65,=1,=2:0
+qsub:-5464/11,57106/13,-42349/21:-699198/143
+qsub:9122/11,30683,21590/69:-328391/11
+qsub:80394,-42819/2,78542:203607/2
+qsub:78738,81991/5,-92741/4:311699/5
+qsub:519349/84038265230060350539,362530/8834704951888139441,101653/2801162463496519815:-25878097111795625550359761/742453277976103030839734354712971508699
+qsub:-45313/4045263795932519300,=1,-897976/3871830745560558349:0
+qsub:-219497/3880705578320077638,=1,1955/195812018697132227:0
+qsub:-694177/1567385155785412134,749667/2535436916491658333,-965299/416081746175083596:-2935058919961612464886319/3974006186339362871680339779520412622
+qsub:26135/62576945582816088,732203/950441429248291026,=2:-1165513362953922339853/3304206755429125252534073692157016
+qsub:344416/442049470250620209,200643/69700793670676003,61742/228330350355985637:-64688063306615644345139/30811198918170109145079107043144627
+qsub:497397/42178943629236355,-221769/8144580724357867,=2:13405072168265547184194/343529811256455471792784946654785
+qsub:48033/18607268489677754,110044/5810062497436207,44420/6136363607606977:-1768543521738745430345/108109392831603170896668602039078
+qsub:556572/2349911949088169,-916879/8313100022391424,574574/9350618406931231:6781423623630450943079/19535053076582732528599605462656
+qsub:284777/1927882721172702,160787/3581064945969006,754048/423838688960001:19717401473028344033/191774256464747287423446257617
+qsub:892952/185949909151557,=1,175057/59061216301442:0
+qsub:-661714/491200735750687,450275/303031578402964,15122/4784925303203:-421695649161479509221/148849334267227909475125836268
+qsub:187069/55339769759630,621163/52226505565130,637525/3333974030852:-1230252861681887286/144510139666216453870485095
+qsub:219295/84834684101354,903655/27591730927967,=2:-70610557827760525605/2340735777083639503901167318
+qsub:-81292/3037742698087,279570/7725479008867,-183321/5178790607504:-1477281365692998754/23468017448410123176937429
+qsub:17070/729776002573,=1,494590/5887202393519:0
+qsub:480492/747354949451,=1,=2:0
+qsub:-199046/37296461289,419244/37303053961,-158450/158465916423:-23061341295366722/1391271908017914615729
+qsub:189316/25281354931,=1,=2:0
+qsub:-322219/71926874588,364328/31410801333,564494/88472961545:-36326131359614791/2259280768187274225804
+qsub:865470/7987112681,-75379/665073758,-53389/213996667:1177661952117359/5312019046322125198
+qsub:508019/5416093157,978840/4026946153,=1:-3255723468096973/21810315502870775021
+qsub:-355411/591634303,88/18167855,-400943/223386928:-6509119332069/10748726229930065
+qsub:-448810/805205621,80689/395020417,609682/664304967:-22023668155149/28915696379833087
+qsub:-295343/11433941,-409495/43207522,-681896/44977613:-8078897500251/494032257304202
+qsub:24193/2785136,19643/9724857,=2:180565038953/27085049325552
+qsub:260123/1810064,259343/3327309,989234/353681:396082171055/6022642237776
+qsub:81657/9557416,=1,74075/783308:0
+qsub:-379579/856742,338617/650312,4129/163380:-268476092231/278574801752
+qsub:625321/775536,-97485/252179,=2:233295951419/195573892944
+qsub:947687/23575,-30577/320,-279954/24839:204822523/1508800
+qsub:259621/46980,191999/83022,85242/3763:2089023607/650062260
+qsub:-109983/2035,269459/7712,=2:-1396537961/15693920
+qsub:495239/4609,169141/85,150340/2337:-737475554/391765
+qsub:181604/763,478129/150,491042/65:-337571827/114450
+qsub:88196/477,143431/288,-238297/503:-4779571/15264
+qsub:-570,200993/64,457558/27:-237473/64
+qsub:404456/75,=1,-923061/28:0
+qsub:-139593/4,318475/9,155531/3:-2530237/36
+qsub:-14344,290960/3,=2:-333992/3
+qsub:3264013/82557280791246853782,1806333/5633889739728044851,-2296597/13263726327210302219:-130736851332456348274354343/465118617189652853731071620663934976482
+qsub:-2980063/1992165262437351098,7376362/30250769500070022259,7703450/29762987155235234457:-104844131048250074763167793/60264532160038812168147102169858090382
+qsub:4464355/431626495996272004,3629338/7179109931450482327,3949813/156748150199903165:30483576874294500186500733/3098694064084008191204928519686873308
+qsub:-3555443/3617243579662686774,303530/2167413807252149777,2777975/533604037161157073:-8804058192833020476098431/7840063678755098878650516823284949398
+qsub:-5552437/989682869077264596,=1,326173/620111908036849741:0
+qsub:4895607/926011931053273421,-1175537/233388199725215284,5091515/239597642395083213:2231138191686733898359465/216120257512593662347946882140166564
+qsub:-2773250/45398131003067227,=1,2736089/95411568076119212:0
+qsub:4006296/68939728562838647,2292964/17013091088520595,5733592/97158552976704111:-89916836988785049713588/1172877881657458911248848921434965
+qsub:515144/49193197792111,=1,1856594/2763661324543529:0
+qsub:8325234/9817785169298149,775935/6180815223492473,=2:43838769910997775719367/60681916035376625680601994332477
+qsub:8627988/156641134252337,=1,3184877/121316717056413:0
+qsub:-3680933/800181047302935,-234725/6902800483321,1839349/73481955705762:162413750236709199382/5523490120067003681501847135
+qsub:1566629/16292772606875,7730144/88872981722417,=1:13285512072409282293/1447987282098298252715816875
+qsub:-7275809/32705732310204,529237/33225169211346,1246554/16046220459869:-14391614934727197959/60369638343750779183798588
+qsub:672357/665582539507,3252537/4040790284267,=1:552021796858428060/2689479459017642288036369
+qsub:-9287113/8904358895491,-1605430/1566913557651,9964765/2264645576736:-256778369548735433/13952360675535131712451641
+qsub:-7651618/4395153917,-1710285/172432083914,2275814/176521974301:-1311867471236936507/757865549031089791138
+qsub:1899605/130650302531,-4840329/426407852458,-3076004/154973753433:206056705252578827/7958616417890244567314
+qsub:2052129/29055355967,2964502/48925195457,=2:14266151553094519/1421538969758186241919
+qsub:2602385/95672384206,3573881/34551770887,7452346/64314906595:-252004705858757991/3305650299298749410722
+qsub:4133338/19957331,8985416/288073487,-848120/288429411:1011380169324910/5749177932383197
+qsub:-1320449/3975283846,-7547086/2795237793,1985723/1567287621:26310840111643699/11111863644241591878
+qsub:3012/50622749,=1,-3880764/539469199:0
+qsub:3415313/456078745,973889/57988958,2014841/282103745:-246119630775451/26447531188497710
+qsub:2670463/29405389,-1058573/52085339,8775931/27268718:170219721491854/1531589654491871
+qsub:8583563/83502235,=1,=1:0
+qsub:-2291635/5535573,5441924/9510935,4978191/9285940:-51919759091177/52648474990755
+qsub:-4162723/8479109,344312/1648925,7433795/4104773:-9783477000783/13981414807825
+qsub:8751329/789348,=1,=2:0
+qsub:8924261/337441,670861/129305,9868269/414227:927575561904/43632808505
+qsub:2681459/27003,=1,4549337/93154:0
+qsub:8680180/14441,4554745/21934,4059413/27440:124615995575/316748894
+qsub:-4518181/5562,-2276489/226,3678862/4781:2910180728/314253
+qsub:210295/1363,9437631/8144,1068488/1033:-11150848573/11100272
+qsub:5745218/207,-7575883/59,=1:1907175643/12213
+qsub:379339/704,=1,-7001184/173:0
+qsub:6487539/2,639662/15,=1:96033761/30
+qsub:402577,2061668/19,=2:5587295/19
+qsub:-3105019/2,3111189,867043/4:-9327397/2
+qsub:1261450/7,4029231,=1:-26943167/7
+qsub:56324553/19397300916635452498,-35924092/46902696457421385061,84175915/39224029534660703473:3338603835139839372201484549/909785716986214223068528185651632332378
+qsub:71555823/5836071212068629344,=1,=2:0
+qsub:77442257/5545018942084673068,42879535/9528293896880000587,=1:500124750930929791835741479/52834570143949387832940624231543090916
+qsub:1882546/587096528196767501,600949/3758491116151436011,-57408520/7215298889224654953:6722717345223102023805557/2206597085550901708728088609445878511
+qsub:18533295/259544696596588724,29260803/65551904123652131,8066314/468460265894896593:-6379593459872191703783727/17013649067101965587047139053170844
+qsub:32814976/324705085482999809,15878615/126957830524485142,48012589/448457761496522203:-20198956719461136022407/841303126799778581810770681823222
+qsub:73425587/76876862799514627,=1,=2:0
+qsub:42901263/91461268846245118,59358212/33469972365725591,25272929/7921365826117970:-3993073298899687352887583/3061206140818023006999579911414738
+qsub:-63644711/8497399665364222,7797817/1098486658784562,56710153/9438426287422742:-34043508375517625313739/2333570041690749863451890185191
+qsub:25665970/5646791945789527,18692206/1353307528791823,8000643/4532947645247332:-70817047855093605963252/7641846053757994531550156637721
+qsub:-29275899/499819621292276,8512344/446435883937597,42654021/421680780818527:-17324448402522389929647/223137414440972214604482100772
+qsub:10506641/183030842318251,56266904/341432867278395,19138129/13903991433546:-6711266271665423143709/62492745293100236702806487145
+qsub:40020635/13147436598409,=1,95925753/47588135567153:0
+qsub:64062683/28830327884364,35024477/22435119389260,-3892716/40203147434419:53435848201618925869/80851481014652251447941330
+qsub:687674/747723187903,75114792/959745497435,-6008972/779187819521:-55505079707707644986/717623962917648709528805
+qsub:11227721/638144654215,83818613/2696629423889,5802172/903741356827:-23211396997849476826/1720839651253640565542135
+qsub:68154693/605106523822,7149707/547148784630,-89487120/164245654829:8241105773166237109/82770824770222860613965
+qsub:5295524/207408901727,=1,-20716229/60404143771:0
+qsub:-49715976/27289320239,1751391/3004904467,-59390244/46731089623:-197186028226367241/82001800287564607613
+qsub:78299509/99826075029,4177685/5327015769,=1:20274296809852/177258358612286710767
+qsub:-1671167/695155932,-66109555/7854377639,8291158/4963791901:32830472604295547/5460017207919004548
+qsub:35734579/4659787581,=1,97009779/704152619:0
+qsub:30397277/925127047,-10856719/255060817,82870995/232582799:17796998694774102/235963660436617399
+qsub:5543155/496322152,-87192627/129840895,=1:43995360477497029/64442912424006040
+qsub:4832663/6516999,1014585/45500272,66517292/12541481:213275431553921/296525227123728
+qsub:-61572274/59677033,88452583/75989018,9276799/22909073:-9957404351913171/4534799134823594
+qsub:10222701/4964078,=1,44891997/7795153:0
+qsub:-12931066/33763,=1,-11768212/629261:0
+qsub:40097296/352421,81636923/466815,-2827835/59378:-10052546808343/164515409115
+qsub:-58131798/713399,-10445579/899533,=1:-44839605037313/641725942667
+qsub:82683100/20953,11064248/17087,1257553/185:1180976941356/358023911
+qsub:-80145609/17039,35705967/4424,=1:-962958145929/75380536
+qsub:24043257/7198,56987892/9335,-75350352/8581:-185755042521/67193330
+qsub:14613190/1321,24976151/4199,-77272282/6003:28367289339/5546879
+qsub:-95371537/443,32446316/271,28275075/223:-40219404515/120053
+qsub:94947713/221,57161945/491,2069553/455:33986537238/108511
+qsub:-18909223/59,-948326/3,-48280688/79:-776435/177
+qsub:88798812/19,23507525/86,=2:7190054857/1634
+qsub:-47127907/7,27516609/8,38296261/5:-569639519/56
+qsub:31326068/9,51645326/9,=1:-6773086/3
+qsub:898471353/97040476457400255673,774658681/12204618595061363031,=2:-64207747314147492788222196370/1184342003445601583509560261503270224863
+qsub:249093288/12417260530710049873,-801966629/44332144897015616603,=2:21001068305718331000060348781/550483793071430964691988116237976841419
+qsub:-134206127/1610240404875467236,97309922/1581131192036203833,53593907/846433764211142925:-368889861761752296658200383/2546001330825606997121589113609115588
+qsub:421338764/3148326051373083753,429845640/199253189241064703,=1:-1269341134003247764575839828/627314006506815051070753494111070359
+qsub:52740675/795085501889262583,149708345/329574924655249317,2466699/30866271646478867:-101648930631943883299486160/262040244379634804277810209144405811
+qsub:-191594029/598205858083829268,446816852/164644010257658459,56048321/893326266268239982:-298833267632957457898965647/98491011434545366397536822011978012
+qsub:-575491297/25955098472036838,-138975931/6423674226330072,-340643144/90343407636590953:-4979702092675981002067/9262616505371226069222196177352
+qsub:-473218836/46012936562560027,926673527/60598178499774699,=1:-71315169705438365692335593/2788300143116822172490338163356873
+qsub:-16401255/53884896854597,845057173/2931801378584781,=2:-93621040622862865174436/157979814883206214102194088257
+qsub:-78818865/905572899138638,481887257/926039606509552,=1:-254686715554792714417223/419298185592029277399259635088
+qsub:116637517/435071997593711,431546961/511014413627938,-757699852/228015168261633:-128150546020991644612325/222328061736285879181642697918
+qsub:-108955903/383831042493702,422517039/842122710676085,337667995/131589026243929:-253929395929242726868133/323232837946423896536774516670
+qsub:-838736295/92052976509482,-126995685/98224611661102,=1:-1039620824328469286940/132968645145476678498140723
+qsub:692740952/65411481215877,935265461/38090055601935,-384913949/18100942097057:-11596852584880885994059/830508985505893916304640665
+qsub:-860091341/514295231452,256640967/7499412024638,-53504958/4042771540931:-3291084285252876276821/1928455921482556068257188
+qsub:563680440/4169101815059,=1,-402824439/859095166759:0
+qsub:987037827/249183535720,-9882433/691842226,729392866/51288203029:1572707021916944831/86197846017537656360
+qsub:427594973/45174550465,-168845346/330313786895,27534398/79447419565:5954721095702106589/596871073414937326247
+qsub:242570638/16753352417,33473267/19130627213,798544080/26148870871:4079739009798235555/320502139657639523821
+qsub:-376284203/51060506886,29964175/4314022267,946743721/88569137724:-3153284394383157251/220276163670510830562
+qsub:74562538/3217746607,101790049/9743999086,-125780219/323630553:399002717325726525/31353719997587601202
+qsub:42296349/1360874,206369290/316181321,=1:13092472899137569/430282939034554
+qsub:140753986/202352937,938572056/619643731,-19975553/199697682:-102705487079566706/125386728861487947
+qsub:285566114/446058601,342294325/851420566,454403609/475658768:90453534672561199/379783466532588166
+qsub:-161678013/7988168,=1,=2:0
+qsub:4509787/2436277,-428747855/91437693,820266458/82427847:1456913057137226/222767548388961
+qsub:234853231/269701,164588489/2987771,26310281/83858:657297992766312/805804826471
+qsub:-31992898/7754101,-108145397/2546307,471535535/4631202:757106590895411/19744321655007
+qsub:-668796933/155882,935009291/130380,48837623/940728:-2840839785661/247852380
+qsub:456817877/484064,62463895/102249,201875360/879883:2353235462299/7070722848
+qsub:174324995/23089,=1,-75895555/10708:0
+qsub:-40050163/4536,-337645492/6227,218198970/84373:1282167586711/28245672
+qsub:-486371763/6677,832463275/2822,668314177/8066:-6930898402361/18842494
+qsub:323293648/4923,451897472/6255,1266843/26:-7499610608/1140495
+qsub:-867092722/717,317941119/130,-414616612/433:-340685836183/93210
+qsub:817008963/673,332237585/116,450682823/188:-128822854997/78068
+qsub:364631942/71,-521194704/91,393312056/29:70186330706/6461
+qsub:-366929570/43,-318888401/38,12434704/63:-231122417/1634
+qsub:-960895081/4,-86364312,369915274/3:-615437833/4
+qsub:-88689682,-50232394/7,220772295/2:-570595380/7
+qsub:5045827429/82586019977510276867,=1,=1:0
+qsub:1503080467/4197901399132742687,-5426267647/98427189918387234069,3137956632/34196804706756691007:170722923135437211172114777712/413187638271101955385621594687817003403
+qsub:1357458555/213194631658339198,5860802023/9743688404730714679,5343163284/4333989766915232599:1711023093391439556544861613/296757437205742197184000936677098206
+qsub:-4868419043/1874304123005359675,-6816693713/4442416679029074571,5495574701/476000389079390237:-1264426975083621632892461754/1189491413944567430701990198321617775
+qsub:-1647705544/574150473752043335,=1,1879152786/115463808794482409:0
+qsub:-6055562447/487155696631523136,2938185647/317996041759500124,-4728956063/923230126390049652:-839249691117625070582468105/38728395812354051261713195025217216
+qsub:1426529236/11670702563243101,9841949531/91619079682399779,1403083816/16150846549726251:15834830123605943657503213/1069259028091357016655804645674679
+qsub:6837809671/96275996695534461,3411015807/98409047856427193,96187735/946145664954649:344503392583431867018558476/9474429166236077065902521068997973
+qsub:-1004764769/8655312988255579,2879315998/2504870158905897,-1660768037/5076443781115095:-27438186441369551619395635/21680435220272026384233246249363
+qsub:-1613849677/5578341227875998,-681199447/9468113018720909,=2:-11480148177455803120623287/52816365202520317549788821842182
+qsub:7085065306/241255838198475,9871968965/122428691848806,9976645636/596673705145837:-504751623414488774067913/9845545557175498481373256950
+qsub:277829246/34194391207887,945644619/248861822737406,507960871/53401800544381:36805350523599913065823/8509678523390688833157121122
+qsub:8778198607/68845960402604,6712013093/80288466242958,-1204808691/92342273421469:121346557454831419932667/2763768283874247206479931316
+qsub:576607227/41894800028798,=1,=2:0
+qsub:-8197300862/1066469371293,2407397879/7628604144700,=1:-65101379433675314418947/8135672666041382998097100
+qsub:433828061/8105976668621,12288275/146073601224,-3529694919/6043133675158:-36237643265303572111/1184069203423191947992104
+qsub:2306893742/244897997045,=1,9806514683/82914371649:0
+qsub:-6917120851/658194979071,-9884712310/347680431211,2627577543/430392157826:4101120451789026783449/228841514144320400184981
+qsub:4348960295/47252752559,7472787551/90699413377,-104990832/2615837561:41338366482986273206/4285796937549835581743
+qsub:92405095/21190566348,1628334368/828240675,-4846323983/71007937340:-11476264601192136313/5850296325233268300
+qsub:8741146531/1488923836,4234232059/588146433,=1:-1163374887262484401/875705243152076988
+qsub:-7225160297/450834154,-10918713/11024261,3391394031/6088513222:-74729524142841715/4970113381410194
+qsub:2938592113/331333420,3934937063/187151085,=1:-13705735495420961/1127443800904740
+qsub:-2273685624/814502443,3041871576/168756109,=1:-2861310168939737184/137452263051674287
+qsub:3296666020/58254199,2646013137/43895953,=2:-9431079168795203/2557123581356647
+qsub:531031879/25049980,=1,=2:0
+qsub:5011008152/8879109,=1,8455979085/128459:0
+qsub:6770210010/3190157,-4380377540/4239579,3903233564/5705791:42676932255859570/13524922623903
+qsub:7663675612/749679,8111469146/393203,=1:-3067617836238898/294776031837
+qsub:4928169857/385836,=1,959097302/535523:0
+qsub:-1033483668/35795,-5074071593/2166,2441844767/6292:179387867046547/77531970
+qsub:-7344953203/83791,4312882738/17085,2299543269/590:-486869282973013/1431569235
+qsub:1418881373/3187,-364599262/733,=2:2202017894403/2336071
+qsub:-9933599930/2319,-676583006/3991,152888566/817:-38076001329716/9255129
+qsub:3939072211/317,-1768855994/157,3228818149/267:1179161687225/49769
+qsub:1276721019/328,1232959715/379,-1601655315/2:79466479681/124312
+qsub:3256070519/2,1845522973/18,5526750176/99:13729555849/9
+qsub:5966979829/5,27542839/7,-425197375/6:41631144608/35
+qsub:3307015390,1197592867/2,1660312324:5416437913/2
+qsub:5489019241/5,-3873449097/4,-9097250437/8:41323322449/20
+qsub:-36147389137/7366455075149766236,36459659324/31660854497077511625,17927437097/85118037223370314774:-21090084632556843838855432867/3481018840202610972909309235691380500
+qsub:-43262536631/6771439507252414257,9845873437/16005003509293583369,35333513871/31102122701082443005:-759087786974806113821731281148/108376913076544103155525491523953691833
+qsub:1879439977/100949624469036789,38241797291/3160034691975528111,7272414554/1249028818965241647:692866817752736748847051616/106334771821352635019895345254225193
+qsub:-23480972450/1429132014458260453,=1,17730739651/3229879048891135949:0
+qsub:87672655831/185695396976817387,=1,=2:0
+qsub:19335279285/86985857831839459,35182894985/296532209461553487,7819401698/300283568935056049:2673118785659508665734403680/25794108614783931312606692925643533
+qsub:105573770/9591706978551267,-91012289917/82779886875572184,-95699623013/92086977963850524:293900867022815896407896173/264666806209370051637912001052376
+qsub:81888799513/62677875753838689,42525624315/5887466452325273,7440075611/13710507286638085:-2183298237216013854166130986/369013890803736912387239799887097
+qsub:45845595582/1944435405423019,3957631182/8503827262812577,=2:382167667398204481110256356/16535142811414295102976398509963
+qsub:70073122775/9889502421893828,49758775289/4581689842004485,97971868835/5554125313499619:-171036213915285631762370417/45310632788869704568457369818580
+qsub:35007906083/96744217462517,41582054123/195125002566641,4259598485/79647205603988:2808094477684438458969612/18877215680681304677212095397
+qsub:53616094879/804153146230066,-40630189441/409120361012696,=1:27304165381945598904758445/164497712747569959659181458968
+qsub:49936923088/1008159757073,=1,=2:0
+qsub:-54774651067/87557778501674,14552025462/34442391625465,32721932085/17018898896738:-3160713005350324584244543/3015699297010375993083528410
+qsub:36944437609/1522384186532,-31109095589/1913990492988,-90340980434/4550319003301:7379456095901269524565/182114303731094876877351
+qsub:37427798265/3644867199671,17190258551/4857734158151,15531453562/538438754347:119158084549871401271294/17705795897765998009168321
+qsub:-1297758412/359023140343,-13169443469/334495854946,62942721054/868305110777:4294040141274688464115/120091752274429528686478
+qsub:64548705326/965177946721,99400187824/233208667431,-40288901926/927917471935:-80885551634177312487598/225087862788593125943751
+qsub:22792905511/831110170,=1,2899870693/1104812470:0
+qsub:-4225625539/18480348712,12201952952/28791900419,=1:-347160135247248998665/532084359824298910328
+qsub:-2659312874/1644066659,16956954950/4918000213,27389168623/355474397:-40956865552225654212/8085520179148198367
+qsub:47019333517/2453731385,25608075613/4795411666,-79908243099/4320471629:162641721633895395317/11766652108859337410
+qsub:79879022561/451475806,-74196589329/217100545,-15269666465/326484577:50839744301821669919/98015643536914270
+qsub:-96216336903/275984570,5409672454/132808555,14083109727/56233823:-2854267759507727989/7330622388799270
+qsub:63979921573/4858216,31476961600/87404319,9515612291/12422366:5439199596284968187/424629061034904
+qsub:82582224886/74464385,=1,10918064727/56241685:0
+qsub:-46341807304/5147537,9784020329/2675947,44710947790/4319699:-174371826881996561/13774536192539
+qsub:-18674665469/1251399,-11269265668/7443487,57599246809/9830290:-124902281860180871/9314772188313
+qsub:58536600266/32903,83073082013/333030,-39859237469/373423:16761090369112241/10957686090
+qsub:35519852107/330820,53390770345/780257,35509809151/171706:10051878599918599/258124620740
+qsub:-63435900802/6951,=1,62381742036/76259:0
+qsub:-81473653859/71229,11757463559/6248,38764522219/56443:-1346519761155043/445038792
+qsub:44117486351/5857,-2571472421/106,=1:19737567523003/620842
+qsub:32241620201/9076,32252415098/1479,=2:-245037563152169/13423404
+qsub:-3547397518/617,24052413914/841,76689146655/466:-17823700697576/518897
+qsub:-7334508913/948,39473373047/321,1323910388:-13258378336543/101436
+qsub:-3196198423/2,-20901693416/31,16678712262:-57278764281/62
+qsub:-62722671643/56,=1,=2:0
+qsub:-24012149879/4,-24290006742/7,57308122924/5:-70925022185/28
+qsub:6872078720/7,-32246825481/8,58358089888:280704408127/56
+qsub:-959881635801/62932017065985873602,-493229779705/99840110881639578512,-80856942953/6609275501579816959:-32397372018886953016823147330351/3141569780936631939917776357106693620112
+qsub:-332008736903/30374537863168416351,682789260493/54319888411218401110,959961568525/17615592824200222523:-38774085785529920230015532683373/1649941507269636595870960818509000549610
+qsub:113948825097/9684396113323745389,=1,10627090663/610867879165779530:0
+qsub:163071738121/654459680340198322,272886493781/4350646667188036069,-795490699161/9312605941419401831:530874306479618083947510650867/2847322827081031281338460249149276218
+qsub:76846819557/104316101165717458,371275948758/843864366174376699,-256575092889/873170706343972834:26118233246947241582284285179/88028640591990321004129490292711142
+qsub:389764163769/207967463890639277,143006030005/867552974642992847,452774579891/377044461928347543:28036405300529641258282732178/16402071993389391564815603942568329
+qsub:580979558458/78741205846222619,33032926279/1750557646838547,12997506366/8714829535529515:-1584014239122301048375024175/137841020015393107847327312494593
+qsub:224741963637/14683522164236398,-960061639375/75273715504183749,=2:31014248993459091498049306363/1105283269990107068967870865896102
+qsub:807804997047/7249998154317344,9105704912/112491433689913,26073756553/3602151159257410:24854798453934594011093183/815562686628381139953493751072
+qsub:191337323199/6659274625984151,83413589251/1210878215905176,-306099086431/1081677916528086:-323787801810171460500982877/8063570578334296950020294865576
+qsub:-331867978975/508606776667332,85749318495/2137585782677,377450159524/218818801378045:-44322080754745095885121415/1087190614777265014877407764
+qsub:262259669890/904860545418883,782901326213/392394092067508,308978360414/335667028727945:-605507375993851106638145959/355061932167352680139373953564
+qsub:815877865693/66519087957156,-546996067745/51276831144013,29432156288/2425613695755:216679532121401094151189/9448443326960766943517748
+qsub:-562619974684/10325037296475,556872690819/57561686137409,595241901749/85716594322193:-38135085699491971638916781/594326556216735906721333275
+qsub:569774646278/5879076793409,-721915496161/392079169147,-50551273318/7061973297467:4467593410196183185587715/2305063544511209685752123
+qsub:-558695968419/8022121294387,-777164712527/4870971993346,733030717073/7075271044115:3513117174644727699545975/39075528152183639071148902
+qsub:230578421654/363657556093,=1,36043149487/191906623355:0
+qsub:-442745155107/891737442305,209381515609/66199123967,267993885312/121209167453:-216022678603831030588214/59032237489164205223935
+qsub:191691349919/14156267513,63217315803/9723609341,-128345831172/10660892885:969010566700217585440/137650015023101638933
+qsub:4645100745/1355591564,-122150924616/84421443943,321940027501/7149085070:557732875097854576959/114440997229829696852
+qsub:444175516387/7975146669,-45314342690/1470525299,290828709372/1185708607:1014559863205550574323/11727654940000079031
+qsub:789307912523/3728805469,=1,424506863658/9402774203:0
+qsub:-502776486811/539515375,235504157527/997755438,=2:-628706087676449005843/538304399290859250
+qsub:5577709792/27083659,72210181067/64923595,840185174073/737144356:-1593590948783541913/1758368508034105
+qsub:185204908129/17512100,=1,397024789371/90565963:0
+qsub:-59165606754/7623599,=1,410439347980/15967881:0
+qsub:821602843151/5722683,192153300265/868108,739244189764/864319:-386392423858282687/4967906893764
+qsub:-321094052171/8002674,=1,63324198409/402344:0
+qsub:-787087016971/706048,314711556301/97333,461259945208/201559:-298811005526046791/68721769984
+qsub:264872646016/44135,-306557419723/722285,-978795728169/729376:40968690169428233/6375609695
+qsub:165112253012/26681,68785586791/12017,-119718397615/15426:148885703274533/320625577
+qsub:17528604773/6611,-99181928610/39343,-52006507697/18356:1345319627624849/260096573
+qsub:871912524148/5723,182323508186/1091,203321662049/9639:-92180873503010/6243793
+qsub:3526953029/731,=1,-108468202939/365:0
+qsub:313486413069/844,-262666586523/625,-366626397895/982:417619607193537/527500
+qsub:-428607477029/682,=1,=2:0
+qsub:90255143123/14,=1,347531313509/64:0
+qsub:32303888109/19,818375118441/16,4032541865:-15032265040635/304
+qsub:292300807915/3,141298658917/2,331142787887/2:160705639079/6
+qsub:-319866639686/9,263653231334,940025135092/3:-2692745721692/9
+qsub:8034198041699/17592454670005017397,=1,=1:0
+qsub:640259140119/57494394354649546144,-8575402433581/98527174739603547922,8981144595803/52261736819163067566:278060246721630225656578041972191/2832380119564115796138164460514727156384
+qsub:1236159983468/2961715085662590789,914344518503/2225413786553289931,-5038738670790/9117790154416123369:42939515651941188118242991841/6591041583476387621705131100927045559
+qsub:544927281821/225573104564678752,1983999095212/528108855513999917,=2:-159755912219641308519411726567/119127154086392326185226159659663584
+qsub:236180252739/93711559633857505,=1,-875119448860/197150931692089343:0
+qsub:3448258604904/101878636218756661,-9369719313239/333311169679336117,-325685803073/239541171961239254:2103917334342722557318697252747/33957287403409359538552421651625337
+qsub:-7939222138274/86505941453702773,-7521663898635/32404928066636033,=2:393398694553935776247333587813/2803218810143866461870349953819509
+qsub:31222491771/28663266692274319,3403082415831/7352452962268472,-4014317624213/42643848690867324:-97313896958642034025767600177/210745320099903543783491148970568
+qsub:-294177603665/4628696580309847,=1,=2:0
+qsub:-9743813636414/8886484266786635,-857487733127/2872659401368146,=1:-20370606598428196700274910799/25527842574094742730786067528710
+qsub:-255869133971/251203098733934,=1,51860449406/2731920492095:0
+qsub:-2551627469690/620119144262383,795142214972/32216229353871,3950813535806/548061345549077:-575286725704502987095668266/19977900578283148512980734593
+qsub:195247370817/63337336480054,1748779495123/30608951696454,-5591675662514/14668720736915:-26196679492456802179448431/484672368225006676058382129
+qsub:-5602181260057/40083459443536,117096388229/5768970730471,2776946949919/9603782260822:-37012448044623646265634591/231240304305780581099185456
+qsub:1645392691271/1862974141789,-9156882237455/3971219830691,81994652595/616265197207:23593250912635096190105256/7398279855937023607846199
+qsub:-5034167196133/6608304488230,=1,=1:0
+qsub:-2111179317912/94974899629,-2734989223771/337151252491,341842794161/202199642400:-452031424253078525037833/32020906365124361225839
+qsub:-3760876499263/10213162407,9612839350222/220968981509,-431780312153/723158370431:-929214539099496136632221/2256792095060796932163
+qsub:3321533964667/20955327844,-462499260819/4621872673,-7406461174035/83827773626:2276684609255051253557/8804805192358146092
+qsub:532057790509/3873792604,5011839386945/38790613612,6678622123429/35927572362:76501363831601540858/9391674507174207853
+qsub:556360173467/244347911,=1,3477739385301/4086080128:0
+qsub:377956900679/9728280520,=1,1041480439146/9369959143:0
+qsub:1811463975309/425739298,=1,7893909438664/413369383:0
+qsub:-8501443522317/437865641,543359387910/555098507,-9540116747492/861158281:-4957057013263567681029/243058563585697987
+qsub:8568564545305/64448189,=1,8670374182673/15999622:0
+qsub:2886469384143/37100146,706817551959/70885648,2821141489561/36201922:89193109177047996825/1314933945052304
+qsub:-5397172720924/583973,=1,5493925869599/2184027:0
+qsub:632128111787/9181877,8269779184000/4428251,-5293123430135/8227357:-533816593733572799/296785810271
+qsub:7690264089163/217441,-454719683537/54069,3844686753380/33269:514679591744923064/11756817429
+qsub:194395407442/487085,7382213747658/754049,=1:-3449181920691764272/367285957165
+qsub:-6820161889575/40973,1260560268388/12497,3951119679544/19667:-136880499010680299/512039581
+qsub:7733127302799/541,-6375441080647/51092,=2:398550053779236535/27640772
+qsub:8552562777105/6802,4122196848132/6401,6588275470270/5237:26705771375255241/43539602
+qsub:892706337045/1181,7525927198633/6084,3376981309819/6148:-3456894667003793/7185204
+qsub:-6525943779397/22,1169543393537/155,=1:-1037251240464349/3410
+qsub:5679159008921/101,2475493569771/410,-6099782991203/439:2078430343110739/41410
+qsub:3105196603053/35,-1561253366581/11,1543062844359/70:88801030463918/385
+qsub:4851198644302/41,5582000284949/83,1538859614246/61:173787475794157/3403
+qsub:7388598539023,1819068317039/2,-1736481275601/2:12958128761007/2
+qsub:-3766516642396/3,-2830365650207/3,2537215743415/9:-936150992189/3
+qsub:-3499529401917/34680274552088347393,49898319429097/81175729919276761270,=2:-2014564271063470770932585857648711/2815196600566690542230200403343687869110
+qsub:85499989069177/86185277165079792548,-54755717014977/95062349548332003740,=2:802935405911321108881332428232086/512060933986668223303815291051772508095
+qsub:10480741720249/6956596051054816346,=1,59792433694419/619860836842181132:0
+qsub:5440922563791/8096299805235361768,21427106892442/4734770642360508925,=2:-147718760937640942166837597622781/38334122629577497138638724698967779400
+qsub:36141945949905/51170764877853868,68289830259221/944862420318148725,=2:30654723677491802840116592104297/48349332752019923728004548840518300
+qsub:-65660705848034/432686937944828595,-14162742932711/370354589759953089,=2:-6063236635081033520164429735327/53415864465682424679265419115259985
+qsub:-10234488359092/9219723369459949,11490568299383/78007645593504592,=1:-904308201825094205011706861931/719208913074983700054297291585808
+qsub:8824638624671/49117783640687736,71425056890483/80617302142742478,31478624534929/82599814978820418:-466136988760823218273617123625/659957200723862808591316843474968
+qsub:2271907634573/5997198598392443,=1,=1:0
+qsub:87118386941689/6769664747763328,-92703763358616/5951838412401733,72544030367331/9826030071433516:1146087960619838557486271181085/40291950684819664403468341047424
+qsub:-38735368831/390121272239902,18518285294580/100122679213001,-3887528092655/74244322705899:-7228255307730681475045702991/39059986994643540045829365902
+qsub:33507643620217/383472784483096,94120308754159/452308027073903,8479974951625/419952955125076:-271906502553380052184822069/2252569072546560464977223944
+qsub:10914633574213/46775840995232,=1,=1:0
+qsub:16227980458171/44733418409925,=1,14382677933809/3568384653206:0
+qsub:19887329250905/3446066449222,-41404484338255/2669125822468,50077337796229/2478834856350:97882194184456020343960575/4598992472779525554359948
+qsub:-23925661872806/841256858717,91800998586059/100553852929,76785865874845/4626636784081:-79634037182778870157375077/84591618446941749632093
+qsub:29336106782491/175641800187,14997313674741/788809675295,41848999082110/169597375583:20506449693715551470283278/138547951373736740280165
+qsub:-6749631331552/100780901939,22080836367893/122987967423,28833497035036/165078850509:-3055450043045906849075023/12394838284534289533197
+qsub:25051511362687/10396488145,38509696040707/88706839049,-60514064785671/63433114810:1821874788029306610246148/922239600553351574105
+qsub:48606586904983/42071764992,29823112345620/42059865901,-21691164849293/4231585639:789675553193949088149643/1769532793781906337792
+qsub:-77589654827242/9817530799,8253947272810/520292243,=1:-1178666768036851921932/49592088544983419
+qsub:-13743493332261/1526967682,37506929991611/658645334,86046505206712/7222464595:-16580989426095086858969/251432534729523947
+qsub:-51679389983753/476057441,=1,66423598858706/714202649:0
+qsub:-27413822608864/942542701,-17319180355605/124314974,69101034128319/135803866:12916118386616536859569/117172171368704774
+qsub:16033466371942/6275041,3173224097293/838266,29304504765697/93980195:-6471801590959231441/5260153518906
+qsub:-14788927543191/5343139,16116445186754/71171839,-4194013841977/34472148:-1138667576905362979055/380281028662621
+qsub:-11863377566581/698789,=1,-4578191177718/4105669:0
+qsub:11442715386293/9531887,=1,35378701532975/8123906:0
+qsub:-15768066912479/362615,92363606714861/652333,67857319926071/827985:-3979859967466135002/21504157345
+qsub:-846557698591/239267,-53144962049294/166663,=2:1796392255561165095/5696708003
+qsub:27268730445959/36577,-13465608951811/44542,=1:1707135370154296725/1629212734
+qsub:-9770756513988/9073,7801336502379/467,4503088681454/9263:-75344469378117063/4237091
+qsub:-7026119147779/830,7101024857299/2048,=1:-10141671323104781/849920
+qsub:21638871622139/2468,-42476176597401/7406,-16930478429705/1639:132544343537973551/9139004
+qsub:24211191920307/215,-80284684935585/301,32429769785659/56:13276785305118/35
+qsub:28102057542845/404,10141824152597/778,49924151629427/38:8883051905342111/157156
+qsub:69683068555423/53,19160487574994/75,34686281737182/41:4210724300182043/3975
+qsub:4481580939807,28880719200344/47,12531106213795/71:181753584970585/47
+qsub:-4015047513343,-99632851064851/5,84319873837035/7:79557613498136/5
+qsub:54919395403009,=1,-97138101140295:0
+qsub:210307390461968/47213629337306710429,115035466737199/13799438784982683745,53333082063959/13664786811438045265:-2529117926464810402732988541238211/651521587857026504089626304754000276605
+qsub:-297705233604298/34583872960377931369,77978617195104/5299999273198438663,74378398780959/5075493209379777979:-4274640112431569633737006160990950/183294501554390171572563143412570119647
+qsub:504589485072677/8294597886664545269,246812476335976/1300669888373460411,681100309448968/2603298518001254955:-1390905895394928956894286988007297/10788533707350714724434632367288845559
+qsub:-78507045905186/4052782705070927105,-26333160825061/378849069158294234,245855933356429/7915638278155738995:76980257498111295165827733680881/1535392955316954446563765566755812570
+qsub:158467575315099/42867668947782517,394831131302747/679471751533163594,-48561231318802/281924646264500261:90748750733599226955741824631607/29127370104093594835779192094086098
+qsub:113675246712051/200230549051637699,388686281013415/708939569436428256,=1:2762013003465965719694013380971/141951359232687658393740425918422944
+qsub:73765282645495/1035056942801718,922427291192222/42055305183418997,-56658710176289/49777804321460907:2147456701619161856688029631119/43529635611742911300567485436846
+qsub:11558926182346/2193559666056113,-471907499361325/65178860043302296,906292398921179/61879479804047118:1788554888598395874379208496141/142973718470504311324402957735448
+qsub:272316495707495/5727398323662772,165581996805511/2159650095677579,=2:-360245704923343561937821381887/12369176337681911126512437388988
+qsub:-342373342517849/1018510666353060,=1,349084421810221/2519615499139835:0
+qsub:107181823655878/330213883798891,603343425900400/335568866158937,=2:-163265492894049375913454174714/110809498576332828976950338867
+qsub:186420967060580/27505382732689,107841057765734/938888436801099,150317703871619/56186192325509:172062280782312586790437698694/25824485797510315886178425211
+qsub:277369102524627/35009202732584,-58922735852011/29409493631158,-114354072702623/27524533096262:5110061429589788410990577245/514801462397924199102126136
+qsub:-208415718182346/82232835696833,-149287320962885/17528744477017,144393102539827/5550994994610:8623053867348966063892901323/1441438364550307853348187161
+qsub:885772499510025/2385708677677,1981679910892/945475145135,-927158264975185/51617668049:832748171571039374752920491/2255628258276490509651395
+qsub:199709343421874/120107420805,250421330523511/911998437151,-85756219123893/3387032230561:152057148961466103844594619/109537780064397502326555
+qsub:229005499534863/114476975336,=1,7933977177406/971528526457:0
+qsub:913313238746453/105012167131,998890143666531/308838539768,-340536941048242/129794732609:177170708293018948806450343/32431804354611205965608
+qsub:202747896046111/4130383286,-326610886734874/924106823,400325691919789/22798999151:1536388861680468580631317/3816915376197760378
+qsub:311867860118047/14615054044,78891545894795/49519747784,=2:3572653392028586160839217/180933447527102309624
+qsub:-187714403734023/740833429,506207386211644/6706938891,-756195691891397/5384742450:-1634004388516894022835769/4968724536712987239
+qsub:509320078163086/994171477,-149792211533821/1161942848,919509848550973/7287718870:740719966348074014332545/1155170437385746496
+qsub:744782913412383/35221159,-843622816486697/241699112,=2:209726742160051637325719/8512922853910808
+qsub:110124296861427/126487978,781814771935103/735468241,103648920994391/217349966:-17897246768566789251827/93027890687306698
+qsub:55559598357120/4133243,136581368630879/43479449,-46084945523102/26713943:1851176737404882616283/179711128223107
+qsub:245122390741101/24043876,-76258811060014/21938089,448115170340604/6879827:7211074221005454870253/527476691592964
+qsub:100716567078550/981447,=1,-106552246729921/451809:0
+qsub:-896329574019135/7303813,-344467277086635/1213327,261333607789282/121043:1428383703404051827110/8861913515851
+qsub:76900938369059/75326,993229733624034/890555,-908067780499933/8580:-6331507745706647339/67081945930
+qsub:995595550040069/769920,-34334285476045/592726,=2:308275010533383252247/228175800960
+qsub:10750797928613/490,364135307090702/81553,469882435848719/39098:698333522997732009/39960970
+qsub:318012047587094/63457,344774587461563/88455,=2:6251394672767996479/5613088935
+qsub:-161244027390189/3742,967621707258700/3013,=2:-4106668683088694857/11274646
+qsub:707755729590189/3985,-311896862542891/2746,890911807982825/5104:3186406230688079629/10942810
+qsub:-62494041004924/7,-6009036767325/88,277826134449449/209:-5457412351062037/616
+qsub:313000944443410/187,-424215294038191/492,-69562914630308/101:233324724651299437/92004
+qsub:-214477481502137/44,812058199759953/13,-233671238320360/3:-38518768048965713/572
+qsub:54243114068304/29,862438291931992/63,26733981451778:-21593394279724616/1827
+qsub:266687619713649/8,-362755079043871/2,389177566612001/4:1717707935889133/8
+qsub:653323126774499/9,703678334484790/3,-319996079506951/4:-1457711876679871/9
+qsub:2559305963434670/8990269372406324049,=1,4982250095086138/44081334052072166999:0
+qsub:-1992239658448600/48178503938440461483,=1,-140689209800518/56784446808413335831:0
+qsub:939937733606495/990699059564945896,1384063287837877/148639317667949967,1401228942153371/4899174789530501904:-1231478494265723021017590198267127/147256832228013279266729677589985432
+qsub:2427308943763117/3926876732707845738,-3053828283650605/3709355702828503657,-6851889315460370/7456794982130606687:20995759505827045845208479606590359/14566182602774409222023359782524863866
+qsub:1132187368153827/166386612794510246,3559319078115267/192456340011573829,-9701789017274666/34504738221262233:-374326408180256253543105561132099/32022158525354344242032513725951934
+qsub:1011380512372054/229809286711122957,=1,785057330967873/261864117017722910:0
+qsub:-6373636813888041/82626527312705989,2824358117452821/9660944401937999,8376921479245765/84777299790282297:-294942254029695997688528161214928/798250286493264100581508493976011
+qsub:-9564803757424938/80601591821040757,-5966553227630720/32402706800195057,3062333169701829/13649400405257704:170988156078760300221549229123574/2611709747406183624616884346938149
+qsub:-6645498550927964/1641651956201489,-2448344965334987/7285796471405420,97763428336761/717874275284599:-44398419591282543726427305969237/11960742029768613657228526670380
+qsub:9428078639060/796311207574343,487570664734529/270542984787885,=2:-385707284276751727768550801347/215436410917207812839223234555
+qsub:-8945032146859492/173832543857525,=1,3904355716222363/11348996463718:0
+qsub:-314682518932207/411979868553284,2079866721697896/66512597834021,4675528081388171/426553668427461:-877793570440583492839563904811/27401851312797413669226474964
+qsub:-8416034028506899/32609965027765,-2867068576526460/10471107007973,=2:5369813117494012224678656173/341462433331984537021370345
+qsub:2553878719400981/21754385300349,84746758238377/1863679896278,-358102168359771/6286290072209:2915998795206632613088155145/40543210540146072197201022
+qsub:4236427671394109/2859515833221,=1,=2:0
+qsub:5583901594900219/6147672416839,1662784468995713/977705344691,6565243303664406/3132796116919:-4762843781630684936693623878/6010612179352927527651749
+qsub:5880633088314980/144288094133,445227880160405/385441741948,=1:129552963472585426795492775/3271450255587089340652
+qsub:7123796066897691/646623152591,1738054940928918/811478311493,-465948486952257/36744411995:4656939438506791528261936125/524720664036825168028363
+qsub:-2868399842871272/39606511493,-7967653324405171/45882725248,-4382209264799369/87703483877:183960951073424117991854847/1817254684865073275264
+qsub:2456186256319560/3308343473,=1,3527461933566325/44562489087:0
+qsub:674305784927060/4912146059,-9009832420557345/1095083558,555087666246961/159683002:44996033995029100460532835/5379210383705397922
+qsub:9556395264243127/5642678959,2704206989021393/1653137405,3456993987111567/2767730221:539062590553413975895548/9328123651529361395
+qsub:1913172323114056/317852309,1923331312586217/68059942,5111100924241691/235015288:-481124901330381924280301/21633009715106078
+qsub:7396974207537751/994805053,=1,=1:0
+qsub:284214608834666/15371405,8605121290252485/36320753,7299109191726065/1345108:-17421416545731139652561/79757286323995
+qsub:7309254006136367/43026806,=1,=2:0
+qsub:3445238551293254/7474347,=1,-935490243888754/754065:0
+qsub:-4928287873457776/7482701,5635600141645415/1697376,-9526446027760/22031:-50534668372988554461691/12700957092576
+qsub:-8478337945368580/589969,6645220551921478/525883,=1:-8379087917520827410322/310254667627
+qsub:1719300936213092/194297,902706986884743/48626,2385654314953825/180074:-91790532106447099079/9447885922
+qsub:-2129417266022053/3839,6573034386134051/14296,9786617326073399/94956:-55676028243419891477/54882344
+qsub:-2187293709879460/39491,3573469347555406/99807,4017132988613391/36830:-21142770665073517798/231851661
+qsub:4464053162985503/909,4551500989123885/3361,84727686825382/35:10866368281680664118/3055149
+qsub:2535331877045977/3627,6763176539554039/4483,3870940332291032/173:-13164148504165384562/16259841
+qsub:2507736196654456/51,3033138651383092/821,=2:1904161346232770684/41871
+qsub:684175263169205/133,=1,2378871296865361/491:0
+qsub:-646739283957087/8,=1,1100407856892355/16:0
+qsub:4793571136533963/92,-5722502959595165/61,4757322618112904/15:818878111611326923/5612
+qsub:-7552421230993378,4948198001592823/4,5729503250754923/5:-35157882925566335/4
+qsub:-2755491483441304,=1,-7933615614234907/9:0
+qsub:321721693263421/1424970458268329442,4783029016817033/9976530684162778611,-1284537047056835/71620015235724957994:-400667633933462179077276150388595/1579584611215498321716283384428796118
+qsub:-47606652409415837/99944870827944430499,23322967894703462/17256392723432667009,17445922268336980/1262651123373099837:-3152530103785264263460897588705709071/1724687941699758103837340929139210707491
+qsub:-35800247390542268/3022381832969706807,27658822050080425/3538855927509428196,7414524545924163/4386817849214572582:-70095812989943154324914458022980501/3565257954933885823399042050112976724
+qsub:11270912894283697/4254771338147418239,21165198074272866/1790561357737218389,=2:-69871817037702583386330221699898841/7618429144094642739542804241664796971
+qsub:-22475320938058069/200115960226568483,15533995839026021/419448235219902685,-7677187468882297/691145254573545404:-12535834196951596319645500834511408/83938286356370387266153122748076855
+qsub:6144083459003009/341129592319435505,=1,28739569462221666/606069168271474349:0
+qsub:22546360696472435/24894286772021269,84274062567114482/52430302346827669,-1685672888973312/2330511345390725:-915830172852329009982850908113643/1305214982165707736650909145691961
+qsub:4376832304770209/939333180215946,3715739686394692/26867721681796733,88210818404099477/4648321047973775:114105194635987182911079063768565/25237742452519050348798217304418
+qsub:9647062281850006/4819913902499121,26298077512843496/1999760481189285,=2:-35820885167446167638178828727102/3212891114984188905357249039495
+qsub:-59102942672072861/9022665222289159,37341501938137229/6463207427444592,843867142853825/330321510152954:-718914448947247239109480525418123/58315356880045303166891874778128
+qsub:-48186053317977182/524586203313577,=1,-88203767474302754/222044585954625:0
+qsub:2980158547616795/16459590834659,=1,55614737163455091/802181444522069:0
+qsub:27674141753240653/30123979153216,-69911536707649590/61364291872711,15121999849118525/43270921417874:3804217786223168944052276101723/1848536649125408180638288576
+qsub:-8139585494164199/22694171735055,16416172833245775/23356807697711,-82721251840807344/24795330336689:-562666178636295181890388591114/530063405074508024821959105
+qsub:40963317287207743/9100834089657,-89978521261181858/4614790398485,=2:1007916716937791923695301312061/41998441775154099246969645
+qsub:-22418658716107103/2534171344870,-19948846211000086/637313996471,34428844071591534/7978524432977:36266069449253256094105625307/1615062867541388503953770
+qsub:8499094378194009/144881993257,18142016047956879/328774983548,51933573865337015/728907876721:165838167635160267022399029/47633574949471621935836
+qsub:10952289218891361/410721990889,11230753555935868/494713123343,3356713875262630/76566376963:805523747555915071545833171/203189558938352379221927
+qsub:-48383763418441148/36254620229,7147640525044487/65513778698,-83702869612157193/80045858746:-3428938161941039381724192827/2375177166462740081842
+qsub:-35618330302934381/40720985765,-70406046479991145/43883735712,=1:1303938222964954498988736653/1786988977243374139680
+qsub:19345365507179985/787013497,20346629715849781/1124536845,=1:5741504087980952707553168/885025674888796965
+qsub:25916947948395837/4727212922,65968479175889910/4243635367,38561855794849199/1001864541:-201864970286444028592649841/20060567943138612374
+qsub:-83872784258426507/338189336,72676607354297993/258443836,-31045469397994216/211178075:-11563714420907729197990875/21850737322533224
+qsub:29002323373127602/104867985,31657958092331122/399470525,25010437022653087/448628233:1653133413945169069200376/8378333804728425
+qsub:17927870354086417/3556758,1245879275137696/8208269,-3178672357614557/3197484:142725491384586358632605/29194826431902
+qsub:-62585597691019581/32367872,61984767454961662/87347591,-3097688625515242/23912601:-7473016208537687574702635/2827255644996352
+qsub:-64134232347614188/1287231,5681700507230407/3441090,-22197438767027251/8198005:-1333364483126750936947/25903378490
+qsub:80521535865700778/4914387,29629877920205801/5735623,-31675469441529533/5832635:316228486243991867655707/28187071108101
+qsub:-12089212581249183/367213,39065393509910584/485831,61520933914433223/513745:-20218634584515667108465/178403459003
+qsub:35626200118349978/22677,3226283532016027/401890,70294093126508565/985048:14244651133908145214141/9113659530
+qsub:-42445465189342283/64064,52962797531106583/66292,30509808145126571/40195:-1551700859841172689487/1061732672
+qsub:94842682855165703/29546,-21781294090030679/19071,-98420376085320606/98821:2452294919914911563647/563471766
+qsub:21298039427969457/4529,41390344046065517/4944,-47466303948648638/1437:-82159361252749731085/22391376
+qsub:91816424325919179/1700,99837657326420362/9975,=2:5969158521569033561/135660
+qsub:84285557657486063/501,22158640591353121/907,1409871428669941/18:65345521859071945520/454407
+qsub:-74339750859264619/932,17864819649304693/421,6794209676711141/199:-47947047024902378475/392372
+qsub:-78194010431589383/58,62126554703583997/90,93510406253215651/10:-2660200277912729074/1305
+qsub:71106157246341874/49,-1886317442316576/19,=1:1443446542354007830/931
+qsub:-39663070419423940/7,33868806617110099/6,-19327938437654750:-475060068836314333/42
+qsub:52313046276155719/7,90139156444699943/4,49168703277366491/5:-421721910008276725/28
+qsub:31764659627457502/35459829258840257855,125864014273474351/30437232401502771513,-438810788001077539/21929003917091975594:-3496288128734077196451731372945036579/1079299064068928704074589544922068484615
+qsub:40163813719117127/12253004736518941871,-39840230360733540/9868332108049144213,=1:884512383820142074541633838441289391/120916720061468118490436389825843042523
+qsub:616147121341955963/2895479716224140287,529082239113522161/2438652913112833925,=2:-29377919201006207047359381264955432/7061070044829121412952661959332836475
+qsub:150980224993479452/371034742997570395,=1,97628589854512901/1461818398649717323:0
+qsub:828501131055695330/861555563679753833,-968363844399576751/400987885360876602,4318808141772773/272140134925135118:1166518174369888540148356746507605243/345473343600842551070257384449515466
+qsub:997737191667232852/878873090216825721,-215309181373978527/178339642478000642,44112408043295555/167730641087926307:367165539635142230228004432374783951/156737912692804302819698495840112882
+qsub:-874288368924506038/33067894686016771,172933382638695999/15746943377378890,=1:-19485912325748182437244211303337049/520718265229834381226960561364190
+qsub:113445092902670316/24432013651972039,789628644660942395/81838347379866874,-253719530063131225/7192012672525274:-10008058904834319340307600738181221/1999475620439737613479475390336086
+qsub:469761512155527237/7409272817081662,644368433953482322/2796535736601265,-743279324916258749/3941987500967613:-3460596665454235362140115831224359/20720296215197195433635837502430
+qsub:8261654401496347/568538524395616,-778532546601001661/1096269337597285,-306562427101658699/2779592495957628:451682743636680727605399921736071/623271351537719810570227502560
+qsub:461974279165354118/107945644045613,=1,-4203580865175374/431296441354377:0
+qsub:999567545272721386/528172429856767,-306849659405574946/410631585483429,58620020684173871/34198792094556:572523536122080656350523300672176/216884282280719425778922014043
+qsub:838953299025019215/26401444256374,855300290662954227/88914568043701,-233880940259636371/26804240414928:52014007245249037196988469721817/2347473011785344971879800174
+qsub:-84648269690239765/7748568048141,86620759660993385/4650491023414,740584294215236889/18424376078527:-1064842868956861583564451404995/36034646152192259510173374
+qsub:144119271324804795/7593869059598,-862271465889805512/4817698847465,30615084012712336/133690674221:7242299853153814002244162498851/36584974216225407996219070
+qsub:-514146414782774671/7780370709815,270344156048491787/2722967818331,219882280138478/11635197457:-3503381894653098523553024083506/21185699057511364438618765
+qsub:27542214966861168/383672867,287936038111037884/394023185191,231925740783907885/236839247989:10741798023203186757550669660/151176005126702912597
+qsub:-202417103371781662/185891935843,-75016780652064931/26395556610,539072986943728448/794028543247:8602102465239973123041336013/4906721115886394572230
+qsub:146159764562795268/26252940211,5977449519968967/15598248256,=2:2122910667826975950339620571/409499878861103022016
+qsub:92905251016109811/18087473051,861913285707088178/49029015865,575397421398561364/35847357407:-11034780301515165605154539563/886811003175238954115
+qsub:43007028131858062/2453663475,=1,=1:0
+qsub:-99491213767410734/5448033345,607696219524202834/7914352487,932551377887323725/7825731284:-4098157802713052856358895188/43117656253259679015
+qsub:-693848599167966481/337019784,451296938813827771/190206672,138269118881809795/286360117:-11836276239937430206424279/2670975479699952
+qsub:885539919667431975/906601532,=1,679476927167924457/542648272:0
+qsub:-4563620543259161/50948374,877797754583710364/85678397,871721618807362291/51516582:-45113371989553804002793053/4365175014076478
+qsub:267267974303681854/59860387,643485159739694623/65130620,-346322759520229537/79392976:-21111941818232071960829621/3898744118749940
+qsub:-292697070229916239/6469138,451527711321523043/1713209,-690729392819742293/7199521:-3422446330354619505247885/11082985443842
+qsub:109167064549424855/933921,-974615071639008317/9073576,-141072367242930847/2470173:1900749139206286464552437/8474003171496
+qsub:-442186452566118477/433250,243224124572764479/694402,188939975597921698/84623:-103108002251492003298126/75212416625
+qsub:504154364259376845/839918,-816470041468996533/562156,932823927594899937/948502:484590642542575439841057/236082471604
+qsub:58385990303797466/4715,23346464312197309/7769,-83189886883209658/1309:343522179438192201419/36630835
+qsub:-31667255028373761/6166,=1,=2:0
+qsub:264267843061809424/1507,=1,780372905769447077/8088:0
+qsub:942357538510813910/7893,-485153351303873623/1639,-20022501530390273/127:5373839407460698504829/12936627
+qsub:-42475017998288473/153,147697152269679268/85,=2:-1541649460418555777/765
+qsub:75774035481832811/18,340160682114414248/343,=1:19867601892209197709/6174
+qsub:74102130227248217,144497961842228027/6,-998137158213905035/43:300114819521261275/6
+qsub:821735055204387778/45,=1,=2:0
+qsub:-57815587457821904,51008807915322849,-147281045102225347/3:-108824395373144753
+qsub:454222567912329981,22540753838160371,18269107333524567:431681814074169610
+qsub:3210043239752875243/72149763518252375009,3261470914498557412/93230677190142956657,-4064987413615246181/33645849737189283754:63960149849071755625510420647536825943/6726571311915340136410812262723596984913
+qsub:9804073501780182793/38766744515505567422,=1,=2:0
+qsub:257063569033647893/47627381308050634,=1,=2:0
+qsub:1552551009049725266/1621244061592046727,8268958120903544781/425547204494853721,213262382085564484/2263543462839420049:-12745315507331426593439792125381167001/689915878214377929840178814861821167
+qsub:2934623879325117949/357068238595800494,9728045374534083071/521016049535609725,-804894226755345532/55644798067314489:-1944589886386070523678697500282383049/186038283087822502456659294746204150
+qsub:-3413740827484155595/35201790823660144,=1,=2:0
+qsub:5742873913112182553/61766168241911339,3984407637182474330/61987278332263327,448424158078834703/1851056518481567:109883531216609955256617440787705961/3828716662328761978044444335164853
+qsub:-5538305489874918085/47200167153328601,2292592129732611685/3752960621013977,-7047966941457980339/13001528931023405:-128995774148430971478100961252376730/177140368631719625362323294856177
+qsub:2647084994940083287/8257587043096855,8517457859612680059/8568918876347054,4335833152174662442/3522517188924281:-47650993081224012631875300587027947/70758593486671494919389915915170
+qsub:-2174815554300743477/1055854216058324,1106694427573230889/1439497035446960,1663682898924590039/6228481982913678:-1074787130075326655568302535462489/379974753470032846369692123760
+qsub:-673256166894368145/58357219332101,=1,-9850462360230406692/697272419401589:0
+qsub:-7350812074670262181/353785488987714,-9161255025310493969/644044224968076,1118265777181240006/160586465643975:-82951609813686583656885009057605/12658527836669113872289234348
+qsub:7934622905365481543/24281747034726,=1,=1:0
+qsub:-4406459203030692110/40412972154809,-328394051086803323/17512120371320,3271184521881465212/24850026200233:-63895064332408368266126902654893/707716832937818605603677880
+qsub:460352415792245815/1067976849408,-3006172239763431339/8488209165760,=2:111220155509497494992102376433/141643920030694887966720
+qsub:-8685801779232576472/5545683151339,-9379688590927802729/4661614228739,-1045039004738707304/2306882972179:11526923821437860566165526575323/25851835486360019500131521
+qsub:-1099655652591638878/2758191281,1569957311481795188/313204152767,4679104365556960009/172279461301:-348746959573478031289777831254/863876963334931424527
+qsub:7376706437670791929/273943068790,6472278838608399241/616870830740,-2499089563512667949/302238168048:277743910121812542672687030907/16898748841995226660460
+qsub:6865154371318865863/58818463172,7515040679922839317/98572518047,3436930220114417551/26193376471:234692409694146480303501596037/5797884022518774865084
+qsub:1254860182105767734/5016375113,=1,2599681765080769493/46385850085:0
+qsub:4216394462161257127/7652601313,154087255858661733/228011378,=1:-31111774998800660662723489/249268595808819902
+qsub:-8218805797153900006/3225230965,162240217381132332/3267619919,470501772660009028/17345893:-27379195706038716372068879894/10538828944609591835
+qsub:2993035686422028942/288390385,572871629063315065/300592553,-6417147951768049106/301422311:734473568540558494144018901/86688002087802905
+qsub:-413167836327757837/385147459,=1,4223408874712268336/273008947:0
+qsub:3297442160967679169/69599199,9036377343550866545/45162311,=1:-480004516594753739709297896/3143260670588889
+qsub:368876976532110737/16510688,6518851187565474853/50791699,-1104665290033392205/7386446:-88894829716274002481356701/838605895178912
+qsub:-2062139936169240279/2037445,=1,252666902590280893/289459:0
+qsub:7094134562467803247/3012150,=1,9333233846214751643/9878490:0
+qsub:6076762026375939088/714143,-1173122156103211995/424924,=2:3419939003221785664774597/303456500132
+qsub:-5491034419852196360/519619,715863173404931/44,-3750063252517296119/253359:-613581620774993481129/22863236
+qsub:-5533397069224776206/61493,=1,1084791347634995311/940:0
+qsub:2610588148432509992/29651,=1,-1360998239306614670/89179:0
+qsub:3100610288438845270/1619,9307237399334731519/4955,9392825838002497590/8501:295106629691547983589/8022145
+qsub:3368071818378567709/3813,-3776828995456884473/1454,=2:19298225383599537944435/5544102
+qsub:1898435934717526073/873,4308565906715352586/295,=1:-3201339435820832616043/257535
+qsub:1300690053258900179/243,4943814111367222345/439,=2:-630343895681577851254/106677
+qsub:251833946462887840,-869006720570670337/8,-725021352968265541/99:2883678292273773057/8
+qsub:626008792964496823,3012267373701938935/3,-1881182483045937043/16:-1134240994808448466/3
+qsub:8909701403779037643/2,4263103087268485691/6,-4865092756990722784/5:11233000562034313619/3
+qsub:1563790691172262117/4,4953143499970208620,6661387731632814693/7:-18248783308708572363/4
+qsub:-5421505027803143917/29277316475549977927,-24881453522128465658/13193126736034804489,=2:656935586207185980835950093591652887553/386259346752930686132136354247710514303
+qsub:43002545629357992251/65752963968398524190,31308403854434073804/48746580693008293241,1726565764440537923/12956415087885593469:37606709977597341370212061004874356731/3205232163890005466586601709015151999790
+qsub:-59751660477015957831/4286192839388269021,11974517458086843067/1241046631081301617,=2:-125479687920496057578907990371068840134/5319365183487609778049805813238306957
+qsub:-49461165347668030699/208457055709777407,52105901053159218571/6869817428870197111,-36441364311401291685/8657876687713166642:-350651018476287040134985140793799735986/1432061914485994468255463550024471177
+qsub:-7581437680655861221/49307213191711325,-32918301279907528476/380204896359543505,-62274249636519514774/637143890847264601:-251878005702543064394570301716545781/3749368776266504127275465347738825
+qsub:88463778015782255603/611086942952818386,28997739596524666645/367897090074176869,-81867305184567355447/440111079789875727:14825426466392080175430281904511312037/224817108094666407622918422599113434
+qsub:27845231969167468634/7852896265044091,=1,16619399537337723559/18069459979251540:0
+qsub:-37414950961700930/7204075375675961,-11821234740040951665/4482466888001314,-23524535630982071810/37803027645100347:84993354822012222699375201588403045/32292029330133121955123006212754
+qsub:61321523796737027359/5452182446309742,=1,48591916429664483052/1740855337030687:0
+qsub:5363425484789562617/1756465539350314,-40936806728242699939/5412202567319265,-3599607803259833000/278745158021617:100932035487606021271304492855347351/9506347301479586913476715999210
+qsub:33564895484794792189/136772489172128,4571443108763064643/186748602496254,=2:2821474835811978960085724681544851/12771035606414468103340604256
+qsub:-94258077286598647991/474232208430175,98462449436025151993/228502005075011,=1:-68232224497993790090895883442041676/108363010497445522187430856925
+qsub:34061962820425097482/24899834941843,1855142409964422527/902056706202,14293533188899209595/42267239349684:-15466917813159310212214440113897/22461063092612364807410286
+qsub:-73929207028429916638/21372812626357,-66185303844781311744/59463089468249,-6818430024504790355/20557416897032:-2981492954155214407839662609790254/1270893469389188176252038893
+qsub:57077240876377553179/935097318175,=1,42604601978623894017/8385603091453:0
+qsub:7077386151750173156/1231852917417,40471318485412028642/1706097941603,38461201962265231448/5304200381911:-37779997802536821420601638448646/2101661726762794047599451
+qsub:-37489576712437584437/499625554669,60955914069456492767/885230799387,50229679483949978567/539847952020:-63642060339139483486584581919242/442283929153812140187903
+qsub:3147094074418762156/310106471081,=1,-3700969786876628910/15570398827:0
+qsub:12329606272247487589/40674617665,-77828250896400397795/50092227757,-22437013421232931285/13509778618:343931981299121509240432077868/185225655636734138855
+qsub:49832350382626108453/8964749413,=1,2620089939108140247/2413101797:0
+qsub:50952962315511975411/6309290837,-16012147625149581763/1214855186,49964518797252328078/9043690267:162925766803109858544836037077/7664874693311730682
+qsub:348630015993655559/4656837405,26166625137687604221/1177967663,47073618836385117951/1978562296:-121443043818605211479526497888/5485603874938834515
+qsub:17078935151701402183/29370735,-53438577236731723122/493863599,27771088952431040471/715856601:10004194671903945161352471287/14505136892375265
+qsub:-82659381362807119713/632881567,29388144547912909553/176840848,11667678020670746965/17707269:-33216770068059835487916346175/111919312991848816
+qsub:21029165726302721351/47748016,59722770221895701365/6011409,7537524523228744530/7443449:-2725228872009811783253348281/287032853114544
+qsub:-1377712971222794171/46200083,67781278282353575281/46204616,=1:-3195157381284400868447041659/2134657094183128
+qsub:99498503205328073847/8536940,67748617769009531540/8445211,-11519205096064985138/4045881:261919968776203677676409117/72096259594340
+qsub:4104972121385207947/636151,13294784517447053191/977547,13689829596826434020/1075639:-4444687283214714461541832/621867501597
+qsub:82730974983634629799/122118,-16204666767231941581/177953,=2:16701106687543563518610005/21731264454
+qsub:-10650367180325946520/50547,1632386827276484871/118112,-75101239763743917691/649672:-1340448425361002676144677/5970207264
+qsub:77412383597894642193/47240,80267467079572070186/72803,-25049349718395484959/22130:1844018618238539039990339/3439213720
+qsub:35230904033764128322/11419,95208581964982041789/24788,1540889192878250023/4339:-213883148269184722342855/283054172
+qsub:-83663795012357893939/1322,-18656774262532233660/4619,54887210177965383636/8713:-361778813587013499205721/6106318
+qsub:39695783291112421139/8771,=1,27510059665458841174/5277:0
+qsub:19248997287659952171/173,73630829417088216857/778,-16684093916667265360/351:2237586400643181272777/134594
+qsub:88156024379250020383/629,-6327178680410193049/304,=1:30779226801270017624253/191216
+qsub:-11930537715494417409/2,80328608387065532851/43,41042034234564284791/75:-673670338540391014289/86
+qsub:36406323599126203370/21,48085922416521160270/63,=1:61133048380857449840/63
+qsub:-13809041632683030117/5,28242141662062188361/7,=2:-237873999739092152624/35
+qsub:7450923073218275163/2,73871343095222710643/8,-1203953812110244763/4:-44067650802349609991/8
diff --git a/polly/lib/External/isl/imath/tests/qsubz.t b/polly/lib/External/isl/imath/tests/qsubz.t
new file mode 100644
index 00000000000..7af689db540
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qsubz.t
@@ -0,0 +1,800 @@
+qsubz:1/89666066690010668869,8,0:-717328533520085350951/89666066690010668869
+qsubz:-7/92370362169890168582,0,3/10759595446182824504:-7/92370362169890168582
+qsubz:0,-6,=1:6
+qsubz:6/6514124205427226147,7,1/7791165451225637150:-45598869437990583023/6514124205427226147
+qsubz:8/927453510429432507,1,-7/939604332333807555:-927453510429432499/927453510429432507
+qsubz:6/791634116823984509,1,3/166448493180216857:-791634116823984503/791634116823984509
+qsubz:9/28379125138664429,2,2/1928364957970427:-56758250277328849/28379125138664429
+qsubz:1/4792771676887137,4,1/7102881482139131:-19171086707548547/4792771676887137
+qsubz:1/6412666850016412,5,2/3998647479596483:-32063334250082059/6412666850016412
+qsubz:1/2202724091118898,7,8/2921444666229659:-15419068637832285/2202724091118898
+qsubz:0,-5,=1:5
+qsubz:1/52166421933102,8,-4/458542817737975:-417331375464815/52166421933102
+qsubz:3/70257684761911,9,2/38216141537789:-632319162857196/70257684761911
+qsubz:0,8,5/16844906665344:-8
+qsubz:1/888589420311,-7,=1:6220125942178/888589420311
+qsubz:-3/9029660826470,1,2/1660505018071:-9029660826473/9029660826470
+qsubz:4/175194964803,2,0:-350389929602/175194964803
+qsubz:0,3,1/28737296870:-3
+qsubz:-1/7337600358,1,4/48392570781:-7337600359/7337600358
+qsubz:1/627219895,8,7/75038497999:-5017759159/627219895
+qsubz:5/6927289812,4,-1/1790030470:-27709159243/6927289812
+qsubz:-4/2649530011,3,-8/6194440675:-7948590037/2649530011
+qsubz:6/83079221,8,=1:-664633762/83079221
+qsubz:-6/331542793,3,2/296815681:-994628385/331542793
+qsubz:8/66065289,2,-1/4328527:-132130570/66065289
+qsubz:1/2350655,7,=1:-16454584/2350655
+qsubz:2/3582747,9,1/2075528:-32244721/3582747
+qsubz:-1/1935616,2,8/4881029:-3871233/1935616
+qsubz:-8/465389,-4,1/262387:1861548/465389
+qsubz:2/240549,5,1/4804:-1202743/240549
+qsubz:3/48194,9,0:-433743/48194
+qsubz:4/27421,0,5/29029:4/27421
+qsubz:4/373,8,3/1025:-2980/373
+qsubz:3/1183,0,-1/3894:3/1183
+qsubz:1/106,3,9/871:-317/106
+qsubz:1/371,2,=1:-741/371
+qsubz:-3/56,5,0:-283/56
+qsubz:-5/91,4,-1/34:-369/91
+qsubz:8,4,9/4:4
+qsubz:4/7,9,=1:-59/7
+qsubz:67/67063488163100893306,-90,=1:6035713934679080397607/67063488163100893306
+qsubz:93/14983550478036855485,-67,69/28718649239616874679:1003897882028469317588/14983550478036855485
+qsubz:-8/1154267369681644285,87,7/1422761935805056072:-100421261162303052803/1154267369681644285
+qsubz:37/9228347282193695562,-68,32/723121468170916937:627527615189171298253/9228347282193695562
+qsubz:70/67740456883245887,-44,=1:2980580102862819098/67740456883245887
+qsubz:-4/290534225323804529,3,14/82856366067157729:-871602675971413591/290534225323804529
+qsubz:46/92984464090082831,31,37/3777138432527707:-2882518386792567715/92984464090082831
+qsubz:-1/30135296523120697,19,39/50227831157182621:-572570633939293244/30135296523120697
+qsubz:5/1204201678805616,27,-95/8641770984922113:-32513445327751627/1204201678805616
+qsubz:13/221269253819147,-51,85/902323678584334:11284731944776510/221269253819147
+qsubz:16/197386558463723,66,11/188936591024340:-13027512858605702/197386558463723
+qsubz:-33/364958822489692,-68,29/670095439482948:24817199929299023/364958822489692
+qsubz:2/69405413649461,25,14/58807481541667:-1735135341236523/69405413649461
+qsubz:4/151019996133,86,-7/15591256924134:-12987719667434/151019996133
+qsubz:-20/2213441952101,68,-5/766058099692:-150514052742888/2213441952101
+qsubz:47/3397682774754,62,-27/825236302529:-210656332034701/3397682774754
+qsubz:-8/300999779133,-8,52/319011801871:2407998233056/300999779133
+qsubz:78/930349215041,-94,-16/849840150359:87452826213932/930349215041
+qsubz:-62/78781195345,97,63/94454224597:-7641775948527/78781195345
+qsubz:84/67865566651,10,40/38840532741:-678655666426/67865566651
+qsubz:97/9037713489,26,=1:-234980550617/9037713489
+qsubz:55/8758626548,-31,-23/3424652585:271517423043/8758626548
+qsubz:96/712280131,76,-47/143760491:-54133289860/712280131
+qsubz:-34/979750323,86,18/751431151:-84258527812/979750323
+qsubz:0,40,49/28166996:-40
+qsubz:11/655774,-79,-5/2552876:51806157/655774
+qsubz:38/4762681,-34,-38/4640209:161931192/4762681
+qsubz:10/759353,91,-79/8482283:-69101113/759353
+qsubz:52/658491,60,-10/24871:-39509408/658491
+qsubz:47/356452,48,-52/327287:-17109649/356452
+qsubz:-23/1045,-17,40/36411:17742/1045
+qsubz:29/57207,74,-19/15711:-4233289/57207
+qsubz:71/6841,24,27/3695:-164113/6841
+qsubz:41/2,-28,-8/503:97/2
+qsubz:1/992,69,-79/335:-68447/992
+qsubz:-80/873,58,55/97:-50714/873
+qsubz:-80/59,25,-24/29:-1555/59
+qsubz:31/53,4,83/16:-181/53
+qsubz:52/5,87,55/4:-383/5
+qsubz:64/3,-44,86/7:196/3
+qsubz:217/14857025609834400288,407,-29/32222540400290548019:-6046809423202600916999/14857025609834400288
+qsubz:-2/3173544479029088453,617,=1:-1958076943560947575503/3173544479029088453
+qsubz:599/8002882171639730594,194,994/7112031035139432061:-1552559141298107734637/8002882171639730594
+qsubz:226/1547262749305138445,841,=1:-1301247972165621432019/1547262749305138445
+qsubz:-21/33650083175862080,-295,-192/250269714000112853:9926774536879313579/33650083175862080
+qsubz:371/195117884451651598,98,-31/6936245079767325:-19121552676261856233/195117884451651598
+qsubz:490/84964164487466941,-621,85/1727659786593371:52762746146716970851/84964164487466941
+qsubz:73/2114768125726396,264,371/90346751835547482:-558298785191768471/2114768125726396
+qsubz:-67/754047118019190,473,=1:-356664286823076937/754047118019190
+qsubz:428/1757703052948383,545,-929/6392239532410133:-957948163856868307/1757703052948383
+qsubz:-187/146639276395956,379,49/117345807572527:-55576285754067511/146639276395956
+qsubz:574/304011640895343,117,31/939392861513114:-35569361984754557/304011640895343
+qsubz:281/28071632904233,839,-779/61474591794274:-23552100006651206/28071632904233
+qsubz:-451/21089251676176,966,-402/36593676777599:-20372217119186467/21089251676176
+qsubz:447/699261969911,217,305/9706389468401:-151739847470240/699261969911
+qsubz:921/4456064406581,-752,-25/13909101793:3350960433749833/4456064406581
+qsubz:57/94353144617,914,944/766019154987:-86238774179881/94353144617
+qsubz:317/388136152543,159,423/224732026858:-61713648254020/388136152543
+qsubz:545/36819534187,-885,=1:32585287756040/36819534187
+qsubz:260/75651626533,-80,142/23885409609:6052130122900/75651626533
+qsubz:308/2920452939,386,176/748052249:-1127294834146/2920452939
+qsubz:956/2320741999,604,=1:-1401728166440/2320741999
+qsubz:229/136668710,-720,=1:98401471429/136668710
+qsubz:697/821017209,-389,877/710813436:319375694998/821017209
+qsubz:70/9998911,-414,409/41910723:4139549224/9998911
+qsubz:-137/4902402,-780,0:3823873423/4902402
+qsubz:98/339603,579,751/7297217:-196630039/339603
+qsubz:843/8995763,-683,=1:6144106972/8995763
+qsubz:-68/25519,874,97/240532:-22303674/25519
+qsubz:-407/183461,-958,53/66366:175755231/183461
+qsubz:353/72580,466,747/59113:-33821927/72580
+qsubz:83/41954,447,884/15765:-18753355/41954
+qsubz:-931/5272,773,5/391:-4076187/5272
+qsubz:81/167,110,19/123:-18289/167
+qsubz:456/823,345,870/7:-283479/823
+qsubz:688/747,879,678/181:-655925/747
+qsubz:-849/62,395,=1:-25339/62
+qsubz:-433/39,676,=1:-26797/39
+qsubz:220,191,-109/5:29
+qsubz:32/3,-877,655/2:2663/3
+qsubz:4482/942383524654707545,4232,9844/42644717112858614311:-3988167076338722325958/942383524654707545
+qsubz:1875/2912377751134048423,-2847,=1:8291539457478635862156/2912377751134048423
+qsubz:3804/6718901259124469983,-7372,7774/3759543365401515053:49531740082265592718480/6718901259124469983
+qsubz:9425/3546445994609032698,-6247,9653/7954521365876236362:22154648128322627273831/3546445994609032698
+qsubz:-5435/351267797941464751,7271,4323/405081904237732000:-2554068158832390209956/351267797941464751
+qsubz:4747/334289067072715219,-9265,1271/365223131014466030:3097188206428706508782/334289067072715219
+qsubz:593/11020543433206946,-9783,1692/92769627960132841:107813976407063553311/11020543433206946
+qsubz:58/71759187206685567,2562,=1:-183847037623528422596/71759187206685567
+qsubz:8176/5868555722851603,4639,749/1128170091785729:-27224229998308578141/5868555722851603
+qsubz:1048/2494671804723743,258,-9823/9523787627049892:-643625325618724646/2494671804723743
+qsubz:4016/437682693132675,-5554,9263/342594970246293:2430889677658880966/437682693132675
+qsubz:-449/124840348021110,-2661,=1:332200166084173261/124840348021110
+qsubz:3767/38680047773174,-361,3480/41604972731513:13963497246119581/38680047773174
+qsubz:8637/56843071105219,5929,9928/45360343092035:-337022568582834814/56843071105219
+qsubz:42/1232757862481,3179,4357/5496968152610:-3918937244827057/1232757862481
+qsubz:546/1614496289405,1603,2191/3651782433017:-2588037551915669/1614496289405
+qsubz:809/91979873066,4972,-4804/368689337963:-457323928883343/91979873066
+qsubz:-3210/152298659683,-4089,541/44970493080:622749219440577/152298659683
+qsubz:7246/21217273455,2308,=1:-48969467126894/21217273455
+qsubz:2397/86866068995,7381,-2866/3975744919:-641158455249698/86866068995
+qsubz:3087/4683188920,6673,9169/306325723:-31250919660073/4683188920
+qsubz:990/4768458857,4306,4877/2755124455:-20532983837252/4768458857
+qsubz:-3658/338788855,2880,5674/71884221:-975711906058/338788855
+qsubz:-9886/839837613,-2330,4083/690099413:1956821628404/839837613
+qsubz:7337/91119486,5300,9061/80090081:-482933268463/91119486
+qsubz:6273/50364475,-837,-1696/28323419:42155071848/50364475
+qsubz:648/537779,-5873,8567/8273739:3158376715/537779
+qsubz:3179/1733392,4267,1178/6835527:-7396380485/1733392
+qsubz:2567/620512,4677,7019/800989:-2902132057/620512
+qsubz:8643/360838,5106,-8302/971695:-1842430185/360838
+qsubz:-2586/31991,-5074,2570/21109:162319748/31991
+qsubz:2023/2705,2980,317/96960:-8058877/2705
+qsubz:-1301/5346,4188,-7061/2853:-22390349/5346
+qsubz:-6732/8017,9992,31/59:-80112596/8017
+qsubz:-3890/853,2695,962/263:-2302725/853
+qsubz:2329/43,7457,=1:-318322/43
+qsubz:1601/82,2574,301/13:-209467/82
+qsubz:-1347/20,4147,-355:-84287/20
+qsubz:1381,-456,5461/3:1837
+qsubz:1267,3358,=1:-2091
+qsubz:12513/10252103968497865097,4751,58924/7482016308047316835:-48707745954333357063334/10252103968497865097
+qsubz:-8397/12043175373779318638,32237,-75596/84316290023168074765:-388235844524523894941603/12043175373779318638
+qsubz:2207/1864898564933133421,-268,=1:499792815402079759035/1864898564933133421
+qsubz:93903/5738092942308156928,-98800,=1:566923582700045904580303/5738092942308156928
+qsubz:-22733/84967665346179535,83373,37597/787951056254403061:-7084009162907026394288/84967665346179535
+qsubz:-86661/144430519608110792,44749,-90279/140207959688288608:-6463121321943349917869/144430519608110792
+qsubz:483/360261339188405,529,=1:-190578248430665762/360261339188405
+qsubz:-38143/29201842630357283,93563,=1:-2732212002024118507472/29201842630357283
+qsubz:62857/8632026056772207,-87080,-91675/4159937477960427:751676829023723848417/8632026056772207
+qsubz:23972/3672679577284837,52253,85704/3937432008899357:-191908525951864563789/3672679577284837
+qsubz:-14599/133661353793289,51189,99045/961552885468912:-6841991039324685220/133661353793289
+qsubz:62703/884965957527142,86064,=1:-76163710168615886385/884965957527142
+qsubz:64258/63053331939447,29993,33125/6340027354888:-1891158584859769613/63053331939447
+qsubz:20336/70880915457155,41846,79118/19214581682805:-2966082788220087794/70880915457155
+qsubz:36038/5027873766967,8156,18212/2385080863253:-41007338443346814/5027873766967
+qsubz:5053/326394695366,-96066,48835/616131440759:31355432805035209/326394695366
+qsubz:-42352/85957538425,63707,=1:-5476096900483827/85957538425
+qsubz:98097/378312685672,74927,-87935/235046263733:-28345834599247847/378312685672
+qsubz:547/343462127,45098,71335/96241407069:-15489455002899/343462127
+qsubz:-60477/84209971088,13484,11423/1932234184:-1135487250211069/84209971088
+qsubz:78087/178203607,2768,99674/645255053:-493267506089/178203607
+qsubz:5795/9287277564,55525,94160/3355805697:-515676086735305/9287277564
+qsubz:18925/113809474,-82623,=1:9403280189227/113809474
+qsubz:24851/454133872,99932,41237/85240886:-45382506071853/454133872
+qsubz:32911/22337158,43967,9767/5792458:-982097792875/22337158
+qsubz:4426/88473719,34001,302/1024805:-3008194915293/88473719
+qsubz:19589/4824560,27427,-56021/4154865:-132323187531/4824560
+qsubz:54075/7773166,56830,-399/153359:-441748969705/7773166
+qsubz:18078/738403,66012,86419/302521:-48743440758/738403
+qsubz:2510/112811,-47375,17956/599429:5344423635/112811
+qsubz:-69109/5420,2635,=1:-14350809/5420
+qsubz:696/5261,-27292,12449/12093:143583908/5261
+qsubz:6568/1031,5374,=1:-5534026/1031
+qsubz:307/167,87414,=1:-14597831/167
+qsubz:14308/171,-77499,92955/236:13266637/171
+qsubz:-3325/3,-32369,-9967/90:93782/3
+qsubz:62901/65,-51444,-55475/13:3406761/65
+qsubz:94982/85,74494,1763/15:-6237008/85
+qsubz:-15489,36907,29337/5:-52396
+qsubz:-44489/6,51924,=1:-356033/6
+qsubz:866110/92140247631008473461,992450,-12311/75887274686890544356:-91444588761394359485503340/92140247631008473461
+qsubz:286002/21377811703132112171,-707482,=1:15124416979355312983249424/21377811703132112171
+qsubz:205249/6361297615099533875,893207,=1:-5681955558890209353681876/6361297615099533875
+qsubz:602071/8282499324515240138,143540,=1:-1188869953040917568806449/8282499324515240138
+qsubz:-157822/195585936483662037,948292,47401/94049003322925483:-185472578879964840548626/195585936483662037
+qsubz:-485225/770852827673995413,462391,451203/793998272131521284:-356435409841006413497708/770852827673995413
+qsubz:832061/32966123055937780,297720,-38054/4240951695865905:-9814674156213795029539/32966123055937780
+qsubz:378475/97089199745880654,-144939,804700/47910921928599697:14072011521968196488581/97089199745880654
+qsubz:168809/1173744791921052,993504,123481/4027191055766810:-1166120145752732677399/1173744791921052
+qsubz:984079/7930167991939240,207285,19678/312910315596939:-1643804872209124379321/7930167991939240
+qsubz:268867/66218854685878,-341636,=1:22622744639464885275/66218854685878
+qsubz:-265818/703448681374513,-608432,516434/935917451239689:428000688106057427798/703448681374513
+qsubz:30312/17555819170721,-807531,837647/26238515163476:14176868210751530163/17555819170721
+qsubz:273401/67808858597950,255506,47585/13599555299396:-17325570224927539299/67808858597950
+qsubz:861384/410255576291,400497,402375/1586446068433:-164306127536955243/410255576291
+qsubz:76471/2810776113738,700348,=1:-1968521429704104353/2810776113738
+qsubz:46697/205225703,-877191,-693829/982561781845:180022139686970/205225703
+qsubz:694597/894706887191,189537,-5500/6992098541:-169580059276825970/894706887191
+qsubz:190839/96993581741,-48652,-262577/87880831891:4718931739053971/96993581741
+qsubz:926735/37595457632,309200,228538/46784730005:-11624515498887665/37595457632
+qsubz:-289777/2914954976,-922880,-785617/9421248912:2690153647961103/2914954976
+qsubz:146291/1692030840,816085,-21414/520023815:-1380840987915109/1692030840
+qsubz:149175/195113702,21897,=1:-4272404583519/195113702
+qsubz:-798035/275024051,342,=1:-94059023477/275024051
+qsubz:84407/78878758,-202254,414137/15080286:15953544404939/78878758
+qsubz:99099/5326786,776103,-250532/35421237:-4134134495859/5326786
+qsubz:820103/1983152,83528,386969/1852538:-165647900153/1983152
+qsubz:-277421/4047779,-724923,-962247/9651313:2934327818596/4047779
+qsubz:300716/83775,791615,597967/22363:-66317245909/83775
+qsubz:913987/585082,571734,-207060/17131:-334510358201/585082
+qsubz:286582/40727,479108,247602/7559:-19512344934/40727
+qsubz:969635/90993,547019,-27576/16163:-49773930232/90993
+qsubz:484543/4803,-13377,17384/831:64734274/4803
+qsubz:3392/77,159299,=1:-12262631/77
+qsubz:272609/60,-479733,5158/5:29056589/60
+qsubz:-63573/145,944778,245967/77:-137056383/145
+qsubz:684504/71,664239,-229408/35:-46476465/71
+qsubz:-86273,-276646,-115497/7:190373
+qsubz:355634/9,348514,373603/7:-2780992/9
+qsubz:-35219/3,752707,462886/5:-2293340/3
+qsubz:6360943/76846663141823723315,-4919575,2604527/5657014356260399834:378052922825937443633752068/76846663141823723315
+qsubz:183663/3383815743880203737,3975537,7064811/78463982107211848135:-13452484690978273523798106/3383815743880203737
+qsubz:4452901/2427919735747339403,2077568,=1:-5044168349557128424359003/2427919735747339403
+qsubz:8188529/976933204663543185,-1819612,=1:1777639382404239150132749/976933204663543185
+qsubz:5989009/760314382917671424,-4531658,4299344/201823238781745367:3445484755863929055930001/760314382917671424
+qsubz:893159/325858362948738303,4913385,=1:-1601067592636886545992496/325858362948738303
+qsubz:-1545535/21298499245651851,4547022,64678/4463799054157215:-96844744636962372383257/21298499245651851
+qsubz:297441/54069528036684176,-4566133,1740182/82453971200884283:246888656262728826908849/54069528036684176
+qsubz:6314549/8139443267727551,7518036,2558291/3365437156048481:-61192627506733360295287/8139443267727551
+qsubz:-372197/9493061230738691,8349035,2681821/7376683826021902:-79257900472580407385382/9493061230738691
+qsubz:2058974/610730967434339,-3873084,=1:2365412338274461490450/610730967434339
+qsubz:1047887/255819069867599,4832574,-2588613/40555255514690:-1236264585746341321939/255819069867599
+qsubz:2862299/15444378077100,3725846,-3488340/75081425094083:-57543374281047864301/15444378077100
+qsubz:189642/13804468201471,-9916920,=1:136897806796531978962/13804468201471
+qsubz:9152299/2631833515647,7403594,-1874909/1403676750221:-19485026825433883019/2631833515647
+qsubz:9157819/3680087499503,6393090,2353381/629919919878:-23527130592188476451/3680087499503
+qsubz:-9202064/585608331143,7948050,3400424/545300178161:-4654444296350323214/585608331143
+qsubz:4941532/944567169683,3506737,-5183542/977397734325:-3312348642907712839/944567169683
+qsubz:-1132569/74601321698,9858377,-2217591/82351435039:-735447953998296715/74601321698
+qsubz:-6722621/70207951128,-2574827,4755161/88553923140:180773328172332235/70207951128
+qsubz:-131623/1102596343,4262329,6139281/2146761991:-4699628368194470/1102596343
+qsubz:-1537871/2076518121,-611135,3524466/1036431631:1269032900339464/2076518121
+qsubz:1873496/94557071,9574995,=1:-905383480166149/94557071
+qsubz:6133681/175761766,-4032589,-1323487/51867812:708774970325855/175761766
+qsubz:33618/108073,9301994,=1:-1005294363944/108073
+qsubz:99693/1649666,4815171,3560665/23554903:-7943423783193/1649666
+qsubz:-1476863/6094467,1954168,6826155/1513109:-11909613865319/6094467
+qsubz:9947161/5499663,-7436262,=1:40896944926867/5499663
+qsubz:-3188500/101159,-1362013,1715658/206461:137776684567/101159
+qsubz:1661723/438801,3554863,397247/83229:-1559875777540/438801
+qsubz:6730319/39072,-7285917,-785583/26039:284682079343/39072
+qsubz:881050/8251,9977014,5611562/26365:-82319461464/8251
+qsubz:-697786/267,9879500,=1:-2638524286/267
+qsubz:1563831/1594,3690522,330707/648:-5881128237/1594
+qsubz:2617466/799,4838440,1742596/21:-3863296094/799
+qsubz:-5575739/795,5654259,241335/887:-4500711644/795
+qsubz:3099833/23,1330008,2467779/32:-27490351/23
+qsubz:-119153/20,-5081644,-9942949/35:101513727/20
+qsubz:4981844/3,7468100,=1:-17422456/3
+qsubz:4124549/2,8822966,-327579:-13521383/2
+qsubz:1379187/4947079973483919932,39455371,85787924/46398781838625356921:-195188875720478223449975585/4947079973483919932
+qsubz:10309279/3518090035798479574,41783212,55881853/31567898190111952667:-146997101800855461307802409/3518090035798479574
+qsubz:7964765/7203559539360591689,17787685,-3457138/299200161568971109:-128134647964891306369585200/7203559539360591689
+qsubz:3870874/16190098037406359,32189441,=1:-521150205559307782184445/16190098037406359
+qsubz:57899009/680974553755525868,95258028,91102702/899472329944903875:-64868293108931388230769295/680974553755525868
+qsubz:36574505/725775689525814263,59424702,7088419/54125181064287425:-43129004068916033849550121/725775689525814263
+qsubz:-1339365/1352359843453361,37294708,32650165/49041162900322251:-50435865472518811452953/1352359843453361
+qsubz:64855889/55163734975059261,-50495551,10273592/5300232731771161:2785523192783588706703700/55163734975059261
+qsubz:87062294/350231041000041,87531372,18935971/2964729931492256:-30656203535721753723958/350231041000041
+qsubz:28654577/4766700414359347,-75710062,18946345/966631458761659:360887183906571880304091/4766700414359347
+qsubz:98899630/25197967410013,-94124519,=1:2371746562245248308377/25197967410013
+qsubz:-60951681/826245104735740,90114845,-46517310/138373690437397:-74456949545270037011981/826245104735740
+qsubz:3673134/7692444132233,98053795,-43749749/38563121801152:-754273339990923801101/7692444132233
+qsubz:-16042613/18604599439295,32614949,=1:-606788061878051063568/18604599439295
+qsubz:-18542903/4333580495789,95232673,8705127/3818163979847:-412698454274670256900/4333580495789
+qsubz:93847183/260167494778,70420110,50108689/4318919693752:-18321023600597338397/260167494778
+qsubz:63160383/511521681755,93405210,-8686231/33289600401:-47778790103815783167/511521681755
+qsubz:10995233/136483986795,-35714136,1540987/281295347273:4874407666229829353/136483986795
+qsubz:11840157/22134680227,-12663935,50115473/42408027975:280312151652353402/22134680227
+qsubz:2165532/84739740289,74114119,81643079/62400874960:-6280411195805874859/84739740289
+qsubz:9910853/253156711,83607638,59919120/1185300817:-21165834640647765/253156711
+qsubz:58968716/943992033,-17638483,-40257956/5469268719:16650587485174655/943992033
+qsubz:85910396/690654879,-56543102,-38201318/528835655:39051769356005054/690654879
+qsubz:4001435/163786307,-76984433,46803523/742917958:12608995981560366/163786307
+qsubz:90944610/52515871,87539015,32701282/49688015:-4597187528262455/52515871
+qsubz:46996626/49950215,-40784808,14253005/11778372:2037209975330346/49950215
+qsubz:16216866/657419,8499426,=1:-5587667924628/657419
+qsubz:26087801/6436061,-9418424,-60061709/1990672:60617577475665/6436061
+qsubz:48316307/459047,-25148975,-96687866/162915:11544609843132/459047
+qsubz:82175177/512872,74792479,9314575/111969:-38358886114511/512872
+qsubz:93244651/92781,94189756,-7781135/31498:-8738926506785/92781
+qsubz:65538455/49692,48926272,-470122/28003:-2431178769769/49692
+qsubz:-12968804/1131,-21968160,-33199358/3561:24833020156/1131
+qsubz:-10642810/4567,43054752,29068797/4090:-196641695194/4567
+qsubz:-16504669/331,19366230,-37110959/378:-6426726799/331
+qsubz:120055/122,35383126,21063457/242:-4316621317/122
+qsubz:-6229424/5,84957981,45357911/68:-431019329/5
+qsubz:13067352,40056104,=1:-26988752
+qsubz:-9746025,-39734152,-1201754/9:29988127
+qsubz:26013/7,93156445,90743757/8:-652069102/7
+qsubz:865257379/90357408174523899396,294967632,443698369/37895023238390231028:-26652510722896757331379092893/90357408174523899396
+qsubz:344980185/77047998342627739241,546105928,895790581/53691868371888449511:-42076368635443183496403340463/77047998342627739241
+qsubz:-701770897/9142934914307305747,-480401371,=1:4392278467796997195473208240/9142934914307305747
+qsubz:171005591/1827355652621001622,996389504,-95300137/8222844065780808107:-1820757992346636105956769897/1827355652621001622
+qsubz:-913921523/880602809205096206,-38929444,=1:34281377747192476352167941/880602809205096206
+qsubz:298448428/179100960271183235,-314975674,481319159/261547773510673260:56412445675463162520073818/179100960271183235
+qsubz:48498841/75668495862610916,840770177,14203580/1565428657566429:-63619814659731147478953291/75668495862610916
+qsubz:425310066/60222413302772033,-201447801,=1:12131672730756573677459499/60222413302772033
+qsubz:-940057/1889686623104801,252375598,-199312501/752380091448134:-476910791538674769986055/1889686623104801
+qsubz:-138260663/718501375621144,583863337,699241429/9216930315103608:-419506610809251721858191/718501375621144
+qsubz:-341109904/135846371828305,-320703571,357847807/48145438729245:43566416552730871267251/135846371828305
+qsubz:763032333/814687008627806,672611909,-202445947/307017891884461:-547968184110647301109321/814687008627806
+qsubz:624917837/39308871863154,192138767,126397892/82282223854417:-7552758171946777373281/39308871863154
+qsubz:330847639/89408290233165,395051236,734130441/60162275528191:-35320855565258230594301/89408290233165
+qsubz:241863323/8941917277532,727547638,36393496/593234672785:-6505670794459555206093/8941917277532
+qsubz:-844311241/3424218332208,394767882,35903300/424665745313:-1351771418512168854697/3424218332208
+qsubz:-38997799/537796116092,500842415,30021710/666347170909:-269351105561176639979/537796116092
+qsubz:152248609/304406597856,-602339321,39788505/63196175173:183356063460655344385/304406597856
+qsubz:-585718840/1597344893,-966455736,981830119/83198283632:1543763133624437408/1597344893
+qsubz:781348015/38619662873,624508546,-83818298/66343651279:-24118309507046064643/38619662873
+qsubz:26891135/250398333,-399834495,887194659/4297219804:100117891050787970/250398333
+qsubz:366957713/4214088144,750168389,303961849/7723958136:-3161275713721522303/4214088144
+qsubz:-382233523/802407598,539224619,643293638/180492853:-432677931696488685/802407598
+qsubz:504657599/972138678,943952223,=1:-917652465657723595/972138678
+qsubz:-408988345/21433274,760561192,417030670/7339543:-16301316830890953/21433274
+qsubz:410157974/58771605,-898139207,117071195/99665253:52785083118975209/58771605
+qsubz:-181359243/8378299,999308019,-685030111/5629257:-8372501557638924/8378299
+qsubz:367963568/2283391,533036363,91720099/586329:-1217130065983365/2283391
+qsubz:44939447/196951,46409799,-103285387/76069:-9140411383402/196951
+qsubz:814899293/55934,-36864186,292213674/137551:2062776279017/55934
+qsubz:151776179/86747,-807563906,322468120/95761:70053897929961/86747
+qsubz:-425405259/29272,662984675,715664474/9319:-19407312811859/29272
+qsubz:24777055/3654,967458144,-290540261/2806:-3535067281121/3654
+qsubz:366485985/1627,409846678,116744107/387:-666454059121/1627
+qsubz:87840767/198,-135713419,331986209/900:26959097729/198
+qsubz:606872603/617,110773818,-2999504/3:-67740573103/617
+qsubz:-126522338/7,345173453,=1:-2542736509/7
+qsubz:-107170432/13,706985358,-54309695/7:-9297980086/13
+qsubz:813855667/3,475384819,895215002:-612298790/3
+qsubz:464635413/2,211174932,343207577/7:42285549/2
+qsubz:-1073292494/4835121375628045513,2251773912,5366939142/90030076701246336647:-10887600174992785502795349350/4835121375628045513
+qsubz:9937723759/16929248820944777341,3536220517,5346758168/36993790254509343525:-59865557018022980947303181538/16929248820944777341
+qsubz:1854788341/3248262723951959327,-8297282960,=1:26951754949049775984384956261/3248262723951959327
+qsubz:-906823037/71927651067601606,2683555089,2600732775/4128402288016064626:-193021814062278573712695971/71927651067601606
+qsubz:6194391639/613753365565872866,-6823117729,-5801950686/463111032618663091:4187711469825925275559032953/613753365565872866
+qsubz:7222246398/974438771703442207,-2981326784,144559659/180449736371193901:2905120409447533563947418686/974438771703442207
+qsubz:598767509/618842078099439,467678172,4281762740/40185499542661501:-289418931842226266977999/618842078099439
+qsubz:9493241893/56354383572502234,5379218555,=1:-303142545768791195418509977/56354383572502234
+qsubz:7562126681/5274644967533227,5051748469,-1293127915/1893065732128434:-26646179639254526641752782/5274644967533227
+qsubz:7565520398/6835621275673391,7146311176,-1198943513/715334747317684:-48849476717248123463597418/6835621275673391
+qsubz:8495334411/471195956506405,6785264959,2168272913/863558614872658:-3197189412505389410227984/471195956506405
+qsubz:329831990/194008083833657,4410191432,4944067900/100050586251673:-855612789061931484794834/194008083833657
+qsubz:3921639067/5566583240720,-1672367274,6936260591/2578150592889:9309371639780913836347/5566583240720
+qsubz:2380554367/10517458627732,-7041942370,3279856951/33783400334050:74063337535350408359207/10517458627732
+qsubz:3445818365/3619763010066,895311547,-53891527/6375878985703:-3240815620312121213737/3619763010066
+qsubz:9680947669/4195349234903,9847517105,1869006639/80865949846:-41313773352146274568146/4195349234903
+qsubz:-6058980583/155496366963,4042446763,9119016077/744819499043:-628585785293898471352/155496366963
+qsubz:-1977545176/405611601655,-4869751414,5820473357/314742970445:1975227670692263444994/405611601655
+qsubz:-2162676941/6345800531,1286256621,-697595567/9987397219:-8162327950706742692/6345800531
+qsubz:3392475437/45282237869,6472179727,-5979122928/2366853503:-293074781925541006326/45282237869
+qsubz:4416785424/2111265383,-3271176628,821511083/7068316944:6906321980791853948/2111265383
+qsubz:4093300065/635906036,5062025739,285565567/61253547:-3218972717724160539/635906036
+qsubz:7916328811/940173619,5412477560,6775158536/668079907:-5088668607425160829/940173619
+qsubz:3127361256/855850901,-4692272984,2575948861/541199820:4015886064221719840/855850901
+qsubz:283244715/13702009,963515826,-1674038966/12371545:-13202102236249719/13702009
+qsubz:540577841/30024966,5801262858,9382566733/31524563:-174182719527934987/30024966
+qsubz:7954787149/971554,327753005,4739437825/5416433:-318421788232621/971554
+qsubz:1560609006/1064401,1688715477,-368001807/3080264:-1797468881825271/1064401
+qsubz:-4972657594/362819,8090532645,-203495293/57308:-2935403936383849/362819
+qsubz:1444526623/179543,2853408565,726160202/41635:-512308089459172/179543
+qsubz:4218657381/36913,7674015126,1050342199/14146:-283266701688657/36913
+qsubz:9320467151/38863,-4055403274,308167507/16643:157614457904613/38863
+qsubz:7827452709/3047,-9072276043,5468639/133:27651052555730/3047
+qsubz:778524864/3065,1683932125,1339853306/655:-5160473438261/3065
+qsubz:3472788866/281,6153287472,-7044029756/603:-1725600990766/281
+qsubz:-5843681042/587,6535907369,6873433701/140:-3842421306645/587
+qsubz:1706274151/40,475391167,=1:-17309372529/40
+qsubz:-7106248861/76,-7953014416,1126059826/93:597322846755/76
+qsubz:8857605738,-2247650088,7100250512/3:11105255826
+qsubz:1839886389/7,1649369168,688187521:-9705697787/7
+qsubz:21420789821/10134187221769337622,-67300091654,97875160505/23312037706226247093:682031728863872046028891196609/10134187221769337622
+qsubz:19184556071/53765794610868208511,60577023217,74452356089/4734788160637873210:-3256971788423016947478859443816/53765794610868208511
+qsubz:-7679928117/2767247253219016337,55513625448,18687044299/6286371666239502248:-153619927537207285250890872093/2767247253219016337
+qsubz:38618312951/8137064142866736162,91272025410,=1:-742686325210532613183211563469/8137064142866736162
+qsubz:-70329305757/733471856768781955,17530726893,-36062653409/460161038303613091:-12858294804715129971700921572/733471856768781955
+qsubz:-92664480037/251152784368324677,58676410442,-81532606580/860207074670537961:-14736743859246940544233557271/251152784368324677
+qsubz:38165401669/68739156230002569,44174230933,-23746763849/25990052797565342:-3036499361443699108023865208/68739156230002569
+qsubz:9045716812/13158209333079373,-79399582136,-87223831269/2510586287796491:1044756322704517467366597540/13158209333079373
+qsubz:52939174938/4974456626264035,87493688728,43147212680/2387939387259719:-435233559649282454892122542/4974456626264035
+qsubz:81367771694/850281974804851,92502648537,-69900752953/1391561070523707:-78653334672719339847881293/850281974804851
+qsubz:-85053146313/639164379192017,54673455287,13200170243/100963367078830:-34945325106797939689990192/639164379192017
+qsubz:20156443510/20773119248737,37480014907,20271435745/312278412786689:-778576819107531244478949/20773119248737
+qsubz:-10838886733/6871945259460,92773868860,6711171275/80361105218191:-637536948314251553302333/6871945259460
+qsubz:97173191102/49466168642747,17726036129,12845931025/12225527003766:-876839092524443042615261/49466168642747
+qsubz:95109045/199572919304,-36806647761,19117093237/4980142825265:7345610143456900387389/199572919304
+qsubz:-19508332357/8876460386507,29224737608,43187977743/4349125197230:-259412225683492846987613/8876460386507
+qsubz:12109709171/148689816535,84702134869,23340728701/21524306891:-12594344893782326549744/148689816535
+qsubz:70406287853/869355596938,33776459373,55742597576/52660518145:-29363754000596113912021/869355596938
+qsubz:585222646/31985233215,-81118619,8164685068/93850613725:2594597947378952731/31985233215
+qsubz:46451898407/8549297194,35096580302,=1:-300051095448432374181/8549297194
+qsubz:60939385/27011903,-54212225249,34047977198/2734124659:1464375369901078232/27011903
+qsubz:27241414109/5032121410,-80524782294,=1:405210481044467728649/5032121410
+qsubz:-1517062448/92397599,82706710904,32781270955/804186901:-7641901510233781944/92397599
+qsubz:-72090700936/254068779,44740138239,=1:-11367072366764641117/254068779
+qsubz:-32335979955/7707637,-5502717532,2999795591/1166575:42412916914211929/7707637
+qsubz:-24159394717/30439725,42916822470,3512473831/6138983:-1306376298020015467/30439725
+qsubz:-83277071349/5625575,91497956206,=1:-514728698260639799/5625575
+qsubz:38672562477/8826391,24030139693,-6160335294/93847:-212099370042475486/8826391
+qsubz:-3384269055/64964,9103457689,30554917387/326314:-591400409577251/64964
+qsubz:-59571884431/32240,-81755116216,408787901/1755:2635725374919409/32240
+qsubz:48229096314/54161,27903967566,=1:-1511258558245812/54161
+qsubz:20045879099/62217,-64596206712,-66029045734/75381:4019002238879603/62217
+qsubz:23489616563/872,29670916860,-5971297606/557:-25849549885357/872
+qsubz:83219508219/5974,15772230677,582785677/54:-94140086556179/5974
+qsubz:6729510238/31,24272198233,=1:-745708634985/31
+qsubz:16173563552/113,27486903185,=1:-3089846496353/113
+qsubz:-47472904273/69,7141425373,6439404343/56:-540231255010/69
+qsubz:51824444351/61,-52527701227,=1:3256014219198/61
+qsubz:-28091556651/2,5950022569,-3627844227:-39991601789/2
+qsubz:54841455404,-4522114796,-49302775324/7:59363570200
+qsubz:582044754139/56293289312589333700,543100653961,-293376120510/22101874091130677947:-30572922239283039282121211031561/56293289312589333700
+qsubz:863378183609/36104436361383843452,7988014019,=1:-288402743802827490871299169979/36104436361383843452
+qsubz:310042961637/3290967571160173688,-218205349633,481594120353/6095463672099458281:718106729495870507345090018141/3290967571160173688
+qsubz:332189704537/4416708145100434021,836207829003,9340261402/4185349277685404729:-3693285929354301043761262006526/4416708145100434021
+qsubz:-249460520992/202110419372893751,428458525044,-44611263972/42616655580362771:-86595932180534340237045121036/202110419372893751
+qsubz:122311231452/75027142810316983,377180651007,-741450514659/647861091739096129:-28298786568390519041656920429/75027142810316983
+qsubz:13278459816/99368908017329513,705837543053,20559860194/117508700464855:-70138305890811416988946563373/99368908017329513
+qsubz:973128819452/9328598030058051,-470123313629,-372304176079/29720264187522870:4385591417403853652478296531/9328598030058051
+qsubz:-43724262678/1538974313385071,155441438418,321158859675/1414718865236666:-239220380960929390691320356/1538974313385071
+qsubz:297720090859/6268772602498826,-683800722712,195404651967/567524423173634:4286591236105882613651626971/6268772602498826
+qsubz:-478151981509/569806807788948,393132978368,429377458060/939853885300617:-224009847440432106145458373/569806807788948
+qsubz:646410569317/333338235834566,-549506177325,=1:183171419729712340170985267/333338235834566
+qsubz:51236525512/4913829572565,518862556472,849462110245/92311588868614:-2549602174088739697865168/4913829572565
+qsubz:170018414037/33080905332140,27360261367,430903523746/37958380653475:-905102216144164327021343/33080905332140
+qsubz:389185485712/9793322203883,-659024335733,59021105873/481883158776:6454037660033622853736951/9793322203883
+qsubz:909632962214/4281741824583,12584416260,=1:-53883221437494739957366/4281741824583
+qsubz:-433649087373/555105608969,522178231717,636663919751/434542406633:-289864065308054524557146/555105608969
+qsubz:226289850773/240939721173,-779455912091,325469197331/306494129848:187801890126078229253516/240939721173
+qsubz:-28728778059/3012978130,-106991553027,613396487281/79642465446:322363209336357521451/3012978130
+qsubz:78754526716/14242413985,431207764296,152553713159/10855948650:-6141439492571179552844/14242413985
+qsubz:387141036389/5539390134,145933365862,=1:-808381846690234169119/5539390134
+qsubz:205234713289/2404538676,831396150355,445862618338/245594955:-1999124198400873916691/2404538676
+qsubz:406556133145/882230806,-177285397339,-907530046754/970980799:156406639392972358379/882230806
+qsubz:-437068913804/579574371,60088259224,=1:-34825615481303661908/579574371
+qsubz:30508378793/3569747,-780792504756,198433507438/97598395:2787231731983595525/3569747
+qsubz:196609293534/8130889,426393278342,-296591563367/98318012:-3466956219935612504/8130889
+qsubz:-103665512384/3219407,343041471685,327414529149/276949:-1104390218898503179/3219407
+qsubz:15404741180/341451,869230362129,339893658990/5534429:-296799560974567999/341451
+qsubz:-209751243565/196919,-569752205869,-11109223799/401194:112194824876274046/196919
+qsubz:-83409156386/117227,525814065374,791933892737/764822:-61639688850754284/117227
+qsubz:-104685303052/62283,-731959248807,114243681256/7429:45588513208143329/62283
+qsubz:895224938428/69119,-716278812153,-90243582193/10681:49509370442141635/69119
+qsubz:42133988649/3631,-445162819995,-954951120397/5875:1616428333390494/3631
+qsubz:112664025666/277,503116531409,247371933467/111:-139250615174627/277
+qsubz:284809115647/66,672615493530,554002682515/271:-44107813457333/66
+qsubz:5127131051/6,-212712172623,=1:1281400166789/6
+qsubz:171390839296/35,-82337476599,417661388196/89:3053202520261/35
+qsubz:191091147431/39,-920358211719,-25819031162/73:36085061404472/39
+qsubz:807118523227/5,346448150075,80611631468:-925122227148/5
+qsubz:418694152501/6,739403431228,-129305925739/8:-4017726434867/6
+qsubz:126259912535/19744860018986912314,1555457055296,-3487093339153/28692815598057427812:-30712281822365105276971541402409/19744860018986912314
+qsubz:-968360818288/10957042492839702615,-2258597022367,3154775409189/49421866618340899520:24747543548276443243508422571417/10957042492839702615
+qsubz:1890330468609/2410198493801717930,9205721307529,=1:-22187615629764777182735712826361/2410198493801717930
+qsubz:1034477250607/615640323458489068,9353407953800,1425836114708/170749360405788367:-5758335098116636371727071807793/615640323458489068
+qsubz:262340294343/741793310935990,-2150652932535,=1:1595339959499334241513728993/741793310935990
+qsubz:5309424088963/684908358112044502,3522078056131,-8179152756076/644669401491648789:-2412300698567144519392901852799/684908358112044502
+qsubz:3588674603747/1545966035679074,3212946088828,=1:-4967105527796005520630181525/1545966035679074
+qsubz:-4534453995828/32270512908519613,6589946455938,-9801838977275/38162912829764278:-212660952172800308629967307822/32270512908519613
+qsubz:2685068067884/3336975215402057,-7595365246836,-8811372244318/6683370423107785:25345545580617861619855209536/3336975215402057
+qsubz:543922202681/1166407376560219,-6302819775757,4908003544930/9587540580797447:7351655479572590719509013464/1166407376560219
+qsubz:1156846910145/409653034339684,9351664480220,1708516236439/66993814409903:-3830937730448765627932140335/409653034339684
+qsubz:9324441180811/420640541106436,1370697368460,-1313111911158/152906436709229:-576570882762172957528227749/420640541106436
+qsubz:-3788617052905/39205078029262,1228798560487,=1:-48175143446141445080023499/39205078029262
+qsubz:-7794396369241/56330672452520,-7704693024950,871554050776/21153823483007:434010539135666159654004759/56330672452520
+qsubz:4137136201806/8737070701967,-9979643114697,6058666158875/9867656564998:87192847473509993220710805/8737070701967
+qsubz:2641531019871/5593201879555,-4265291606149,1130816894271/2795283200510:23856637028365393126403566/5593201879555
+qsubz:8014147074772/512942258297,-8116516720099,876859202116/274307119021:4163304415920954656486175/512942258297
+qsubz:7059941701479/197648480521,8708557606758,=1:-1721233178498254999259439/197648480521
+qsubz:3755712200003/217202180,2401179822277,3189798795928/5096167231:-521541488214864763857/217202180
+qsubz:5560957786655/41651212441,8862436005090,=1:-369131204787209989538035/41651212441
+qsubz:-9615360976410/8344722377,6598017106271,700561666213/7396251362:-55058621000143761702577/8344722377
+qsubz:-1589748773573/2251431553,1769925300090,9628158560519/9021450241:-3984865668665368513343/2251431553
+qsubz:4945046252645/140767167,-3087509026163,3397834417837/518301300:434619903644940642866/140767167
+qsubz:1602058825487/99985791,6831864885925,3194690165276/457014865:-683089413022277066188/99985791
+qsubz:4764685272484/38991805,2571787873727,410456342572/677513:-100278646509042534751/38991805
+qsubz:4983758675551/20456287,-100153673261,=1:2048777268089917458/20456287
+qsubz:5694289753177/6317218,3418777293359,4923010338011/2845899:-21597155761309002085/6317218
+qsubz:329203322035/1858873,-4317791382401,5975893406151/9192155:8026226149581216108/1858873
+qsubz:4335665925075/55982,1656849962526,181594437680/67803:-92749438936205457/55982
+qsubz:9709390247427/166663,5132356269680,-3016218694867/745383:-855364183583430413/166663
+qsubz:-4359941557652/86109,1888975613916,3532475125997/7807:-162662161080250496/86109
+qsubz:75022830289/2220,1146635653662,6798944526217/46106:-2545456128299351/2220
+qsubz:4100868613295/1849,7054226490020,=1:-13039163911433685/1849
+qsubz:8649747700020/5381,3828262903125,2064106492493/761:-20591232934015605/5381
+qsubz:8502529839374/915,3194584992739,=1:-2914542738516811/915
+qsubz:9574702992505/246,5116051092239,5492259470317/599:-1248973865698289/246
+qsubz:-2543724436678/17,5669830231740,2153080048221/11:-98930838376258/17
+qsubz:1139363340091/4,4576282403250,1187287585095/19:-17165766272909/4
+qsubz:801445681414,5625028722145,=1:-4823583040731
+qsubz:287567579499,-5591174678442,-4382414917357/2:5878742257941
+qsubz:-715733231768/486064740545382237,89623634634077,58742041670676/35324168704538737315:-43562888715146770490499323922017/486064740545382237
+qsubz:-75727619487742/10388202751580825775,96108515478673,48660513204241/1818946673143737333:-998394744945899243492150360684317/10388202751580825775
+qsubz:-96029325769707/9893650986371005511,-74226005177085,-46687636878977/2387058458323178030:734366189334646371739993740145728/9893650986371005511
+qsubz:35783358055412/1552476032897596751,43490497059466,-1079321111837/5800379511336485288:-67517954343624372543080377339554/1552476032897596751
+qsubz:57789813906856/971696921385158133,2391642623404,863087819839/4775785527716489:-2323951774215189888927692837876/971696921385158133
+qsubz:-77070689378461/283257676299534021,-94811904810524,3607206487153/28906915118888592:26856199842161639591718807458543/283257676299534021
+qsubz:34509538492008/72304248340579153,-41953401106124,=1:3033409132309117863454513524980/72304248340579153
+qsubz:1340089579409/19730355565997710,37067446196524,342940118101/16746159833490834:-731353893380907947460704380631/19730355565997710
+qsubz:3919216713549/2250316629207754,-29394351385551,2872931002859/32162204014599:66146597727681403624549476003/2250316629207754
+qsubz:13914230734213/7377733041063051,68650193198811,-10400363504789/7533498628147940:-506482798638229846031398498148/7377733041063051
+qsubz:8362337855011/33881947681545,3976758804466,=1:-134740333755032092353924959/33881947681545
+qsubz:-79790637400646/303532319009043,-60289205709726,=1:18299722420286289131189651572/303532319009043
+qsubz:49164617138338/49329628036955,77336493302650,8067608439485/33220679284796:-3814980448302136859582292412/49329628036955
+qsubz:-22432972371586/38951076862109,-92458433570223,-31701633786722/95207688313893:3601355552543932683767008721/38951076862109
+qsubz:-4621525773709/140347977321,34467754323165,49739152325557/4329768753107:-4837479602057982650714674/140347977321
+qsubz:-43517481518770/3452004002879,30104767625988,21895741020071/133893785957:-103921778350696223428738222/3452004002879
+qsubz:52840510018437/757153700674,-23243061688718,81530288553473/77422952760:17598570172659746044814369/757153700674
+qsubz:66795802116211/748770475694,13193952800144,=1:-9879242314381210389583725/748770475694
+qsubz:40654512282679/28351746821,-94129569333945,4668047575488/16185258151:2668737718166428753421524/28351746821
+qsubz:-8794421645897/53319870337,-20198498303046,44580016832223/49670829584:1076981310511732830500605/53319870337
+qsubz:33181476617649/4377168145,45758335183370,79624732407833/456222057:-200291927099698421131001/4377168145
+qsubz:28405759396583/2581458592,80820518399572,-54287042127266/4414416479:-208634821604063469126041/2581458592
+qsubz:20477840610563/180143060,-48654124735301,-16777846576721/391089816:8764702931916652771623/180143060
+qsubz:19988889540450/80587711,60651285384749,-44648119713661/448244778:-4887748238375786679089/80587711
+qsubz:-52456127766149/43656429,6722399471849,16794509454023/64472294:-293476007708541133370/43656429
+qsubz:79338612639523/4449964,42881321722350,24368081230145/16600353:-190820258598262855877/4449964
+qsubz:-36687850855147/3594342,40016343462709,59189303240521/1278571:-143832460682291247625/3594342
+qsubz:-30566194381329/2595937,67081788792968,-67923038242759/8884794:-174140128120045352345/2595937
+qsubz:-6295335911933/438252,-44734738625819,76501444579927/371738:19605082376906516455/438252
+qsubz:27767502414109/413061,97215608337806,34631303453755/296748:-40155948628120070057/413061
+qsubz:37136350760161/3002,-92175327996582,76466821875271/29733:276747470996499325/3002
+qsubz:2935626294482/5109,20674608574976,-2365106865080/11931:-105623639583257902/5109
+qsubz:52812699008901/2884,84249241650178,6737583755031/134:-242922000220104451/2884
+qsubz:-65470998619593/2326,32262904613011,=1:-75108987128483179/2326
+qsubz:78999075171323/661,-10593407332566,=1:7081241321997449/661
+qsubz:1731396778013/5,56049768012708,=1:-278517443285527/5
+qsubz:-8277249758540/11,59885952775145,-25291842793412/45:-667022730285135/11
+qsubz:-42440035424938/57,-39767184220346,-904504982593/8:2224289465134784/57
+qsubz:22865720041019/4,40904975798004,8075381981923/3:-140754183150997/4
+qsubz:-21922184931013/2,-85282941031136,34448564580295/4:148643697131259/2
+qsubz:-246867251356781/34913747863834817207,99725282227818,=1:-3481783359351804958476515011821107/34913747863834817207
+qsubz:-305181664167009/90807051195363677740,-556419009100301,=1:50526769445444561004327150236832731/90807051195363677740
+qsubz:338648296555449/4263692604904527856,496604482821540,809299601354051/8236031413566206038:-2117368860968637737678068110262791/4263692604904527856
+qsubz:-229143629870713/5276801568796926466,-709348348254893,403852851463129/9918468826070875579:3743090476894927918180789515827425/5276801568796926466
+qsubz:541314787008921/969761679678247393,-625023945769056,-10730423739323/107949110676011946:606124271488125555126774399079929/969761679678247393
+qsubz:269697710637581/986639032055630686,-647511576454662,81783586137827/121738862044573311:638860195038043221027996005595713/986639032055630686
+qsubz:-688966709079205/74860741099180639,648207519211481,879845264372555/41946111313649477:-48525295274232840016387170795564/74860741099180639
+qsubz:166710353298975/16970305651247011,-698094548558201,213765522314/321157776265937:11846877862501969531938114086186/16970305651247011
+qsubz:49899180545856/2876267857739683,557467828819843,18059812167469/275257158459484:-1603426797758442090812218383913/2876267857739683
+qsubz:6692317961394/141734941248049,-441438992382050,647025798139055/12642657149192:62567329649867813522743081844/141734941248049
+qsubz:479537992567656/157885618980541,477496194629370,723421646353653/802564393977836:-75389782249910480040744521514/157885618980541
+qsubz:908470734681149/429897226733416,29178161829135,=1:-12543610851523044744852194011/429897226733416
+qsubz:77188802685248/7318291809111,-463455255292264,-108058346785819/1176426648669:3391700798694900254405702552/7318291809111
+qsubz:171404401104613/33934604643401,855275555777772,36574880343413/903775150870:-29023437846483581280861177959/33934604643401
+qsubz:-541340901900380/6622210685537,359991433354457,757631862823376/2232325778223:-2383939116662207278386288789/6622210685537
+qsubz:692469292076099/5877109446415,650562123345311,-533032945119773/2302096119676:-3823424800591835209803933966/5877109446415
+qsubz:-95311828811477/314989654006,189810882360044,-28308634395237/5347103791:-59788464161259140107747741/314989654006
+qsubz:698022114495799/176594100926,695874989112564,-126581470685793/77926271237:-122887418058525256076138465/176594100926
+qsubz:842269707991031/20902452297,641480824512781,-207378748871278/20625232021:-13408522332976363411316926/20902452297
+qsubz:90008215456199/31308617602,-364998910104603,7226822032963/10002572848:11427611301701797362478205/31308617602
+qsubz:-351501780974067/3968320430,622136787208291,55114547224579/2370456759:-2468838123284725621659197/3968320430
+qsubz:344449638260631/4282977544,558958638427895,637819877664383/3604552102:-2394007296067040109929249/4282977544
+qsubz:210466623353876/42415731,582912199285926,-497147675534948/306590031:-24724646831063605948030/42415731
+qsubz:159664413249106/959545307,-279292307566119,-653584191266708/745665815:267993623165934491902639/959545307
+qsubz:-392198737412127/18608647,672422899635821,-569033599510242/82909327:-12512880766238158956314/18608647
+qsubz:39300503655213/2721430,511724197547707,59370211633018/15974095:-1392621543631752605797/2721430
+qsubz:87754948235651/938752,383351463740417,375522385390265/6961414:-359871865534295703933/938752
+qsubz:41618261156437/401439,-114295722812862,220994573438802/7353641:45882802288533664855/401439
+qsubz:583595357599684/369917,-921858234302871,506477458084177/879257:341011616053972731391/369917
+qsubz:45271960096970/353353,134033050982156,449578874064836/569165:-47360935391737672098/353353
+qsubz:226890272517543/20945,-473968771427454,474551299506991/45887:9927502807820541573/20945
+qsubz:-684400875331106/63053,771762142119055,263139740728045/52269:-48662602747908106021/63053
+qsubz:34178215463647/1460,-574309051342644,-63579349430280/3001:838525393175723887/1460
+qsubz:304677119786896/7379,953072503508023,=1:-7032417326265914821/7379
+qsubz:690712418406353/551,-878220570482942,945308150006353/640:484590246754507395/551
+qsubz:563742800297603/343,-370471036590769,=1:127635308350931370/343
+qsubz:21771882327450/17,838540815832625,=1:-14233421986827175/17
+qsubz:-70429366835830/23,421029379926378,193588248726221/68:-9754105105142524/23
+qsubz:579884703987868/9,158994766699977,-448423246325295:-851068196311925/9
+qsubz:211206174985053/5,-931363857001162,111347832442520/3:4868025459990863/5
+qsubz:-1832545914230682/30139417405441315141,-2206272301963151,1860280227521645/86203654952388608222:66495761818931270288235871646138609/30139417405441315141
+qsubz:-2244126580089402/15802353325367691233,4284202352680604,9672828494536963/16956491871832558298:-67700479294430428930131058720034134/15802353325367691233
+qsubz:-2873054508761746/4018888696438887255,6328415852872821,1498506651106845/518044831134554573:-25433198937475240507570306781558101/4018888696438887255
+qsubz:7896973515418738/171152447613110907,28172470782975,2496184225627819/8379223243264936533:-4821787329815018407032286989587/171152447613110907
+qsubz:6171557047136737/153596772628473013,1680648096723096,-1368752415341766/146474119282103663:-258142123580853290414834522671511/153596772628473013
+qsubz:6110188097149881/174980302833168079,1110459252556,-1094629510180661/186263856652338951:-194308496296136243983761210043/174980302833168079
+qsubz:-3332313275107576/6438318281683471,7900787008515747,=1:-50867781436614198716281448225413/6438318281683471
+qsubz:-7156623476138575/60768468431925828,4848185091878538,2590883047783370/29043794443881857:-294616782707954363603301077218039/60768468431925828
+qsubz:6244864610487455/4441450329956024,4695453677641407,8682107496188525/1108836802236426:-20854624285853647226021740998313/4441450329956024
+qsubz:1214388452257501/8099557799286469,-7732646369856166,439856662355753/161507957350071:62631016214092712520853412275355/8099557799286469
+qsubz:152270808963307/225936249720782,5032164593494515,-3042221834459135/169235048654169:-1136948396231854028931589547423/225936249720782
+qsubz:2643724012201914/307126445994791,-693785933640383,=1:213080008080151385664497446867/307126445994791
+qsubz:-4268051553498140/95366069343373,-8287002357898623,-3054534942105489/17777545496443:790298841512051368610157377239/95366069343373
+qsubz:3485602780203412/25700401711199,7457017497637979,428269713159377/10715443614396:-191648345256732514829431823409/25700401711199
+qsubz:-8234491447936746/4919684964695,4149505619200689,=1:-20414260405707280268532611601/4919684964695
+qsubz:810546492778734/1537255953059,9694022516419974,9086115085796596/3823340626845:-14902193822453782061581221732/1537255953059
+qsubz:-5877831901958825/989824365981,-7295262013116067,170001713972327/26272141179:7221028096792006892537357902/989824365981
+qsubz:413656776972827/989269893760,7369973639327299,-436236958984308/162577127395:-7290893039190903982820781413/989269893760
+qsubz:3878951355242185/83694892558,3450947753988635,2108640605094263/15564008636:-288826701489471270922836145/83694892558
+qsubz:-2535073297478552/40453071523,4908538742513000,7101922105535221/34207081432:-198565468826829943054777552/40453071523
+qsubz:-2382309885993389/696509530,-1466852366874503,-2309936099592793/3712437025:1021676650248837767520201/696509530
+qsubz:7607952043533620/5686913259,6298086275997422,4940928909130479/2342224064:-35816670341687720578084678/5686913259
+qsubz:2927215245836138/37741447,-962144281698956,=1:36312720341309463665470/37741447
+qsubz:4910061305028263/340473560,8119898610953665,=1:-2764610782000388012569137/340473560
+qsubz:4067805811057167/37177673,5330125030512986,-1997223198941339/66900704:-198161641365721004704411/37177673
+qsubz:7759637046791302/19652141,-310036804999994,=1:6092894766686433878456/19652141
+qsubz:3919065179535201/3669449,-9390389769263598,2882022398896797/3976985:34457560267499719952703/3669449
+qsubz:716031381446830/216733,7947765435310961,=1:-1722542330059869063583/216733
+qsubz:4054967994410335/373802,525724563764829,3503712661359490/252721:-196512838416426199523/373802
+qsubz:9078916136353979/203034,-9146320842030949,-2957406411653994/351673:1857023184757048053245/203034
+qsubz:6377608393262961/38293,5049392078825515,=1:-193349993266072182934/38293
+qsubz:6441803794276323/46595,-7945891506343445,444633258633711/77876:370245256541867096098/46595
+qsubz:-31739640835113/134,9187216015631531,4944420675707143/1828:-1231118685735460267/134
+qsubz:9380863138336115/5303,6462848225018826,-6700633266931069/6325:-34263103274136498163/5303
+qsubz:-3097631232518591/9,-8171290453822216,-9196963695173/266:70443982851881353/9
+qsubz:1093336426937324/7,1050221975761222,4629256617357701/951:-6258217403391230/7
+qsubz:-347597167946897/2,7674954857028324,305176137974688:-15697506882003545/2
+qsubz:2328475415769504/79,272925582329873,-6102549509203995/38:-19232645588290463/79
+qsubz:2308509394585516,-3830045206470274,7003553193110811/4:6138554601055790
+qsubz:1732760946956491,1777160492223769,3345447948158671/5:-44399545267278
+qsubz:60622144360049674/33802404082907624055,-69039399995425550,51265382108255056/56157062688150984537:2333697696286865212886332363501654924/33802404082907624055
+qsubz:36134312588149621/46726106282722203568,88368419250610983,16599233636304207/89218481321406581495:-4129112149940203572739672031514437723/46726106282722203568
+qsubz:20529608710739058/363448886403849905,-38414609254761218,-28483290600430736/9731878244397435811:13961746955281991196780195397723348/363448886403849905
+qsubz:-21301556721438976/6513242985788039333,10185328317205357,19471190728639913/1019778013146869138:-66339518219986085639448723675745857/6513242985788039333
+qsubz:44545192250412223/556091898773307973,-68210916338593275,48338123621716519/630903301445119154:37931537983795590439601289412093798/556091898773307973
+qsubz:8756185550667068/221237800002764551,37082500190782117,-49571575251913483/428549478410686743:-8204050760810732298651341341667399/221237800002764551
+qsubz:1266875902956333/74065487263129243,82179201358611673,-22809095236679413/11512992706379829:-6086642591520386247198936144497206/74065487263129243
+qsubz:-3290636228641958/39922728219039171,27776924787657947,38458678927210417/47863542399556842:-1108930619058360556827999971083895/39922728219039171
+qsubz:-42130079299808296/8434875921605067,-11019950142983699,-23447400609379164/121422770092321:92951912118341475833697196994537/8434875921605067
+qsubz:4099885603797749/2435210469429361,74350793422542339,86927824732188143/8409742118553639:-181059830552954771443357588417630/2435210469429361
+qsubz:67669333773707083/272613019755061,-93798347274264096,-45708312696783257/349531962793823:25570650698471097774452720296939/272613019755061
+qsubz:90957430568123489/391120597363954,6192418291726731,47258016849281278/236338757046761:-2421982341387543639094949530885/391120597363954
+qsubz:9680926001959435/35332948152676,87479517830701337,69091152204102197/219079971218:-3090909267933256327145631368377/35332948152676
+qsubz:-2401057520785223/6794448427129,78594993607525862,9822515380715691/6307070974391:-534009630696870303660610695421/6794448427129
+qsubz:-35669437330800467/9924679089374,82178011946947185,7494777953306900/464563380743:-815590396776229150262403512657/9924679089374
+qsubz:11660103886719350/702376882271,76866897184391316,33851103741574544/1043053682715:-53989531594206620633040039286/702376882271
+qsubz:46821131628705451/862314840987,-23194527064543517,=1:20000984917477331879225436730/862314840987
+qsubz:161045881718771/27075945293,-43271044257960465,=1:1171604427099680375978560016/27075945293
+qsubz:-60112156053007651/36372620700,39791023371344653,1476360991693221/6530487026:-1447303800410866468595124751/36372620700
+qsubz:93025606850655363/57750297227,70375311017089745,-20809770167586319/6537747728:-4064195128586474843432981752/57750297227
+qsubz:66318318188267865/1763416382,-8494345308336372,25978643271663860/9056806641:14979067737403517739513969/1763416382
+qsubz:39872461457095153/7697794394,16021018477534333,-29038307872337798/2023268917:-123326506182661742052834049/7697794394
+qsubz:-10578481873157050/399979569,-74955252966976839,7152087282045522/102539471:29980569765438885423045341/399979569
+qsubz:78420049286413657/598935089,57793609900514480,71630428375584251/480499416:-34614620810975871938175063/598935089
+qsubz:-27519033180387711/13885085,57110868026002395,=1:-792989284483858645166286/13885085
+qsubz:112418468340001/301745,54405933003593985,=1:-16416718141750998663824/301745
+qsubz:9174319448294783/1062136,97028070754069006,=1:-103056997784124389462033/1062136
+qsubz:-11682605623507087/1833691,7208465426749752,42708279458013085/2810354:-13218109859447803001719/1833691
+qsubz:2812356728656513/534935,68388753901027584,97245878303468343/140699:-36583535255689461990527/534935
+qsubz:31551448030819707/330632,-80750562495416306,5621444274957506/269077:26698751530432514905099/330632
+qsubz:-33849467579218205/69497,60936973306267634,=1:-4234970683333260978303/69497
+qsubz:-10824831395257468/25447,96813598240824230,25910641834610055/22417:-2463626459265649438278/25447
+qsubz:4701573695056803/1438,20730190652622936,22128237033227327/2325:-29805312584776725165/1438
+qsubz:19342403188073667/1838,77710503528688069,-29951149360890159/1909:-142812563082540597155/1838
+qsubz:20926018629804348/149,51657522271692972,=1:-7676044799852448480/149
+qsubz:13573480210796164/447,33824716809070641,1445132915921588/9:-15106074933443780363/447
+qsubz:-42143315976323015/51,33391903738170435,=1:-1745130406623015200/51
+qsubz:-28698219386640759/13,83268075330816132,-49006503722648020/31:-1111183198687250475/13
+qsubz:12975981398542545,18975161321245933,550313867201012:-5999179922703388
+qsubz:-4164064005006797/3,12081203464497637,84626976109311453/4:-40407674398499708/3
+qsubz:-477106876207656134/7877944473247978593,-803086328922597207,311162678588479799/34146563555720051689:6326669506476782929117540896089933617/7877944473247978593
+qsubz:-465449358463997555/82259489098814668274,78609606376504442,23623692298759933/1909856158146778290:-6466386058790179182859588942381470663/82259489098814668274
+qsubz:55657155637787468/352243932662032145,931147756136809511,-706077458182178492/4890139950764490669:-327991147511056658341169010385943627/352243932662032145
+qsubz:-338412710404804019/9240924616405735378,180507301532576790,354994699428236406/1584136814505879965:-1668054366173361583178755373609480639/9240924616405735378
+qsubz:-278052766531165423/213589938382221126,-717335569765330249,327115671099490325/973040503527761492:153215660145552371350937879003474951/213589938382221126
+qsubz:319790079757993429/85843803189992002,129266654884522405,=1:-11096741280935559317469625781811381/85843803189992002
+qsubz:647723610543155092/95934901226294863,10437868520469255,655999718116549702/60165561163831581:-1001355885524269831096747212781973/95934901226294863
+qsubz:-490792959368504510/8839690905932849,780493070335457531,=1:-6899317495987951906756776145840329/8839690905932849
+qsubz:200230806231530877/534053235743650,574182776580143425,=1:-306644169740898654458247301470373/534053235743650
+qsubz:-415400268260899058/3432173800064079,-969417138049457063,=1:3327208102546448501242352298240919/3432173800064079
+qsubz:610500835640448509/244349286982576,-726909463539500534,141143959595247333/41552246570044:177619809116764391827142641144093/244349286982576
+qsubz:136794096998673790/125947220203517,501933222844173130,=1:-63217094145015905841679184224420/125947220203517
+qsubz:37195166234504707/4122583546869,350304198433672874,288669113811749979/50036393133086:-1444158324861755915971558426799/4122583546869
+qsubz:-220618681215838560/14377665800771,8868226871326041,=1:-127504402201563441934106016171/14377665800771
+qsubz:-178245325407305280/431875286797,92993296137381601,775757861791511902/3521879350061:-40161506439708276569913327277/431875286797
+qsubz:479413403799611117/2544433559696,571317426935469616,=1:-1453679234333296934118530585619/2544433559696
+qsubz:78548226516829117/75731440956,475186597103136792,372968862509778142/473438190991:-35986565721520216379222424035/75731440956
+qsubz:356871544245112943/457036865155,380199263690323829,=1:-173765079610907947968711165552/457036865155
+qsubz:164087683390841152/9866781011,414256053008139562,142080480091212971/28353008652:-4087373757348433175388616030/9866781011
+qsubz:-926767597190934385/71130390483,424803581672574937,997220370520185575/14320267108:-30216444643874005118080058956/71130390483
+qsubz:-508670075791922879/7201821098,217937729927638852,137262476496651971/1332969124:-1569548541951765573450022375/7201821098
+qsubz:708541217086167290/1270367493,137055529956144222,612951099738164089/8319475532:-174110889283632118162408156/1270367493
+qsubz:478290371375801493/32509979,-621018688752149419,=1:20189305008230285192353694/32509979
+qsubz:202407674710634402/98360799,438420143767171363,805524032483129161/407774601:-43123355436226170523964635/98360799
+qsubz:750240893218756098/12726925,682819412842796873,556437922516174385/42980509:-8690190705553419374149427/12726925
+qsubz:239662400690312894/37085945,-617903896056362368,=1:22915550144094372370030654/37085945
+qsubz:547526163264525237/6384643,925215752491576731,243367286469210971/2199851:-5907171730108914670016796/6384643
+qsubz:488339838572246377/8987524,833735135695423197,67144546497217911/577715:-7493214053366034100947851/8987524
+qsubz:54158926298615969/463896,903750262214101670,-323417221290610907/56479:-419246077481146609690351/463896
+qsubz:899979201562416758/19011,36874785972814972,333938930051256853/431121:-700126576927623015934/19011
+qsubz:251495623875326929/9839,122446851891915382,980630311370393757/34454:-1204503080140680116569/9839
+qsubz:586639670688982327/24017,-796132898656953871,-681706178572361176/45543:19121310466714750102134/24017
+qsubz:-102851779508569447/3820,-939797330665416187,=1:3589922951362381264893/3820
+qsubz:197733827323726961/1063,970508998896485514,-112039443168568153/1485:-1031453331999640374421/1063
+qsubz:798475189524604680/239,365694081282229859,=1:-86602410236928331621/239
+qsubz:142434970975405303/27,565787783866093670,80082655399847437/326:-15133835193409123787/27
+qsubz:814435903223223400/23,934520995176210672,824076522724149791/98:-20679546985829622056/23
+qsubz:-342004432352715490/61,708047941844384558,-893520674572963797/68:-43532928884860173528/61
+qsubz:188506043793261871/2,173381870849138370,457155699541150681/8:-158257697905014869/2
+qsubz:-195061562764744895,-579261672564430749,572618332809556695/7:384200109799685854
+qsubz:-5211865465872518894/11421997512267397151,9216468347981324231,-3730577014383987231/46090107429011417798:-105270478542533892972691061438449184775/11421997512267397151
+qsubz:443443414160163915/4491468994021274354,932514129347471790,=1:-4188358298450913632328975749705309745/4491468994021274354
+qsubz:275361187224379309/346698790548066715,-9688017663470973747,1805402917593442446/2385740059851766675:3358824006733693814162539396593910414/346698790548066715
+qsubz:1927916840762649449/644266943246233650,1019481372573774207,=1:-656818147604580167864072677502816101/644266943246233650
+qsubz:3969083678872801204/896572266795201101,6807779792226215707,=1:-6103666560158821383204536354397092203/896572266795201101
+qsubz:-865341312927331777/288496053508154740,8626492255839507491,1039454095259162685/156542247725866016:-2488708971428357042860912746744489117/288496053508154740
+qsubz:2279766799414118849/27989015333357246,61102716510638539,8643998670150313515/44107462445321072:-1710204869326040746987478648384745/27989015333357246
+qsubz:-9598524755027771179/55399943240765642,-815430339648713125,884311989519445007/53819690104622587:45174794533336946781627589986680071/55399943240765642
+qsubz:-2021737476156144347/2495236846065565,3202240405398277170,3178930774678872133/7381295168863952:-7990348249509715413422020018795397/2495236846065565
+qsubz:68053119707871158/578630692788811,737684984689589161,-7410529972742470086/9627432535163773:-426847173750840343829989219806413/578630692788811
+qsubz:2141868292014076693/328873136022248,-6454969195161975215,2185675198776140021/319490487602131:2122865962139927113433579878660013/328873136022248
+qsubz:6904094780152376715/105515417760572,9013725078444379686,=1:-951086967230996440142437656163677/105515417760572
+qsubz:986043406552959943/14107596810979,2995890298668631332,8819951421573670481/67954939364565:-42264812423539521185379288034085/14107596810979
+qsubz:-4371503587867387026/10407970809659,7789426111500215458,1611857228024591370/10701042327247:-81072119592494224995141074895848/10407970809659
+qsubz:128834428582928630/134708403993,8492912687875656470,-1262307966262698384/1518482758745:-1144066713435500610282261356080/134708403993
+qsubz:9450827094775890930/2700687301223,-6757147386255266788,6002877009556405644/1405277037833:18248942138561235652948359572654/2700687301223
+qsubz:-8388250355830908541/266466413258,2862142690442542385,=1:-762664896963214716421421848871/266466413258
+qsubz:-5619275429133115259/41783227722,-2163358989032247609,=1:90392121277550826819203901439/41783227722
+qsubz:9606560958482546016/29644869859,-7459227243081357178,9905446256945526764/20720077985:221127820879460752649388043918/29644869859
+qsubz:4930763186584321169/47984083979,6662837494722716160,551152931619292049/65568759475:-319710153880274018353836079471/47984083979
+qsubz:6701839224687506932/985583379,457687991137105386,3188171598044228633/792087660:-451089670130791153925472362/985583379
+qsubz:4977850203493279051/6143184950,3544412937261195005,5139590551055599222/1513126297:-21773984207790417170237895699/6143184950
+qsubz:2743230165777443647/888694730,494148490776673118,9757565623145649909/510318983:-439147156847452841121824493/888694730
+qsubz:-2143911698311688420/449171481,-6870034167785299997,639958345512727336/149888949:3085823419520813991370097137/449171481
+qsubz:-8533723636383149797/39725880,2768513107473221737,3141886070022952860/42371633:-109981628019631946320603357/39725880
+qsubz:-5314262731256470963/63761165,5833696012508623470,-7880529150937062671/68519301:-371963259327667136250013513/63761165
+qsubz:1681639872255718298/1514077,5997071385278801708,-6427612516373280573/8782472:-9080026170168899997925218/1514077
+qsubz:6099083259404780614/4192479,-5164344556388094262,-681054291106360636/3826929:21651412200504660448236112/4192479
+qsubz:8734142975627530613/432795,8347557484528703322,=1:-3612772407373624526714377/432795
+qsubz:9737081301281728277/751482,-1055406353334667048,=1:793128614297943544293413/751482
+qsubz:7681560095018293619/96421,-1078017997145375078,=1:103951254862849228689457/96421
+qsubz:9092804880201392539/52889,4169259379769360400,-5597148679483744113/49247:-220498866531741500803061/52889
+qsubz:-4754156917842901869/1537,-7603757415178737028,=1:11682220990211875910167/1537
+qsubz:-1492184829986224781/167,-4909822866544288080,-7885239837871971805/6814:818448233882909884579/167
+qsubz:-3561671662616934523/234,-1643132577230822696,=1:380931351409395576341/234
+qsubz:2224799941584138562/239,4895333498642631574,97344947199515758/161:-1167759906234004807624/239
+qsubz:7083599259933004607/80,7011559617335986001,1255271091090021783/31:-553841170126945875473/80
+qsubz:958854888905624023/33,5357637989296291879,-6913737981438705455/54:-175843198757872007984/33
+qsubz:-3476077523929127472,9908984532191635107,-6771898413854964869/5:-13385062056120762579
+qsubz:9188473183063801985/2,3589464423036032766,-2241566641820695587/2:2009544336991736453/2
+qsubz:41509521914914232161/2172094934845501331,95015472716989623433,=1:-206382627020524085395686379432876057162/2172094934845501331
+qsubz:-570614734467915216/612897350622429103,-29603844723095151643,717827408667935931/776625266995427534:18144117999022796755619629936333551013/612897350622429103
+qsubz:-27042524847598213145/9016861265984956672,61942065399081471006,-85599646530160700355/3483722943530240888:-558523010232084733112550144976532465177/9016861265984956672
+qsubz:26949534603425444509/3315837931819363899,1606604827685202950,-71919839549756914182/3712334721902834665:-5327241229082708837857932880292857541/3315837931819363899
+qsubz:41438250760107242789/99249508352697542,73974969596388490897,=1:-7341979362847306203122430732354032385/99249508352697542
+qsubz:87351178611540281996/61845876966812939,-91007621652632243823,19408679396333792502/44151394776784993:5628446171770955073811619296219507793/61845876966812939
+qsubz:4405917364991104531/771908998098153,64506590711703018448,53841168466232317214/53456487025575297:-49793217806998294835979616482622013/771908998098153
+qsubz:-9365617946363817493/26374061478484340,43990273202897382222,83764348600369483135/35424906140909763:-1160202169908537784737001508585220973/26374061478484340
+qsubz:-23473112900467700871/4618168111280368,15106111862258441004,38672462198241424645/4699633736186089:-69762564087716050528958198499110343/4618168111280368
+qsubz:-22186709781123392335/603508867935672,76634878648225439420,-26972666418343859759/2836755066733443:-46249828857378158866193511616382575/603508867935672
+qsubz:23848664713951836051/633837930342658,61700049658138946296,-28353020445764265473/310114901939234:-39107831777353989139731668388058717/633837930342658
+qsubz:2630510857358657218/37381246359883,-12240046954756473381,48743251697811443023/762346209014900:457548210672290050277093994431641/37381246359883
+qsubz:22881875543808933841/18718381442116,7150358297276988453,14651206458917400377/15752969059626:-133843134056206859479223810952707/18718381442116
+qsubz:1082979078922829695/1046984148841,-43275384717956071867,=1:45308641834697139731977743585842/1046984148841
+qsubz:21755828016468111169/5500110518439,18412344180922250307,63875503932039462805/8260608840523:-101269927898587827121167828799604/5500110518439
+qsubz:69011314837775177660/2882678720201,32263646636145101120,=1:-93005727594031047489899556547460/2882678720201
+qsubz:97885536037352108896/150601844165,4452732237850850724,=1:-670589686495399999211173316564/150601844165
+qsubz:22138505699176485607/252116416049,61532865941590224682,27472490489762575799/708864811:-15513445630395164712899324235811/252116416049
+qsubz:89674388203290664536/67784290823,-72266756979360926584,=1:4898550872013740444455898603168/67784290823
+qsubz:35131532657379157626/53215163647,19053685252752801749,28163327184395823897/32686497356:-1013944978768539369653403660977/53215163647
+qsubz:83869306682999924931/5573344090,99595425285705819332,=1:-555079574823255782969610022949/5573344090
+qsubz:-22687176270238560014/37602313,49747019891864444660,1536837876444207726/641869829:-1870603035478289271915058594/37602313
+qsubz:49755871830274632905/374641781,42438577123950343113,31092478152506184877/7732186:-15899264067066742469140771348/374641781
+qsubz:10982404440168695175/15660421,60671432520545031046,-27453714136445367576/288574235:-950140164962421895469735191/15660421
+qsubz:6775869043981190441/18805965,64780757548781992084,=1:-1218264652360010891780790619/18805965
+qsubz:44672679637496213080/48849753,95859623215842468974,18456416171029545998/4876557:-4682718872094290658793850342/48849753
+qsubz:-42152529057348698335/3235744,59925250634539284363,-3628407662598980249/15331:-193902812341735739490569407/3235744
+qsubz:52085283917127896710/9866863,38283604142633656357,4824692675957093036/5558115:-377739025136314829335701381/9866863
+qsubz:23591689782602478979/107299,69997830527239555546,79585026335134005520/792209:-7510673626052494468051275/107299
+qsubz:75522219291754027577/523942,98517292436821748408,-78467100165240534481/769278:-51617271711713968750356759/523942
+qsubz:-85486382965188732358/90271,23243020426810978176,=1:-2098256183331618999658054/90271
+qsubz:983479060786951655/34946,98005836915865207790,=1:-3424910993382764764477685/34946
+qsubz:35301842348289418558/1435,49016933196656116973,=1:-70303997294853238437697/1435
+qsubz:2632750748212302453/790,20382032741788103576,=1:-16099173115264389522587/790
+qsubz:-18891606196309322941/371,15238007397425687662,=1:-5672192350641239445543/371
+qsubz:22866847672127230662/17,21730312190117757012,30995020678487656037/5:-346548459559874638542/17
+qsubz:1126858518170848635,-611735474764215689,1160987006014179401/33:1738593992935064324
+qsubz:7067907915086579691/25,-28626674589646474416,=1:722734772656248440091/25
+qsubz:60995824276572751408/5,-94170815171282976513,=1:531849900132987633973/5
+qsubz:-26266792979830841992/9,26748623877696285585,-25180055821630578113/8:-267004407879097412257/9
diff --git a/polly/lib/External/isl/imath/tests/qtodec.t b/polly/lib/External/isl/imath/tests/qtodec.t
new file mode 100644
index 00000000000..e037a8dfa65
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/qtodec.t
@@ -0,0 +1,1303 @@
+qtodec:3/29668193161647153598,10,8,0:0.00000000
+qtodec:1/2552439818325226004,8,24,0:0.000000000000000000003472
+qtodec:2/2729838301109816701,10,17,0:0.00000000000000000
+qtodec:-2/8398891633027131961,8,2,0:0.00
+qtodec:1/30929359245686845,10,17,0:0.00000000000000003
+qtodec:1/93965811021736277,4,4,0:0.0000
+qtodec:0,2,5,0:0.00000
+qtodec:6/83909376915228431,16,18,0:0.00000000000005270C
+qtodec:-3/7079577697657177,33,15,0:-0.0000000000LDPIW
+qtodec:-6/9174315766316507,8,5,0:0.00000
+qtodec:9/479356093905517,16,19,0:0.00000000000548E50ED
+qtodec:7/272231567064361,2,0,0:0
+qtodec:5/47376768449307,10,11,0:0.00000000000
+qtodec:1/12288137207534,10,19,0:0.0000000000000813792
+qtodec:3/2308297858255,16,3,0:0.000
+qtodec:3/7879579455704,4,19,0:0.0000000000000000000
+qtodec:1/716028119691,8,6,0:0.000000
+qtodec:-7/176165656001,10,2,0:0.00
+qtodec:-2/79472074107,16,21,0:-0.000000001BAB9EA7B105E
+qtodec:7/39648256931,10,3,0:0.000
+qtodec:4/9367226433,10,11,0:0.00000000042
+qtodec:4/5861792533,21,10,0:0.00000014H0
+qtodec:3/243862471,8,3,0:0.000
+qtodec:-5/892143793,16,23,0:-0.0000001812303B762B937DA
+qtodec:-2/12767069,11,15,0:-0.00000030641A338
+qtodec:-1/10048225,25,3,0:0.000
+qtodec:-9/1466150,8,1,0:0.0
+qtodec:0,20,1,0:0.0
+qtodec:4/16203,10,13,0:0.0002468678639
+qtodec:5/580616,2,22,0:0.0000000000000000100100
+qtodec:-4/49429,10,8,0:-0.00008092
+qtodec:-5/74444,2,7,0:0.0000000
+qtodec:-2/437,10,9,0:-0.004576659
+qtodec:-6/2737,4,17,0:-0.00002033222223022
+qtodec:2/295,16,18,0:0.01BC4FD65883E7B3A2
+qtodec:-1/41,13,18,0:-0.04177C08322B136459
+qtodec:0,8,11,0:0.00000000000
+qtodec:1/90,8,11,0:0.00554055405
+qtodec:3,16,7,0:3.0000000
+qtodec:1/5,10,16,0:0.2000000000000000
+qtodec:27/28225889819425315955,10,14,0:0.00000000000000
+qtodec:97/39183286035001818490,16,11,0:0.00000000000
+qtodec:-35/3702072548595294917,10,20,0:-0.00000000000000000945
+qtodec:37/8652786483007175262,16,10,0:0.0000000000
+qtodec:41/181598573551235020,23,14,0:0.000000000004LI
+qtodec:15/600082766020339676,16,13,0:0.0000000000000
+qtodec:-9/2722110669597035,16,10,0:0.0000000000
+qtodec:57/47186773574985517,4,12,0:0.000000000000
+qtodec:0,8,15,0:0.000000000000000
+qtodec:38/8249095374399173,10,12,0:0.000000000000
+qtodec:86/135104489739753,30,7,0:0.0000000
+qtodec:-23/99519784680918,16,16,0:-0.0000000000410D37
+qtodec:17/35672209854079,10,3,0:0.000
+qtodec:56/46540343251387,8,11,0:0.00000000000
+qtodec:0,16,1,0:0.0
+qtodec:-59/6929353087150,8,13,0:-0.0000000000004
+qtodec:79/932785444169,16,2,0:0.00
+qtodec:-39/53188416323,8,10,0:0.0000000000
+qtodec:70/56574330991,10,12,0:0.000000001237
+qtodec:-83/19562860498,22,23,0:-0.000000ACI2EFKHH9BB0IH2B
+qtodec:13/307883133,16,18,0:0.000000B55992EED238
+qtodec:11/573365410,10,14,0:0.00000001918497
+qtodec:-89/983323622,8,20,0:-0.00000001411360322773
+qtodec:-27/872316667,10,14,0:-0.00000003095206
+qtodec:23/38939829,18,17,0:0.0000121AHFG008FEF
+qtodec:10/15277977,33,22,0:0.0000PKABC0QM81FH6PKCEH
+qtodec:10/731501,8,10,0:0.0000034526
+qtodec:6/1029065,10,15,0:0.000005830535486
+qtodec:49/332590,16,17,0:0.0009A7C345BF4128D
+qtodec:50/776461,8,1,0:0.0
+qtodec:2/479,10,16,0:0.0041753653444676
+qtodec:43/1929,16,15,0:0.05B4E2ABBA75950
+qtodec:-3/4439,2,0,0:0
+qtodec:-77/3511,16,1,0:0.0
+qtodec:-3/73,2,22,0:-0.0000101010000101010000
+qtodec:-11/574,4,21,0:-0.001032133222211322030
+qtodec:85/7,30,12,0:C.48H48H48H48H
+qtodec:17/4,8,21,0:4.200000000000000000000
+qtodec:-61/8,16,1,0:-7.A
+qtodec:81/2,16,0,0:28
+qtodec:-223/7523256159150326952,19,11,0:0.00000000000
+qtodec:492/63927532590023633933,10,7,0:0.0000000
+qtodec:-488/4671427241940113665,10,11,0:0.00000000000
+qtodec:869/1536545359977443591,16,13,0:0.0000000000002
+qtodec:255/990950541390055304,35,10,0:0.0000000000
+qtodec:314/865017777698304039,10,21,0:0.000000000000000362998
+qtodec:397/94739791379991670,4,10,0:0.0000000000
+qtodec:197/49947954439637722,10,12,0:0.000000000000
+qtodec:4/2294468349351839,10,1,0:0.0
+qtodec:465/3028494196809779,11,17,0:0.00000000000053342
+qtodec:441/948226064615029,10,9,0:0.000000000
+qtodec:415/205250226057042,8,4,0:0.0000
+qtodec:-7/17462466865516,16,18,0:-0.000000000070D4FD1C
+qtodec:608/28239839509857,8,12,0:0.000000000001
+qtodec:-223/866713738143,10,22,0:-0.0000000002572937178517
+qtodec:563/7786288255956,8,1,0:0.0
+qtodec:-919/714101559956,4,11,0:0.00000000000
+qtodec:-835/607709250842,10,7,0:0.0000000
+qtodec:-734/88891360337,16,6,0:0.000000
+qtodec:41/3074329077,10,10,0:0.0000000133
+qtodec:-34/7345250185,8,9,0:0.000000000
+qtodec:142/2351029685,16,14,0:0.00000103697A0A
+qtodec:34/31175165,8,8,0:0.00000022
+qtodec:-96/319314395,16,17,0:-0.0000050B41B8D426F
+qtodec:948/10607737,16,12,0:0.0005DB5BC777
+qtodec:47/24044059,35,24,0:0.0002WNBVR50LE0WRKG58RQLQ
+qtodec:535/6095688,10,7,0:0.0000877
+qtodec:486/1456495,10,6,0:0.000333
+qtodec:373/978875,8,11,0:0.00014370747
+qtodec:6/6211,16,7,0:0.003F4F4
+qtodec:685/2168,4,0,0:0
+qtodec:-88/41285,4,1,0:0.0
+qtodec:168/2015,8,2,0:0.05
+qtodec:-257/2002,16,21,0:-0.20DCF6899725153A0DCF6
+qtodec:89/871,5,6,0:0.022341
+qtodec:499/295,2,3,0:1.101
+qtodec:587/48,4,5,0:30.03222
+qtodec:155/24,10,16,0:6.4583333333333333
+qtodec:199/9,4,16,0:112.0130130130130130
+qtodec:-106,8,2,0:-152.00
+qtodec:-2933/29115963383147957058,10,2,0:0.00
+qtodec:1529/24516687344881033558,4,16,0:0.0000000000000000
+qtodec:-8335/3596290216553914092,10,2,0:0.00
+qtodec:1923/868496977516837484,10,2,0:0.00
+qtodec:9839/964058578172332209,2,23,0:0.00000000000000000000000
+qtodec:6976/372390689442127831,4,16,0:0.0000000000000000
+qtodec:-5619/82130008401991793,16,19,0:-0.00000000001341E2F2A
+qtodec:-793/7362155502859746,10,10,0:0.0000000000
+qtodec:-4999/903131924743945,8,11,0:0.00000000000
+qtodec:-9413/1178970988260896,10,8,0:0.00000000
+qtodec:7323/311224385698598,10,22,0:0.0000000000235296472143
+qtodec:-9700/190189472805017,22,7,0:0.0000000
+qtodec:2239/31441940161082,16,18,0:0.000000004E4C01D373
+qtodec:7871/77670518853986,15,19,0:0.000000003D68421BBCA
+qtodec:2122/2157192364211,16,24,0:0.00000004399300DABE38D2A1
+qtodec:28/69260597489,10,18,0:0.000000000404270263
+qtodec:4611/328096450714,4,18,0:0.000000000000033011
+qtodec:-8445/771625180456,16,17,0:-0.0000002F0187FDD06
+qtodec:6104/31076369717,6,7,0:0.0000000
+qtodec:-5146/99207462261,16,19,0:-0.000000DEC8E01BF79F7
+qtodec:6599/8951560744,10,14,0:0.00000073718988
+qtodec:9817/9012958484,4,15,0:0.000000000102101
+qtodec:103/2508067,10,1,0:0.0
+qtodec:160/346307341,4,15,0:0.000000000013300
+qtodec:-6972/39670075,8,20,0:-0.00005604455467641370
+qtodec:-4197/45941168,2,7,0:0.0000000
+qtodec:-4076/9631149,16,5,0:-0.001BB
+qtodec:-6082/452297,16,8,0:-0.037141D2
+qtodec:3422/343607,10,20,0:0.00995905205656462179
+qtodec:2255/505667,2,4,0:0.0000
+qtodec:393/6293,16,1,0:0.0
+qtodec:235/511,8,6,0:0.353353
+qtodec:1809/3322,8,10,0:0.4266367156
+qtodec:-751/3630,10,5,0:-0.20688
+qtodec:1444/297,16,14,0:4.DCA8F158C7F91A
+qtodec:-175/18,10,10,0:-9.7222222222
+qtodec:-1745/2,10,10,0:-872.5000000000
+qtodec:-7930/67,2,18,0:-1110110.010110111011001110
+qtodec:3077/4,2,21,0:1100000001.010000000000000000000
+qtodec:-3053/2,2,20,0:-10111110110.10000000000000000000
+qtodec:21182/2833372713644414301,16,20,0:0.0000000000021AB1F123
+qtodec:45387/14250357568649348800,10,19,0:0.0000000000000031849
+qtodec:-13863/3176447931757610564,16,21,0:-0.0000000000013A7B4A19F
+qtodec:51053/6071062782227045417,4,2,0:0.00
+qtodec:48153/204469188404773127,26,12,0:0.000000001769
+qtodec:-35643/103256682364442069,8,14,0:-0.00000000000001
+qtodec:54071/11780111475151984,4,10,0:0.0000000000
+qtodec:40181/97271345682485899,16,15,0:0.00000000007445A
+qtodec:63074/426635952224589,27,6,0:0.000000
+qtodec:37487/5041371975161711,10,7,0:0.0000000
+qtodec:33690/403332722546693,29,23,0:0.0000001CMM80DDDLOISN2P1
+qtodec:-32096/929352974579813,10,23,0:-0.00000000003453585545848
+qtodec:27697/5399115155752,8,13,0:0.0000000005404
+qtodec:43081/77103958462682,2,0,0:0
+qtodec:76092/2192729147447,10,15,0:0.000000034701960
+qtodec:40520/1057974855979,4,10,0:0.0000000000
+qtodec:-93832/180749201941,4,21,0:-0.000000000020231122031
+qtodec:15613/112650436297,10,22,0:0.0000001385968888645643
+qtodec:-15981/2114647337,8,16,0:-0.0000017662447224
+qtodec:-2956/48741428353,8,24,0:-0.000000010107463123137573
+qtodec:36488/7263916629,10,6,0:0.000005
+qtodec:17486/4731824201,33,11,0:0.0004CKGBDNA
+qtodec:87479/200379782,2,0,0:0
+qtodec:-21070/435273677,4,21,0:-0.000000030230013321132
+qtodec:-22652/26779223,16,7,0:-0.00376F8
+qtodec:88608/32268761,16,23,0:0.00B3F52FA37144F68F26E67
+qtodec:31998/3038585,4,10,0:0.0002230202
+qtodec:-8472/444571,10,14,0:-0.01905657364065
+qtodec:34267/677762,10,24,0:0.050559045800738312268908
+qtodec:-92699/231514,16,22,0:-0.6680D6DAC04F671A8CA61A
+qtodec:36031/70412,4,3,0:0.200
+qtodec:98/63775,8,24,0:0.000622645765407600507635
+qtodec:-65898/3023,10,11,0:-21.79887528944
+qtodec:7561/977,16,22,0:7.BD2EE71B83467C335B7281
+qtodec:-37137/52,10,8,0:-714.17307692
+qtodec:-88738/631,21,8,0:-6E.D536IE1D
+qtodec:67918/13,10,20,0:5224.46153846153846153846
+qtodec:-20668/21,8,20,0:-1730.14141414141414141414
+qtodec:-72712/5,16,11,0:-38CE.66666666666
+qtodec:45492,2,7,0:1011000110110100.0000000
+qtodec:296304/46496256563281536829,23,10,0:0.0000000000
+qtodec:-319725/3061659936699002531,4,23,0:-0.00000000000000000000013
+qtodec:-702855/9285437245836392212,10,4,0:0.0000
+qtodec:-199215/2284481803901388209,12,10,0:0.0000000000
+qtodec:199669/333012758422549802,8,4,0:0.0000
+qtodec:486363/473044697601679021,10,17,0:0.00000000000102815
+qtodec:-825841/23059317823282264,7,9,0:0.000000000
+qtodec:117332/24561684169423891,10,11,0:0.00000000000
+qtodec:-281263/409628091879471,10,19,0:-0.0000000006866301544
+qtodec:63007/1228412979569096,10,9,0:0.000000000
+qtodec:102915/195471522013601,2,19,0:0.0000000000000000000
+qtodec:-93162/25115626353389,4,5,0:0.00000
+qtodec:338038/29004229856357,16,17,0:0.000000320E91B972B
+qtodec:439672/13350641833293,27,21,0:0.00000CKD439M189BCG4PN
+qtodec:-1085/288156538958,28,0,0:0
+qtodec:15999/3935036028619,11,22,0:0.0000000096501919328434
+qtodec:958486/806510801671,16,0,0:0
+qtodec:24222/167944894493,10,15,0:0.000000144225878
+qtodec:90199/33724326940,16,16,0:0.00002CDF4F08A894
+qtodec:798735/74124476497,10,20,0:0.00001077559043580330
+qtodec:276215/643447444,10,5,0:0.00042
+qtodec:-877491/8506905787,2,17,0:-0.00000000000001101
+qtodec:622736/862215415,2,9,0:0.000000000
+qtodec:48302/90081849,18,8,0:0.00325372
+qtodec:996595/91668012,16,21,0:0.02C87E4CDFA1A8C2484B9
+qtodec:10754/13902389,4,9,0:0.000003022
+qtodec:424209/505345,31,11,0:0.Q0LRENN7438
+qtodec:198628/7370669,10,13,0:0.0269484357525
+qtodec:906593/696606,10,19,0:1.3014429964714630652
+qtodec:63392/486251,16,14,0:0.215FDAEB4E8BAF
+qtodec:775986/96101,8,4,0:10.0461
+qtodec:985049/21250,17,1,0:2C.6
+qtodec:-284525/1208,10,4,0:-235.5339
+qtodec:933244/2529,10,20,0:369.01700276789244760775
+qtodec:719857/48,8,6,0:35225.012525
+qtodec:-26991/715,32,2,0:-15.NV
+qtodec:-59177/2,10,20,0:-29588.50000000000000000000
+qtodec:833931/65,8,0,0:31035
+qtodec:283969/4,10,9,0:70992.250000000
+qtodec:692243/9,13,10,0:29017.B72B72B72B
+qtodec:2220425/82098663244722404628,2,19,0:0.0000000000000000000
+qtodec:1332706/24886222077598879681,30,8,0:0.00000000
+qtodec:3722825/2026604562916823564,27,7,0:0.0000000
+qtodec:293817/19154085506889290,8,22,0:0.0000000000010335564623
+qtodec:-2328299/361670841450282499,10,4,0:0.0000
+qtodec:6148084/561670125531460687,33,17,0:0.0000000FD0POOHRUD
+qtodec:-6433247/6864670391549153,16,4,0:0.0000
+qtodec:5175613/4620647601293887,16,8,0:0.00000004
+qtodec:2667155/2429659044108081,17,20,0:0.00000007B30FD7461E0A
+qtodec:681343/9032805224095139,10,9,0:0.000000000
+qtodec:5863994/174238841171323,10,15,0:0.000000033654918
+qtodec:8643703/353914077710020,10,10,0:0.0000000244
+qtodec:5346661/34799692977081,10,0,0:0
+qtodec:5106120/19563121357247,2,24,0:0.000000000000000000000100
+qtodec:6183913/2383366879745,2,8,0:0.00000000
+qtodec:518571/148387088269,4,4,0:0.0000
+qtodec:-3361270/733528692901,16,24,0:-0.00004CE0F4509B06F00B6586
+qtodec:1562255/21178801269,10,21,0:0.000073765034203645702
+qtodec:3467363/42461659020,10,21,0:0.000081658679383366213
+qtodec:-9936449/10071886359,4,11,0:-0.00001000221
+qtodec:-3336987/9840159415,10,18,0:-0.000339119201149649
+qtodec:2604333/1086112640,15,22,0:0.00815CEC195D2CA7051D65
+qtodec:7503718/882484091,10,16,0:0.0085029498849061
+qtodec:4474267/384881278,10,10,0:0.0116250575
+qtodec:712293/1045276,8,2,0:0.53
+qtodec:-272327/2700287,10,16,0:-0.1008511317500695
+qtodec:3101476/3471127,16,21,0:0.E4BCDE9EB583017073130
+qtodec:3127691/6558689,10,20,0:0.47687746743289703170
+qtodec:41313/916,16,17,0:2D.19FDC3A2189808F17
+qtodec:590136/11795,16,10,0:32.0860B6A96C
+qtodec:3688335/27739,16,21,0:84.F736CF72645AD9608B190
+qtodec:430927/16465,10,14,0:26.17230488915882
+qtodec:6193621/6249,10,24,0:991.137942070731317010721715
+qtodec:6881703/4802,4,1,0:112121.0
+qtodec:-3142168/979,10,7,0:-3209.5689479
+qtodec:-3176297/326,10,20,0:-9743.24233128834355828220
+qtodec:6271672/3,10,7,0:2090557.3333333
+qtodec:-2915894/79,10,18,0:-36910.050632911392405063
+qtodec:654753,16,2,0:9FDA1.00
+qtodec:-6358267/9,4,15,0:-2230132222.013013013013013
+qtodec:-18678516/29688438786197957,16,22,0:-0.00000002B3C24F9A0699C5
+qtodec:-5100140/10011896485948009711,16,1,0:0.0
+qtodec:-63971979/5765059347475183331,16,20,0:-0.000000000C3363110E8A
+qtodec:49592178/2236069654488181723,16,23,0:0.000000001862A177C1DD31F
+qtodec:70399774/240687813855844671,2,14,0:0.00000000000000
+qtodec:45825874/963387555556851547,16,15,0:0.00000000344D0AD
+qtodec:-7101885/38297123998463233,35,6,0:0.000000
+qtodec:45706162/20208127584234763,8,23,0:0.00000000023333300051317
+qtodec:-4603037/752013415132706,10,9,0:-0.000000006
+qtodec:-33461502/9204850740162821,16,15,0:-0.0000000F9CF2B5A
+qtodec:17754722/53304375179261,16,15,0:0.000005969369127
+qtodec:-38722845/596630162922919,22,24,0:-0.0000077JCJJ5DGKGF1H14836
+qtodec:68992640/66560021807813,8,5,0:0.00000
+qtodec:14264823/17373344136937,10,2,0:0.00
+qtodec:12383615/9923197741689,16,17,0:0.000014EFE3254D306
+qtodec:-67431335/7690429580523,16,6,0:-0.000093
+qtodec:4367596/64156078187,16,15,0:0.000476275848D8E
+qtodec:20810847/488563827005,16,17,0:0.0002CAA4454B3E427
+qtodec:-22478409/38544781642,10,5,0:-0.00058
+qtodec:36702575/69781180501,24,3,0:0.007
+qtodec:65365649/26951426,16,8,0:2.6CE15346
+qtodec:13356174/2840415263,29,12,0:0.03RJM9IFG27A
+qtodec:47208715/178421993,10,21,0:0.264590223470937240343
+qtodec:7539463/119654423,24,13,0:0.1C717ALE7IC94
+qtodec:-43582754/39677013,2,15,0:-1.000110010011001
+qtodec:-57528557/8850837,5,6,0:-11.222214
+qtodec:47234381/8936103,10,1,0:5.2
+qtodec:33301301/106817,4,20,0:10313.30022203221331330110
+qtodec:81045865/711846,16,16,0:71.DA63F30882704AB2
+qtodec:91094596/828431,4,13,0:1231.3311313002012
+qtodec:40293131/48303,8,20,0:1502.13126064102265372300
+qtodec:-181649/70,8,6,0:-5042.770537
+qtodec:45546885/4774,10,1,0:9540.6
+qtodec:828359/734,31,12,0:15C.H5QUJ6M5B8HO
+qtodec:-59718139/406,16,16,0:-23E91.032717F5E94CED15
+qtodec:2679103/162,4,10,0:10002121.2230033303
+qtodec:12366443/53,8,10,0:707561.0717545336
+qtodec:34041109/25,4,7,0:11030123230.1130022
+qtodec:-42857879/3,4,13,0:-312133302013.2222222222222
+qtodec:-16602037/6,10,15,0:-2767006.166666666666666
+qtodec:201634836/47285863779715310669,8,2,0:0.00
+qtodec:744820415/27255853323214067023,2,1,0:0.0
+qtodec:-625328361/8980450114346406298,4,0,0:0
+qtodec:403756951/6617643244507173155,16,12,0:0.000000004315
+qtodec:-426683165/783310053429126211,16,23,0:-0.0000000256EC83CE37DE9A6
+qtodec:787333919/76979591766305433,10,11,0:0.00000001022
+qtodec:661348691/70208895966253883,16,20,0:0.000000287519ABAB23C0
+qtodec:280056103/19236376368074700,8,12,0:0.000000001750
+qtodec:7656653/5938020515370151,16,3,0:0.000
+qtodec:-208421697/1757008688014187,8,19,0:-0.0000000177275547023
+qtodec:246570074/100899135942843,34,13,0:0.0003912R3IHWN
+qtodec:113230062/65743402595005,10,7,0:0.0000017
+qtodec:70543944/10849645138255,10,19,0:0.0000065019586448286
+qtodec:642672567/24971850717497,10,5,0:0.00002
+qtodec:-314721695/752512751681,8,6,0:-0.000155
+qtodec:-163807291/5886020608,8,4,0:-0.0161
+qtodec:438467533/52265645624,20,6,0:0.037259
+qtodec:498074863/824377038073,16,4,0:0.0027
+qtodec:-27700104/49948246387,10,14,0:-0.00055457610634
+qtodec:141171374/99253478457,4,5,0:0.00001
+qtodec:-361755751/3656937423,4,14,0:-0.01211103001233
+qtodec:22816939/611768152,4,22,0:0.0021203010123303032113
+qtodec:-53856232/403256995,4,11,0:-0.02020300202
+qtodec:449484375/227346169,10,2,0:1.97
+qtodec:217806981/3021451,16,19,0:48.163DE229590DF0963DD
+qtodec:250860083/22259097,10,17,0:11.27000268699130068
+qtodec:431639694/8164765,22,23,0:28.J14GK2EE5A85EIDALF8872L
+qtodec:-39808798/57615,8,20,0:-1262.74366630432236034771
+qtodec:7210334/8793,8,10,0:1464.0042361134
+qtodec:-90699159/75166,16,16,0:-4B6.A6C208F34F5CA17D
+qtodec:-190010/41897,2,13,0:-100.1000100100000
+qtodec:-37292046/12725,4,21,0:-231302.213031123013102122123
+qtodec:-827038151/3021,16,21,0:-42D63.0AD8C3EB52CA876A2DEDD
+qtodec:-263139079/9216,2,19,0:-110111110001000.0110101011011100011
+qtodec:859020523/138,8,13,0:27575622.3140355346016
+qtodec:-50892458/33,4,12,0:-11320200303.230212302123
+qtodec:207612373/7,10,7,0:29658910.4285714
+qtodec:35998064/9,10,13,0:3999784.8888888888888
+qtodec:424044905/4,10,2,0:106011226.25
+qtodec:493019,10,13,0:493019.0000000000000
+qtodec:-4042513085/15637696512520985642,10,22,0:-0.0000000002585107775792
+qtodec:6403629722/13409004049280473687,10,14,0:0.00000000047756
+qtodec:4310949661/9182204608528567055,2,12,0:0.000000000000
+qtodec:-6207213301/7937357727791570577,26,7,0:-0.0000006
+qtodec:-5492618011/924682356235504554,10,14,0:-0.00000000594000
+qtodec:8192041323/632108923605970228,7,1,0:0.0
+qtodec:-186147758/5553753716846915,31,20,0:-0.00000TN4N56ODGNH7IPI
+qtodec:5752674759/45700966145683610,31,19,0:0.00003IM5RCTBI6HUEBC
+qtodec:1348886735/4229222108363968,4,20,0:0.00000000001111213123
+qtodec:-991251339/2657176318638922,10,1,0:0.0
+qtodec:8018307442/898724497172469,16,0,0:0
+qtodec:2014050707/340069109236288,16,18,0:0.0000635CD5D59A22E0
+qtodec:4505135732/39991791916081,10,7,0:0.0001126
+qtodec:6453084395/58624215198992,10,17,0:0.00011007540780027
+qtodec:-1804902629/2765243734591,10,16,0:-0.0006527101413962
+qtodec:2151190453/5551909474614,16,4,0:0.0019
+qtodec:725818559/82908634105,4,2,0:0.00
+qtodec:3396663851/192565119374,8,0,0:0
+qtodec:411464751/68497491776,8,15,0:0.003046546407536
+qtodec:331510163/2781814914,8,21,0:0.075007644307123546602
+qtodec:6307596319/2688917842,16,11,0:2.5884B649AE6
+qtodec:-9200062729/3512239660,4,3,0:-2.213
+qtodec:2884984405/325651823,3,8,0:22.21201202
+qtodec:1305611221/700300760,10,8,0:1.86435785
+qtodec:1587226477/40056887,4,16,0:213.2133310223222233
+qtodec:34378367/11734676,30,22,0:2.RQK7MSK4KA6QIJ9KADGNRK
+qtodec:7518884673/9949274,7,15,0:2126.502424542621013
+qtodec:3931084199/1830484,10,10,0:2147.5654520880
+qtodec:-2575482611/282998,22,10,0:-IHE.FD9E9AGG86
+qtodec:-1417727301/197914,10,14,0:-7163.35024808755317
+qtodec:3672290/691,8,14,0:12302.35211047212436
+qtodec:8228518089/35371,30,13,0:8IEE.HL4JRHM3K3LL1
+qtodec:410532666/2941,16,24,0:22145.7B57D42113C25F3A3BB688A9
+qtodec:8394604490/1573,8,21,0:24267154.265477753126202662152
+qtodec:7379334711/332,31,2,0:O22T4.O5
+qtodec:-2823493053/70,2,0,0:-10011001110111100011111111
+qtodec:2377080339/46,8,24,0:305101013.426205441310262054413102
+qtodec:419615836/45,10,23,0:9324796.35555555555555555555555
+qtodec:8359035220,4,24,0:13302033030011110.000000000000000000000000
+qtodec:2211961894/3,8,5,0:5374517267.25252
+qtodec:3722836622/14480498279571705649,16,0,0:0
+qtodec:65111863307/11533490001438870777,10,19,0:0.0000000056454605933
+qtodec:5949898539/1696780621152707101,8,11,0:0.00000000036
+qtodec:56815400197/1686789806569317842,10,11,0:0.00000003368
+qtodec:90925627747/25695775444577271,16,1,0:0.0
+qtodec:-27535487045/285845335283069982,10,8,0:-0.00000009
+qtodec:15775413556/25311693641355547,8,4,0:0.0000
+qtodec:-2057810676/17252279485169683,8,10,0:-0.0000000200
+qtodec:85387309833/8636897486832992,10,20,0:0.00000988634054800042
+qtodec:716266208/466095180147391,16,22,0:0.000019C83D60B83CEE8EE7
+qtodec:43248451649/397132885993682,8,6,0:0.000034
+qtodec:-45534175087/316387723492611,10,5,0:-0.00014
+qtodec:-47173726353/7171454234480,10,11,0:-0.00657798611
+qtodec:297529128/678060165163,8,5,0:0.00016
+qtodec:-6512811254/5361725734445,8,6,0:-0.000476
+qtodec:-20777019927/2016234688361,4,22,0:-0.0002220311123210221201
+qtodec:-947693138/3599271747,2,24,0:-0.010000110110011110110111
+qtodec:22262357967/226160142878,10,16,0:0.0984362570862418
+qtodec:82037055923/64093321236,4,17,0:1.10132223220113313
+qtodec:16205375896/9742150071,10,22,0:1.6634290970572752532996
+qtodec:97719092318/5262332763,10,12,0:18.569538780419
+qtodec:-49761904323/530474551,8,19,0:-135.6346771114202260241
+qtodec:33397252622/403519053,16,11,0:52.C3D6BF6B7B6
+qtodec:695492668/55458573,16,23,0:C.8A6F439434C6E70775E0AAB
+qtodec:75005050378/73364577,7,5,0:2660.23445
+qtodec:29030528543/40315167,10,15,0:720.089502370162574
+qtodec:31369038993/5743048,2,5,0:1010101010110.00010
+qtodec:39339254427/4936337,16,16,0:1F21.52312B564042C6B3
+qtodec:37009536016/100485,30,9,0:DJ6T.1P2MILPAG
+qtodec:1551216144/205609,10,8,0:7544.49534796
+qtodec:99143355445/6654,10,8,0:14899812.96137661
+qtodec:893556747/43649,4,15,0:10333313.122133133133000
+qtodec:-32107553839/5925,26,21,0:-BM86O.B3HIL8OGDBF29CN87DEB6
+qtodec:40475869854/7411,10,21,0:5461593.557414653892861961948
+qtodec:-21388883933/385,16,0,0:-34FB5D6
+qtodec:23566612035/406,4,14,0:3131123112102.13031203220002
+qtodec:-94254132457/78,8,23,0:-11001501411.43220322032203220322032
+qtodec:55429871241/94,2,1,0:100011001001011100101101111001.0
+qtodec:81069744134/9,10,14,0:9007749348.22222222222222
+qtodec:-63777906131/8,16,5,0:-1DB2EB3BA.60000
+qtodec:22636846283/8589275715769980395,16,4,0:0.0000
+qtodec:451030208027/11667920285394363609,2,13,0:0.0000000000000
+qtodec:-396336330142/9218513566402258373,8,6,0:0.000000
+qtodec:-812297708247/6583818474797492140,10,17,0:-0.00000012337790164
+qtodec:65812963138/110962035363701723,4,16,0:0.0000000000213303
+qtodec:-367081998292/90608900002645629,8,22,0:-0.0000010376016446422266
+qtodec:765068976289/27117928920114978,4,23,0:0.00000001312111101312131
+qtodec:466163950691/74887899881824511,21,19,0:0.000148I9D04GG13GACA
+qtodec:2881317737/21976075689165,4,1,0:0.0
+qtodec:17255779745/25462798741843,16,23,0:0.002C69AEC9C156BD44A08C5
+qtodec:53125954797/33441637786834,2,13,0:0.0000000001101
+qtodec:43895010407/151886174379178,10,1,0:0.0
+qtodec:-251294209230/63991299908567,16,24,0:-0.01015C39B4D2F68935F6E4BE
+qtodec:955590711151/37535044163376,10,6,0:0.025458
+qtodec:174878212849/3669903179355,7,21,0:0.022226131634650361136
+qtodec:-157330267554/4348224760679,3,12,0:-0.000222101011
+qtodec:459430618651/21414547740,10,19,0:21.4541359560367722246
+qtodec:34869089840/299703846887,10,8,0:0.11634515
+qtodec:745844090051/5002251143,3,7,0:12112.0022020
+qtodec:466911780262/26884443459,2,21,0:10001.010111100000101100111
+qtodec:815254747041/5076712349,10,16,0:160.5871459708736789
+qtodec:-481092000475/9125040392,10,17,0:-52.72217763515626967
+qtodec:148261988694/154485473,10,2,0:959.71
+qtodec:87399306218/237779763,8,23,0:557.44064516575231734633261
+qtodec:554983007393/9392637,10,12,0:59087.028210820880
+qtodec:-959429967314/73223417,10,23,0:-13102.77513154022844904929798
+qtodec:594089636023/951818,10,18,0:624163.060609276143128203
+qtodec:271932654628/1030467,10,22,0:263892.6376371101646146844100
+qtodec:381378480415/45628,10,8,0:8358430.79720785
+qtodec:157468278507/203998,4,1,0:2330131012.3
+qtodec:-195533395495/7408,16,4,0:-192C110.CCD2
+qtodec:-101137757753/54175,4,16,0:-13013301313.1210302022313232
+qtodec:236424674428/8301,10,2,0:28481469.03
+qtodec:44997066682/681,8,22,0:374034553.6221666243714700060074
+qtodec:49672355883/11,10,17,0:4515668716.63636363636363636
+qtodec:-156344022343/116,10,21,0:-1347793296.060344827586206896551
+qtodec:-282780023728/5,2,11,0:-110100101011000000000010010110001001.10011001100
+qtodec:638682849990/23,16,9,0:677268F6C.C8590B216
+qtodec:535560667707,16,18,0:7CB1E7423B.000000000000000000
+qtodec:-401907828437/3,16,9,0:-1F3130ECF1.AAAAAAAAA
+qtodec:3218700909539/29338078141536091560,8,23,0:0.00000001656320570000741
+qtodec:5439189996708/94348764673867659923,16,4,0:0.0000
+qtodec:1740848648701/1119578055730924485,31,18,0:0.0001DFUO0I3QPKUBB3
+qtodec:7295053757088/1450625657591198545,8,7,0:0.0000012
+qtodec:-1032855428030/265721276914642799,10,4,0:0.0000
+qtodec:9675459200429/511269589228603602,16,0,0:0
+qtodec:-6223725941437/56926625845778373,8,5,0:-0.00003
+qtodec:-2879348418643/47766734102586734,8,12,0:-0.000017632436
+qtodec:2520416264460/3387623665183741,4,12,0:0.000003003002
+qtodec:-3355498216855/9089973231071546,8,11,0:-0.00014061140
+qtodec:76270631539/39479824809239,10,8,0:0.00193188
+qtodec:3364353901017/768729606000529,10,2,0:0.00
+qtodec:-9452026777809/99657509107327,8,9,0:-0.060437046
+qtodec:-4815297415205/21430300809226,10,10,0:-0.2246957454
+qtodec:-6342167555982/3875920251233,7,17,0:-1.43115201521246450
+qtodec:8934479736203/3867754877020,10,18,0:2.309991201688244985
+qtodec:-3753600089937/143741616224,10,19,0:-26.1135236164839743412
+qtodec:2897856603605/615018645051,2,9,0:100.101101100
+qtodec:435938574533/2644597999,10,15,0:164.841149655955706
+qtodec:826020960749/10601806559,16,12,0:4D.E9C93E2C5870
+qtodec:9761146029167/8021480002,24,3,0:22G.L0D
+qtodec:2245343058343/784476985,4,9,0:230232.031313033
+qtodec:1072296751915/36801933,10,3,0:29136.968
+qtodec:-807541874983/131278078,8,7,0:-14007.3045040
+qtodec:-435413761289/43289060,7,10,0:-41216.2001345166
+qtodec:4073307919652/31662917,8,7,0:373206.0046555
+qtodec:-1321397617831/1964025,23,21,0:-296J4.IG8A9IBJ59J61E8CGB7GI
+qtodec:2696371910638/7287271,16,17,0:5A55B.3403DE272E3931399
+qtodec:5257481019409/238632,10,21,0:22031751.900034362533105367260
+qtodec:1568947440315/909929,10,13,0:1724252.5958783597401
+qtodec:766431707621/1221,2,20,0:100101011010100001000100100100.00111111111100101001
+qtodec:-431144146277/82280,4,20,0:-103333102122.32023132113312320331
+qtodec:384242556775/153,4,15,0:2111230030021023.331322021030331
+qtodec:2640838852687/18,16,18,0:2228CAD559.B8E38E38E38E38E38E
+qtodec:7610182808651/115,8,1,0:755027404533.7
+qtodec:-9118836627837/914,8,15,0:-112252512015.670667132577121
+qtodec:1898758084737/34,4,17,0:310000222322313211.22310231023102310
+qtodec:3941772625972/27,16,22,0:21FDC6B473.B425ED097B425ED097B425
+qtodec:7305852397411/8,4,6,0:31102200311321103230.120000
+qtodec:7715401636819/8,28,19,0:2FD9CJPF6.AE00000000000000000
+qtodec:-6377466965229/5272197654656004845,2,11,0:0.00000000000
+qtodec:95367642815004/58794630553530738613,16,8,0:0.00001B36
+qtodec:89910282347329/7828383835585298780,10,8,0:0.00001148
+qtodec:2038526394593/1990816553437773794,10,2,0:0.00
+qtodec:28272663625994/160960199502197837,35,1,0:0.0
+qtodec:-59069158030644/424215731327050267,16,3,0:0.000
+qtodec:75400206290854/49799134304108783,16,11,0:0.00633A28CE3
+qtodec:-37669923041786/75586822083192129,4,11,0:-0.00000200222
+qtodec:7496638266025/6034056131446777,8,8,0:0.00050553
+qtodec:24694543702374/3151507628740733,6,3,0:0.001
+qtodec:36765006277527/993625421845964,16,6,0:0.0978E3
+qtodec:24118383293179/139876602800164,8,3,0:0.130
+qtodec:84628426174922/74981426674997,16,16,0:1.20EFC3CE6BC695C0
+qtodec:75123320783542/76127954130971,2,8,0:0.11111100
+qtodec:72843089406231/6513652706969,16,20,0:B.2EE2417719BC9EBF6400
+qtodec:30025878059676/8095500354281,16,3,0:3.B57
+qtodec:40392627698767/335455107355,16,17,0:78.69533006D036F2932
+qtodec:19166212064859/56607758681,10,2,0:338.57
+qtodec:32912615723976/61714756253,32,24,0:GL.9LEN5HK85GIITU1DGPP794DF
+qtodec:41214369996242/38676773967,3,1,0:1110110.1
+qtodec:90080254229318/6760666411,2,10,0:11010000001100.0010101011
+qtodec:82429041024490/7102488371,16,5,0:2D55.A816C
+qtodec:57660654095256/202993813,8,10,0:1052623.2234624203
+qtodec:2309226834537/34009046,4,0,0:100210330
+qtodec:5980018582499/10018234,4,16,0:2101232301.1302033232010302
+qtodec:6907402092405/8167279,10,18,0:845740.924536188858002769
+qtodec:687627440189/2492032,4,3,0:1003113122.122
+qtodec:-26205406708751/2529448,16,19,0:-9E1540.A7F1ECC11AC5EB38F15
+qtodec:7987206144352/958979,16,4,0:7F16A0.7EAA
+qtodec:9349896502895/60416,10,12,0:154758615.315396583686
+qtodec:10860759301327/48735,10,2,0:222853376.45
+qtodec:3148381751581/5818,19,7,0:B9A7BD1.66HDG7A
+qtodec:61935911504963/4361,10,20,0:14202226898.63861499656042192157
+qtodec:-69993147865828/9859,4,19,0:-12213022013333300.0110131201200023123
+qtodec:86935769322811/926,16,10,0:15DBDEBA5B.04B3250B9C
+qtodec:-64121171058167/770,20,5,0:-351341067.9FGHD
+qtodec:9446426763225/4,16,18,0:225DABA57F6.400000000000000000
+qtodec:-15324302869615/24,8,5,0:-11225224260057.22525
+qtodec:-4671160833472/3,8,5,0:-26520750116225.25252
+qtodec:55245335112604/3,10,5,0:18415111704201.33333
+qtodec:566728086891451/10568813125939255124,3,12,0:0.000000001001
+qtodec:739540223328929/6053203450796243551,10,17,0:0.00012217336313578
+qtodec:-267044400853535/2379289330009370147,16,14,0:-0.00075B066EC680
+qtodec:-843852024858729/4271893173695550305,10,6,0:-0.000197
+qtodec:197347580645443/108172371955754181,16,12,0:0.0077900729BF
+qtodec:-471123271600944/654989858032575515,10,23,0:-0.00071928330770812175815
+qtodec:-163920861540435/9535143268783618,16,17,0:-0.0466A503DF678948D
+qtodec:-245368226573823/3254547830228791,16,1,0:-0.1
+qtodec:369028112478579/2538185191154003,16,21,0:0.253850793AFB1044E30DD
+qtodec:626129443248141/7910783804367593,16,19,0:0.1443195BA445886AF1D
+qtodec:-157750576827642/153140053336643,8,8,0:-1.01732420
+qtodec:275996140907183/409619916609098,16,20,0:0.AC7D3C447ED47543D31A
+qtodec:355251513430543/14307219099290,10,15,0:24.830228080324321
+qtodec:937664836189255/79009750870091,30,11,0:B.Q0S5AR173F3
+qtodec:349923951151518/2085182381581,10,14,0:167.81455389346000
+qtodec:942533795406013/1253026069985,8,12,0:1360.151377610176
+qtodec:168503932887067/490675611980,16,3,0:157.697
+qtodec:-677938451596593/682092667400,2,8,0:-1111100001.11101000
+qtodec:803603551114720/23581903161,2,0,0:1000010100011101
+qtodec:112615275542863/25757128420,16,2,0:1114.32
+qtodec:579802064583250/5360830521,16,9,0:1A67B.44BEE11BF
+qtodec:273379089201067/1016082892,2,13,0:1000001101011111011.1111010010100
+qtodec:975288121833827/137728947,2,4,0:11011000000110011111101.1100
+qtodec:-99770800296007/18724410,33,20,0:-4G8U3.H9T203QQF1ID7D4MF4GL
+qtodec:-991804729064264/26457723,2,18,0:-10001110111111111100111101.110010101110011101
+qtodec:-62591002485079/97559203,16,0,0:-9CA21
+qtodec:688513532701121/5610689,10,13,0:122714613.6064788121387
+qtodec:553695114091357/8948070,4,23,0:3230003012333.20320221111300131301211
+qtodec:394354539297348/400625,10,16,0:984348304.0183413416536661
+qtodec:950552587873347/888277,16,0,0:3FC88E89
+qtodec:350686839911665/16413,4,22,0:103321202113333012.3231220011031122032301
+qtodec:903828738534/25,16,20,0:86AE54865.5C28F5C28F5C28F5C28F
+qtodec:541050473343191/7988,10,3,0:67732908530.694
+qtodec:247693604041126/753,10,20,0:328942369244.52324037184594953519
+qtodec:669870599648747/481,8,6,0:24210111252064.072426
+qtodec:754104756872751/751,10,4,0:1004134163612.1850
+qtodec:400809404312086/31,29,15,0:POFCDO4JM.ES1P7E0R3LES1P7
+qtodec:691618327861484/41,2,13,0:11110101011110001111001111001110010010000010.1010001001010
+qtodec:-210072315488840,8,7,0:-5760750557365110.0000000
+qtodec:-81144130253573,10,3,0:-81144130253573.000
+qtodec:5170809372187007/11283707234075047947,10,10,0:0.0004582544
+qtodec:1639188787409323/46524006641110741684,10,3,0:0.000
+qtodec:5309238096936419/7635150210858603024,16,9,0:0.002D92563
+qtodec:6245068701898179/9732919709002668103,9,8,0:0.00041788
+qtodec:-4005803274360553/523443601614052653,8,16,0:-0.0037261037222672
+qtodec:910033404367986/51511134209314135,10,14,0:0.01766673202477
+qtodec:-8946453122467272/16357932122088269,4,1,0:-0.2
+qtodec:1439256442170292/18860267700460975,16,18,0:0.13892784AB4AC9534F
+qtodec:176342308920979/1166455373773242,19,16,0:0.2GAHC9H4CGC0CEHD
+qtodec:9127798257300245/3295488783649008,2,3,0:10.110
+qtodec:2823851681807332/216293042654769,35,9,0:D.1X72DBVCV
+qtodec:1528606788714955/776202467853779,8,1,0:1.7
+qtodec:-2245234784303738/7968662735081,2,19,0:-100011001.1100001000001110110
+qtodec:-128444956522416/7394678196655,16,17,0:-11.5EB2F81C36E711FA5
+qtodec:9112358352966977/2361812921250,16,7,0:F12.3478F81
+qtodec:2905352187696283/1380663976291,16,7,0:838.50B0C57
+qtodec:8510056286946796/21028769443,10,6,0:404686.365981
+qtodec:-327110149217475/8556403273,16,0,0:-9555
+qtodec:-9974695312898971/92239807984,10,5,0:-108138.72590
+qtodec:1221192643750202/2497860115,8,18,0:1672677.417113245412637252
+qtodec:-4419213285773803/8210131295,10,24,0:-538263.412238622792937929502380
+qtodec:3449812953293071/3716759862,3,8,0:1202011012221.11200111
+qtodec:-1747118140195518/581874449,30,24,0:-3L65I.ROIQ9PQN4D3L479OTM4HQTTO
+qtodec:2932615081988594/424849503,10,16,0:6902715.1056561174793230
+qtodec:205249461865499/1394293,8,8,0:1061431264.50247217
+qtodec:200178651506113/94362405,10,18,0:2121381.407204627732834914
+qtodec:4983485895963716/3124575,16,4,0:5F10BCAD.83B3
+qtodec:-2126394804343852/5400439,16,12,0:-177811A5.9FF614B5F0EB
+qtodec:-4331181325256657/303608,28,15,0:-11GP6OLI.GLNOMIO8LGAFBFB
+qtodec:5081378901139473/111776,10,6,0:45460375224.909399
+qtodec:2920920792505487/41003,10,4,0:71236758103.1994
+qtodec:7658747612532673/37587,8,3,0:2756104626662.525
+qtodec:4821921280150899/6211,10,2,0:776351840307.66
+qtodec:971865299978799/70,10,4,0:13883789999697.1285
+qtodec:-7430593251383/46,8,3,0:-2263415567573.502
+qtodec:2823536151388589/214,8,16,0:277777522736567.1720114437064505
+qtodec:4578540213882646/39,9,17,0:511604860453776.84754754754754754
+qtodec:-9927408845436128/93,7,7,0:-31325111416165136.1335226
+qtodec:407609585094280/3,2,13,0:11110111001001010101010110101111001101000101101.0101010101010
+qtodec:253188219226631/3,10,12,0:84396073075543.666666666666
+qtodec:-68930748060360886/37490536052536135645,16,16,0:-0.00787EE12917A18A
+qtodec:-27942742835596649/47682255502975144563,10,22,0:-0.0005860197371295314577
+qtodec:-889817670509617/3535523156098154639,2,8,0:0.00000000
+qtodec:15158188532341466/3995083585765893961,16,13,0:0.00F8A84A7CDC0
+qtodec:-59804365023342061/621117898115362242,8,8,0:-0.06123043
+qtodec:-81485939236590623/615428154300888948,34,11,0:-0.4H21W6LIJ50
+qtodec:36074584319124862/92634714729867147,10,20,0:0.38942835225781451191
+qtodec:27642416496412871/152889510367347,4,19,0:2310.3030302130330102330
+qtodec:-33829733020352429/4052703927980325,10,17,0:-8.34744743794091070
+qtodec:-66100320694014641/8124063954599958,16,10,0:-8.22E8955406
+qtodec:58590194428080104/702027678864689,16,14,0:53.7561E129C90D18
+qtodec:31662226155385957/171148946506769,28,12,0:6G.RQDMHIG61C7H
+qtodec:80426773270148529/88072832508602,10,6,0:913.184815
+qtodec:6986828640027445/26266703980128,4,16,0:10021.3332320200120130
+qtodec:-1329127236657015/571179194743,14,21,0:-BC2.DB9808DAB68A65CB41223
+qtodec:30790043632436089/2944082517781,10,21,0:10458.281466799040529212839
+qtodec:37527850657958435/230664339986,8,17,0:475606.50517543663044013
+qtodec:1274159114112977/691969514703,25,20,0:2NG.8JHABOIBBB9OE6722AG6
+qtodec:-8727012566649617/7034024865,10,9,0:-1240685.487205711
+qtodec:17256266960825731/63664944830,16,1,0:422C8.2
+qtodec:50744507398196374/8821405641,10,16,0:5752428.7469954669551965
+qtodec:47177149363508061/3993510814,4,7,0:231010021030.1003113
+qtodec:60964430640468696/20931833,8,19,0:25546310107.6643376221343113763
+qtodec:28046052697862828/808622915,4,7,0:2010103231022.1202200
+qtodec:15333390554164126/4607479,16,11,0:C65C4208.702AED37B48
+qtodec:36857302943990537/94956649,10,23,0:388148732.41778505684209643918668
+qtodec:8496754449568199/55962,10,8,0:151830786061.40236231
+qtodec:-40689989695341081/5616818,2,13,0:-110101111110010110111001100010011.0001001001010
+qtodec:23163002269331293/193866,16,4,0:1BD187A9C2.1156
+qtodec:34444442500613215/206713,8,13,0:2331370253516.7722402424374
+qtodec:62933776312076227/59883,16,14,0:F4B13D77CA.C8A382A3CADEC9
+qtodec:-18647677587711109/26916,18,2,0:-38FB804D22.HC
+qtodec:17817200142697406/9583,10,24,0:1859250771438.735886465616195345925075
+qtodec:-11671994921731151/3051,10,14,0:-3825629276214.73320222877745
+qtodec:-25084790823695601/724,4,9,0:-13320023333333312130211.012303213
+qtodec:55617132227847436/639,34,15,0:1EP48NP5TQ.OG5WKWQDA955GBD
+qtodec:-7818552938767891/33,10,5,0:-236925846629330.03030
+qtodec:38873447567837132/65,4,8,0:2013332310102332133330202.22111222
+qtodec:95354368608906933/5,8,15,0:1036015571557436212.463146314631463
+qtodec:-40993349533336479,5,21,0:-320441040014321013231404.000000000000000000000
+qtodec:135033976497795375/40316057739120473824,25,19,0:0.02288KK6H25D8FAK52C
+qtodec:-968873270873936405/81604197111822403467,33,1,0:0.0
+qtodec:-582538953962125016/4568729267973575005,4,6,0:-0.020022
+qtodec:6393160063269118/92227912540813733,10,19,0:0.0693191452255839024
+qtodec:474281688207585819/814291209842309920,10,3,0:0.582
+qtodec:40690442908425581/187118373843998614,8,12,0:0.157255306433
+qtodec:-268184957010686822/58138937651604387,10,18,0:-4.612828645369753495
+qtodec:244145735027212276/20118199473446397,10,18,0:12.135565876531608828
+qtodec:185382924301762910/5186767786834931,8,19,0:43.5735167671261201162
+qtodec:433898808529646925/9828786248752108,10,7,0:44.1457162
+qtodec:245241871711849034/3863301881929,10,23,0:63479.86235789484292426582206
+qtodec:-347923793289428653/116335863891625,16,5,0:-BAE.AF130
+qtodec:-101194595933896924/47243525609381,2,20,0:-100001011101.11111010011000101111
+qtodec:472198009745101481/5392622647777,4,6,0:111120023.231000
+qtodec:192703964184690803/5888450417178,10,2,0:32725.75
+qtodec:351370652185299362/4111024159547,10,9,0:85470.344748355
+qtodec:966591837542629967/302542852166,8,20,0:14140014.25030572653613126432
+qtodec:849532369021753832/344987961049,10,3,0:2462498.593
+qtodec:232084364697362395/63954852178,10,0,0:3628878
+qtodec:-15233960541477728/29236841251,2,10,0:-1111111001101011101.1001001000
+qtodec:-204455585309689977/2573797241,24,8,0:-9NA80J.I46J0E07
+qtodec:-208654616780822858/3143953651,16,20,0:-3F4ADE6.A4B10A1959FE7A9D8B74
+qtodec:61432060563100995/654186158,10,20,0:93906084.39486577305415869101
+qtodec:-215408951941727837/842697775,16,20,0:-F3C6CE3.6A4AABDAB1F876EE1689
+qtodec:1494042204388242/341149,2,14,0:100000101000010001111101010110000.01010101100110
+qtodec:252329963368832243/44580470,35,4,0:32QT0LR.50QV
+qtodec:168671981609579290/315937,10,17,0:533878531509.69747133130972314
+qtodec:97357880572782372/2370407,5,16,0:1133103442034142.2141330201310323
+qtodec:438158095794943133/660884,8,17,0:11513512103507.35524017602321151
+qtodec:7850289549554440/306739,21,4,0:E4890EGI.6AGB
+qtodec:119806400157154998/22543,8,20,0:115254513702023.51671000734614004504
+qtodec:842337451434634867/22911,16,20,0:21702A953033.D41940A3C2E70126A09C
+qtodec:-191741119725912979/977,10,12,0:-196254984366338.770726714431
+qtodec:679872291852418397/4361,16,19,0:8DC9E4228BBD.64F7B9167BA06ED4626
+qtodec:-520912901611533563/280,2,4,0:-110100111000000011011100001000100011100110111100111.0100
+qtodec:39729892807989997/54,8,8,0:24722320713461336.35502275
+qtodec:970713517442043449/37,10,14,0:26235500471406579.70270270270270
+qtodec:29117381123938587/8,16,12,0:CEE4352D5D323.600000000000
+qtodec:363588332502803888/3,35,2,0:18WP2QFWYK2H.NB
+qtodec:797307393945548281/8,10,23,0:99663424243193535.12500000000000000000000
+qtodec:962196352783334317/9197391367410673270,24,6,0:0.2C653F
+qtodec:-1712459327217296767/24201664403827655252,2,12,0:-0.000100100001
+qtodec:-6257340861519758901/171587352958408768,11,22,0:-33.516097715A478605011696
+qtodec:417344045124814390/1985525411662453127,16,6,0:0.35CF39
+qtodec:4903347687958413477/936909515551143478,8,9,0:5.167443402
+qtodec:6815391545417096283/459992327223804545,16,7,0:E.D0FA110
+qtodec:104292470919702350/405232099156473,10,0,0:257
+qtodec:1273295935414124869/12782736302053151,34,23,0:2V.KPSOK4L6RBMXDCVRWQAD0GN
+qtodec:4109078480849408360/435043171158277,10,19,0:9445.2200454249798277382
+qtodec:6514718679505732082/7354769508455189,8,8,0:1565.62007631
+qtodec:9866917402610085742/359433106924021,16,16,0:6B3B.54E315BF403F00E2
+qtodec:-1457774896854499915/466537799128293,21,21,0:-71G.DKGG5JHK6IED1DCB8C949
+qtodec:3562469801994530303/39520702664299,10,5,0:90141.86393
+qtodec:-1121788856677512277/4346264061083,10,15,0:-258104.165074127011561
+qtodec:-9277969991539582813/2921352796605,8,5,0:-14072753.47761
+qtodec:9405317682640021543/7885054834345,8,24,0:4431543.050247665143116233543566
+qtodec:6327008262496741021/191631004675,10,9,0:33016621.048494437
+qtodec:932916830728130561/490000068712,16,15,0:1D0D27.A1E90D8F3EB7E02
+qtodec:529997294498903710/61063223157,27,15,0:G8Q0A.BEM6E6H7QAPGMP1
+qtodec:-378316587720990944/3926689661,16,23,0:-5BE1B54.8DB9C3FC5575501C10951F3
+qtodec:-3320019367427260995/7860304231,16,6,0:-192CF9F4.E51A76
+qtodec:2546767615570206397/876018632,2,5,0:10101101010010000111010111011100.11111
+qtodec:4651229211968910861/560332411,10,14,0:8300839145.94208768873089
+qtodec:5163696080111021129/746361687,8,10,0:63427744254.2545124347
+qtodec:-9950518479492602835/4241804,8,1,0:-42105571761136.6
+qtodec:420714617814952557/20658446,10,21,0:20365259701.284044162857167475230
+qtodec:6389761026090454423/1077366,10,3,0:5930910225578.359
+qtodec:-3097681303678311991/1783890,4,6,0:-121101032000121021210.120323
+qtodec:821760264557780373/82357,2,1,0:10010001001100110000101011011100100010101100.1
+qtodec:6406014444168904793/598448,10,17,0:10704379401667.15369255139962035
+qtodec:1412628290169413175/3619,16,24,0:16302549B006E.CA617A05CCED655E02B02315
+qtodec:2486326722603345473/4212,10,22,0:590295993020737.2917853751187084520417
+qtodec:2663530739497419216/4037,16,2,0:25810EFFC7428.72
+qtodec:-214922836739795459/270,10,12,0:-796010506443686.885185185185
+qtodec:6226184158746697831/799,16,18,0:1BAF35FD2D429A.8FDC1D7A12954E7F84
+qtodec:-2407322554685617466/195,16,13,0:-2BDBEF138C3CFD.ABFABFABFABFA
+qtodec:858459865910732119/11,24,16,0:236L1CMG4BGII.248HALJF6D248HAL
+qtodec:2546836315293994167/4,8,10,0:43260270424442471455.6000000000
+qtodec:1687480025170556035,8,1,0:135531042215166732203.0
+qtodec:8502691839655002109/6,10,23,0:1417115306609167018.16666666666666666666666
+qtodec:13139171374879806857/10977381074509304689,10,0,0:1
+qtodec:25010427150343850302/67656897694844048439,16,9,0:0.5EA2677CC
+qtodec:34472195313108788669/434602033270864170,16,10,0:4F.51A97A0B8E
+qtodec:-83602382263216798102/7417291363069673277,2,14,0:-1011.01000101011100
+qtodec:255840050198896639/1315714580972021,2,17,0:11000010.01110011000100101
+qtodec:28302759431751782745/592140283405467652,16,17,0:2F.CC21AE72A26F651F8
+qtodec:3937631720009717237/36823618427527354,20,8,0:56.ICHH37AC
+qtodec:22545518158553313659/62467059813338995,16,15,0:168.EB237A73BBA8622
+qtodec:-48446768942686919883/3741466474083086,4,11,0:-3022110.21222310212
+qtodec:7169357010298918984/1220646708315151,10,7,0:5873.4087115
+qtodec:46778564443315773088/210614351846423,4,12,0:312032121.103121102132
+qtodec:30982166662165412803/52147001878280,2,11,0:10010001000011010011.01001111111
+qtodec:80598339985947052706/2958216824641,16,15,0:19FBC0E.4F4E111B987AE60
+qtodec:44066815386005295782/52340788103663,10,7,0:841921.1284845
+qtodec:2228125575854677152/794184699731,16,5,0:2ACF2E.DEE87
+qtodec:-31021849545265661608/4106419586427,27,24,0:-E5LLB.8KKG3308C79II4HIF7HO8DM2
+qtodec:77877994428662842064/93387431541,16,12,0:31B4AA89.4008C5AB084B
+qtodec:-659373254181263916/165391612333,10,10,0:-3986739.3810375323
+qtodec:98882644692855550886/8432909589,10,7,0:11725803964.7240371
+qtodec:69505961999667187147/91220437346,10,11,0:761956026.76218709506
+qtodec:10734338306931222346/1274484573,10,24,0:8422493715.764437382483718773110641
+qtodec:61367391524217084335/6370835564,14,13,0:6754326B1.A46C4BC7937B9
+qtodec:44577580152302734007/198070854,8,10,0:3214643014233.3071243700
+qtodec:-56791209452014782584/235059441,16,12,0:-3840B28498.8ADFAA158075
+qtodec:16511384744316378091/2678129,8,6,0:131556651335325.270744
+qtodec:88298173378026931716/10792589,10,12,0:8181370881261.848451377144
+qtodec:-42234235979751132649/8018900,24,5,0:-1NK84K6EHI.JE0IE
+qtodec:18531075354063777193/5038119,16,19,0:35864383BFF.AB3590FFE1BAF5F6E6B
+qtodec:36664397392769922711/807520,4,10,0:22110231133201221212231.0003203003
+qtodec:-42507384945776962084/555657,10,23,0:-76499324125813.15826850017186861679057
+qtodec:486858786170940568/88643,8,18,0:117731165754015.026354742305726672
+qtodec:893199977657440169/88569,10,0,0:10084792395278
+qtodec:45981109152253249913/3272,16,8,0:31ED0B3350005A.DF87D2EF
+qtodec:10005656828299907515/97,4,10,0:11232131312011100201311102202.3222320233
+qtodec:5497769811530428529/891,4,11,0:111322332031222203312210312.12320022322
+qtodec:19676898338016110283/235,4,18,0:10221132111123222120031323300.201133313102033302
+qtodec:92885714512301641859/8,10,19,0:11610714314037705232.3750000000000000000
+qtodec:46299019950017172226/55,2,14,0:101110101110101011001111100001001000001011000011010010110101.10010000010010
+qtodec:86031296735581415137/3,8,6,0:3067714130270613633640.252525
+qtodec:-74317122139160378225/9,4,6,0:-13022120120211002233111020312313.032032
+qtodec:68655/564493455483553,10,10,0:0.0000000001
+qtodec:744/11213190182777,8,17,0:0.00000000000443637
+qtodec:1969/316819189359038,10,8,0:0.00000000
+qtodec:-28439/301147910327855,8,17,0:-0.00000000000637251
+qtodec:47926/42794221756379,10,6,0:0.000000
+qtodec:8609/54631358200256,4,0,0:0
+qtodec:52489/82632930569226,2,8,0:0.00000000
+qtodec:10307/11184215134882,16,14,0:0.00000003F545F5
+qtodec:-31349/9533318763438,2,5,0:0.00000
+qtodec:-26472/3296480616721,8,0,0:0
+qtodec:57256/806743900853,16,15,0:0.00000130D23A739
+qtodec:40722/3682812606167,2,7,0:0.0000000
+qtodec:37969/34007088009,10,0,0:0
+qtodec:78781/962690517003,10,15,0:0.000000081834191
+qtodec:7283/142340577595,16,9,0:0.000000DBC
+qtodec:76855/907629934047,4,2,0:0.00
+qtodec:15363/69482486347,8,4,0:0.0000
+qtodec:-289/869154128,10,24,0:-0.000000332507193706845053
+qtodec:-21217/25103660786,19,1,0:0.0
+qtodec:13692/5736313747,32,11,0:0.0002G2T6T27
+qtodec:1355/477699881,10,14,0:0.00000283650897
+qtodec:18475/503078099,16,14,0:0.00026820095C41
+qtodec:62593/8927182523,8,24,0:0.000001655043044264105063
+qtodec:-82180/4421221347,16,9,0:-0.000137D93
+qtodec:-24674/17452297,12,7,0:-0.0025396
+qtodec:-11477/47606496,21,11,0:-0.0024ICB8BA6
+qtodec:-21973/418977883,8,17,0:-0.00001557675043667
+qtodec:-41725/131769957,22,2,0:0.00
+qtodec:3199/70769667,10,10,0:0.0000452029
+qtodec:34338/94122911,2,20,0:0.00000000000101111110
+qtodec:-13736/2772531,10,23,0:-0.00495431791384839339938
+qtodec:-5183/49753414,2,20,0:-0.00000000000001101101
+qtodec:-51566/4144321,10,12,0:-0.012442568999
+qtodec:-96027/1859756,4,4,0:-0.0031
+qtodec:12379/2809096,16,6,0:0.0120CD
+qtodec:-24031/9122052,17,11,0:-0.00CG07B319C
+qtodec:12305/38714,8,11,0:0.24257063763
+qtodec:88995/335867,8,14,0:0.20752442752633
+qtodec:81953/624954,16,1,0:0.2
+qtodec:1944/4277,33,16,0:0.EWW7Q5DG2C5HIGRA
+qtodec:54911/82297,10,10,0:0.6672296681
+qtodec:29583/27671,16,14,0:1.11B0618C693572
+qtodec:-75887/60475,10,16,0:-1.2548491112029764
+qtodec:17652/15565,16,2,0:1.22
+qtodec:87767/115652505214716,4,18,0:0.000000000000000310
+qtodec:12897/583646546551346,16,2,0:0.00
+qtodec:-19825/432539042784217,16,19,0:-0.00000000326520AEFDE
+qtodec:736440/839968528505573,4,18,0:0.000000000000000330
+qtodec:703589/85878714909896,8,18,0:0.000000001063003223
+qtodec:608123/89966921812529,10,15,0:0.000000006759406
+qtodec:919819/82768941199286,8,23,0:0.00000000137353716263317
+qtodec:-38153/35848949843701,16,23,0:-0.00000004922DAC4A09FC403
+qtodec:209877/1638057441965,10,0,0:0
+qtodec:751856/1582376330691,8,10,0:0.0000000776
+qtodec:212627/2270529591527,16,5,0:0.00000
+qtodec:-342197/1695850530890,8,19,0:-0.0000000330524323052
+qtodec:360157/727872304477,16,10,0:0.0000084D2F
+qtodec:-840347/766875155324,8,7,0:-0.0000002
+qtodec:441366/320303145713,10,14,0:0.00000137796336
+qtodec:-397333/170752574257,20,0,0:0
+qtodec:377646/38251209193,16,16,0:0.0000A5A34AEE4273
+qtodec:492455/93020377059,10,14,0:0.00000529405508
+qtodec:-329137/677535547,8,1,0:0.0
+qtodec:-906246/51378477563,10,1,0:0.0
+qtodec:860093/6194527744,19,3,0:0.000
+qtodec:31316/103976957,23,3,0:0.003
+qtodec:243505/1499845166,8,7,0:0.0000524
+qtodec:482241/2737367521,10,17,0:0.00017616962147042
+qtodec:567088/116192713,16,14,0:0.013FDA91B97CF9
+qtodec:694040/908350707,8,9,0:0.000310227
+qtodec:288216/7323035,10,14,0:0.03935745220390
+qtodec:991400/605403489,16,24,0:0.006B522057B40442574209DF
+qtodec:-461143/35204521,2,16,0:-0.0000001101011010
+qtodec:-117710/43583043,16,20,0:-0.00B1004216172B6035A9
+qtodec:-3056/22397223,2,15,0:-0.000000000000100
+qtodec:-102033/8495267,4,1,0:0.0
+qtodec:110927/145078,27,19,0:0.KHAI30C2MDG85E9MMC2
+qtodec:106035/1516586,8,11,0:0.04363023014
+qtodec:-78219/7511632,16,22,0:-0.02AA6DFD6E8394C7FBAF89
+qtodec:64866/256723,16,1,0:0.4
+qtodec:-384383/794667,30,8,0:-0.EF9TIJGJ
+qtodec:105023/359600,10,13,0:0.2920550611790
+qtodec:-335084/614183,10,5,0:-0.54557
+qtodec:173356/199035,16,23,0:0.DEF8B56028757A16842DA12
+qtodec:381414/97673,27,20,0:3.OBK85563P4LQHMP877N1
+qtodec:740226/15361,10,10,0:48.1886595924
+qtodec:791292/78311,4,2,0:22.01
+qtodec:284139/12334,10,12,0:23.037052051240
+qtodec:823655/378760563881187,10,4,0:0.0000
+qtodec:4866313/111569112800605,19,9,0:0.0000020IE
+qtodec:1858787/249890994746724,10,5,0:0.00000
+qtodec:7273440/805769398706737,8,22,0:0.0000000011542366515000
+qtodec:-9119403/7773223229000,16,5,0:-0.00001
+qtodec:2054927/69883023343346,8,17,0:0.00000000374455467
+qtodec:-3095106/23726483413861,10,19,0:-0.0000001304494200009
+qtodec:1124235/18821267939248,8,16,0:0.0000000100106064
+qtodec:-825697/8046469218859,4,4,0:0.0000
+qtodec:-8466329/522547357251,10,5,0:-0.00001
+qtodec:-451191/4499178998474,16,11,0:-0.000001AEB64
+qtodec:359287/900902946089,10,1,0:0.0
+qtodec:-1567363/85934054431,8,3,0:0.000
+qtodec:508948/70232110139,16,17,0:0.00007994276FF3FFE
+qtodec:2394568/624074713719,8,1,0:0.0
+qtodec:-4216998/945198033841,16,12,0:-0.00004AD9FB9A
+qtodec:8302337/6722959869,16,14,0:0.0050EE9167ED89
+qtodec:429445/95937769192,35,7,0:0.0006P3L
+qtodec:331857/43689514733,10,16,0:0.0000075958042113
+qtodec:159145/7758156704,10,4,0:0.0000
+qtodec:2901825/9825452368,8,1,0:0.0
+qtodec:9606613/3849003924,16,22,0:0.00A391BF8D5B12DB0C8967
+qtodec:581921/247249935,4,17,0:0.00002122033212230
+qtodec:-7077467/7969534729,4,23,0:-0.00000322030310031021011
+qtodec:7654151/567131838,8,0,0:0
+qtodec:-157427/61065933,16,22,0:-0.00A8F3651849629E3984C9
+qtodec:9393952/205343869,19,20,0:0.0G9EG2BH71D114B92E89
+qtodec:1582726/158038579,2,13,0:0.0000001010010
+qtodec:2124277/82841119,4,6,0:0.001221
+qtodec:3083421/3981011,10,22,0:0.7745321477383508862447
+qtodec:3235080/17333887,4,3,0:0.023
+qtodec:-1229849/73704028,8,18,0:-0.010426157756241450
+qtodec:-1583401/1441424,10,15,0:-1.098497735572600
+qtodec:7626667/3243668,4,4,0:2.1121
+qtodec:-1121161/1274083,10,0,0:0
+qtodec:562341/836315,10,1,0:0.6
+qtodec:7101809/698134,2,17,0:1010.00101100001011001
+qtodec:3520373/805634,4,1,0:10.1
+qtodec:-6935257/276974,16,22,0:-19.0A14C076A97C6E6EAC313C
+qtodec:-944696/960767,10,0,0:0
+qtodec:-1179024/57377,8,10,0:-24.4307440501
+qtodec:-6460475/3693,10,9,0:-1749.383969672
+qtodec:4614415/37109,10,2,0:124.34
+qtodec:-257431/24801,26,10,0:-A.9MKCFG90C1
+qtodec:79010339/389043341388123,16,19,0:0.00000368427AA7D37AB
+qtodec:77290549/450505435559884,29,11,0:0.00003F1D92R
+qtodec:1533996/23992454790335,16,3,0:0.000
+qtodec:20673781/414667535279553,10,20,0:0.00000004985628061300
+qtodec:1613195/541735894212,4,23,0:0.00000000030133112221312
+qtodec:-63576657/214144111954,16,16,0:-0.001374F10A12653D
+qtodec:80261049/89465234336497,10,11,0:0.00000089711
+qtodec:-92707227/46577185021877,16,2,0:0.00
+qtodec:20180088/9052096932529,10,11,0:0.00000222932
+qtodec:5958725/9682403484536,4,2,0:0.00
+qtodec:6585917/42481037484,10,19,0:0.0001550319245964863
+qtodec:47989819/1900947593758,4,15,0:0.000000012213202
+qtodec:-54873667/162032680162,8,4,0:-0.0001
+qtodec:-52980833/419098674300,26,15,0:-0.0025JPO9FCEKGE3
+qtodec:-60842116/680762626237,16,5,0:-0.0005D
+qtodec:-45311824/640856069947,16,19,0:-0.0004A23C4D9E3DCA928
+qtodec:46200845/79924033279,10,24,0:0.000578059478539094811289
+qtodec:98460259/75913335170,2,10,0:0.0000000001
+qtodec:24809941/19096691737,16,18,0:0.005524895A3969F3B0
+qtodec:10882277/3259863295,31,11,0:0.036DTIINPNJ
+qtodec:4972596/3972114529,8,24,0:0.000510127773454276673616
+qtodec:-14213132/6879138065,10,24,0:-0.002066121055530813801161
+qtodec:10551615/4849980697,16,18,0:0.008E94803047CFE692
+qtodec:-10819947/251762996,10,4,0:-0.0429
+qtodec:-5411766/234581185,10,2,0:-0.02
+qtodec:-14769835/347988511,2,7,0:-0.0000101
+qtodec:50123417/964435923,2,23,0:0.00001101010011100000010
+qtodec:-16460359/132357561,2,23,0:-0.00011111110101100011110
+qtodec:3791364/16604819,16,22,0:0.3A73C74220AF142E9A1AF8
+qtodec:37528863/53944966,10,17,0:0.69568795353397757
+qtodec:-124027/319601,16,3,0:-0.635
+qtodec:4793306/12338915,4,12,0:0.120313023033
+qtodec:26259994/812687,4,17,0:200.11000003221312333
+qtodec:-46562347/4867601,8,15,0:-11.441530754510376
+qtodec:17565101/2286550,4,6,0:13.223221
+qtodec:63309560/2167187,16,1,0:1D.3
+qtodec:272611/47935,7,17,0:5.45445020052652515
+qtodec:22106/1745,10,15,0:12.668194842406876
+qtodec:92712989/247904,12,7,0:271.BA24145
+qtodec:-26831343/493699,10,1,0:-54.3
+qtodec:82814925/36226,8,4,0:4356.0402
+qtodec:5223041/7597,2,6,0:1010101111.100000
+qtodec:1284647/982,10,12,0:1308.194501018329
+qtodec:1433947/3182,4,8,0:13002.22102233
+qtodec:-344137/2854599874650,4,20,0:-0.00000000000200113013
+qtodec:165197798/175803438592331,10,11,0:0.00000093967
+qtodec:-477975899/343848834437535,8,4,0:0.0000
+qtodec:-179094377/38000927193456,8,12,0:-0.000001170433
+qtodec:128908614/5526392874913,10,7,0:0.0000233
+qtodec:78808036/21436353240389,15,20,0:0.00002BD2221322244863
+qtodec:141778616/4804415363543,2,7,0:0.0000000
+qtodec:-525236484/20786529543401,4,20,0:-0.00000001221332312331
+qtodec:-330972359/2306003612051,16,0,0:0
+qtodec:72312481/6690636866,16,10,0:0.02C4505872
+qtodec:52490699/28938790787,4,14,0:0.00001312313312
+qtodec:-282868783/8254983317343,10,11,0:-0.00003426642
+qtodec:822417609/530339299663,10,5,0:0.00155
+qtodec:-481554202/25544143895,16,17,0:-0.04D3797320111700E
+qtodec:35278143/42465228617,4,10,0:0.0000031213
+qtodec:369827999/465038226115,8,12,0:0.000320362366
+qtodec:-505275021/38032954912,10,1,0:0.0
+qtodec:254690907/68730592706,16,17,0:0.00F2DA573347E3502
+qtodec:-106083040/46269280369,10,12,0:-0.002292731573
+qtodec:-60406265/22643434934,34,12,0:-0.032SWS7SG010
+qtodec:319918396/6184401717,10,9,0:0.051729886
+qtodec:-140330623/1088869052,8,5,0:-0.10177
+qtodec:-409230877/2046172793,16,9,0:-0.333315036
+qtodec:314851793/5236274560,2,24,0:0.000011110110010010011100
+qtodec:128553221/836175814,6,6,0:0.053112
+qtodec:-122961428/611026759,4,19,0:-0.0303201010230121103
+qtodec:-446255647/346867903,10,24,0:-1.286529088279465281052539
+qtodec:-260572769/470364896,28,6,0:-0.FE8R4F
+qtodec:280776256/10072775,8,5,0:33.67770
+qtodec:369274812/9412439,10,11,0:39.23263800169
+qtodec:-316593321/24342910,28,8,0:-D.04A53L0J
+qtodec:152179493/70796663,10,7,0:2.1495291
+qtodec:-600553760/2862917,10,22,0:-209.7698815578656314521168
+qtodec:68116207/854536,10,8,0:79.71133691
+qtodec:831793089/4921439,2,17,0:10101001.00000011101000101
+qtodec:-430839925/3981974,4,0,0:-1230
+qtodec:665664377/410666,16,9,0:654.F04907A9E
+qtodec:427424299/163630,7,24,0:10421.065444130504402406531221
+qtodec:-570208971/139948,6,8,0:-30510.23351152
+qtodec:403698908/154223,35,7,0:24R.M2YQLYB
+qtodec:211979567/2715,16,13,0:130FD.3046E824F649B
+qtodec:691881174/35801,10,17,0:19325.74995111868383564
+qtodec:718421447/46942,16,16,0:3BC8.72F483CD15F4B8DA
+qtodec:201501728/17427,10,7,0:11562.6170884
+qtodec:6614235784/345886207819559,10,13,0:0.0000191225774
+qtodec:-2302388421/790735305178466,2,17,0:0.00000000000000000
+qtodec:7147160405/219749646210273,2,19,0:0.0000000000000010001
+qtodec:1993884675/319701400539757,2,9,0:0.000000000
+qtodec:6157645931/53304026168395,16,19,0:0.00079217C9BDFCFA6C0
+qtodec:1746071285/5227857159967,4,16,0:0.0000011132031323
+qtodec:553442690/20934817860993,32,23,0:0.000RN1U6EMOSU5RV9F49PC4
+qtodec:3205641509/24017897955798,10,12,0:0.000133468862
+qtodec:3393272000/255645842301,10,2,0:0.01
+qtodec:9744696047/5669769706461,16,16,0:0.0070A32FE7590818
+qtodec:3865439982/2777396640079,8,22,0:0.0005546553373234167534
+qtodec:4190724699/7966032689051,33,7,0:0.00ITT41
+qtodec:-9506622734/658378266099,10,0,0:0
+qtodec:3974837290/274042666569,10,23,0:0.01450444684313124346213
+qtodec:3060351821/439485280782,8,7,0:0.0034413
+qtodec:-3608767797/392112547931,3,20,0:-0.00002020101100120022
+qtodec:-955758669/13342842196,10,4,0:-0.0716
+qtodec:389442347/27273496087,8,16,0:0.0072371430615551
+qtodec:5632160912/39395530459,10,16,0:0.1429644644044466
+qtodec:2712067031/40703849020,33,24,0:0.26IF0WA1MRBQE0RTIFEMN3WE
+qtodec:5097549193/6461069250,2,14,0:0.11001001111110
+qtodec:7958065019/7287746841,24,20,0:1.24NC8DE54L3EKC4A039D
+qtodec:8706651840/8110760959,21,20,0:1.1B887AG7I6KF270GDIG0
+qtodec:1270979794/691940283,8,10,0:1.6543531132
+qtodec:-9105312527/329024092,10,18,0:-27.673695478202246661
+qtodec:1056925223/1272276,19,5,0:25D.DIBG8
+qtodec:-7999259177/792682763,16,11,0:-A.17645D7D0D8
+qtodec:7669473418/610724525,16,17,0:C.8ED8889631A0F8E4A
+qtodec:1543148811/90789352,12,22,0:14.BB6A362A93B84A069598BB
+qtodec:3603627164/30995143,10,11,0:116.26425353159
+qtodec:7737616061/5485940,10,3,0:1410.444
+qtodec:2810821129/39280616,10,16,0:71.5574605296413885
+qtodec:5927485272/2570707,10,23,0:2305.78018887411128533901374
+qtodec:3101097701/525664,2,22,0:1011100001011.0110010000110101010011
+qtodec:2470594099/907464,2,4,0:101010100010.1000
+qtodec:22580764/15141,4,19,0:113103.1131203032310023320
+qtodec:-41037999/6632,16,0,0:-182B
+qtodec:1026897985/217757,10,4,0:4715.7978
+qtodec:8539499023/655885,10,21,0:13019.811434931428527866927
+qtodec:-2250794858/346599,4,14,0:-1211131.33013232112020
+qtodec:-9450403358/13649,10,1,0:-692387.9
+qtodec:204008989/1324,27,17,0:7M9N.945Q8MB323LQ00ENA
+qtodec:1031368481/24059,10,0,0:42868
+qtodec:1641140120/9907,10,17,0:165654.59977793479358029
+qtodec:10594464181/256539867180682,8,2,0:0.00
+qtodec:-46231449261/99440850943399,10,14,0:-0.00046491405516
+qtodec:27073997033/979290145342336,16,12,0:0.0001CFD50AA2
+qtodec:21909914237/215314847601042,10,18,0:0.000101757563313037
+qtodec:22790213983/20690898775054,16,15,0:0.00482F72209EE2C
+qtodec:57162073993/66399138763836,16,24,0:0.00386B443F1EB24EAADD18E5
+qtodec:49004505327/38821416507106,16,17,0:0.0052B9FACDD757940
+qtodec:11768332051/3589682824180,10,12,0:0.003278376566
+qtodec:15850186666/2474635965095,10,16,0:0.0064050579113730
+qtodec:46667593003/1864122052703,4,0,0:0
+qtodec:-59759544899/1772867786040,10,1,0:0.0
+qtodec:-56774525477/9339451223280,10,9,0:-0.006079000
+qtodec:88931309073/791190043090,10,23,0:0.11240195683666335508307
+qtodec:-35855044967/97196495706,10,12,0:-0.368892362904
+qtodec:31352585060/666072991803,16,24,0:0.0C0CD4E3E1E55177982A4E95
+qtodec:-4008002633/30236135502,4,15,0:-0.020132330330203
+qtodec:-46826363590/29612569101,16,18,0:-1.94D0183BB64FFD4582
+qtodec:-35128605083/27702402610,16,20,0:-1.44A0480BA20A024C6723
+qtodec:-65659897349/54589663850,16,11,0:-1.33EA0A452B1
+qtodec:86323433001/89177536283,16,5,0:0.F7CE8
+qtodec:12490055427/952518779,2,8,0:1101.00011100
+qtodec:2264332583/1185373888,16,18,0:1.E9049A2BCA80B2A224
+qtodec:-74427879390/4597012537,29,9,0:-G.5F5O0DEKA
+qtodec:29951503181/2445822201,8,0,0:14
+qtodec:-31576431431/83020171,10,9,0:-380.346499539
+qtodec:-9447985051/104277227,16,6,0:-5A.9ABFE8
+qtodec:35232385623/566066791,16,1,0:3E.3
+qtodec:-15116306133/99765700,16,7,0:-97.84A01D7
+qtodec:85943946533/13486473,8,4,0:14344.4650
+qtodec:17458384033/41778207,10,15,0:417.882558554990165
+qtodec:47372358000/36962941,16,4,0:501.9E1F
+qtodec:-19944419571/15407785,16,5,0:-50E.7014B
+qtodec:5577496827/9366839,16,9,0:253.738AF7ED4
+qtodec:2073882842/2445003,16,16,0:350.367A18E86AC9C78B
+qtodec:-43839972997/4451064,10,3,0:-9849.324
+qtodec:26005540769/1779488,24,3,0:118M.199
+qtodec:1651522055/135313,16,9,0:2FAD.32DF9AD5F
+qtodec:76197886466/518409,27,11,0:7CGN.30FE7G874BA
+qtodec:765108336/7387,10,5,0:103574.97441
+qtodec:23901412931/455042,5,21,0:3140100.331040440011320300133
+qtodec:-30812270737/28228,2,4,0:-100001010011111011101.1110
+qtodec:-40336960322/42873,30,15,0:-14PBH.IOF1RIL9A5ETT1J
+qtodec:8218880614/47365,10,15,0:173522.234012456455188
+qtodec:4420970446/22233,4,11,0:300202333.03222222132
+qtodec:614430785631/133706995251806,16,5,0:0.012D2
+qtodec:599123774551/302548464679822,4,8,0:0.00002001
+qtodec:281790013817/560893551217888,8,11,0:0.00020354622
+qtodec:-206717407741/550231026879086,8,23,0:-0.00014237041720054527517
+qtodec:666962690207/14069382615292,10,18,0:0.047405256395691365
+qtodec:931917525705/93596193043406,11,24,0:0.0122860711573932A1A861A6
+qtodec:-113538101447/619757160013,16,16,0:-0.2EE60BCB5C2D54A9
+qtodec:728394383355/38080601690192,4,13,0:0.0010321120312
+qtodec:189773534962/4102482488695,8,2,0:0.02
+qtodec:10973390446/485105217927,4,22,0:0.0011302213131130210013
+qtodec:-115610427903/163642536352,4,24,0:-0.231031233321010131133112
+qtodec:-24720050891/3267467595011,10,13,0:-0.0075655075902
+qtodec:406509460181/819769573976,8,3,0:0.375
+qtodec:819367776495/157261270951,2,4,0:101.0011
+qtodec:-256014045305/291786063426,4,1,0:-0.3
+qtodec:10334656186/19273767409,16,24,0:0.89449D46C54D81A73E4D1527
+qtodec:-186869912318/39153869757,16,24,0:-4.C5D010D70DDE0283131D1DFB
+qtodec:217180119685/68726204146,10,3,0:3.160
+qtodec:129836079717/94890868831,16,19,0:1.5E46C53EB0621ACB13D
+qtodec:810979911896/61650722121,8,1,0:15.1
+qtodec:45011863358/4039593361,16,18,0:B.248624FAE640A4ACF0
+qtodec:-215420752673/1003997587,8,4,0:-326.4402
+qtodec:784586911285/4052339642,10,20,0:193.61331492386293912725
+qtodec:25138297055/497924358,10,20,0:50.48617656700377771034
+qtodec:66808621591/367038485,10,13,0:182.0207534667652
+qtodec:657202139395/116949531,10,10,0:5619.5363399533
+qtodec:-50242217502/259433627,8,15,0:-301.522407370214770
+qtodec:-805222832932/648093307,8,3,0:-2332.345
+qtodec:176740416233/55550964,23,7,0:607.DD7LBL1
+qtodec:15978966044/90531185,16,14,0:B0.809963ADB03146
+qtodec:-22930906857/3466300,10,13,0:-6615.3843744049851
+qtodec:428950257809/90217188,4,20,0:1022102.22033130022220202132
+qtodec:-729269681423/3415862,4,17,0:-310013313.01003010133211323
+qtodec:716760678407/8104084,4,6,0:111211330.120101
+qtodec:-56519730643/958996,4,4,0:-32120320.1123
+qtodec:75679919054/101713,10,8,0:744053.55317412
+qtodec:899780170392/784091,16,20,0:118299.976D24C16D10DCEF0726
+qtodec:654179133521/312025,10,22,0:2096559.9984648665972277862350
+qtodec:157095035973/829990,4,19,0:232031121.1220131333300101012
+qtodec:-118896971485/312696,8,8,0:-1346507.64746463
+qtodec:291032078135/26972,8,11,0:51122413.51356143360
+qtodec:-125244286687/10654,16,7,0:-B3605B.AA6F343
+qtodec:-254071356292/52021,2,8,0:-10010101000011000101111.00111010
+qtodec:-411717868922/67827,4,7,0:-113021331211.2202322
+qtodec:-3022414154367/90907778612482,16,11,0:-0.0882E0B2B5C
+qtodec:-17701275548/653297673253,17,7,0:-0.07E206F
+qtodec:8979713291953/175380602612246,8,24,0:0.032156070756223520303273
+qtodec:-5326013448559/12787683829043,4,24,0:-0.122221331303312310031302
+qtodec:857488611960/30586540342757,10,7,0:0.0280348
+qtodec:5738645734057/90951057139915,10,6,0:0.063095
+qtodec:2150180745771/75085058005357,10,10,0:0.0286365996
+qtodec:9211573654621/31326323574601,10,1,0:0.2
+qtodec:-2622066957883/1546353871091,10,6,0:-1.695644
+qtodec:224011912746/207690732319,10,17,0:1.07858405738553459
+qtodec:9555205925617/1205795142091,2,20,0:111.11101100101001011010
+qtodec:-8730617437121/6055175866493,10,24,0:-1.441843743207007133126749
+qtodec:-4064904713342/494211830517,10,24,0:-8.225025105306892432251847
+qtodec:7676618287424/780404569679,35,3,0:9.T9Y
+qtodec:-4358217891649/583281222878,17,13,0:-7.80676F3C2CC10
+qtodec:4328191663159/246276445006,26,9,0:H.EO9M9D2J7
+qtodec:737625000181/4792760124,17,17,0:90.F646D65A829FCC044
+qtodec:-71443761268/988984303,10,8,0:-72.23953004
+qtodec:381451888319/69461063050,16,1,0:5.7
+qtodec:201128820701/3339261143,16,3,0:3C.3B4
+qtodec:4042648911199/1793950960,10,7,0:2253.4890871
+qtodec:5673741769200/852342691,10,0,0:6656
+qtodec:-8389684341647/9150651656,10,15,0:-916.840095879505961
+qtodec:1372726881895/1560653491,16,19,0:36F.95ACC431C89A521C30D
+qtodec:328988903869/101330533,4,1,0:302232.2
+qtodec:6568406520821/800160752,8,17,0:20020.66750526036730745
+qtodec:501238490585/5971867,8,0,0:243735
+qtodec:6266930625937/691212664,8,23,0:21552.44562064316534547754507
+qtodec:4565491072367/11630659,16,17,0:5FD5B.541017CCD8963842F
+qtodec:-1162420020152/24630125,4,22,0:-23201123.0031031110222320020123
+qtodec:5113275296450/89201439,15,21,0:11EB7.BC9038ED2071A71B54669
+qtodec:3315661534768/61059429,10,14,0:54302.20342820434825
+qtodec:1733402780098/4797927,4,12,0:1120031001.212321010002
+qtodec:3283980196433/2438910,18,5,0:CEFF5.0A1C8
+qtodec:8489184557941/8439595,35,7,0:NG4A.SQX37QV
+qtodec:3788804069259/3461851,10,3,0:1094444.581
+qtodec:-3096145670549/510543,7,24,0:-102355342.020600564131455624420322
+qtodec:-3078702213873/276616,10,22,0:-11129877.5698911125892934609711
+qtodec:1748608098871/9819,8,9,0:1247254444.540514032
+qtodec:8487930264661/21627,15,11,0:246C724D.08EEC2CE9E2
+qtodec:740911632886/11719,16,19,0:3C4B546.94752D05B3962EF76A3
+qtodec:563687406299/41136,8,8,0:64213553.32002623
+qtodec:1780375881783/26804,33,7,0:1N09JI.51C9U8J
+qtodec:-3247679347711/26264,2,20,0:-111010111101101010000000000.10010101101101001111
+qtodec:21406766924698/763359226461945,8,7,0:0.0162672
+qtodec:24260209610958/200034339782053,10,24,0:0.121280224372428559322852
+qtodec:1814902384527/227339212768685,4,12,0:0.000200230300
+qtodec:31173219462521/203933404240669,8,6,0:0.116207
+qtodec:18030863259117/23714043196153,16,11,0:0.C2A5FEBA219
+qtodec:12974701069361/70664067852975,10,2,0:0.18
+qtodec:25696621276083/44253078013283,8,4,0:0.4512
+qtodec:9021988651073/35238715595793,10,6,0:0.256024
+qtodec:8048554533578/701038746989,16,11,0:B.7B1C260E450
+qtodec:-23885228112881/6921647732686,10,20,0:-3.45080088373872630271
+qtodec:33478283623865/8474518157089,8,1,0:3.7
+qtodec:-25807603431943/2948804373766,8,19,0:-10.6007565676256043474
+qtodec:89076698620825/964761424737,10,3,0:92.330
+qtodec:76836733524587/591287975017,16,14,0:81.F2B4FA0C640A59
+qtodec:2301284879441/92761811708,8,7,0:30.6357611
+qtodec:-22162325445043/7119385698,10,7,0:-3112.9547386
+qtodec:-88830049403167/77327410704,10,12,0:-1148.752409972677
+qtodec:40330389045243/30915263495,8,10,0:2430.4275130461
+qtodec:-97356183980680/88686324821,8,0,0:-2111
+qtodec:-61508444809/21872771653,4,5,0:-2.30333
+qtodec:-76008039360448/2365100065,2,20,0:-111110110001001.01011000100110100100
+qtodec:4553948402077/3181382511,10,21,0:1431.436926031746831338509
+qtodec:43200901021147/9612178431,4,1,0:1012032.1
+qtodec:98112477878099/2403895417,10,22,0:40813.9543776579361896591194
+qtodec:88141431773341/441452695,10,20,0:199662.23509710593113493168
+qtodec:-74737428452597/886243587,8,21,0:-244552.444607747231253546632
+qtodec:42004523099961/727188967,16,7,0:E1A2.DF30844
+qtodec:535967733905/65519711,9,19,0:12188.2235053083367133015
+qtodec:29508211302267/62743787,22,5,0:203F2.KH16G
+qtodec:20444506756589/73095694,10,8,0:279695.09061079
+qtodec:60358251477113/17276777,2,9,0:1101010100111011100101.111110110
+qtodec:7675515321823/53051166,16,2,0:23529.5E
+qtodec:68145812098865/9201386,6,15,0:422423113.430414512210252
+qtodec:9010952293583/1041530,10,5,0:8651649.29822
+qtodec:64799577298519/4451432,10,22,0:14557018.3479201749010206153884
+qtodec:4766086981551/1109401,4,20,0:100120312122.12111220122321000303
+qtodec:-14985202309069/259277,7,5,0:-1301154532.10024
+qtodec:77527740569441/65903,10,5,0:1176391675.18081
+qtodec:-34544219638590/487433,16,10,0:-43962AD.C208E5DFB8
+qtodec:89606198611077/718691,4,14,0:13123213120300.10302120010032
+qtodec:-20900481598325/19479,8,1,0:-7775046350.6
+qtodec:8694579108687/6527,2,14,0:1001111011001100010010100100000.10100101000000
+qtodec:11008512080877/36688,10,4,0:300057568.7112
+qtodec:-26629103193937/3238,16,24,0:-1EA2F4C19.E0C5562D391507BF7C71372F
+qtodec:320315168187847/67090457824132,16,10,0:4.C63D998DFE
+qtodec:37992496059712/933307870572061,2,15,0:0.000010100110101
+qtodec:-642835243415327/563880960452415,8,2,0:-1.10
+qtodec:-996741207812269/744724604059786,10,19,0:-1.3384024139643589286
+qtodec:865729136060421/18601273799867,4,24,0:232.202221202012312012111231
+qtodec:-190792427336021/12399475938971,8,11,0:-17.30615536546
+qtodec:353117587688196/41602134470867,4,12,0:20.133032231321
+qtodec:223068576005855/34076492509692,15,12,0:6.82D1EA2D84C4
+qtodec:219205101136492/2395575765723,4,5,0:1123.20010
+qtodec:456340378396493/4330214900946,16,21,0:69.6299AAE57B6C08183D61A
+qtodec:3571581360820/3092454154269,2,22,0:1.0010011110101001110001
+qtodec:847831462081399/7150211415400,10,5,0:118.57432
+qtodec:-898578802522565/555835047564,16,16,0:-650.A0E8207F331CE070
+qtodec:663661151253796/453138066205,10,19,0:1464.5892736664396649880
+qtodec:271225450200625/257749526519,34,21,0:UW.9L5RX9FJI38PG83BX6NV9
+qtodec:-165514406278015/4322124123,22,8,0:-3D2E.F462JIGL
+qtodec:969134788868309/87912888352,10,13,0:11023.8078515624311
+qtodec:349857780160166/918601801,10,19,0:380859.0183247049828067994
+qtodec:583417315283519/55625636618,23,7,0:JJ0.6AGDG5C
+qtodec:5198673145663/2582846448,2,16,0:11111011100.1100010011011010
+qtodec:25224504315989/2747113245,10,16,0:9182.1858315815444295
+qtodec:-354734288655699/8606733226,10,5,0:-41215.90379
+qtodec:294622457238131/4699248277,10,15,0:62695.656809649983088
+qtodec:84851645314450/3149545649,8,5,0:64474.72505
+qtodec:162782722239884/940443795,10,5,0:173091.38845
+qtodec:-503919081966818/49953093,10,12,0:-10087845.450667449160
+qtodec:696741265176479/547456417,10,10,0:1272688.0963320208
+qtodec:123373090223114/171645417,10,19,0:718767.1676844945997014298
+qtodec:530906534529992/21770787,10,10,0:24386189.3706457189
+qtodec:25200685975741/10321244,4,3,0:21110012200.213
+qtodec:-58528486417214/9145779,16,23,0:-61A614.0F20EFF0ECB8777D9D089D6
+qtodec:-202870643410118/39728965,4,0,0:-103132222332
+qtodec:226786253503/4854200,10,10,0:46719.5940634914
+qtodec:947663833947325/1199459,8,24,0:5705715226.174676743125024435532213
+qtodec:58508575771048/1950595,10,12,0:29995245.435904429161
+qtodec:-162029920997164/5378993,10,23,0:-30122723.89965259296675046797792
+qtodec:-638908439370581/780673,2,13,0:-110000110001111110011101001101.0011111111011
+qtodec:54048561476435/260446,16,13,0:C5E8D1C.AADE1542405BB
+qtodec:311253898901698/112463,16,23,0:A4F666A8.42F6DD7D2BF402286E84E52
+qtodec:-364014082098529/378836,16,13,0:-3945CA63.2A9FE228A057C
+qtodec:662955978899037/29150,8,10,0:251345254234.0616507470
+qtodec:380819161094198/155,16,19,0:23C0A857C06.F4704F4704F4704F470
+qtodec:19950100398461/41364,3,22,0:1020121112200021201.1102012021021112012001
+qtodec:843068174103353/67398,8,22,0:135145224047.7022451545330470767051
+
+# Writing decimal fractions, with rounding
+qtodec:@0.001,10,1,0:0.0
+qtodec:@-3.5,10,0,0:-3
+qtodec:@12.001,10,2,0:12.00
+qtodec:@0.001,10,1,2:0.1
+qtodec:@-3.2,10,0,2:-4
+qtodec:@12.001,10,2,2:12.01
+qtodec:@0.001,10,1,3:0.0
+qtodec:@0.051,10,1,3:0.1
+qtodec:@0.050,10,1,3:0.0
+qtodec:@-3.5,10,0,3:-3
+qtodec:@12.001,10,2,3:12.00
+qtodec:@0.001,10,1,1:0.0
+qtodec:@0.051,10,1,1:0.1
+qtodec:@0.050,10,1,1:0.1
+qtodec:@-3.5,10,0,1:-4
+qtodec:@12.002,10,2,1:12.00
+qtodec:@12.005,10,2,1:12.01
diff --git a/polly/lib/External/isl/imath/tests/root.t b/polly/lib/External/isl/imath/tests/root.t
new file mode 100644
index 00000000000..b7c5e8b4107
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/root.t
@@ -0,0 +1,44 @@
+# Root-finding tests
+
+# Square root tests
+sqrt:0,0:0
+sqrt:0,=1:0
+sqrt:1,0:1
+sqrt:1,=1:1
+sqrt:1,5:1
+sqrt:256,=1:16
+sqrt:257,=1:16
+sqrt:-1,0:$MP_UNDEF
+sqrt:-1,=1:$MP_UNDEF
+sqrt:-1029384298,66883:$MP_UNDEF
+sqrt:394820398429038402938402,=1:628347354915
+sqrt:394820398429038402938402,-5839823984:628347354915
+sqrt:17179869183,0:131071
+sqrt:4295098369,=1:65537
+sqrt:26965706504352387672564992041751053514175649974280741932736827760729,=1:5192851481060515336695158019653723
+
+# More general roots
+root:0,1,0:0
+root:0,1,=1:0
+root:0,5,0:0
+root:0,5,=1:0
+root:-1,5,0:-1
+root:-1,4,0:$MP_UNDEF
+root:-1,3,=1:-1
+root:-8,3,0:-2
+root:-8,3,=1:-2
+root:17,2,0:4
+root:17,3,0:2
+root:29,2,0:5
+root:29,3,0:3
+root:50,5,=1:2
+root:4295098369,2,0:65537
+root:4295098369,2,43:65537
+root:4295098369,2,=1:65537
+root:-4295098369,2,=1:$MP_UNDEF
+root:-4295098369,4,65537:$MP_UNDEF
+root:-281487861809153,3,0:-65537
+root:-281487861809153,3,=1:-65537
+root:-281487861809153,3,8349283:-65537
+root:-19991036671350700657170189502736817905009200157042372341654483623953031910930270960998207372480741818129399253027601458115528449927512127290460743651463958852225556661727551760552841554362323271980596910944452290359774556447658518439936535499843549082781717193598437061923,7,=1:-571823748273487384719287348728374273472
+root:26965706504352387672564992041751053514175649974280741932736827760729,2,=1:5192851481060515336695158019653723
diff --git a/polly/lib/External/isl/imath/tests/set.t b/polly/lib/External/isl/imath/tests/set.t
new file mode 100644
index 00000000000..0b870a135d0
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/set.t
@@ -0,0 +1,12 @@
+#Unsigned integer assignment. Assumes sizeof(long) == 8.
+setu:0,0:0
+setu:0,18446744073709551615:18446744073709551615
+setu:0,567:567
+
+#Signed integer assignment. Assumes sizeof(long) == 8.
+setv:0,0:0
+setv:0,-1:-1
+setv:0,9223372036854775807:9223372036854775807
+setv:0,-9223372036854775808:-9223372036854775808
+setv:0,4324:4324
+
diff --git a/polly/lib/External/isl/imath/tests/sqr.t b/polly/lib/External/isl/imath/tests/sqr.t
new file mode 100644
index 00000000000..84ef2d2d621
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/sqr.t
@@ -0,0 +1,755 @@
+# Squaring tests
+
+sqr:0,0:0
+sqr:495,0:245025
+sqr:702,0:492804
+sqr:23080,0:532686400
+sqr:-485,0:235225
+sqr:31727877,0:1006658178927129
+sqr:-8234442,0:67806035051364
+sqr:80,0:6400
+sqr:75029676,0:5629452280664976
+sqr:-8153,0:66471409
+sqr:5729957,0:32832407221849
+sqr:641,0:410881
+sqr:-82,0:6724
+sqr:7356,0:54110736
+sqr:0,=1:0
+sqr:7761224,0:60236597978176
+sqr:928319,0:861776165761
+sqr:912,0:831744
+sqr:334190449,0:111683256202821601
+sqr:#xAC46D3FD,0:#x73EF407495E70809
+sqr:-180,0:32400
+sqr:8965915,0:80387631787225
+sqr:1771,0:3136441
+sqr:131,0:17161
+sqr:2518088106,0:6340767709578667236
+sqr:31019,0:962178361
+sqr:460877681,0:212408236843937761
+sqr:2,0:4
+sqr:2,=1:4
+sqr:-43189,0:1865289721
+sqr:400,0:160000
+sqr:400,=1:160000
+sqr:16978,0:288252484
+sqr:32,0:1024
+sqr:4185,0:17514225
+sqr:246082426,0:60556560386045476
+sqr:5024,0:25240576
+sqr:4283818927,0:18351104599323431329
+sqr:79803747,0:6368638035240009
+sqr:27,0:729
+sqr:-294872579,0:86949837846111241
+sqr:5431,0:29495761
+sqr:-64,0:4096
+sqr:-27347593472,0:747890868709777014784
+sqr:-93,0:8649
+sqr:5941698,0:35303775123204
+sqr:68188,0:4649603344
+sqr:-10073,0:101465329
+sqr:712007,0:506953968049
+sqr:74981,0:5622150361
+sqr:590060947429,0:348171921680809101710041
+sqr:3375362,0:11393068631044
+sqr:6288,0:39538944
+sqr:-14938,0:223143844
+sqr:818,0:669124
+sqr:-61517636,0:3784419539028496
+sqr:-485757743,0:235960584884454049
+sqr:52047149,0:2708905719028201
+sqr:880295,0:774919287025
+sqr:23268913856,0:541442352037948788736
+sqr:8611582804,0:74159358390148502416
+sqr:-35440071,0:1255998632485041
+sqr:-123,0:15129
+sqr:-198239315,0:39298826011669225
+sqr:-18792,0:353139264
+sqr:42334,0:1792167556
+sqr:8871716,0:78707344784656
+sqr:-742998638,0:552046976069855044
+sqr:599309793653,0:359172228768401439084409
+sqr:92330620850,0:8524943546546454722500
+sqr:-21253,0:451690009
+sqr:-8591240,0:73809404737600
+sqr:-4406721416023,0:19419193638435754241136529
+sqr:7093605833487,0:50319243720880795970579169
+sqr:540053945630,0:291658264190530996096900
+sqr:6679643648234,0:44617639267392821131318756
+sqr:521589,0:272055084921
+sqr:13144286787,0:172772275138902783369
+sqr:-47469,0:2253305961
+sqr:480758624,0:231128854550373376
+sqr:-8238434,0:67871794772356
+sqr:-867204631,0:752043872027846161
+sqr:84079798766,0:7069412560531055122756
+sqr:14048677,0:197365325450329
+sqr:647598376181,0:419383656832267988144761
+sqr:89538606,0:8017161964423236
+sqr:8775965118,0:77017563752352753924
+sqr:135957585,0:18484464919032225
+sqr:76500157735,0:5852274133479880330225
+sqr:821777330800,0:675317981416772628640000
+sqr:38741,0:1500865081
+sqr:262422499893,0:68865568450091585011449
+sqr:-114911750278913,0:13204710352163261933292461569
+sqr:645965,0:417270781225
+sqr:-846535490921,0:716622337388858473428241
+sqr:56965538331,0:3245072557340630265561
+sqr:-744309142053,0:553996098943672933054809
+sqr:8398405793,0:70533219863895958849
+sqr:14899711014997,0:222001388330422931958910009
+sqr:4321091217,0:18671829305634541089
+sqr:818709681211,0:670285542108617246426521
+sqr:557620246567,0:310940339381441875285489
+sqr:666538614295667,0:444273724347187940858494974889
+sqr:-169058708804,0:28580847022475667110416
+sqr:-796502,0:634415436004
+sqr:-5416597755634,0:29339531246339285978741956
+sqr:922525,0:851052375625
+sqr:2993210,0:8959306104100
+sqr:1714169182508836,0:2938375986263011104043218074896
+sqr:-27353337,0:748205045035569
+sqr:9130672606905,0:83369182254485348653679025
+sqr:1596656380704,0:2549311598042796583535616
+sqr:-9683496758810,0:93770109477883775312616100
+sqr:909229240,0:826697810870977600
+sqr:333499398389171,0:111221848725938992589570067241
+sqr:-307250046,0:94402590767002116
+sqr:3035000042541,0:9211225258223871809736681
+sqr:-2721781933,0:7408096890805216489
+sqr:48792067992331,0:2380665898968251261074813561
+sqr:9234221,0:85270837476841
+sqr:8101724703211,0:65637943166619366033710521
+sqr:8164095821,0:66652460574469664041
+sqr:804766485,0:647649095379255225
+sqr:6183556496806,0:38236370949191691088201636
+sqr:48857539680655569,0:2387059183646833479261385610713761
+sqr:7026205978661388,0:49367570454577033123192362086544
+sqr:644316320534354,0:415143520906928406000094197316
+sqr:-2418657837,0:5849905732481518569
+sqr:-689024588558,0:474754883637521184519364
+sqr:7595432034404,0:57690587789250486239635216
+sqr:51477603372463937,0:2649943648972710500135406365539969
+sqr:-4859149914716259,0:23611337893687027113016478955081
+sqr:-596229664,0:355489812233552896
+sqr:539807450614764,0:291392083739210874761534775696
+sqr:-1566967626957,0:2455387543931251913079849
+sqr:65611170065548,0:4304825637370261946616540304
+sqr:30495282,0:929962224259524
+sqr:24673048425668,0:608759318615358173321246224
+sqr:-417870989,0:174616163447838121
+sqr:973135796,0:946993277456553616
+sqr:61834268876013338,0:3823476807431111794332536353902244
+sqr:82806890204302,0:6856981065307326523299307204
+sqr:1316959192994,0:1734381516011407738684036
+sqr:80328462383346,0:6452661868872633334658155716
+sqr:42624480104111,0:1816846304145754485399100321
+sqr:-375979141,0:141360314467097881
+sqr:9920379080,0:98413921090901646400
+sqr:80353168236771535,0:6456631645686909915006519786256225
+sqr:21921266256,0:480541914266444257536
+sqr:51036336390,0:2604707632113238232100
+sqr:7536279247897084,0:56795504902284238073836255703056
+sqr:4057492473172,0:16463245169847433139741584
+sqr:270453549401790,0:73145122384026464066855204100
+sqr:-97595328880030,0:9524848219201217774132800900
+sqr:2730620091663,0:7456286084993650522105569
+sqr:596640915610381483,0:355980382180394358404919444789279289
+sqr:907362117785845,0:823306012792813655285282364025
+sqr:3529407863794686,0:12456719869015768803663561838596
+sqr:5637629105915,0:31782861935859962287987225
+sqr:701177821774260333,0:491650337748096387958827849257270889
+sqr:388674994544,0:151068251383778429767936
+sqr:9003508844276352939,0:81063171508962508596780155978893937721
+sqr:5782278255807599,0:33434741827585369298571706144801
+sqr:54932190594257,0:3017545563483777218801382049
+sqr:2330326791,0:5430422952852357681
+sqr:2344523846,0:5496792064462631716
+sqr:734348606390121,0:539267875707112861194846394641
+sqr:1667343410703,0:2780034049214712934954209
+sqr:47416690990247089326,0:2248342584464579496535799798615023134276
+sqr:2992718026488505861,0:8956361186069257268281338748231351321
+sqr:36345508239,0:1320995969151216881121
+sqr:9136952501974852622,0:83483901023344519207328952878620274884
+sqr:-68684476889,0:4717557365515575118321
+sqr:3324362191672831934,0:11051383981423794566026717599410180356
+sqr:3950591846438354580,0:15607175937145207775001664097806976400
+sqr:452699498737223,0:204936836156932968571605751729
+sqr:16407472075973,0:269205139923833746283896729
+sqr:-42791759402,0:1831134672718655397604
+sqr:-969620447288,0:940163811798981186554944
+sqr:-7324554153015094663,0:53649093540450670762129798726851083569
+sqr:1246969904304174,0:1554933942240360863251113822276
+sqr:527095728932983463,0:277829907459393180154350270231472369
+sqr:133034527166,0:17698185418281191991556
+sqr:5806610887494202860,0:33716729998766214183769310106832179600
+sqr:604840631315943,0:365832189290668488059885979249
+sqr:7106121629098296578,0:50496964607538628518974633341246510084
+sqr:81378228896850,0:6622416138388112367939922500
+sqr:-18768741494576,0:352265657290218942237419776
+sqr:81188620065937,0:6591592028211068078227687969
+sqr:8219251025608152,0:67556087421960658524081448855104
+sqr:20867876779389,0:435468281279762622975213321
+sqr:27156769177930279482,0:737490112183384027655411672542630188324
+sqr:40320990680365371419,0:1625782289446111137560608246113822073561
+sqr:231848755308011786,0:53753845337874323313724120314909796
+sqr:841695784516,0:708451793672004705354256
+sqr:1766836913116,0:3121712677549275732829456
+sqr:664177322904,0:441131516259924282993216
+sqr:5979213918247228581465,0:35750999080161375874506971631233196141546225
+sqr:1758746127509067,0:3093187941028139358526167210489
+sqr:135179542401621982047,0:18273508683911915341791581411360790310209
+sqr:112047175441308,0:12554569524375254604552750864
+sqr:70541788345164680600,0:4976143902934011567084482333700016360000
+sqr:1492832267100,0:2228548177694925742410000
+sqr:3521705164411,0:12402407265039108540976921
+sqr:-473191108111249626,0:223909824795552331595427695285139876
+sqr:855883713881684,0:732536931687904321002750675856
+sqr:16916839558930925199,0:286179460662610259828831065810133189601
+sqr:296829185936965,0:88107565624001340524953411225
+sqr:7414275234516727336390,0:54971477253168072142121335070692704218232100
+sqr:90237037450605,0:8142722927861889317814866025
+sqr:60553464627047020812,0:3666722078339034795281351845204761139344
+sqr:4439551436109999,0:19709616953866354532829227780001
+sqr:5735204172472,0:32892566899940238322590784
+sqr:-477556465681133,0:228060177913855160813632163689
+sqr:6136903544018042,0:37661585108581203963482021513764
+sqr:7355012443029717610726,0:54096208037121975042332803663623262070247076
+sqr:2615297272121929464,0:6839779821568405573166111210191327296
+sqr:1236583510060121661932,0:1529138777352611011481426496873465697972624
+sqr:259304999298782298,0:67239082661341488057486265598160804
+sqr:67283385405374162098001,0:4527053951608116799312629323426390509928196001
+sqr:301048056239861279998,0:90629932165798680163672601418278954880004
+sqr:513985608867175879,0:264181206122561507573492869119422641
+sqr:8456087728243890247050,0:71505419667756916634176268857406110033702500
+sqr:978607251971625,0:957672153611455542449805140625
+sqr:190320200462916,0:36221778704244531620691223056
+sqr:213818886286553,0:45718516132821882562028621809
+sqr:-862217602106683,0:743419193382598324879713262489
+sqr:318640018205323583652,0:101531461201888944823553345475699841657104
+sqr:-500900129006539730,0:250900939238768144201293108068472900
+sqr:820114087330800098,0:672587116238431209810989756836809604
+sqr:55403047897851377414057,0:3069497716371613929908572787677424384421199249
+sqr:4810813844423644764918,0:23143929845698208536190754736426427483546724
+sqr:9103047106745502875,0:82865466627627670814122634036633265625
+sqr:963951698125641,0:929202876319306914592621660881
+sqr:539175052498265418,0:290709737236507269568171898774714724
+sqr:-50157204922004988220,0:2515745205588001416429472062562338768400
+sqr:11026905984136936161244,0:121592655582994972607713656480448242767627536
+sqr:3502071722216797290044,0:12264506347550524601785650136506422261521936
+sqr:-40351577732954785,0:1628249825538692426114606854396225
+sqr:-95254896582422725495010,0:9073495322928048629343683310955771449534900100
+sqr:60457070221477869,0:3655057339764706108220106456781161
+sqr:93325659970487089,0:8709678808926976205678491915693921
+sqr:413237232385124613101743,0:170765010229317482334791391007519236011269638049
+sqr:951114415591592288075347,0:904618631546136131332571710964234352253549170409
+sqr:401010074180215687828,0:160809079594022088656212052683319147357584
+sqr:52476554710721850732027,0:2753788794307383662963857897873667915763528729
+sqr:5258576802493280623,0:27652629987720455286211141065027268129
+sqr:6054103219841182396749,0:36652165796491372073556099894662392045769001
+sqr:956352502346019997280,0:914610108743494184401252227637651207398400
+sqr:-26892207599979464777,0:723190829600393285039943832095383659729
+sqr:764634776535170557034248,0:584666341486990214285762412733243291473444925504
+sqr:8999350031831592,0:80988300995427275943650249254464
+sqr:7641437781743263624,0:58391571372253409436905597502761613376
+sqr:27231085935730852312965,0:741532041239158628505821004397916290307091225
+sqr:54460324605443402457738,0:2965926956130264089583329153826508098876076644
+sqr:360110851757167625249,0:129679825553272757329435766523210102312001
+sqr:5646907739554115833792819,0:31887567019036174101601259024712393010835015966761
+sqr:8713094333529031952536,0:75918012864975725504514567963780052556831296
+sqr:6067775047370385059161755,0:36817894025490678648663816543505226751463254680025
+sqr:-39161602370641311011,0:1533631100236219150516980671952829842121
+sqr:7592562487471228106393,0:57647005126155282856061129287036732527470449
+sqr:-117854390966306661620,0:13889657470039065250071587891189181024400
+sqr:-5296482668083754900244441,0:28052728653311610979016516323012132263081551402481
+sqr:4890037916081745315,0:23912470820717098435617409376524449225
+sqr:878103465304676151,0:771065695780080592884753986988174801
+sqr:410286152523309284403,0:168334726952380209481013581654379939066409
+sqr:1320575015715850,0:1743918372132917474487941222500
+sqr:1130593146191972580760544,0:1278240862216263084092458499026711588345467175936
+sqr:9152293784326972307,0:83764481514630131881899390265544902249
+sqr:-30945617243677794421601,0:957631226592208454530069639810039434135403201
+sqr:637512608176985502983848,0:406422325584622643202173308977613669311348887104
+sqr:953752290145863389507,0:909643430958479183560202570458470797703049
+sqr:71232551174252547137921372,0:5074076346792507932127726514013453732491272854362384
+sqr:89641379812972941263,0:8035576974773672749927646579813248035169
+sqr:570533510213359628,0:325508486276377734955790890860298384
+sqr:156037452082545281465,0:24347686452412614795656577852136072546225
+sqr:820946717694830576249,0:673953513293915850368458978756517402910001
+sqr:897982009226057242719944960,0:806371688893666754984415476086593388617121385429401600
+sqr:30047225710589062348346,0:902835772903084382776376808801558904248935716
+sqr:91332956688159987977447,0:8341708977401308279373560739783999581780637809
+sqr:779547769133542092868254,0:607694724361082242143909923818285375848601008516
+sqr:70223199028646964984,0:4931297681816964046455576234794522120256
+sqr:-7130588717194686908,0:50845295453784170628102737064146600464
+sqr:7862855876206371917242,0:61824502529993072660297880196210138896886564
+sqr:99635166626419149819259,0:9927166428674308348042432184271252852367309081
+sqr:9143110466763720332929390,0:83596469007444295894790689042921258303578725772100
+sqr:624603802062355481979,0:390129909550750146243139974448833393756441
+sqr:57467188276773877127351,0:3302477728438176937336538778081989035872277201
+sqr:56666158509765775413,0:3211053520253900204952292290417155320569
+sqr:1669285813108053464947655816,0:2786515125843815201176904833798671100095144793598625856
+sqr:-3894381579633443035,0:15166207887788271015100954608590011225
+sqr:260571571745997869095,0:67897544002179714981985817184280756119025
+sqr:53560277137779384583336,0:2868703287075733025329170304306805830328888896
+sqr:532633647890554999729943,0:283698602865199724513575317928240776802930783249
+sqr:-8109683324597705697831,0:65766963625258096837076939441707642678104561
+sqr:71512764950951349786,0:5114075550930015809763806667815322245796
+sqr:-3230261313024043132,0:10434588150419815167286482704196369424
+sqr:3876597618180653484531214,0:15028009093283915659666843759569773575981340313796
+sqr:2022902748890635933130119,0:4092135531469291257986156298716581802948984954161
+sqr:-9239803654422657921335,0:85373971572282304128064994834647223048182225
+sqr:40891548247525081118,0:1672118718079671532749847110472480129924
+sqr:165164019691356860628567608,0:27279153400606916807248493439181759924278997826841664
+sqr:236044194969218596813550,0:55716861978666481928715444466626794213463602500
+sqr:-9327691800876445934166044473,0:87005834332137675107296063213991033162475616331013847729
+sqr:-1141008979009187167080443,0:1301901490179587721260801760634357975556433076249
+sqr:80240901025439711368171436,0:6438602197374411723371216408703542996140198286302096
+sqr:48396694980176876386,0:2342240085004277665404844769815924420996
+sqr:8287110859147430899223483,0:68676206391799270292835857144249638800252378651289
+sqr:979738309307210018577,0:959887154724150329311355128100080685104929
+sqr:79997549118990663707588,0:6399607865045323915139363453196300002368777744
+sqr:404720558142791950357,0:163798730183413039673176219498755952427449
+sqr:39783276700470626124196,0:1582709105026208988642497555015175748816646416
+sqr:68076977401073761586383174,0:4634474852066307646499543932220927310440054750314276
+sqr:8780946490021005951868,0:77105021260612224378649288336653880732689424
+sqr:2293326364302719333015,0:5259345813205928950683229209501046468990225
+sqr:-85950587462318432622522110756,0:7387503485117650543389782822459944191622287564105530891536
+sqr:-45213570780978740239083451,0:2044266982766574490551025400685924690824376542069401
+sqr:-252288475394454050742693,0:63649474816858046994487266873669024064892892249
+sqr:13343208905111714280686404,0:178041223885452552994753470810964520657769390451216
+sqr:2532670767542782527921078886,0:6414421216765747171902768427962647904467236158235000996
+sqr:90594811403510761816916775742,0:8207419853237683569360118704220290897994537812705119650564
+sqr:8205141011719296761924,0:67324339022197964842201619162042351536181776
+sqr:9720036859316498875611356,0:94479116546471347354649044496204860597822756158736
+sqr:283132666802141375993924892,0:80164107010492409231567496032871329019099690937211664
+sqr:35478297544662423863733,0:1258709596667599773811969774518746956152695289
+sqr:32285080416677631255843925,0:1042326417511341492231091561259042214939463959405625
+sqr:-34268147969999862649888,0:1174305965293805707432076575873585053266412544
+sqr:700904064615551520403894,0:491266507794601220883840126321977531400890363236
+sqr:911134642830965648237534581154,0:830166337366711341532911911675565532094507072828006211971716
+sqr:51391198660039915856968,0:2641055299715688443070254859801397489834153024
+sqr:66416349272456975065639625734,0:4411131450680996161120441843876023071544149766499595038756
+sqr:806758926584205263840,0:650859965623299098779505861978364011545600
+sqr:477799154735707308352114224,0:228292032266156375585779864239845871819082410743122176
+sqr:-1654950158079442331247637936451,0:2738860025727171161306644564106812249408719162131709514475401
+sqr:942376212580429636273132640938,0:888072926037435108264123633745578188505325516681766433519844
+sqr:-173744882442406814125820238,0:30187284174925763628296929994001889276434196290376644
+sqr:2808504238232363752504253,0:7887696056169149811385548240526285742328783088009
+sqr:807298846393541075908135,0:651731427388342229023346153451352474114959178225
+sqr:26937190640553605997330,0:725612239605528790179357561582679743967128900
+sqr:62574675969704339348702583,0:3915590072713493701996057357474786632808765390871889
+sqr:804162708867230857991464,0:646677662332682695199247623301634798792296863296
+sqr:-386730036170782490733,0:149560120876654733607852171916967230877289
+sqr:-434273419527492647189701,0:188593402908101632063112882554636374293080469401
+sqr:869166535411038930671123943286,0:755450466278428791412005047210119303561723595211750144477796
+sqr:10449922204455770677506,0:109200874079177753861811872396922278254380036
+sqr:-90720321424101605506013285,0:8230176719292308756103957083707087895694294596491225
+sqr:618017451906480640476197978670,0:381945570860979111437601753456109637509740412489393774968900
+sqr:600218595859234657114146,0:360262362815231263075003129475804047328873309316
+sqr:-1271084021549941372472074416151,0:1615654589839571823374561631341349734773214052728307529654801
+sqr:-1550867554578739621065776,0:2405190171845039917385273345455165995626118482176
+sqr:6043648591268889505332580,0:36525688294746432641148169772867559568256409456400
+sqr:4436117400241675705710942,0:19679137588726963606581585499912481843633658527364
+sqr:963653222408138267064741,0:928627533057588796323445139533613848091885397081
+sqr:79810459027918017737526,0:6369709370246980620783598883260816355828600676
+sqr:902803003175340266413761,0:815053262542413447161071151674614683772050165121
+sqr:41752360733446165868795969,0:1743259626815817253890642356111049015824205750648961
+sqr:18433679660798345484293758,0:339800545836930605431594748131416795001464037762564
+sqr:-8099616466845982700651861415703,0:65603786910002599981017618042158396492585415981482319374984209
+sqr:53861499928450854325903869409643,0:2901061174542511385668622771108001926502370466421638385341387449
+sqr:-9539042911647353522749973,0:90993339670249619985617080925599605810472271500729
+sqr:-9953723302036330682964697708913,0:99076607573501034335207891975711363757759935206913991279641569
+sqr:819405964225846194717255113,0:671426134208888733847054770271652175310634741124642769
+sqr:802401078039205223147440807946,0:643847490038478710635011163996163360107384995763769256738916
+sqr:519449268240923314088505,0:269827542276030702352860062200068431818973135025
+sqr:-4555091246368490325696260,0:20748856262742846629765230682011655772853777987600
+sqr:92030015548432048748093276815,0:8469523761844644646313223067398164807006285055804216544225
+sqr:69892106365908429041254342845691,0:4884906532263457551578632249701418592382287262507816195837267481
+sqr:910047959446947352191893618610,0:828187288493552732485135863553654427423698002303240138332100
+sqr:248378228391386474704886916939167,0:61691744338843742253916643321386052988120454926320117359978653889
+sqr:44668713115713790179611935799452,0:1995293931413941180740289260931549563994989167786466958363500304
+sqr:554146318830994817582767590433,0:307078142673942561571697027825775135058421635981084833127489
+sqr:913107312130554773072541881000511,0:833764963466286379835121944707623846292155777477098298802382261121
+sqr:81108023466385198143279886584,0:6578511470623691973244557720131367432321893163523903189056
+sqr:-4943833529340426042939004,0:24441489965830613211569173244841340595166064512016
+sqr:51140730159890637422105920403,0:2615374281286747861428645748709966547587341461263771682409
+sqr:-607843803842581788311388679398,0:369474089869819046801414956186873945785214116905230429642404
+sqr:122000635477119336893648,0:14884155056820949371250828570794377554062747904
+sqr:5316396721948668528754688,0:28264074105146548353074606970605680292688081977344
+sqr:3871007685189086282275603,0:14984700498792968128669630624162919017232049013609
+sqr:7594454675984973208305706419,0:57675741825590024399104214106984154178550700718617803561
+sqr:28214522979760017572876300,0:796059306975406100990301973660076181981455101690000
+sqr:-8758954355837792555434977,0:76719281407649839529729437792891939009581674990529
+sqr:192247354570382237619981,0:36959045339310268227417106552924468739370440361
+sqr:17921008488602803526064091292,0:321162545248573740358745190642913074581611098877710229264
+sqr:2786656582338594569854846808207651,0:7765454907891016297545581568122273298720717571197646453099134937801
+sqr:-8119878340729712848165819773762372,0:65932424268251514701015178259411842162406168492081516233544323066384
+sqr:-79010392379176306659400405,0:6242642103911401396317544499881175920416754114164025
+sqr:502548653639979591878843903680232,0:252555149275356173101979364004936274487595147326132901113707573824
+sqr:370095553656392383016573,0:136970718836231613385863745681913470927192664329
+sqr:3308233251214375641713788330957879,0:10944407244440438253289991279061494519953582690662512604421672178641
+sqr:-183583169171890388291350537,0:33702780003194925435879559331574763782761847410188369
+sqr:20022240072762280694432559381,0:400890097531327699316940227336660015830476888446091103161
+sqr:991600160459479600853539507705,0:983270878223265691657333328413726449497510327213293754367025
+sqr:-886802930484090401215003053,0:786419437515170472599024051267193209332214818799320809
+sqr:-4021243178549426619810076170246,0:16170396701030295777747606521080114147933679758148426375700516
+sqr:-437190641321459296906356238626351,0:191135656859068873243134481446335599971533230314698916447391575201
+sqr:4949096192729469662233605922109588,0:24493553124889331919611856555201632265117322697483182895572281529744
+sqr:-222922740889004859161836432272026,0:49694548405466398945671001441165552874782078359206058576462144676
+sqr:6633207453537081635390578639208521,0:43999441121659895022772886274234937490050952802629650017809319007441
+sqr:-388419057976394528897376766008911,0:150869364599269734301902942514512041010013259450627804723731405921
+sqr:1587145903911990027117983209,0:2519032120304607880066057705136945202936833323605937681
+sqr:9341556580305242597961446590124642,0:87264679343044178399059265004205078308505980101212849351757095628164
+sqr:-98589396724476958519746033,0:9719869146496308037624494359753950110951166819237089
+sqr:68949788143317567890727634506437,0:4754073285008375866022480396033956238363312230990817816594434969
+sqr:15348440724699030968793800,0:235574632679599714954032510452755198589426918440000
+sqr:19579760235445809588453948,0:383367010877544944929983398547473038485912916786704
+sqr:72079227800301785573175211637474,0:5195415080287797782151390372393575616172253417843110320401100676
+sqr:6817374173872891802717574,0:46476590626589093993102340500884140128371608445476
+sqr:27365680739830168291453603457,0:748880482354311826968810008262872424540584520070202350849
+sqr:267264590007941098022378239,0:71430361072112848614264522780315039578433629580741121
+sqr:6823763963460016478347085218,0:46563754629015553103873634993707652191220912556554107524
+sqr:8549091706180068110128584180,0:73086969000676828009663171737806902080553533491346272400
+sqr:-68363462105740373654914242951,0:4673562951083000043628088543159794818215387066081453188401
+sqr:63674293081366378395048823165,0:4054415599411742243170904564153062594260665424051440617225
+sqr:12314822493559883827822938851812,0:151654853047888474961995203087973689051788205242869652895683344
+sqr:360322042567152808702152365098795,0:129831974359765080636852128393794927791043507146551510810110452025
+sqr:2648892181207467563739706353,0:7016629787662055175845497345399540904332220966668560609
+sqr:1931728450461383908845059474429384,0:3731574806321939346389291168735723327873036035228210710552402619456
+sqr:358403207284545478566799458841,0:128452858991848873192347508921766736387368968538450453063281
+sqr:16923832563401191240604105408,0:286416108634038535732613208202327062603817395183974846464
+sqr:-60296919348805772314352496412720,0:3635718482956387921607376827103051300909552440589140468577798400
+sqr:137381863838359684196723188000,0:18873776511701600260921940211907923493005196696883344000000
+sqr:591213095515431378414779198676378,0:349532924308938586251105113436721993590864360832386253227175198884
+sqr:550075895507569886172410506205,0:302583490818454944080300856365310614939073667909864343502025
+sqr:711087936283568776727078639050747961,0:505646053128024768394217620639062509678773141734419309834385513545657521
+sqr:87137753047658080124389033343282625,0:7592988006194645030937734327894136192749543225796276656746210626890625
+sqr:892477052408611488403157406380218433,0:796515289075963457333727567531410316000818421665541198467895652792975489
+sqr:6158563241782182682620279504718154739,0:37927901203030667115475855586796884579475600717657459343120085141148158121
+sqr:163129498185919713569905746566,0:26611233178389983120491164583169402737995471084949820792356
+sqr:-840675253673606619740059054280,0:706734882139182840398643757541187982055463962461807986318400
+sqr:3156757217808506455275677523420556199,0:9965116132186102265018848181467495754138541196082820401622097670517327601
+sqr:993671209419443022612977747577,0:987382472429098591948836324268579783286641834412572329370929
+sqr:-9326822514499666899515267554736938,0:86989618216977889172048813242979601855371201795395107397962381615844
+sqr:-235676703573040466448512193799813867,0:55543508607054784964710322367602777661099488105005836599662883845493689
+sqr:9745324195976053070545476544,0:94971343684676305233934428420617617171065924820054183936
+sqr:42036349610817613966650109709956317,0:1767054688602886165196914277223620205192980370693225930615078048204489
+sqr:6423789221002494265324250049541,0:41265067955867832110408469297659891351326774859357340954310681
+sqr:39820799073224257724368475037593,0:1585696038830097902894340812101752876025276615089993162763233649
+sqr:-248685011975388562625272850484520,0:61844235181199152802863183501684240433880069673516902798759630400
+sqr:7810586566859132079040306752412919266,0:61005262518400323306681848115066990496722484937205544401071870384233978756
+sqr:148248035689146148163507965322876507,0:21977480085690350061040242660528838386718186881517058316005748772521049
+sqr:2174924777531088681854941082964503,0:4730297787918655595183218550423839198281245191521603201754758037009
+sqr:7460214282782494008461541364649578693,0:55654797145031921479620736345863324550380883977276538456407066982399588249
+sqr:910214324198168001046442701640701,0:828490115975527682261108829195991618894759199353089171357299771401
+sqr:-59899876223007500200643117496816827084,0:3587995171531619267909340862365356764690500898711702775194521329813155943056
+sqr:3693325822188682181380816692,0:13640655628845705229325716773595065057160551856905822864
+sqr:-377300624776321473819796906114622586,0:142355761456602529596293103174374647548147320880285674734176169221327396
+sqr:414831269398550325451238357295142,0:172084982070812635693442772673726339898901985136718231410496800164
+sqr:6560318055585225985879353052799903,0:43037772990437520228181479222553604645045752273627418993347756809409
+sqr:81752690538327392490210233502803189412,0:6683502410255525163317352014073423856877240881760773530410353274879548905744
+sqr:218839351597324273539262978455,0:47890661807537314072553854206046627823699636362157794187025
+sqr:-5805326576316957672801693030589753,0:33701816657691969378866024022901213186262873511166214639390988601009
+sqr:657052654171627411520319781527678957,0:431718190353980208506608543148088461575698759507192213967541915660607849
+sqr:850803172144816061232121227544210866,0:723866037731681512526641628957082234808088810211668969221470630672469956
+sqr:96750262807275012100488295035769,0:9360613353276782505243770907131423414773817247651756648989421361
+sqr:1302972096425652715773488728124955290,0:1697736284063860438660129973080040668130028649420585700653556064498984100
+sqr:362539128333737071068563296326856312,0:131434619572985877564322363931711449060712966012688612245083752694241344
+sqr:8647059398106102973445629549035094,0:74771636234375079831388808708994826778243955204442145247786443588836
+sqr:4801679506442312786805559965365951,0:23056126082588092523487649586475214155591493450499364174637350134401
+sqr:-77184374294092760219449891857411639,0:5957427635170607277431236668258878037311657775496943176517416692666321
+sqr:237675308690641513277997273186171423,0:56489552361191733248853882918288952408272576415112822843718756741844929
+sqr:-5002351530431559668603019491716529,0:25023520834010967237231458781580750346527800518094804987246891807841
+sqr:43664655191273703505834328260330,0:1906602112972825584894722514125938669910101850559285284251708900
+sqr:61437334296785487665781722675145481656,0:3774546045494974352232649823192447953130381594535380154723604664512232502336
+sqr:76999761286305362841208123728009,0:5928963238148010105553373748266081481905919994513298364211104081
+sqr:4045969265340624054820554440481625,0:16369867296080949138563301459618249171273665229809612664561962640625
+sqr:-90733797775896931157915560238405881,0:8232622058837358891226618551896739737707140965912018467654084095386161
+sqr:1250789450925599394334826479552697791,0:1564474250546762415577515695203307841292579604239130459928690626176279681
+sqr:5972484542109405765482619578501051194087,0:35670571605735798250313214826049005528483190382247035739054380369668008543763569
+sqr:65678344134099005094717808763640919760,0:4313644888197137191319800821202398871887873211187330220689626491898758457600
+sqr:-62990747469444164811979252597669258024,0:3967834266759286452973199215274493545160660868223522376653578082958688384576
+sqr:-53997255662311143749287788767141410,0:2915703619060992875399948731380693863707266595015584952708102936788100
+sqr:5686190404642301882852816915831698249955,0:32332761317846184821910191091058430280642996317973095727786765956628209657502025
+sqr:4318656996688968372478897431491494622189,0:18650798255050580180132125928030568680914499281769771597690822356558707851151721
+sqr:90772643431688731485119396638690,0:8239672795576503406798366498149929387564332199866630470404916100
+sqr:5194695663243172552311326817796924132,0:26984863033717424374763712982568150984157237537337208924447183760163953424
+sqr:663052304331426874021220834995676750,0:439638358279215120964420211896852784266488221371872739050191190490562500
+sqr:765274211863773061319130051954728,0:585644619343719017714207640892708560609108866025443392573761553984
+sqr:8793390746808666322341142829879636,0:77323720826060274427606858051544436111644164324015870268834247492496
+sqr:-1143404644203622436511911843731903,0:1307374180386412415102092423534367931853000575304412276790140001409
+sqr:1274715157279956414098609764282,0:1624898732199264017780108312111877512545271895107751602975524
+sqr:409119214024402199476926287393039,0:167378531283944613340338055007668151076742941392029630986865655521
+sqr:71377375780409892756507920763626830337332,0:5094729773297844747021699813855551310975623888825070108789795349920431748912878224
+sqr:16711505580703743734170498011402976914,0:279274418773892371081455883621263741224242040916240683397794226501216963396
+sqr:-74453371480687043335744644177229319766278,0:5543304524841182775798580739240538131276183842677571645900572414881617796545973284
+sqr:-6405878501504187329383105565378712287,0:41035279376033532548797887930856354109329109091108165640510577306324770369
+sqr:40950531000192473613267941356844194183,0:1676945989197724793333658733771064889173041987235658694162953328114611037489
+sqr:4307204533471560374295387513178008657555,0:18552010893157962052718908742109438219933838558835235689466967303594533258578025
+sqr:-149484891420637067740168061887375693,0:22345732763039653620332820862877954314918077499338875920118166527230249
+sqr:8343682513737833903327046937516169964,0:69617037890054498842921226973866568012575744383637684564661631967735761296
+sqr:3509188584470681541017936658877926984,0:12314404521379345637100883238194066833159131043160907804892714733235336256
+sqr:843579050130514060756624621185917,0:711625613819100354786465278348435375464052902370772400359479130889
+sqr:31410619716472975493735222400837838865,0:986627030972880827393632528272477830148142517559149626692979125963704488225
+sqr:99785546587226129843537244978723,0:9957155307711476328643044694094129659431472972828141076722710729
+sqr:87088383260454928172097866342477398,0:7584386498919886145615067404165620415719691675067902815356104140850404
+sqr:-21019572728823619340736653333183687,0:441822437702305615250281344482791728824090026904703796170591282913969
+sqr:-213022293683144585643783023194682847,0:45378497606027901635433606485223048786626898394552542573714372916025409
+sqr:821558964589159729952441643882176928965,0:674959132296812211087604639834230395153394804319126838028473912988118655971225
+sqr:93628576598887540441164941175327620645,0:8766310355933751549963656542407355813018943206504806465783388451037030216025
+sqr:808908479404403522256434597056244,0:654332928052344317344932524548899015475902513950134223950499387536
+sqr:2403686005394008280252761408349209,0:5777706412527004403350603444613906227812077284451715581174490925681
+sqr:98761522656704312056591131334972202427,0:9753838357470719156604333998408117019236907401667603138016126272795064690329
+sqr:264921969502430465410895298885047472157,0:70183649925046697616917925839949419303701946877664620425503463543495690232649
+sqr:5734044193381222850292161236386120,0:32879262811648918591058681843423942962076958921730666289037728654400
+sqr:-77343515936181223098604746930499746,0:5982019457370318819325847928980176284218772540166615080618809306064516
+sqr:477530086265353018187224199691826067746,0:228034983288595495261021696621307088152352747277191879096752478920892981520516
+sqr:6380429851450892850108602700855721,0:40709885089285662602074098891157189887680003507622857222825658429841
+sqr:1614017525491513292625779920457654198,0:2605052572593747761378509433651355353858519931761187647033655684947023204
+sqr:5843196999513910258932442804866747074,0:34142951175128363766762829236509048605085738725187936744829961482287561476
+sqr:-16840291081678306354388229172771403474441,0:283595403715653901461439541409615997910511102944454782045143368506083646540262481
+sqr:7474294456536468895568721815784039906712,0:55865077623011788920219279745354529689516076975872074869650077219876961662650944
+sqr:40025018325908445925732334410935532,0:1602002091989306935275241821685425175435487432655654492651387460123024
+sqr:71178821881382993600746091906288293726,0:5066424684421646444739284493107312862767524722848585207267121476784450963076
+sqr:-956534424185242867042536059215467741482912,0:914958104651394134287596545591933348101595618215576678952462132267362996716787999744
+sqr:721829962859255739884681107822513072001361,0:521038495281394520876802923408055786959896312734012309918355263586370064581985852321
+sqr:513339816745878383185851793188104945331,0:263517767456692000522339869140844051045940350138813491305250127423978498699561
+sqr:799894410213938707352908144028526318948,0:639831067491504852234204013807619439299774103064068517022995175896723023826704
+sqr:5059143920618658416911136512212276876813,0:25594937209532730337328341168912486221010349334531467986696362464941481577036969
+sqr:7379242107602262033739052700681405641112,0:54453214082610274166992064235604092051241247993780042359574422852539255744596544
+sqr:4599028230060805133113661583732548660414,0:21151060660896221947440972108717970222629954445507481380394996890598345890651396
+sqr:-610947584794355405122282058915720029,0:373256951366056087824599406569194476559334062938481114234422535511760841
+sqr:151016760305167557688524773300221125,0:22806061893068431731595439152646898640190980000204142970991973896265625
+sqr:-5043972380615273383773350465024144665722,0:25441657376409708308182401188063792057370329788793418956979339486342827121781284
+sqr:-1901326156132477111554066093388015224,0:3615041151993500730555701528108452476651988041641332535522955478055770176
+sqr:186173294979292913545567242624444046622,0:34660495763446811970285555836345743988397392804771376759698280409658509610884
+sqr:134444238155321083315064919179926948671901,0:18075253173164693407381472881519065043651038267940050028398999140418897027746953801
+sqr:182751469381748889650715918274290926706,0:33398099561188301891306676682175702712867585589145527684366524689236264010436
+sqr:-19782833113399238615456499401930538244,0:391360485992605412572841611431223918801790691677441123223853085111546603536
+sqr:-53439814746421546360134168635454563545302138,0:2855813800131853763301018844500573332922284544274015258314229885052800908865809707371044
+sqr:-942658818709448211511437874237821183862608,0:888605648490692349494488804835692227243472617418048028178845602724596399794620561664
+sqr:9834555863623710363291061910128791251884,0:96718489034735503589624960384782834610966324564239408703329883463441847933549456
+sqr:51449832652939146582734700068610837004647986,0:2647085280015443222139677978390743228846577502050643060932244409106773419670167773856196
+sqr:2291742184006479592618233849836236908475350,0:5252082237954788967476725027613349500538682695376657947018844871340710892661557622500
+sqr:35726042449731702718621910342910442871,0:1276350109120031602372605532253019950930377400791207831395379049985354722641
+sqr:314864095665797450690432494576559180549068,0:99139398739440448973186550472760318244168691761448570815799105906596791989955668624
+sqr:-59649935536675658576676397615555554,0:3558114809529561588382641776313422189329463523863391447026516060246916
+sqr:46149412421201088724138934931962583741,0:2129768266822109334168041249232625528680710162397761120741201681200437555081
+sqr:81505683246039956870662440686055779,0:6643176401403798520603430158045363639536746978811045511154051899296841
+sqr:-91299975424257598936582802453683157768592,0:8335685512470041532934583154336766995790602158310653976092333552449139600621662464
+sqr:574823126630437679349613040851854060,0:330421626909192191581312097609382416497762511199933655831540139538483600
+sqr:5848279024202366423130208101566693655407,0:34202367544925383191149561091505226508437583697212620809081729403292547660335649
+sqr:33303836250493780483071804093805232,0:1109145508999703631203582340229800796051766205357661302556477550573824
+sqr:-90097283028670050701146267779856415835245618,0:8117520409148276344113019232317307994477445330168474386622133497011544293514182388201924
+sqr:-14668385513233950758334444245442362205,0:215161533564851632997671384914831185622213282649650113792531204770412462025
+sqr:7590774137730042375112728223871690355920093,0:57619852010031268329372461592010579705963482263927747947299813304373576413452601128649
+sqr:343995691938696340599208107211356310244992,0:118333036072382474528342713640289708614178710132517265632044214980665310259061080064
+sqr:9070182305961666411059354831291359229936,0:82268207063380092355731635277150073589698333812886179476183173042500898918564096
+sqr:-613222418174165442752517769424869180677247339,0:376041734151371031903812645758550041032916828201133265381231649900288825614887998182580921
+sqr:581873090996018714406098523305834447403,0:338576294025261075090661404647983063923320691169652763323293680756298373444409
+sqr:820560888183185727159245513358928235617874576,0:673320171215978629926989442338497570791398876600290863949889599973315463411875711667179776
+sqr:-9626227543559910905998441385452600037,0:92664256720391476419210060982085791459697761624823914410791509283492401369
+sqr:66650014481401668085852877112449263254057605,0:4442224430371052066838460958811706436780164160347132176597571432339519948135496658336025
+sqr:7315583918748836072386922803226766220,0:53517768072256576981304868128894291620776130258551034531987652238533088400
+sqr:70529223458010474926294230806646675385113866,0:4974371361589975054598623878560502789346907784009727387771830847443624158903789785465956
+sqr:401470286946091912268711270125222133422,0:161178391300577378096702751397459234166566519344188262751550714578757169430084
+sqr:4572343757129188862013232461765111042143389,0:20906327433358266822416965557951167365266138697665588057103694409510400778423236405321
+sqr:715210017519130849476306967366881834101790443,0:511525369159715456627844733333364085544303094139050148620796444543726446833386218286136249
+sqr:4527199826692724171566735731879658501804396281,0:20495538270806631774445707083379965566022585863396771217697173872449187877155922938886630961
+sqr:35406064719217317374472447210630089246913,0:1253589418901405255011316475685007527140454016052775693446831108384535391480029569
+sqr:2644657831335048513698968865262623996785,0:6994215044841801912150035078815852976779574670478382280388121561737327690336225
+sqr:228843981090068751940043109460476113233,0:52369567681151744523434257037145251209496783558582439385608973652170637712289
+sqr:-363455548653099175486553836897754887953239,0:132099935846725341876165715863568689720197347788826724804411086993540711366650591121
+sqr:49645456723940808192361707189216800740740233,0:2464671373328679603526959106904136209915438913265444195194837009476455587724892784894289
+sqr:-41972159081040399279897402054342460893529,0:1761662137924162054566224840868772179586183621899204603865834479280728681074073841
+sqr:904449444989445227486671780903374927026028972,0:818028798541715508716549477493246211642182516309001046520574799048903490361447595383376784
+sqr:-4637800501264787734476081456234817427937,0:21509193489531916376293763644814267498077828503138957431543983297006948188075969
+sqr:2819020042629861965107669573484320344278,0:7946874000748868771060776526221076809798728593879130631101816702469560447341284
+sqr:-1419073712851139608844222498035130011907978763,0:2013770202505118633030036333824745381599233534572616361640971080598274677688338220059010169
+sqr:1279435386592185332336335306072373865346150,0:1636954908464294734873238356134567494583629002794863673644038288728942651859319822500
+sqr:7540143721140140666472157286788379305,0:56853767335449087373733223381002849374201673267193998122596274388552283025
+sqr:-5262011646580039205673608048505741906619582985,0:27688766568743975427118675132271563800332472067380214865377259872310937555902021895301510225
+sqr:-7327313385175641658893891579493621423472131,0:53689521444574121181384482122663805719648236391922401719821519793880350881347733681161
+sqr:5706335860903446254669972577013696202625,0:32562268957432675122028129097936933650790091200861535522835758415216345056890625
+sqr:60764795039857320711933375802630887834931,0:3692360316235868846208377282943565982855715966661963445194081550939587924703774761
+sqr:6600882114332387632455874953453879300978,0:43571644687313212152096063287158210620222118112302362027400043627924277911756484
+sqr:-2251822567054969085004683861579459385511998,0:5070704873498030741204798440716913976082340904309541108933200404386498317664601952004
+sqr:2529814352175492857421615283607797166745474847,0:6399960656473108602788181861993114613603433429900229071740736287078399957217499951509673409
+sqr:8879583655989939149712696359705781351087498,0:78847005903723654012446892603376809645393741694579508469156852345582458114307251900004
+sqr:3351414487201377754699699738698168276843,0:11231979065023273817960765077734203806947341396425672066505356077057923890046649
+sqr:493311088492211553497370970192138517368154,0:243355830029370578206188770286494126657338190622766247718762414035192416310773367716
+sqr:82685877720710523061992100323174276509125450,0:6836954374444292844442742416877544049404896861094638922225024615086673653057123837702500
+sqr:647294863666837620786899669173664903756583190,0:418990640529469902225676759601758499930370634181067199099319436360711522177979263390576100
+sqr:216273949195441394151753549195148053993499942,0:46774421100592365260727829266381968975002672686299927792795537237038284660867986754003364
+sqr:3950961225764940372370426740411682156774744080,0:15610094607498000126930368549421600598238504973066689872189952445984103363005501349495046400
+sqr:-64567592264420980155379737156740169852286,0:4168973970824515995743765693939003440464366784937500483094535902887465079059425796
+sqr:-5393776308108858222846593366287251097190,0:29092822861916424670653729347861600362879624868296884894957063675916858825896100
+sqr:4421257035474409230652669129710743041139129999,0:19547513773731961522209166180650357790395010294343310626102311499057900780186531074621740001
+sqr:25745585348235541052001355061838556004714,0:662835164923280565618572665499610627882266313568159091349035783688149905990221796
+sqr:3022361477414863092264903791427345647050163,0:9134668900161353985753195181966102732074420111230027247692488593788588488383438326569
+sqr:16174126083338739712392546466600144029545,0:261602354559738560524227152873205540857880607788363443574217951532138509832907025
+sqr:8536359038962118971924046789322102135506936,0:72869425642070271408155883035265401649238199527773293064559915981755136561073704108096
+sqr:16829452309909947550920920604869233567741,0:283230465051533269305657969245471380416496809799098078990297800266415747635843081
+sqr:355623225691640883087356495814808440781511,0:126467878651327748249114458690580697745795910662947600858514518696687118116439443121
+sqr:-4209401143443034381092730841013060610254,0:17719057986419525309516357045133676283967190690277715809293823866768206889944516
+sqr:918167948787358412274755629955529806721807808,0:843032382180385220097634047295256324836379578514035039013396468142117850016057007689764864
+sqr:938573266314205341044186153980377755729062621,0:880919776239716222375696294047377432376471646919887673869340040964527602792324015339389641
+sqr:-337834833138283209912173119871827704113293618,0:114132374481571659273888147381589921838671732890472824055868207447165729730421587879529924
+sqr:3347677785850637302491730901579246582150171,0:11206946557877825427011369191220138899303204964536294325376558809200796800953595329241
+sqr:4356645141393535940709418390025017847118962,0:18980356888027902768955973980307120610625051788598446346637986213696827755243779957444
+sqr:92826772426011694027779601747722647943499793413,0:8616809679030564963186880963791809918932126468805307429201291100830072265634908592373678188569
+sqr:51010376762258960953864569830757574823681474404,0:2602058537427608996290624274755631383147159000024273704429828958236707279671443068347307155216
+sqr:30382831063227602873284055143189355113414,0:923116423416628149265937489922124060523986868896196859513517045335380028802735396
+sqr:3915054492997401943585003235342851158415,0:15327651683139143984118805637794267152206819518847446899400091861876507425312225
+sqr:-4641090311724785696843174695620414415792,0:21539719281585668471865797038997005291814557178275054719466959614202528658987264
+sqr:-39951447861070793408634234428218891908517431,0:1596118186195858073668911179663982468054349199578643473088622372024243339381964430839761
+sqr:-555198960224555495005823246552894089948692,0:308245885434427554629461691197291076483738765823061906226206596488656320063192510864
+sqr:58589016716833637943477313441669085819261,0:3432672879845411479467663313022248204450828930033468407431125219807738163558586121
+sqr:81263647890474008516998822691088790271345139919,0:6603780468466940774544731497500550809853395908650543188970162129807619747633000977661687326561
+sqr:5560457512376932639583447838381337320337229849,0:30918687746949065998721620382358683435170457483405007324210641546498211977797053331056562801
+sqr:432730426644912729122981083168165400551009,0:187255622144288196428332849203454859775636894202341850981185369067975298080810918081
+sqr:165634868693456077262813338073145431993831748,0:27434909727098436123329108213498577822229788099353666621117280426073913085588319332735504
+sqr:5136036432296350718059822910992767783245508,0:26378870233875426793297045400748869895784309008118709948631066937426759954797802178064
+sqr:52495461812056415175919972939040513752659169,0:2755773510861073404770251585451023468741709259421767644302188340904609910323218679770561
+sqr:644921741309901067265662755007058628663417209308,0:415924052414194952773497338448414267721637881779193538991963654588957862098729012454014681838864
+sqr:77219986751846279294740383367169789369471081163,0:5962926353955314887856712243839730087619098814350842401405209118435169818950049029756133432569
+sqr:-406564763021417498306152266546407011266123,0:165294906530661369246246104614399625280534743301156579253890792930213067047527451129
+sqr:77332635435051704171741918986869908321498,0:5980336503330614478952575573159205861850436194935556182332670256809867467728964004
+sqr:-30133226652964637636178317676292739183072833,0:908011348518938418160952049024705846190373876758216571799570644467898365634836182645889
+sqr:843353980371530518867911928059756715267687917567,0:711245936208503883695472164087598868479574150979252250593440597707343604621646246021356987199489
+sqr:52416664036135192338300928811249602187501,0:2747506668677068472049940358100381783185000537820108447834753651234627284360625001
+sqr:24936864359653987871165102360085320772025101390,0:621847204091781294552778349831227902040956037620708005774854493451595520123946776239779932100
+sqr:2505909981582499443571901125584999220379619248,0:6279584835794802700486852245258742443988754052584342546884836165850470328098083893452085504
+sqr:-73977703479204885730664268429435963708518,0:5472700612057162655101360993309179348039302715439935757192986595911588767665756324
+sqr:-198589249704105435037679342682866043073186,0:39437690098039540617666518382007710264897977029189581552408645429654317451352190596
+sqr:73328039448018528864208189941878255640285587838,0:5377001369290161515275169918004259959150861969199997507466059992543980522974959373053213514244
+sqr:535683488298987839878819855712326543532053,0:286956799636171841961137163658674435700232958301938352313323115244951797648638394809
+sqr:184063216702015429721557935438113110817744644,0:33879267742693091845169539821262585008285349159029510408323623234301679006071982790686736
+sqr:9676294432856266922797489910606089116869045937198,0:93630673951325184339475444014224838280508945273159278657409367399182897368794695514896350160091204
+sqr:-2663749195133384508359036407296314458167292120970,0:7095559774573753778551499428892681382031491295323466926688594859703932221913778622258641113740900
+sqr:56186493557755840121940359083662314213584866639,0:3156922058315738524532619454274852899939633083172653727996908969426171204418780549199415156321
+sqr:144196799982597573891264558388418615203807,0:20792717125221251686070638980516239709909762281452172068877272181455090376147293249
+sqr:450542969038187905714211262451476459135879207294,0:202988966949745545842203931499090333856324212634176893780523587535885897796107342866845822802436
+sqr:467808110665735390128574258585344541690288818,0:218844428404644929675525571476567575876982168069310375514724173646708352135783728255837124
+sqr:43329024140220466727250156222903487498123397,0:1877404332943807955894226235179737256169220753410657867280549089825917543297596638819609
+sqr:-6438501793677256617789281924089504319534108161,0:41454305347185250745373491255204904408762383595512409623526297043091627263730566245646801921
+sqr:-510407326611660928505767463487707749496052517369,0:260515639058862714248740984693664668973511630313643512343292186231469444203704884750122046682161
+sqr:594859310867495622564465375741063919562317268,0:353857599725751795685985263032949412484008176182571404388603629978255638007107293890983824
+sqr:472755285423104075830726552388870346265278901544,0:223497559895480601087050545047908867496351886554740936596802968200467105106203324052391245583936
+sqr:919376689556435886927444595022970417850392,0:845253497299751088037885686267060750171668735078243780695626798158701607430094553664
+sqr:-57876848300975619887354759108579447562241954,0:3349729569254144498438740796585193942967339615854670325521241615639822207154890837738116
+sqr:92443624150723929520372770653993712765851558123728,0:8545823646120308559485384430414356108540247254855261339713154331207835436289869077213927151756617984
+sqr:6356695791313384685269608982290373651589003464257,0:40407581383301297900732576196843555338795405220256471898087562078412738286830831265520747076562049
+sqr:307127491594185711277517789087998032847443,0:94327296092936614738485546027297758808557937399435107006033165112073657182511638249
+sqr:17428956723465902727803305936369912233011708,0:303768532468447295689240001394414945439324062976254537841546907447929084153848065077264
+sqr:72297817711860917755762192038277545133731492273,0:5226974445897470229462257539080517594348715584296818355233250622811936276677931595563458706529
+sqr:67252278294589637192130214244481638653946844,0:4522868935812932439511615502129787436243727493914417949589485803608267599747418777560336
+sqr:233519289964558213430232864885327053119123532000,0:54531258785551418329049006520631935794109261573329320368381923668902676071212807876155024000000
+sqr:-563139419418908049216270219501394613917054555130,0:317126005703464832075631587212216737604993581567807889138062714550857544319576086464682209316900
+sqr:387346925081870204031788982970764929245794451,0:150037640370379968568374859913413077524950740578939448357312222610670070607632870142391401
+sqr:6548128948957570787901878097677042348848668836243860,0:42877992732176180696955854123775448728390486486456039969161855812399796757319019743578067660753387699600
+sqr:3936261343830022028126989725444688680102839,0:15494153366930530895998393269628264395230650631049274762266477014870155078335615859921
+sqr:-6668751893614929632721278392171875150277412,0:44472251818592709753921778491551103916600149753115944646208009229845890958300557417744
+sqr:822791736100600708215338516228167925437093404964,0:676986240995440558720776181683504597370626325184035707987923521578936602522691804063023299841296
+sqr:2255604311982997704851854524113475159961890,0:5087750812236292443500181849614429747419680925075316427764315940109096523306252372100
+sqr:52999724285024877184966735916574085712319285570070,0:2808970774288655729113448519823998478249246548895966709777902921010943548779991866954934924879804900
+sqr:8675455794622195828232781164728362446211729095767700,0:75263533244443835242476547921223757363355239874534465194829970026093679319415889649583007878052363290000
+sqr:9766818189510276491458799796620669154596997230,0:95390737546948795157658200093224007046731125703431784850732659642141281407725292532627672900
+sqr:-9024401376963549724600495802510085357805727790,0:81439820212541612297986698812686168419623022133807410031655461931147272504463139331578284100
+sqr:-164402463040098189805763808555384663595781727680,0:27028169853650851333425988271230481834028482476783289514442582861911248333185010717365678182400
+sqr:8209632913178182128605357625511278362817287,0:67398072569138485304045634372020174804374820709272995681812799898811875361955746040369
+sqr:7849224085998259155678225291216074629306321405059,0:61610318752215206841639102273634107076695214340061949813699902301891202503337597099419319950793481
+sqr:84268602084300522449759528578955949436191540691506,0:7101197297242178356528279504357739226784541729116446371397131837835040302245005109217734596660548036
+sqr:6902994314778717651425565958771304030675588082954,0:47651330509867297636610632795902289548938744057689235679157410009315813482325208267069460785366116
+sqr:50206220922066168700530370919092488455057426610,0:2520664619275314690877903300166053204159444860750414396463078163212160418801872872915536092100
+sqr:96072567275642889243275576425042150057804998,0:9229938182932928965775346621497651355565875548926029234561161694019317264672817793780004
+sqr:-6595062761346074146596020647362793948252580229123,0:43494852826093704554640308679361114439497638530221613744048447331967293266246352267351827177349129
+sqr:8568149081811385177067925203516520860649420,0:73413178688145282880121477119739180696541954507523244741188166930150537554224146336400
+sqr:49248502660946919517092747877001926974328533013,0:2425415014345295812313592875146328669679484501975145885494533043030190389627256319264630858169
+sqr:17904856181876925295665552266562559466201268258,0:320583874893696347362514229991660521224017219129814545000338054375384201139526969367678354564
+sqr:771631948578145161796849085547411200917340758349,0:595415864066505259182407508395039909989724181602136362998216709114978732844986284528318413205801
+sqr:12382670011838180563176688905711438881735913656016,0:153330516622076566768604699870546073103022701784337888662872589882573674742398852825302835572992256
+sqr:79887086905840845071329751273276580577004634220257,0:6381946654301367805599628548194540727819498426580860632249477255744128432673947273772575390389146049
+sqr:-30740506384917649516095908074870705315727017255,0:944978732801162777072483626498071187718358606407147765800812805176218918541578974739067735025
+sqr:2367793261905004127519128277205938124388123643062,0:5606444931122739470452985637552178996115400052104533840285616956995976414363107753679718780735844
+sqr:-7205537163239928136782948117253088856431489639087,0:51919765810831710781135325357956163524444034169223786198198403577770151672808946737583429518193569
+sqr:-87222501875881575403280138643647476695025770484971921,0:7607764833488164940156888723183272524826225411571931628845909517856498792285963403271657878006104158430241
+sqr:768592553397196739913804827364926053433680074,0:590734513137622721905021754614420272988265613837215107708841948464515520527214250584645476
+sqr:72654430008231434800757497564201500782485093291413,0:5278666199821000407130155626386018512614357611234992080780160725379258284115224662271305897739536569
+sqr:5294979779912456291593332485003094781099145296,0:28036810869681764068248622882698671835224328885732252901436697669373532746966430141718927616
+sqr:-225524330077841338311518714864637992502982300827,0:50861223457059131344076452854745359154811942946783092141124606168363630406185633713222724883929
+sqr:76300515665590045878902542341914483141905465924,0:5821768690834952001877892404074353487780621638858283497181488390792314668694315843107525173776
+sqr:1367671021590108635537147568793462718551758852,0:1870524023297331401480243199414359851331324615117918733772848624680091553081397302760357904
+sqr:510148602546875823515395311882287764490427522201,0:260251596680530277967028454013847983210561613833634354975554290871003699196080451660212347884401
+sqr:-431885828352074513804191534183233827345066984060724,0:186525368731357569947997844493090345640360420960321598190276095427440182661892141310259951076519404176
+sqr:-809483217718253905386013436699549868896275873002,0:655263079767498053425256239691815322385021649460858579931313119375600071847578167997497232492004
+sqr:7093947060113745921407567380188169090451326617,0:50324084891696458689525345491512385227204357117921476509864826534231186457831032775212664689
+sqr:-68080232880306501903664558878954222691596262631984,0:4634918109036766536359386931180300421938059628159541879284111014923670444055728559424188487019776256
+sqr:123732084807188820529492594422304230836960515452,0:15309628810733366542785996328670362388267452693830627108998185467309957713222828345677530764304
+sqr:7540117648567179857455046065990308358027888235,0:56853374154234257609895527408355719669136623351747723531173678837172982618421514013651415225
+sqr:-45060593639989118987524402495961714937398249804074054,0:2030457099188227839836890779305097649691764560779479754889468083163520905704358745278334218397976315994916
+sqr:632053029293918960044415400816420531501630472353905348,0:399491031839619579039593812314125996580654591892869493458792928066176249648663979069801773646377507343001104
+sqr:3817746132424122174583264307874535849181410143,0:14575185531639343007201251665616569687900232059519506674273338124182781949884342453983280449
+sqr:-601998309194629269720110854571071245260480241599,0:362401964273192463544703828120443279897492192836031400769571647881320007895533397773473410076801
+sqr:149189674784531010082775561427484020603730152224437164,0:22257559062314127889768903830566720975053523644513943276233173866428033619416786913180630322709896584362896
+sqr:-667952680634617065225948909891271695652859024779524,0:446160783566970739385553579285903168560292605633974252482379900185517391327443619782431132256809666576
+sqr:896442187023978024135817888181355581875489698966,0:803608594676332793793077691071489566065573314613637479558689073204033255413470271487577301469156
+sqr:469876837063508044888529054004029741634188262,0:220784242008806487516585370721594781809415657049495909138954715803166606284395035658580644
+sqr:333460505499634389071621746836449438345651158948851902,0:111195908728071696640013460481101860680028270768188479169081462544951631246428196028946634293924963929017604
+sqr:2786546981347699152350591332346527753272696601615332,0:7764844079257974407678493361975288835463281192151603359405015138569536085295805773150543091151697470224
+sqr:-73071180676220826524286202896313207937408377936310398,0:5339397445416907926684389231894822147916634835106530498340816561362917793316088182837322991485253402918404
+sqr:97268643839279074792000245431060117711471587597076511,0:9461189074332523111016107641208277216000335342535735276099162974736485081225309337128089039686273987933121
+sqr:5373770600769362045085178646946336003315453933096,0:28877410469693110277861132973833648845693365290082720947082539067604050573484907294481735644145216
+sqr:7730022208425583302760731266174266674824479287,0:59753243342752732027570001943282813441979961478227838695136173133534955486934528970692028369
+sqr:186015250092269625466554459097460746814672772260764,0:34601673266889614905648672478996105551510265225901936707632047204975658817888057802926645503613863696
+sqr:4815666699948553139200366699245624686477868625356,0:23190645764993388131257987862178276692328734350163125333215390017611850098020996699531633086126736
+sqr:17081969233179688351760402283975114660908394799,0:291793672883297470081631634308890045217155311366254116499612450017968346005970487790850250401
+sqr:-43332131748563083907399274032132960698499791186721,0:1877673641874828787625525012286653311094511677166880415689214828901799869432475136212839985486731841
+sqr:1898554232540005594761509086534555991176474523590966619,0:3604508173895569638767886256267002152378977439165342675620569566281281336502387804811587491743137018772291161
+sqr:-6445244173897779327967913685216339870247860278566770826,0:41541172461163267894256110942941660309957282870559131430664069420103268562436340311324462473310528425204722276
+sqr:65847514811614176821263497363221055127791917392687769,0:4335895206865748400390819297884493082375490967259923170455114945080901924156961634452124720130029922197361
+sqr:-28264343742850718502716299981680971000837535755872043920,0:798873127214024562941629848748102397995321372847598546364602780290618822199779680422856795951621179798408966400
+sqr:-282181133469986333088832466973840605999043481716,0:79626192086406241151931423646013826941082487042406305406535152992700626621319634719227626304656
+sqr:-434247247729195929964308594117079054346013291477644823,0:188570672160381659752938334784076794251905170787774464494097399065847591192000757928868479498829562938701329
+sqr:9240816951257803833721612536356214330313434983018109831,0:85392697926653572474441387898710779160646698736295404941246735442747843749195839063211719258143563711978848561
+sqr:-553437984914283832199711793939722097864052715723678494,0:306293603145983058628720487059837183281755876058747737586115542682024534807946633420427796579332982678108036
+sqr:6047211011673838976527797824201388483565752195,0:36568761019709335078453798066472987505683172242522836648346989500201360601930015916147318025
+sqr:8955137550631297248650463364979038566397939600995033172,0:80194488550726709893601438825399931426591990165490900865830781031863248149485356041714708909894913413380381584
+sqr:790779058506749058766189248617038335165057845224,0:625331519372820450923822161102637479423295357609393493544855157664620164122653416349989939610176
+sqr:924579527319299462598706457157008969788011018317012,0:854847302337979221303684560755968979733480484179132343486688206396061271407117703550270221776928608144
+sqr:8261040079039720082284754517273813743276045370542446932,0:68244783187500584624392647600687253970401912865126265782976546569564017937607883404257489780392858354036212624
+sqr:81648112117151901296706874493743067927111503972,0:6666414212295007129897504217103504480128611223900886718005747056017651759771665045223771776784
+sqr:7899564578684868309378186947806084222206879072463,0:62403120532812640959186386238692291461262959507356112939970796721050816677313636908195151204886369
+sqr:202875148688606841162017225883717133105073395273,0:41158325955424334103292855054548709570644287446922395354404946376369163111503043012196098744529
+sqr:-447599944273190621944023321274152349834427894265443,0:200345710113363350241573135392171477512633083999735087675041776698945249056665566679475323004543986249
+sqr:279448269247759221729545915827816901286962304397091,0:78091335185568132343602216620236567337871190952067796247538287572338846008514454214870712673009262281
+sqr:263048068751475889817576462013638717456577558094,0:69194286473881186494904734527044427456680242987310636245194242896044320271253317351079944912836
+sqr:4953918586547460893294750792007989508019383275031399,0:24541309362140392785101770879220285481237618136650376029112407574731123149898250836474326855904435897201
+sqr:4471437353356145807877658377771700534452125783017614265,0:19993752004988613946043886485552363304372507758161087249440003657966157279048035653082325835710499252331490225
+sqr:-72098170677932326230814230626869993207419376557699079862,0:5198146215104260669761646225033691215158769193995972929447181676171580708713242869981328524528675902921453939044
+sqr:298429988994779695408244160373799551781709296663708,0:89060458331424330116238562159365179356263870750077166569310858891659319712469121280685043299644309264
+sqr:15631841203855394599569166381728452039734506241667,0:244354459422551272302469662109502580403312226387630490060815637724042398254594605237073781406938889
+sqr:660426807315003637221713949061982205086603339679753,0:436163567820288941746673080355640275297800545472250496547078441144692622864124308034416680452598141009
+sqr:917392439916950305180360768242753564177817712397351776809,0:841608888816775275663208862326623620567046837893704481168518555441621791638059053430461906332510516549269350222481
+sqr:-155846450238268495344369959195559500580543629842832,0:24288116051869098349295047128215656778566742131145679653985424636366108865305515159091137545021780224
+sqr:25472033362764858072900019697941213135876145681845377,0:648824483633806003744793667544511819270248356569452159505562928008016765090401968998670090576448136272129
+sqr:20189277289260360026888777803572924468097073267041778216,0:407606917462644151076725849420885819139012157714254702542998040670975149459822767551525742560834848763332142656
+sqr:325204287745187960673217120597871887240330145314572,0:105757828767855008418740324132756067538697480557296437838517344014269355767453319221651293844835543184
+sqr:-6414722934234222900958263644266120836831440017886,0:41148670322990518384944829118717910442843247950185748761142292129209592995146647048734271999908996
+sqr:312301120272909624627968726242736198455177785970818842,0:97531989723714362934668096275738607603861443157722482847186557044333833343486010148981998218139163982220964
+sqr:9028894954680171974419101406148453477562571298124980366,0:81520944102649064731832317449161331094564889092209138390941931719546194698076589489252890701465890227885493956
+sqr:788806307332790616113150948641884167876975922667808167,0:622215390487992922911688182036473235781447944210433463649952255548713919326836326920237228393877695911899889
+sqr:8462072534820037419699255083511733952413272276484107788809,0:71606671584555613408851055334596052520163369900719944476255980385358955582796459794726778717991205869753539345638481
+sqr:-685942527221288609261737584619270624284127458641912,0:470517150650728264715592414998231622951986855228964433454490078408056889339366486340487414051443015744
+sqr:370058929694186697058774342888571633336040599274254758,0:136943611446407012761130137137417712864012148304763406301401028969847631099408086708759895389055756285638564
+sqr:9704187879914430313664077393665195769441512689418966870566,0:94171262408678125773934398641195191307284789234258975677909176503419014249751224545097316770934552462579867397160356
+sqr:5925798128737745925759715663331423546607679889144875112930,0:35115083462551771236157369162138315687265847656064728641830503311468988183199467328159949805669318527886480253184900
+sqr:33488647002377175259885536134537076443400396426003731,0:1121489478049825766276530922246725189111830952465458275864281151986139799264328218398374227234130825920361
+sqr:2123735232819297700815836330311374814786388785356210060,0:4510251339118036610109622239017828107705345092062097267522409602229318236281318584088873097703239806845203600
+sqr:29872141162702890384989735017623770258183788742075,0:892344817644448391848145835628174663828417858780217507228848289828118687946707014712413510875305625
+sqr:7532139657883258576470960593627865781553593844952,0:56733127825857731552224724505206926449807777229886757388281330093349393178013626920192739015882304
+sqr:845457525713874120263223171268947077567681659698840902652,0:714798427786226119268210281388981030688454506537030966614579539102544522728409887855024503885468326555462140633104
+sqr:521768158545019160169259844676904044401662888508547040917,0:272242011271460250849489239712473973544134037328971616162419516920558472338192391022931027231772869417436872200889
+sqr:8452712498170643941637436558664265704301557216577944354047371344426782440907597751590676094202515006314790319892114058862117560952042968596008623655407033230534186943984081346699704282822823056848387726531379014466368452684024987821414350380272583623832617294363807973375,=1:71448348576730208360402604523024658663907311448489024669693316988935593287322878666163481950176220037593478347105937422686501991894419788796088422137966026262523598150372719976137911322484446114613284904383977643176193557817897027023063420124852033989626806764509137929897881780377071828193979369536094745977623512725964279515528917451111552087757216338484610394583686853163069435510427134801022221259480105632478261997058761512146362996413333996057383868504433356414886358698618132135318758644287722813462338791398132036589335991224708890625
diff --git a/polly/lib/External/isl/imath/tests/sub.t b/polly/lib/External/isl/imath/tests/sub.t
new file mode 100644
index 00000000000..ef5f97a061b
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/sub.t
@@ -0,0 +1,849 @@
+# Subtraction tests
+
+sub:0,0,0:0
+sub:0,0,=1:0
+sub:1,=1,=1:0
+sub:1,-1,0:2
+sub:1,-1,=2:2
+sub:1,-1,=1:2
+sub:-1,1,0:-2
+sub:-1,1,=1:-2
+
+sub:103427990038,909510006269847,0:-909406578279809
+sub:128593002,-9007199254740992,0:9007199383333994
+sub:-65537,70000,0:-135537
+sub:-1000000,-6543210,0:5543210
+sub:#x29C932F25E6CEF8046FA,#x29C932F25E6CEF8046FA,0:0
+sub:#x800000001,2,0:#x7FFFFFFFF
+sub:95031018,=1,=1:0
+sub:#x-176E7F8018D6BA4B550AB36AAAFDC78A9,#x186DAD2485A41B18AAF5EF17922D7E5F1F,=1:#x-19E4951C873186BD60469A4E3CDD5AD7C8
+sub:-628443782411312,-301652218193016,=2:-326791564218296
+sub:950147,37133897,0:-36183750
+sub:649972385,297,0:649972088
+sub:505,9,0:496
+sub:33,-2638,0:2671
+sub:-5,71542573,0:-71542578
+sub:4,475357,0:-475353
+sub:5,775166,0:-775161
+sub:0,20805741,0:-20805741
+sub:1,39,0:-38
+sub:76825770,751287444,0:-674461674
+sub:-5846049,574445,0:-6420494
+sub:501105944,54475,0:501051469
+sub:84350933,594,0:84350339
+sub:1367,-96716998,0:96718365
+sub:49879,-426695,0:476574
+sub:4,2,0:2
+sub:710883222,2440893,0:708442329
+sub:-68,2096377330,0:-2096377398
+sub:-87838,-485655,0:397817
+sub:4683739592,822,0:4683738770
+sub:2849496,766332,0:2083164
+sub:60422837,52,0:60422785
+sub:-13318,250,0:-13568
+sub:1,2001827,0:-2001826
+sub:97481748,62763650,0:34718098
+sub:1643,636255899,0:-636254256
+sub:-400522,-40393280,0:39992758
+sub:45568099,22,0:45568077
+sub:645024401,860182184,0:-215157783
+sub:37244191,-976205,0:38220396
+sub:-27,359887,0:-359914
+sub:27528,8076231,0:-8048703
+sub:7298,58548352177,0:-58548344879
+sub:71847293055,573,0:71847292482
+sub:673824473,27805877,0:646018596
+sub:449,53709067,0:-53708618
+sub:40569,6538078687,0:-6538038118
+sub:-642338,9669221067,0:-9669863405
+sub:209745,-28,0:209773
+sub:2488518646,-1846396,0:2490365042
+sub:581,539581676,0:-539581095
+sub:-86,16372077246,0:-16372077332
+sub:82972869,96,0:82972773
+sub:81666,-224,0:81890
+sub:3353174666,6467525,0:3346707141
+sub:178,76264272942,0:-76264272764
+sub:67786255,18533457,0:49252798
+sub:-59339460,8103,0:-59347563
+sub:427117459,-6532,0:427123991
+sub:-514830072898,10894,0:-514830083792
+sub:4160587,946181096,0:-942020509
+sub:76936,1066849,0:-989913
+sub:-776709551,28397881,0:-805107432
+sub:917,6034390,0:-6033473
+sub:5528,-1297,0:6825
+sub:303,37728739196,0:-37728738893
+sub:920355,13059,0:907296
+sub:55576,-56300,0:111876
+sub:-85278759,67364939177,0:-67450217936
+sub:50472201146,-89468966856,0:139941168002
+sub:7257002442515,-4541182637,0:7261543625152
+sub:56005,-57203,0:113208
+sub:1508,8778323669,0:-8778322161
+sub:7477,1777344,0:-1769867
+sub:619620595216,-271826,0:619620867042
+sub:503021,559324,0:-56303
+sub:46990,601026675862,0:-601026628872
+sub:630276867,92393884,0:537882983
+sub:64847122,-1741761,0:66588883
+sub:-901885041650,6063747686,0:-907948789336
+sub:9090817588683,-74217059906,0:9165034648589
+sub:4643353802,39676050,0:4603677752
+sub:61222313,-991211846100,0:991273068413
+sub:8145673172195,79545920286,0:8066127251909
+sub:4326733518687,315334416,0:4326418184271
+sub:65122622889524,686861271,0:65121936028253
+sub:91927935495,815931,0:91927119564
+sub:360036184139,-929647,0:360037113786
+sub:851769193,5104213614039,0:-5103361844846
+sub:49764,-1370901,0:1420665
+sub:543849288,7706203685,0:-7162354397
+sub:62844,8576091,0:-8513247
+sub:-809058073978,541423856,0:-809599497834
+sub:-2639589,58729,0:-2698318
+sub:-79585473,1798247,0:-81383720
+sub:316852976150,-860129592,0:317713105742
+sub:1273939285186,11601,0:1273939273585
+sub:80537932950,292617381640,0:-212079448690
+sub:5467548,5430035835,0:-5424568287
+sub:-5937877,24003123599412,0:-24003129537289
+sub:684651821908033,41369461672136,0:643282360235897
+sub:1137993337,2322246811872,0:-2321108818535
+sub:7374342836,64650413647,0:-57276070811
+sub:432132,-42261483441184,0:42261483873316
+sub:83231980056423,2783677270377,0:80448302786046
+sub:2587541968775,479202225,0:2587062766550
+sub:-928954175477668,-1742785659277,0:-927211389818391
+sub:6404997096,7343350521970,0:-7336945524874
+sub:727251429810,3193503,0:727248236307
+sub:77165840,-457577668996931,0:457577746162771
+sub:33934095603840,74283623494449,0:-40349527890609
+sub:3846088301735,-44249412464855,0:48095500766590
+sub:24497022452,4724262825964,0:-4699765803512
+sub:463651487662200,-753243402,0:463652240905602
+sub:71713522960,15380043873197,0:-15308330350237
+sub:8294630828927135,31183461626,0:8294599645465509
+sub:6703541383230,44950919818203,0:-38247378434973
+sub:868891910767,8481827,0:868883428940
+sub:6321902376793877,-477388684714663,0:6799291061508540
+sub:-32763637641,66549351522069,0:-66582115159710
+sub:288533359019263,58471469888811,0:230061889130452
+sub:-751498035858161,527076997758,0:-752025112855919
+sub:1940356995569832,103761002,0:1940356891808830
+sub:11785051,32863482880064,0:-32863471095013
+sub:6832388,998030894437455,0:-998030887605067
+sub:-29992855,4391685016,0:-4421677871
+sub:-60108503487,-15310122633,0:-44798380854
+sub:-6477442216968621,60885516917,0:-6477503102485538
+sub:31744989963367,971914401,0:31744018048966
+sub:4773395,-699494329,0:704267724
+sub:158083905091,153315973803,0:4767931288
+sub:9257392592301,778762452,0:9256613829849
+sub:-869525659304,751325704189605,0:-752195229848909
+sub:-49703875573842714,4505925018715,0:-49708381498861429
+sub:-91664099,25339513330017666,0:-25339513421681765
+sub:469453608,-325915913621728,0:325916383075336
+sub:-6329249891,453489665443616,0:-453495994693507
+sub:1555896943,216164615094,0:-214608718151
+sub:7867736225,6515990968510638,0:-6515983100774413
+sub:47191079551,22909405,0:47168170146
+sub:480598620144,-630471272,0:481229091416
+sub:-44964236,4129791840132424,0:-4129791885096660
+sub:2078461471836,9510166882939211,0:-9508088421467375
+sub:3399372328,4480430653,0:-1081058325
+sub:37397829728829741,55828595309,0:37397773900234432
+sub:932684640397258009,-748484093750,0:932685388881351759
+sub:840884486710412,70796060480,0:840813690649932
+sub:2539205,16161203759,0:-16158664554
+sub:713637461058,6441899124,0:707195561934
+sub:-8173074559441,-280676331618304941,0:280668158543745500
+sub:430261608,4233937508,0:-3803675900
+sub:-131645380114748755,77441408953418,0:-131722821523702173
+sub:-31661643391,786373077474234,0:-786404739117625
+sub:278686734235471032,120592814722,0:278686613642656310
+sub:-2931231599090,18746712502644976,0:-18749643734244066
+sub:61029444723255769,-2293742672243933,0:63323187395499702
+sub:816220890520,640524790657208413,0:-640523974436317893
+sub:16665591262,113580566277835849,0:-113580549612244587
+sub:-868305701832,6230551669213729,0:-6231419974915561
+sub:11999732039934306,23827304849399,0:11975904735084907
+sub:91534672684829653,795520608093438312,0:-703985935408608659
+sub:-8985197818103126,141826190572801,0:-9127024008675927
+sub:390870406977082056,3249082110578,0:390867157894971478
+sub:88089340380,339939269745765,0:-339851180405385
+sub:-9559600885723,1043929655718,0:-10603530541441
+sub:7521666468386587380,-6553266884,0:7521666474939854264
+sub:8481985305837,8883976116,0:8473101329721
+sub:8322745787655471,-2367148822664118142,0:2375471568451773613
+sub:-1536130411,5098377844876093,0:-5098379381006504
+sub:-80409580247,-379667394325917,0:379586984745670
+sub:2780978527253898223,-793585194380805771,0:3574563721634703994
+sub:983228849414820623,411233979567,0:983228438180841056
+sub:4312344973,8504030055,0:-4191685082
+sub:6929160648081603523,-9139369237550637,0:6938300017319154160
+sub:40543447104286,922867012966969520,0:-922826469519865234
+sub:-32492268811,-52539511415,0:20047242604
+sub:-837736542959704435,-11698939306808,0:-837724844020397627
+sub:30695570430,6965534034801150,0:-6965503339230720
+sub:743449156492,-892800013061,0:1636249169553
+sub:4650491989907718938,9119100370137466,0:4641372889537581472
+sub:475327493368,391070618301538,0:-390595290808170
+sub:9789197909023,-2250068166694,0:12039266075717
+sub:3951486522961630212,41419130651165087030,0:-37467644128203456818
+sub:36289729721981,609158820292,0:35680570901689
+sub:5238096716643,857369737080,0:4380726979563
+sub:20927421747352,7859500562781,0:13067921184571
+sub:853523362775,-58650620319893709899,0:58650621173417072674
+sub:46324137709977166,3445427404517058,0:42878710305460108
+sub:8903783900,665953140969,0:-657049357069
+sub:8807754569337,1429027872766,0:7378726696571
+sub:-69086569251605,3823065660047,0:-72909634911652
+sub:74058749504331776,4434739153355644691,0:-4360680403851312915
+sub:-52234016526389,-2748494775019,0:-49485521751370
+sub:-6279254893906588798,625713048668,0:-6279255519619637466
+sub:3054225188071649,435737551736,0:3053789450519913
+sub:773765483980477636,76679006788618217,0:697086477191859419
+sub:9779893465932,7787153050157190775,0:-7787143270263724843
+sub:59561782129137,9069749963639028245,0:-9069690401856899108
+sub:-341767412794852361,347062438266855646,0:-688829851061708007
+sub:-9228152928357,640608182261,0:-9868761110618
+sub:-42043060859484,7345135549532130055,0:-7345177592592989539
+sub:19318981939433,264137322793696365561,0:-264137303474714426128
+sub:8745011564822621615,75690236981341546,0:8669321327841280069
+sub:2006412627556,444508404836,0:1561904222720
+sub:-996892139262,3687846060016536,0:-3688842952155798
+sub:591666758481462692,6187092701409,0:591660571388761283
+sub:17253871467666658,521693769674,0:17253349773896984
+sub:-18811272204464,-70402687077401900203,0:70402668266129695739
+sub:45980222925454243960,90960767776830610102,0:-44980544851376366142
+sub:-66394515686754,99465607502696,0:-165860123189450
+sub:-731492671961447493,42337700004380375319,0:-43069192676341822812
+sub:6642648198381310,-567336740547801378,0:573979388746182688
+sub:811917479145896,258859229290245057,0:-258047311811099161
+sub:66015593565297,625461142945341,0:-559445549380044
+sub:30440701155222429,6075207040555619467769,0:-6075176599854464245340
+sub:2751861052219993314121,760255884133587996796,0:1991605168086405317325
+sub:9525855084181563454,4607581127890,0:9525850476600435564
+sub:5557962211148071712,1921710471388746938,0:3636251739759324774
+sub:800293622218736473310,8120868065192,0:800293614097868408118
+sub:-45549550905111,-3937133121943669502489,0:3937133076394118597378
+sub:-81611168134401657674033,-29024094310537521258,0:-81582144040091120152775
+sub:473739545776060,-95651109326027,0:569390655102087
+sub:-9943711197250791783,5192955396843373262,0:-15136666594094165045
+sub:74362674758137703088,991218776208774087,0:73371455981928929001
+sub:8942190838160347,42915360862670,0:8899275477297677
+sub:66210460069722759,8216793402040737008247,0:-8216727191580667285488
+sub:28630228799120059057,-727654086775011,0:28630956453206834068
+sub:-2502191839260572,-609085018990088802,0:606582827150828230
+sub:-707403262721461629,-9548746126714505844843,0:9548038723451784383214
+sub:-42739413943936747053,7248311562458017,0:-42746662255499205070
+sub:46123774937019599821,521218568189626101724,0:-475094793252606501903
+sub:9415554602318087,9000595012272170366,0:-8991179457669852279
+sub:-1951679141829705122,-12285787616979339429,0:10334108475149634307
+sub:-4386967398151873150474,2143436435198250529,0:-4389110834587071401003
+sub:97977437591194303377451,642191000671555391,0:97976795400193631822060
+sub:83261682108887535662635,511317890231125086112,0:82750364218656410576523
+sub:41310833218589671,9897170076989397,0:31413663141600274
+sub:1683930885684182315875,-66190399132485560,0:1683997076083314801435
+sub:83038493375345259207979,58284882728646817780,0:82980208492616612390199
+sub:174833752819190460,58205143986480293592,0:-58030310233661103132
+sub:-51972688295317718162,-53017954844280432,0:-51919670340473437730
+sub:3049073769975215127,-8413940824249555462,0:11463014594224770589
+sub:66856363357316667,-37906703703222242237619,0:37906770559585599554286
+sub:541685788711205,813493512383742701225466,0:-813493511842056912514261
+sub:12039482877604486443159,-27784227929617157318,0:12067267105534103600477
+sub:2031498290041713,-706931410323604521481,0:706933441821894563194
+sub:793163145663267355,488093806957995,0:792675051856309360
+sub:-35932264894813,6608203939349524510555,0:-6608203975281789405368
+sub:6095035696899997995461,49012978744796870,0:6094986683921253198591
+sub:736660687461873,2928166059556503986320,0:-2928165322895816524447
+sub:-80752317921759003744482,-2784356502312865996499584,0:2703604184391106992755102
+sub:-55600025805872206,-7990044978835553,0:-47609980827036653
+sub:20131235857391244,745599894858331816,0:-725468659000940572
+sub:473379993971533482724,53545104197056246737,0:419834889774477235987
+sub:-7901274667808068,7310483319842229,0:-15211757987650297
+sub:611143500250518767744,565842823113937536426566,0:-565231679613687017658822
+sub:8702674605316149,74225958414698686231,0:-74217255740093370082
+sub:847520472084398906,-181833891734712245,0:1029354363819111151
+sub:882552741752125480,4287937154291698619767895,0:-4287936271738956867642415
+sub:1164933678283444,-605787688418745409686,0:605788853352423693130
+sub:8189990356647722508802,5327680305703219926,0:8184662676342019288876
+sub:20126414182234863325418,651586473061170891,0:20125762595761802154527
+sub:-7243913367665451229510,920916193262000838,0:-7244834283858713230348
+sub:241247407616518609790,849820061721310660,0:240397587554797299130
+sub:11610932258446222276,-238310622287414468083,0:249921554545860690359
+sub:333102694750160639,69609722651274194224,0:-69276619956524033585
+sub:489371802875965014118478,96271202587903139,0:489371706604762426215339
+sub:7344620696143243253130,-354550759273217997666,0:7699171455416461250796
+sub:7443029079637089736774,47397475977873627,0:7442981682161111863147
+sub:-552185046973685246703728,5086882342952953836639656,0:-5639067389926639083343384
+sub:34160638466370340264992,6442462400353615432715,0:27718176066016724832277
+sub:224642516163621778782,4567297709761777098,0:220075218453860001684
+sub:396245283577471672779404,-28835207585120519380895,0:425080491162592192160299
+sub:542742994231711454505,1493274706520691229211,0:-950531712288979774706
+sub:-4010437024179449951252946,6148766465731638330749,0:-4016585790645181589583695
+sub:-45993733981177457,-2333654032343500227394581,0:2333653986349766246217124
+sub:-53268979390855780768161,244917458799919371067,0:-53513896849655700139228
+sub:9597472083289623017,283637277496645411,0:9313834805792977606
+sub:-549237729763380362715631,4233347728399082996881,0:-553471077491779445712512
+sub:546810502069383982063,-5966616092961401439222,0:6513426595030785421285
+sub:2693320235570423841,-636227430987384270,0:3329547666557808111
+sub:299001294509600705281,-662976479255032381882,0:961977773764633087163
+sub:-9969627469592910143441654,-4697810125124307023,0:-9969622771782785019134631
+sub:295862851742112486,62089965837017871773124,0:-62089669974166129660638
+sub:35578586721878839413,524399278031861381275,0:-488820691309982541862
+sub:-579419395708175094375,-86888512465827623053,0:-492530883242347471322
+sub:6685264590200748832,2474399060436569565967165,0:-2474392375171979365218333
+sub:411194309664386491791190124,-758109583623796174126,0:411195067773970115587364250
+sub:63387968120454752,367951841292571472228663,0:-367951777904603351773911
+sub:-523269515783595554078,49060669022383177598,0:-572330184805978731676
+sub:13445326521609443648,9751080551639245658806,0:-9737635225117636215158
+sub:789739255835156800013,315101502591672711170806,0:-314311763335837554370793
+sub:73481634769773817391,7522066373372077852,0:65959568396401739539
+sub:59238938099041804756,-284755768386936014001,0:343994706485977818757
+sub:2345748144830635294766296,26772347379722903394664,0:2318975797450912391371632
+sub:-96180432920038812502,7130528324583233658,0:-103310961244622046160
+sub:-6103646636128907863077733278,167360991644513667938,0:-6103646803489899507591401216
+sub:89183651282796860734843567,650591691692940868,0:89183650632205169041902699
+sub:885385723843334016669166462,7959173204532632279022148,0:877426550638801384390144314
+sub:426509712333758537770,3053810150190399695475807,0:-3053383640478065936938037
+sub:-43602818211336693439,37720583430905942376,0:-81323401642242635815
+sub:42082335899892839012828,54006514124159856356378769,0:-53964431788259963517365941
+sub:744007647137500935704813,9607111119925514823029,0:734400536017575420881784
+sub:49316936033792930103965,-3034940638845987540137,0:52351876672638917644102
+sub:83874798574806162505693,464988593797915772,0:83874333586212364589921
+sub:47935017932067725904,525937150680246466817568,0:-525889215662314399091664
+sub:15759732742160839060899,8468547017336608217,0:15751264195143502452682
+sub:68081177675380449585,232838274961715380121771,0:-232770193784039999672186
+sub:198837569846432824894,74142127460226777613642,0:-73943289890380344788748
+sub:1898390184425605471746,-8609726339421831182804422363,0:8609728237812015608409894109
+sub:5010086610580228482335807,750924907754526639102577674,0:-745914821143946410620241867
+sub:3239772657087138659473,26630017052110857873,0:3213142640035027801600
+sub:30931222688688580641792927,47650975868262142324567646743,0:-47620044645573453743925853816
+sub:2618635242932069293276,-37969350588765740201326652600,0:37969353207400983133395945876
+sub:62748041061334975755,-8597227755884238992024742173,0:8597227818632280053359717928
+sub:73666512572900713065,727593598628012630085291831,0:-727593524961500057184578766
+sub:73065402278129705309963059248,-1510259437891597840030938,0:73066912537567596907803090186
+sub:652852443033404198570557,3218208198091308335983,0:649634234835312890234574
+sub:322654125619631317783651175,103982638102588159557510478,0:218671487517043158226140697
+sub:47298054366651393257588577343,25292337944252217030,0:47298054341359055313336360313
+sub:4969650998010954466,-5928799632879538310681042,0:5928804602530536321635508
+sub:94361219162537205953,-573028299187075717448661476,0:573028393548294879985867429
+sub:500487140938346964814,-666190790348527856857515,0:666691277489466203822329
+sub:2397057037367709886558,8469650679664722706535608,0:-8467253622627354996649050
+sub:5916454672457377863577802905,-301691311710205742681455,0:5916756363769088069320484360
+sub:-4732324961421982812667328,-41666595440544717926863264,0:36934270479122735114195936
+sub:7784556296620016124437432,295631109431335676271,0:7784260665510584788761161
+sub:-468243465340943117955484398,-86059014635749889021797574078,0:85590771170408945903842089680
+sub:7581798337258404983887829,286326330291344819121713,0:7295472006967060164766116
+sub:-59661872187286137669680,993451500121394333929486,0:-1053113372308680471599166
+sub:2962196560211918477855182834,429980300074111981923309698661,0:-427018103513900063445454515827
+sub:-117191815514577197960025,-93952901109567063533541898393,0:93952783917751548956343938368
+sub:972649124468069443877962,39940702160872858805890483783,0:-39939729511748390736446605821
+sub:52911349728309634554095814861,640041502135571284090,0:52911349088268132418524530771
+sub:9563434009347863250789850,39324990112287164371797250,0:-29761556102939301121007400
+sub:501256807694158654884,8345102795766270329548488379,0:-8345102294509462635389833495
+sub:73135419149054064613594459638,-376755188742340618890,0:73135419525809253355935078528
+sub:258128605755268399576,116154542754127542403,0:141974063001140857173
+sub:-388289190817020242752560429,683426700586684828499964340,0:-1071715891403705071252524769
+sub:77603273142377289304718668478,7907734025138351381355884534,0:69695539117238937923362783944
+sub:59920022083646756381083767,-676349674131765453090842,0:60596371757778521834174609
+sub:1386456963825362091135,5043324890371013843489776600,0:-5043323503914050018127685465
+sub:22908004694216963557562131,1437848391259187655742912574429,0:-1437825483254493438779355012298
+sub:75830204485394953668558224750,818650518003178932071960,0:75829385834876950489626152790
+sub:8072507208044425938387,2801437782939637080569080,0:-2793365275731592654630693
+sub:996986457053305310363710,4270654800444412431799788016,0:-4269657813987359126489424306
+sub:476227015634465030195295,802516552923254955041235580710,0:-802516076696239320576205385415
+sub:-3862793080955285675336,601225923445782883856004,0:-605088716526738169531340
+sub:34058788843087368388987,788661560182208367542729826,0:-788627501393365280174340839
+sub:75890485056733894277957536421,28898157540847408357479445339,0:46992327515886485920478091082
+sub:836419152310550927547976,-715832228817310323167747520,0:716668647969620874095295496
+sub:71149688455411718068481321,130052491916581090823794037636,0:-129981342228125679105725556315
+sub:3047224655714425540346555,583427698600273187296801675761,0:-583424651375617472871261329206
+sub:-1762508903601801463391,1123979050566438206073605513714,0:-1123979052328947109675406977105
+sub:75571713529690058494700131,154047782298368874362663480,0:-78476068768678815867963349
+sub:8881924107521011726353538,-3145465133030840075856549,0:12027389240551851802210087
+sub:2119385564140685046061904,42628989499638883272827242,0:-40509603935498198226765338
+sub:636137867409083757104434174,876963242090925483645110008648,0:-876327104223516399888005574474
+sub:956392636402263734252628073,47247440520063140522408813223,0:-46291047883660876788156185150
+sub:5565262347877821939981460417240,-985376663560828156502183,0:5565263333254485500809616919423
+sub:-96960327111310542205299575340,754323275128519456665692931,0:-97714650386439061661965268271
+sub:390903876504582680914435276856,409728963505921718859992691123,0:-18825087001339037945557414267
+sub:600683747782519279592349358,3076791699376918600719019341,0:-2476107951594399321126669983
+sub:9867764659515798940712578323,6357991496217721443026258037557,0:-6348123731558205644085545459234
+sub:68114522731034072566854092812686,62725405971469064330284876,0:68114460005628101097789762527810
+sub:907396594886580376638506,-894708410482856602073830977246,0:894709317879451488654207615752
+sub:-30792046454713176872672190485565,-8017250846058869636998077777,0:-30784029203867118003035192407788
+sub:-18821866119770039003181629912,82441485710616151410107,0:-18821948561255749619333040019
+sub:80095770818874409058224,9316123957640218030400143320,0:-9316043861869399155991085096
+sub:-901755584000000420457516562373,-2517773106349772310667656,0:-901753066226894070685205894717
+sub:-883321569482669903165683,-44558935482820169589044365546478,0:44558934599498600106374462380795
+sub:601706200500617282847480732962335,43201582734874942566066864633597,0:558504617765742340281413868328738
+sub:3611141688653897808711895791472,54026584092810638450252354,0:3611087662069804998073445539118
+sub:-9089386632359156927536477163974,604640114580951133123734104973745,0:-613729501213310290051270582137719
+sub:-65911585682039568232806668,921349267715834145888878007323,0:-921415179301516185457110813991
+sub:740180119243741829715055823,420700352624083519085129,0:739759418891117746195970694
+sub:85012296935839090922311415,56044320231947385798897291322,0:-55959307935011546707974979907
+sub:5658315653448747612688000,4877275861716865293755139,0:781039791731882318932861
+sub:53078309233697402718315797802,786142563765269101788772678439,0:-733064254531571699070456880637
+sub:380283779338470154888541799,69789893061880576858724867806,0:-69409609282542106703836326007
+sub:-36819622867396721797461,-487239057841776678372530391049923,0:487239057804957055505133669252462
+sub:432355289983835194025265634880,722175859400496706671386831852299,0:-721743504110512871477361566217419
+sub:406113849743376356851682,-2948843385313638396180656653220,0:2948843791427488139557013504902
+sub:-450089373848778279085231682276,6922355877436261896463320824,0:-457011729726214540981695003100
+sub:-461778533905902103878563791120779,30903051263975616567418133538553,0:-492681585169877720445981924659332
+sub:2225847828886634429718900,-141670429280564340131559528873669,0:141670431506412169018193958592569
+sub:-518005307820181246928833,41493548566098807242410918395372,0:-41493549084104115062592165324205
+sub:1386972819787742372011414030306,6378199700569631039860797133,0:1380594620087172740971553233173
+sub:-9953467574634703627642091359525106,109232097199219102894213900,0:-9953467683866800826861194253739006
+sub:272224578522098768588271712614,-954774545043667358357735233977,0:1226999123565766126946006946591
+sub:-13397521090097970078307026041,-208746646957761968673045385061,0:195349125867663998594738359020
+sub:90242053814362992528569637627538,819378127307812972535514213,0:90241234436235684715597102113325
+sub:475879565794423355160366826570767,-981714991594839343058124009,0:475880547509414949999709884694776
+sub:73272944471878906655000028253254,9316121481273747448232884110081053,0:-9242848536801868541577884081827799
+sub:156124484535009677347773264807041,41067689846332812531537548182,0:156083416845163344535241727258859
+sub:5750622698618635176765494780582,8778936683577810871387349,0:5750613919681951598954623393233
+sub:752423753475915953095080157764850,110028403919321544278497683,0:752423643447512033773535879267167
+sub:986438424059798089328623129,944289987162416305345778315780032,0:-944289000723992245547688987156903
+sub:2940131992853959894009314316599,-6130856644000035009877295436,0:2946262849497959929019191612035
+sub:-60219475207618615852406049263760,245420985013813274904940493371846,0:-305640460221431890757346542635606
+sub:76132456058041997180166479105207,1333701621741713587577000118516444,0:-1257569165683671590396833639411237
+sub:551757239718514829275035933587668,20975678617718960357674898185,0:551736264039897110314678258689483
+sub:827026171479636357807858542315003,657266896495283042560293955528681,0:169759274984353315247564586786322
+sub:62029235723027056966248632640016,4720308399791420006433428083,0:62024515414627265546242199211933
+sub:3370077911228331451226459981542,56700095331827269676453888012958,0:-53330017420598938225227428031416
+sub:3514193210192659422357386965236028,5945062235433978181560378967712895,0:-2430869025241318759202992002476867
+sub:3725417532430237033267313551512,-29139588479237546460280773,0:3725446672018716270813773832285
+sub:86971485372454469574581715701279,76600079495825348746163163766060,0:10371405876629120828418551935219
+sub:52025473585241225053445613599064,64931994025064476703228951534248,0:-12906520439823251649783337935184
+sub:-46094956887492446679275334,4199288643419024266960740601763,0:-4199334738375911759407419877097
+sub:-199531081865328340581624098,61586813654360478634926776,0:-261117895519688819216550874
+sub:2228997256609098057220853694688,77983035307573853597859653028,0:2151014221301524203622994041660
+sub:-998325557636914977245575086,7667612449137815647454849829,0:-8665938006774730624700424915
+sub:746793137925798942820906830,399507178175236915401754759449,0:-398760385037311116458933852619
+sub:634724387005569029859717498,3437595978823543942820525964913,0:-3436961254436538373790666247415
+sub:7141573144886127523784053337066625,-390050969405812623337724114002,0:7141963195855533336407391061180627
+sub:-91403573621251855050085889821,78465471196357080847824505165565,0:-78556874769978332702874591055386
+sub:349658297262594920988266356059043171,796963132566625995186691340562185,0:348861334130028294993079664718480986
+sub:-633893601713106197757857736129298,86189806992731837430692951480,0:-633979791520098929595288429080778
+sub:-43900746259116235552821471377,591055471482916203481396667491207,0:-591099372229175319716949488962584
+sub:2557547273135447028597996609,64663579124550082208338293785,0:-62106031851414635179740297176
+sub:94701712281465414851697898675451825,1024428303725598723580617161,0:94701711257037111126099175094834664
+sub:1405995388343974884472280878660,-220054432405512280858363563,0:1406215442776380396753139242223
+sub:999816594826990228141732119822,984552280063995997341773813089627665,0:-984551280247401170351545671357507843
+sub:5838938294141788996592039893,50902237118539094354421180186316,0:-50896398180244952565424588146423
+sub:599678492538583548148447971111185,73667844355412382811962121530977,0:526010648183171165336485849580208
+sub:6395778081807663524044632168813593,867149393095359006170012722,0:6395777214658270428685625998800871
+sub:939460433716954373684816294933837,474277009046118167849279293527097,0:465183424670836205835537001406740
+sub:7816286294597662244110191807959541,6233835682136551847146227987794,0:7810052458915525692263045579971747
+sub:23281631659668473110100795038996,116520759657498664805703882673,0:23165110900010974445295091156323
+sub:46391396072715161551587488065814,33356982434471244343742063785074041,0:-33310591038398529182190476297008227
+sub:4585954807809352935161825310034011798,-54552397859131970401808336962,0:4585954862361750794293795711842348760
+sub:2422872895287330189582522753,4480479893211606075278003418285,0:-4478057020316318745088420895532
+sub:-13361745527437011657973841351,984220774495913608130872189292612,0:-984234136241441045142530163133963
+sub:-52685529704743149299243245793811,124512071496978690744692284754346701,0:-124564757026683433893991528000140512
+sub:143835388043216256200766869526,498925860575853395417250651462811889,0:-498925716740465352200994450695942363
+sub:371250666979424888145103423650818,1951666913810216016291928636377,0:369299000065614672128811495014441
+sub:14113880586323385101587281089,5086582061966123909499437086680,0:-5072468181379800524397849805591
+sub:457422738047527621626918654730135,17793707850630720090008287485134930,0:-17336285112583192468381368830404795
+sub:75091527004493134510290819264195424,48439881910003416229205500079317137,0:26651645094489718281085319184878287
+sub:-37624201790320133398219479795320611,4305256066030674211442956228314751717,0:-4342880267820994344841175708110072328
+sub:-63359729740153326293762634,354591974904021002246602880500006792,0:-354591974967380731986756206793769426
+sub:9308446708313654525402624748223454,-60317991035211151378177464977415474,0:69626437743524805903580089725638928
+sub:120534458842619000629729516606,567080219552763040041011655657,0:-446545760710144039411282139051
+sub:-8121545527448089591108392261383421226,-250658045580063728305171566063327,0:-8121294869402509527380087089817357899
+sub:196379537181644459409584027643681,1405776248624555617885389492315342,0:-1209396711442911158475805464671661
+sub:249608305407374994198898962694969319,2499313962944780828355872882428,0:249605806093412049418070606822086891
+sub:-86133870952625036607121720129239484192,-2210083521958904762483447549909,0:-86133868742541514648216957645791934283
+sub:-5537761268890338810683747816401,88831072690533799673765398860186343,0:-88836610451802690012576082608002744
+sub:7650066177648379388712028843866717642,918679522282053129239748147974121,0:7649147498126097335582789095718743521
+sub:565791730633833592281012727365648,852047442684103892006895595156346311,0:-851481650953470058414614582428980663
+sub:35625580968671553109914463243195234,991752088396773683576302377308181924,0:-956126507428102130466387914064986690
+sub:6830152102738950636231503454962474,6109835276749854485232715520241,0:6824042267462200781746270739442233
+sub:9645316618209602253070352413137908638,3394079504397347166925767086732227,0:9641922538705204905903426646051176411
+sub:6906473148858285032644642660383154266,-13248476237838956330778312519,0:6906473162106761270483598991161466785
+sub:663679860762267995009788953575,245501799877415862306412167957117435,0:-245501136197555100038417158168163860
+sub:-44512568466689863068389777224796828752,59397617756155227553085552332805471,0:-44571966084446018295942862777129634223
+sub:-9780895042010683622315363216460759418,76907130979153947097579514138695056628,0:-86688026021164630719894877355155816046
+sub:7347847663681638512926883660656747,21689722568710802776572651908345,0:7326157941112927710150311008748402
+sub:3783373250173630571015208086015385375,85650811474649882924710498921920,0:3783287599362155921132283375516463455
+sub:56849910710166566393455502068193,938068347237485972222899422567001939804,0:-938068290387575262056333029111499871611
+sub:504581213153898088538898634074784,298859276817968178012741515281,0:504282353877080120360885892559503
+sub:62457537532467044548168035547098,350956278715084042186918483657291476,0:-350893821177551575142370315621744378
+sub:7253075028419141077788097530219264862,50712428890680046435253055355573928021,0:-43459353862260905357464957825354663159
+sub:908092436379098470271979681591988,-50980440695559153633860322916212052697,0:50981348787995532732330594895893644685
+sub:199609775815884715957098583502038535,126431898613403845101203447550779,0:199483343917271312111997380054487756
+sub:9582359917228621477273022611353,-7814266758202663854720672879571,0:17396626675431285331993695490924
+sub:-8602898145948602715689375495162314,160918011477272833149624669760689743,0:-169520909623221435865314045255852057
+sub:9948567545244824462599097821402,321969130181831095335604501478150,0:-312020562636586270873005403656748
+sub:3108375720921396317913873465866,515757643860608151355730977219,0:2592618077060788166558142488647
+sub:-6959118740348618652311501232880384,314902316795577348140190091299453995580,0:-314909275914317696758842402800686875964
+sub:852431860747366034722063069637910,697844878845085176354494126562269534,0:-696992446984337810319772063492631624
+sub:-695872067848396881315408129801830330160,515796995164989970353676000353939744,0:-696387864843561871285761805802184269904
+sub:763264778536698023696216317523596944856,66658684467328574590928002628720352,0:763198119852230695121625389520968224504
+sub:551406701743303600756051581664966707,-2096778986234403787979394471172513533,0:2648185687977707388735446052837480240
+sub:8980464673485071567470684316357345,706157473742536317728718771566732899996,0:-706148493277862832657151300882416542651
+sub:-8959013916303797315474218091253977724,17317243712015390717561716185598103919,0:-26276257628319188033035934276852081643
+sub:610642046003967779716956199512502965820,-1342047130732031394498227273521440693,0:611984093134699811111454426786024406513
+sub:39048465017221373894786787092323,27171758183377068947756846246554,0:11876706833844304947029940845769
+sub:8851422489276175894252333429720103986615,23971945232205648973518397199417121,0:8851398517330943688603359911322904569494
+sub:-84833640081477194078008827918110,4096265727659744202225819899847459,0:-4181099367741221396303828727765569
+sub:2449552679550251863203300609863059096,-87978393823203322230640767374297,0:2449640657944075066525531250630433393
+sub:-78001817791533007712431842020149120,-517984095203705432252174589659459457366,0:517906093385913899244462157817439308246
+sub:925643199231868890271300730031810,24193296045997277400311155524231,0:901449903185871612870989574507579
+sub:45809177403727955831024802122687486932,47359799236575106780358807894627994236,0:-1550621832847150949334005771940507304
+sub:517605223957091165935716210936350445,862910955378659702358254436657666937,0:-345305731421568536422538225721316492
+sub:72688630642528437745188023003208451686,-6514092119486018712109302075636901,0:72695144734647923763900132305284088587
+sub:9017708871653095110086602388639208564217,9686163604138029584498185971117663,0:9017699185489490972057017890453237446554
+sub:232079069033420026812017177630381923958,-620458583032652195500759259597623123174,0:852537652066072222312776437228005047132
+sub:7890695491854299352485817202277388,703159083088728550533731201284887315751,0:-703151192393236696234378715467685038363
+sub:89820101894310757911847760478077656263,83262600530464963372213698397466309520,0:6557501363845794539634062080611346743
+sub:15643499204310770849595390474553,-167812233465782889797029678386637503251,0:167812249109282094107800527982027977804
+sub:-5489423773440626595521848968440708,53474930188578916210505119684094887079874,0:-53474935678002689651131715205943855520582
+sub:9795002336914579634933717979516686913,261017010939337312979598924346472448676,0:-251222008602422733344665206366955761763
+sub:4331261142314159296760231606251204672243,95924782688351130622315102956854589,0:4331165217531470945629609291148247817654
+sub:-8555084299250330981422502494290977,-783738723298387481257063528884261006006,0:783730168214088230926082106381766715029
+sub:55877969868981220363181591809987047101,-582660368158295495569660057228613506663,0:638538338027276715932841649038600553764
+sub:7431276323200780996119690290385564268160,352432120959308196444383869982649742380,0:7078844202241472799675306420402914525780
+sub:55510991248344199097615219287024885342254,332608825632573500219548085422149375,0:55510658639518566524114999738939463192879
+sub:-407443715077704811283446238871658731249,-40791246123034116937388818513050,0:-407443674286458688249329301482840218199
+sub:92659603513745501543601415394970469662329,6767288283622355176053882537452755648142,0:85892315230123146367547532857517714014187
+sub:47223347378419458293433033085679670112,-62754319264178123190515063783530,0:47223410132738722471556223600743453642
+sub:1267788394862117094544460471276744086901,-665697188010909239862834883890257046539,0:1933485582873026334407295355167001133440
+sub:295345762969445285300883528234566,676193063455453770878866399645739938,0:-675897717692484325593565516117505372
+sub:5505393498870816097766218031623252626,39514445630793756368190395762767,0:5505353984425185304009849841227489859
+sub:42208069897508165365927050240558926,45558978530284359271147071076409531,0:-3350908632776193905220020835850605
+sub:54167453556761503889312836115010425171760,187522719313793483915703839179272166586,0:53979930837447710405397132275831153005174
+sub:362669233317017065848977774618899144317100,22296129083231337516474760065879885,0:362669211020887982617640258144139078437215
+sub:2070398587579928847370215004355097684669,-64067479504146184394486079741662,0:2070398651647408351516399398841177426331
+sub:547456256889894902401571239347850863825110,963930110027673150476898540751636078,0:547455292959784874728420762449310112189032
+sub:1331413985442244763704908202938864787301,-6928236741466387982911397285024730442,0:1338342222183711151687819600223889517743
+sub:2647018820693334945869095350861961405456,68207845515177324917936202808076981,0:2646950612847819768544177414659153328475
+sub:8513268833284045819607290710032375651,877742296072025989690540346672438747497853,0:-877733782803192705644720739381728715122202
+sub:-362723824300008973505657052571345045426697,-3728428407208494550981026382186278817,0:-362720095871601765011106071544962859147880
+sub:29679672086905939495640819132486834971886,805805496484559347056265315535987,0:29679671281100443011081472076221519435899
+sub:85912095665544820943415113062566570378,-2312537069323562328248319672615297,0:85914408202614144505743361382239185675
+sub:-92634213643016881068533819685947190995,874723874226479957426284530510689780,0:-93508937517243361025960104216457880775
+sub:339348983157405555268049494721010874912,538915927881095996244878294700090,0:339348444241477674172053249842716174822
+sub:-786507623206485460799545427617928648802,-66497629708368438568316964408808815,0:-786441125576777092360977110653519839987
+sub:7838773867614617728873367710439469,-20970941234515400392700499346730050,0:28809715102130018121573867057169519
+sub:-14549979612356881205802146600958641293,-4331851795749574278449787125765833575320873,0:4331837245769961921568581323619232616679580
+sub:916100575956975239103806648291021240434945,-6239107263122317258754465996318083039813,0:922339683220097556362561114287339323474758
+sub:92055367791915247552778134001204029114,6493201508072505271272645779402011239988532,0:-6493109452704713356025093001268010035959418
+sub:-6983015937156891828369789959503372656192768,774335279468118483882198373037947794429,0:-6983790272436359946853672157876410603987197
+sub:3000995395281402114598820789701617484765714,21554713637509345916067753026101593,0:3000995373726688477089474873633864458664121
+sub:210513959404424485767273638342023036080,7040631017221420564743196284036319107483,0:-6830117057816996078975922645694296071403
+sub:927299366270769201971090702434342061,292331300721224857352792240371766440,0:634968065549544344618298462062575621
+sub:4878072375408814508188936210997478,1660478705544816285463647361127486,0:3217593669863998222725288849869992
+sub:549522597810758995529412992430729353622069,28161367971601239141551130639124424718,0:549494436442787394290271441300090229197351
+sub:-3158360246238245818023338839988456941,266461438371462069740221467823944724791696,0:-266464596731708307986039491162784713248637
+sub:9007280594321441251173718122758301273400191,5723070952876244917629403533894720814995808,0:3284209641445196333544314588863580458404383
+sub:7884430922306064951790326519656428,-265155882238652982403545634743490030,0:273040313160959047355335961263146458
+sub:4597158820829446940984073371303248589349336,4591368594874737502008341975525406,0:4597158816238078346109335869294906613823930
+sub:187371543407659146021544517634809651432,2502692698036481709764505060551779924246,0:-2315321154628822563742960542916970272814
+sub:-46135001830288779024726983515547650361,28041526428243568730358118145100364532,0:-74176528258532347755085101660648014893
+sub:-9572831631676924773779207132507340476745,6190297632466241073074006835641016273635051,0:-6199870464097917997847786042773523614111796
+sub:47274442119812358441831910654123850,99197173529181174900799490801927162,0:-51922731409368816458967580147803312
+sub:4006521386515878530482447147782028809,9872623466258041127006795769315012678883,0:-9868616944871525248476313322167230650074
+sub:82360906569911962379105787490864998240463,3515099274891762492395251937584744489436,0:78845807295020199886710535553280253751027
+sub:343670280360898716041692324762031485,912832148190967667750082998631524743067,0:-912488477910606769034041306306762711582
+sub:-253140613356453965474749134907880537,-170796125539274882635608256319127725001467,0:170795872398661526181642781569992817120930
+sub:36063566343365723001908493555712611383171,32734135808710310540138548400630432992351,0:3329430534655412461769945155082178390820
+sub:8562448362864558581436509546230412228013,97253910164731217335889068286633868249,0:8465194452699827364100620477943778359764
+sub:458404043113501189736392131389765493,90992739814093306447341282135584737049,0:-90534335770979805257604890004194971556
+sub:93153136351650823472294576193567969076519204,-173058937221894304147436488969103021,0:93153136524709760694188880341004458045622225
+sub:6881134628891939703289843575851421899205356,411386417698245110176551995497774432463572,0:6469748211193694593113291580353647466741784
+sub:4806770024356558662054629453935871253631,-54599892445310777761980324364755187,0:4806824624249003972832391434260236008818
+sub:-659266383152476584352966529996782786154127,435809612191536018491951858809486469615871,0:-1095075995344012602844918388806269255769998
+sub:6935351506572536921188795798274428881775,-576575580669724321453218122448616063259,0:7511927087242261242642013920723044945034
+sub:858138516046706031509684781296126036025,8270111802191391308669991938939548604849,0:-7411973286144685277160307157643422568824
+sub:817937608310793751229857205081702066047,67716404516400692803055765045097508053,0:750221203794393058426801440036604557994
+sub:21505104291973748253849551840337359946735,724706181460445217421835535592570632258046,0:-703201077168471469167985983752233272311311
+sub:708273146228220275650926105350112291281906759,23865262954820244462104344820227603348946351,0:684407883273400031188821760529884687932960408
+sub:6099153001249914941269621426404674818058,2938683952037817006492484814984313285,0:6096214317297877124263128941589690504773
+sub:-31923841914332687245342017699243753384096,-5606132365222969440586408949174817104241599,0:5574208523308636753341066931475573350857503
+sub:72727007176742518045851035107319602707253724,6024790453998465390250582473731871348,0:72727001151952064047385644856737128975382376
+sub:83215407925470185284051090474309060496,291921577188866523931442328192670035753786,0:-291838361780941053746158277102195726693290
+sub:9122506511038509689834545171005820589612113,719752849629179435477077881697561682399792,0:8402753661409330254357467289308258907212321
+sub:-706538117813388518478786341886424717471940980,753933770122593367025588615709647464797283389,0:-1460471887935981885504374957596072182269224369
+sub:-521928555277746411910375390507381642863,6565723095409618237803362642454225982248113,0:-6566245023964895984215273017844733363890976
+sub:24450643550397676433664068681105834123,-3553012684598341625460876864934571794587360,0:3553037135241892023137310529003252900421483
+sub:4697123465198881265199203985357713516731,2536656939218887194502000678986317871877842,0:-2531959815753688313236801475000960158361111
+sub:-434930612814998054601249422118251831669239,-9901632499831703140917838027000240996177,0:-425028980315166351460331584091251590673062
+sub:-24385109664317253785149664202310847974785,96607275813663749523021171230142234086194,0:-120992385477981003308170835432453082060979
+sub:175998623183130570261164123649545173,5736821048759940607107406386900421138480116,0:-5736820872761317423976836125736297488934943
+sub:29899463144003206689099598069297927023037663,99983896248939908245937246988587266778965056,0:-70084433104936701556837648919289339755927393
+sub:-2847961215729667396008072338427848628952207702,-18041421325649266529475871020854283985158140,0:-2829919794404018129478596467406994344967049562
+sub:860655541398867584200967070629696235008,78536431962263231465180358761552384639106,0:-77675776420864363880979391690922688404098
+sub:635054687904331166120357977754969371811679971,-686756348638066683308736393560844813903,0:635055374660679804187041286491362932656493874
+sub:66115475514119620126879119225040664892295317,-87563343403151221453653304787865218792612594,0:153678818917270841580532424012905883684907911
+sub:-95550181030075465859987797705444435041845,-13665284586416167283376541733856225706235,0:-81884896443659298576611255971588209335610
+sub:92616049236912210791574668731523882357,-50096816156035511846343817545380962370926891,0:50096908772084748758554609120049693894809248
+sub:752708246188412062918458739359406381571670,-91802938193508678084864563021449730861494286,0:92555646439697090147783021760809137243065956
+sub:4243612523329014748898840962380294468164,-7391899758560053704137252356014460148281541618,0:7391904002172577033152001254855422528576009782
+sub:7067486379132347032443631353172208490907237,6868653310067531021850169369487996413345,0:7060617725822279501421781183802720494493892
+sub:652556473645101039426795633187084650620590359,66152612457983000774979517275135281517333,0:652490321032643056426020653669809515339073026
+sub:-35248969314647098087083472237063687482719167,25849045865960518844267357563296662714932,0:-35274818360513058605927739594626984145434099
+sub:154806501204449775250550809865383692315599,220408143673773957176222952814246726548300733,0:-220253337172569507400972402004381342855985134
+sub:426192001635333106574725027301522624829,54396270337654281439857103497213765055827390,0:-54395844145652646106750528772186463533202561
+sub:2229896635643148464416291192052339376,44520846864866048574834661782670612999637,0:-44518616968230405426370245491478560660261
+sub:3511182372941029827917330703726647738515,103149425998143931124350359115352011,0:3511079223515031683986206353367532386504
+sub:525626542557810263995696385369141917216429,28217794014403546465377535948401259179623,0:497408748543406717530318849420740658036806
+sub:246690678230593477546220249711651118557673599,7508868156388634892422733339741334130597495770,0:-7262177478158041414876513090029683012039822171
+sub:-52449842456878273278887468997485654278006880781,-8622224358149020156382756933011263673304901,0:-52441220232520124258731086240552643014333575880
+sub:43917648018810264827549426849617327620,237558137782296171751042504067082682085,0:-193640489763485906923493077217465354465
+sub:436885913378194523559098742354033959419293521,-4530060472748984412434685566970122986799899668,0:4966946386127178935993784309324156946219193189
+sub:934641428600528147928021193868692944237063,766500089354618869804173156494044479533434,0:168141339245909278123848037374648464703629
+sub:-9768794865885075606938340182122123503498,43399753693320722515476020420307206331,0:-9812194619578396329453816202542430709829
+sub:4363510431895873679990777251153049456887914686,-513680867120410140612246382388345195337,0:4363510945576740800400917863399431845233110023
+sub:813902461333355602341973794050956320693244,45925401255610697190710944025791579854,0:813856535932099991644783083106930529113390
+sub:469188297775571118958824594174696108861,49387169240595114881040011727698749675,0:419801128534976004077784582446997359186
+sub:2617097578471262472460098378161373440917,626830512279231586849866185531317270325856135,0:-626827895181653115587393725432939108952415218
+sub:5151556733598102144567084692707520491967675549,925683351507641765110930982020390027551182330,0:4225873382090460379456153710687130464416493219
+sub:7961214185889032744958189528184087887568,15082937694452952801156707282245848781046520,0:-15074976480267063768411749092717664693158952
+sub:103879675257649176952122144944531240879704,-22423657059836578389654041651233303849189846,0:22527536735094227566606163796177835090069550
+sub:-377277225308671992459589258065441211400861174609,785048601099920118475775642499967466881441513003,0:-1162325826408592110935364900565408678282302687612
+sub:2735744675788022453896759288099853051599961,8561848816916220633924173923975969846159936,0:-5826104141128198180027414635876116794559975
+sub:-8108322047295156406910661075095138292543118,765970407325610304094444482334627162219563792,0:-774078729372905460501355143409722300512106910
+sub:62171119480646146147373364600786632314820,68234069541303335859784698762591456286309,0:-6062950060657189712411334161804823971489
+sub:522026031606431401123213997569507489607798170076,-717305442128471697055893486214586513387,0:522026032323736843251685694625400975822384683463
+sub:7106849336102271174193475715677967626534,9912977315535152329193899289756117840576705086,0:-9912970208685816226922725096280402162609078552
+sub:5058631248804275381537183819839410866070,50068425216904104076548398574368463679233329,0:-50063366585655299801166861390548624268367259
+sub:377384922290900684378766697765696266656684929965,3450714239029691596858831084813277683453331017,0:373934208051870992781907866680882988973231598948
+sub:4127043375130626839550947340494729073973521,-93626779328435839646986009707952408489178855259,0:93630906371810970273825560655292903218252828780
+sub:8332162922657358325764463012629457809751,18980828259225905732804403805861953606268378,0:-18972496096303248374478639342849324148458627
+sub:6824265591340935169578122399500191463946638,540683715600472521291029118849898014133054,0:6283581875740462648287093280650293449813584
+sub:938521197483583303249511621812565283382055,44983796709641426782128325690649049185212710901,0:-44982858188443943198825076179027236619929328846
+sub:6735919466177663580236501266144291220013606,545280109966768999298146733178996573556068,0:6190639356210894580938354532965294646457538
+sub:141557686844798866713592847624357600454939,63012778579350927253738282115561965895300222,0:-62871220892506128387024689267937608294845283
+sub:2911872274073904179049270098803758998758604373,5178258239494241937818225445947335874009677,0:2906694015834409937111451873357811662884594696
+sub:1408871869925689627762516558570503883504,142730298505138588027696948531422563739,0:1266141571420551039734819610039081319765
+sub:8517606735957047009697093887557000606415498004,67761524001779430467799539453579156328203130,0:8449845211955267579229294348103421450087294874
+sub:4191752928232629208839556407817672130663759960,31120143251696350351062838658625186585417641244,0:-26928390323463721142223282250807514454753881284
+sub:1773460231905714486091498164221417916299907001,-13984788525502795401300137979455088110924764646,0:15758248757408509887391636143676506027224671647
+sub:25958221336257013267259455572234542250872387609,369753082501759921518867762124056653598276202875,0:-343794861165502908251608306551822111347403815266
+sub:2747326205290884717571093710516354517279131,-200370678858880488915468681389496795418066109,0:203118005064171373633039775100013149935345240
+sub:40540925013283891720123827423744878263336,16816649411016376863928894144184888209331,0:23724275602267514856194933279559990054005
+sub:956824713963595631181304277992935834382643,3722011506884112771542173984351354075026431,0:-2765186792920517140360869706358418240643788
+sub:33786382660255444220666312795011817615453429904,735670904381689507641600295585249267679379526941,0:-701884521721434063420933982790237450063926097037
+sub:2877930508524945640926303283416511321376944980965,-43009247946073345794766337066700378436417844073,0:2920939756471018986721069620483211699813362825038
+sub:850600786011638919961278503128401557972292751560,899851210392294397522137472190488479511758393106,0:-49250424380655477560858969062086921539465641546
+sub:2462694975979744365735428888726732845981,9408686710098328540592679577780711010523157567,0:-9408684247403352560848313842351822283790311586
+sub:-2041867610696880800533651474257712171578353,-2951979315678021415040184889765351233307860,0:910111704981140614506533415507639061729507
+sub:-129073103525919620980862298218649200450487,-4680531750102980987058307458952588397482469573,0:4680402676999455067437326596654369748282019086
+sub:560697897202574381605152953497173580884569831607,-4417286348361216883592573456612155389663357,0:560702314488922742822036546070630193039959494964
+sub:17697094196983519858381804010054585256525242,1131229531263856806842311520174862769452765002,0:-1113532437066873286983929716164808184196239760
+sub:804944662083760414801916105180787524533460301166,561420687759659377688505547923187467868090247,0:804383241396000755424227599632864337065592210919
+sub:-1028404789696953408936491711523277627418563936203,-464819589190508369472777448816708894892918349,0:-1027939970107762900567018934074460918523671017854
+sub:3239904738301933363048789064790365041923795,-9362725662858815747997680077547152674652685944821,0:9362728902763554049931043126336217465017727868616
+sub:761535872788271240805547447218654406655,107117430857728547131949784152272910306695,0:-106355894984940275891144236705054255900040
+sub:-706599751963833313886288562747297926395913585,8278362817238299934703728858793740479430872564850,0:-8279069416990263768017615147356487777357268478435
+sub:463035181445197130733843489204182896424351860,455471771631505836436066499095031596509414,0:462579709673565624897407422705087864827842446
+sub:2824978869446515961236880620253514087311655553702,84452147844444783212562643686865477267414258,0:2824894417298671516453668057609827221834388139444
+sub:95172190180193659817200533401819150201616611288,4253516641549024667802049662408505566309488148712,0:-4158344451368831007984849129006686416107871537424
+sub:-413667190552706011487044934212907016404257969614,33510901758543302257900826215150539862667792900853,0:-33924568949096008269387871149363446879072050870467
+sub:1802858236899130718560292083677283004676939126204,-9591029147984982245013613101603852129053721197,0:1812449266047115700805305696778886856805992847401
+sub:5057939642669588382714715374719737582363077336,6279587642602985268062149755325894048022192320,0:-1221647999933396885347434380606156465659114984
+sub:20062487148514066658598386877620234236424,92694212932494347668352880363113439277308854,0:-92674150445345833601694281976235819043072430
+sub:334984437475294142374221031664489193167379,-6135445036242663334683894840540269979231933,0:6470429473717957477058115872204759172399312
+sub:78029827510297184965229487811790757939762626812,-32404291595021766293653499499799280338229,0:78029859914588779986995781465290257739042965041
+sub:713392855478976816484264895166180199146764030460313,681291155333056129472241044283899139868686991,0:713392174187821483428135422925135915247624161773322
+sub:-80133415624337150636387109270312659175361915999,51418478774844443709286576402320460325196,0:-80133467042815925480830818556889061495822241195
+sub:880115711847568080735088547347709199159560057170765,93939048978536600599293035541531212947874110,0:880115617908519102198487948054673657628347109296655
+sub:6923910812034533596353419663722878592724935671,484167528133286735810248062291120475761574,0:6923426644506400309617609415660587472249174097
+sub:67181341858171188344681106006257889001113561091,-275892233786910833508198970431602677775347,0:67181617750404975255514614205228320603791336438
+sub:36921718877954581697392970162605715186348102300,94932105400913864317595606773063738421165759973115,0:-94895183682035909735898213802901132705979411870815
+sub:10176087189864101236325835126503742119508524,578515167611780503112210135879212793628134689743,0:-578504991524590639010973810044086289886015181219
+sub:771806623592639026200339778481682177781432660780,67004362616728326045114859791690823708021066956420,0:-66232555993135687018914520013209141530239634295640
+sub:-203402851288321919373536431407297524778554,6479472994213736597322939815331596128853683,0:-6682875845502058516696476246738893653632237
+sub:1472434831082398237848463668763914130244321191790,749284377551792267939683738695982222675701748529,0:723150453530605969908779930067931907568619443261
+sub:21819548957613983312659642613368102599157263541546,-43027293878272366259573611249912277474953128041,0:21862576251492255678919216224618014876632216669587
+sub:79183581106215686052084319942513882987033006034916,395676242411723933204666672941564134969621059,0:79183185429973274328151115275840941422898036413857
+sub:8848994582532139477750176043869310148875814,308406836916867466802062976742038687492470522689,0:-308397987922284934662585226565994818182321646875
+sub:7723560617201337569325102213658726205516718762753,10703682032080071751681616104703726510312121990,0:7712856935169257497573420597554022479006406640763
+sub:57399920075594463974650254762286091360205308040447,7737623533444627764626187063734986201237515268274,0:49662296542149836210024067698551105158967792772173
+sub:9235227695889244745982433565536373274090597220112,107148050059803991302004419466765330676586504,0:9235120547839184941991131561116906508759920633608
+sub:-4983756542035372848701023851198318990123574220609,-6542643049007414884687990348404270219346342352782197,0:6537659292465379511839289324553071900356218778561588
+sub:567419840932221417516346055492012551836180868531246,33746605794257306032350927932072975156967743676747,0:533673235137964111483995127559939576679213124854499
+sub:587649861585950611495201008010198217521972105575,887181300999163339932116937542961612984777530930,0:-299531439413212728436915929532763395462805425355
+sub:7453222478591891189413329402038211767394218016685,2017672006030135323721939597399603743488046383,0:7451204806585861054089607462440812163650729970302
+sub:2861829900660252465253636986401989994945337,773601832041130668133623108987574604308317806,0:-770740002140470415668369472001172614313372469
+sub:1854813068723965360605974071849448846065646688997753,-1779594647650002771086955563648126785119135484216483,0:3634407716373968131692929635497575631184782173214236
+sub:92477926938178288909943789222630295714892817851483,-9993806749512159715432826828952487671606121447735045,0:10086284676450338004342770618175117967321014265586528
+sub:180006337772988467709872310927140175108921733,2381572659355146492539589222943064206470713510957947,0:-2381572479348808719551121513070753279330538402036214
+sub:-8062115630203258999893376666703748484646367,-242384162973621030696116727652753612307623848798,0:242376100857990827437116834276086908559139202431
+sub:-9512092783939545330832128518113211511839319679,51817273821892700393156339701080192019872355095563,0:-51826785914676639938487171829598305231384194415242
+sub:95014753687636191420633875239958137975948173417195,-3085034910995602744319197683314962939217430996273791,0:3180049664683238935739831558554921077193379169690986
+sub:-851020909203213144832385221818295668814907441557232,920708095345140363620526592235073155935947208,0:-851021829911308489972748842344887903888063377504440
+sub:57322816917914786923271397439113286785049794499,375876690150945835847772932354648419953665427305,0:-318553873233031048924501534915535133168615632806
+sub:31393149038789273525817858949583645513566324353,414359836823939404881738593288787821854173,0:31392734678952449586412977210990356725744470180
+sub:77504028676487775641669635436308236988049655601524,181344091581225499628551847769549638986540093069,0:77322684584906550142041083588538687349063115508455
+sub:98633986434584756460936637580630245052082529240,4571853594019360336499761737542755082748090242,0:94062132840565396124436875843087489969334438998
+sub:72702371263558464947877213929280953160835791,336826520924373293318758608698133996765552613,0:-264124149660814828370881394768853043604716822
+sub:790131994620824397445459877738169154533174191,3152340776901124584130874954251376174718487427033,0:-3151550644906503759733429494373638005563954252842
+sub:-9550173574955362798449947158209546914492142849353,-54424792605728662879926674617913575370555620507,0:-9495748782349634135570020483591633339121587228846
+sub:94354150013483998466350999623761463016719477838,6188045953454972757543729666811730031705853499240,0:-6093691803441488759077378667187968568689134021402
+sub:3939113274773256610453330771473753217221500577791591,-8856764963107169782992507920019475780655171681871327,0:12795878237880426393445838691493228997876672259662918
+sub:2660941406633181818791417317975166457527878033652214,7055550945359964654212545682444924769432938191323615,0:-4394609538726782835421128364469758311905060157671401
+sub:6672381018209518975788815573873682181604983076,69748594953382081761188754597777837110112667,0:6602632423256136894027626819275904344494870409
+sub:-22928680073391300326697730831966862930951563902710,-36030604459777331413643572771813761886932316,0:-22928644042786840549366317188394091117189676970394
+sub:906731248248897060644189710812453469279110754543,-41959270679040328466239441893560854573456943089818,0:42866001927289225526883631604373308042736053844361
+sub:-70638227944710922429439115847001418432478750483,760914797512164822868407393497280368562831931857,0:-831553025456875745297846509344281786995310682340
+sub:-216358205244444335173319801401182209472584639,998326193886993948549118716632444642265383767831852,0:-998326410245199192993453889952246043447593240416491
+sub:9580122909801568750668900466947122420236232215529435,-62027973553309464740272784879673114659231909,0:9580122971829542303978365207219907299909346874761344
+sub:622693558963818873312878405559947227488964435,3981112093580815021150239981188100077575880890208,0:-3980489400021851202276927102782540130348391925773
+sub:866815675276233673264562843306494664048668452463644611,71519824955354947547025359232296671791960617075,0:866815603756408717909615296281135431751996660503027536
+sub:-6687913766044745929873407959705938856856788714,-128082208096293248054363272445011912033353379,0:-6559831557948452681819044687260926944823435335
+sub:6533704846133682195298434566037164357331105933,-9099620103006618056421372601941016491284861199065,0:9106153807852751738616671036507053655642192304998
+sub:4119542544028390490425044803879052308401738542548112,-20834003332412447609236300940967058715737799257,0:4119563378031722902872654040179993275460454280347369
+sub:-13158459479990345059531702133456996581106330236513,888807402238789998415182036488079992896567250394,0:-14047266882229135057946884169945076574002897486907
+sub:986374598296880992789870555481914795958300865,36115966024290721654021137035289387632631652243,0:-35129591425993840661231266479807472836673351378
+sub:60328360173152774817583105641423657510833102534,806537457680548774367999519005704564118620169512120612,0:-806537397352188601215224701422598922694962658679018078
+sub:8497710798125734752308241652761644166763994003249,2232134954790237265184644308782501409978670104200558,0:-2223637243992111530432336067129739765811906110197309
+sub:-66833280768590802448180039862748595225905660580,8736830538198277449921336865075351529251534384,0:-75570111306789079898101376727823946755157194964
+sub:912827735433629466385516382081400733023462641070447,4902935580754276432455992085105349174803805305833,0:907924799852875189953060389996295383848658835764614
+sub:5478598360832354100644271821080131609231404518792,-47055673068764638632714990426082071032104852775171,0:52534271429596992733359262247162202641336257293963
+sub:7690586776927788135745843200669172025110973236,384324896599663253158847925223211417882480709853337445,0:-384324888909076476231059789477368217213308684742364209
+sub:983884777941532996194149884936915312060876070737,518287984800732830855502265279223067978197266689047,0:-517304100022791297859308115394286152666136390618310
+sub:-954694380473047886020997568695000343640652324258341,14189460325400480062958182003318094361774366261792942,0:-15144154705873527948979179572013094705415018586051283
+sub:61441847820605789319902797573300129174741870859,-56353161438453661015964270802670942459168904316247488,0:56353222880301481621753590705468515759298079058118347
+sub:840900363013208299376170217559531949250066389223,-518733806293446093467395721640110032406740773472,0:1359634169306654392843565939199641981656807162695
+sub:2801043712260244666215482898915857882171271259,30068822738933846329923273175088581474609748837369043,0:-30068819937890134069678606959605682558751866666097784
+sub:39332562720628190237986833106169417514936299004,3977882056567658721057988043991788532782214317,0:35354680664060531516928845062177628982154084687
+sub:4875943313527670330837641575224800871607771346650,3006293236431797162023390328257380215745687023197,0:1869650077095873168814251246967420655862084323453
+sub:1046076579612442168236157596521887526129291572,56509310551736435818443805857748077305452153240874241,0:-56509309505659856206001637621590480783564627111582669
+sub:68801970722430443700036017990845232711747541145506,3921528808796839431326261733514349542141553429,0:68798049193621646860604691729111718362205399592077
+sub:7996124256938877464175310613395477260421185912077919187,43920453269964575011284701085185099530091428989544,0:7996080336485607499600299328694392075321655820648929643
+sub:437847871205482940383237227334352005149025155566700,8912640649325787853768245140880891930970131371688993,0:-8474792778120304913385007913546539925821106216122293
+sub:-189562142066164910097303467426752455631983999971824429,-3126396058243394757216280555044878821697145366839147,0:-186435746007921515340087186871707576810286854604985282
+sub:3738151126960474749651813623570168405472279315305,16849954488569956342093577361010810357803346759,0:3721301172471904793309720046209157595114475968546
+sub:326436788465045244627154191800265908625864556666530,8436920985951650690723103995113757167828613977782053802,0:-8436594549163185645478476840921956901919988113225387272
+sub:73862903715165018158730950116899815638213415384,3605176405676828750083989599730691253025429971416,0:-3531313501961663731925258649613791437387216556032
+sub:-98508500558610553174664717035831451337440647751,-85349349113075502208578338510421486004026291637018909,0:85349250604574943598025163845704450172574954196371158
+sub:-3958479771038348317047929281014493361412362156,74460379620572355406333334733218930851102604423,0:-78418859391610703723381264014233424212514966579
+sub:-2678832891454610091209266352796918435982227896,844180754012069973260601080737112141842619632733391282,0:-844180756690902864715211171946378494639538068715619178
+sub:62145977984087344899814827854294051292745009920192834974,7334739588662979743633482328597512684449095879737,0:62145970649347756236835084220811722695232325471096955237
+sub:829628512088735025241917875963770566118880397874,2778273578473650916716745944557448674527619910366636167,0:-2778272748845138827981720702639572710757053791486238293
+sub:5475358208178590127449325322332321821544579907242021829,5101549647265375935536396006666544834314249747938912445,0:373808560913214191912929315665776987230330159303109384
+sub:-327933746445993810109526304208281604193537699541388,-17513330151263794083025328269239503268164355683299,0:-310420416294730016026500975939042100925373343858089
+sub:-97299271106272768099051589856225693996221199008328,-683640181471185906440394924792222282513250833654408,0:586340910364913138341343334935996588517029634646080
+sub:81950415706753285772469335186046579994901810195099988,-695576496751235568817818414861599429774724685935,0:81951111283250037008038153004461441594331584919785923
+sub:11733022337838616680086438101577803026869925229236251633,4209981603742836477443590186310139108935024708250714,0:11728812356234873843608994511391492887760990204528000919
+sub:2993252088056118669505330045592351552378298855615136540,12751727236236955721686048352301817814151141431,0:2993252075304391433268374323906303200076481041463995109
+sub:39376759077330221210471049201931709948853198615,-9493608874721279041170835115951049053361083855467392,0:9493648251480356371392045587000250985071032708666007
+sub:-5280130155085387575883303159292113846385931782810769147,-1019810672320943407741389860781837676645351883469636964,0:-4260319482764444168141913298510276169740579899341132183
+sub:8457922806422768126334853404146638292374687915778812,995127687303275765352581834049367391219012453856914,0:7462795119119492360982271570097270901155675461921898
+sub:34992662458077134231839550916665303135384048742,-8152964279502937641561776276851678598174407814,0:43145626737580071873401327193516981733558456556
+sub:8237492058118191763481523977841344753346311488313,1647118892275027900093320780430922273315158677508003654,0:-1647110654782969781901557298906944431970405331196515341
+sub:-440042339580320057764506833117106015591230779324161,513962930617733479729549861446740257284856596728706,0:-954005270198053537494056694563846272876087376052867
+sub:34635151931992497392391616758693644900635250427499823,287128980133325949899403223688828310849990578079457307,0:-252493828201333452507011606930134665949355327651957484
+sub:48138028043471938379654489799905392276347294678190375860,8955461479465751553200394404645878189278984773776867,0:48129072581992472628101289405500746398158015693416598993
+sub:7624317887859192567599023956675797189693348039462742,-973928186389609942202650295012119719585450666839535260,0:981552504277469134770249318968795516775144014878998002
+sub:775402642132715473344595954662582545794117369927872,63796684229986115177275440213147384846517231365197485,0:-63021281587853399703930844258484802300723113995269613
+sub:37362432357418646911115330814724472853415155235293,87036796847105652716376950065916449694424391617602112013,0:-87036759484673295297730038950585634969951538202446876720
+sub:-300945445086734604702237356948834421909997080585835251,86543393214880176913230280671573673375238923042066,0:-301031988479949484879150587229505995583372319508877317
+sub:-654047435982290398129267970179757606710004276417490112,86422930881746427524648992269920847889306495489,0:-654047522405221279875695494828749876630852165723985601
+sub:794552108714326403336258405676646043844624401498072689,544976653015779028031808690831373018858631899320,0:794551563737673387557230373867955212471605542866173369
+sub:-195959798494693192093817249845807727728979751653,18593677965094459754532848130637776457537309190937253673,0:-18593678161054258249226040224455026303345036919917005326
+sub:57601304615929231199752161276702979414912411756145,21951958716061857914468826747760163180070915240014675524,0:-21951901114757241985237626995598886477091500327602919379
+sub:311215074108149476976205428525338649682414980832,6243249733271681693520367645680387625166806885842687456,0:-6243249422056607585370890669474959099828157203427706624
+sub:-60089258178336658544420554675373945148810656687928409220,-940949437845306471952666460412774999437620754784474,0:-60088317228898813237948602008913532373811219067173624746
+sub:3844895658482592533059556269556968661475827694950384997,527322363491124024058755005552497077118499938802,0:3844895131160229041935532210801963108978750576450446195
+sub:-6028944995177498518136854918757906591099625985414,15888968609159402431030920451645796896759203224067431,0:-15894997554154579929549057306564554803350302850052845
+sub:996013497441974701923950607149438472739078933691,112407411020615162605964831561295393767448218127,0:883606086421359539317985775588143078971630715564
+sub:7719318511816366427665580178076378029426275595533,163667549683108101581704958685911902179912256741218,0:-155948231171291735154039378507835524150485981145685
+sub:123382564431290774896664572552493052435404643704458759934,12531798191484951858836698658135874099473672299388553,0:123370032633099289944805735853834916561305170032159371381
+sub:942048756549299165967164928739420673047263758767141,3639275805983487223033248868875293658626128636190227,0:-2697227049434188057066083940135872985578864877423086
+sub:240418823794626925772533604032962688702579243574687,4907674204394917198714890794857507854118108024516422187,0:-4907433785571122571789118261253474891429405445272847500
+sub:3950213238876863129818663666502819327768719939127457701,29991402193339371342321385670768500228753395231039352972,0:-26041188954462508212502722004265680900984675291911895271
+sub:1920667868219534801099538208015399489683153418341349572065,-233412004414149707586851107620826952570732551540827551954,0:2154079872633684508686389315636226442253885969882177124019
+sub:7784321585128756839986661147453831080387260908002873,586237266875238457979621090825032494806800315405801,0:7198084318253518382007040056628798585580460592597072
+sub:-34225848774985487393407814198681047162140030645991253741,-789489361585689258214473176784928536166156096643657,0:-34225059285623901704149599725504262233603864489894610084
+sub:-944338971240124849797024756328867740674305651345965,649970029057878269623349411694378680589331156335769959,0:-650914368029118394473146436450707548330005461987115924
+sub:25816073494421415375915233416338690441492640884943818729,764159631162282034769988362928740167840568754650018844,0:25051913863259133341145245053409950273652072130293799885
+sub:7111381553325219432932289055091214481651627513743376,7385563406175559235314072692841151936136627185182905,0:-274181852850339802381783637749937454484999671439529
+sub:-438137611853268269308435226684643695607887735487389,5824616025576441892684517623276732904299681537303913,0:-6262753637429710161992952849961376599907569272791302
+sub:-9680790659167697968786181797074343179561171865505840566,-932899327759500157755319258322165056527752927868968726,0:-8747891331408197811030862538752178123033418937636871840
+sub:567793364811051880825781313748966696400236576537363041402,-976578291468928773578542746545826341079985184892523837,0:568769943102520809599359856495512522741316561722255565239
+sub:38007779187090670273244552314378701844162920433585869254,7187767815567041059760334263355184283280579165883650238,0:30820011371523629213484218051023517560882341267702219016
+sub:9014053603553462724377168305482782158101121369010869473906,755601637469656651454003843855153366578358802242924461,0:9013298001915993067725714301638927004734543010208626549445
+
+# Small integer subtraction tests
+
+subv:3358604991,36411,0:3358568580
+subv:674222429,18986,0:674203443
+subv:-3,-29805,=1:29802
+subv:3,-61063,=1:61066
+subv:2717723,-25258,=1:2742981
+subv:394,-40508,=2:40902
+subv:4744781967,21435,0:4744760532
+subv:-14,50287,0:-50301
+subv:2197,3582,=2:-1385
+subv:-5296,38162,=2:-43458
+subv:-258774,57544,=2:-316318
+subv:7417476246,-58958,=2:7417535204
+subv:6714936,-40949,0:6755885
+subv:15862,-58672,0:74534
+subv:958081,21046,0:937035
+subv:82515,-11287,0:93802
+subv:72715,-25449,0:98164
+subv:-8346662975566,52150,0:-8346663027716
+subv:96216,-33648,=2:129864
+subv:71597071124556,40786,0:71597071083770
+subv:2795133710510,-24996,=1:2795133735506
+subv:8501300888546,1685,0:8501300886861
+subv:3877092429,45143,0:3877047286
+subv:-9123902,27698,0:-9151600
+subv:-71914098152,-49684,0:-71914048468
+subv:-5633175963555389,-13681,0:-5633175963541708
+subv:-68774492,24946,0:-68799438
+subv:2837978518,2447,=1:2837976071
+subv:9527903026793981,34045,=2:9527903026759936
+subv:-719766995836501,-14683,=1:-719766995821818
+subv:6826892934542,-9599,0:6826892944141
+subv:474765520,-36545,=2:474802065
+subv:137980222,12896,0:137967326
+subv:4124108674,61743,0:4124046931
+subv:-4977334202151,16161,0:-4977334218312
+subv:-6764356933,33130,=1:-6764390063
+subv:6639990082377605303,63220,0:6639990082377542083
+subv:68384248282,-28652,0:68384276934
+subv:-64782488650,-31866,=2:-64782456784
+subv:84126983615,63328,0:84126920287
+subv:280281352217,19756,=1:280281332461
+subv:-337730569530652702,55596,0:-337730569530708298
+subv:750462053456012,-18056,=1:750462053474068
+subv:-859984251764611,60341,0:-859984251824952
+subv:781147832162694072159,10186,0:781147832162694061973
+subv:414707731902540,13874,0:414707731888666
+subv:4749293013793395,-27594,0:4749293013820989
+subv:-476780935041195291,-51859,0:-476780935041143432
+subv:-3619074244886709,38416,=1:-3619074244925125
+subv:97855199057493,40752,0:97855199016741
+subv:777675086535345464853,9892,=2:777675086535345454961
+subv:3103441257588144,4992,0:3103441257583152
+subv:136564148041720,53068,=2:136564147988652
+subv:-4664978338218772692212,46644,0:-4664978338218772738856
+subv:235299291342838779459,27155,=1:235299291342838752304
+subv:45286262426870,28782,0:45286262398088
+subv:422289955984703063,27236,=2:422289955984675827
+subv:-6379926829937406097,-63773,0:-6379926829937342324
+subv:830836702855178852980658,-61406,=1:830836702855178853042064
+subv:4000074483936047411,59077,=2:4000074483935988334
+subv:1622930723651719839167208,63514,0:1622930723651719839103694
+subv:532951482400205192926144,57956,0:532951482400205192868188
+subv:148980429628794512840,63138,=2:148980429628794449702
+subv:-9890648040727702186064,-46766,=1:-9890648040727702139298
+subv:-10934480308082214085686,63224,=2:-10934480308082214148910
+subv:355809482274653919711872,32446,0:355809482274653919679426
+subv:-33926193961684655624,11389,=2:-33926193961684667013
+subv:-7186493575578045620,15528,=1:-7186493575578061148
+subv:34706765155128499193360248,83,=1:34706765155128499193360165
+subv:4328479538590740673745630,14623,0:4328479538590740673731007
+subv:-963713498430054741223932789,30239,0:-963713498430054741223963028
+subv:-831264221344401371,39516,0:-831264221344440887
+subv:318721481318817753735405,52833,0:318721481318817753682572
+subv:-62693787119478234447,27553,=1:-62693787119478262000
+subv:-7016655669525046977522194886,32638,=2:-7016655669525046977522227524
+subv:608134301020199755515,29066,0:608134301020199726449
diff --git a/polly/lib/External/isl/imath/tests/test.bc b/polly/lib/External/isl/imath/tests/test.bc
new file mode 100644
index 00000000000..f067be8c483
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/test.bc
@@ -0,0 +1,155 @@
+/* e(a, b, m) := a^b (mod m) */
+define e(a, b, m) {
+ auto s, sb;
+
+ sb = obase; obase = 16;
+ s = 1;
+ while(b != 0) {
+ if((b % 2) == 1) {
+ s = (s * a) % m;
+ }
+ b /= 2;
+ a = (a * a) % m;
+ }
+ obase = sb;
+ return (s);
+}
+
+/* g(a, b) := (a, b) */
+define g(a, b) {
+ auto r;
+
+ while(b != 0) {
+ r = a % b;
+ a = b;
+ b = r;
+ }
+ if(a < 0) {
+ return(-a);
+ } else {
+ return(a);
+ }
+}
+
+define a(x) {
+ if(x < 0) {
+ return (-x);
+ } else {
+ return (x);
+ }
+}
+
+xgu = 0; xgv = 0;
+define x(a, b) {
+ auto u, v, x, y, t, r;
+
+ if(a(b) > a(a)) {
+ t = b; b = a; a = t; r = 1;
+ } else {
+ r = 0;
+ }
+
+ u = 1; v = 0;
+ x = 0; y = 1;
+
+ while(b != 0) {
+ t = a / b;
+
+ a = a - (t * b);
+ v = v - (t * y);
+ u = u - (t * x);
+
+ if(a(a) < a(b)) {
+ t = a; a = b; b = t;
+ t = v; v = y; y = t;
+ t = u; u = x; x = t;
+ }
+ }
+
+ if(r) {
+ xgu = v; xgv = u;
+ } else {
+ xgu = u; xgv = v;
+ }
+
+ if(a < 0) {
+ return (-a);
+ } else {
+ return (a);
+ }
+}
+
+define i(a, m) {
+ auto c;
+
+ c = x(a, m);
+ if(c != 1)
+ return(0);
+
+ return ((xgu + m) % m);
+}
+
+scale = 0
+rand_modulus = 2860385147
+rand_base = 129
+rand_seed = 10342799
+
+define srand(s) {
+ rand_seed = s;
+}
+
+define rand(n) {
+ auto r;
+
+ r = (rand_seed * rand_base) % rand_modulus;
+ rand_seed = r;
+ return(r % n);
+}
+
+define rand_digits(k) {
+ auto s;
+
+ s = 0;
+ while(k > 0) {
+ s = (s * 10) + rand(10);
+ k = k - 1;
+ }
+
+ return(s);
+}
+
+define rval(ndigits, probneg) {
+ auto x;
+ x = rand_digits(ndigits);
+ if(probneg > 0 && rand(100) < probneg)
+ x = x * -1;
+ return(x);
+}
+
+for(i = 2; i < 100; i += 4) {
+ value = rand_digits(i);
+ obase = 256;
+ print "readuns:", value;
+ obase = 10;
+ print ":", value, "\n"
+}
+
+/*
+for(i = 2; i < 100; i += 4) {
+ for(j = 0; j < 2; ++j) {
+ ndig = rand(7);
+ base = rval(ndig, 20);
+ expt = rand_digits(i);
+ mod = rand_digits(i);
+
+ result = e(base, expt, mod);
+ if(result < 0) {
+ result = result + mod;
+ }
+ print "emodbv:", base, ",", expt, ",", mod, ",0:", result, "\n";
+ print "emodbv:", base, ",", expt, ",", mod, ",=2:", result, "\n";
+ print "emodbv:", base, ",", expt, ",", mod, ",=3:", result, "\n";
+ }
+}
+*/
+halt
diff --git a/polly/lib/External/isl/imath/tests/test.sh b/polly/lib/External/isl/imath/tests/test.sh
new file mode 100755
index 00000000000..d1ced881e34
--- /dev/null
+++ b/polly/lib/External/isl/imath/tests/test.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+##
+## Name: test.sh
+## Purpose: Run test suites for IMath library.
+## Author: M. J. Fromberger <http://spinning-yarns.org/michael/>
+##
+
+if [ ! -f ../imtest ] ; then
+ echo "I can't find the imath test driver 'imtest', did you build it?"
+ echo "I can't proceed with the unit tests until you do so, sorry."
+ exit 1
+fi
+
+echo "-- Running all available unit tests"
+../imtest *.t | grep -v OK
+
+echo ""
+echo "-- Running test to compute 1024 decimal digits of pi"
+if [ ! -f ../pi ] ; then
+ echo "I can't find the pi computing program, did you build it?"
+ echo "I can't proceed with the pi test until you do so, sorry."
+ exit 1
+fi
+
+tempfile="/tmp/pi.1024.$$"
+
+../pi 1024 | tr -d '\r\n' > ${tempfile}
+if cmp -s ${tempfile} ./pi1024.txt ; then
+ echo " PASSED 1024 digits"
+else
+ echo " FAILED"
+ echo "Obtained:"
+ cat ${tempfile}
+ echo "Expected:"
+ cat ./pi1024.txt
+fi
+rm -f ${tempfile}
+
+tempfile="/tmp/pi.1698.$$"
+
+echo "-- Running test to compute 1698 hexadecimal digits of pi"
+
+../pi 1698 16 | tr -d '\r\n' > ${tempfile}
+if cmp -s ${tempfile} ./pi1698-16.txt ; then
+ echo " PASSED 1698 digits"
+else
+ echo " FAILED"
+ echo "Obtained:"
+ cat ${tempfile}
+ echo "Expected:"
+ cat ./pi1698-16.txt
+fi
+rm -f ${tempfile}
+
+tempfile="/tmp/pi.1500.$$"
+
+echo "-- Running test to compute 1500 decimal digits of pi"
+
+../pi 1500 10 | tr -d '\r\n' > ${tempfile}
+if cmp -s ${tempfile} ./pi1500-10.txt ; then
+ echo " PASSED 1500 digits"
+else
+ echo " FAILED"
+ echo "Obtained:"
+ cat ${tempfile}
+ echo "Expected:"
+ cat ./pi1500-10.txt
+fi
+rm -f ${tempfile}
+
+echo "-- Running regression tests"
+
+for bug in bug-swap ; do
+ ../${bug}
+done
+
+exit 0
diff --git a/polly/lib/External/isl/imath_wrap/gmp_compat.c b/polly/lib/External/isl/imath_wrap/gmp_compat.c
new file mode 100644
index 00000000000..a116913a44c
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/gmp_compat.c
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/gmp_compat.c"
diff --git a/polly/lib/External/isl/imath_wrap/gmp_compat.h b/polly/lib/External/isl/imath_wrap/gmp_compat.h
new file mode 100644
index 00000000000..11a332daf54
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/gmp_compat.h
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/gmp_compat.h"
diff --git a/polly/lib/External/isl/imath_wrap/imath.c b/polly/lib/External/isl/imath_wrap/imath.c
new file mode 100644
index 00000000000..c4e35c1ac8b
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/imath.c
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/imath.c"
diff --git a/polly/lib/External/isl/imath_wrap/imath.h b/polly/lib/External/isl/imath_wrap/imath.h
new file mode 100644
index 00000000000..12029ce5b67
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/imath.h
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/imath.h"
diff --git a/polly/lib/External/isl/imath_wrap/imrat.c b/polly/lib/External/isl/imath_wrap/imrat.c
new file mode 100644
index 00000000000..0c7feaaeadb
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/imrat.c
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/imrat.c"
diff --git a/polly/lib/External/isl/imath_wrap/imrat.h b/polly/lib/External/isl/imath_wrap/imrat.h
new file mode 100644
index 00000000000..c9983900a45
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/imrat.h
@@ -0,0 +1,2 @@
+#include "wrap.h"
+#include "../imath/imrat.h"
diff --git a/polly/lib/External/isl/imath_wrap/wrap.h b/polly/lib/External/isl/imath_wrap/wrap.h
new file mode 100644
index 00000000000..f68e50d20f4
--- /dev/null
+++ b/polly/lib/External/isl/imath_wrap/wrap.h
@@ -0,0 +1,172 @@
+#ifndef ISL_IMATH_WRAP
+#define ISL_IMATH_WRAP
+
+#define MP_BADARG ISL_MP_BADARG
+#define MP_FALSE ISL_MP_FALSE
+#define MP_MEMORY ISL_MP_MEMORY
+#define MP_MINERR ISL_MP_MINERR
+#define MP_NEG ISL_MP_NEG
+#define MP_OK ISL_MP_OK
+#define MP_RANGE ISL_MP_RANGE
+#define MP_TRUE ISL_MP_TRUE
+#define MP_TRUNC ISL_MP_TRUNC
+#define MP_UNDEF ISL_MP_UNDEF
+#define MP_ZPOS ISL_MP_ZPOS
+
+#define impq_canonicalize isl_impq_canonicalize
+#define impq_clear isl_impq_clear
+#define impq_cmp isl_impq_cmp
+#define impq_denref isl_impq_denref
+#define impq_get_str isl_impq_get_str
+#define impq_init isl_impq_init
+#define impq_mul isl_impq_mul
+#define impq_numref isl_impq_numref
+#define impq_set isl_impq_set
+#define impq_set_str isl_impq_set_str
+#define impq_set_ui isl_impq_set_ui
+#define impq_sgn isl_impq_sgn
+#define impz_abs isl_impz_abs
+#define impz_add isl_impz_add
+#define impz_addmul isl_impz_addmul
+#define impz_add_ui isl_impz_add_ui
+#define impz_cdiv_q isl_impz_cdiv_q
+#define impz_clear isl_impz_clear
+#define impz_cmp isl_impz_cmp
+#define impz_cmpabs isl_impz_cmpabs
+#define impz_cmp_si isl_impz_cmp_si
+#define impz_divexact isl_impz_divexact
+#define impz_divexact_ui isl_impz_divexact_ui
+#define impz_divisible_p isl_impz_divisible_p
+#define impz_export isl_impz_export
+#define impz_fdiv_q isl_impz_fdiv_q
+#define impz_fdiv_q_ui isl_impz_fdiv_q_ui
+#define impz_fdiv_r isl_impz_fdiv_r
+#define impz_gcd isl_impz_gcd
+#define impz_get_si isl_impz_get_si
+#define impz_get_str isl_impz_get_str
+#define impz_get_ui isl_impz_get_ui
+#define impz_import isl_impz_import
+#define impz_init isl_impz_init
+#define impz_lcm isl_impz_lcm
+#define impz_mul isl_impz_mul
+#define impz_mul_2exp isl_impz_mul_2exp
+#define impz_mul_ui isl_impz_mul_ui
+#define impz_neg isl_impz_neg
+#define impz_pow_ui isl_impz_pow_ui
+#define impz_set isl_impz_set
+#define impz_set_si isl_impz_set_si
+#define impz_set_str isl_impz_set_str
+#define impz_set_ui isl_impz_set_ui
+#define impz_sgn isl_impz_sgn
+#define impz_sizeinbase isl_impz_sizeinbase
+#define impz_sub isl_impz_sub
+#define impz_submul isl_impz_submul
+#define impz_sub_ui isl_impz_sub_ui
+#define impz_swap isl_impz_swap
+#define impz_tdiv_q isl_impz_tdiv_q
+#define mp_error_string isl_mp_error_string
+#define mp_int_abs isl_mp_int_abs
+#define mp_int_add isl_mp_int_add
+#define mp_int_add_value isl_mp_int_add_value
+#define mp_int_alloc isl_mp_int_alloc
+#define mp_int_binary_len isl_mp_int_binary_len
+#define mp_int_clear isl_mp_int_clear
+#define mp_int_compare isl_mp_int_compare
+#define mp_int_compare_unsigned isl_mp_int_compare_unsigned
+#define mp_int_compare_uvalue isl_mp_int_compare_uvalue
+#define mp_int_compare_value isl_mp_int_compare_value
+#define mp_int_compare_zero isl_mp_int_compare_zero
+#define mp_int_copy isl_mp_int_copy
+#define mp_int_count_bits isl_mp_int_count_bits
+#define mp_int_div isl_mp_int_div
+#define mp_int_divisible_value isl_mp_int_divisible_value
+#define mp_int_div_pow2 isl_mp_int_div_pow2
+#define mp_int_div_value isl_mp_int_div_value
+#define mp_int_egcd isl_mp_int_egcd
+#define mp_int_expt isl_mp_int_expt
+#define mp_int_expt_full isl_mp_int_expt_full
+#define mp_int_exptmod isl_mp_int_exptmod
+#define mp_int_exptmod_bvalue isl_mp_int_exptmod_bvalue
+#define mp_int_exptmod_evalue isl_mp_int_exptmod_evalue
+#define mp_int_exptmod_known isl_mp_int_exptmod_known
+#define mp_int_expt_value isl_mp_int_expt_value
+#define mp_int_free isl_mp_int_free
+#define mp_int_gcd isl_mp_int_gcd
+#define mp_int_init isl_mp_int_init
+#define mp_int_init_copy isl_mp_int_init_copy
+#define mp_int_init_size isl_mp_int_init_size
+#define mp_int_init_uvalue isl_mp_int_init_uvalue
+#define mp_int_init_value isl_mp_int_init_value
+#define mp_int_invmod isl_mp_int_invmod
+#define mp_int_is_pow2 isl_mp_int_is_pow2
+#define mp_int_lcm isl_mp_int_lcm
+#define mp_int_mod isl_mp_int_mod
+#define mp_int_mul isl_mp_int_mul
+#define mp_int_mul_pow2 isl_mp_int_mul_pow2
+#define mp_int_mul_value isl_mp_int_mul_value
+#define mp_int_neg isl_mp_int_neg
+#define mp_int_read_binary isl_mp_int_read_binary
+#define mp_int_read_cstring isl_mp_int_read_cstring
+#define mp_int_read_string isl_mp_int_read_string
+#define mp_int_read_unsigned isl_mp_int_read_unsigned
+#define mp_int_redux_const isl_mp_int_redux_const
+#define mp_int_root isl_mp_int_root
+#define mp_int_set_uvalue isl_mp_int_set_uvalue
+#define mp_int_set_value isl_mp_int_set_value
+#define mp_int_sqr isl_mp_int_sqr
+#define mp_int_string_len isl_mp_int_string_len
+#define mp_int_sub isl_mp_int_sub
+#define mp_int_sub_value isl_mp_int_sub_value
+#define mp_int_swap isl_mp_int_swap
+#define mp_int_to_binary isl_mp_int_to_binary
+#define mp_int_to_int isl_mp_int_to_int
+#define mp_int_to_string isl_mp_int_to_string
+#define mp_int_to_uint isl_mp_int_to_uint
+#define mp_int_to_unsigned isl_mp_int_to_unsigned
+#define mp_int_unsigned_len isl_mp_int_unsigned_len
+#define mp_int_zero isl_mp_int_zero
+#define mp_rat_abs isl_mp_rat_abs
+#define mp_rat_add isl_mp_rat_add
+#define mp_rat_add_int isl_mp_rat_add_int
+#define mp_rat_alloc isl_mp_rat_alloc
+#define mp_rat_clear isl_mp_rat_clear
+#define mp_rat_compare isl_mp_rat_compare
+#define mp_rat_compare_unsigned isl_mp_rat_compare_unsigned
+#define mp_rat_compare_value isl_mp_rat_compare_value
+#define mp_rat_compare_zero isl_mp_rat_compare_zero
+#define mp_rat_copy isl_mp_rat_copy
+#define mp_rat_decimal_len isl_mp_rat_decimal_len
+#define mp_rat_denom isl_mp_rat_denom
+#define mp_rat_denom_ref isl_mp_rat_denom_ref
+#define mp_rat_div isl_mp_rat_div
+#define mp_rat_div_int isl_mp_rat_div_int
+#define mp_rat_expt isl_mp_rat_expt
+#define mp_rat_free isl_mp_rat_free
+#define mp_rat_init isl_mp_rat_init
+#define mp_rat_init_copy isl_mp_rat_init_copy
+#define mp_rat_init_size isl_mp_rat_init_size
+#define mp_rat_is_integer isl_mp_rat_is_integer
+#define mp_rat_mul isl_mp_rat_mul
+#define mp_rat_mul_int isl_mp_rat_mul_int
+#define mp_rat_neg isl_mp_rat_neg
+#define mp_rat_numer isl_mp_rat_numer
+#define mp_rat_numer_ref isl_mp_rat_numer_ref
+#define mp_rat_read_cdecimal isl_mp_rat_read_cdecimal
+#define mp_rat_read_cstring isl_mp_rat_read_cstring
+#define mp_rat_read_decimal isl_mp_rat_read_decimal
+#define mp_rat_read_string isl_mp_rat_read_string
+#define mp_rat_read_ustring isl_mp_rat_read_ustring
+#define mp_rat_recip isl_mp_rat_recip
+#define mp_rat_reduce isl_mp_rat_reduce
+#define mp_rat_set_uvalue isl_mp_rat_set_uvalue
+#define mp_rat_set_value isl_mp_rat_set_value
+#define mp_rat_sign isl_mp_rat_sign
+#define mp_rat_string_len isl_mp_rat_string_len
+#define mp_rat_sub isl_mp_rat_sub
+#define mp_rat_sub_int isl_mp_rat_sub_int
+#define mp_rat_to_decimal isl_mp_rat_to_decimal
+#define mp_rat_to_ints isl_mp_rat_to_ints
+#define mp_rat_to_string isl_mp_rat_to_string
+#define mp_rat_zero isl_mp_rat_zero
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/aff.h b/polly/lib/External/isl/include/isl/aff.h
new file mode 100644
index 00000000000..4ed02854d1c
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/aff.h
@@ -0,0 +1,663 @@
+#ifndef ISL_AFF_H
+#define ISL_AFF_H
+
+#include <isl/local_space.h>
+#include <isl/printer.h>
+#include <isl/set_type.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/multi.h>
+#include <isl/union_set_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls);
+__isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
+ __isl_take isl_val *val);
+__isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls);
+
+__isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff);
+__isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff);
+
+isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff);
+
+int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type);
+int isl_aff_involves_dims(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff);
+__isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff);
+__isl_give isl_local_space *isl_aff_get_domain_local_space(
+ __isl_keep isl_aff *aff);
+__isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff);
+
+const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff);
+__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos);
+int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos);
+__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff);
+__isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v);
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v);
+__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+int isl_aff_is_cst(__isl_keep isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+
+int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type,
+ const char *name);
+
+int isl_aff_plain_is_equal(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2);
+int isl_aff_plain_is_zero(__isl_keep isl_aff *aff);
+int isl_aff_is_nan(__isl_keep isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos);
+
+__isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *mod);
+
+__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_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,
+ __isl_take isl_aff *aff2);
+
+__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f);
+__isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v);
+
+__isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
+ __isl_take isl_space *model);
+
+__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
+ __isl_take isl_set *context);
+__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
+ __isl_take isl_set *context);
+
+__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
+ __isl_take isl_multi_aff *ma);
+
+__isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff);
+__isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff);
+
+__isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+
+__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);
+void isl_aff_dump(__isl_keep isl_aff *aff);
+
+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_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,
+ __isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(
+ __isl_take isl_local_space *ls);
+__isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls);
+__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
+ __isl_take isl_val *v);
+
+__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set);
+
+const char *isl_pw_aff_get_dim_name(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+int isl_pw_aff_has_dim_id(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_pw_aff_get_dim_id(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_pw_aff *isl_pw_aff_set_dim_id(__isl_take isl_pw_aff *pma,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+
+int isl_pw_aff_find_dim_by_name(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type, const char *name);
+
+int isl_pw_aff_is_empty(__isl_keep isl_pw_aff *pwaff);
+int isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa);
+int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
+ __isl_keep isl_pw_aff *pa2);
+int isl_pw_aff_plain_is_equal(__isl_keep isl_pw_aff *pwaff1,
+ __isl_keep isl_pw_aff *pwaff2);
+int isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2);
+
+__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_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+
+__isl_give isl_pw_aff *isl_pw_aff_copy(__isl_keep isl_pw_aff *pwaff);
+__isl_null isl_pw_aff *isl_pw_aff_free(__isl_take isl_pw_aff *pwaff);
+
+unsigned isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff, enum isl_dim_type type);
+int isl_pw_aff_involves_dims(__isl_keep isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff);
+
+__isl_give isl_pw_aff *isl_pw_aff_align_params(__isl_take isl_pw_aff *pwaff,
+ __isl_take isl_space *model);
+
+int isl_pw_aff_has_tuple_id(__isl_keep isl_pw_aff *pa, enum isl_dim_type type);
+__isl_give isl_id *isl_pw_aff_get_tuple_id(__isl_keep isl_pw_aff *pa,
+ enum isl_dim_type type);
+__isl_give isl_pw_aff *isl_pw_aff_set_tuple_id(__isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_pw_aff *isl_pw_aff_reset_tuple_id(__isl_take isl_pw_aff *pa,
+ enum isl_dim_type type);
+
+__isl_give isl_set *isl_pw_aff_params(__isl_take isl_pw_aff *pwa);
+__isl_give isl_set *isl_pw_aff_domain(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_from_range(__isl_take isl_pw_aff *pwa);
+
+__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__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_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,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_neg(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
+ __isl_take isl_val *mod);
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+
+__isl_give isl_pw_aff *isl_pw_aff_intersect_params(__isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
+__isl_give isl_pw_aff *isl_pw_aff_intersect_domain(__isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
+
+__isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
+ __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale_val(__isl_take isl_pw_aff *pa,
+ __isl_take isl_val *v);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down_val(__isl_take isl_pw_aff *pa,
+ __isl_take isl_val *f);
+
+__isl_give isl_pw_aff *isl_pw_aff_insert_dims(__isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_move_dims(__isl_take isl_pw_aff *pa,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_drop_dims(__isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_pw_aff *isl_pw_aff_coalesce(__isl_take isl_pw_aff *pwqp);
+__isl_give isl_pw_aff *isl_pw_aff_gist(__isl_take isl_pw_aff *pwaff,
+ __isl_take isl_set *context);
+__isl_give isl_pw_aff *isl_pw_aff_gist_params(__isl_take isl_pw_aff *pwaff,
+ __isl_take isl_set *context);
+
+__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_aff(
+ __isl_take isl_pw_aff *pa, __isl_take isl_multi_aff *ma);
+__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_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
+ __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa);
+
+int isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
+int isl_pw_aff_foreach_piece(__isl_keep isl_pw_aff *pwaff,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_aff *aff,
+ void *user), void *user);
+
+__isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff);
+
+__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff);
+
+__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2);
+
+__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);
+void isl_pw_aff_dump(__isl_keep isl_pw_aff *pwaff);
+
+__isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list);
+__isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list);
+
+__isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2);
+
+ISL_DECLARE_MULTI(aff)
+
+__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);
+__isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space);
+__isl_give isl_multi_aff *isl_multi_aff_project_out_map(
+ __isl_take isl_space *space, enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
+ __isl_take isl_space *space, __isl_take isl_multi_val *mv);
+
+__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_sub(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+
+__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,
+ __isl_take isl_set *context);
+
+__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
+ __isl_give isl_local_space **ls);
+
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+ __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
+
+__isl_give isl_multi_aff *isl_multi_aff_move_dims(__isl_take isl_multi_aff *ma,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+__isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2);
+
+__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_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);
+
+ISL_DECLARE_MULTI(pw_aff)
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
+ __isl_take isl_space *space);
+__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_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+__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,
+ __isl_take isl_multi_aff *maff);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_copy(
+ __isl_keep isl_pw_multi_aff *pma);
+__isl_null isl_pw_multi_aff *isl_pw_multi_aff_free(
+ __isl_take isl_pw_multi_aff *pma);
+
+unsigned isl_pw_multi_aff_dim(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
+ __isl_keep isl_pw_multi_aff *pma, int pos);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
+ __isl_take isl_pw_multi_aff *pma, unsigned pos,
+ __isl_take isl_pw_aff *pa);
+
+isl_ctx *isl_pw_multi_aff_get_ctx(__isl_keep isl_pw_multi_aff *pma);
+__isl_give isl_space *isl_pw_multi_aff_get_domain_space(
+ __isl_keep isl_pw_multi_aff *pma);
+__isl_give isl_space *isl_pw_multi_aff_get_space(
+ __isl_keep isl_pw_multi_aff *pma);
+int isl_pw_multi_aff_has_tuple_name(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+const char *isl_pw_multi_aff_get_tuple_name(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+__isl_give isl_id *isl_pw_multi_aff_get_tuple_id(
+ __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type);
+int isl_pw_multi_aff_has_tuple_id(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_tuple_id(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_tuple_id(
+ __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type);
+
+int isl_pw_multi_aff_find_dim_by_name(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_drop_dims(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_set *isl_pw_multi_aff_domain(__isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_empty(__isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
+ __isl_take isl_set *set);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_set *domain, __isl_take isl_multi_val *mv);
+
+const char *isl_pw_multi_aff_get_dim_name(__isl_keep isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_pw_multi_aff_get_dim_id(
+ __isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type,
+ unsigned pos);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_dim_id(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+
+int isl_pw_multi_aff_plain_is_equal(__isl_keep isl_pw_multi_aff *pma1,
+ __isl_keep isl_pw_multi_aff *pma2);
+
+__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_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_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(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_val(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_val *v);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_val(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_val *v);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
+ __isl_take isl_multi_aff *ma);
+
+__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_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_give isl_pw_multi_aff *isl_pw_multi_aff_product(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_params(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_domain(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_domain_on_params(
+ __isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_align_params(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_space *model);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_coalesce(
+ __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist_params(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+
+__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_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);
+
+int isl_pw_multi_aff_foreach_piece(__isl_keep isl_pw_multi_aff *pma,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_multi_aff *maff,
+ void *user), void *user);
+
+__isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_printer *isl_printer_print_pw_multi_aff(__isl_take isl_printer *p,
+ __isl_keep isl_pw_multi_aff *pma);
+
+__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_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);
+
+
+__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_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_copy(
+ __isl_keep isl_union_pw_multi_aff *upma);
+__isl_null isl_union_pw_multi_aff *isl_union_pw_multi_aff_free(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_pw_multi_aff *pma);
+
+isl_ctx *isl_union_pw_multi_aff_get_ctx(
+ __isl_keep isl_union_pw_multi_aff *upma);
+__isl_give isl_space *isl_union_pw_multi_aff_get_space(
+ __isl_keep isl_union_pw_multi_aff *upma);
+
+unsigned isl_union_pw_multi_aff_dim(__isl_keep isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type);
+int isl_union_pw_multi_aff_find_dim_by_name(
+ __isl_keep isl_union_pw_multi_aff *upma, enum isl_dim_type type,
+ const char *name);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_coalesce(
+ __isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_gist_params(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_set *context);
+__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_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_align_params(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *model);
+
+int isl_union_pw_multi_aff_foreach_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma,
+ int (*fn)(__isl_take isl_pw_multi_aff *pma, void *user), void *user);
+__isl_give isl_pw_multi_aff *isl_union_pw_multi_aff_extract_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma, __isl_take isl_space *space);
+
+int isl_union_pw_multi_aff_plain_is_equal(
+ __isl_keep isl_union_pw_multi_aff *upma1,
+ __isl_keep isl_union_pw_multi_aff *upma2);
+
+__isl_give isl_union_set *isl_union_pw_multi_aff_domain(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__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_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);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_sub(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_val(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_val *val);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_down_val(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_val *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_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);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_intersect_params(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_set *set);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_intersect_domain(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
+ __isl_take isl_union_map *umap);
+
+__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);
+__isl_give char *isl_union_pw_multi_aff_to_str(
+ __isl_keep isl_union_pw_multi_aff *upma);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
+ __isl_take isl_space *space);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+__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);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_intersect_params(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *set);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_intersect_domain(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *domain);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
+ __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *set);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist_params(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *set);
+
+int isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
+ __isl_keep isl_multi_pw_aff *mpa2);
+
+__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_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_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);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_move_dims(
+ __isl_take isl_multi_pw_aff *pma,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__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_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma);
+
+__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(
+ __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa);
+void isl_multi_pw_aff_dump(__isl_keep isl_multi_pw_aff *mpa);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/aff_type.h b/polly/lib/External/isl/include/isl/aff_type.h
new file mode 100644
index 00000000000..ce19f1dfa18
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/aff_type.h
@@ -0,0 +1,36 @@
+#ifndef ISL_AFF_TYPE_H
+#define ISL_AFF_TYPE_H
+
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_aff;
+typedef struct isl_aff isl_aff;
+
+ISL_DECLARE_LIST(aff)
+
+struct isl_pw_aff;
+typedef struct isl_pw_aff isl_pw_aff;
+
+ISL_DECLARE_LIST(pw_aff)
+
+struct isl_multi_aff;
+typedef struct isl_multi_aff isl_multi_aff;
+
+struct isl_pw_multi_aff;
+typedef struct isl_pw_multi_aff isl_pw_multi_aff;
+
+struct isl_union_pw_multi_aff;
+typedef struct isl_union_pw_multi_aff isl_union_pw_multi_aff;
+
+struct isl_multi_pw_aff;
+typedef struct isl_multi_pw_aff isl_multi_pw_aff;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/arg.h b/polly/lib/External/isl/include/isl/arg.h
new file mode 100644
index 00000000000..896293a9fc5
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/arg.h
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_ARG_H
+#define ISL_ARG_H
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_arg_choice {
+ const char *name;
+ unsigned value;
+};
+
+struct isl_arg_flags {
+ const char *name;
+ unsigned mask;
+ unsigned value;
+};
+
+enum isl_arg_type {
+ isl_arg_end,
+ isl_arg_alias,
+ isl_arg_arg,
+ isl_arg_bool,
+ isl_arg_child,
+ isl_arg_choice,
+ isl_arg_flags,
+ isl_arg_footer,
+ isl_arg_int,
+ isl_arg_user,
+ isl_arg_long,
+ isl_arg_ulong,
+ isl_arg_str,
+ isl_arg_str_list,
+ isl_arg_version
+};
+
+struct isl_args;
+
+struct isl_arg {
+ enum isl_arg_type type;
+ char short_name;
+ const char *long_name;
+ const char *argument_name;
+ size_t offset;
+ const char *help_msg;
+#define ISL_ARG_SINGLE_DASH (1 << 0)
+#define ISL_ARG_BOOL_ARG (1 << 1)
+#define ISL_ARG_HIDDEN (1 << 2)
+ unsigned flags;
+ union {
+ struct {
+ struct isl_arg_choice *choice;
+ unsigned default_value;
+ unsigned default_selected;
+ int (*set)(void *opt, unsigned val);
+ } choice;
+ struct {
+ struct isl_arg_flags *flags;
+ unsigned default_value;
+ } flags;
+ struct {
+ unsigned default_value;
+ int (*set)(void *opt, unsigned val);
+ } b;
+ struct {
+ int default_value;
+ } i;
+ struct {
+ long default_value;
+ long default_selected;
+ int (*set)(void *opt, long val);
+ } l;
+ struct {
+ unsigned long default_value;
+ } ul;
+ struct {
+ const char *default_value;
+ } str;
+ struct {
+ size_t offset_n;
+ } str_list;
+ struct {
+ struct isl_args *child;
+ } child;
+ struct {
+ void (*print_version)(void);
+ } version;
+ struct {
+ int (*init)(void*);
+ void (*clear)(void*);
+ } user;
+ } u;
+};
+
+struct isl_args {
+ size_t options_size;
+ struct isl_arg *args;
+};
+
+#define ISL_ARGS_START(s,name) \
+ struct isl_arg name ## LIST[]; \
+ struct isl_args name = { sizeof(s), name ## LIST }; \
+ struct isl_arg name ## LIST[] = {
+#define ISL_ARGS_END \
+ { isl_arg_end } };
+
+#define ISL_ARG_ALIAS(l) { \
+ .type = isl_arg_alias, \
+ .long_name = l, \
+},
+#define ISL_ARG_ARG(st,f,a,d) { \
+ .type = isl_arg_arg, \
+ .argument_name = a, \
+ .offset = offsetof(st, f), \
+ .u = { .str = { .default_value = d } } \
+},
+#define ISL_ARG_FOOTER(h) { \
+ .type = isl_arg_footer, \
+ .help_msg = h, \
+},
+#define ISL_ARG_CHOICE(st,f,s,l,c,d,h) { \
+ .type = isl_arg_choice, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .choice = { .choice = c, .default_value = d, \
+ .default_selected = d, .set = NULL } } \
+},
+#define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h) { \
+ .type = isl_arg_choice, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .choice = { .choice = c, .default_value = d, \
+ .default_selected = ds, .set = NULL } } \
+},
+#define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h) { \
+ .type = isl_arg_choice, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .choice = { .choice = c, .default_value = d, \
+ .default_selected = ds, .set = setter } } \
+},
+#define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl) { \
+ .type = isl_arg_bool, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = o, \
+ .help_msg = h, \
+ .flags = fl, \
+ .u = { .b = { .default_value = d, .set = setter } } \
+},
+#define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl) \
+ _ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
+#define ISL_ARG_BOOL(st,f,s,l,d,h) \
+ ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
+#define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl) \
+ _ISL_ARG_BOOL_F(-1,s,l,setter,0,h,fl)
+#define ISL_ARG_PHANTOM_BOOL(s,l,setter,h) \
+ ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
+#define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl) { \
+ .type = isl_arg_int, \
+ .short_name = s, \
+ .long_name = l, \
+ .argument_name = a, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .flags = fl, \
+ .u = { .ul = { .default_value = d } } \
+},
+#define ISL_ARG_INT(st,f,s,l,a,d,h) \
+ ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
+#define ISL_ARG_LONG(st,f,s,lo,d,h) { \
+ .type = isl_arg_long, \
+ .short_name = s, \
+ .long_name = lo, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .l = { .default_value = d, .default_selected = d, \
+ .set = NULL } } \
+},
+#define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h) { \
+ .type = isl_arg_long, \
+ .short_name = s, \
+ .long_name = lo, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .l = { .default_value = d, .default_selected = d, \
+ .set = setter } } \
+},
+#define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h) { \
+ .type = isl_arg_long, \
+ .short_name = s, \
+ .long_name = lo, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .l = { .default_value = d, .default_selected = ds, \
+ .set = NULL } } \
+},
+#define ISL_ARG_ULONG(st,f,s,l,d,h) { \
+ .type = isl_arg_ulong, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .ul = { .default_value = d } } \
+},
+#define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl) { \
+ .type = isl_arg_str, \
+ .short_name = s, \
+ .long_name = l, \
+ .argument_name = a, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .flags = fl, \
+ .u = { .str = { .default_value = d } } \
+},
+#define ISL_ARG_STR(st,f,s,l,a,d,h) \
+ ISL_ARG_STR_F(st,f,s,l,a,d,h,0)
+#define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h) { \
+ .type = isl_arg_str_list, \
+ .short_name = s, \
+ .long_name = l, \
+ .argument_name = a, \
+ .offset = offsetof(st, f_l), \
+ .help_msg = h, \
+ .u = { .str_list = { .offset_n = offsetof(st, f_n) } } \
+},
+#define _ISL_ARG_CHILD(o,l,c,h,fl) { \
+ .type = isl_arg_child, \
+ .long_name = l, \
+ .offset = o, \
+ .help_msg = h, \
+ .flags = fl, \
+ .u = { .child = { .child = c } } \
+},
+#define ISL_ARG_CHILD(st,f,l,c,h) \
+ _ISL_ARG_CHILD(offsetof(st, f),l,c,h,0)
+#define ISL_ARG_GROUP_F(l,c,h,fl) \
+ _ISL_ARG_CHILD(-1,l,c,h,fl)
+#define ISL_ARG_GROUP(l,c,h) \
+ ISL_ARG_GROUP_F(l,c,h,0)
+#define ISL_ARG_FLAGS(st,f,s,l,c,d,h) { \
+ .type = isl_arg_flags, \
+ .short_name = s, \
+ .long_name = l, \
+ .offset = offsetof(st, f), \
+ .help_msg = h, \
+ .u = { .flags = { .flags = c, .default_value = d } } \
+},
+#define ISL_ARG_USER(st,f,i,c) { \
+ .type = isl_arg_user, \
+ .offset = offsetof(st, f), \
+ .u = { .user = { .init = i, .clear = c} } \
+},
+#define ISL_ARG_VERSION(print) { \
+ .type = isl_arg_version, \
+ .u = { .version = { .print_version = print } } \
+},
+
+#define ISL_ARG_ALL (1 << 0)
+#define ISL_ARG_SKIP_HELP (1 << 1)
+
+void isl_args_set_defaults(struct isl_args *args, void *opt);
+void isl_args_free(struct isl_args *args, void *opt);
+int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
+ unsigned flags);
+
+#define ISL_ARG_DECL(prefix,st,args) \
+extern struct isl_args args; \
+st *prefix ## _new_with_defaults(void); \
+void prefix ## _free(st *opt); \
+int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
+
+#define ISL_ARG_DEF(prefix,st,args) \
+st *prefix ## _new_with_defaults() \
+{ \
+ st *opt = (st *)calloc(1, sizeof(st)); \
+ if (opt) \
+ isl_args_set_defaults(&(args), opt); \
+ return opt; \
+} \
+ \
+void prefix ## _free(st *opt) \
+{ \
+ isl_args_free(&(args), opt); \
+} \
+ \
+int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags) \
+{ \
+ return isl_args_parse(&(args), argc, argv, opt, flags); \
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/ast.h b/polly/lib/External/isl/include/isl/ast.h
new file mode 100644
index 00000000000..cc3008bbfda
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/ast.h
@@ -0,0 +1,159 @@
+#ifndef ISL_AST_H
+#define ISL_AST_H
+
+#include <isl/ctx.h>
+#include <isl/ast_type.h>
+#include <isl/id.h>
+#include <isl/id_to_ast_expr.h>
+#include <isl/val.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_options_set_ast_iterator_type(isl_ctx *ctx, const char *val);
+const char *isl_options_get_ast_iterator_type(isl_ctx *ctx);
+
+int isl_options_set_ast_always_print_block(isl_ctx *ctx, int val);
+int isl_options_get_ast_always_print_block(isl_ctx *ctx);
+
+__isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v);
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id);
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
+ __isl_take isl_ast_expr_list *indices);
+__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr);
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr);
+__isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr);
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr);
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr);
+__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr);
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr);
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr);
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+ int pos);
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+ int pos, __isl_take isl_ast_expr *arg);
+
+int isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
+ __isl_keep isl_ast_expr *expr2);
+
+__isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
+ __isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr);
+
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr);
+void isl_ast_expr_dump(__isl_keep isl_ast_expr *expr);
+__isl_give char *isl_ast_expr_to_str(__isl_keep isl_ast_expr *expr);
+
+__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr);
+__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node);
+__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node);
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node);
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+ __isl_take isl_ast_node *node, __isl_take isl_id *annotation);
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+ __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+ __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+ __isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+ __isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+ __isl_keep isl_ast_node *node);
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+ __isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+ __isl_keep isl_ast_node *node);
+int isl_ast_node_if_has_else(__isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+ __isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+ __isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+ __isl_keep isl_ast_node *node);
+
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node);
+void isl_ast_node_dump(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx);
+__isl_give isl_ast_print_options *isl_ast_print_options_copy(
+ __isl_keep isl_ast_print_options *options);
+__isl_null isl_ast_print_options *isl_ast_print_options_free(
+ __isl_take isl_ast_print_options *options);
+isl_ctx *isl_ast_print_options_get_ctx(
+ __isl_keep isl_ast_print_options *options);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user);
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user);
+
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+ int (*fn)(enum isl_ast_op_type type, void *user), void *user);
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+ enum isl_ast_op_type type, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print_macros(
+ __isl_keep isl_ast_node *node, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/ast_build.h b/polly/lib/External/isl/include/isl/ast_build.h
new file mode 100644
index 00000000000..4fa7b454909
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/ast_build.h
@@ -0,0 +1,100 @@
+#ifndef ISL_AST_CONTEXT_H
+#define ISL_AST_CONTEXT_H
+
+#include <isl/ctx.h>
+#include <isl/set.h>
+#include <isl/ast.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_build;
+typedef struct isl_ast_build isl_ast_build;
+
+
+int isl_options_set_ast_build_atomic_upper_bound(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_atomic_upper_bound(isl_ctx *ctx);
+
+int isl_options_set_ast_build_prefer_pdiv(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_prefer_pdiv(isl_ctx *ctx);
+
+int isl_options_set_ast_build_exploit_nested_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_exploit_nested_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_group_coscheduled(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_group_coscheduled(isl_ctx *ctx);
+
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT 0
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT 1
+int isl_options_set_ast_build_separation_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_separation_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_scale_strides(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_scale_strides(isl_ctx *ctx);
+
+int isl_options_set_ast_build_allow_else(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_allow_else(isl_ctx *ctx);
+
+int isl_options_set_ast_build_allow_or(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_allow_or(isl_ctx *ctx);
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set);
+
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+ __isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_restrict(
+ __isl_take isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_ast_build *isl_ast_build_copy(
+ __isl_keep isl_ast_build *build);
+__isl_null isl_ast_build *isl_ast_build_free(
+ __isl_take isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_set_options(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_union_map *options);
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_id_list *iterators);
+__isl_give isl_ast_build *isl_ast_build_set_at_each_domain(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_before_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_id *(*fn)(__isl_keep isl_ast_build *build,
+ void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_after_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+ void *user), void *user);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
+
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+ __isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/ast_type.h b/polly/lib/External/isl/include/isl/ast_type.h
new file mode 100644
index 00000000000..19b14b3b7dc
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/ast_type.h
@@ -0,0 +1,71 @@
+#ifndef ISL_AST_TYPE_H
+#define ISL_AST_TYPE_H
+
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_expr;
+typedef struct isl_ast_expr isl_ast_expr;
+
+struct isl_ast_node;
+typedef struct isl_ast_node isl_ast_node;
+
+enum isl_ast_op_type {
+ isl_ast_op_error = -1,
+ isl_ast_op_and,
+ isl_ast_op_and_then,
+ isl_ast_op_or,
+ isl_ast_op_or_else,
+ isl_ast_op_max,
+ isl_ast_op_min,
+ isl_ast_op_minus,
+ isl_ast_op_add,
+ isl_ast_op_sub,
+ isl_ast_op_mul,
+ isl_ast_op_div,
+ isl_ast_op_fdiv_q, /* Round towards -infty */
+ isl_ast_op_pdiv_q, /* Dividend is non-negative */
+ isl_ast_op_pdiv_r, /* Dividend is non-negative */
+ isl_ast_op_zdiv_r, /* Result only compared against zero */
+ isl_ast_op_cond,
+ isl_ast_op_select,
+ isl_ast_op_eq,
+ isl_ast_op_le,
+ isl_ast_op_lt,
+ isl_ast_op_ge,
+ isl_ast_op_gt,
+ isl_ast_op_call,
+ isl_ast_op_access,
+ isl_ast_op_member,
+ isl_ast_op_address_of
+};
+
+enum isl_ast_expr_type {
+ isl_ast_expr_error = -1,
+ isl_ast_expr_op,
+ isl_ast_expr_id,
+ isl_ast_expr_int
+};
+
+enum isl_ast_node_type {
+ isl_ast_node_error = -1,
+ isl_ast_node_for = 1,
+ isl_ast_node_if,
+ isl_ast_node_block,
+ isl_ast_node_user
+};
+
+struct isl_ast_print_options;
+typedef struct isl_ast_print_options isl_ast_print_options;
+
+ISL_DECLARE_LIST(ast_expr)
+ISL_DECLARE_LIST(ast_node)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/band.h b/polly/lib/External/isl/include/isl/band.h
new file mode 100644
index 00000000000..cb2bfeebfc1
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/band.h
@@ -0,0 +1,56 @@
+#ifndef ISL_BAND_H
+#define ISL_BAND_H
+
+#include <isl/printer.h>
+#include <isl/list.h>
+#include <isl/union_map_type.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_band;
+typedef struct isl_band isl_band;
+
+ISL_DECLARE_LIST(band)
+
+__isl_give isl_band *isl_band_copy(__isl_keep isl_band *band);
+__isl_null isl_band *isl_band_free(__isl_take isl_band *band);
+
+isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band);
+
+int isl_band_has_children(__isl_keep isl_band *band);
+__isl_give isl_band_list *isl_band_get_children(
+ __isl_keep isl_band *band);
+
+__isl_give isl_union_map *isl_band_get_prefix_schedule(
+ __isl_keep isl_band *band);
+__isl_give isl_union_map *isl_band_get_partial_schedule(
+ __isl_keep isl_band *band);
+__isl_give isl_union_map *isl_band_get_suffix_schedule(
+ __isl_keep isl_band *band);
+
+int isl_options_set_tile_scale_tile_loops(isl_ctx *ctx, int val);
+int isl_options_get_tile_scale_tile_loops(isl_ctx *ctx);
+int isl_options_set_tile_shift_point_loops(isl_ctx *ctx, int val);
+int isl_options_get_tile_shift_point_loops(isl_ctx *ctx);
+
+int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes);
+int isl_band_split(__isl_keep isl_band *band, int pos);
+
+int isl_band_n_member(__isl_keep isl_band *band);
+int isl_band_member_is_coincident(__isl_keep isl_band *band, int pos);
+
+int isl_band_list_foreach_band(__isl_keep isl_band_list *list,
+ int (*fn)(__isl_keep isl_band *band, void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_band(__isl_take isl_printer *p,
+ __isl_keep isl_band *band);
+void isl_band_dump(__isl_keep isl_band *band);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/constraint.h b/polly/lib/External/isl/include/isl/constraint.h
new file mode 100644
index 00000000000..70de5b5a823
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/constraint.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_CONSTRAINT_H
+#define ISL_CONSTRAINT_H
+
+#include <isl/local_space.h>
+#include <isl/space.h>
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+#include <isl/list.h>
+#include <isl/val.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_constraint;
+typedef struct isl_constraint isl_constraint;
+
+ISL_DECLARE_LIST(constraint)
+
+isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c);
+
+__isl_give isl_constraint *isl_equality_alloc(__isl_take isl_local_space *ls);
+__isl_give isl_constraint *isl_inequality_alloc(__isl_take isl_local_space *ls);
+
+struct isl_constraint *isl_constraint_cow(struct isl_constraint *c);
+struct isl_constraint *isl_constraint_copy(struct isl_constraint *c);
+__isl_null isl_constraint *isl_constraint_free(__isl_take isl_constraint *c);
+
+int isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap);
+int isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset);
+int isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap,
+ int (*fn)(__isl_take isl_constraint *c, void *user), void *user);
+int isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset,
+ int (*fn)(__isl_take isl_constraint *c, void *user), void *user);
+__isl_give isl_constraint_list *isl_basic_map_get_constraint_list(
+ __isl_keep isl_basic_map *bmap);
+__isl_give isl_constraint_list *isl_basic_set_get_constraint_list(
+ __isl_keep isl_basic_set *bset);
+int isl_constraint_is_equal(struct isl_constraint *constraint1,
+ struct isl_constraint *constraint2);
+
+int isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos,
+ int (*fn)(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper,
+ __isl_take isl_basic_set *bset, void *user), void *user);
+
+__isl_give isl_basic_map *isl_basic_map_add_constraint(
+ __isl_take isl_basic_map *bmap, __isl_take isl_constraint *constraint);
+__isl_give isl_basic_set *isl_basic_set_add_constraint(
+ __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint);
+__isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map,
+ __isl_take isl_constraint *constraint);
+__isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
+ __isl_take isl_constraint *constraint);
+
+int isl_basic_map_has_defining_equality(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type type, int pos,
+ __isl_give isl_constraint **c);
+int isl_basic_set_has_defining_equality(
+ struct isl_basic_set *bset, enum isl_dim_type type, int pos,
+ struct isl_constraint **constraint);
+int isl_basic_set_has_defining_inequalities(
+ struct isl_basic_set *bset, enum isl_dim_type type, int pos,
+ struct isl_constraint **lower,
+ struct isl_constraint **upper);
+
+__isl_give isl_space *isl_constraint_get_space(
+ __isl_keep isl_constraint *constraint);
+__isl_give isl_local_space *isl_constraint_get_local_space(
+ __isl_keep isl_constraint *constraint);
+int isl_constraint_dim(struct isl_constraint *constraint,
+ enum isl_dim_type type);
+
+int isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_val *isl_constraint_get_constant_val(
+ __isl_keep isl_constraint *constraint);
+__isl_give isl_val *isl_constraint_get_coefficient_val(
+ __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos);
+__isl_give isl_constraint *isl_constraint_set_constant_si(
+ __isl_take isl_constraint *constraint, int v);
+__isl_give isl_constraint *isl_constraint_set_constant_val(
+ __isl_take isl_constraint *constraint, __isl_take isl_val *v);
+__isl_give isl_constraint *isl_constraint_set_coefficient_si(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, int v);
+__isl_give isl_constraint *isl_constraint_set_coefficient_val(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+__isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint,
+ int pos);
+
+struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint);
+
+int isl_constraint_is_equality(__isl_keep isl_constraint *constraint);
+int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint);
+
+int isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+int isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos);
+
+__isl_give isl_basic_map *isl_basic_map_from_constraint(
+ __isl_take isl_constraint *constraint);
+struct isl_basic_set *isl_basic_set_from_constraint(
+ struct isl_constraint *constraint);
+
+__isl_give isl_aff *isl_constraint_get_bound(
+ __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos);
+__isl_give isl_aff *isl_constraint_get_aff(
+ __isl_keep isl_constraint *constraint);
+__isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff);
+
+__isl_give isl_basic_set *isl_basic_set_drop_constraint(
+ __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint);
+
+int isl_constraint_plain_cmp(__isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2);
+int isl_constraint_cmp_last_non_zero(__isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2);
+
+__isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,
+ __isl_keep isl_constraint *c);
+void isl_constraint_dump(__isl_keep isl_constraint *c);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/ctx.h b/polly/lib/External/isl/include/isl/ctx.h
new file mode 100644
index 00000000000..44680b10a08
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/ctx.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_CTX_H
+#define ISL_CTX_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isl/arg.h>
+#include <isl/hash.h>
+
+#ifndef __isl_give
+#define __isl_give
+#endif
+#ifndef __isl_take
+#define __isl_take
+#endif
+#ifndef __isl_keep
+#define __isl_keep
+#endif
+#ifndef __isl_null
+#define __isl_null
+#endif
+#ifndef __isl_export
+#define __isl_export
+#endif
+#ifndef __isl_constructor
+#define __isl_constructor
+#endif
+#ifndef __isl_subclass
+#define __isl_subclass(super)
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Nearly all isa functions require a struct isl_ctx allocated using
+ * isl_ctx_alloc. This ctx contains (or will contain) options that
+ * control the behavior of the library and some caches.
+ *
+ * An object allocated within a given ctx should never be used inside
+ * another ctx. Functions for moving objects from one ctx to another
+ * will be added as the need arises.
+ *
+ * A given context should only be used inside a single thread.
+ * A global context for synchronization between different threads
+ * as well as functions for moving a context to a different thread
+ * will be added as the need arises.
+ *
+ * If anything goes wrong (out of memory, failed assertion), then
+ * the library will currently simply abort. This will be made
+ * configurable in the future.
+ * Users of the library should expect functions that return
+ * a pointer to a structure, to return NULL, indicating failure.
+ * Any function accepting a pointer to a structure will treat
+ * a NULL argument as a failure, resulting in the function freeing
+ * the remaining structures (if any) and returning NULL itself
+ * (in case of pointer return type).
+ * The only exception is the isl_ctx argument, which should never be NULL.
+ */
+struct isl_stats {
+ long gbr_solved_lps;
+};
+enum isl_error {
+ isl_error_none = 0,
+ isl_error_abort,
+ isl_error_alloc,
+ isl_error_unknown,
+ isl_error_internal,
+ isl_error_invalid,
+ isl_error_quota,
+ isl_error_unsupported
+};
+struct isl_ctx;
+typedef struct isl_ctx isl_ctx;
+
+/* Some helper macros */
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define ISL_DEPRECATED __attribute__((__deprecated__))
+#else
+#define ISL_DEPRECATED
+#endif
+
+#define ISL_FL_INIT(l, f) (l) = (f) /* Specific flags location. */
+#define ISL_FL_SET(l, f) ((l) |= (f))
+#define ISL_FL_CLR(l, f) ((l) &= ~(f))
+#define ISL_FL_ISSET(l, f) (!!((l) & (f)))
+
+#define ISL_F_INIT(p, f) ISL_FL_INIT((p)->flags, f) /* Structure element flags. */
+#define ISL_F_SET(p, f) ISL_FL_SET((p)->flags, f)
+#define ISL_F_CLR(p, f) ISL_FL_CLR((p)->flags, f)
+#define ISL_F_ISSET(p, f) ISL_FL_ISSET((p)->flags, f)
+
+void *isl_malloc_or_die(isl_ctx *ctx, size_t size);
+void *isl_calloc_or_die(isl_ctx *ctx, size_t nmemb, size_t size);
+void *isl_realloc_or_die(isl_ctx *ctx, void *ptr, size_t size);
+
+#define isl_alloc(ctx,type,size) ((type *)isl_malloc_or_die(ctx, size))
+#define isl_calloc(ctx,type,size) ((type *)isl_calloc_or_die(ctx,\
+ 1, size))
+#define isl_realloc(ctx,ptr,type,size) ((type *)isl_realloc_or_die(ctx,\
+ ptr, size))
+#define isl_alloc_type(ctx,type) isl_alloc(ctx,type,sizeof(type))
+#define isl_calloc_type(ctx,type) isl_calloc(ctx,type,sizeof(type))
+#define isl_realloc_type(ctx,ptr,type) isl_realloc(ctx,ptr,type,sizeof(type))
+#define isl_alloc_array(ctx,type,n) isl_alloc(ctx,type,(n)*sizeof(type))
+#define isl_calloc_array(ctx,type,n) ((type *)isl_calloc_or_die(ctx,\
+ n, sizeof(type)))
+#define isl_realloc_array(ctx,ptr,type,n) \
+ isl_realloc(ctx,ptr,type,(n)*sizeof(type))
+
+#define isl_die(ctx,errno,msg,code) \
+ do { \
+ isl_handle_error(ctx, errno, msg, __FILE__, __LINE__); \
+ code; \
+ } while (0)
+
+void isl_handle_error(isl_ctx *ctx, enum isl_error error, const char *msg,
+ const char *file, int line);
+
+#define isl_assert4(ctx,test,code,errno) \
+ do { \
+ if (test) \
+ break; \
+ isl_die(ctx, errno, "Assertion \"" #test "\" failed", code); \
+ } while (0)
+#define isl_assert(ctx,test,code) \
+ isl_assert4(ctx,test,code,isl_error_unknown)
+
+#define isl_min(a,b) ((a < b) ? (a) : (b))
+
+/* struct isl_ctx functions */
+
+struct isl_options *isl_ctx_options(isl_ctx *ctx);
+
+isl_ctx *isl_ctx_alloc_with_options(struct isl_args *args,
+ __isl_take void *opt);
+isl_ctx *isl_ctx_alloc(void);
+void *isl_ctx_peek_options(isl_ctx *ctx, struct isl_args *args);
+int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags);
+void isl_ctx_ref(struct isl_ctx *ctx);
+void isl_ctx_deref(struct isl_ctx *ctx);
+void isl_ctx_free(isl_ctx *ctx);
+
+void isl_ctx_abort(isl_ctx *ctx);
+void isl_ctx_resume(isl_ctx *ctx);
+int isl_ctx_aborted(isl_ctx *ctx);
+
+void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations);
+unsigned long isl_ctx_get_max_operations(isl_ctx *ctx);
+void isl_ctx_reset_operations(isl_ctx *ctx);
+
+#define ISL_ARG_CTX_DECL(prefix,st,args) \
+st *isl_ctx_peek_ ## prefix(isl_ctx *ctx);
+
+#define ISL_ARG_CTX_DEF(prefix,st,args) \
+st *isl_ctx_peek_ ## prefix(isl_ctx *ctx) \
+{ \
+ return (st *)isl_ctx_peek_options(ctx, &(args)); \
+}
+
+#define ISL_CTX_GET_INT_DEF(prefix,st,args,field) \
+int prefix ## _get_ ## field(isl_ctx *ctx) \
+{ \
+ st *options; \
+ options = isl_ctx_peek_ ## prefix(ctx); \
+ if (!options) \
+ isl_die(ctx, isl_error_invalid, \
+ "isl_ctx does not reference " #prefix, \
+ return -1); \
+ return options->field; \
+}
+
+#define ISL_CTX_SET_INT_DEF(prefix,st,args,field) \
+int prefix ## _set_ ## field(isl_ctx *ctx, int val) \
+{ \
+ st *options; \
+ options = isl_ctx_peek_ ## prefix(ctx); \
+ if (!options) \
+ isl_die(ctx, isl_error_invalid, \
+ "isl_ctx does not reference " #prefix, \
+ return -1); \
+ options->field = val; \
+ return 0; \
+}
+
+#define ISL_CTX_GET_STR_DEF(prefix,st,args,field) \
+const char *prefix ## _get_ ## field(isl_ctx *ctx) \
+{ \
+ st *options; \
+ options = isl_ctx_peek_ ## prefix(ctx); \
+ if (!options) \
+ isl_die(ctx, isl_error_invalid, \
+ "isl_ctx does not reference " #prefix, \
+ return NULL); \
+ return options->field; \
+}
+
+#define ISL_CTX_SET_STR_DEF(prefix,st,args,field) \
+int prefix ## _set_ ## field(isl_ctx *ctx, const char *val) \
+{ \
+ st *options; \
+ options = isl_ctx_peek_ ## prefix(ctx); \
+ if (!options) \
+ isl_die(ctx, isl_error_invalid, \
+ "isl_ctx does not reference " #prefix, \
+ return -1); \
+ if (!val) \
+ return -1; \
+ free(options->field); \
+ options->field = strdup(val); \
+ if (!options->field) \
+ return -1; \
+ return 0; \
+}
+
+#define ISL_CTX_GET_BOOL_DEF(prefix,st,args,field) \
+ ISL_CTX_GET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_SET_BOOL_DEF(prefix,st,args,field) \
+ ISL_CTX_SET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_GET_CHOICE_DEF(prefix,st,args,field) \
+ ISL_CTX_GET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_SET_CHOICE_DEF(prefix,st,args,field) \
+ ISL_CTX_SET_INT_DEF(prefix,st,args,field)
+
+enum isl_error isl_ctx_last_error(isl_ctx *ctx);
+void isl_ctx_reset_error(isl_ctx *ctx);
+void isl_ctx_set_error(isl_ctx *ctx, enum isl_error error);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/aff_int.h b/polly/lib/External/isl/include/isl/deprecated/aff_int.h
new file mode 100644
index 00000000000..cbab1f98717
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/aff_int.h
@@ -0,0 +1,45 @@
+#ifndef ISL_DEPRECATED_AFF_INT_H
+#define ISL_DEPRECATED_AFF_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/aff_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v);
+int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int *v);
+int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v);
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int v);
+__isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff,
+ isl_int v);
+__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int v);
+
+__isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int mod);
+
+__isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f);
+__isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f);
+
+__isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff,
+ isl_int mod);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale(__isl_take isl_pw_aff *pwaff,
+ isl_int f);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+ isl_int f);
+
+__isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
+ isl_int f);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/ast_int.h b/polly/lib/External/isl/include/isl/deprecated/ast_int.h
new file mode 100644
index 00000000000..7d2039be0a5
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/ast_int.h
@@ -0,0 +1,17 @@
+#ifndef ISL_DEPRECATED_AST_INT_H
+#define ISL_DEPRECATED_AST_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/ast.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/constraint_int.h b/polly/lib/External/isl/include/isl/deprecated/constraint_int.h
new file mode 100644
index 00000000000..c5ab0aabc41
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/constraint_int.h
@@ -0,0 +1,25 @@
+#ifndef ISL_DEPRECATED_CONSTRAINT_INT_H
+#define ISL_DEPRECATED_CONSTRAINT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/constraint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void isl_constraint_get_constant(__isl_keep isl_constraint *constraint,
+ isl_int *v);
+void isl_constraint_get_coefficient(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_constraint *isl_constraint_set_constant(
+ __isl_take isl_constraint *constraint, isl_int v);
+__isl_give isl_constraint *isl_constraint_set_coefficient(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/ilp_int.h b/polly/lib/External/isl/include/isl/deprecated/ilp_int.h
new file mode 100644
index 00000000000..b952e1b17ac
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/ilp_int.h
@@ -0,0 +1,23 @@
+#ifndef ISL_DEPRECATED_ILP_INT_H
+#define ISL_DEPRECATED_ILP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/lp.h>
+#include <isl/ilp.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum isl_lp_result isl_basic_set_max(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj, isl_int *opt);
+enum isl_lp_result isl_set_min(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj, isl_int *opt);
+enum isl_lp_result isl_set_max(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj, isl_int *opt);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/int.h b/polly/lib/External/isl/include/isl/deprecated/int.h
new file mode 100644
index 00000000000..98782346192
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/int.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_DEPRECATED_INT_H
+#define ISL_DEPRECATED_INT_H
+
+#include <isl/hash.h>
+#include <string.h>
+#include <gmp.h>
+#if defined(__cplusplus)
+#include <iostream>
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef mp_get_memory_functions
+void mp_get_memory_functions(
+ void *(**alloc_func_ptr) (size_t),
+ void *(**realloc_func_ptr) (void *, size_t, size_t),
+ void (**free_func_ptr) (void *, size_t));
+#endif
+
+/* isl_int is the basic integer type. It currently always corresponds
+ * to a gmp mpz_t, but in the future, different types such as long long
+ * or cln::cl_I will be supported.
+ */
+typedef mpz_t isl_int;
+
+#define isl_int_init(i) mpz_init(i)
+#define isl_int_clear(i) mpz_clear(i)
+
+#define isl_int_set(r,i) mpz_set(r,i)
+#define isl_int_set_gmp(r,i) mpz_set(r,i)
+#define isl_int_set_si(r,i) mpz_set_si(r,i)
+#define isl_int_set_ui(r,i) mpz_set_ui(r,i)
+#define isl_int_get_gmp(i,g) mpz_set(g,i)
+#define isl_int_get_si(r) mpz_get_si(r)
+#define isl_int_get_ui(r) mpz_get_ui(r)
+#define isl_int_get_d(r) mpz_get_d(r)
+#define isl_int_get_str(r) mpz_get_str(0, 10, r)
+typedef void (*isl_int_print_gmp_free_t)(void *, size_t);
+#define isl_int_free_str(s) \
+ do { \
+ isl_int_print_gmp_free_t gmp_free; \
+ mp_get_memory_functions(NULL, NULL, &gmp_free); \
+ (*gmp_free)(s, strlen(s) + 1); \
+ } while (0)
+#define isl_int_abs(r,i) mpz_abs(r,i)
+#define isl_int_neg(r,i) mpz_neg(r,i)
+#define isl_int_swap(i,j) mpz_swap(i,j)
+#define isl_int_swap_or_set(i,j) mpz_swap(i,j)
+#define isl_int_add_ui(r,i,j) mpz_add_ui(r,i,j)
+#define isl_int_sub_ui(r,i,j) mpz_sub_ui(r,i,j)
+
+#define isl_int_add(r,i,j) mpz_add(r,i,j)
+#define isl_int_sub(r,i,j) mpz_sub(r,i,j)
+#define isl_int_mul(r,i,j) mpz_mul(r,i,j)
+#define isl_int_mul_2exp(r,i,j) mpz_mul_2exp(r,i,j)
+#define isl_int_mul_ui(r,i,j) mpz_mul_ui(r,i,j)
+#define isl_int_pow_ui(r,i,j) mpz_pow_ui(r,i,j)
+#define isl_int_addmul(r,i,j) mpz_addmul(r,i,j)
+#define isl_int_submul(r,i,j) mpz_submul(r,i,j)
+
+#define isl_int_gcd(r,i,j) mpz_gcd(r,i,j)
+#define isl_int_lcm(r,i,j) mpz_lcm(r,i,j)
+#define isl_int_divexact(r,i,j) mpz_divexact(r,i,j)
+#define isl_int_divexact_ui(r,i,j) mpz_divexact_ui(r,i,j)
+#define isl_int_tdiv_q(r,i,j) mpz_tdiv_q(r,i,j)
+#define isl_int_cdiv_q(r,i,j) mpz_cdiv_q(r,i,j)
+#define isl_int_fdiv_q(r,i,j) mpz_fdiv_q(r,i,j)
+#define isl_int_fdiv_r(r,i,j) mpz_fdiv_r(r,i,j)
+#define isl_int_fdiv_q_ui(r,i,j) mpz_fdiv_q_ui(r,i,j)
+
+#define isl_int_read(r,s) mpz_set_str(r,s,10)
+#define isl_int_print(out,i,width) \
+ do { \
+ char *s; \
+ s = mpz_get_str(0, 10, i); \
+ fprintf(out, "%*s", width, s); \
+ isl_int_free_str(s); \
+ } while (0)
+
+#define isl_int_sgn(i) mpz_sgn(i)
+#define isl_int_cmp(i,j) mpz_cmp(i,j)
+#define isl_int_cmp_si(i,si) mpz_cmp_si(i,si)
+#define isl_int_eq(i,j) (mpz_cmp(i,j) == 0)
+#define isl_int_ne(i,j) (mpz_cmp(i,j) != 0)
+#define isl_int_lt(i,j) (mpz_cmp(i,j) < 0)
+#define isl_int_le(i,j) (mpz_cmp(i,j) <= 0)
+#define isl_int_gt(i,j) (mpz_cmp(i,j) > 0)
+#define isl_int_ge(i,j) (mpz_cmp(i,j) >= 0)
+#define isl_int_abs_eq(i,j) (mpz_cmpabs(i,j) == 0)
+#define isl_int_abs_ne(i,j) (mpz_cmpabs(i,j) != 0)
+#define isl_int_abs_lt(i,j) (mpz_cmpabs(i,j) < 0)
+#define isl_int_abs_gt(i,j) (mpz_cmpabs(i,j) > 0)
+#define isl_int_abs_ge(i,j) (mpz_cmpabs(i,j) >= 0)
+
+
+#define isl_int_is_zero(i) (isl_int_sgn(i) == 0)
+#define isl_int_is_one(i) (isl_int_cmp_si(i,1) == 0)
+#define isl_int_is_negone(i) (isl_int_cmp_si(i,-1) == 0)
+#define isl_int_is_pos(i) (isl_int_sgn(i) > 0)
+#define isl_int_is_neg(i) (isl_int_sgn(i) < 0)
+#define isl_int_is_nonpos(i) (isl_int_sgn(i) <= 0)
+#define isl_int_is_nonneg(i) (isl_int_sgn(i) >= 0)
+#define isl_int_is_divisible_by(i,j) mpz_divisible_p(i,j)
+
+uint32_t isl_gmp_hash(mpz_t v, uint32_t hash);
+#define isl_int_hash(v,h) isl_gmp_hash(v,h)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if defined(__cplusplus)
+extern "C" { typedef void (*isl_gmp_free_t)(void *, size_t); }
+
+static inline std::ostream &operator<<(std::ostream &os, isl_int i)
+{
+ char *s;
+ s = mpz_get_str(0, 10, i);
+ os << s;
+ isl_int_free_str(s);
+ return os;
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/map_int.h b/polly/lib/External/isl/include/isl/deprecated/map_int.h
new file mode 100644
index 00000000000..915afbf8661
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/map_int.h
@@ -0,0 +1,27 @@
+#ifndef ISL_DEPRECATED_MAP_INT_H
+#define ISL_DEPRECATED_MAP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, isl_int *val);
+
+__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+int isl_map_plain_is_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int *val);
+int isl_map_fast_is_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int *val);
+
+__isl_give isl_map *isl_map_fixed_power(__isl_take isl_map *map, isl_int exp);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/mat_int.h b/polly/lib/External/isl/include/isl/deprecated/mat_int.h
new file mode 100644
index 00000000000..efacd4e5882
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/mat_int.h
@@ -0,0 +1,19 @@
+#ifndef ISL_DEPRECATED_MAT_INT_H
+#define ISL_DEPRECATED_MAT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/mat.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_mat_get_element(__isl_keep isl_mat *mat, int row, int col, isl_int *v);
+__isl_give isl_mat *isl_mat_set_element(__isl_take isl_mat *mat,
+ int row, int col, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/point_int.h b/polly/lib/External/isl/include/isl/deprecated/point_int.h
new file mode 100644
index 00000000000..2e1a98b6d6f
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/point_int.h
@@ -0,0 +1,20 @@
+#ifndef ISL_DEPRECATED_POINT_INT_H
+#define ISL_DEPRECATED_POINT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/point.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_point_get_coordinate(__isl_keep isl_point *pnt,
+ enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_point *isl_point_set_coordinate(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/polynomial_int.h b/polly/lib/External/isl/include/isl/deprecated/polynomial_int.h
new file mode 100644
index 00000000000..b86fcf29f48
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/polynomial_int.h
@@ -0,0 +1,32 @@
+#ifndef ISL_DEPRECATED_POLYNOMIAL_INT_H
+#define ISL_DEPRECATED_POLYNOMIAL_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/polynomial.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
+ __isl_take isl_space *space, const isl_int n, const isl_int d);
+int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+ isl_int *n, isl_int *d);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale(
+ __isl_take isl_qpolynomial *qp, isl_int v);
+
+void isl_term_get_num(__isl_keep isl_term *term, isl_int *n);
+void isl_term_get_den(__isl_keep isl_term *term, isl_int *d);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale(
+ __isl_take isl_qpolynomial_fold *fold, isl_int v);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fix_dim(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, unsigned n, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/set_int.h b/polly/lib/External/isl/include/isl/deprecated/set_int.h
new file mode 100644
index 00000000000..84bb88ae3d4
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/set_int.h
@@ -0,0 +1,27 @@
+#ifndef ISL_DEPRECATED_SET_INT_H
+#define ISL_DEPRECATED_SET_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+
+int isl_set_plain_is_fixed(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int *val);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/union_map_int.h b/polly/lib/External/isl/include/isl/deprecated/union_map_int.h
new file mode 100644
index 00000000000..4a57997a91f
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/union_map_int.h
@@ -0,0 +1,18 @@
+#ifndef ISL_DEPRECATED_UNION_MAP_INT_H
+#define ISL_DEPRECATED_UNION_MAP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/union_map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_union_map *isl_union_map_fixed_power(
+ __isl_take isl_union_map *umap, isl_int exp);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/val_int.h b/polly/lib/External/isl/include/isl/deprecated/val_int.h
new file mode 100644
index 00000000000..ef2eba221d2
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/val_int.h
@@ -0,0 +1,18 @@
+#ifndef ISL_DEPRECATED_VAL_INT_H
+#define ISL_DEPRECATED_VAL_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n);
+int isl_val_get_num_isl_int(__isl_keep isl_val *v, isl_int *n);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/deprecated/vec_int.h b/polly/lib/External/isl/include/isl/deprecated/vec_int.h
new file mode 100644
index 00000000000..c072997ac0f
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/deprecated/vec_int.h
@@ -0,0 +1,22 @@
+#ifndef ISL_DEPRECATED_VEC_INT_H
+#define ISL_DEPRECATED_VEC_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v);
+__isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
+ int pos, isl_int v);
+
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v);
+__isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/dim.h b/polly/lib/External/isl/include/isl/dim.h
new file mode 100644
index 00000000000..6c439f5bbcc
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/dim.h
@@ -0,0 +1,174 @@
+#ifndef ISL_DIM_H
+#define ISL_DIM_H
+
+#include <isl/space.h>
+#include <isl/local_space.h>
+#include <isl/aff_type.h>
+#include <isl/constraint.h>
+#include <isl/map_type.h>
+#include <isl/set_type.h>
+#include <isl/point.h>
+#include <isl/union_map.h>
+#include <isl/union_set.h>
+#include <isl/polynomial_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define isl_dim isl_space
+
+ISL_DEPRECATED
+isl_ctx *isl_dim_get_ctx(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned n_in, unsigned n_out);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_copy(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+void isl_dim_free(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+unsigned isl_dim_size(__isl_keep isl_space *dim, enum isl_dim_type type);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_dim_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+ISL_DEPRECATED
+int isl_dim_has_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+ISL_DEPRECATED
+__isl_give isl_id *isl_dim_get_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+
+ISL_DEPRECATED
+int isl_dim_find_dim_by_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, __isl_keep isl_id *id);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, __isl_take isl_id *id);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_reset_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type);
+ISL_DEPRECATED
+int isl_dim_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type);
+ISL_DEPRECATED
+__isl_give isl_id *isl_dim_get_tuple_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_keep const char *name);
+ISL_DEPRECATED
+__isl_keep const char *isl_dim_get_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_tuple_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, const char *s);
+ISL_DEPRECATED
+const char *isl_dim_get_tuple_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type);
+
+ISL_DEPRECATED
+int isl_dim_is_wrapping(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_wrap(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_unwrap(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_domain(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_from_domain(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_range(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_from_range(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_reverse(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_join(__isl_take isl_space *left,
+ __isl_take isl_space *right);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_align_params(__isl_take isl_space *dim1,
+ __isl_take isl_space *dim2);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_insert(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_add(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_drop(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_move(__isl_take isl_space *dim,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_map_from_set(
+ __isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_zip(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+__isl_give isl_local_space *isl_local_space_from_dim(
+ __isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_local_space_get_dim(
+ __isl_keep isl_local_space *ls);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_aff_get_dim(__isl_keep isl_aff *aff);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_aff_get_dim(__isl_keep isl_pw_aff *pwaff);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_constraint_get_dim(
+ __isl_keep isl_constraint *constraint);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_basic_map_get_dim(__isl_keep isl_basic_map *bmap);
+ISL_DEPRECATED
+__isl_give isl_space *isl_map_get_dim(__isl_keep isl_map *map);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_map_get_dim(__isl_keep isl_union_map *umap);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_basic_set_get_dim(__isl_keep isl_basic_set *bset);
+ISL_DEPRECATED
+__isl_give isl_space *isl_set_get_dim(__isl_keep isl_set *set);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_set_get_dim(__isl_keep isl_union_set *uset);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_point_get_dim(__isl_keep isl_point *pnt);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_qpolynomial_get_dim(__isl_keep isl_qpolynomial *qp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_qpolynomial_get_dim(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_qpolynomial_fold_get_dim(
+ __isl_keep isl_qpolynomial_fold *fold);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_dim(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_pw_qpolynomial_get_dim(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_dim(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/flow.h b/polly/lib/External/isl/include/isl/flow.h
new file mode 100644
index 00000000000..2aee1949f04
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/flow.h
@@ -0,0 +1,77 @@
+#ifndef ISL_FLOW_H
+#define ISL_FLOW_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Let n (>= 0) be the number of iterators shared by first and second.
+ * If first precedes second textually return 2 * n + 1,
+ * otherwise return 2 * n.
+ */
+typedef int (*isl_access_level_before)(void *first, void *second);
+
+struct isl_restriction;
+typedef struct isl_restriction isl_restriction;
+
+__isl_null isl_restriction *isl_restriction_free(
+ __isl_take isl_restriction *restr);
+__isl_give isl_restriction *isl_restriction_empty(
+ __isl_take isl_map *source_map);
+__isl_give isl_restriction *isl_restriction_none(
+ __isl_take isl_map *source_map);
+__isl_give isl_restriction *isl_restriction_input(
+ __isl_take isl_set *source_restr, __isl_take isl_set *sink_restr);
+__isl_give isl_restriction *isl_restriction_output(
+ __isl_take isl_set *source_restr);
+
+isl_ctx *isl_restriction_get_ctx(__isl_keep isl_restriction *restr);
+
+typedef __isl_give isl_restriction *(*isl_access_restrict)(
+ __isl_keep isl_map *source_map, __isl_keep isl_set *sink,
+ void *source_user, void *user);
+
+struct isl_access_info;
+typedef struct isl_access_info isl_access_info;
+struct isl_flow;
+typedef struct isl_flow isl_flow;
+
+__isl_give isl_access_info *isl_access_info_alloc(__isl_take isl_map *sink,
+ void *sink_user, isl_access_level_before fn, int max_source);
+__isl_give isl_access_info *isl_access_info_set_restrict(
+ __isl_take isl_access_info *acc, isl_access_restrict fn, void *user);
+__isl_give isl_access_info *isl_access_info_add_source(
+ __isl_take isl_access_info *acc, __isl_take isl_map *source,
+ int must, void *source_user);
+__isl_null isl_access_info *isl_access_info_free(
+ __isl_take isl_access_info *acc);
+
+isl_ctx *isl_access_info_get_ctx(__isl_keep isl_access_info *acc);
+
+__isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc);
+int isl_flow_foreach(__isl_keep isl_flow *deps,
+ int (*fn)(__isl_take isl_map *dep, int must, void *dep_user, void *user),
+ void *user);
+__isl_give isl_map *isl_flow_get_no_source(__isl_keep isl_flow *deps, int must);
+void isl_flow_free(__isl_take isl_flow *deps);
+
+isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps);
+
+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,
+ __isl_take isl_union_map *schedule,
+ __isl_give isl_union_map **must_dep, __isl_give isl_union_map **may_dep,
+ __isl_give isl_union_map **must_no_source,
+ __isl_give isl_union_map **may_no_source);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/hash.h b/polly/lib/External/isl/include/isl/hash.h
new file mode 100644
index 00000000000..791f549ad3b
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/hash.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_HASH_H
+#define ISL_HASH_H
+
+#include <stdlib.h>
+
+// We do not generate isl/stdint.h in the Polly build. The configure logic has
+// not yet been implemented and it is unclear if it actually needed on the
+// platform LLVM is compiled for.
+
+#include <stdint.h>
+// #include <isl/stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define isl_hash_init() (2166136261u)
+#define isl_hash_byte(h,b) do { \
+ h *= 16777619; \
+ h ^= b; \
+ } while(0)
+#define isl_hash_hash(h,h2) \
+ do { \
+ isl_hash_byte(h, (h2) & 0xFF); \
+ isl_hash_byte(h, ((h2) >> 8) & 0xFF); \
+ isl_hash_byte(h, ((h2) >> 16) & 0xFF); \
+ isl_hash_byte(h, ((h2) >> 24) & 0xFF); \
+ } while(0)
+#define isl_hash_bits(h,bits) \
+ ((bits) == 32) ? (h) : \
+ ((bits) >= 16) ? \
+ ((h) >> (bits)) ^ ((h) & (((uint32_t)1 << (bits)) - 1)) : \
+ (((h) >> (bits)) ^ (h)) & (((uint32_t)1 << (bits)) - 1)
+
+uint32_t isl_hash_string(uint32_t hash, const char *s);
+uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len);
+
+#define isl_hash_builtin(h,l) isl_hash_mem(h, &l, sizeof(l))
+
+struct isl_hash_table_entry
+{
+ uint32_t hash;
+ void *data;
+};
+
+struct isl_hash_table {
+ int bits;
+ int n;
+ struct isl_hash_table_entry *entries;
+};
+
+struct isl_ctx;
+
+struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size);
+void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table);
+
+int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
+ int min_size);
+void isl_hash_table_clear(struct isl_hash_table *table);
+struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ uint32_t key_hash,
+ int (*eq)(const void *entry, const void *val),
+ const void *val, int reserve);
+int isl_hash_table_foreach(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ int (*fn)(void **entry, void *user), void *user);
+void isl_hash_table_remove(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ struct isl_hash_table_entry *entry);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/hmap.h b/polly/lib/External/isl/include/isl/hmap.h
new file mode 100644
index 00000000000..41cd06f8700
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/hmap.h
@@ -0,0 +1,56 @@
+#include <isl/ctx.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_xCAT(A,B) A ## B
+#define ISL_CAT(A,B) ISL_xCAT(A,B)
+#define ISL_KEY ISL_CAT(isl_,ISL_KEY_BASE)
+#define ISL_VAL ISL_CAT(isl_,ISL_VAL_BASE)
+#define ISL_xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define ISL_FN(TYPE,NAME) ISL_xFN(TYPE,NAME)
+#define ISL_xHMAP(KEY,VAL_BASE) KEY ## _to_ ## VAL_BASE
+#define ISL_yHMAP(KEY,VAL_BASE) ISL_xHMAP(KEY,VAL_BASE)
+#define ISL_HMAP ISL_yHMAP(ISL_KEY,ISL_VAL_BASE)
+#define ISL_HMAP_BASE ISL_yHMAP(ISL_KEY_BASE,ISL_VAL_BASE)
+
+struct ISL_HMAP;
+typedef struct ISL_HMAP ISL_HMAP;
+
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,alloc)(isl_ctx *ctx, int min_size);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,copy)(__isl_keep ISL_HMAP *hmap);
+__isl_null ISL_HMAP *ISL_FN(ISL_HMAP,free)(__isl_take ISL_HMAP *hmap);
+
+isl_ctx *ISL_FN(ISL_HMAP,get_ctx)(__isl_keep ISL_HMAP *hmap);
+
+int ISL_FN(ISL_HMAP,has)(__isl_keep ISL_HMAP *hmap, __isl_keep ISL_KEY *key);
+__isl_give ISL_VAL *ISL_FN(ISL_HMAP,get)(__isl_keep ISL_HMAP *hmap,
+ __isl_take ISL_KEY *key);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,set)(__isl_take ISL_HMAP *hmap,
+ __isl_take ISL_KEY *key, __isl_take ISL_VAL *val);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
+ __isl_take ISL_KEY *key);
+
+int ISL_FN(ISL_HMAP,foreach)(__isl_keep ISL_HMAP *hmap,
+ int (*fn)(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val, void *user),
+ void *user);
+
+__isl_give isl_printer *ISL_FN(isl_printer_print,ISL_HMAP_BASE)(
+ __isl_take isl_printer *p, __isl_keep ISL_HMAP *hmap);
+void ISL_FN(ISL_HMAP,dump)(__isl_keep ISL_HMAP *hmap);
+
+#undef ISL_xCAT
+#undef ISL_CAT
+#undef ISL_KEY
+#undef ISL_VAL
+#undef ISL_xFN
+#undef ISL_FN
+#undef ISL_xHMAP
+#undef ISL_yHMAP
+#undef ISL_HMAP
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/polly/lib/External/isl/include/isl/id.h b/polly/lib/External/isl/include/isl/id.h
new file mode 100644
index 00000000000..bd81d66562a
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/id.h
@@ -0,0 +1,39 @@
+#ifndef ISL_ID_H
+#define ISL_ID_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_id;
+typedef struct isl_id isl_id;
+
+ISL_DECLARE_LIST(id)
+
+isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id);
+uint32_t isl_id_get_hash(__isl_keep isl_id *id);
+
+__isl_give isl_id *isl_id_alloc(isl_ctx *ctx,
+ __isl_keep const char *name, void *user);
+__isl_give isl_id *isl_id_copy(isl_id *id);
+__isl_null isl_id *isl_id_free(__isl_take isl_id *id);
+
+void *isl_id_get_user(__isl_keep isl_id *id);
+__isl_keep const char *isl_id_get_name(__isl_keep isl_id *id);
+
+__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,
+ __isl_give void (*free_user)(void *user));
+
+__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,
+ __isl_keep isl_id *id);
+void isl_id_dump(__isl_keep isl_id *id);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/id_to_ast_expr.h b/polly/lib/External/isl/include/isl/id_to_ast_expr.h
new file mode 100644
index 00000000000..958360c3b63
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/id_to_ast_expr.h
@@ -0,0 +1,13 @@
+#ifndef ISL_ID_TO_AST_EXPR_H
+#define ISL_ID_TO_AST_EXPR_H
+
+#include <isl/id.h>
+#include <isl/ast_type.h>
+
+#define ISL_KEY_BASE id
+#define ISL_VAL_BASE ast_expr
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/id_to_pw_aff.h b/polly/lib/External/isl/include/isl/id_to_pw_aff.h
new file mode 100644
index 00000000000..e54fefb50b8
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/id_to_pw_aff.h
@@ -0,0 +1,13 @@
+#ifndef ISL_ID_TO_PW_AFF_H
+#define ISL_ID_TO_PW_AFF_H
+
+#include <isl/id.h>
+#include <isl/aff_type.h>
+
+#define ISL_KEY_BASE id
+#define ISL_VAL_BASE pw_aff
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/ilp.h b/polly/lib/External/isl/include/isl/ilp.h
new file mode 100644
index 00000000000..c177014fda5
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/ilp.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_ILP_H
+#define ISL_ILP_H
+
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+#include <isl/val.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_basic_set_max_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj);
+__isl_give isl_val *isl_set_min_val(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj);
+__isl_give isl_val *isl_set_max_val(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/list.h b/polly/lib/External/isl/include/isl/list.h
new file mode 100644
index 00000000000..3dbde2e58e5
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/list.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_LIST_H
+#define ISL_LIST_H
+
+#include <isl/ctx.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_DECLARE_LIST_TYPE(EL) \
+struct isl_##EL; \
+struct isl_##EL##_list; \
+typedef struct isl_##EL##_list isl_##EL##_list;
+#define ISL_DECLARE_LIST_FN(EL) \
+isl_ctx *isl_##EL##_list_get_ctx(__isl_keep isl_##EL##_list *list); \
+__isl_give isl_##EL##_list *isl_##EL##_list_from_##EL( \
+ __isl_take struct isl_##EL *el); \
+__isl_give isl_##EL##_list *isl_##EL##_list_alloc(isl_ctx *ctx, int n); \
+__isl_give isl_##EL##_list *isl_##EL##_list_copy( \
+ __isl_keep isl_##EL##_list *list); \
+__isl_null isl_##EL##_list *isl_##EL##_list_free( \
+ __isl_take isl_##EL##_list *list); \
+__isl_give isl_##EL##_list *isl_##EL##_list_add( \
+ __isl_take isl_##EL##_list *list, \
+ __isl_take struct isl_##EL *el); \
+__isl_give isl_##EL##_list *isl_##EL##_list_insert( \
+ __isl_take isl_##EL##_list *list, unsigned pos, \
+ __isl_take struct isl_##EL *el); \
+__isl_give isl_##EL##_list *isl_##EL##_list_drop( \
+ __isl_take isl_##EL##_list *list, unsigned first, unsigned n); \
+__isl_give isl_##EL##_list *isl_##EL##_list_concat( \
+ __isl_take isl_##EL##_list *list1, \
+ __isl_take isl_##EL##_list *list2); \
+int isl_##EL##_list_n_##EL(__isl_keep isl_##EL##_list *list); \
+__isl_give struct isl_##EL *isl_##EL##_list_get_##EL( \
+ __isl_keep isl_##EL##_list *list, int index); \
+__isl_give struct isl_##EL##_list *isl_##EL##_list_set_##EL( \
+ __isl_take struct isl_##EL##_list *list, int index, \
+ __isl_take struct isl_##EL *el); \
+int isl_##EL##_list_foreach(__isl_keep isl_##EL##_list *list, \
+ int (*fn)(__isl_take struct isl_##EL *el, void *user), \
+ void *user); \
+__isl_give isl_##EL##_list *isl_##EL##_list_sort( \
+ __isl_take isl_##EL##_list *list, \
+ int (*cmp)(__isl_keep struct isl_##EL *a, \
+ __isl_keep struct isl_##EL *b, \
+ void *user), void *user); \
+int isl_##EL##_list_foreach_scc(__isl_keep isl_##EL##_list *list, \
+ int (*follows)(__isl_keep struct isl_##EL *a, \
+ __isl_keep struct isl_##EL *b, void *user), \
+ void *follows_user, \
+ int (*fn)(__isl_take isl_##EL##_list *scc, void *user), \
+ void *fn_user); \
+__isl_give isl_printer *isl_printer_print_##EL##_list( \
+ __isl_take isl_printer *p, __isl_keep isl_##EL##_list *list); \
+void isl_##EL##_list_dump(__isl_keep isl_##EL##_list *list);
+
+#define ISL_DECLARE_LIST(EL) \
+ ISL_DECLARE_LIST_TYPE(EL) \
+ ISL_DECLARE_LIST_FN(EL)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/local_space.h b/polly/lib/External/isl/include/isl/local_space.h
new file mode 100644
index 00000000000..57ac83f10dd
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/local_space.h
@@ -0,0 +1,92 @@
+#ifndef ISL_LOCAL_SPACE_H
+#define ISL_LOCAL_SPACE_H
+
+#include <isl/aff_type.h>
+#include <isl/space.h>
+#include <isl/printer.h>
+#include <isl/map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_local_space;
+typedef struct isl_local_space isl_local_space;
+
+isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim);
+
+__isl_give isl_local_space *isl_local_space_copy(
+ __isl_keep isl_local_space *ls);
+__isl_null isl_local_space *isl_local_space_free(
+ __isl_take isl_local_space *ls);
+
+int isl_local_space_is_params(__isl_keep isl_local_space *ls);
+int isl_local_space_is_set(__isl_keep isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_set_tuple_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, __isl_take isl_id *id);
+
+int isl_local_space_dim(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type);
+int isl_local_space_has_dim_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_local_space *isl_local_space_set_dim_name(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, const char *s);
+int isl_local_space_has_dim_id(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_local_space_get_dim_id(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_local_space *isl_local_space_set_dim_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+__isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls);
+__isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls,
+ int pos);
+
+int isl_local_space_find_dim_by_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_local_space *isl_local_space_domain(
+ __isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_range(
+ __isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_from_domain(
+ __isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_add_dims(
+ __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n);
+__isl_give isl_local_space *isl_local_space_drop_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_local_space *isl_local_space_insert_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_local_space *isl_local_space_intersect(
+ __isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2);
+
+int isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
+ __isl_keep isl_local_space *ls2);
+
+__isl_give isl_basic_map *isl_local_space_lifting(
+ __isl_take isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_flatten_domain(
+ __isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_flatten_range(
+ __isl_take isl_local_space *ls);
+
+__isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls);
+void isl_local_space_dump(__isl_keep isl_local_space *ls);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/lp.h b/polly/lib/External/isl/include/isl/lp.h
new file mode 100644
index 00000000000..461ae0098e0
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/lp.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_LP_H
+#define ISL_LP_H
+
+#include <isl/aff.h>
+#include <isl/val.h>
+#include <isl/set_type.h>
+
+enum isl_lp_result {
+ isl_lp_error = -1,
+ isl_lp_ok = 0,
+ isl_lp_unbounded,
+ isl_lp_empty
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_basic_set_min_lp_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj);
+__isl_give isl_val *isl_basic_set_max_lp_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/map.h b/polly/lib/External/isl/include/isl/map.h
new file mode 100644
index 00000000000..a31ddfc8e16
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/map.h
@@ -0,0 +1,697 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_MAP_H
+#define ISL_MAP_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/space.h>
+#include <isl/vec.h>
+#include <isl/mat.h>
+#include <isl/printer.h>
+#include <isl/local_space.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/map_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* General notes:
+ *
+ * All structures are reference counted to allow reuse without duplication.
+ * A *_copy operation will increase the reference count, while a *_free
+ * operation will decrease the reference count and only actually release
+ * the structures when the reference count drops to zero.
+ *
+ * Functions that return an isa structure will in general _destroy_
+ * all argument isa structures (the obvious execption begin the _copy
+ * functions). A pointer passed to such a function may therefore
+ * never be used after the function call. If you want to keep a
+ * reference to the old structure(s), use the appropriate _copy function.
+ */
+
+unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type);
+
+unsigned isl_map_n_in(const struct isl_map *map);
+unsigned isl_map_n_out(const struct isl_map *map);
+unsigned isl_map_n_param(const struct isl_map *map);
+unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type);
+
+isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap);
+isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map);
+__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap);
+__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map);
+
+__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
+ int pos);
+
+__isl_give isl_local_space *isl_basic_map_get_local_space(
+ __isl_keep isl_basic_map *bmap);
+
+__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s);
+const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type);
+int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type);
+const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
+ enum isl_dim_type type);
+__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
+ enum isl_dim_type type, const char *s);
+const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+int isl_map_has_dim_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+const char *isl_map_get_dim_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_set_dim_name(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_basic_map *isl_basic_map_set_tuple_id(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+int isl_map_has_dim_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
+ enum isl_dim_type type);
+int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type);
+__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
+ enum isl_dim_type type);
+__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map);
+
+int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, const char *name);
+int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
+ __isl_keep isl_id *id);
+int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
+ const char *name);
+
+int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap);
+
+struct isl_basic_map *isl_basic_map_alloc(struct 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_identity(__isl_take isl_space *dim);
+struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model);
+struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap);
+__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap);
+struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
+ unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
+ unsigned n_eq, unsigned n_ineq);
+struct isl_basic_map *isl_basic_map_extend_constraints(
+ struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq);
+__isl_give isl_basic_map *isl_basic_map_equal(
+ __isl_take isl_space *dim, unsigned n_equal);
+__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
+ unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
+ unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim);
+struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model);
+struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model);
+__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_universe_like(
+ __isl_keep isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_remove_redundancies(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_remove_redundancies(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_map_simple_hull(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_map_unshifted_simple_hull(
+ __isl_take isl_map *map);
+
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_intersect_domain(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_intersect_range(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_intersect(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_map *isl_basic_map_union(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_apply_domain(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_apply_range(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_affine_hull(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma);
+__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_domain_map(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_range_map(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_remove_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_eliminate(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_from_basic_set(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap);
+struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_detect_equalities(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
+ FILE *input);
+__isl_constructor
+__isl_give isl_basic_map *isl_basic_map_read_from_str(isl_ctx *ctx,
+ const char *str);
+__isl_give isl_map *isl_map_read_from_file(isl_ctx *ctx, FILE *input);
+__isl_constructor
+__isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx, const char *str);
+void isl_basic_map_dump(__isl_keep isl_basic_map *bmap);
+void isl_basic_map_print(__isl_keep isl_basic_map *bmap, FILE *out, int indent,
+ const char *prefix, const char *suffix, unsigned output_format);
+void isl_map_dump(__isl_keep isl_map *map);
+void isl_map_print(__isl_keep isl_map *map, FILE *out, int indent,
+ unsigned output_format);
+__isl_give isl_printer *isl_printer_print_basic_map(
+ __isl_take isl_printer *printer, __isl_keep isl_basic_map *bmap);
+__isl_give char *isl_map_to_str(__isl_keep isl_map *map);
+__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *printer,
+ __isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value);
+
+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_floordiv_val(__isl_take isl_map *map,
+ __isl_take isl_val *d);
+
+__isl_export
+int isl_basic_map_is_equal(
+ __isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+int isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+
+__isl_give isl_map *isl_basic_map_partial_lexmax(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_map *isl_basic_map_partial_lexmin(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_map *isl_map_partial_lexmax(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_map *isl_map_partial_lexmin(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+__isl_export
+__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_lexmin(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_lexmax(__isl_take isl_map *map);
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
+ __isl_take isl_map *map);
+__isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
+ __isl_take isl_map *map);
+
+void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
+ FILE *out, int indent);
+
+struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map);
+__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
+ __isl_keep isl_basic_map *bmap);
+
+__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos);
+
+int isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap);
+int isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap);
+int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap);
+ISL_DEPRECATED
+int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap);
+__isl_export
+int isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap);
+__isl_export
+int isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+int isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+
+struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned in, unsigned out, int n,
+ unsigned flags);
+__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim);
+__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim);
+struct isl_map *isl_map_empty_like(struct isl_map *model);
+struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model);
+struct isl_map *isl_map_dup(struct isl_map *map);
+__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim);
+struct isl_map *isl_map_identity_like(struct isl_map *model);
+struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model);
+__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim);
+struct isl_map *isl_map_finalize(struct isl_map *map);
+__isl_null isl_map *isl_map_free(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_copy(__isl_keep isl_map *map);
+struct isl_map *isl_map_extend(struct isl_map *base,
+ unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_export
+__isl_give isl_map *isl_map_reverse(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_union(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+struct isl_map *isl_map_union_disjoint(
+ struct isl_map *map1, struct isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_intersect_domain(
+ __isl_take isl_map *map,
+ __isl_take isl_set *set);
+__isl_export
+__isl_give isl_map *isl_map_intersect_range(
+ __isl_take isl_map *map,
+ __isl_take isl_set *set);
+__isl_export
+__isl_give isl_map *isl_map_apply_domain(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_apply_range(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma);
+__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma);
+__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
+ __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
+ __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_basic_map *isl_basic_map_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_domain_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_basic_map *isl_basic_map_range_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_flat_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_flat_range_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+int isl_map_domain_is_wrapping(__isl_keep isl_map *map);
+int isl_map_range_is_wrapping(__isl_keep isl_map *map);
+__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
+ __isl_take isl_set *params);
+__isl_export
+__isl_give isl_map *isl_map_subtract(
+ __isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
+ __isl_take isl_set *dom);
+__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
+ __isl_take isl_set *dom);
+__isl_export
+__isl_give isl_map *isl_map_complement(__isl_take isl_map *map);
+struct isl_map *isl_map_fix_input_si(struct isl_map *map,
+ unsigned input, int value);
+__isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_export
+__isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_deltas_map(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_detect_equalities(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_affine_hull(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_map_convex_hull(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_polyhedral_hull(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_insert_dims(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type,
+ unsigned pos, unsigned n);
+__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_move_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_project_out(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_remove_divs(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_map *isl_map_remove_inputs(struct isl_map *map,
+ unsigned first, unsigned n);
+
+__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+
+__isl_export
+__isl_give isl_map *isl_set_identity(__isl_take isl_set *set);
+
+__isl_export
+int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_set_is_wrapping(__isl_keep isl_set *set);
+__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap);
+__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset);
+__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten_domain(
+ __isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten_range(
+ __isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set);
+__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set);
+__isl_give isl_set *isl_map_params(__isl_take isl_map *map);
+__isl_give isl_set *isl_map_domain(__isl_take isl_map *bmap);
+__isl_give isl_set *isl_map_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map);
+__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set);
+__isl_constructor
+__isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_from_domain(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_map *isl_basic_map_from_range(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
+ __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range);
+__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
+ __isl_take isl_set *range);
+__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
+ __isl_take isl_space *dim);
+struct isl_set *isl_set_from_map(struct isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map);
+
+int isl_map_plain_is_empty(__isl_keep isl_map *map);
+ISL_DEPRECATED
+int isl_map_fast_is_empty(__isl_keep isl_map *map);
+int isl_map_plain_is_universe(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_empty(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_strict_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap);
+int isl_map_plain_is_single_valued(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_single_valued(__isl_keep isl_map *map);
+int isl_map_plain_is_injective(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_injective(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_bijective(__isl_keep isl_map *map);
+int isl_map_is_translation(__isl_keep isl_map *map);
+int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+
+int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap);
+int isl_map_can_zip(__isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_zip(__isl_take isl_map *map);
+
+int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap);
+int 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);
+
+int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap);
+int isl_map_can_uncurry(__isl_keep isl_map *map);
+__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);
+
+__isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map);
+__isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map);
+__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_map *isl_map_drop_constraints_involving_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+int isl_map_involves_dims(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent);
+
+__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos);
+
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_map *context);
+__isl_export
+__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+ __isl_take isl_map *context);
+__isl_export
+__isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
+ __isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
+ __isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
+ __isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *context);
+
+__isl_export
+__isl_give isl_map *isl_map_coalesce(__isl_take isl_map *map);
+
+int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+ISL_DEPRECATED
+int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+
+uint32_t isl_map_get_hash(__isl_keep isl_map *map);
+
+int isl_map_n_basic_map(__isl_keep isl_map *map);
+__isl_export
+int isl_map_foreach_basic_map(__isl_keep isl_map *map,
+ int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user);
+
+__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set);
+
+__isl_give isl_map *isl_map_fixed_power_val(__isl_take isl_map *map,
+ __isl_take isl_val *exp);
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact);
+__isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
+ int *exact);
+__isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
+ int *exact);
+
+__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2);
+
+__isl_give isl_basic_map *isl_basic_map_align_params(
+ __isl_take isl_basic_map *bmap, __isl_take isl_space *model);
+__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
+ __isl_take isl_space *model);
+
+__isl_give isl_mat *isl_basic_map_equalities_matrix(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+__isl_give isl_mat *isl_basic_map_inequalities_matrix(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
+ __isl_take isl_space *dim,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5);
+
+__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_basic_map *isl_basic_map_from_multi_aff(
+ __isl_take isl_multi_aff *maff);
+__isl_give isl_basic_map *isl_basic_map_from_aff_list(
+ __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list);
+
+__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff);
+
+__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/map_to_basic_set.h b/polly/lib/External/isl/include/isl/map_to_basic_set.h
new file mode 100644
index 00000000000..7df8ee3e0a9
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/map_to_basic_set.h
@@ -0,0 +1,13 @@
+#ifndef ISL_MAP_TO_BASIC_SET_H
+#define ISL_MAP_TO_BASIC_SET_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+
+#define ISL_KEY_BASE map
+#define ISL_VAL_BASE basic_set
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/map_type.h b/polly/lib/External/isl/include/isl/map_type.h
new file mode 100644
index 00000000000..148dc0d3c70
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/map_type.h
@@ -0,0 +1,35 @@
+#ifndef ISL_MAP_TYPE_H
+#define ISL_MAP_TYPE_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct __isl_subclass(isl_map) isl_basic_map;
+typedef struct isl_basic_map isl_basic_map;
+struct __isl_subclass(isl_union_map) isl_map;
+typedef struct isl_map isl_map;
+
+#ifndef isl_basic_set
+struct __isl_subclass(isl_set) isl_basic_set;
+typedef struct isl_basic_set isl_basic_set;
+ISL_DECLARE_LIST_TYPE(basic_set)
+#endif
+
+#ifndef isl_set
+struct __isl_subclass(isl_union_set) isl_set;
+typedef struct isl_set isl_set;
+ISL_DECLARE_LIST_TYPE(set)
+#endif
+
+ISL_DECLARE_LIST_FN(basic_set)
+ISL_DECLARE_LIST_FN(set)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/mat.h b/polly/lib/External/isl/include/isl/mat.h
new file mode 100644
index 00000000000..7a43ccbaf64
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/mat.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_MAT_H
+#define ISL_MAT_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/vec.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_mat;
+typedef struct isl_mat isl_mat;
+
+isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat);
+
+__isl_give isl_mat *isl_mat_alloc(isl_ctx *ctx,
+ unsigned n_row, unsigned n_col);
+struct isl_mat *isl_mat_dup(struct isl_mat *mat);
+struct isl_mat *isl_mat_extend(struct isl_mat *mat,
+ unsigned n_row, unsigned n_col);
+struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row);
+__isl_give isl_mat *isl_mat_copy(__isl_keep isl_mat *mat);
+struct isl_mat *isl_mat_cow(struct isl_mat *mat);
+__isl_null isl_mat *isl_mat_free(__isl_take isl_mat *mat);
+
+int isl_mat_rows(__isl_keep isl_mat *mat);
+int isl_mat_cols(__isl_keep isl_mat *mat);
+__isl_give isl_val *isl_mat_get_element_val(__isl_keep isl_mat *mat,
+ int row, int col);
+__isl_give isl_mat *isl_mat_set_element_si(__isl_take isl_mat *mat,
+ int row, int col, int v);
+__isl_give isl_mat *isl_mat_set_element_val(__isl_take isl_mat *mat,
+ int row, int col, __isl_take isl_val *v);
+
+struct isl_mat *isl_mat_swap_cols(struct isl_mat *mat, unsigned i, unsigned j);
+struct isl_mat *isl_mat_swap_rows(struct isl_mat *mat, unsigned i, unsigned j);
+
+struct isl_vec *isl_mat_vec_product(struct isl_mat *mat, struct isl_vec *vec);
+struct isl_vec *isl_vec_mat_product(struct isl_vec *vec, struct isl_mat *mat);
+__isl_give isl_vec *isl_mat_vec_inverse_product(__isl_take isl_mat *mat,
+ __isl_take isl_vec *vec);
+struct isl_mat *isl_mat_aff_direct_sum(struct isl_mat *left,
+ struct isl_mat *right);
+__isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1,
+ __isl_take isl_mat *mat2);
+struct isl_mat *isl_mat_left_hermite(struct isl_mat *M,
+ int neg, struct isl_mat **U, struct isl_mat **Q);
+struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat);
+struct isl_mat *isl_mat_inverse_product(struct isl_mat *left,
+ struct isl_mat *right);
+__isl_give isl_mat *isl_mat_product(__isl_take isl_mat *left,
+ __isl_take isl_mat *right);
+struct isl_mat *isl_mat_transpose(struct isl_mat *mat);
+__isl_give isl_mat *isl_mat_right_inverse(__isl_take isl_mat *mat);
+__isl_give isl_mat *isl_mat_right_kernel(__isl_take isl_mat *mat);
+
+__isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat);
+__isl_give isl_mat *isl_mat_normalize_row(__isl_take isl_mat *mat, int row);
+
+struct isl_mat *isl_mat_drop_cols(struct isl_mat *mat,
+ unsigned col, unsigned n);
+struct isl_mat *isl_mat_drop_rows(struct isl_mat *mat,
+ unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_insert_cols(__isl_take isl_mat *mat,
+ unsigned col, unsigned n);
+__isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat,
+ unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_move_cols(__isl_take isl_mat *mat,
+ unsigned dst_col, unsigned src_col, unsigned n);
+__isl_give isl_mat *isl_mat_add_rows(__isl_take isl_mat *mat, unsigned n);
+__isl_give isl_mat *isl_mat_insert_zero_cols(__isl_take isl_mat *mat,
+ unsigned first, unsigned n);
+__isl_give isl_mat *isl_mat_add_zero_cols(__isl_take isl_mat *mat, unsigned n);
+__isl_give isl_mat *isl_mat_insert_zero_rows(__isl_take isl_mat *mat,
+ unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_add_zero_rows(__isl_take isl_mat *mat, unsigned n);
+
+void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col);
+
+struct isl_mat *isl_mat_unimodular_complete(struct isl_mat *M, int row);
+
+__isl_give isl_mat *isl_mat_from_row_vec(__isl_take isl_vec *vec);
+__isl_give isl_mat *isl_mat_concat(__isl_take isl_mat *top,
+ __isl_take isl_mat *bot);
+__isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
+ __isl_take isl_vec *bot);
+
+int isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2);
+
+int isl_mat_initial_non_zero_cols(__isl_keep isl_mat *mat);
+
+void isl_mat_print_internal(__isl_keep isl_mat *mat, FILE *out, int indent);
+void isl_mat_dump(__isl_keep isl_mat *mat);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/multi.h b/polly/lib/External/isl/include/isl/multi.h
new file mode 100644
index 00000000000..ddcdc20fabd
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/multi.h
@@ -0,0 +1,123 @@
+#ifndef ISL_MULTI_H
+#define ISL_MULTI_H
+
+#include <isl/space.h>
+#include <isl/list.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_DECLARE_MULTI(BASE) \
+unsigned isl_multi_##BASE##_dim(__isl_keep isl_multi_##BASE *multi, \
+ enum isl_dim_type type); \
+isl_ctx *isl_multi_##BASE##_get_ctx( \
+ __isl_keep isl_multi_##BASE *multi); \
+__isl_give isl_space *isl_multi_##BASE##_get_space( \
+ __isl_keep isl_multi_##BASE *multi); \
+__isl_give isl_space *isl_multi_##BASE##_get_domain_space( \
+ __isl_keep isl_multi_##BASE *multi); \
+int isl_multi_##BASE##_find_dim_by_name( \
+ __isl_keep isl_multi_##BASE *multi, \
+ enum isl_dim_type type, const char *name); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_##BASE##_list( \
+ __isl_take isl_space *space, __isl_take isl_##BASE##_list *list); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_zero( \
+ __isl_take isl_space *space); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_copy( \
+ __isl_keep isl_multi_##BASE *multi); \
+__isl_null isl_multi_##BASE *isl_multi_##BASE##_free( \
+ __isl_take isl_multi_##BASE *multi); \
+int isl_multi_##BASE##_plain_is_equal( \
+ __isl_keep isl_multi_##BASE *multi1, \
+ __isl_keep isl_multi_##BASE *multi2); \
+int isl_multi_##BASE##_find_dim_by_id( \
+ __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type, \
+ __isl_keep isl_id *id); \
+__isl_give isl_id *isl_multi_##BASE##_get_dim_id( \
+ __isl_take isl_multi_##BASE *multi, \
+ enum isl_dim_type type, unsigned pos); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_dim_name( \
+ __isl_take isl_multi_##BASE *multi, \
+ enum isl_dim_type type, unsigned pos, const char *s); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_dim_id( \
+ __isl_take isl_multi_##BASE *multi, \
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id); \
+const char *isl_multi_##BASE##_get_tuple_name( \
+ __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type); \
+int isl_multi_##BASE##_has_tuple_id(__isl_keep isl_multi_##BASE *multi, \
+ enum isl_dim_type type); \
+__isl_give isl_id *isl_multi_##BASE##_get_tuple_id( \
+ __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_tuple_name( \
+ __isl_take isl_multi_##BASE *multi, \
+ enum isl_dim_type type, const char *s); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_tuple_id( \
+ __isl_take isl_multi_##BASE *multi, \
+ enum isl_dim_type type, __isl_take isl_id *id); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_reset_tuple_id( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_reset_user( \
+ __isl_take isl_multi_##BASE *multi); \
+int isl_multi_##BASE##_involves_dims( \
+ __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned first, unsigned n); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_insert_dims( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned first, unsigned n); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_add_dims( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned n); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_drop_dims( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned first, unsigned n); \
+__isl_give isl_##BASE *isl_multi_##BASE##_get_##BASE( \
+ __isl_keep isl_multi_##BASE *multi, int pos); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_##BASE( \
+ __isl_take isl_multi_##BASE *multi, int pos, \
+ __isl_take isl_##BASE *el); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_splice( \
+ __isl_take isl_multi_##BASE *multi1, unsigned pos, \
+ __isl_take isl_multi_##BASE *multi2); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_splice( \
+ __isl_take isl_multi_##BASE *multi1, unsigned in_pos, \
+ unsigned out_pos, __isl_take isl_multi_##BASE *multi2); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_flatten_range( \
+ __isl_take isl_multi_##BASE *multi); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_flat_range_product( \
+ __isl_take isl_multi_##BASE *multi1, \
+ __isl_take isl_multi_##BASE *multi2); \
+__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##_product( \
+ __isl_take isl_multi_##BASE *multi1, \
+ __isl_take isl_multi_##BASE *multi2); \
+int isl_multi_##BASE##_range_is_wrapping( \
+ __isl_keep isl_multi_##BASE *multi); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_factor_domain( \
+ __isl_take isl_multi_##BASE *multi); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_factor_range( \
+ __isl_take isl_multi_##BASE *multi); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_val( \
+ __isl_take isl_multi_##BASE *multi, __isl_take isl_val *v); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_val( \
+ __isl_take isl_multi_##BASE *multi, __isl_take isl_val *v); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_multi_val( \
+ __isl_take isl_multi_##BASE *multi, \
+ __isl_take isl_multi_val *mv); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_multi_val( \
+ __isl_take isl_multi_##BASE *multi, \
+ __isl_take isl_multi_val *mv); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_align_params( \
+ __isl_take isl_multi_##BASE *multi, \
+ __isl_take isl_space *model); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_range( \
+ __isl_take isl_multi_##BASE *multi);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/obj.h b/polly/lib/External/isl/include/isl/obj.h
new file mode 100644
index 00000000000..7c796f3473e
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/obj.h
@@ -0,0 +1,55 @@
+#ifndef ISL_OBJ_H
+#define ISL_OBJ_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+#include <isl/polynomial_type.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_obj_vtable {
+ void *(*copy)(void *v1);
+ void *(*add)(void *v1, void *v2);
+ __isl_give isl_printer *(*print)(__isl_take isl_printer *p, void *v);
+ void (*free)(void *v);
+};
+typedef struct isl_obj_vtable *isl_obj_type;
+extern struct isl_obj_vtable isl_obj_none_vtable;
+#define isl_obj_none (&isl_obj_none_vtable)
+extern struct isl_obj_vtable isl_obj_int_vtable;
+#define isl_obj_int (&isl_obj_int_vtable)
+extern struct isl_obj_vtable isl_obj_val_vtable;
+#define isl_obj_val (&isl_obj_val_vtable)
+extern struct isl_obj_vtable isl_obj_set_vtable;
+#define isl_obj_set (&isl_obj_set_vtable)
+extern struct isl_obj_vtable isl_obj_union_set_vtable;
+#define isl_obj_union_set (&isl_obj_union_set_vtable)
+extern struct isl_obj_vtable isl_obj_map_vtable;
+#define isl_obj_map (&isl_obj_map_vtable)
+extern struct isl_obj_vtable isl_obj_union_map_vtable;
+#define isl_obj_union_map (&isl_obj_union_map_vtable)
+extern struct isl_obj_vtable isl_obj_pw_multi_aff_vtable;
+#define isl_obj_pw_multi_aff (&isl_obj_pw_multi_aff_vtable)
+extern struct isl_obj_vtable isl_obj_pw_qpolynomial_vtable;
+#define isl_obj_pw_qpolynomial (&isl_obj_pw_qpolynomial_vtable)
+extern struct isl_obj_vtable isl_obj_union_pw_qpolynomial_vtable;
+#define isl_obj_union_pw_qpolynomial (&isl_obj_union_pw_qpolynomial_vtable)
+extern struct isl_obj_vtable isl_obj_pw_qpolynomial_fold_vtable;
+#define isl_obj_pw_qpolynomial_fold (&isl_obj_pw_qpolynomial_fold_vtable)
+extern struct isl_obj_vtable isl_obj_union_pw_qpolynomial_fold_vtable;
+#define isl_obj_union_pw_qpolynomial_fold (&isl_obj_union_pw_qpolynomial_fold_vtable)
+struct isl_obj {
+ isl_obj_type type;
+ void *v;
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/options.h b/polly/lib/External/isl/include/isl/options.h
new file mode 100644
index 00000000000..b0c9a436967
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/options.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_OPTIONS_H
+#define ISL_OPTIONS_H
+
+#include <isl/arg.h>
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_options;
+
+ISL_ARG_DECL(isl_options, struct isl_options, isl_options_args)
+
+#define ISL_BOUND_BERNSTEIN 0
+#define ISL_BOUND_RANGE 1
+int isl_options_set_bound(isl_ctx *ctx, int val);
+int isl_options_get_bound(isl_ctx *ctx);
+
+#define ISL_ON_ERROR_WARN 0
+#define ISL_ON_ERROR_CONTINUE 1
+#define ISL_ON_ERROR_ABORT 2
+int isl_options_set_on_error(isl_ctx *ctx, int val);
+int isl_options_get_on_error(isl_ctx *ctx);
+
+int isl_options_set_gbr_only_first(isl_ctx *ctx, int val);
+int isl_options_get_gbr_only_first(isl_ctx *ctx);
+
+#define ISL_SCHEDULE_ALGORITHM_ISL 0
+#define ISL_SCHEDULE_ALGORITHM_FEAUTRIER 1
+int isl_options_set_schedule_algorithm(isl_ctx *ctx, int val);
+int isl_options_get_schedule_algorithm(isl_ctx *ctx);
+
+int isl_options_set_coalesce_bounded_wrapping(isl_ctx *ctx, int val);
+int isl_options_get_coalesce_bounded_wrapping(isl_ctx *ctx);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/point.h b/polly/lib/External/isl/include/isl/point.h
new file mode 100644
index 00000000000..3247ebb27c5
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/point.h
@@ -0,0 +1,45 @@
+#ifndef ISL_POINT_H
+#define ISL_POINT_H
+
+#include <stdio.h>
+#include <isl/space.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_point;
+typedef struct isl_point isl_point;
+
+isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt);
+__isl_give isl_space *isl_point_get_space(__isl_keep isl_point *pnt);
+
+__isl_give isl_point *isl_point_zero(__isl_take isl_space *dim);
+__isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt);
+void isl_point_free(__isl_take isl_point *pnt);
+
+__isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
+ enum isl_dim_type type, int pos);
+__isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+__isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val);
+__isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val);
+
+__isl_give isl_point *isl_point_void(__isl_take isl_space *dim);
+int isl_point_is_void(__isl_keep isl_point *pnt);
+
+__isl_give isl_printer *isl_printer_print_point(
+ __isl_take isl_printer *printer, __isl_keep isl_point *pnt);
+void isl_point_dump(__isl_keep isl_point *pnt);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/polynomial.h b/polly/lib/External/isl/include/isl/polynomial.h
new file mode 100644
index 00000000000..f7b55a55bf7
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/polynomial.h
@@ -0,0 +1,623 @@
+#ifndef ISL_POLYNOMIAL_H
+#define ISL_POLYNOMIAL_H
+
+#include <isl/ctx.h>
+#include <isl/constraint.h>
+#include <isl/space.h>
+#include <isl/set_type.h>
+#include <isl/point.h>
+#include <isl/printer.h>
+#include <isl/union_set_type.h>
+#include <isl/aff_type.h>
+#include <isl/polynomial_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp);
+__isl_give isl_space *isl_qpolynomial_get_domain_space(
+ __isl_keep isl_qpolynomial *qp);
+__isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp);
+unsigned isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
+ enum isl_dim_type type);
+int isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_val *isl_qpolynomial_get_constant_val(
+ __isl_keep isl_qpolynomial *qp);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
+ __isl_take isl_space *space, __isl_take isl_val *val);
+__isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp);
+__isl_null isl_qpolynomial *isl_qpolynomial_free(
+ __isl_take isl_qpolynomial *qp);
+
+int isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,
+ __isl_keep isl_qpolynomial *qp2);
+int isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,
+ unsigned power);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_val *v);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_down_val(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_val *v);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
+ __isl_take isl_qpolynomial *qp, enum isl_dim_type type,
+ unsigned first, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_add_dims(
+ __isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(
+ __isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_substitute(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n,
+ __isl_keep isl_qpolynomial **subs);
+
+int isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
+ __isl_keep isl_basic_set *bset,
+ int (*fn)(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, void *user), void *user);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
+ __isl_take isl_qpolynomial *poly);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_align_params(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *model);
+
+isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term);
+
+__isl_give isl_term *isl_term_copy(__isl_keep isl_term *term);
+void isl_term_free(__isl_take isl_term *term);
+
+unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type);
+__isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term);
+int isl_term_get_exp(__isl_keep isl_term *term,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos);
+
+int isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
+ int (*fn)(__isl_take isl_term *term, void *user), void *user);
+
+__isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
+ __isl_take isl_point *pnt);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *context);
+__isl_give isl_qpolynomial *isl_qpolynomial_gist(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *context);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_constraint(
+ __isl_take isl_constraint *c, enum isl_dim_type type, unsigned pos);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
+ __isl_take isl_qpolynomial *qp);
+
+__isl_give isl_printer *isl_printer_print_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp);
+void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
+ unsigned output_format);
+void isl_qpolynomial_dump(__isl_keep isl_qpolynomial *qp);
+
+isl_ctx *isl_pw_qpolynomial_get_ctx(__isl_keep isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_plain_is_equal(__isl_keep isl_pw_qpolynomial *pwqp1,
+ __isl_keep isl_pw_qpolynomial *pwqp2);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero(__isl_take isl_space *dim);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
+ __isl_take isl_qpolynomial *qp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+__isl_null isl_pw_qpolynomial *isl_pw_qpolynomial_free(
+ __isl_take isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_is_zero(__isl_keep isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_space *isl_pw_qpolynomial_get_domain_space(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+__isl_give isl_space *isl_pw_qpolynomial_get_space(
+ __isl_keep isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_reset_domain_space(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_space *dim);
+unsigned isl_pw_qpolynomial_dim(__isl_keep isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type);
+int isl_pw_qpolynomial_involves_dims(__isl_keep isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+int isl_pw_qpolynomial_has_equal_space(__isl_keep isl_pw_qpolynomial *pwqp1,
+ __isl_keep isl_pw_qpolynomial *pwqp2);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_set_dim_name(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+int isl_pw_qpolynomial_find_dim_by_name(__isl_keep isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_set *isl_pw_qpolynomial_domain(__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_domain(
+ __isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_params(
+ __isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_project_domain_on_params(
+ __isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_drop_dims(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_dims(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sub(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_disjoint(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_neg(
+ __isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_scale_val(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_scale_down_val(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
+ __isl_take isl_pw_qpolynomial *pwqp, unsigned exponent);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_insert_dims(
+ __isl_take isl_pw_qpolynomial *pwqp, enum isl_dim_type type,
+ unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_dims(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_move_dims(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_fix_val(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned n, __isl_take isl_val *v);
+
+__isl_give isl_val *isl_pw_qpolynomial_eval(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_point *pnt);
+
+__isl_give isl_val *isl_pw_qpolynomial_max(__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_val *isl_pw_qpolynomial_min(__isl_take isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_foreach_piece(__isl_keep isl_pw_qpolynomial *pwqp,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
+ void *user), void *user);
+int isl_pw_qpolynomial_foreach_lifted_piece(__isl_keep isl_pw_qpolynomial *pwqp,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
+ void *user), void *user);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(
+ __isl_take isl_pw_aff *pwaff);
+
+__isl_constructor
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
+ const char *str);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
+ FILE *input);
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp);
+void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
+ unsigned output_format);
+void isl_pw_qpolynomial_dump(__isl_keep isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_coalesce(
+ __isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_set *context);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist_params(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_set *context);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_periods(
+ __isl_take isl_pw_qpolynomial *pwqp, int max_periods);
+
+__isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
+ __isl_take isl_basic_set *bset,
+ __isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset));
+
+isl_ctx *isl_qpolynomial_fold_get_ctx(__isl_keep isl_qpolynomial_fold *fold);
+enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
+ __isl_take isl_space *dim);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
+ enum isl_fold type, __isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
+ __isl_keep isl_qpolynomial_fold *fold);
+void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold);
+
+int isl_qpolynomial_fold_is_empty(__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_space(
+ __isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_val(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_down_val(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned first, unsigned n,
+ __isl_keep isl_qpolynomial **subs);
+
+__isl_give isl_val *isl_qpolynomial_fold_eval(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context);
+
+int isl_qpolynomial_fold_foreach_qpolynomial(
+ __isl_keep isl_qpolynomial_fold *fold,
+ int (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_qpolynomial_fold(
+ __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold);
+void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, FILE *out,
+ unsigned output_format);
+void isl_qpolynomial_fold_dump(__isl_keep isl_qpolynomial_fold *fold);
+
+isl_ctx *isl_pw_qpolynomial_fold_get_ctx(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+int isl_pw_qpolynomial_fold_plain_is_equal(
+ __isl_keep isl_pw_qpolynomial_fold *pwf1,
+ __isl_keep isl_pw_qpolynomial_fold *pwf2);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
+ enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_alloc(
+ enum isl_fold type,
+ __isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_copy(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_null isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_free(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+
+int isl_pw_qpolynomial_fold_is_zero(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_domain_space(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_space(
+ __isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_reset_space(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_space *dim);
+unsigned isl_pw_qpolynomial_fold_dim(__isl_keep isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type);
+int isl_pw_qpolynomial_fold_has_equal_space(
+ __isl_keep isl_pw_qpolynomial_fold *pwf1,
+ __isl_keep isl_pw_qpolynomial_fold *pwf2);
+
+size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_zero(
+ __isl_take isl_space *dim, enum isl_fold type);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_set_dim_name(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+int isl_pw_qpolynomial_fold_find_dim_by_name(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_set *isl_pw_qpolynomial_fold_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_intersect_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_intersect_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fold(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add_disjoint(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_scale_val(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_scale_down_val(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_val *v);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_project_domain_on_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_drop_dims(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_move_dims(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_val *isl_pw_qpolynomial_fold_eval(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_point *pnt);
+
+int isl_pw_qpolynomial_fold_foreach_piece(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold,
+ void *user), void *user);
+int isl_pw_qpolynomial_fold_foreach_lifted_piece(
+ __isl_keep isl_pw_qpolynomial_fold *pwf,
+ int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold,
+ void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf);
+void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
+ FILE *out, unsigned output_format);
+void isl_pw_qpolynomial_fold_dump(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_coalesce(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_gist(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *context);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_gist_params(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *context);
+
+__isl_give isl_val *isl_pw_qpolynomial_fold_max(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_val *isl_pw_qpolynomial_fold_min(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
+ __isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type, int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
+ __isl_take isl_pw_qpolynomial_fold *pwf, int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_set_apply_pw_qpolynomial_fold(
+ __isl_take isl_set *set, __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
+ __isl_take isl_map *map, __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
+ __isl_take isl_pw_qpolynomial *pwqp, int sign);
+
+isl_ctx *isl_union_pw_qpolynomial_get_ctx(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+
+unsigned isl_union_pw_qpolynomial_dim(
+ __isl_keep isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type);
+
+int isl_union_pw_qpolynomial_plain_is_equal(
+ __isl_keep isl_union_pw_qpolynomial *upwqp1,
+ __isl_keep isl_union_pw_qpolynomial *upwqp2);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_from_pw_qpolynomial(__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_zero(
+ __isl_take isl_space *dim);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_add_pw_qpolynomial(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_copy(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+__isl_null isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_free(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+
+__isl_constructor
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_neg(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_add(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_sub(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_val(
+ __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_val *v);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_down_val(
+ __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_val *v);
+
+__isl_give isl_union_set *isl_union_pw_qpolynomial_domain(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_intersect_domain(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_intersect_params(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_set *set);
+
+__isl_give isl_space *isl_union_pw_qpolynomial_get_space(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
+
+int isl_union_pw_qpolynomial_find_dim_by_name(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_val *isl_union_pw_qpolynomial_eval(
+ __isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_point *pnt);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_coalesce(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_gist(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_union_set *context);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_gist_params(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_set *context);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_align_params(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ __isl_take isl_space *model);
+
+int isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp,
+ int (*fn)(__isl_take isl_pw_qpolynomial *pwqp, void *user), void *user);
+__isl_give isl_pw_qpolynomial *isl_union_pw_qpolynomial_extract_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp, __isl_take isl_space *dim);
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp);
+
+isl_ctx *isl_union_pw_qpolynomial_fold_get_ctx(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+unsigned isl_union_pw_qpolynomial_fold_dim(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type);
+
+int isl_union_pw_qpolynomial_fold_plain_is_equal(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf1,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf2);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(__isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_zero(
+ __isl_take isl_space *dim, enum isl_fold type);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+ __isl_take isl_union_pw_qpolynomial_fold *upwqp,
+ __isl_take isl_pw_qpolynomial_fold *pwqp);
+__isl_null isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_free(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_copy(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf1,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf2);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_scale_val(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_val *v);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_scale_down_val(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_val *v);
+
+__isl_give isl_union_set *isl_union_pw_qpolynomial_fold_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_intersect_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_intersect_params(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_set *set);
+
+enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+int isl_union_pw_qpolynomial_fold_find_dim_by_name(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_val *isl_union_pw_qpolynomial_fold_eval(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_point *pnt);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_coalesce(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_gist(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *context);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_gist_params(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_set *context);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_align_params(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_space *model);
+
+int isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf,
+ int (*fn)(__isl_take isl_pw_qpolynomial_fold *pwf,
+ void *user), void *user);
+__isl_give isl_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_extract_pw_qpolynomial_fold(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_space *dim);
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_bound(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_fold type, int *tight);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_set_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
+ __isl_take isl_union_pw_qpolynomial *upwqp, int sign);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/polynomial_type.h b/polly/lib/External/isl/include/isl/polynomial_type.h
new file mode 100644
index 00000000000..df432bda911
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/polynomial_type.h
@@ -0,0 +1,31 @@
+#ifndef ISL_POLYNOMIAL_TYPE_H
+#define ISL_POLYNOMIAL_TYPE_H
+
+struct isl_qpolynomial;
+typedef struct isl_qpolynomial isl_qpolynomial;
+
+struct isl_term;
+typedef struct isl_term isl_term;
+
+struct __isl_export isl_pw_qpolynomial;
+typedef struct isl_pw_qpolynomial isl_pw_qpolynomial;
+
+enum isl_fold {
+ isl_fold_min,
+ isl_fold_max,
+ isl_fold_list
+};
+
+struct isl_qpolynomial_fold;
+typedef struct isl_qpolynomial_fold isl_qpolynomial_fold;
+
+struct isl_pw_qpolynomial_fold;
+typedef struct isl_pw_qpolynomial_fold isl_pw_qpolynomial_fold;
+
+struct __isl_export isl_union_pw_qpolynomial;
+typedef struct isl_union_pw_qpolynomial isl_union_pw_qpolynomial;
+
+struct isl_union_pw_qpolynomial_fold;
+typedef struct isl_union_pw_qpolynomial_fold isl_union_pw_qpolynomial_fold;
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/printer.h b/polly/lib/External/isl/include/isl/printer.h
new file mode 100644
index 00000000000..f43bfbc5f24
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/printer.h
@@ -0,0 +1,62 @@
+#ifndef ISL_PRINTER_H
+#define ISL_PRINTER_H
+
+#include <stdio.h>
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_printer;
+typedef struct isl_printer isl_printer;
+
+__isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file);
+__isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx);
+__isl_null isl_printer *isl_printer_free(__isl_take isl_printer *printer);
+
+isl_ctx *isl_printer_get_ctx(__isl_keep isl_printer *printer);
+FILE *isl_printer_get_file(__isl_keep isl_printer *printer);
+
+__isl_give char *isl_printer_get_str(__isl_keep isl_printer *printer);
+
+__isl_give isl_printer *isl_printer_set_indent(__isl_take isl_printer *p,
+ int indent);
+__isl_give isl_printer *isl_printer_indent(__isl_take isl_printer *p,
+ int indent);
+
+#define ISL_FORMAT_ISL 0
+#define ISL_FORMAT_POLYLIB 1
+#define ISL_FORMAT_POLYLIB_CONSTRAINTS 2
+#define ISL_FORMAT_OMEGA 3
+#define ISL_FORMAT_C 4
+#define ISL_FORMAT_LATEX 5
+#define ISL_FORMAT_EXT_POLYLIB 6
+__isl_give isl_printer *isl_printer_set_output_format(__isl_take isl_printer *p,
+ int output_format);
+int isl_printer_get_output_format(__isl_keep isl_printer *p);
+
+__isl_give isl_printer *isl_printer_set_indent_prefix(__isl_take isl_printer *p,
+ const char *prefix);
+__isl_give isl_printer *isl_printer_set_prefix(__isl_take isl_printer *p,
+ const char *prefix);
+__isl_give isl_printer *isl_printer_set_suffix(__isl_take isl_printer *p,
+ const char *suffix);
+__isl_give isl_printer *isl_printer_set_isl_int_width(__isl_take isl_printer *p,
+ int width);
+
+__isl_give isl_printer *isl_printer_start_line(__isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
+ double d);
+__isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i);
+__isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
+ const char *s);
+
+__isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/schedule.h b/polly/lib/External/isl/include/isl/schedule.h
new file mode 100644
index 00000000000..83b89d910c2
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/schedule.h
@@ -0,0 +1,93 @@
+#ifndef ISL_SCHEDULE_H
+#define ISL_SCHEDULE_H
+
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+#include <isl/band.h>
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_schedule_constraints;
+typedef struct isl_schedule_constraints isl_schedule_constraints;
+struct isl_schedule;
+typedef struct isl_schedule isl_schedule;
+
+int isl_options_set_schedule_max_coefficient(isl_ctx *ctx, int val);
+int isl_options_get_schedule_max_coefficient(isl_ctx *ctx);
+
+int isl_options_set_schedule_max_constant_term(isl_ctx *ctx, int val);
+int isl_options_get_schedule_max_constant_term(isl_ctx *ctx);
+
+int isl_options_set_schedule_maximize_band_depth(isl_ctx *ctx, int val);
+int isl_options_get_schedule_maximize_band_depth(isl_ctx *ctx);
+
+int isl_options_set_schedule_outer_coincidence(isl_ctx *ctx, int val);
+int isl_options_get_schedule_outer_coincidence(isl_ctx *ctx);
+
+int isl_options_set_schedule_split_scaled(isl_ctx *ctx, int val);
+int isl_options_get_schedule_split_scaled(isl_ctx *ctx);
+
+int isl_options_set_schedule_separate_components(isl_ctx *ctx, int val);
+int isl_options_get_schedule_separate_components(isl_ctx *ctx);
+
+#define ISL_SCHEDULE_FUSE_MAX 0
+#define ISL_SCHEDULE_FUSE_MIN 1
+int isl_options_set_schedule_fuse(isl_ctx *ctx, int val);
+int isl_options_get_schedule_fuse(isl_ctx *ctx);
+
+__isl_give isl_schedule_constraints *isl_schedule_constraints_copy(
+ __isl_keep isl_schedule_constraints *sc);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_on_domain(
+ __isl_take isl_union_set *domain);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *validity);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_coincidence(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *coincidence);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_proximity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *proximity);
+__isl_give isl_schedule_constraints *
+isl_schedule_constraints_set_conditional_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *condition,
+ __isl_take isl_union_map *validity);
+__isl_null isl_schedule_constraints *isl_schedule_constraints_free(
+ __isl_take isl_schedule_constraints *sc);
+
+isl_ctx *isl_schedule_constraints_get_ctx(
+ __isl_keep isl_schedule_constraints *sc);
+
+void isl_schedule_constraints_dump(__isl_keep isl_schedule_constraints *sc);
+
+__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
+ __isl_take isl_schedule_constraints *sc);
+
+__isl_give isl_schedule *isl_union_set_compute_schedule(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_union_map *validity,
+ __isl_take isl_union_map *proximity);
+__isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched);
+__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_give isl_band_list *isl_schedule_get_band_forest(
+ __isl_keep isl_schedule *schedule);
+
+__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);
+
+int isl_schedule_foreach_band(__isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_band *band, void *user), void *user);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/set.h b/polly/lib/External/isl/include/isl/set.h
new file mode 100644
index 00000000000..73b6570621f
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/set.h
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_SET_H
+#define ISL_SET_H
+
+#include <isl/map_type.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/mat.h>
+#include <isl/point.h>
+#include <isl/local_space.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset);
+unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset);
+unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset);
+unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type);
+
+unsigned isl_set_n_dim(__isl_keep isl_set *set);
+unsigned isl_set_n_param(__isl_keep isl_set *set);
+unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type);
+
+isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset);
+isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set);
+__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset);
+__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set);
+__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
+ __isl_take isl_space *dim);
+
+__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
+ int pos);
+
+__isl_give isl_local_space *isl_basic_set_get_local_space(
+ __isl_keep isl_basic_set *bset);
+
+const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset);
+int isl_set_has_tuple_name(__isl_keep isl_set *set);
+const char *isl_set_get_tuple_name(__isl_keep isl_set *set);
+__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
+ __isl_take isl_basic_set *set, const char *s);
+__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
+ const char *s);
+const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_set *isl_basic_set_set_dim_name(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, const char *s);
+int isl_set_has_dim_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+const char *isl_set_get_dim_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_set *isl_basic_set_set_tuple_id(
+ __isl_take isl_basic_set *bset, __isl_take isl_id *id);
+__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_set_has_dim_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
+ __isl_take isl_id *id);
+__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set);
+int isl_set_has_tuple_id(__isl_keep isl_set *set);
+__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set);
+__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set);
+
+int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
+ __isl_keep isl_id *id);
+int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
+ const char *name);
+
+int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset);
+
+struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
+ unsigned nparam, unsigned dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_extend_constraints(
+ struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset);
+__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_universe_like_set(
+ __isl_keep isl_set *model);
+__isl_give isl_basic_set *isl_basic_set_positive_orthant(
+ __isl_take isl_space *space);
+void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
+ FILE *out, int indent);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_intersect(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_intersect_params(
+ __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_apply(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_affine_hull(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_remove_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_detect_equalities(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_remove_redundancies(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_remove_redundancies(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_basic_set_list_intersect(
+ __isl_take struct isl_basic_set_list *list);
+__isl_give isl_basic_set *isl_basic_set_list_product(
+ __isl_take struct isl_basic_set_list *list);
+
+__isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
+ FILE *input);
+__isl_constructor
+__isl_give isl_basic_set *isl_basic_set_read_from_str(isl_ctx *ctx,
+ const char *str);
+__isl_give isl_set *isl_set_read_from_file(isl_ctx *ctx, FILE *input);
+__isl_constructor
+__isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str);
+void isl_basic_set_dump(__isl_keep isl_basic_set *bset);
+void isl_set_dump(__isl_keep isl_set *set);
+__isl_give isl_printer *isl_printer_print_basic_set(
+ __isl_take isl_printer *printer, __isl_keep isl_basic_set *bset);
+__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *printer,
+ __isl_keep isl_set *map);
+void isl_basic_set_print(__isl_keep isl_basic_set *bset, FILE *out, int indent,
+ const char *prefix, const char *suffix, unsigned output_format);
+void isl_set_print(__isl_keep struct isl_set *set, FILE *out, int indent,
+ unsigned output_format);
+__isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *value);
+__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *value);
+
+__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+
+struct isl_basic_set *isl_basic_set_from_underlying_set(
+ struct isl_basic_set *bset, struct isl_basic_set *like);
+struct isl_set *isl_set_from_underlying_set(
+ struct isl_set *set, struct isl_basic_set *like);
+struct isl_set *isl_set_to_underlying_set(struct isl_set *set);
+
+__isl_export
+int isl_basic_set_is_equal(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2);
+int isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+
+__isl_give isl_set *isl_basic_set_partial_lexmin(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_set *isl_basic_set_partial_lexmax(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_set *isl_set_partial_lexmin(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_set *isl_set_partial_lexmax(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty);
+__isl_export
+__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_set_lexmin(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_set *isl_set_lexmax(__isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_set_lexmin_pw_multi_aff(
+ __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_set_lexmax_pw_multi_aff(
+ __isl_take isl_set *set);
+
+__isl_export
+__isl_give isl_set *isl_basic_set_union(
+ __isl_take isl_basic_set *bset1,
+ __isl_take isl_basic_set *bset2);
+
+int isl_basic_set_compare_at(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2, int pos);
+int isl_set_follows_at(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2, int pos);
+
+__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_from_params(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_params(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set);
+
+int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, unsigned n, int *signs);
+
+int isl_basic_set_is_universe(__isl_keep isl_basic_set *bset);
+int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset);
+ISL_DEPRECATED
+int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_basic_set_is_empty(__isl_keep isl_basic_set *bset);
+int isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2);
+
+struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned dim, int n, unsigned flags);
+struct isl_set *isl_set_extend(struct isl_set *base,
+ unsigned nparam, unsigned dim);
+__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim);
+struct isl_set *isl_set_empty_like(struct isl_set *set);
+__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim);
+__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model);
+__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *bset);
+struct isl_set *isl_set_finalize(struct isl_set *set);
+__isl_give isl_set *isl_set_copy(__isl_keep isl_set *set);
+__isl_null isl_set *isl_set_free(__isl_take isl_set *set);
+struct isl_set *isl_set_dup(struct isl_set *set);
+__isl_constructor
+__isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set);
+__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_export
+__isl_give isl_set *isl_set_detect_equalities(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_set *isl_set_affine_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_convex_hull(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_set *isl_set_polyhedral_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_simple_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull(
+ __isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
+ __isl_take isl_set *set, __isl_take isl_set_list *list);
+struct isl_basic_set *isl_set_bounded_simple_hull(struct isl_set *set);
+__isl_give isl_set *isl_set_recession_cone(__isl_take isl_set *set);
+
+struct isl_set *isl_set_union_disjoint(
+ struct isl_set *set1, struct isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_union(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_basic_set *isl_basic_set_flat_product(
+ __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2);
+__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_intersect(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
+ __isl_take isl_set *params);
+__isl_export
+__isl_give isl_set *isl_set_subtract(
+ __isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_complement(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_set *isl_set_apply(
+ __isl_take isl_set *set,
+ __isl_take isl_map *map);
+__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
+ __isl_take isl_multi_aff *ma);
+__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
+ __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
+ __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+struct isl_set *isl_set_fix_dim_si(struct isl_set *set,
+ unsigned dim, int value);
+__isl_give isl_basic_set *isl_basic_set_insert_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned n);
+/* deprecated */
+__isl_give isl_basic_set *isl_basic_set_add(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_project_out(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_divs(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_eliminate(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_set *isl_set_eliminate_dims(struct isl_set *set,
+ unsigned first, unsigned n);
+__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_drop_constraints_involving_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+int isl_set_involves_dims(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent);
+int isl_set_plain_is_empty(__isl_keep isl_set *set);
+ISL_DEPRECATED
+int isl_set_fast_is_empty(__isl_keep isl_set *set);
+int isl_set_plain_is_universe(__isl_keep isl_set *set);
+ISL_DEPRECATED
+int isl_set_fast_is_universe(__isl_keep isl_set *set);
+int isl_set_is_params(__isl_keep isl_set *set);
+__isl_export
+int isl_set_is_empty(__isl_keep isl_set *set);
+int isl_set_is_bounded(__isl_keep isl_set *set);
+__isl_export
+int isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_is_singleton(__isl_keep isl_set *set);
+int isl_set_is_box(__isl_keep isl_set *set);
+int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+
+__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_neg(__isl_take isl_set *set);
+
+__isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set);
+struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset);
+__isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set);
+
+struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set);
+struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
+ struct isl_basic_set *bset);
+
+__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+int isl_set_dim_is_bounded(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos);
+
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_gist(__isl_take isl_basic_set *bset,
+ __isl_take isl_basic_set *context);
+__isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *context);
+__isl_export
+__isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
+ __isl_take isl_set *context);
+__isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
+ __isl_take isl_set *context);
+int isl_set_dim_residue_class_val(__isl_keep isl_set *set,
+ int pos, __isl_give isl_val **modulo, __isl_give isl_val **residue);
+
+__isl_export
+__isl_give isl_set *isl_set_coalesce(__isl_take isl_set *set);
+
+int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+ISL_DEPRECATED
+int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+ISL_DEPRECATED
+int isl_set_fast_is_disjoint(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2);
+
+uint32_t isl_set_get_hash(struct isl_set *set);
+
+int isl_set_dim_is_unique(struct isl_set *set, unsigned dim);
+
+int isl_set_n_basic_set(__isl_keep isl_set *set);
+__isl_export
+int isl_set_foreach_basic_set(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user);
+
+int isl_set_foreach_point(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_point *pnt, void *user), void *user);
+__isl_give isl_val *isl_set_count_val(__isl_keep isl_set *set);
+
+__isl_give isl_basic_set *isl_basic_set_from_point(__isl_take isl_point *pnt);
+__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);
+__isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
+ __isl_take isl_point *pnt2);
+
+__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_lift(__isl_take isl_set *set);
+
+__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2);
+
+int isl_set_size(__isl_keep isl_set *set);
+
+__isl_give isl_basic_set *isl_basic_set_align_params(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *model);
+__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
+ __isl_take isl_space *model);
+
+__isl_give isl_mat *isl_basic_set_equalities_matrix(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+__isl_give isl_mat *isl_basic_set_inequalities_matrix(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
+ __isl_take isl_space *dim,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+
+__isl_give isl_mat *isl_basic_set_reduced_basis(__isl_keep isl_basic_set *bset);
+
+__isl_give isl_basic_set *isl_basic_set_coefficients(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_set_coefficients(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_basic_set_solutions(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_set_solutions(__isl_take isl_set *set);
+
+__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos);
+__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos);
+
+__isl_give char *isl_set_to_str(__isl_keep isl_set *set);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/set_type.h b/polly/lib/External/isl/include/isl/set_type.h
new file mode 100644
index 00000000000..ce349e1b5d4
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/set_type.h
@@ -0,0 +1,6 @@
+#ifndef ISL_SET_TYPE_H
+#define ISL_SET_TYPE_H
+
+#include <isl/map_type.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/space.h b/polly/lib/External/isl/include/isl/space.h
new file mode 100644
index 00000000000..d6fce404156
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/space.h
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_SPACE_H
+#define ISL_SPACE_H
+
+#include <isl/ctx.h>
+#include <isl/id.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_space;
+typedef struct isl_space isl_space;
+
+enum isl_dim_type {
+ isl_dim_cst,
+ isl_dim_param,
+ isl_dim_in,
+ isl_dim_out,
+ isl_dim_set = isl_dim_out,
+ isl_dim_div,
+ isl_dim_all
+};
+
+isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim);
+__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned dim);
+__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam);
+__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim);
+__isl_null isl_space *isl_space_free(__isl_take isl_space *space);
+
+int isl_space_is_params(__isl_keep isl_space *space);
+int isl_space_is_set(__isl_keep isl_space *space);
+int isl_space_is_map(__isl_keep isl_space *space);
+
+__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, const char *s);
+int isl_space_has_tuple_name(__isl_keep isl_space *space,
+ enum isl_dim_type type);
+const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type);
+__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type);
+int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type);
+__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type);
+__isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space);
+
+__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_space_has_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+
+int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type,
+ __isl_keep isl_id *id);
+int isl_space_find_dim_by_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, const char *name);
+
+int isl_space_has_dim_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos);
+__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos,
+ __isl_keep const char *name);
+__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos);
+
+__isl_give isl_space *isl_space_extend(__isl_take isl_space *dim,
+ unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_give isl_space *isl_space_add_dims(__isl_take isl_space *dim, enum isl_dim_type type,
+ unsigned n);
+__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
+ __isl_take isl_space *right);
+__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
+ __isl_take isl_space *right);
+__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
+ __isl_take isl_space *right);
+__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
+ __isl_take isl_space *right);
+__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_domain_factor_domain(
+ __isl_take isl_space *space);
+__isl_give isl_space *isl_space_domain_factor_range(
+ __isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_factor_domain(
+ __isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_factor_range(
+ __isl_take isl_space *space);
+__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_map_from_domain_and_range(
+ __isl_take isl_space *domain, __isl_take isl_space *range);
+__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned first, unsigned num);
+__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
+ unsigned first, unsigned n);
+__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
+ unsigned first, unsigned n);
+__isl_give isl_space *isl_space_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_range(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_params(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space);
+
+__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
+ __isl_take isl_space *dim2);
+
+int isl_space_is_wrapping(__isl_keep isl_space *dim);
+int isl_space_domain_is_wrapping(__isl_keep isl_space *space);
+int isl_space_range_is_wrapping(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim);
+
+int isl_space_can_zip(__isl_keep isl_space *dim);
+__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim);
+
+int isl_space_can_curry(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_curry(__isl_take isl_space *space);
+
+int isl_space_can_uncurry(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space);
+
+int isl_space_is_domain(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+int isl_space_is_range(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+int isl_space_is_equal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+int isl_space_tuple_is_equal(__isl_keep isl_space *space1,
+ enum isl_dim_type type1, __isl_keep isl_space *space2,
+ enum isl_dim_type type2);
+int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
+ __isl_keep isl_space *dim2, enum isl_dim_type dim2_type);
+ISL_DEPRECATED
+int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
+ __isl_keep isl_space *space2, enum isl_dim_type type2);
+int isl_space_compatible(__isl_keep isl_space *dim1,
+ __isl_keep isl_space *dim2);
+unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type);
+
+__isl_give char *isl_space_to_str(__isl_keep isl_space *space);
+__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim);
+void isl_space_dump(__isl_keep isl_space *dim);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/stream.h b/polly/lib/External/isl/include/isl/stream.h
new file mode 100644
index 00000000000..42734996780
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/stream.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_STREAM_H
+#define ISL_STREAM_H
+
+#include <stdio.h>
+#include <isl/hash.h>
+#include <isl/aff_type.h>
+#include <isl/obj.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum isl_token_type { ISL_TOKEN_ERROR = -1,
+ ISL_TOKEN_UNKNOWN = 256, ISL_TOKEN_VALUE,
+ ISL_TOKEN_IDENT, ISL_TOKEN_GE,
+ ISL_TOKEN_LE, ISL_TOKEN_GT, ISL_TOKEN_LT,
+ ISL_TOKEN_NE, ISL_TOKEN_EQ_EQ,
+ ISL_TOKEN_LEX_GE, ISL_TOKEN_LEX_LE,
+ ISL_TOKEN_LEX_GT, ISL_TOKEN_LEX_LT,
+ ISL_TOKEN_TO, ISL_TOKEN_AND,
+ ISL_TOKEN_OR, ISL_TOKEN_EXISTS, ISL_TOKEN_NOT,
+ ISL_TOKEN_DEF, ISL_TOKEN_INFTY, ISL_TOKEN_NAN,
+ ISL_TOKEN_MIN, ISL_TOKEN_MAX, ISL_TOKEN_RAT,
+ ISL_TOKEN_TRUE, ISL_TOKEN_FALSE,
+ ISL_TOKEN_CEILD, ISL_TOKEN_FLOORD, ISL_TOKEN_MOD,
+ ISL_TOKEN_STRING,
+ ISL_TOKEN_MAP, ISL_TOKEN_AFF,
+ ISL_TOKEN_CEIL, ISL_TOKEN_FLOOR,
+ ISL_TOKEN_IMPLIES,
+ ISL_TOKEN_LAST };
+
+struct isl_token;
+
+__isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok);
+__isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok);
+int isl_token_get_type(struct isl_token *tok);
+void isl_token_free(struct isl_token *tok);
+
+struct isl_stream {
+ struct isl_ctx *ctx;
+ FILE *file;
+ const char *str;
+ int line;
+ int col;
+ int eof;
+
+ char *buffer;
+ size_t size;
+ size_t len;
+ int c;
+ int un[5];
+ int n_un;
+
+ struct isl_token *tokens[5];
+ int n_token;
+
+ struct isl_hash_table *keywords;
+ enum isl_token_type next_type;
+};
+
+struct isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file);
+struct isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str);
+void isl_stream_free(struct isl_stream *s);
+
+void isl_stream_error(struct isl_stream *s, struct isl_token *tok, char *msg);
+
+struct isl_token *isl_stream_next_token(struct isl_stream *s);
+struct isl_token *isl_stream_next_token_on_same_line(struct isl_stream *s);
+int isl_stream_next_token_is(struct isl_stream *s, int type);
+void isl_stream_push_token(struct isl_stream *s, struct isl_token *tok);
+void isl_stream_flush_tokens(struct isl_stream *s);
+int isl_stream_eat_if_available(struct isl_stream *s, int type);
+char *isl_stream_read_ident_if_available(struct isl_stream *s);
+int isl_stream_eat(struct isl_stream *s, int type);
+int isl_stream_is_empty(struct isl_stream *s);
+int isl_stream_skip_line(struct isl_stream *s);
+
+enum isl_token_type isl_stream_register_keyword(struct isl_stream *s,
+ const char *name);
+
+struct isl_obj isl_stream_read_obj(struct isl_stream *s);
+__isl_give isl_multi_aff *isl_stream_read_multi_aff(struct isl_stream *s);
+__isl_give isl_map *isl_stream_read_map(struct isl_stream *s);
+__isl_give isl_set *isl_stream_read_set(struct isl_stream *s);
+__isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
+ struct isl_stream *s);
+__isl_give isl_union_map *isl_stream_read_union_map(struct isl_stream *s);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/union_map.h b/polly/lib/External/isl/include/isl/union_map.h
new file mode 100644
index 00000000000..2d4d94cd3b3
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/union_map.h
@@ -0,0 +1,249 @@
+#ifndef ISL_UNION_MAP_H
+#define ISL_UNION_MAP_H
+
+#include <isl/space.h>
+#include <isl/map_type.h>
+#include <isl/union_map_type.h>
+#include <isl/printer.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type);
+int isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_id *isl_union_map_get_dim_id(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned pos);
+
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_from_basic_map(
+ __isl_take isl_basic_map *bmap);
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map);
+__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *dim);
+__isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap);
+__isl_null isl_union_map *isl_union_map_free(__isl_take isl_union_map *umap);
+
+isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap);
+__isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_reset_user(
+ __isl_take isl_union_map *umap);
+
+int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, const char *name);
+
+__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_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap);
+__isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_domain_map(
+ __isl_take isl_union_map *umap);
+__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(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_map *isl_union_map_from_domain(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_map *isl_union_map_from_range(
+ __isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_affine_hull(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_polyhedral_hull(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_simple_hull(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_coalesce(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_compute_divs(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_lexmin(__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_lexmax(__isl_take isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
+ __isl_take isl_map *map);
+__isl_export
+__isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set);
+__isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+__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_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_give isl_union_map *isl_union_map_domain_factor_domain(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_domain_factor_range(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_range_factor_range(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_factor_domain(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_factor_range(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
+ __isl_take isl_union_map *context);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *dom);
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *dom);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_apply_domain(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_apply_range(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_map *isl_union_map_preimage_range_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_map *isl_union_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_map *isl_union_map_preimage_range_pw_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_pw_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_union_map *isl_union_map_preimage_domain_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __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_give isl_union_map *isl_union_map_from_domain_and_range(
+ __isl_take isl_union_set *domain, __isl_take isl_union_set *range);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_detect_equalities(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_deltas_map(
+ __isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_map_project_out(
+ __isl_take isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_export
+int isl_union_map_is_empty(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap);
+int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_injective(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_bijective(__isl_keep isl_union_map *umap);
+
+__isl_export
+int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+__isl_export
+int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+__isl_export
+int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+
+int isl_union_map_n_map(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
+ int (*fn)(__isl_take isl_map *map, void *user), void *user);
+__isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
+ __isl_keep isl_space *dim);
+__isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
+ __isl_take isl_space *dim);
+__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_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,
+ int *exact);
+__isl_give isl_union_map *isl_union_map_transitive_closure(
+ __isl_take isl_union_map *umap, int *exact);
+
+__isl_give isl_union_map *isl_union_map_lex_lt_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_lex_le_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_lex_gt_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_lex_ge_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+
+__isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
+ FILE *input);
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_read_from_str(isl_ctx *ctx,
+ const char *str);
+__isl_give char *isl_union_map_to_str(__isl_keep isl_union_map *umap);
+__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_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset);
+
+__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_uncurry(__isl_take isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_align_params(
+ __isl_take isl_union_map *umap, __isl_take isl_space *model);
+__isl_give isl_union_set *isl_union_set_align_params(
+ __isl_take isl_union_set *uset, __isl_take isl_space *model);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/union_map_type.h b/polly/lib/External/isl/include/isl/union_map_type.h
new file mode 100644
index 00000000000..e93f2cc7137
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/union_map_type.h
@@ -0,0 +1,21 @@
+#ifndef ISL_UNION_MAP_TYPE_H
+#define ISL_UNION_MAP_TYPE_H
+
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct __isl_export isl_union_map;
+typedef struct isl_union_map isl_union_map;
+#ifndef isl_union_set
+struct __isl_export isl_union_set;
+typedef struct isl_union_set isl_union_set;
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/union_set.h b/polly/lib/External/isl/include/isl/union_set.h
new file mode 100644
index 00000000000..616acb8011c
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/union_set.h
@@ -0,0 +1,147 @@
+#ifndef ISL_UNION_SET_H
+#define ISL_UNION_SET_H
+
+#include <isl/point.h>
+#include <isl/union_map.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+ enum isl_dim_type type);
+
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_from_basic_set(
+ __isl_take isl_basic_set *bset);
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set);
+__isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *dim);
+__isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset);
+__isl_null isl_union_set *isl_union_set_free(__isl_take isl_union_set *uset);
+
+isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset);
+__isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_reset_user(
+ __isl_take isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_universe(
+ __isl_take isl_union_set *uset);
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_set *isl_union_set_detect_equalities(
+ __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_affine_hull(
+ __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_polyhedral_hull(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_set *isl_union_set_simple_hull(
+ __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_coalesce(
+ __isl_take isl_union_set *uset);
+__isl_give isl_union_set *isl_union_set_compute_divs(
+ __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_lexmin(__isl_take isl_union_set *uset);
+__isl_export
+__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_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_subtract(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_intersect(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_intersect_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set);
+__isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
+ __isl_take isl_union_set *context);
+__isl_export
+__isl_give isl_union_set *isl_union_set_gist_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set);
+
+__isl_export
+__isl_give isl_union_set *isl_union_set_apply(
+ __isl_take isl_union_set *uset, __isl_take isl_union_map *umap);
+__isl_give isl_union_set *isl_union_set_preimage_multi_aff(
+ __isl_take isl_union_set *uset, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_set *isl_union_set_preimage_pw_multi_aff(
+ __isl_take isl_union_set *uset, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_multi_aff *upma);
+
+int isl_union_set_is_params(__isl_keep isl_union_set *uset);
+__isl_export
+int isl_union_set_is_empty(__isl_keep isl_union_set *uset);
+
+__isl_export
+int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+__isl_export
+int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+__isl_export
+int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+
+int isl_union_set_n_set(__isl_keep isl_union_set *uset);
+__isl_export
+int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
+ int (*fn)(__isl_take isl_set *set, void *user), void *user);
+__isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
+ __isl_keep isl_space *dim);
+__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);
+int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
+ int (*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_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_set_lex_lt_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_le_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_gt_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_ge_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+
+__isl_give isl_union_set *isl_union_set_coefficients(
+ __isl_take isl_union_set *bset);
+__isl_give isl_union_set *isl_union_set_solutions(
+ __isl_take isl_union_set *bset);
+
+__isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
+ FILE *input);
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_read_from_str(isl_ctx *ctx,
+ const char *str);
+__isl_give char *isl_union_set_to_str(__isl_keep isl_union_set *uset);
+__isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
+ __isl_keep isl_union_set *uset);
+void isl_union_set_dump(__isl_keep isl_union_set *uset);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/union_set_type.h b/polly/lib/External/isl/include/isl/union_set_type.h
new file mode 100644
index 00000000000..86b2c317fa1
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/union_set_type.h
@@ -0,0 +1,6 @@
+#ifndef ISL_UNION_SET_TYPE_H
+#define ISL_UNION_SET_TYPE_H
+
+#include <isl/union_map_type.h>
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/val.h b/polly/lib/External/isl/include/isl/val.h
new file mode 100644
index 00000000000..238f0c282cf
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/val.h
@@ -0,0 +1,114 @@
+#ifndef ISL_VAL_H
+#define ISL_VAL_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+#include <isl/multi.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_val;
+typedef struct isl_val isl_val;
+
+ISL_DECLARE_LIST(val)
+
+struct isl_multi_val;
+typedef struct isl_multi_val isl_multi_val;
+
+ISL_DECLARE_MULTI(val)
+
+__isl_give isl_val *isl_val_zero(isl_ctx *ctx);
+__isl_give isl_val *isl_val_one(isl_ctx *ctx);
+__isl_give isl_val *isl_val_negone(isl_ctx *ctx);
+__isl_give isl_val *isl_val_nan(isl_ctx *ctx);
+__isl_give isl_val *isl_val_infty(isl_ctx *ctx);
+__isl_give isl_val *isl_val_neginfty(isl_ctx *ctx);
+__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,
+ size_t size, const void *chunks);
+
+__isl_give isl_val *isl_val_copy(__isl_keep isl_val *v);
+__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);
+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,
+ void *chunks);
+
+__isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i);
+
+__isl_give isl_val *isl_val_abs(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_neg(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_inv(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_floor(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_ceil(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_trunc(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
+ __isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y);
+
+int isl_val_sgn(__isl_keep isl_val *v);
+int isl_val_is_zero(__isl_keep isl_val *v);
+int isl_val_is_one(__isl_keep isl_val *v);
+int isl_val_is_negone(__isl_keep isl_val *v);
+int isl_val_is_nonneg(__isl_keep isl_val *v);
+int isl_val_is_nonpos(__isl_keep isl_val *v);
+int isl_val_is_pos(__isl_keep isl_val *v);
+int isl_val_is_neg(__isl_keep isl_val *v);
+int isl_val_is_int(__isl_keep isl_val *v);
+int isl_val_is_rat(__isl_keep isl_val *v);
+int isl_val_is_nan(__isl_keep isl_val *v);
+int isl_val_is_infty(__isl_keep isl_val *v);
+int isl_val_is_neginfty(__isl_keep isl_val *v);
+
+int isl_val_cmp_si(__isl_keep isl_val *v, long i);
+
+int isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+
+int isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+
+__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);
+void isl_val_dump(__isl_keep isl_val *v);
+__isl_give char *isl_val_to_str(__isl_keep isl_val *v);
+
+__isl_give isl_multi_val *isl_multi_val_add_val(__isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+__isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv,
+ __isl_take isl_val *v);
+
+__isl_give isl_printer *isl_printer_print_multi_val(__isl_take isl_printer *p,
+ __isl_keep isl_multi_val *mv);
+void isl_multi_val_dump(__isl_keep isl_multi_val *mv);
+__isl_give char *isl_multi_val_to_str(__isl_keep isl_multi_val *mv);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/val_gmp.h b/polly/lib/External/isl/include/isl/val_gmp.h
new file mode 100644
index 00000000000..9558c1a1338
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/val_gmp.h
@@ -0,0 +1,21 @@
+#ifndef ISL_VAL_GMP_H
+#define ISL_VAL_GMP_H
+
+#include <gmp.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx, mpz_t z);
+__isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx,
+ const mpz_t n, const mpz_t d);
+int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z);
+int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/vec.h b/polly/lib/External/isl/include/isl/vec.h
new file mode 100644
index 00000000000..d2fb48ccdb9
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/vec.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_VEC_H
+#define ISL_VEC_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/val.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_vec;
+typedef struct isl_vec isl_vec;
+
+__isl_give isl_vec *isl_vec_alloc(isl_ctx *ctx, unsigned size);
+__isl_give isl_vec *isl_vec_copy(__isl_keep isl_vec *vec);
+__isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec);
+
+isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec);
+
+int isl_vec_size(__isl_keep isl_vec *vec);
+__isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos);
+__isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
+ int pos, int v);
+__isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec,
+ int pos, __isl_take isl_val *v);
+
+int isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2);
+int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2,
+ int pos);
+
+void isl_vec_dump(__isl_keep isl_vec *vec);
+__isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
+ __isl_keep isl_vec *vec);
+
+struct isl_vec *isl_vec_ceil(struct isl_vec *vec);
+struct isl_vec *isl_vec_normalize(struct isl_vec *vec);
+__isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v);
+__isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec,
+ __isl_take isl_val *v);
+__isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec);
+__isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec);
+__isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
+ __isl_take isl_vec *vec2);
+__isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size);
+__isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size);
+__isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
+ __isl_take isl_vec *vec2);
+
+__isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec);
+
+__isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input);
+
+__isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec,
+ unsigned dst_col, unsigned src_col, unsigned n);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/version.h b/polly/lib/External/isl/include/isl/version.h
new file mode 100644
index 00000000000..7f8f23d6945
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/version.h
@@ -0,0 +1,14 @@
+#ifndef ISL_VERSION_H
+#define ISL_VERSION_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+const char *isl_version(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/include/isl/vertices.h b/polly/lib/External/isl/include/isl/vertices.h
new file mode 100644
index 00000000000..7a4b353a5a9
--- /dev/null
+++ b/polly/lib/External/isl/include/isl/vertices.h
@@ -0,0 +1,47 @@
+#ifndef ISL_VERTICES_H
+#define ISL_VERTICES_H
+
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_external_vertex;
+typedef struct isl_external_vertex isl_vertex;
+
+struct isl_cell;
+typedef struct isl_cell isl_cell;
+
+struct isl_vertices;
+typedef struct isl_vertices isl_vertices;
+
+isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex);
+int isl_vertex_get_id(__isl_keep isl_vertex *vertex);
+__isl_give isl_basic_set *isl_vertex_get_domain(__isl_keep isl_vertex *vertex);
+__isl_give isl_multi_aff *isl_vertex_get_expr(__isl_keep isl_vertex *vertex);
+void isl_vertex_free(__isl_take isl_vertex *vertex);
+
+__isl_give isl_vertices *isl_basic_set_compute_vertices(
+ __isl_keep isl_basic_set *bset);
+isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices);
+int isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices);
+int isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
+void isl_vertices_free(__isl_take isl_vertices *vertices);
+
+isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell);
+__isl_give isl_basic_set *isl_cell_get_domain(__isl_keep isl_cell *cell);
+int isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
+void isl_cell_free(__isl_take isl_cell *cell);
+
+int isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_cell *cell, void *user), void *user);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/interface/Makefile.am b/polly/lib/External/isl/interface/Makefile.am
new file mode 100644
index 00000000000..0269e9113d0
--- /dev/null
+++ b/polly/lib/External/isl/interface/Makefile.am
@@ -0,0 +1,32 @@
+AUTOMAKE_OPTIONS = nostdinc
+
+noinst_PROGRAMS = extract_interface
+
+AM_CXXFLAGS = $(CLANG_CXXFLAGS)
+AM_LDFLAGS = $(CLANG_LDFLAGS)
+
+includes = -I$(top_builddir) -I$(top_srcdir) \
+ -I$(top_builddir)/include -I$(top_srcdir)/include
+
+extract_interface_CPPFLAGS = $(includes)
+extract_interface_SOURCES = \
+ python.h \
+ python.cc \
+ extract_interface.h \
+ extract_interface.cc
+extract_interface_LDADD = \
+ -lclangFrontend -lclangSerialization -lclangParse -lclangSema \
+ $(LIB_CLANG_EDIT) \
+ -lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
+ $(CLANG_LIBS) $(CLANG_LDFLAGS)
+
+test: extract_interface
+ ./extract_interface$(EXEEXT) $(includes) $(srcdir)/all.h
+
+isl.py: extract_interface isl.py.top
+ (cat $(srcdir)/isl.py.top; \
+ ./extract_interface$(EXEEXT) $(includes) $(srcdir)/all.h) \
+ > isl.py
+
+dist-hook: isl.py
+ cp isl.py $(distdir)/
diff --git a/polly/lib/External/isl/interface/all.h b/polly/lib/External/isl/interface/all.h
new file mode 100644
index 00000000000..46634e2b8db
--- /dev/null
+++ b/polly/lib/External/isl/interface/all.h
@@ -0,0 +1,4 @@
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>
diff --git a/polly/lib/External/isl/interface/extract_interface.cc b/polly/lib/External/isl/interface/extract_interface.cc
new file mode 100644
index 00000000000..fd83003329e
--- /dev/null
+++ b/polly/lib/External/isl/interface/extract_interface.cc
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */
+
+#include "isl_config.h"
+
+#include <assert.h>
+#include <iostream>
+#ifdef HAVE_ADT_OWNINGPTR_H
+#include <llvm/ADT/OwningPtr.h>
+#else
+#include <memory>
+#endif
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/ASTConsumer.h>
+#include <clang/Basic/FileSystemOptions.h>
+#include <clang/Basic/FileManager.h>
+#include <clang/Basic/TargetOptions.h>
+#include <clang/Basic/TargetInfo.h>
+#include <clang/Basic/Version.h>
+#include <clang/Driver/Compilation.h>
+#include <clang/Driver/Driver.h>
+#include <clang/Driver/Tool.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Frontend/CompilerInvocation.h>
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+#include <clang/Basic/DiagnosticOptions.h>
+#else
+#include <clang/Frontend/DiagnosticOptions.h>
+#endif
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Frontend/Utils.h>
+#include <clang/Lex/HeaderSearch.h>
+#include <clang/Lex/Preprocessor.h>
+#include <clang/Parse/ParseAST.h>
+#include <clang/Sema/Sema.h>
+
+#include "extract_interface.h"
+#include "python.h"
+
+using namespace std;
+using namespace clang;
+using namespace clang::driver;
+
+#ifdef HAVE_ADT_OWNINGPTR_H
+#define unique_ptr llvm::OwningPtr
+#endif
+
+static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
+ llvm::cl::Required, llvm::cl::desc("<input file>"));
+static llvm::cl::list<string> Includes("I",
+ llvm::cl::desc("Header search path"),
+ llvm::cl::value_desc("path"), llvm::cl::Prefix);
+
+static const char *ResourceDir =
+ CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
+
+/* Does decl have an attribute of the following form?
+ *
+ * __attribute__((annotate("name")))
+ */
+bool has_annotation(Decl *decl, const char *name)
+{
+ if (!decl->hasAttrs())
+ return false;
+
+ AttrVec attrs = decl->getAttrs();
+ for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
+ const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+ if (!ann)
+ continue;
+ if (ann->getAnnotation().str() == name)
+ return true;
+ }
+
+ return false;
+}
+
+/* Is decl marked as exported?
+ */
+static bool is_exported(Decl *decl)
+{
+ return has_annotation(decl, "isl_export");
+}
+
+/* Collect all types and functions that are annotated "isl_export"
+ * in "types" and "function".
+ *
+ * We currently only consider single declarations.
+ */
+struct MyASTConsumer : public ASTConsumer {
+ set<RecordDecl *> types;
+ set<FunctionDecl *> functions;
+
+ virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
+ Decl *decl;
+
+ if (!D.isSingleDecl())
+ return HandleTopLevelDeclContinue;
+ decl = D.getSingleDecl();
+ if (!is_exported(decl))
+ return HandleTopLevelDeclContinue;
+ switch (decl->getKind()) {
+ case Decl::Record:
+ types.insert(cast<RecordDecl>(decl));
+ break;
+ case Decl::Function:
+ functions.insert(cast<FunctionDecl>(decl));
+ break;
+ default:
+ break;
+ }
+ return HandleTopLevelDeclContinue;
+ }
+};
+
+#ifdef USE_ARRAYREF
+
+#ifdef HAVE_CXXISPRODUCTION
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+ return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+ "", false, false, Diags);
+}
+#elif defined(HAVE_ISPRODUCTION)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+ return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+ "", false, Diags);
+}
+#elif defined(DRIVER_CTOR_TAKES_DEFAULTIMAGENAME)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+ return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+ "", Diags);
+}
+#else
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+ return new Driver(binary, llvm::sys::getDefaultTargetTriple(), Diags);
+}
+#endif
+
+/* Create a CompilerInvocation object that stores the command line
+ * arguments constructed by the driver.
+ * The arguments are mainly useful for setting up the system include
+ * paths on newer clangs and on some platforms.
+ */
+static CompilerInvocation *construct_invocation(const char *filename,
+ DiagnosticsEngine &Diags)
+{
+ const char *binary = CLANG_PREFIX"/bin/clang";
+ const unique_ptr<Driver> driver(construct_driver(binary, Diags));
+ std::vector<const char *> Argv;
+ Argv.push_back(binary);
+ Argv.push_back(filename);
+ const unique_ptr<Compilation> compilation(
+ driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
+ JobList &Jobs = compilation->getJobs();
+
+ Command *cmd = cast<Command>(*Jobs.begin());
+ if (strcmp(cmd->getCreator().getName(), "clang"))
+ return NULL;
+
+ const ArgStringList *args = &cmd->getArguments();
+
+ CompilerInvocation *invocation = new CompilerInvocation;
+ CompilerInvocation::CreateFromArgs(*invocation, args->data() + 1,
+ args->data() + args->size(),
+ Diags);
+ return invocation;
+}
+
+#else
+
+static CompilerInvocation *construct_invocation(const char *filename,
+ DiagnosticsEngine &Diags)
+{
+ return NULL;
+}
+
+#endif
+
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+ return new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
+}
+
+#else
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+ DiagnosticOptions DO;
+ return new TextDiagnosticPrinter(llvm::errs(), DO);
+}
+
+#endif
+
+#ifdef CREATETARGETINFO_TAKES_SHARED_PTR
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+ DiagnosticsEngine &Diags)
+{
+ shared_ptr<TargetOptions> TO = Clang->getInvocation().TargetOpts;
+ TO->Triple = llvm::sys::getDefaultTargetTriple();
+ return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#elif defined(CREATETARGETINFO_TAKES_POINTER)
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+ DiagnosticsEngine &Diags)
+{
+ TargetOptions &TO = Clang->getTargetOpts();
+ TO.Triple = llvm::sys::getDefaultTargetTriple();
+ return TargetInfo::CreateTargetInfo(Diags, &TO);
+}
+
+#else
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+ DiagnosticsEngine &Diags)
+{
+ TargetOptions &TO = Clang->getTargetOpts();
+ TO.Triple = llvm::sys::getDefaultTargetTriple();
+ return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#endif
+
+#ifdef CREATEDIAGNOSTICS_TAKES_ARG
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+ Clang->createDiagnostics(0, NULL, construct_printer());
+}
+
+#else
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+ Clang->createDiagnostics(construct_printer());
+}
+
+#endif
+
+#ifdef CREATEPREPROCESSOR_TAKES_TUKIND
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+ Clang->createPreprocessor(TU_Complete);
+}
+
+#else
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+ Clang->createPreprocessor();
+}
+
+#endif
+
+#ifdef ADDPATH_TAKES_4_ARGUMENTS
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+ HSO.AddPath(Path, frontend::Angled, false, false);
+}
+
+#else
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+ HSO.AddPath(Path, frontend::Angled, true, false, false);
+}
+
+#endif
+
+#ifdef HAVE_SETMAINFILEID
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+ SM.setMainFileID(SM.createFileID(file, SourceLocation(),
+ SrcMgr::C_User));
+}
+
+#else
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+ SM.createMainFileID(file);
+}
+
+#endif
+
+int main(int argc, char *argv[])
+{
+ llvm::cl::ParseCommandLineOptions(argc, argv);
+
+ CompilerInstance *Clang = new CompilerInstance();
+ create_diagnostics(Clang);
+ DiagnosticsEngine &Diags = Clang->getDiagnostics();
+ Diags.setSuppressSystemWarnings(true);
+ CompilerInvocation *invocation =
+ construct_invocation(InputFilename.c_str(), Diags);
+ if (invocation)
+ Clang->setInvocation(invocation);
+ Clang->createFileManager();
+ Clang->createSourceManager(Clang->getFileManager());
+ TargetInfo *target = create_target_info(Clang, Diags);
+ Clang->setTarget(target);
+ CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
+ LangStandard::lang_unspecified);
+ HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
+ LangOptions &LO = Clang->getLangOpts();
+ PreprocessorOptions &PO = Clang->getPreprocessorOpts();
+ HSO.ResourceDir = ResourceDir;
+
+ for (int i = 0; i < Includes.size(); ++i)
+ add_path(HSO, Includes[i]);
+
+ PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
+ PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
+ PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
+ PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
+ PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
+ PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
+
+ create_preprocessor(Clang);
+ Preprocessor &PP = Clang->getPreprocessor();
+
+ PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), LO);
+
+ const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
+ assert(file);
+ create_main_file_id(Clang->getSourceManager(), file);
+
+ Clang->createASTContext();
+ MyASTConsumer consumer;
+ Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
+
+ Diags.getClient()->BeginSourceFile(LO, &PP);
+ ParseAST(*sema);
+ Diags.getClient()->EndSourceFile();
+
+ generate_python(consumer.types, consumer.functions);
+
+ delete sema;
+ delete Clang;
+ llvm::llvm_shutdown();
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/interface/extract_interface.h b/polly/lib/External/isl/interface/extract_interface.h
new file mode 100644
index 00000000000..b6788f1343d
--- /dev/null
+++ b/polly/lib/External/isl/interface/extract_interface.h
@@ -0,0 +1,3 @@
+#include <clang/AST/Decl.h>
+
+bool has_annotation(clang::Decl *decl, const char *name);
diff --git a/polly/lib/External/isl/interface/isl.py.top b/polly/lib/External/isl/interface/isl.py.top
new file mode 100644
index 00000000000..6d4ae49eb9b
--- /dev/null
+++ b/polly/lib/External/isl/interface/isl.py.top
@@ -0,0 +1,29 @@
+from ctypes import *
+
+isl = cdll.LoadLibrary("libisl.so")
+libc = cdll.LoadLibrary("libc.so.6")
+
+class Error(Exception):
+ pass
+
+class Context:
+ defaultInstance = None
+
+ def __init__(self):
+ ptr = isl.isl_ctx_alloc()
+ self.ptr = ptr
+
+ def __del__(self):
+ isl.isl_ctx_free(self)
+
+ def from_param(self):
+ return self.ptr
+
+ @staticmethod
+ def getDefaultInstance():
+ if Context.defaultInstance == None:
+ Context.defaultInstance = Context()
+ return Context.defaultInstance
+
+isl.isl_ctx_alloc.restype = c_void_p
+isl.isl_ctx_free.argtypes = [Context]
diff --git a/polly/lib/External/isl/interface/python.cc b/polly/lib/External/isl/interface/python.cc
new file mode 100644
index 00000000000..bb5f708028c
--- /dev/null
+++ b/polly/lib/External/isl/interface/python.cc
@@ -0,0 +1,519 @@
+/*
+ * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */
+
+#include "isl_config.h"
+
+#include <stdio.h>
+#include <iostream>
+#include <map>
+#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".
+ */
+static bool is_subclass(RecordDecl *decl, string &super)
+{
+ if (!decl->hasAttrs())
+ return false;
+
+ string sub = "isl_subclass";
+ size_t len = sub.length();
+ AttrVec attrs = decl->getAttrs();
+ for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
+ const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+ if (!ann)
+ continue;
+ string s = ann->getAnnotation().str();
+ if (s.substr(0, len) == sub) {
+ super = s.substr(len + 1, s.length() - len - 2);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* Is decl marked as a constructor?
+ */
+static bool is_constructor(Decl *decl)
+{
+ return has_annotation(decl, "isl_constructor");
+}
+
+/* Is decl marked as consuming a reference?
+ */
+static bool takes(Decl *decl)
+{
+ return has_annotation(decl, "isl_take");
+}
+
+/* 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.
+ */
+struct isl_class {
+ string name;
+ RecordDecl *type;
+ set<FunctionDecl *> constructors;
+ set<FunctionDecl *> methods;
+
+ void print(map<string, isl_class> &classes, set<string> &done);
+ void print_constructor(FunctionDecl *method);
+ void print_method(FunctionDecl *method, bool subclass, string super);
+};
+
+/* Return the class that has a name that matches the initial part
+ * of the namd of function "fd".
+ */
+static isl_class &method2class(map<string, isl_class> &classes,
+ FunctionDecl *fd)
+{
+ string best;
+ map<string, isl_class>::iterator ci;
+ string name = fd->getNameAsString();
+
+ for (ci = classes.begin(); ci != classes.end(); ++ci) {
+ if (name.substr(0, ci->first.length()) == ci->first)
+ best = ci->first;
+ }
+
+ return classes[best];
+}
+
+/* Is "type" the type "isl_ctx *"?
+ */
+static bool is_isl_ctx(QualType type)
+{
+ if (!type->isPointerType())
+ return 0;
+ type = type->getPointeeType();
+ if (type.getAsString() != "isl_ctx")
+ return false;
+
+ return true;
+}
+
+/* Is the first argument of "fd" of type "isl_ctx *"?
+ */
+static bool first_arg_is_isl_ctx(FunctionDecl *fd)
+{
+ ParmVarDecl *param;
+
+ if (fd->getNumParams() < 1)
+ return false;
+
+ param = fd->getParamDecl(0);
+ return is_isl_ctx(param->getOriginalType());
+}
+
+/* Is "type" that of a pointer to an isl_* structure?
+ */
+static bool is_isl_type(QualType type)
+{
+ if (type->isPointerType()) {
+ string s = type->getPointeeType().getAsString();
+ return s.substr(0, 4) == "isl_";
+ }
+
+ return false;
+}
+
+/* Is "type" that of a pointer to a function?
+ */
+static bool is_callback(QualType type)
+{
+ if (!type->isPointerType())
+ return false;
+ type = type->getPointeeType();
+ return type->isFunctionType();
+}
+
+/* Is "type" that of "char *" of "const char *"?
+ */
+static bool is_string(QualType type)
+{
+ if (type->isPointerType()) {
+ string s = type->getPointeeType().getAsString();
+ return s == "const char" || s == "char";
+ }
+
+ return false;
+}
+
+/* Return the name of the type that "type" points to.
+ * The input "type" is assumed to be a pointer type.
+ */
+static string extract_type(QualType type)
+{
+ if (type->isPointerType())
+ return type->getPointeeType().getAsString();
+ assert(0);
+}
+
+/* Drop the "isl_" initial part of the type name "name".
+ */
+static string type2python(string name)
+{
+ return name.substr(4);
+}
+
+/* Construct a wrapper for a callback argument (at position "arg").
+ * Assign the wrapper to "cb". We assume here that a function call
+ * has at most one callback argument.
+ *
+ * The wrapper converts the arguments of the callback to python types.
+ * If any exception is thrown, the wrapper keeps track of it in exc_info[0]
+ * and returns -1. Otherwise the wrapper returns 0.
+ */
+static void print_callback(QualType type, int arg)
+{
+ const FunctionProtoType *fn = type->getAs<FunctionProtoType>();
+ unsigned n_arg = fn->getNumArgs();
+
+ printf(" exc_info = [None]\n");
+ printf(" fn = CFUNCTYPE(c_int");
+ for (int i = 0; i < n_arg - 1; ++i) {
+ QualType arg_type = fn->getArgType(i);
+ assert(is_isl_type(arg_type));
+ printf(", c_void_p");
+ }
+ printf(", c_void_p)\n");
+ printf(" def cb_func(");
+ for (int i = 0; i < n_arg; ++i) {
+ if (i)
+ printf(", ");
+ printf("cb_arg%d", i);
+ }
+ printf("):\n");
+ for (int i = 0; i < n_arg - 1; ++i) {
+ string arg_type;
+ arg_type = type2python(extract_type(fn->getArgType(i)));
+ printf(" cb_arg%d = %s(ctx=arg0.ctx, ptr=cb_arg%d)\n",
+ i, arg_type.c_str(), i);
+ }
+ printf(" try:\n");
+ printf(" arg%d(", arg);
+ for (int i = 0; i < n_arg - 1; ++i) {
+ if (i)
+ printf(", ");
+ printf("cb_arg%d", i);
+ }
+ printf(")\n");
+ printf(" except:\n");
+ printf(" import sys\n");
+ printf(" exc_info[0] = sys.exc_info()\n");
+ printf(" return -1\n");
+ printf(" return 0\n");
+ printf(" cb = fn(cb_func)\n");
+}
+
+/* Print 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").
+ *
+ * If the function has a callback argument, then it also has a "user"
+ * argument. Since Python has closures, there is no need for such
+ * a user argument in the Python interface, so we simply drop it.
+ * We also create a wrapper ("cb") for the callback.
+ *
+ * For each argument of the function that refers to an isl structure,
+ * including the object on which the method is called,
+ * we check if the corresponding actual argument is of the right type.
+ * If not, we try to convert it to the right type.
+ * 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.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ */
+void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
+{
+ string fullname = method->getName();
+ string cname = fullname.substr(name.length() + 1);
+ int num_params = method->getNumParams();
+ int drop_user = 0;
+
+ for (int i = 1; i < num_params; ++i) {
+ ParmVarDecl *param = method->getParamDecl(i);
+ QualType type = param->getOriginalType();
+ if (is_callback(type))
+ 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");
+
+ for (int i = 0; i < num_params; ++i) {
+ ParmVarDecl *param = method->getParamDecl(i);
+ string type;
+ if (!is_isl_type(param->getOriginalType()))
+ continue;
+ type = type2python(extract_type(param->getOriginalType()));
+ printf(" try:\n");
+ printf(" if not arg%d.__class__ is %s:\n",
+ i, type.c_str());
+ printf(" arg%d = %s(arg%d)\n",
+ i, type.c_str(), i);
+ printf(" except:\n");
+ if (i > 0 && subclass) {
+ printf(" return %s(arg0).%s(",
+ type2python(super).c_str(), cname.c_str());
+ for (int i = 1; i < num_params - drop_user; ++i) {
+ if (i != 1)
+ printf(", ");
+ printf("arg%d", i);
+ }
+ printf(")\n");
+ } else
+ printf(" raise\n");
+ }
+ for (int i = 1; i < num_params; ++i) {
+ ParmVarDecl *param = method->getParamDecl(i);
+ QualType type = param->getOriginalType();
+ if (!is_callback(type))
+ continue;
+ print_callback(type->getPointeeType(), i);
+ }
+ printf(" res = isl.%s(", fullname.c_str());
+ if (takes(method->getParamDecl(0)))
+ printf("isl.%s_copy(arg0.ptr)", name.c_str());
+ else
+ printf("arg0.ptr");
+ 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);
+ }
+ if (drop_user)
+ printf(", None");
+ printf(")\n");
+
+ if (is_isl_type(method->getReturnType())) {
+ string type;
+ type = type2python(extract_type(method->getReturnType()));
+ printf(" return %s(ctx=arg0.ctx, ptr=res)\n",
+ type.c_str());
+ } else {
+ if (drop_user) {
+ printf(" if exc_info[0] != None:\n");
+ printf(" raise exc_info[0][0], "
+ "exc_info[0][1], exc_info[0][2]\n");
+ }
+ printf(" return res\n");
+ }
+}
+
+/* Print part of the constructor for this isl_class.
+ *
+ * In particular, check if the actual arguments correspond to the
+ * formal arguments of "cons" and if so call "cons" and put the
+ * result in self.ptr and a reference to the default context in self.ctx.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ */
+void isl_class::print_constructor(FunctionDecl *cons)
+{
+ string fullname = cons->getName();
+ string cname = fullname.substr(name.length() + 1);
+ int num_params = cons->getNumParams();
+ int drop_ctx = first_arg_is_isl_ctx(cons);
+
+ printf(" if len(args) == %d", num_params - drop_ctx);
+ for (int i = drop_ctx; i < num_params; ++i) {
+ ParmVarDecl *param = cons->getParamDecl(i);
+ if (is_isl_type(param->getOriginalType())) {
+ string type;
+ type = extract_type(param->getOriginalType());
+ type = type2python(type);
+ printf(" and args[%d].__class__ is %s",
+ i - drop_ctx, type.c_str());
+ } else
+ printf(" and type(args[%d]) == str", i - drop_ctx);
+ }
+ printf(":\n");
+ printf(" self.ctx = Context.getDefaultInstance()\n");
+ printf(" self.ptr = isl.%s(", fullname.c_str());
+ if (drop_ctx)
+ printf("self.ctx");
+ for (int i = drop_ctx; i < num_params; ++i) {
+ ParmVarDecl *param = cons->getParamDecl(i);
+ if (i)
+ printf(", ");
+ if (is_isl_type(param->getOriginalType())) {
+ if (takes(param)) {
+ string type;
+ type = extract_type(param->getOriginalType());
+ printf("isl.%s_copy(args[%d].ptr)",
+ type.c_str(), i - drop_ctx);
+ } else
+ printf("args[%d].ptr", i - drop_ctx);
+ } else
+ printf("args[%d]", i - drop_ctx);
+ }
+ printf(")\n");
+ printf(" return\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.
+ *
+ * Then we print a constructor with several cases, one for constructing
+ * a Python object from a return value and one for each function that
+ * was marked as a constructor.
+ *
+ * Next, we print out some common methods and the methods corresponding
+ * to functions that are not marked as constructors.
+ *
+ * Finally, we tell ctypes about the types of the arguments of the
+ * constructor functions and the return types of those function returning
+ * an isl object.
+ */
+void 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);
+
+ if (subclass && done.find(super) == done.end())
+ classes[super].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");
+ printf(" def __init__(self, *args, **keywords):\n");
+
+ printf(" if \"ptr\" in keywords:\n");
+ printf(" self.ctx = keywords[\"ctx\"]\n");
+ printf(" self.ptr = keywords[\"ptr\"]\n");
+ printf(" return\n");
+
+ for (in = constructors.begin(); in != constructors.end(); ++in)
+ print_constructor(*in);
+ printf(" raise Error\n");
+ printf(" def __del__(self):\n");
+ printf(" if hasattr(self, 'ptr'):\n");
+ printf(" isl.%s_free(self.ptr)\n", name.c_str());
+ printf(" def __str__(self):\n");
+ printf(" ptr = isl.%s_to_str(self.ptr)\n", name.c_str());
+ printf(" res = str(cast(ptr, c_char_p).value)\n");
+ printf(" libc.free(ptr)\n");
+ printf(" return res\n");
+ printf(" def __repr__(self):\n");
+ printf(" return 'isl.%s(\"%%s\")' %% str(self)\n", p_name.c_str());
+
+ for (in = methods.begin(); in != methods.end(); ++in)
+ print_method(*in, subclass, 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());
+ }
+ 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());
+}
+
+/* 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.
+ *
+ * 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.
+ */
+void generate_python(set<RecordDecl *> &types, set<FunctionDecl *> functions)
+{
+ map<string, isl_class> classes;
+ map<string, isl_class>::iterator ci;
+ set<string> done;
+
+ set<RecordDecl *>::iterator it;
+ for (it = types.begin(); it != types.end(); ++it) {
+ RecordDecl *decl = *it;
+ string name = decl->getName();
+ classes[name].name = name;
+ classes[name].type = decl;
+ }
+
+ 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);
+ }
+
+ for (ci = classes.begin(); ci != classes.end(); ++ci) {
+ if (done.find(ci->first) == done.end())
+ ci->second.print(classes, done);
+ }
+}
diff --git a/polly/lib/External/isl/interface/python.h b/polly/lib/External/isl/interface/python.h
new file mode 100644
index 00000000000..0f6e8ec5b2f
--- /dev/null
+++ b/polly/lib/External/isl/interface/python.h
@@ -0,0 +1,7 @@
+#include <set>
+#include <clang/AST/Decl.h>
+
+using namespace std;
+using namespace clang;
+
+void generate_python(set<RecordDecl *> &types, set<FunctionDecl *> functions);
diff --git a/polly/lib/External/isl/isl.py b/polly/lib/External/isl/isl.py
new file mode 100644
index 00000000000..6382f6384e7
--- /dev/null
+++ b/polly/lib/External/isl/isl.py
@@ -0,0 +1,100 @@
+import gdb
+import re
+
+# GDB Pretty Printers for most isl objects
+class IslObjectPrinter:
+ """Print an isl object"""
+ def __init__ (self, val, type):
+ self.val = val
+ self.type = type
+
+ def to_string (self):
+ # Cast val to a void pointer to stop gdb using this pretty
+ # printer for the pointer which would lead to an infinite loop.
+ void_ptr = gdb.lookup_type('void').pointer()
+ value = str(self.val.cast(void_ptr))
+ printer = gdb.parse_and_eval("isl_printer_to_str(isl_"
+ + str(self.type)
+ + "_get_ctx(" + value + "))")
+ printer = gdb.parse_and_eval("isl_printer_print_"
+ + str(self.type) + "("
+ + str(printer) + ", "
+ + value + ")")
+ string = gdb.parse_and_eval("(char*)isl_printer_get_str("
+ + str(printer) + ")")
+ gdb.parse_and_eval("isl_printer_free(" + str(printer) + ")")
+ return string
+
+ def display_hint (self):
+ return 'string'
+
+class IslIntPrinter:
+ """Print an isl_int """
+ def __init__ (self, val):
+ self.val = val
+
+ def to_string (self):
+ # Cast val to a void pointer to stop gdb using this pretty
+ # printer for the pointer which would lead to an infinite loop.
+ void_ptr = gdb.lookup_type('void').pointer()
+ value = str(self.val.cast(void_ptr))
+
+ context = gdb.parse_and_eval("isl_ctx_alloc()")
+ printer = gdb.parse_and_eval("isl_printer_to_str("
+ + str(context) + ")")
+ printer = gdb.parse_and_eval("isl_printer_print_isl_int("
+ + str(printer) + ", "
+ + value + ")")
+ string = gdb.parse_and_eval("(char*)isl_printer_get_str("
+ + str(printer) + ")")
+ gdb.parse_and_eval("isl_printer_free(" + str(printer) + ")")
+ gdb.parse_and_eval("isl_ctx_free(" + str(context) + ")")
+ return string
+
+ def display_hint (self):
+ return 'string'
+
+class IslPrintCommand (gdb.Command):
+ """Print an isl value."""
+ def __init__ (self):
+ super (IslPrintCommand, self).__init__ ("islprint",
+ gdb.COMMAND_OBSCURE)
+ def invoke (self, arg, from_tty):
+ arg = gdb.parse_and_eval(arg);
+ printer = str_lookup_function(arg)
+
+ if printer == None:
+ print "No isl printer for this type"
+ return
+
+ print printer.to_string()
+
+IslPrintCommand()
+
+def str_lookup_function (val):
+ if val.type.code != gdb.TYPE_CODE_PTR:
+ if str(val.type) == "isl_int":
+ return IslIntPrinter(val)
+ else:
+ return None
+
+ lookup_tag = val.type.target()
+ regex = re.compile ("^isl_(.*)$")
+
+ if lookup_tag == None:
+ return None
+
+ m = regex.match (str(lookup_tag))
+
+ if m:
+ # Those types of printers defined in isl.
+ if m.group(1) in ["basic_set", "set", "union_set", "basic_map",
+ "map", "union_map", "qpolynomial",
+ "pw_qpolynomial", "pw_qpolynomial_fold",
+ "union_pw_qpolynomial",
+ "union_pw_qpolynomial_fold"]:
+ return IslObjectPrinter(val, m.group(1))
+ return None
+
+# Do not register the pretty printer.
+# gdb.current_objfile().pretty_printers.append(str_lookup_function)
diff --git a/polly/lib/External/isl/isl_aff.c b/polly/lib/External/isl/isl_aff.c
new file mode 100644
index 00000000000..7c785047635
--- /dev/null
+++ b/polly/lib/External/isl/isl_aff.c
@@ -0,0 +1,6809 @@
+/*
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-2014 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_ctx_private.h>
+#define ISL_DIM_H
+#include <isl_map_private.h>
+#include <isl_union_map_private.h>
+#include <isl_aff_private.h>
+#include <isl_space_private.h>
+#include <isl_local_space_private.h>
+#include <isl_vec_private.h>
+#include <isl_mat_private.h>
+#include <isl/constraint.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl_val_private.h>
+#include <isl/deprecated/aff_int.h>
+#include <isl_config.h>
+
+#undef BASE
+#define BASE aff
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_list_templ.c>
+
+__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
+ __isl_take isl_vec *v)
+{
+ isl_aff *aff;
+
+ if (!ls || !v)
+ goto error;
+
+ aff = isl_calloc_type(v->ctx, struct isl_aff);
+ if (!aff)
+ goto error;
+
+ aff->ref = 1;
+ aff->ls = ls;
+ aff->v = v;
+
+ return aff;
+error:
+ isl_local_space_free(ls);
+ isl_vec_free(v);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
+{
+ isl_ctx *ctx;
+ isl_vec *v;
+ unsigned total;
+
+ if (!ls)
+ return NULL;
+
+ ctx = isl_local_space_get_ctx(ls);
+ if (!isl_local_space_divs_known(ls))
+ isl_die(ctx, isl_error_invalid, "local space has unknown divs",
+ goto error);
+ if (!isl_local_space_is_set(ls))
+ isl_die(ctx, isl_error_invalid,
+ "domain of affine expression should be a set",
+ goto error);
+
+ total = isl_local_space_dim(ls, isl_dim_all);
+ v = isl_vec_alloc(ctx, 1 + 1 + total);
+ return isl_aff_alloc_vec(ls, v);
+error:
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls)
+{
+ isl_aff *aff;
+
+ aff = isl_aff_alloc(ls);
+ if (!aff)
+ return NULL;
+
+ isl_int_set_si(aff->v->el[0], 1);
+ isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
+
+ return aff;
+}
+
+/* Return a piecewise affine expression defined on the specified domain
+ * that is equal to zero.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls)
+{
+ return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
+}
+
+/* Return an affine expression defined on the specified domain
+ * that represents NaN.
+ */
+__isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls)
+{
+ isl_aff *aff;
+
+ aff = isl_aff_alloc(ls);
+ if (!aff)
+ return NULL;
+
+ isl_seq_clr(aff->v->el, aff->v->size);
+
+ return aff;
+}
+
+/* Return a piecewise affine expression defined on the specified domain
+ * that represents NaN.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls)
+{
+ return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls));
+}
+
+/* Return an affine expression that is equal to "val" on
+ * domain local space "ls".
+ */
+__isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
+ __isl_take isl_val *val)
+{
+ isl_aff *aff;
+
+ if (!ls || !val)
+ goto error;
+ if (!isl_val_is_rat(val))
+ isl_die(isl_val_get_ctx(val), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ if (!aff)
+ goto error;
+
+ isl_seq_clr(aff->v->el + 2, aff->v->size - 2);
+ isl_int_set(aff->v->el[1], val->n);
+ isl_int_set(aff->v->el[0], val->d);
+
+ isl_local_space_free(ls);
+ isl_val_free(val);
+ return aff;
+error:
+ isl_local_space_free(ls);
+ isl_val_free(val);
+ return NULL;
+}
+
+/* Return an affine expression that is equal to the specified dimension
+ * in "ls".
+ */
+__isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ isl_space *space;
+ isl_aff *aff;
+
+ if (!ls)
+ return NULL;
+
+ space = isl_local_space_get_space(ls);
+ if (!space)
+ goto error;
+ if (isl_space_is_map(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "expecting (parameter) set space", goto error);
+ if (pos >= isl_local_space_dim(ls, type))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "position out of bounds", goto error);
+
+ isl_space_free(space);
+ aff = isl_aff_alloc(ls);
+ if (!aff)
+ return NULL;
+
+ pos += isl_local_space_offset(aff->ls, type);
+
+ isl_int_set_si(aff->v->el[0], 1);
+ isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
+ isl_int_set_si(aff->v->el[1 + pos], 1);
+
+ return aff;
+error:
+ isl_local_space_free(ls);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Return a piecewise affine expression that is equal to
+ * the specified dimension in "ls".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos));
+}
+
+__isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+
+ aff->ref++;
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+
+ return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
+ isl_vec_copy(aff->v));
+}
+
+__isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+
+ if (aff->ref == 1)
+ return aff;
+ aff->ref--;
+ return isl_aff_dup(aff);
+}
+
+__isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+
+ if (--aff->ref > 0)
+ return NULL;
+
+ isl_local_space_free(aff->ls);
+ isl_vec_free(aff->v);
+
+ free(aff);
+
+ return NULL;
+}
+
+isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
+{
+ return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
+}
+
+/* Externally, an isl_aff has a map space, but internally, the
+ * ls field corresponds to the domain of that space.
+ */
+int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
+{
+ if (!aff)
+ return 0;
+ if (type == isl_dim_out)
+ return 1;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ return isl_local_space_dim(aff->ls, type);
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "aff".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type,
+ const char *name)
+{
+ if (!aff)
+ return -1;
+ if (type == isl_dim_out)
+ return -1;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ return isl_local_space_find_dim_by_name(aff->ls, type, name);
+}
+
+__isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff)
+{
+ return aff ? isl_local_space_get_space(aff->ls) : NULL;
+}
+
+__isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff)
+{
+ isl_space *space;
+ if (!aff)
+ return NULL;
+ space = isl_local_space_get_space(aff->ls);
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ return space;
+}
+
+__isl_give isl_local_space *isl_aff_get_domain_local_space(
+ __isl_keep isl_aff *aff)
+{
+ return aff ? isl_local_space_copy(aff->ls) : NULL;
+}
+
+__isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
+{
+ isl_local_space *ls;
+ if (!aff)
+ return NULL;
+ ls = isl_local_space_copy(aff->ls);
+ ls = isl_local_space_from_domain(ls);
+ ls = isl_local_space_add_dims(ls, isl_dim_out, 1);
+ return ls;
+}
+
+/* Externally, an isl_aff has a map space, but internally, the
+ * ls field corresponds to the domain of that space.
+ */
+const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!aff)
+ return NULL;
+ if (type == isl_dim_out)
+ return NULL;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ return isl_local_space_get_dim_name(aff->ls, type, pos);
+}
+
+__isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
+ __isl_take isl_space *dim)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff || !dim)
+ goto error;
+
+ aff->ls = isl_local_space_reset_space(aff->ls, dim);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Reset the space of "aff". This function is called from isl_pw_templ.c
+ * and doesn't know if the space of an element object is represented
+ * directly or through its domain. It therefore passes along both.
+ */
+__isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
+ __isl_take isl_space *space, __isl_take isl_space *domain)
+{
+ isl_space_free(space);
+ return isl_aff_reset_domain_space(aff, domain);
+}
+
+/* Reorder the coefficients of the affine expression based
+ * on the given reodering.
+ * The reordering r is assumed to have been extended with the local
+ * variables.
+ */
+static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec,
+ __isl_take isl_reordering *r, int n_div)
+{
+ isl_vec *res;
+ int i;
+
+ if (!vec || !r)
+ goto error;
+
+ res = isl_vec_alloc(vec->ctx,
+ 2 + isl_space_dim(r->dim, isl_dim_all) + n_div);
+ isl_seq_cpy(res->el, vec->el, 2);
+ isl_seq_clr(res->el + 2, res->size - 2);
+ for (i = 0; i < r->len; ++i)
+ isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i]);
+
+ isl_reordering_free(r);
+ isl_vec_free(vec);
+ return res;
+error:
+ isl_vec_free(vec);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+/* Reorder the dimensions of the domain of "aff" according
+ * to the given reordering.
+ */
+__isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
+ __isl_take isl_reordering *r)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+
+ r = isl_reordering_extend(r, aff->ls->div->n_row);
+ aff->v = vec_reorder(aff->v, isl_reordering_copy(r),
+ aff->ls->div->n_row);
+ aff->ls = isl_local_space_realign(aff->ls, r);
+
+ if (!aff->v || !aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
+ __isl_take isl_space *model)
+{
+ if (!aff || !model)
+ goto error;
+
+ if (!isl_space_match(aff->ls->dim, isl_dim_param,
+ model, isl_dim_param)) {
+ isl_reordering *exp;
+
+ model = isl_space_drop_dims(model, isl_dim_in,
+ 0, isl_space_dim(model, isl_dim_in));
+ model = isl_space_drop_dims(model, isl_dim_out,
+ 0, isl_space_dim(model, isl_dim_out));
+ exp = isl_parameter_alignment_reordering(aff->ls->dim, model);
+ exp = isl_reordering_extend_space(exp,
+ isl_aff_get_domain_space(aff));
+ aff = isl_aff_realign_domain(aff, exp);
+ }
+
+ isl_space_free(model);
+ return aff;
+error:
+ isl_space_free(model);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Is "aff" obviously equal to zero?
+ *
+ * If the denominator is zero, then "aff" is not equal to zero.
+ */
+int isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return -1;
+
+ if (isl_int_is_zero(aff->v->el[0]))
+ return 0;
+ return isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1) < 0;
+}
+
+/* Does "aff" represent NaN?
+ */
+int isl_aff_is_nan(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return -1;
+
+ return isl_seq_first_non_zero(aff->v->el, 2) < 0;
+}
+
+/* Does "pa" involve any NaNs?
+ */
+int isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa)
+{
+ int i;
+
+ if (!pa)
+ return -1;
+ if (pa->n == 0)
+ return 0;
+
+ for (i = 0; i < pa->n; ++i) {
+ int is_nan = isl_aff_is_nan(pa->p[i].aff);
+ if (is_nan < 0 || is_nan)
+ return is_nan;
+ }
+
+ return 0;
+}
+
+/* Are "aff1" and "aff2" obviously equal?
+ *
+ * NaN is not equal to anything, not even to another NaN.
+ */
+int isl_aff_plain_is_equal(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
+{
+ int equal;
+
+ if (!aff1 || !aff2)
+ return -1;
+
+ if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2))
+ return 0;
+
+ equal = isl_local_space_is_equal(aff1->ls, aff2->ls);
+ if (equal < 0 || !equal)
+ return equal;
+
+ return isl_vec_is_equal(aff1->v, aff2->v);
+}
+
+/* Return the common denominator of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
+{
+ if (!aff)
+ return -1;
+ if (isl_aff_is_nan(aff))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot get denominator of NaN", return -1);
+ isl_int_set(*v, aff->v->el[0]);
+ return 0;
+}
+
+/* Return the common denominator of "aff".
+ */
+__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
+{
+ isl_ctx *ctx;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (isl_aff_is_nan(aff))
+ return isl_val_nan(ctx);
+ return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
+}
+
+/* Return the constant term of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
+{
+ if (!aff)
+ return -1;
+ if (isl_aff_is_nan(aff))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot get constant term of NaN", return -1);
+ isl_int_set(*v, aff->v->el[1]);
+ return 0;
+}
+
+/* Return the constant term of "aff".
+ */
+__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (isl_aff_is_nan(aff))
+ return isl_val_nan(ctx);
+ v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
+ return isl_val_normalize(v);
+}
+
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int *v)
+{
+ if (!aff)
+ return -1;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return -1);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", return -1);
+
+ if (isl_aff_is_nan(aff))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot get coefficient of NaN", return -1);
+ pos += isl_local_space_offset(aff->ls, type);
+ isl_int_set(*v, aff->v->el[1 + pos]);
+
+ return 0;
+}
+
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "aff".
+ */
+__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, int pos)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (type == isl_dim_out)
+ isl_die(ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return NULL);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(ctx, isl_error_invalid,
+ "position out of bounds", return NULL);
+
+ if (isl_aff_is_nan(aff))
+ return isl_val_nan(ctx);
+ pos += isl_local_space_offset(aff->ls, type);
+ v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
+ return isl_val_normalize(v);
+}
+
+/* Return the sign of the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ */
+int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
+ int pos)
+{
+ isl_ctx *ctx;
+
+ if (!aff)
+ return 0;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (type == isl_dim_out)
+ isl_die(ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return 0);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(ctx, isl_error_invalid,
+ "position out of bounds", return 0);
+
+ pos += isl_local_space_offset(aff->ls, type);
+ return isl_int_sgn(aff->v->el[1 + pos]);
+}
+
+/* Replace the denominator of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
+{
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_set(aff->v->el[0], v);
+
+ return aff;
+}
+
+/* Replace the numerator of the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
+{
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_set(aff->v->el[1], v);
+
+ return aff;
+}
+
+/* Replace the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (isl_aff_is_nan(aff)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ if (isl_int_eq(aff->v->el[1], v->n) &&
+ isl_int_eq(aff->v->el[0], v->d)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_set(aff->v->el[1], v->n);
+ } else if (isl_int_is_one(v->d)) {
+ isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Add "v" to the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
+{
+ if (isl_int_is_zero(v))
+ return aff;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
+
+ return aff;
+}
+
+/* Add "v" to the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (isl_aff_is_nan(aff) || isl_val_is_zero(v)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ if (isl_int_is_one(v->d)) {
+ isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+ } else if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
+{
+ isl_int t;
+
+ isl_int_init(t);
+ isl_int_set_si(t, v);
+ aff = isl_aff_add_constant(aff, t);
+ isl_int_clear(t);
+
+ return aff;
+}
+
+/* Add "v" to the numerator of the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v)
+{
+ if (isl_int_is_zero(v))
+ return aff;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_add(aff->v->el[1], aff->v->el[1], v);
+
+ return aff;
+}
+
+/* Add "v" to the numerator of the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v)
+{
+ isl_int t;
+
+ if (v == 0)
+ return aff;
+
+ isl_int_init(t);
+ isl_int_set_si(t, v);
+ aff = isl_aff_add_constant_num(aff, t);
+ isl_int_clear(t);
+
+ return aff;
+}
+
+/* Replace the numerator of the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
+{
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_set_si(aff->v->el[1], v);
+
+ return aff;
+}
+
+/* Replace the numerator of the coefficient of the variable of type "type"
+ * at position "pos" of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int v)
+{
+ if (!aff)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", return isl_aff_free(aff));
+
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ pos += isl_local_space_offset(aff->ls, type);
+ isl_int_set(aff->v->el[1 + pos], v);
+
+ return aff;
+}
+
+/* Replace the numerator of the coefficient of the variable of type "type"
+ * at position "pos" of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v)
+{
+ if (!aff)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos < 0 || pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", return isl_aff_free(aff));
+
+ if (isl_aff_is_nan(aff))
+ return aff;
+ pos += isl_local_space_offset(aff->ls, type);
+ if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0)
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_set_si(aff->v->el[1 + pos], v);
+
+ return aff;
+}
+
+/* Replace the coefficient of the variable of type "type" at position "pos"
+ * of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", goto error);
+
+ if (isl_aff_is_nan(aff)) {
+ isl_val_free(v);
+ return aff;
+ }
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ pos += isl_local_space_offset(aff->ls, type);
+ if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
+ isl_int_eq(aff->v->el[0], v->d)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_set(aff->v->el[1 + pos], v->n);
+ } else if (isl_int_is_one(v->d)) {
+ isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Add "v" to the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int v)
+{
+ if (!aff)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", return isl_aff_free(aff));
+
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ pos += isl_local_space_offset(aff->ls, type);
+ isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
+
+ return aff;
+}
+
+/* Add "v" to the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (isl_val_is_zero(v)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ if (pos >= isl_local_space_dim(aff->ls, type))
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "position out of bounds", goto error);
+
+ if (isl_aff_is_nan(aff)) {
+ isl_val_free(v);
+ return aff;
+ }
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ goto error;
+
+ pos += isl_local_space_offset(aff->ls, type);
+ if (isl_int_is_one(v->d)) {
+ isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ } else if (isl_int_eq(aff->v->el[0], v->d)) {
+ isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ } else {
+ isl_seq_scale(aff->v->el + 1,
+ aff->v->el + 1, v->d, aff->v->size - 1);
+ isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, int v)
+{
+ isl_int t;
+
+ isl_int_init(t);
+ isl_int_set_si(t, v);
+ aff = isl_aff_add_coefficient(aff, type, pos, t);
+ isl_int_clear(t);
+
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
+{
+ if (!aff)
+ return NULL;
+
+ return isl_local_space_get_div(aff->ls, pos);
+}
+
+/* Return the negation of "aff".
+ *
+ * As a special case, -NaN = NaN.
+ */
+__isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
+
+ return aff;
+}
+
+/* Remove divs from the local space that do not appear in the affine
+ * expression.
+ * We currently only remove divs at the end.
+ * Some intermediate divs may also not appear directly in the affine
+ * 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)
+{
+ int pos;
+ int off;
+ int n;
+
+ if (!aff)
+ return NULL;
+
+ n = isl_local_space_dim(aff->ls, isl_dim_div);
+ off = isl_local_space_offset(aff->ls, isl_dim_div);
+
+ pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
+ if (pos == n)
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos);
+ aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos);
+ if (!aff->ls || !aff->v)
+ return isl_aff_free(aff);
+
+ return aff;
+}
+
+/* Given two affine expressions "p" of length p_len (including the
+ * denominator and the constant term) and "subs" of length subs_len,
+ * plug in "subs" for the variable at position "pos".
+ * The variables of "subs" and "p" are assumed to match up to subs_len,
+ * but "p" may have additional variables.
+ * "v" is an initialized isl_int that can be used internally.
+ *
+ * In particular, if "p" represents the expression
+ *
+ * (a i + g)/m
+ *
+ * with i the variable at position "pos" and "subs" represents the expression
+ *
+ * f/d
+ *
+ * then the result represents the expression
+ *
+ * (a f + d g)/(m d)
+ *
+ */
+void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
+ int p_len, int subs_len, isl_int v)
+{
+ isl_int_set(v, p[1 + pos]);
+ isl_int_set_si(p[1 + pos], 0);
+ isl_seq_combine(p + 1, subs[0], p + 1, v, subs + 1, subs_len - 1);
+ isl_seq_scale(p + subs_len, p + subs_len, subs[0], p_len - subs_len);
+ isl_int_mul(p[0], p[0], subs[0]);
+}
+
+/* Look for any divs in the aff->ls with a denominator equal to one
+ * and plug them into the affine expression and any subsequent divs
+ * that may reference the div.
+ */
+static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
+{
+ int i, n;
+ int len;
+ isl_int v;
+ isl_vec *vec;
+ isl_local_space *ls;
+ unsigned pos;
+
+ if (!aff)
+ return NULL;
+
+ n = isl_local_space_dim(aff->ls, isl_dim_div);
+ len = aff->v->size;
+ for (i = 0; i < n; ++i) {
+ if (!isl_int_is_one(aff->ls->div->row[i][0]))
+ continue;
+ ls = isl_local_space_copy(aff->ls);
+ ls = isl_local_space_substitute_seq(ls, isl_dim_div, i,
+ aff->ls->div->row[i], len, i + 1, n - (i + 1));
+ vec = isl_vec_copy(aff->v);
+ vec = isl_vec_cow(vec);
+ if (!ls || !vec)
+ goto error;
+
+ isl_int_init(v);
+
+ pos = isl_local_space_offset(aff->ls, isl_dim_div) + i;
+ isl_seq_substitute(vec->el, pos, aff->ls->div->row[i],
+ len, len, v);
+
+ isl_int_clear(v);
+
+ isl_vec_free(aff->v);
+ aff->v = vec;
+ isl_local_space_free(aff->ls);
+ aff->ls = ls;
+ }
+
+ return aff;
+error:
+ isl_vec_free(vec);
+ isl_local_space_free(ls);
+ return isl_aff_free(aff);
+}
+
+/* Look for any divs j that appear with a unit coefficient inside
+ * the definitions of other divs i and plug them into the definitions
+ * of the divs i.
+ *
+ * In particular, an expression of the form
+ *
+ * floor((f(..) + floor(g(..)/n))/m)
+ *
+ * is simplified to
+ *
+ * floor((n * f(..) + g(..))/(n * m))
+ *
+ * This simplification is correct because we can move the expression
+ * f(..) into the inner floor in the original expression to obtain
+ *
+ * floor(floor((n * f(..) + g(..))/n)/m)
+ *
+ * from which we can derive the simplified expression.
+ */
+static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
+{
+ int i, j, n;
+ int off;
+
+ if (!aff)
+ return NULL;
+
+ n = isl_local_space_dim(aff->ls, isl_dim_div);
+ off = isl_local_space_offset(aff->ls, isl_dim_div);
+ for (i = 1; i < n; ++i) {
+ for (j = 0; j < i; ++j) {
+ if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j]))
+ continue;
+ aff->ls = isl_local_space_substitute_seq(aff->ls,
+ isl_dim_div, j, aff->ls->div->row[j],
+ aff->v->size, i, 1);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+ }
+ }
+
+ return aff;
+}
+
+/* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
+ *
+ * Even though this function is only called on isl_affs with a single
+ * reference, we are careful to only change aff->v and aff->ls together.
+ */
+static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
+{
+ unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
+ isl_local_space *ls;
+ isl_vec *v;
+
+ ls = isl_local_space_copy(aff->ls);
+ ls = isl_local_space_swap_div(ls, a, b);
+ v = isl_vec_copy(aff->v);
+ v = isl_vec_cow(v);
+ if (!ls || !v)
+ goto error;
+
+ isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]);
+ isl_vec_free(aff->v);
+ aff->v = v;
+ isl_local_space_free(aff->ls);
+ aff->ls = ls;
+
+ return aff;
+error:
+ isl_vec_free(v);
+ isl_local_space_free(ls);
+ return isl_aff_free(aff);
+}
+
+/* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
+ *
+ * We currently do not actually remove div "b", but simply add its
+ * coefficient to that of "a" and then zero it out.
+ */
+static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
+{
+ unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
+
+ if (isl_int_is_zero(aff->v->el[1 + off + b]))
+ return aff;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_add(aff->v->el[1 + off + a],
+ aff->v->el[1 + off + a], aff->v->el[1 + off + b]);
+ isl_int_set_si(aff->v->el[1 + off + b], 0);
+
+ return aff;
+}
+
+/* Sort the divs in the local space of "aff" according to
+ * the comparison function "cmp_row" in isl_local_space.c,
+ * combining the coefficients of identical divs.
+ *
+ * Reordering divs does not change the semantics of "aff",
+ * so there is no need to call isl_aff_cow.
+ * Moreover, this function is currently only called on isl_affs
+ * with a single reference.
+ */
+static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
+{
+ int i, j, n;
+ unsigned off;
+
+ if (!aff)
+ return NULL;
+
+ off = isl_local_space_offset(aff->ls, isl_dim_div);
+ n = isl_aff_dim(aff, isl_dim_div);
+ for (i = 1; i < n; ++i) {
+ for (j = i - 1; j >= 0; --j) {
+ int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1);
+ if (cmp < 0)
+ break;
+ if (cmp == 0)
+ aff = merge_divs(aff, j, j + 1);
+ else
+ aff = swap_div(aff, j, j + 1);
+ if (!aff)
+ return NULL;
+ }
+ }
+
+ return aff;
+}
+
+/* Normalize the representation of "aff".
+ *
+ * This function should only be called of "new" isl_affs, i.e.,
+ * with only a single reference. We therefore do not need to
+ * worry about affecting other instances.
+ */
+__isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+ aff->v = isl_vec_normalize(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+ aff = plug_in_integral_divs(aff);
+ aff = plug_in_unit_divs(aff);
+ aff = sort_divs(aff);
+ aff = isl_aff_remove_unused_divs(aff);
+ return aff;
+}
+
+/* Given f, return floor(f).
+ * If f is an integer expression, then just return f.
+ * If f is a constant, then return the constant floor(f).
+ * Otherwise, if f = g/m, write g = q m + r,
+ * create a new div d = [r/m] and return the expression q + d.
+ * The coefficients in r are taken to lie between -m/2 and m/2.
+ *
+ * As a special case, floor(NaN) = NaN.
+ */
+__isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff)
+{
+ int i;
+ int size;
+ isl_ctx *ctx;
+ isl_vec *div;
+
+ if (!aff)
+ return NULL;
+
+ if (isl_aff_is_nan(aff))
+ return aff;
+ if (isl_int_is_one(aff->v->el[0]))
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ if (isl_aff_is_cst(aff)) {
+ isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
+ isl_int_set_si(aff->v->el[0], 1);
+ return aff;
+ }
+
+ div = isl_vec_copy(aff->v);
+ div = isl_vec_cow(div);
+ if (!div)
+ return isl_aff_free(aff);
+
+ ctx = isl_aff_get_ctx(aff);
+ isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two);
+ for (i = 1; i < aff->v->size; ++i) {
+ isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]);
+ isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]);
+ if (isl_int_gt(div->el[i], aff->v->el[0])) {
+ isl_int_sub(div->el[i], div->el[i], div->el[0]);
+ isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1);
+ }
+ }
+
+ aff->ls = isl_local_space_add_div(aff->ls, div);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ size = aff->v->size;
+ aff->v = isl_vec_extend(aff->v, size + 1);
+ if (!aff->v)
+ return isl_aff_free(aff);
+ isl_int_set_si(aff->v->el[0], 1);
+ isl_int_set_si(aff->v->el[size], 1);
+
+ aff = isl_aff_normalize(aff);
+
+ return aff;
+}
+
+/* Compute
+ *
+ * aff mod m = aff - m * floor(aff/m)
+ */
+__isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int m)
+{
+ isl_aff *res;
+
+ res = isl_aff_copy(aff);
+ aff = isl_aff_scale_down(aff, m);
+ aff = isl_aff_floor(aff);
+ aff = isl_aff_scale(aff, m);
+ res = isl_aff_sub(res, aff);
+
+ return res;
+}
+
+/* Compute
+ *
+ * aff mod m = aff - m * floor(aff/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *m)
+{
+ isl_aff *res;
+
+ if (!aff || !m)
+ goto error;
+
+ if (!isl_val_is_int(m))
+ isl_die(isl_val_get_ctx(m), isl_error_invalid,
+ "expecting integer modulo", goto error);
+
+ res = isl_aff_copy(aff);
+ aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
+ aff = isl_aff_floor(aff);
+ aff = isl_aff_scale_val(aff, m);
+ res = isl_aff_sub(res, aff);
+
+ return res;
+error:
+ isl_aff_free(aff);
+ isl_val_free(m);
+ return NULL;
+}
+
+/* Compute
+ *
+ * pwaff mod m = pwaff - m * floor(pwaff/m)
+ */
+__isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
+{
+ isl_pw_aff *res;
+
+ res = isl_pw_aff_copy(pwaff);
+ pwaff = isl_pw_aff_scale_down(pwaff, m);
+ pwaff = isl_pw_aff_floor(pwaff);
+ pwaff = isl_pw_aff_scale(pwaff, m);
+ res = isl_pw_aff_sub(res, pwaff);
+
+ return res;
+}
+
+/* Compute
+ *
+ * pa mod m = pa - m * floor(pa/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
+ __isl_take isl_val *m)
+{
+ if (!pa || !m)
+ goto error;
+ if (!isl_val_is_int(m))
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "expecting integer modulo", goto error);
+ pa = isl_pw_aff_mod(pa, m->n);
+ isl_val_free(m);
+ return pa;
+error:
+ isl_pw_aff_free(pa);
+ isl_val_free(m);
+ return NULL;
+}
+
+/* Given f, return ceil(f).
+ * If f is an integer expression, then just return f.
+ * Otherwise, let f be the expression
+ *
+ * e/m
+ *
+ * then return
+ *
+ * floor((e + m - 1)/m)
+ *
+ * As a special case, ceil(NaN) = NaN.
+ */
+__isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
+{
+ if (!aff)
+ return NULL;
+
+ if (isl_aff_is_nan(aff))
+ return aff;
+ if (isl_int_is_one(aff->v->el[0]))
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
+ isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1);
+ aff = isl_aff_floor(aff);
+
+ return aff;
+}
+
+/* Apply the expansion computed by isl_merge_divs.
+ * The expansion itself is given by "exp" while the resulting
+ * list of divs is given by "div".
+ */
+__isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
+ __isl_take isl_mat *div, int *exp)
+{
+ int i, j;
+ int old_n_div;
+ int new_n_div;
+ int offset;
+
+ aff = isl_aff_cow(aff);
+ if (!aff || !div)
+ goto error;
+
+ old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+ new_n_div = isl_mat_rows(div);
+ if (new_n_div < old_n_div)
+ isl_die(isl_mat_get_ctx(div), isl_error_invalid,
+ "not an expansion", goto error);
+
+ aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
+ if (!aff->v)
+ goto error;
+
+ offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
+ j = old_n_div - 1;
+ for (i = new_n_div - 1; i >= 0; --i) {
+ if (j >= 0 && exp[j] == i) {
+ if (i != j)
+ isl_int_swap(aff->v->el[offset + i],
+ aff->v->el[offset + j]);
+ j--;
+ } else
+ isl_int_set_si(aff->v->el[offset + i], 0);
+ }
+
+ aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));
+ if (!aff->ls)
+ goto error;
+ isl_mat_free(div);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_mat_free(div);
+ return NULL;
+}
+
+/* Add two affine expressions that live in the same local space.
+ */
+static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ isl_int gcd, f;
+
+ aff1 = isl_aff_cow(aff1);
+ if (!aff1 || !aff2)
+ goto error;
+
+ aff1->v = isl_vec_cow(aff1->v);
+ if (!aff1->v)
+ goto error;
+
+ isl_int_init(gcd);
+ isl_int_init(f);
+ isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
+ isl_int_divexact(f, aff2->v->el[0], gcd);
+ isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
+ isl_int_divexact(f, aff1->v->el[0], gcd);
+ isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
+ isl_int_divexact(f, aff2->v->el[0], gcd);
+ isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
+ isl_int_clear(f);
+ isl_int_clear(gcd);
+
+ isl_aff_free(aff2);
+ return aff1;
+error:
+ isl_aff_free(aff1);
+ isl_aff_free(aff2);
+ return NULL;
+}
+
+/* Return the sum of "aff1" and "aff2".
+ *
+ * If either of the two is NaN, then the result is NaN.
+ */
+__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ isl_ctx *ctx;
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_mat *div;
+ int n_div1, n_div2;
+
+ if (!aff1 || !aff2)
+ goto error;
+
+ ctx = isl_aff_get_ctx(aff1);
+ if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", goto error);
+
+ if (isl_aff_is_nan(aff1)) {
+ isl_aff_free(aff2);
+ return aff1;
+ }
+ if (isl_aff_is_nan(aff2)) {
+ isl_aff_free(aff1);
+ return aff2;
+ }
+
+ n_div1 = isl_aff_dim(aff1, isl_dim_div);
+ n_div2 = isl_aff_dim(aff2, isl_dim_div);
+ if (n_div1 == 0 && n_div2 == 0)
+ return add_expanded(aff1, aff2);
+
+ exp1 = isl_alloc_array(ctx, int, n_div1);
+ exp2 = isl_alloc_array(ctx, int, n_div2);
+ if ((n_div1 && !exp1) || (n_div2 && !exp2))
+ goto error;
+
+ div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
+ aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
+ aff2 = isl_aff_expand_divs(aff2, div, exp2);
+ free(exp1);
+ free(exp2);
+
+ return add_expanded(aff1, aff2);
+error:
+ free(exp1);
+ free(exp2);
+ isl_aff_free(aff1);
+ isl_aff_free(aff2);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ return isl_aff_add(aff1, isl_aff_neg(aff2));
+}
+
+/* Return the result of scaling "aff" by a factor of "f".
+ *
+ * As a special case, f * NaN = NaN.
+ */
+__isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
+{
+ isl_int gcd;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+
+ if (isl_int_is_one(f))
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) {
+ isl_int_divexact(aff->v->el[0], aff->v->el[0], f);
+ return aff;
+ }
+
+ isl_int_init(gcd);
+ isl_int_gcd(gcd, aff->v->el[0], f);
+ isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd);
+ isl_int_divexact(gcd, f, gcd);
+ isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
+ isl_int_clear(gcd);
+
+ return aff;
+}
+
+/* Multiple "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational factor", goto error);
+
+ aff = isl_aff_scale(aff, v->n);
+ aff = isl_aff_scale_down(aff, v->d);
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Return the result of scaling "aff" down by a factor of "f".
+ *
+ * As a special case, NaN/f = NaN.
+ */
+__isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
+{
+ isl_int gcd;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff))
+ return aff;
+
+ if (isl_int_is_one(f))
+ return aff;
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ if (isl_int_is_zero(f))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot scale down by zero", return isl_aff_free(aff));
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ isl_int_init(gcd);
+ isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd);
+ isl_int_gcd(gcd, gcd, f);
+ isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
+ isl_int_divexact(gcd, f, gcd);
+ isl_int_mul(aff->v->el[0], aff->v->el[0], gcd);
+ isl_int_clear(gcd);
+
+ return aff;
+}
+
+/* Divide "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
+ __isl_take isl_val *v)
+{
+ if (!aff || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return aff;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (!isl_val_is_pos(v))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "factor needs to be positive", goto error);
+
+ aff = isl_aff_scale(aff, v->d);
+ aff = isl_aff_scale_down(aff, v->n);
+
+ isl_val_free(v);
+ return aff;
+error:
+ isl_aff_free(aff);
+ isl_val_free(v);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
+{
+ isl_int v;
+
+ if (f == 1)
+ return aff;
+
+ isl_int_init(v);
+ isl_int_set_ui(v, f);
+ aff = isl_aff_scale_down(aff, v);
+ isl_int_clear(v);
+
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "cannot set name of output/set dimension",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "cannot set name of output/set dimension",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+error:
+ isl_id_free(id);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Replace the identifier of the input tuple of "aff" by "id".
+ * type is currently required to be equal to isl_dim_in
+ */
+__isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+ if (type != isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "cannot only set id of input tuple", goto error);
+ aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+error:
+ isl_id_free(id);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Exploit the equalities in "eq" to simplify the affine expression
+ * and the expressions of the integer divisions in the local space.
+ * The integer divisions in this local space are assumed to appear
+ * as regular dimensions in "eq".
+ */
+static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
+ __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
+{
+ int i, j;
+ unsigned total;
+ unsigned n_div;
+
+ if (!eq)
+ goto error;
+ if (eq->n_eq == 0) {
+ isl_basic_set_free(eq);
+ return aff;
+ }
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ goto error;
+
+ aff->ls = isl_local_space_substitute_equalities(aff->ls,
+ isl_basic_set_copy(eq));
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->ls || !aff->v)
+ goto error;
+
+ total = 1 + isl_space_dim(eq->dim, isl_dim_all);
+ n_div = eq->n_div;
+ for (i = 0; i < eq->n_eq; ++i) {
+ j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
+ if (j < 0 || j == 0 || j >= total)
+ continue;
+
+ isl_seq_elim(aff->v->el + 1, eq->eq[i], j, total,
+ &aff->v->el[0]);
+ }
+
+ isl_basic_set_free(eq);
+ aff = isl_aff_normalize(aff);
+ return aff;
+error:
+ isl_basic_set_free(eq);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Exploit the equalities in "eq" to simplify the affine expression
+ * and the expressions of the integer divisions in the local space.
+ */
+static __isl_give isl_aff *isl_aff_substitute_equalities(
+ __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
+{
+ int n_div;
+
+ if (!aff || !eq)
+ goto error;
+ n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+ if (n_div > 0)
+ eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div);
+ return isl_aff_substitute_equalities_lifted(aff, eq);
+error:
+ isl_basic_set_free(eq);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Look for equalities among the variables shared by context and aff
+ * and the integer divisions of aff, if any.
+ * The equalities are then used to eliminate coefficients and/or integer
+ * divisions from aff.
+ */
+__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
+ __isl_take isl_set *context)
+{
+ isl_basic_set *hull;
+ int n_div;
+
+ if (!aff)
+ goto error;
+ n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+ if (n_div > 0) {
+ isl_basic_set *bset;
+ isl_local_space *ls;
+ context = isl_set_add_dims(context, isl_dim_set, n_div);
+ ls = isl_aff_get_domain_local_space(aff);
+ bset = isl_basic_set_from_local_space(ls);
+ bset = isl_basic_set_lift(bset);
+ bset = isl_basic_set_flatten(bset);
+ context = isl_set_intersect(context,
+ isl_set_from_basic_set(bset));
+ }
+
+ hull = isl_set_affine_hull(context);
+ return isl_aff_substitute_equalities_lifted(aff, hull);
+error:
+ isl_aff_free(aff);
+ isl_set_free(context);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
+ __isl_take isl_set *context)
+{
+ isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff));
+ dom_context = isl_set_intersect_params(dom_context, context);
+ return isl_aff_gist(aff, dom_context);
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is non-negative.
+ * If "rational" is set, then return a rational basic set.
+ *
+ * If "aff" is NaN, then it is not non-negative (it's not negative either).
+ */
+static __isl_give isl_basic_set *aff_nonneg_basic_set(
+ __isl_take isl_aff *aff, int rational)
+{
+ isl_constraint *ineq;
+ isl_basic_set *bset;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff)) {
+ isl_space *space = isl_aff_get_domain_space(aff);
+ isl_aff_free(aff);
+ return isl_basic_set_empty(space);
+ }
+
+ ineq = isl_inequality_from_aff(aff);
+
+ bset = isl_basic_set_from_constraint(ineq);
+ if (rational)
+ bset = isl_basic_set_set_rational(bset);
+ bset = isl_basic_set_simplify(bset);
+ return bset;
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is non-negative.
+ */
+__isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
+{
+ return aff_nonneg_basic_set(aff, 0);
+}
+
+/* Return a basic set containing those elements in the domain space
+ * of aff where it is negative.
+ */
+__isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
+{
+ aff = isl_aff_neg(aff);
+ aff = isl_aff_add_constant_num_si(aff, -1);
+ return isl_aff_nonneg_basic_set(aff);
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is zero.
+ * If "rational" is set, then return a rational basic set.
+ *
+ * If "aff" is NaN, then it is not zero.
+ */
+static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
+ int rational)
+{
+ isl_constraint *ineq;
+ isl_basic_set *bset;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff)) {
+ isl_space *space = isl_aff_get_domain_space(aff);
+ isl_aff_free(aff);
+ return isl_basic_set_empty(space);
+ }
+
+ ineq = isl_equality_from_aff(aff);
+
+ bset = isl_basic_set_from_constraint(ineq);
+ if (rational)
+ bset = isl_basic_set_set_rational(bset);
+ bset = isl_basic_set_simplify(bset);
+ return bset;
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is zero.
+ */
+__isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
+{
+ return aff_zero_basic_set(aff, 0);
+}
+
+/* Return a basic set containing those elements in the shared space
+ * of aff1 and aff2 where aff1 is greater than or equal to aff2.
+ */
+__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ aff1 = isl_aff_sub(aff1, aff2);
+
+ return isl_aff_nonneg_basic_set(aff1);
+}
+
+/* Return a basic set containing those elements in the shared space
+ * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
+ */
+__isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ return isl_aff_ge_basic_set(aff2, aff1);
+}
+
+__isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
+ __isl_take isl_aff *aff1, __isl_take isl_aff *aff2)
+{
+ aff1 = isl_aff_add(aff1, aff2);
+ aff1 = isl_aff_gist(aff1, isl_set_copy(dom));
+ return aff1;
+}
+
+int isl_aff_is_empty(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return -1;
+
+ return 0;
+}
+
+/* Check whether the given affine expression has non-zero coefficient
+ * for any dimension in the given range or if any of these dimensions
+ * appear with non-zero coefficients in any of the integer divisions
+ * involved in the affine expression.
+ */
+int isl_aff_involves_dims(__isl_keep isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ isl_ctx *ctx;
+ int *active = NULL;
+ int involves = 0;
+
+ if (!aff)
+ return -1;
+ if (n == 0)
+ return 0;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (first + n > isl_aff_dim(aff, type))
+ isl_die(ctx, isl_error_invalid,
+ "range out of bounds", return -1);
+
+ active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
+ if (!active)
+ goto error;
+
+ first += isl_local_space_offset(aff->ls, type) - 1;
+ for (i = 0; i < n; ++i)
+ if (active[first + i]) {
+ involves = 1;
+ break;
+ }
+
+ free(active);
+
+ return involves;
+error:
+ free(active);
+ return -1;
+}
+
+__isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_ctx *ctx;
+
+ if (!aff)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "cannot drop output/set dimension",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
+ return aff;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (first + n > isl_local_space_dim(aff->ls, type))
+ isl_die(ctx, isl_error_invalid, "range out of bounds",
+ return isl_aff_free(aff));
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ first += 1 + isl_local_space_offset(aff->ls, type);
+ aff->v = isl_vec_drop_els(aff->v, first, n);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ return aff;
+}
+
+/* Project the domain of the affine expression onto its parameter space.
+ * The affine expression may not involve any of the domain dimensions.
+ */
+__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff)
+{
+ isl_space *space;
+ unsigned n;
+ int involves;
+
+ n = isl_aff_dim(aff, isl_dim_in);
+ involves = isl_aff_involves_dims(aff, isl_dim_in, 0, n);
+ if (involves < 0)
+ return isl_aff_free(aff);
+ if (involves)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "affine expression involves some of the domain dimensions",
+ return isl_aff_free(aff));
+ aff = isl_aff_drop_dims(aff, isl_dim_in, 0, n);
+ space = isl_aff_get_domain_space(aff);
+ space = isl_space_params(space);
+ aff = isl_aff_reset_domain_space(aff, space);
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_ctx *ctx;
+
+ if (!aff)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(aff->v->ctx, isl_error_invalid,
+ "cannot insert output/set dimensions",
+ return isl_aff_free(aff));
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
+ return aff;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (first > isl_local_space_dim(aff->ls, type))
+ isl_die(ctx, isl_error_invalid, "position out of bounds",
+ return isl_aff_free(aff));
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ first += 1 + isl_local_space_offset(aff->ls, type);
+ aff->v = isl_vec_insert_zero_els(aff->v, first, n);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ return aff;
+}
+
+__isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned n)
+{
+ unsigned pos;
+
+ pos = isl_aff_dim(aff, type);
+
+ return isl_aff_insert_dims(aff, type, pos, n);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
+ enum isl_dim_type type, unsigned n)
+{
+ unsigned pos;
+
+ pos = isl_pw_aff_dim(pwaff, type);
+
+ return isl_pw_aff_insert_dims(pwaff, type, pos, n);
+}
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
+ * to dimensions of "dst_type" at "dst_pos".
+ *
+ * We only support moving input dimensions to parameters and vice versa.
+ */
+__isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ unsigned g_dst_pos;
+ unsigned g_src_pos;
+
+ if (!aff)
+ return NULL;
+ if (n == 0 &&
+ !isl_local_space_is_named_or_nested(aff->ls, src_type) &&
+ !isl_local_space_is_named_or_nested(aff->ls, dst_type))
+ return aff;
+
+ if (dst_type == isl_dim_out || src_type == isl_dim_out)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot move output/set dimension", isl_aff_free(aff));
+ if (dst_type == isl_dim_div || src_type == isl_dim_div)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot move divs", isl_aff_free(aff));
+ if (dst_type == isl_dim_in)
+ dst_type = isl_dim_set;
+ if (src_type == isl_dim_in)
+ src_type = isl_dim_set;
+
+ if (src_pos + n > isl_local_space_dim(aff->ls, src_type))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "range out of bounds", isl_aff_free(aff));
+ if (dst_type == src_type)
+ isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
+ "moving dims within the same type not supported",
+ isl_aff_free(aff));
+
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ g_src_pos = 1 + isl_local_space_offset(aff->ls, src_type) + src_pos;
+ g_dst_pos = 1 + isl_local_space_offset(aff->ls, dst_type) + dst_pos;
+ if (dst_type > src_type)
+ g_dst_pos -= n;
+
+ aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n);
+ aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!aff->v || !aff->ls)
+ return isl_aff_free(aff);
+
+ aff = sort_divs(aff);
+
+ return aff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
+{
+ isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
+ return isl_pw_aff_alloc(dom, aff);
+}
+
+#undef PW
+#define PW isl_pw_aff
+#undef EL
+#define EL isl_aff
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_empty
+#undef ZERO
+#define ZERO empty
+#undef IS_ZERO
+#define IS_ZERO is_empty
+#undef FIELD
+#define FIELD aff
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 0
+
+#define NO_EVAL
+#define NO_OPT
+#define NO_LIFT
+#define NO_MORPH
+
+#include <isl_pw_templ.c>
+
+static __isl_give isl_set *align_params_pw_pw_set_and(
+ __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
+ __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2))
+{
+ if (!pwaff1 || !pwaff2)
+ goto error;
+ if (isl_space_match(pwaff1->dim, isl_dim_param,
+ pwaff2->dim, isl_dim_param))
+ return fn(pwaff1, pwaff2);
+ if (!isl_space_has_named_params(pwaff1->dim) ||
+ !isl_space_has_named_params(pwaff2->dim))
+ isl_die(isl_pw_aff_get_ctx(pwaff1), isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_space(pwaff2));
+ pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_space(pwaff1));
+ return fn(pwaff1, pwaff2);
+error:
+ isl_pw_aff_free(pwaff1);
+ isl_pw_aff_free(pwaff2);
+ return NULL;
+}
+
+/* Compute a piecewise quasi-affine expression with a domain that
+ * is the union of those of pwaff1 and pwaff2 and such that on each
+ * cell, the quasi-affine expression is the better (according to cmp)
+ * of those of pwaff1 and pwaff2. If only one of pwaff1 or pwaff2
+ * is defined on a given cell, then the associated expression
+ * is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2,
+ __isl_give isl_basic_set *(*cmp)(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2))
+{
+ int i, j, n;
+ isl_pw_aff *res;
+ isl_ctx *ctx;
+ isl_set *set;
+
+ if (!pwaff1 || !pwaff2)
+ goto error;
+
+ ctx = isl_space_get_ctx(pwaff1->dim);
+ if (!isl_space_is_equal(pwaff1->dim, pwaff2->dim))
+ isl_die(ctx, isl_error_invalid,
+ "arguments should live in same space", goto error);
+
+ if (isl_pw_aff_is_empty(pwaff1)) {
+ isl_pw_aff_free(pwaff1);
+ return pwaff2;
+ }
+
+ if (isl_pw_aff_is_empty(pwaff2)) {
+ isl_pw_aff_free(pwaff2);
+ return pwaff1;
+ }
+
+ n = 2 * (pwaff1->n + 1) * (pwaff2->n + 1);
+ res = isl_pw_aff_alloc_size(isl_space_copy(pwaff1->dim), n);
+
+ for (i = 0; i < pwaff1->n; ++i) {
+ set = isl_set_copy(pwaff1->p[i].set);
+ for (j = 0; j < pwaff2->n; ++j) {
+ struct isl_set *common;
+ isl_set *better;
+
+ common = isl_set_intersect(
+ isl_set_copy(pwaff1->p[i].set),
+ isl_set_copy(pwaff2->p[j].set));
+ better = isl_set_from_basic_set(cmp(
+ isl_aff_copy(pwaff2->p[j].aff),
+ isl_aff_copy(pwaff1->p[i].aff)));
+ better = isl_set_intersect(common, better);
+ if (isl_set_plain_is_empty(better)) {
+ isl_set_free(better);
+ continue;
+ }
+ set = isl_set_subtract(set, isl_set_copy(better));
+
+ res = isl_pw_aff_add_piece(res, better,
+ isl_aff_copy(pwaff2->p[j].aff));
+ }
+ res = isl_pw_aff_add_piece(res, set,
+ isl_aff_copy(pwaff1->p[i].aff));
+ }
+
+ for (j = 0; j < pwaff2->n; ++j) {
+ set = isl_set_copy(pwaff2->p[j].set);
+ for (i = 0; i < pwaff1->n; ++i)
+ set = isl_set_subtract(set,
+ isl_set_copy(pwaff1->p[i].set));
+ res = isl_pw_aff_add_piece(res, set,
+ isl_aff_copy(pwaff2->p[j].aff));
+ }
+
+ isl_pw_aff_free(pwaff1);
+ isl_pw_aff_free(pwaff2);
+
+ return res;
+error:
+ isl_pw_aff_free(pwaff1);
+ isl_pw_aff_free(pwaff2);
+ return NULL;
+}
+
+/* Compute a piecewise quasi-affine expression with a domain that
+ * is the union of those of pwaff1 and pwaff2 and such that on each
+ * cell, the quasi-affine expression is the maximum of those of pwaff1
+ * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
+ * cell, then the associated expression is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_ge_basic_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
+ &pw_aff_union_max);
+}
+
+/* Compute a piecewise quasi-affine expression with a domain that
+ * is the union of those of pwaff1 and pwaff2 and such that on each
+ * cell, the quasi-affine expression is the minimum of those of pwaff1
+ * and pwaff2. If only one of pwaff1 or pwaff2 is defined on a given
+ * cell, then the associated expression is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_le_basic_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
+ &pw_aff_union_min);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2, int max)
+{
+ if (max)
+ return isl_pw_aff_union_max(pwaff1, pwaff2);
+ else
+ return isl_pw_aff_union_min(pwaff1, pwaff2);
+}
+
+/* Construct a map with as domain the domain of pwaff and
+ * one-dimensional range corresponding to the affine expressions.
+ */
+static __isl_give isl_map *map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+ int i;
+ isl_space *dim;
+ isl_map *map;
+
+ if (!pwaff)
+ return NULL;
+
+ dim = isl_pw_aff_get_space(pwaff);
+ map = isl_map_empty(dim);
+
+ for (i = 0; i < pwaff->n; ++i) {
+ isl_basic_map *bmap;
+ isl_map *map_i;
+
+ bmap = isl_basic_map_from_aff(isl_aff_copy(pwaff->p[i].aff));
+ map_i = isl_map_from_basic_map(bmap);
+ map_i = isl_map_intersect_domain(map_i,
+ isl_set_copy(pwaff->p[i].set));
+ map = isl_map_union_disjoint(map, map_i);
+ }
+
+ isl_pw_aff_free(pwaff);
+
+ return map;
+}
+
+/* Construct a map with as domain the domain of pwaff and
+ * one-dimensional range corresponding to the affine expressions.
+ */
+__isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+ if (!pwaff)
+ return NULL;
+ if (isl_space_is_set(pwaff->dim))
+ isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+ "space of input is not a map", goto error);
+ return map_from_pw_aff(pwaff);
+error:
+ isl_pw_aff_free(pwaff);
+ return NULL;
+}
+
+/* Construct a one-dimensional set with as parameter domain
+ * the domain of pwaff and the single set dimension
+ * corresponding to the affine expressions.
+ */
+__isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+ if (!pwaff)
+ return NULL;
+ if (!isl_space_is_set(pwaff->dim))
+ isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+ "space of input is not a set", goto error);
+ return map_from_pw_aff(pwaff);
+error:
+ isl_pw_aff_free(pwaff);
+ return NULL;
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is non-negative.
+ */
+__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
+{
+ int i;
+ isl_set *set;
+
+ if (!pwaff)
+ return NULL;
+
+ set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
+
+ for (i = 0; i < pwaff->n; ++i) {
+ isl_basic_set *bset;
+ isl_set *set_i;
+ int rational;
+
+ rational = isl_set_has_rational(pwaff->p[i].set);
+ bset = aff_nonneg_basic_set(isl_aff_copy(pwaff->p[i].aff),
+ rational);
+ set_i = isl_set_from_basic_set(bset);
+ set_i = isl_set_intersect(set_i, isl_set_copy(pwaff->p[i].set));
+ set = isl_set_union_disjoint(set, set_i);
+ }
+
+ isl_pw_aff_free(pwaff);
+
+ return set;
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is zero (if complement is 0) or not zero
+ * (if complement is 1).
+ *
+ * The pieces with a NaN never belong to the result since
+ * NaN is neither zero nor non-zero.
+ */
+static __isl_give isl_set *pw_aff_zero_set(__isl_take isl_pw_aff *pwaff,
+ int complement)
+{
+ int i;
+ isl_set *set;
+
+ if (!pwaff)
+ return NULL;
+
+ set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
+
+ for (i = 0; i < pwaff->n; ++i) {
+ isl_basic_set *bset;
+ isl_set *set_i, *zero;
+ int rational;
+
+ if (isl_aff_is_nan(pwaff->p[i].aff))
+ continue;
+
+ rational = isl_set_has_rational(pwaff->p[i].set);
+ bset = aff_zero_basic_set(isl_aff_copy(pwaff->p[i].aff),
+ rational);
+ zero = isl_set_from_basic_set(bset);
+ set_i = isl_set_copy(pwaff->p[i].set);
+ if (complement)
+ set_i = isl_set_subtract(set_i, zero);
+ else
+ set_i = isl_set_intersect(set_i, zero);
+ set = isl_set_union_disjoint(set, set_i);
+ }
+
+ isl_pw_aff_free(pwaff);
+
+ return set;
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is zero.
+ */
+__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
+{
+ return pw_aff_zero_set(pwaff, 0);
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is not zero.
+ */
+__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
+{
+ return pw_aff_zero_set(pwaff, 1);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2.
+ *
+ * We compute the difference on the shared domain and then construct
+ * the set of values where this difference is non-negative.
+ * If strict is set, we first subtract 1 from the difference.
+ * If equal is set, we only return the elements where pwaff1 and pwaff2
+ * are equal.
+ */
+static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2, int strict, int equal)
+{
+ isl_set *set1, *set2;
+
+ set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1));
+ set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2));
+ set1 = isl_set_intersect(set1, set2);
+ pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1));
+ pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1));
+ pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
+
+ if (strict) {
+ isl_space *dim = isl_set_get_space(set1);
+ isl_aff *aff;
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
+ aff = isl_aff_add_constant_si(aff, -1);
+ pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
+ } else
+ isl_set_free(set1);
+
+ if (equal)
+ return isl_pw_aff_zero_set(pwaff1);
+ return isl_pw_aff_nonneg_set(pwaff1);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
+}
+
+__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
+}
+
+__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
+ */
+static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
+}
+
+__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
+}
+
+__isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_ge_set(pwaff2, pwaff1);
+}
+
+__isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_gt_set(pwaff2, pwaff1);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of the elements of list1 and list2 where each element in list1
+ * has the relation specified by "fn" with each element in list2.
+ */
+static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2,
+ __isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2))
+{
+ int i, j;
+ isl_ctx *ctx;
+ isl_set *set;
+
+ if (!list1 || !list2)
+ goto error;
+
+ ctx = isl_pw_aff_list_get_ctx(list1);
+ if (list1->n < 1 || list2->n < 1)
+ isl_die(ctx, isl_error_invalid,
+ "list should contain at least one element", goto error);
+
+ set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0]));
+ for (i = 0; i < list1->n; ++i)
+ for (j = 0; j < list2->n; ++j) {
+ isl_set *set_ij;
+
+ set_ij = fn(isl_pw_aff_copy(list1->p[i]),
+ isl_pw_aff_copy(list2->p[j]));
+ set = isl_set_intersect(set, set_ij);
+ }
+
+ isl_pw_aff_list_free(list1);
+ isl_pw_aff_list_free(list2);
+ return set;
+error:
+ isl_pw_aff_list_free(list1);
+ isl_pw_aff_list_free(list2);
+ return NULL;
+}
+
+/* Return a set containing those elements in the shared domain
+ * of the elements of list1 and list2 where each element in list1
+ * is equal to each element in list2.
+ */
+__isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of the elements of list1 and list2 where each element in list1
+ * is less than or equal to each element in list2.
+ */
+__isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
+ __isl_take isl_pw_aff_list *list2)
+{
+ return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set);
+}
+
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ isl_set *set_lt, *set_gt;
+
+ set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1),
+ isl_pw_aff_copy(pwaff2));
+ set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2);
+ return isl_set_union_disjoint(set_lt, set_gt);
+}
+
+__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+ isl_int v)
+{
+ int i;
+
+ if (isl_int_is_one(v))
+ return pwaff;
+ if (!isl_int_is_pos(v))
+ isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+ "factor needs to be positive",
+ return isl_pw_aff_free(pwaff));
+ pwaff = isl_pw_aff_cow(pwaff);
+ if (!pwaff)
+ return NULL;
+ if (pwaff->n == 0)
+ return pwaff;
+
+ for (i = 0; i < pwaff->n; ++i) {
+ pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v);
+ if (!pwaff->p[i].aff)
+ return isl_pw_aff_free(pwaff);
+ }
+
+ return pwaff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
+{
+ int i;
+
+ pwaff = isl_pw_aff_cow(pwaff);
+ if (!pwaff)
+ return NULL;
+ if (pwaff->n == 0)
+ return pwaff;
+
+ for (i = 0; i < pwaff->n; ++i) {
+ pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff);
+ if (!pwaff->p[i].aff)
+ return isl_pw_aff_free(pwaff);
+ }
+
+ return pwaff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff)
+{
+ int i;
+
+ pwaff = isl_pw_aff_cow(pwaff);
+ if (!pwaff)
+ return NULL;
+ if (pwaff->n == 0)
+ return pwaff;
+
+ for (i = 0; i < pwaff->n; ++i) {
+ pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff);
+ if (!pwaff->p[i].aff)
+ return isl_pw_aff_free(pwaff);
+ }
+
+ return pwaff;
+}
+
+/* Assuming that "cond1" and "cond2" are disjoint,
+ * return an affine expression that is equal to pwaff1 on cond1
+ * and to pwaff2 on cond2.
+ */
+static __isl_give isl_pw_aff *isl_pw_aff_select(
+ __isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2)
+{
+ pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1);
+ pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2);
+
+ return isl_pw_aff_add_disjoint(pwaff1, pwaff2);
+}
+
+/* Return an affine expression that is equal to pwaff_true for elements
+ * where "cond" is non-zero and to pwaff_false for elements where "cond"
+ * is zero.
+ * That is, return cond ? pwaff_true : pwaff_false;
+ *
+ * If "cond" involves and NaN, then we conservatively return a NaN
+ * on its entire domain. In principle, we could consider the pieces
+ * where it is NaN separately from those where it is not.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
+ __isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false)
+{
+ isl_set *cond_true, *cond_false;
+
+ if (!cond)
+ goto error;
+ if (isl_pw_aff_involves_nan(cond)) {
+ isl_space *space = isl_pw_aff_get_domain_space(cond);
+ isl_local_space *ls = isl_local_space_from_space(space);
+ isl_pw_aff_free(cond);
+ isl_pw_aff_free(pwaff_true);
+ isl_pw_aff_free(pwaff_false);
+ return isl_pw_aff_nan_on_domain(ls);
+ }
+
+ cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond));
+ cond_false = isl_pw_aff_zero_set(cond);
+ return isl_pw_aff_select(cond_true, pwaff_true,
+ cond_false, pwaff_false);
+error:
+ isl_pw_aff_free(cond);
+ isl_pw_aff_free(pwaff_true);
+ isl_pw_aff_free(pwaff_false);
+ return NULL;
+}
+
+int isl_aff_is_cst(__isl_keep isl_aff *aff)
+{
+ if (!aff)
+ return -1;
+
+ return isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2) == -1;
+}
+
+/* Check whether pwaff is a piecewise constant.
+ */
+int isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
+{
+ int i;
+
+ if (!pwaff)
+ return -1;
+
+ for (i = 0; i < pwaff->n; ++i) {
+ int is_cst = isl_aff_is_cst(pwaff->p[i].aff);
+ if (is_cst < 0 || !is_cst)
+ return is_cst;
+ }
+
+ return 1;
+}
+
+/* Return the product of "aff1" and "aff2".
+ *
+ * If either of the two is NaN, then the result is NaN.
+ *
+ * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
+ */
+__isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ if (!aff1 || !aff2)
+ goto error;
+
+ if (isl_aff_is_nan(aff1)) {
+ isl_aff_free(aff2);
+ return aff1;
+ }
+ if (isl_aff_is_nan(aff2)) {
+ isl_aff_free(aff1);
+ return aff2;
+ }
+
+ if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1))
+ return isl_aff_mul(aff2, aff1);
+
+ if (!isl_aff_is_cst(aff2))
+ isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,
+ "at least one affine expression should be constant",
+ goto error);
+
+ aff1 = isl_aff_cow(aff1);
+ if (!aff1 || !aff2)
+ goto error;
+
+ aff1 = isl_aff_scale(aff1, aff2->v->el[1]);
+ aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]);
+
+ isl_aff_free(aff2);
+ return aff1;
+error:
+ isl_aff_free(aff1);
+ isl_aff_free(aff2);
+ return NULL;
+}
+
+/* Divide "aff1" by "aff2", assuming "aff2" is a constant.
+ *
+ * If either of the two is NaN, then the result is NaN.
+ */
+__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ int is_cst;
+ int neg;
+
+ if (!aff1 || !aff2)
+ goto error;
+
+ if (isl_aff_is_nan(aff1)) {
+ isl_aff_free(aff2);
+ return aff1;
+ }
+ if (isl_aff_is_nan(aff2)) {
+ isl_aff_free(aff1);
+ return aff2;
+ }
+
+ is_cst = isl_aff_is_cst(aff2);
+ if (is_cst < 0)
+ goto error;
+ if (!is_cst)
+ isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
+ "second argument should be a constant", goto error);
+
+ if (!aff2)
+ goto error;
+
+ neg = isl_int_is_neg(aff2->v->el[1]);
+ if (neg) {
+ isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+ isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+ }
+
+ aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
+ aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
+
+ if (neg) {
+ isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+ isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+ }
+
+ isl_aff_free(aff2);
+ return aff1;
+error:
+ isl_aff_free(aff1);
+ isl_aff_free(aff2);
+ return NULL;
+}
+
+static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_add);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_union_add_(pwaff1, pwaff2);
+}
+
+static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
+}
+
+static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
+}
+
+/* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ int is_cst;
+
+ is_cst = isl_pw_aff_is_cst(pa2);
+ if (is_cst < 0)
+ goto error;
+ if (!is_cst)
+ isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+ "second argument should be a piecewise constant",
+ goto error);
+ return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
+error:
+ isl_pw_aff_free(pa1);
+ isl_pw_aff_free(pa2);
+ return NULL;
+}
+
+/* Compute the quotient of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ * pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ int is_cst;
+ isl_set *cond;
+ isl_pw_aff *f, *c;
+
+ is_cst = isl_pw_aff_is_cst(pa2);
+ if (is_cst < 0)
+ goto error;
+ if (!is_cst)
+ isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+ "second argument should be a piecewise constant",
+ goto error);
+
+ pa1 = isl_pw_aff_div(pa1, pa2);
+
+ cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
+ f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
+ c = isl_pw_aff_ceil(pa1);
+ return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
+error:
+ isl_pw_aff_free(pa1);
+ isl_pw_aff_free(pa2);
+ return NULL;
+}
+
+/* Compute the remainder of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ * pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ int is_cst;
+ isl_pw_aff *res;
+
+ is_cst = isl_pw_aff_is_cst(pa2);
+ if (is_cst < 0)
+ goto error;
+ if (!is_cst)
+ isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+ "second argument should be a piecewise constant",
+ goto error);
+ res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
+ res = isl_pw_aff_mul(pa2, res);
+ res = isl_pw_aff_sub(pa1, res);
+ return res;
+error:
+ isl_pw_aff_free(pa1);
+ isl_pw_aff_free(pa2);
+ return NULL;
+}
+
+static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ isl_set *le;
+ isl_set *dom;
+
+ dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
+ isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
+ le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1),
+ isl_pw_aff_copy(pwaff2));
+ dom = isl_set_subtract(dom, isl_set_copy(le));
+ return isl_pw_aff_select(le, pwaff1, dom, pwaff2);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_min);
+}
+
+static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ isl_set *ge;
+ isl_set *dom;
+
+ dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
+ isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
+ ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1),
+ isl_pw_aff_copy(pwaff2));
+ dom = isl_set_subtract(dom, isl_set_copy(ge));
+ return isl_pw_aff_select(ge, pwaff1, dom, pwaff2);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2)
+{
+ return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_max);
+}
+
+static __isl_give isl_pw_aff *pw_aff_list_reduce(
+ __isl_take isl_pw_aff_list *list,
+ __isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2))
+{
+ int i;
+ isl_ctx *ctx;
+ isl_pw_aff *res;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_pw_aff_list_get_ctx(list);
+ if (list->n < 1)
+ isl_die(ctx, isl_error_invalid,
+ "list should contain at least one element", goto error);
+
+ res = isl_pw_aff_copy(list->p[0]);
+ for (i = 1; i < list->n; ++i)
+ res = fn(res, isl_pw_aff_copy(list->p[i]));
+
+ isl_pw_aff_list_free(list);
+ return res;
+error:
+ isl_pw_aff_list_free(list);
+ return NULL;
+}
+
+/* Return an isl_pw_aff that maps each element in the intersection of the
+ * domains of the elements of list to the minimal corresponding affine
+ * expression.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list)
+{
+ return pw_aff_list_reduce(list, &isl_pw_aff_min);
+}
+
+/* Return an isl_pw_aff that maps each element in the intersection of the
+ * domains of the elements of list to the maximal corresponding affine
+ * expression.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list)
+{
+ return pw_aff_list_reduce(list, &isl_pw_aff_max);
+}
+
+/* Mark the domains of "pwaff" as rational.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff)
+{
+ int i;
+
+ pwaff = isl_pw_aff_cow(pwaff);
+ if (!pwaff)
+ return NULL;
+ if (pwaff->n == 0)
+ return pwaff;
+
+ for (i = 0; i < pwaff->n; ++i) {
+ pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set);
+ if (!pwaff->p[i].set)
+ return isl_pw_aff_free(pwaff);
+ }
+
+ return pwaff;
+}
+
+/* Mark the domains of the elements of "list" as rational.
+ */
+__isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
+ __isl_take isl_pw_aff_list *list)
+{
+ int i, n;
+
+ if (!list)
+ return NULL;
+ if (list->n == 0)
+ return list;
+
+ n = list->n;
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+
+ pa = isl_pw_aff_list_get_pw_aff(list, i);
+ pa = isl_pw_aff_set_rational(pa);
+ list = isl_pw_aff_list_set_pw_aff(list, i, pa);
+ }
+
+ return list;
+}
+
+/* Do the parameters of "aff" match those of "space"?
+ */
+int isl_aff_matching_params(__isl_keep isl_aff *aff,
+ __isl_keep isl_space *space)
+{
+ isl_space *aff_space;
+ int match;
+
+ if (!aff || !space)
+ return -1;
+
+ aff_space = isl_aff_get_domain_space(aff);
+
+ match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+
+ isl_space_free(aff_space);
+ return match;
+}
+
+/* Check that the domain space of "aff" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+ __isl_keep isl_space *space)
+{
+ isl_space *aff_space;
+ int match;
+
+ if (!aff || !space)
+ return -1;
+
+ aff_space = isl_aff_get_domain_space(aff);
+
+ match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "parameters don't match", goto error);
+ match = isl_space_tuple_is_equal(space, isl_dim_in,
+ aff_space, isl_dim_set);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "domains don't match", goto error);
+ isl_space_free(aff_space);
+ return 0;
+error:
+ isl_space_free(aff_space);
+ return -1;
+}
+
+#undef BASE
+#define BASE aff
+#define NO_INTERSECT_DOMAIN
+#define NO_DOMAIN
+
+#include <isl_multi_templ.c>
+
+#undef NO_DOMAIN
+#undef NO_INTERSECT_DOMAIN
+
+/* Remove any internal structure of the domain of "ma".
+ * If there is any such internal structure in the input,
+ * then the name of the corresponding space is also removed.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
+ __isl_take isl_multi_aff *ma)
+{
+ isl_space *space;
+
+ if (!ma)
+ return NULL;
+
+ if (!ma->space->nested[0])
+ return ma;
+
+ space = isl_multi_aff_get_space(ma);
+ space = isl_space_flatten_domain(space);
+ ma = isl_multi_aff_reset_space(ma, space);
+
+ return ma;
+}
+
+/* Given a map space, return an isl_multi_aff that maps a wrapped copy
+ * of the space to its domain.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
+{
+ int i, n_in;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+
+ if (!space)
+ return NULL;
+ if (!isl_space_is_map(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "not a map space", goto error);
+
+ n_in = isl_space_dim(space, isl_dim_in);
+ space = isl_space_domain_map(space);
+
+ ma = isl_multi_aff_alloc(isl_space_copy(space));
+ if (n_in == 0) {
+ isl_space_free(space);
+ return ma;
+ }
+
+ space = isl_space_domain(space);
+ ls = isl_local_space_from_space(space);
+ for (i = 0; i < n_in; ++i) {
+ isl_aff *aff;
+
+ aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ isl_dim_set, i);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+ isl_local_space_free(ls);
+ return ma;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Given a map space, return an isl_multi_aff that maps a wrapped copy
+ * of the space to its range.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
+{
+ int i, n_in, n_out;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+
+ if (!space)
+ return NULL;
+ if (!isl_space_is_map(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "not a map space", goto error);
+
+ n_in = isl_space_dim(space, isl_dim_in);
+ n_out = isl_space_dim(space, isl_dim_out);
+ space = isl_space_range_map(space);
+
+ ma = isl_multi_aff_alloc(isl_space_copy(space));
+ if (n_out == 0) {
+ isl_space_free(space);
+ return ma;
+ }
+
+ space = isl_space_domain(space);
+ ls = isl_local_space_from_space(space);
+ for (i = 0; i < n_out; ++i) {
+ isl_aff *aff;
+
+ aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ isl_dim_set, n_in + i);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+ isl_local_space_free(ls);
+ return ma;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Given the space of a set and a range of set dimensions,
+ * construct an isl_multi_aff that projects out those dimensions.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_project_out_map(
+ __isl_take isl_space *space, enum isl_dim_type type,
+ unsigned first, unsigned n)
+{
+ int i, dim;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+
+ if (!space)
+ return NULL;
+ if (!isl_space_is_set(space))
+ isl_die(isl_space_get_ctx(space), isl_error_unsupported,
+ "expecting set space", goto error);
+ if (type != isl_dim_set)
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "only set dimensions can be projected out", goto error);
+
+ dim = isl_space_dim(space, isl_dim_set);
+ if (first + n > dim)
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "range out of bounds", goto error);
+
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, dim - n);
+
+ if (dim == n)
+ return isl_multi_aff_alloc(space);
+
+ ma = isl_multi_aff_alloc(isl_space_copy(space));
+ space = isl_space_domain(space);
+ ls = isl_local_space_from_space(space);
+
+ for (i = 0; i < first; ++i) {
+ isl_aff *aff;
+
+ aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ isl_dim_set, i);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ for (i = 0; i < dim - (first + n); ++i) {
+ isl_aff *aff;
+
+ aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ isl_dim_set, first + n + i);
+ ma = isl_multi_aff_set_aff(ma, first + i, aff);
+ }
+
+ isl_local_space_free(ls);
+ return ma;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Given the space of a set and a range of set dimensions,
+ * construct an isl_pw_multi_aff that projects out those dimensions.
+ */
+__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_multi_aff *ma;
+
+ ma = isl_multi_aff_project_out_map(space, type, first, n);
+ return isl_pw_multi_aff_from_multi_aff(ma);
+}
+
+/* Create an isl_pw_multi_aff with the given isl_multi_aff on a universe
+ * domain.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma)
+{
+ isl_set *dom = isl_set_universe(isl_multi_aff_get_domain_space(ma));
+ return isl_pw_multi_aff_alloc(dom, ma);
+}
+
+/* Create a piecewise multi-affine expression in the given space that maps each
+ * input dimension to the corresponding output dimension.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
+ __isl_take isl_space *space)
+{
+ 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);
+}
+
+/* Subtract "ma2" from "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_sub_aligned(
+ __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
+{
+ return isl_multi_aff_bin_op(ma1, ma2, &isl_aff_sub);
+}
+
+/* Subtract "ma2" from "ma1" and return the result.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_sub(__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_sub_aligned);
+}
+
+/* Exploit the equalities in "eq" to simplify the affine expressions.
+ */
+static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
+ __isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq)
+{
+ int i;
+
+ maff = isl_multi_aff_cow(maff);
+ if (!maff || !eq)
+ goto error;
+
+ for (i = 0; i < maff->n; ++i) {
+ maff->p[i] = isl_aff_substitute_equalities(maff->p[i],
+ isl_basic_set_copy(eq));
+ if (!maff->p[i])
+ goto error;
+ }
+
+ isl_basic_set_free(eq);
+ return maff;
+error:
+ isl_basic_set_free(eq);
+ isl_multi_aff_free(maff);
+ return NULL;
+}
+
+/* Given f, return floor(f).
+ */
+__isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma)
+{
+ int i;
+
+ ma = isl_multi_aff_cow(ma);
+ if (!ma)
+ return NULL;
+
+ for (i = 0; i < ma->n; ++i) {
+ ma->p[i] = isl_aff_floor(ma->p[i]);
+ if (!ma->p[i])
+ return isl_multi_aff_free(ma);
+ }
+
+ return ma;
+}
+
+__isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
+ isl_int f)
+{
+ int i;
+
+ maff = isl_multi_aff_cow(maff);
+ if (!maff)
+ return NULL;
+
+ for (i = 0; i < maff->n; ++i) {
+ maff->p[i] = isl_aff_scale(maff->p[i], f);
+ if (!maff->p[i])
+ return isl_multi_aff_free(maff);
+ }
+
+ return maff;
+}
+
+__isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
+ __isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
+{
+ maff1 = isl_multi_aff_add(maff1, maff2);
+ maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom));
+ return maff1;
+}
+
+int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
+{
+ if (!maff)
+ return -1;
+
+ return 0;
+}
+
+/* Return the set of domain elements where "ma1" is lexicographically
+ * smaller than or equal to "ma2".
+ */
+__isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2)
+{
+ return isl_multi_aff_lex_ge_set(ma2, ma1);
+}
+
+/* Return the set of domain elements where "ma1" is lexicographically
+ * greater than or equal to "ma2".
+ */
+__isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2)
+{
+ isl_space *space;
+ isl_map *map1, *map2;
+ isl_map *map, *ge;
+
+ map1 = isl_map_from_multi_aff(ma1);
+ map2 = isl_map_from_multi_aff(ma2);
+ map = isl_map_range_product(map1, map2);
+ space = isl_space_range(isl_map_get_space(map));
+ space = isl_space_domain(isl_space_unwrap(space));
+ ge = isl_map_lex_ge(space);
+ map = isl_map_intersect_range(map, isl_map_wrap(ge));
+
+ return isl_map_domain(map);
+}
+
+#undef PW
+#define PW isl_pw_multi_aff
+#undef EL
+#define EL isl_multi_aff
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_empty
+#undef ZERO
+#define ZERO empty
+#undef IS_ZERO
+#define IS_ZERO is_empty
+#undef FIELD
+#define FIELD maff
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 0
+
+#define NO_NEG
+#define NO_EVAL
+#define NO_OPT
+#define NO_INVOLVES_DIMS
+#define NO_INSERT_DIMS
+#define NO_LIFT
+#define NO_MORPH
+
+#include <isl_pw_templ.c>
+
+#undef UNION
+#define UNION isl_union_pw_multi_aff
+#undef PART
+#define PART isl_pw_multi_aff
+#undef PARTS
+#define PARTS pw_multi_aff
+#define ALIGN_DOMAIN
+
+#define NO_EVAL
+
+#include <isl_union_templ.c>
+
+/* Given a function "cmp" that returns the set of elements where
+ * "ma1" is "better" than "ma2", return the intersection of this
+ * set with "dom1" and "dom2".
+ */
+static __isl_give isl_set *shared_and_better(__isl_keep isl_set *dom1,
+ __isl_keep isl_set *dom2, __isl_keep isl_multi_aff *ma1,
+ __isl_keep isl_multi_aff *ma2,
+ __isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2))
+{
+ isl_set *common;
+ isl_set *better;
+ int is_empty;
+
+ common = isl_set_intersect(isl_set_copy(dom1), isl_set_copy(dom2));
+ is_empty = isl_set_plain_is_empty(common);
+ if (is_empty >= 0 && is_empty)
+ return common;
+ if (is_empty < 0)
+ return isl_set_free(common);
+ better = cmp(isl_multi_aff_copy(ma1), isl_multi_aff_copy(ma2));
+ better = isl_set_intersect(common, better);
+
+ return better;
+}
+
+/* Given a function "cmp" that returns the set of elements where
+ * "ma1" is "better" than "ma2", return a piecewise multi affine
+ * expression defined on the union of the definition domains
+ * of "pma1" and "pma2" that maps to the "best" of "pma1" and
+ * "pma2" on each cell. If only one of the two input functions
+ * is defined on a given cell, then it is considered the best.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_opt(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2,
+ __isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
+ __isl_take isl_multi_aff *ma2))
+{
+ int i, j, n;
+ isl_pw_multi_aff *res = NULL;
+ isl_ctx *ctx;
+ isl_set *set = NULL;
+
+ if (!pma1 || !pma2)
+ goto error;
+
+ ctx = isl_space_get_ctx(pma1->dim);
+ if (!isl_space_is_equal(pma1->dim, pma2->dim))
+ isl_die(ctx, isl_error_invalid,
+ "arguments should live in the same space", goto error);
+
+ if (isl_pw_multi_aff_is_empty(pma1)) {
+ isl_pw_multi_aff_free(pma1);
+ return pma2;
+ }
+
+ if (isl_pw_multi_aff_is_empty(pma2)) {
+ isl_pw_multi_aff_free(pma2);
+ return pma1;
+ }
+
+ n = 2 * (pma1->n + 1) * (pma2->n + 1);
+ res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma1->dim), n);
+
+ for (i = 0; i < pma1->n; ++i) {
+ set = isl_set_copy(pma1->p[i].set);
+ for (j = 0; j < pma2->n; ++j) {
+ isl_set *better;
+ int is_empty;
+
+ better = shared_and_better(pma2->p[j].set,
+ pma1->p[i].set, pma2->p[j].maff,
+ pma1->p[i].maff, cmp);
+ is_empty = isl_set_plain_is_empty(better);
+ if (is_empty < 0 || is_empty) {
+ isl_set_free(better);
+ if (is_empty < 0)
+ goto error;
+ continue;
+ }
+ set = isl_set_subtract(set, isl_set_copy(better));
+
+ res = isl_pw_multi_aff_add_piece(res, better,
+ isl_multi_aff_copy(pma2->p[j].maff));
+ }
+ res = isl_pw_multi_aff_add_piece(res, set,
+ isl_multi_aff_copy(pma1->p[i].maff));
+ }
+
+ for (j = 0; j < pma2->n; ++j) {
+ set = isl_set_copy(pma2->p[j].set);
+ for (i = 0; i < pma1->n; ++i)
+ set = isl_set_subtract(set,
+ isl_set_copy(pma1->p[i].set));
+ res = isl_pw_multi_aff_add_piece(res, set,
+ isl_multi_aff_copy(pma2->p[j].maff));
+ }
+
+ isl_pw_multi_aff_free(pma1);
+ isl_pw_multi_aff_free(pma2);
+
+ return res;
+error:
+ isl_pw_multi_aff_free(pma1);
+ isl_pw_multi_aff_free(pma2);
+ isl_set_free(set);
+ return isl_pw_multi_aff_free(res);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmax(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2)
+{
+ return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_ge_set);
+}
+
+/* Given two piecewise multi affine expressions, return a piecewise
+ * multi-affine expression defined on the union of the definition domains
+ * of the inputs that is equal to the lexicographic maximum of the two
+ * inputs on each cell. If only one of the two inputs is defined on
+ * a given cell, then it is considered to be the maximum.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_union_lexmax);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmin(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2)
+{
+ return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_le_set);
+}
+
+/* Given two piecewise multi affine expressions, return a piecewise
+ * multi-affine expression defined on the union of the definition domains
+ * of the inputs that is equal to the lexicographic minimum of the two
+ * inputs on each cell. If only one of the two inputs is defined on
+ * a given cell, then it is considered to be the minimum.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
+ __isl_take isl_pw_multi_aff *pma1,
+ __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_union_lexmin);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_add(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+ &isl_multi_aff_add);
+}
+
+__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)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_add);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+ &isl_multi_aff_sub);
+}
+
+/* Subtract "pma2" from "pma1" and return the result.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_sub);
+}
+
+__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)
+{
+ return isl_pw_multi_aff_union_add_(pma1, pma2);
+}
+
+/* Compute the sum of "upma1" and "upma2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ */
+__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)
+{
+ return isl_union_pw_multi_aff_union_add_(upma1, upma2);
+}
+
+/* Given two piecewise multi-affine expressions A -> B and C -> D,
+ * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ int i, j, n;
+ isl_space *space;
+ isl_pw_multi_aff *res;
+
+ if (!pma1 || !pma2)
+ goto error;
+
+ n = pma1->n * pma2->n;
+ space = isl_space_product(isl_space_copy(pma1->dim),
+ isl_space_copy(pma2->dim));
+ res = isl_pw_multi_aff_alloc_size(space, n);
+
+ for (i = 0; i < pma1->n; ++i) {
+ for (j = 0; j < pma2->n; ++j) {
+ isl_set *domain;
+ isl_multi_aff *ma;
+
+ domain = isl_set_product(isl_set_copy(pma1->p[i].set),
+ isl_set_copy(pma2->p[j].set));
+ ma = isl_multi_aff_product(
+ isl_multi_aff_copy(pma1->p[i].maff),
+ isl_multi_aff_copy(pma2->p[j].maff));
+ res = isl_pw_multi_aff_add_piece(res, domain, ma);
+ }
+ }
+
+ isl_pw_multi_aff_free(pma1);
+ isl_pw_multi_aff_free(pma2);
+ return res;
+error:
+ isl_pw_multi_aff_free(pma1);
+ isl_pw_multi_aff_free(pma2);
+ return NULL;
+}
+
+__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)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_product);
+}
+
+/* Construct a map mapping the domain of the piecewise multi-affine expression
+ * to its range, with each dimension in the range equated to the
+ * corresponding affine expression on its cell.
+ */
+__isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
+{
+ int i;
+ isl_map *map;
+
+ if (!pma)
+ return NULL;
+
+ map = isl_map_empty(isl_pw_multi_aff_get_space(pma));
+
+ for (i = 0; i < pma->n; ++i) {
+ isl_multi_aff *maff;
+ isl_basic_map *bmap;
+ isl_map *map_i;
+
+ maff = isl_multi_aff_copy(pma->p[i].maff);
+ bmap = isl_basic_map_from_multi_aff(maff);
+ map_i = isl_map_from_basic_map(bmap);
+ map_i = isl_map_intersect_domain(map_i,
+ isl_set_copy(pma->p[i].set));
+ map = isl_map_union_disjoint(map, map_i);
+ }
+
+ isl_pw_multi_aff_free(pma);
+ return map;
+}
+
+__isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
+{
+ if (!pma)
+ return NULL;
+
+ if (!isl_space_is_set(pma->dim))
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "isl_pw_multi_aff cannot be converted into an isl_set",
+ goto error);
+
+ return isl_map_from_pw_multi_aff(pma);
+error:
+ isl_pw_multi_aff_free(pma);
+ 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
+ * of the parameters and input dimensions.
+ * Note that this expression may involve integer divisions defined
+ * in terms of parameters and input 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)
+{
+ int eq;
+ unsigned offset;
+ unsigned n_div;
+ isl_local_space *ls;
+ 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);
+ 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);
+
+ 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
+ * in terms of the parameters and input dimensions using an equality,
+ * extract an isl_multi_aff that expresses the output dimensions in terms
+ * of the parameters and input dimensions.
+ */
+static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
+ __isl_take isl_basic_map *bmap)
+{
+ int i;
+ unsigned n_out;
+ isl_multi_aff *ma;
+
+ if (!bmap)
+ return NULL;
+
+ ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
+ 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);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ isl_basic_map_free(bmap);
+
+ return ma;
+}
+
+/* Given a basic set where each set dimension is defined
+ * in terms of the parameters using an equality,
+ * extract an isl_multi_aff that expresses the set dimensions in terms
+ * of the parameters.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
+ __isl_take isl_basic_set *bset)
+{
+ return extract_isl_multi_aff_from_basic_map(bset);
+}
+
+/* Create an isl_pw_multi_aff that is equivalent to
+ * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
+ * The given basic map is such that each output dimension is defined
+ * in terms of the parameters and input dimensions using an equality.
+ *
+ * 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.
+ */
+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;
+
+ ma = extract_isl_multi_aff_from_basic_map(bmap);
+ ma = isl_multi_aff_floor(ma);
+ return isl_pw_multi_aff_alloc(domain, ma);
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ * This obviously only works if the input "map" is single-valued.
+ * If so, we compute the lexicographic minimum of the image in the form
+ * of an isl_pw_multi_aff. Since the image is unique, it is equal
+ * to its lexicographic minimum.
+ * If the input is not single-valued, we produce an error.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base(
+ __isl_take isl_map *map)
+{
+ int i;
+ int sv;
+ isl_pw_multi_aff *pma;
+
+ sv = isl_map_is_single_valued(map);
+ if (sv < 0)
+ goto error;
+ if (!sv)
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "map is not single-valued", goto error);
+ map = isl_map_make_disjoint(map);
+ if (!map)
+ return NULL;
+
+ pma = isl_pw_multi_aff_empty(isl_map_get_space(map));
+
+ for (i = 0; i < map->n; ++i) {
+ isl_pw_multi_aff *pma_i;
+ isl_basic_map *bmap;
+ bmap = isl_basic_map_copy(map->p[i]);
+ pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap);
+ pma = isl_pw_multi_aff_add_disjoint(pma, pma_i);
+ }
+
+ isl_map_free(map);
+ return pma;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
+ * taking into account that the output dimension at position "d"
+ * can be represented as
+ *
+ * x = floor((e(...) + c1) / m)
+ *
+ * given that constraint "i" is of the form
+ *
+ * e(...) + c1 - m x >= 0
+ *
+ *
+ * Let "map" be of the form
+ *
+ * A -> B
+ *
+ * We construct a mapping
+ *
+ * A -> [A -> x = floor(...)]
+ *
+ * apply that to the map, obtaining
+ *
+ * [A -> x = floor(...)] -> B
+ *
+ * and equate dimension "d" to x.
+ * We then compute a isl_pw_multi_aff representation of the resulting map
+ * and plug in the mapping above.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
+ __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i)
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+ isl_aff *aff;
+ isl_vec *v;
+ isl_map *insert;
+ int offset;
+ int n;
+ int n_in;
+ isl_pw_multi_aff *pma;
+ int is_set;
+
+ is_set = isl_map_is_set(map);
+
+ offset = isl_basic_map_offset(hull, isl_dim_out);
+ ctx = isl_map_get_ctx(map);
+ space = isl_space_domain(isl_map_get_space(map));
+ n_in = isl_space_dim(space, isl_dim_set);
+ n = isl_space_dim(space, isl_dim_all);
+
+ v = isl_vec_alloc(ctx, 1 + 1 + n);
+ if (v) {
+ isl_int_neg(v->el[0], hull->ineq[i][offset + d]);
+ isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n);
+ }
+ isl_basic_map_free(hull);
+
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ aff = isl_aff_alloc_vec(ls, v);
+ aff = isl_aff_floor(aff);
+ if (is_set) {
+ isl_space_free(space);
+ ma = isl_multi_aff_from_aff(aff);
+ } else {
+ ma = isl_multi_aff_identity(isl_space_map_from_set(space));
+ ma = isl_multi_aff_range_product(ma,
+ isl_multi_aff_from_aff(aff));
+ }
+
+ insert = isl_map_from_multi_aff(isl_multi_aff_copy(ma));
+ map = isl_map_apply_domain(map, insert);
+ map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d);
+ pma = isl_pw_multi_aff_from_map(map);
+ pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
+
+ return pma;
+}
+
+/* Is constraint "c" of the form
+ *
+ * e(...) + c1 - m x >= 0
+ *
+ * or
+ *
+ * -e(...) + c2 + m x >= 0
+ *
+ * where m > 1 and e only depends on parameters and input dimemnsions?
+ *
+ * "offset" is the offset of the output dimensions
+ * "pos" is the position of output dimension x.
+ */
+static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
+{
+ if (isl_int_is_zero(c[offset + d]))
+ return 0;
+ if (isl_int_is_one(c[offset + d]))
+ return 0;
+ if (isl_int_is_negone(c[offset + d]))
+ return 0;
+ if (isl_seq_first_non_zero(c + offset, d) != -1)
+ return 0;
+ if (isl_seq_first_non_zero(c + offset + d + 1,
+ total - (offset + d + 1)) != -1)
+ return 0;
+ return 1;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ *
+ * As a special case, we first check if there is any pair of constraints,
+ * shared by all the basic maps in "map" that force a given dimension
+ * to be equal to the floor of some affine combination of the input dimensions.
+ *
+ * In particular, if we can find two constraints
+ *
+ * e(...) + c1 - m x >= 0 i.e., m x <= e(...) + c1
+ *
+ * and
+ *
+ * -e(...) + c2 + m x >= 0 i.e., m x >= e(...) - c2
+ *
+ * where m > 1 and e only depends on parameters and input dimemnsions,
+ * and such that
+ *
+ * c1 + c2 < m i.e., -c2 >= c1 - (m - 1)
+ *
+ * then we know that we can take
+ *
+ * x = floor((e(...) + c1) / m)
+ *
+ * without having to perform any computation.
+ *
+ * Note that we know that
+ *
+ * c1 + c2 >= 1
+ *
+ * If c1 + c2 were 0, then we would have detected an equality during
+ * simplification. If c1 + c2 were negative, then we would have detected
+ * a contradiction.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
+ __isl_take isl_map *map)
+{
+ int d, dim;
+ int i, j, n;
+ int offset, total;
+ isl_int sum;
+ isl_basic_map *hull;
+
+ hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
+ if (!hull)
+ goto error;
+
+ isl_int_init(sum);
+ dim = isl_map_dim(map, isl_dim_out);
+ offset = isl_basic_map_offset(hull, isl_dim_out);
+ total = 1 + isl_basic_map_total_dim(hull);
+ n = hull->n_ineq;
+ for (d = 0; d < dim; ++d) {
+ for (i = 0; i < n; ++i) {
+ if (!is_potential_div_constraint(hull->ineq[i],
+ offset, d, total))
+ continue;
+ for (j = i + 1; j < n; ++j) {
+ if (!isl_seq_is_neg(hull->ineq[i] + 1,
+ hull->ineq[j] + 1, total - 1))
+ continue;
+ isl_int_add(sum, hull->ineq[i][0],
+ hull->ineq[j][0]);
+ if (isl_int_abs_lt(sum,
+ hull->ineq[i][offset + d]))
+ break;
+
+ }
+ if (j >= n)
+ continue;
+ isl_int_clear(sum);
+ if (isl_int_is_pos(hull->ineq[j][offset + d]))
+ j = i;
+ return pw_multi_aff_from_map_div(map, hull, d, j);
+ }
+ }
+ isl_int_clear(sum);
+ isl_basic_map_free(hull);
+ return pw_multi_aff_from_map_base(map);
+error:
+ isl_map_free(map);
+ isl_basic_map_free(hull);
+ return NULL;
+}
+
+/* Given an affine expression
+ *
+ * [A -> B] -> f(A,B)
+ *
+ * construct an isl_multi_aff
+ *
+ * [A -> B] -> B'
+ *
+ * such that dimension "d" in B' is set to "aff" and the remaining
+ * dimensions are set equal to the corresponding dimensions in B.
+ * "n_in" is the dimension of the space A.
+ * "n_out" is the dimension of the space B.
+ *
+ * If "is_set" is set, then the affine expression is of the form
+ *
+ * [B] -> f(B)
+ *
+ * and we construct an isl_multi_aff
+ *
+ * B -> B'
+ */
+static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
+ unsigned n_in, unsigned n_out, int is_set)
+{
+ int i;
+ isl_multi_aff *ma;
+ isl_space *space, *space2;
+ isl_local_space *ls;
+
+ space = isl_aff_get_domain_space(aff);
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ space2 = isl_space_copy(space);
+ if (!is_set)
+ space2 = isl_space_range(isl_space_unwrap(space2));
+ space = isl_space_map_from_domain_and_range(space, space2);
+ ma = isl_multi_aff_alloc(space);
+ ma = isl_multi_aff_set_aff(ma, d, aff);
+
+ for (i = 0; i < n_out; ++i) {
+ if (i == d)
+ continue;
+ aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ isl_dim_set, n_in + i);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ isl_local_space_free(ls);
+
+ return ma;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
+ * taking into account that the dimension at position "d" can be written as
+ *
+ * x = m a + f(..) (1)
+ *
+ * where m is equal to "gcd".
+ * "i" is the index of the equality in "hull" that defines f(..).
+ * In particular, the equality is of the form
+ *
+ * f(..) - x + m g(existentials) = 0
+ *
+ * or
+ *
+ * -f(..) + x + m g(existentials) = 0
+ *
+ * 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".
+ *
+ * Specifically, given the input map
+ *
+ * A -> B
+ *
+ * We first wrap it into a set
+ *
+ * [A -> B]
+ *
+ * and define (1) on top of the corresponding space, resulting in "aff".
+ * We use this to create an isl_multi_aff that maps the output position "d"
+ * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
+ * We plug this into the wrapped map, unwrap the result and compute the
+ * corresponding isl_pw_multi_aff.
+ * The result is an expression
+ *
+ * A -> T(A)
+ *
+ * We adjust that to
+ *
+ * A -> [A -> T(A)]
+ *
+ * so that we can plug that into "aff", after extending the latter to
+ * a mapping
+ *
+ * [A -> B] -> B'
+ *
+ *
+ * If "map" is actually a set, then there is no "A" space, meaning
+ * that we do not need to perform any wrapping, and that the result
+ * of the recursive call is of the form
+ *
+ * [T]
+ *
+ * which is plugged into a mapping of the form
+ *
+ * B -> B'
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
+ __isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i,
+ isl_int gcd)
+{
+ isl_set *set;
+ isl_space *space;
+ isl_local_space *ls;
+ isl_aff *aff;
+ isl_multi_aff *ma;
+ isl_pw_multi_aff *pma, *id;
+ unsigned n_in;
+ unsigned o_out;
+ unsigned n_out;
+ int is_set;
+
+ is_set = isl_map_is_set(map);
+
+ n_in = isl_basic_map_dim(hull, isl_dim_in);
+ n_out = isl_basic_map_dim(hull, isl_dim_out);
+ o_out = isl_basic_map_offset(hull, isl_dim_out);
+
+ if (is_set)
+ set = map;
+ else
+ set = isl_map_wrap(map);
+ space = isl_space_map_from_set(isl_set_get_space(set));
+ ma = isl_multi_aff_identity(space);
+ ls = isl_local_space_from_space(isl_set_get_space(set));
+ aff = isl_aff_alloc(ls);
+ if (aff) {
+ isl_int_set_si(aff->v->el[0], 1);
+ if (isl_int_is_one(hull->eq[i][o_out + d]))
+ isl_seq_neg(aff->v->el + 1, hull->eq[i],
+ aff->v->size - 1);
+ else
+ isl_seq_cpy(aff->v->el + 1, hull->eq[i],
+ aff->v->size - 1);
+ isl_int_set(aff->v->el[1 + o_out + d], gcd);
+ }
+ ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff));
+ set = isl_set_preimage_multi_aff(set, ma);
+
+ ma = range_map(aff, d, n_in, n_out, is_set);
+
+ if (is_set)
+ map = set;
+ else
+ map = isl_set_unwrap(set);
+ pma = isl_pw_multi_aff_from_map(set);
+
+ if (!is_set) {
+ space = isl_pw_multi_aff_get_domain_space(pma);
+ space = isl_space_map_from_set(space);
+ id = isl_pw_multi_aff_identity(space);
+ pma = isl_pw_multi_aff_range_product(id, pma);
+ }
+ id = isl_pw_multi_aff_from_multi_aff(ma);
+ pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma);
+
+ isl_basic_map_free(hull);
+ return pma;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ *
+ * As a special case, we first check if all output dimensions are uniquely
+ * defined in terms of the parameters and input dimensions over the entire
+ * domain. If so, we extract the desired isl_pw_multi_aff directly
+ * from the affine hull of "map" and its domain.
+ *
+ * Otherwise, we check if any of the output dimensions is "strided".
+ * That is, we check if can be written as
+ *
+ * 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.
+ * 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
+ * special case.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
+{
+ int i, j;
+ int sv;
+ isl_basic_map *hull;
+ unsigned n_out;
+ unsigned o_out;
+ unsigned n_div;
+ unsigned o_div;
+ isl_int gcd;
+
+ if (!map)
+ return NULL;
+
+ hull = isl_map_affine_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);
+ if (sv < 0)
+ hull = isl_basic_map_free(hull);
+ if (!hull)
+ goto error;
+
+ n_div = isl_basic_map_dim(hull, isl_dim_div);
+ o_div = isl_basic_map_offset(hull, isl_dim_div);
+
+ if (n_div == 0) {
+ isl_basic_map_free(hull);
+ return pw_multi_aff_from_map_check_div(map);
+ }
+
+ isl_int_init(gcd);
+
+ n_out = isl_basic_map_dim(hull, isl_dim_out);
+ o_out = isl_basic_map_offset(hull, isl_dim_out);
+
+ for (i = 0; i < n_out; ++i) {
+ for (j = 0; j < hull->n_eq; ++j) {
+ isl_int *eq = hull->eq[j];
+ isl_pw_multi_aff *res;
+
+ if (!isl_int_is_one(eq[o_out + i]) &&
+ !isl_int_is_negone(eq[o_out + i]))
+ continue;
+ if (isl_seq_first_non_zero(eq + o_out, i) != -1)
+ continue;
+ if (isl_seq_first_non_zero(eq + o_out + i + 1,
+ n_out - (i + 1)) != -1)
+ continue;
+ isl_seq_gcd(eq + o_div, n_div, &gcd);
+ if (isl_int_is_zero(gcd))
+ continue;
+ if (isl_int_is_one(gcd))
+ continue;
+
+ res = pw_multi_aff_from_map_stride(map, hull,
+ i, j, gcd);
+ isl_int_clear(gcd);
+ return res;
+ }
+ }
+
+ isl_int_clear(gcd);
+ isl_basic_map_free(hull);
+ return pw_multi_aff_from_map_check_div(map);
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set)
+{
+ return isl_pw_multi_aff_from_map(set);
+}
+
+/* Convert "map" into an isl_pw_multi_aff (if possible) and
+ * add it to *user.
+ */
+static int pw_multi_aff_from_map(__isl_take isl_map *map, void *user)
+{
+ isl_union_pw_multi_aff **upma = user;
+ isl_pw_multi_aff *pma;
+
+ pma = isl_pw_multi_aff_from_map(map);
+ *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
+
+ return *upma ? 0 : -1;
+}
+
+/* Try and create an isl_union_pw_multi_aff that is equivalent
+ * to the given isl_union_map.
+ * The isl_union_map is required to be single-valued in each space.
+ * Otherwise, an error is produced.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
+ __isl_take isl_union_map *umap)
+{
+ isl_space *space;
+ isl_union_pw_multi_aff *upma;
+
+ space = isl_union_map_get_space(umap);
+ upma = isl_union_pw_multi_aff_empty(space);
+ if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0)
+ upma = isl_union_pw_multi_aff_free(upma);
+ isl_union_map_free(umap);
+
+ return upma;
+}
+
+/* Try and create an isl_union_pw_multi_aff that is equivalent
+ * to the given isl_union_set.
+ * The isl_union_set is required to be a singleton in each space.
+ * Otherwise, an error is produced.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_pw_multi_aff_from_union_map(uset);
+}
+
+/* Return the piecewise affine expression "set ? 1 : 0".
+ */
+__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set)
+{
+ isl_pw_aff *pa;
+ isl_space *space = isl_set_get_space(set);
+ isl_local_space *ls = isl_local_space_from_space(space);
+ isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls));
+ isl_aff *one = isl_aff_zero_on_domain(ls);
+
+ one = isl_aff_add_constant_si(one, 1);
+ pa = isl_pw_aff_alloc(isl_set_copy(set), one);
+ set = isl_set_complement(set);
+ pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero));
+
+ return pa;
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "aff".
+ *
+ * Let i be the dimension to replace and let "subs" be of the form
+ *
+ * f/d
+ *
+ * and "aff" of the form
+ *
+ * (a i + g)/m
+ *
+ * The result is
+ *
+ * (a f + d g')/(m d)
+ *
+ * where g' is the result of plugging in "subs" in each of the integer
+ * divisions in g.
+ */
+__isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
+{
+ isl_ctx *ctx;
+ isl_int v;
+
+ aff = isl_aff_cow(aff);
+ if (!aff || !subs)
+ return isl_aff_free(aff);
+
+ ctx = isl_aff_get_ctx(aff);
+ if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", return isl_aff_free(aff));
+ if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+ isl_die(ctx, isl_error_unsupported,
+ "cannot handle divs yet", return isl_aff_free(aff));
+
+ aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ aff->v = isl_vec_cow(aff->v);
+ if (!aff->v)
+ return isl_aff_free(aff);
+
+ pos += isl_local_space_offset(aff->ls, type);
+
+ isl_int_init(v);
+ isl_seq_substitute(aff->v->el, pos, subs->v->el,
+ aff->v->size, subs->v->size, v);
+ isl_int_clear(v);
+
+ return aff;
+}
+
+/* Plug in "subs" for dimension "type", "pos" in each of the affine
+ * expressions in "maff".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_substitute(
+ __isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos,
+ __isl_keep isl_aff *subs)
+{
+ int i;
+
+ maff = isl_multi_aff_cow(maff);
+ if (!maff || !subs)
+ return isl_multi_aff_free(maff);
+
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ for (i = 0; i < maff->n; ++i) {
+ maff->p[i] = isl_aff_substitute(maff->p[i], type, pos, subs);
+ if (!maff->p[i])
+ return isl_multi_aff_free(maff);
+ }
+
+ return maff;
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "pma".
+ *
+ * pma is of the form
+ *
+ * A_i(v) -> M_i(v)
+ *
+ * while subs is of the form
+ *
+ * v' = B_j(v) -> S_j
+ *
+ * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
+ * has a contribution in the result, in particular
+ *
+ * C_ij(S_j) -> M_i(S_j)
+ *
+ * Note that plugging in S_j in C_ij may also result in an empty set
+ * and this contribution should simply be discarded.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
+ __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
+ __isl_keep isl_pw_aff *subs)
+{
+ int i, j, n;
+ isl_pw_multi_aff *res;
+
+ if (!pma || !subs)
+ return isl_pw_multi_aff_free(pma);
+
+ n = pma->n * subs->n;
+ res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n);
+
+ for (i = 0; i < pma->n; ++i) {
+ for (j = 0; j < subs->n; ++j) {
+ isl_set *common;
+ isl_multi_aff *res_ij;
+ int empty;
+
+ common = isl_set_intersect(
+ isl_set_copy(pma->p[i].set),
+ isl_set_copy(subs->p[j].set));
+ common = isl_set_substitute(common,
+ type, pos, subs->p[j].aff);
+ empty = isl_set_plain_is_empty(common);
+ if (empty < 0 || empty) {
+ isl_set_free(common);
+ if (empty < 0)
+ goto error;
+ continue;
+ }
+
+ res_ij = isl_multi_aff_substitute(
+ isl_multi_aff_copy(pma->p[i].maff),
+ type, pos, subs->p[j].aff);
+
+ res = isl_pw_multi_aff_add_piece(res, common, res_ij);
+ }
+ }
+
+ isl_pw_multi_aff_free(pma);
+ return res;
+error:
+ isl_pw_multi_aff_free(pma);
+ isl_pw_multi_aff_free(res);
+ return NULL;
+}
+
+/* Compute the preimage of a range of dimensions in the affine expression "src"
+ * under "ma" and put the result in "dst". The number of dimensions in "src"
+ * that precede the range is given by "n_before". The number of dimensions
+ * in the range is given by the number of output dimensions of "ma".
+ * The number of dimensions that follow the range is given by "n_after".
+ * If "has_denom" is set (to one),
+ * then "src" and "dst" have an extra initial denominator.
+ * "n_div_ma" is the number of existentials in "ma"
+ * "n_div_bset" is the number of existentials in "src"
+ * The resulting "dst" (which is assumed to have been allocated by
+ * the caller) contains coefficients for both sets of existentials,
+ * first those in "ma" and then those in "src".
+ * f, c1, c2 and g are temporary objects that have been initialized
+ * by the caller.
+ *
+ * Let src represent the expression
+ *
+ * (a(p) + f_u u + b v + f_w w + c(divs))/d
+ *
+ * and let ma represent the expressions
+ *
+ * v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
+ *
+ * We start out with the following expression for dst:
+ *
+ * (a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
+ *
+ * with the multiplication factor f initially equal to 1
+ * and f \sum_i b_i v_i kept separately.
+ * For each x_i that we substitute, we multiply the numerator
+ * (and denominator) of dst by c_1 = m_i and add the numerator
+ * of the x_i expression multiplied by c_2 = f b_i,
+ * after removing the common factors of c_1 and c_2.
+ * The multiplication factor f also needs to be multiplied by c_1
+ * for the next x_j, j > i.
+ */
+void isl_seq_preimage(isl_int *dst, isl_int *src,
+ __isl_keep isl_multi_aff *ma, int n_before, int n_after,
+ int n_div_ma, int n_div_bmap,
+ isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
+{
+ int i;
+ int n_param, n_in, n_out;
+ int o_dst, o_src;
+
+ n_param = isl_multi_aff_dim(ma, isl_dim_param);
+ n_in = isl_multi_aff_dim(ma, isl_dim_in);
+ n_out = isl_multi_aff_dim(ma, isl_dim_out);
+
+ isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
+ o_dst = o_src = has_denom + 1 + n_param + n_before;
+ isl_seq_clr(dst + o_dst, n_in);
+ o_dst += n_in;
+ o_src += n_out;
+ isl_seq_cpy(dst + o_dst, src + o_src, n_after);
+ o_dst += n_after;
+ o_src += n_after;
+ isl_seq_clr(dst + o_dst, n_div_ma);
+ o_dst += n_div_ma;
+ isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
+
+ isl_int_set_si(f, 1);
+
+ for (i = 0; i < n_out; ++i) {
+ int offset = has_denom + 1 + n_param + n_before + i;
+
+ if (isl_int_is_zero(src[offset]))
+ continue;
+ isl_int_set(c1, ma->p[i]->v->el[0]);
+ isl_int_mul(c2, f, src[offset]);
+ isl_int_gcd(g, c1, c2);
+ isl_int_divexact(c1, c1, g);
+ isl_int_divexact(c2, c2, g);
+
+ isl_int_mul(f, f, c1);
+ o_dst = has_denom;
+ o_src = 1;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, 1 + n_param);
+ o_dst += 1 + n_param;
+ o_src += 1 + n_param;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
+ o_dst += n_before;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, n_in);
+ o_dst += n_in;
+ o_src += n_in;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
+ o_dst += n_after;
+ isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+ c2, ma->p[i]->v->el + o_src, n_div_ma);
+ o_dst += n_div_ma;
+ o_src += n_div_ma;
+ isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
+ if (has_denom)
+ isl_int_mul(dst[0], dst[0], c1);
+ }
+}
+
+/* Compute the pullback of "aff" by the function represented by "ma".
+ * In other words, plug in "ma" in "aff". The result is an affine expression
+ * defined over the domain space of "ma".
+ *
+ * If "aff" is represented by
+ *
+ * (a(p) + b x + c(divs))/d
+ *
+ * and ma is represented by
+ *
+ * x = D(p) + F(y) + G(divs')
+ *
+ * then the result is
+ *
+ * (a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
+ *
+ * The divs in the local space of the input are similarly adjusted
+ * through a call to isl_local_space_preimage_multi_aff.
+ */
+__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
+ __isl_take isl_multi_aff *ma)
+{
+ isl_aff *res = NULL;
+ isl_local_space *ls;
+ int n_div_aff, n_div_ma;
+ isl_int f, c1, c2, g;
+
+ ma = isl_multi_aff_align_divs(ma);
+ if (!aff || !ma)
+ goto error;
+
+ n_div_aff = isl_aff_dim(aff, isl_dim_div);
+ n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
+
+ ls = isl_aff_get_domain_local_space(aff);
+ ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
+ res = isl_aff_alloc(ls);
+ if (!res)
+ goto error;
+
+ isl_int_init(f);
+ isl_int_init(c1);
+ isl_int_init(c2);
+ isl_int_init(g);
+
+ isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, n_div_ma, n_div_aff,
+ f, c1, c2, g, 1);
+
+ isl_int_clear(f);
+ isl_int_clear(c1);
+ isl_int_clear(c2);
+ isl_int_clear(g);
+
+ isl_aff_free(aff);
+ isl_multi_aff_free(ma);
+ res = isl_aff_normalize(res);
+ return res;
+error:
+ isl_aff_free(aff);
+ isl_multi_aff_free(ma);
+ isl_aff_free(res);
+ return NULL;
+}
+
+/* Compute the pullback of "aff1" by the function represented by "aff2".
+ * In other words, plug in "aff2" in "aff1". The result is an affine expression
+ * defined over the domain space of "aff1".
+ *
+ * The domain of "aff1" should match the range of "aff2", which means
+ * that it should be single-dimensional.
+ */
+__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2)
+{
+ isl_multi_aff *ma;
+
+ ma = isl_multi_aff_from_aff(aff2);
+ return isl_aff_pullback_multi_aff(aff1, ma);
+}
+
+/* Compute the pullback of "ma1" by the function represented by "ma2".
+ * In other words, plug in "ma2" in "ma1".
+ *
+ * The parameters of "ma1" and "ma2" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
+ __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
+{
+ int i;
+ isl_space *space = NULL;
+
+ ma2 = isl_multi_aff_align_divs(ma2);
+ ma1 = isl_multi_aff_cow(ma1);
+ if (!ma1 || !ma2)
+ goto error;
+
+ space = isl_space_join(isl_multi_aff_get_space(ma2),
+ isl_multi_aff_get_space(ma1));
+
+ for (i = 0; i < ma1->n; ++i) {
+ ma1->p[i] = isl_aff_pullback_multi_aff(ma1->p[i],
+ isl_multi_aff_copy(ma2));
+ if (!ma1->p[i])
+ goto error;
+ }
+
+ ma1 = isl_multi_aff_reset_space(ma1, space);
+ isl_multi_aff_free(ma2);
+ return ma1;
+error:
+ isl_space_free(space);
+ isl_multi_aff_free(ma2);
+ isl_multi_aff_free(ma1);
+ return NULL;
+}
+
+/* Compute the pullback of "ma1" by the function represented by "ma2".
+ * In other words, plug in "ma2" in "ma1".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+ __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_pullback_multi_aff_aligned);
+}
+
+/* Extend the local space of "dst" to include the divs
+ * in the local space of "src".
+ */
+__isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
+ __isl_keep isl_aff *src)
+{
+ isl_ctx *ctx;
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_mat *div;
+
+ if (!src || !dst)
+ return isl_aff_free(dst);
+
+ ctx = isl_aff_get_ctx(src);
+ if (!isl_space_is_equal(src->ls->dim, dst->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", goto error);
+
+ if (src->ls->div->n_row == 0)
+ return dst;
+
+ exp1 = isl_alloc_array(ctx, int, src->ls->div->n_row);
+ exp2 = isl_alloc_array(ctx, int, dst->ls->div->n_row);
+ if (!exp1 || (dst->ls->div->n_row && !exp2))
+ goto error;
+
+ div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2);
+ dst = isl_aff_expand_divs(dst, div, exp2);
+ free(exp1);
+ free(exp2);
+
+ return dst;
+error:
+ free(exp1);
+ free(exp2);
+ return isl_aff_free(dst);
+}
+
+/* Adjust the local spaces of the affine expressions in "maff"
+ * such that they all have the save divs.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_align_divs(
+ __isl_take isl_multi_aff *maff)
+{
+ int i;
+
+ if (!maff)
+ return NULL;
+ if (maff->n == 0)
+ return maff;
+ maff = isl_multi_aff_cow(maff);
+ if (!maff)
+ return NULL;
+
+ for (i = 1; i < maff->n; ++i)
+ maff->p[0] = isl_aff_align_divs(maff->p[0], maff->p[i]);
+ for (i = 1; i < maff->n; ++i) {
+ maff->p[i] = isl_aff_align_divs(maff->p[i], maff->p[0]);
+ if (!maff->p[i])
+ return isl_multi_aff_free(maff);
+ }
+
+ return maff;
+}
+
+__isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff)
+{
+ aff = isl_aff_cow(aff);
+ if (!aff)
+ return NULL;
+
+ aff->ls = isl_local_space_lift(aff->ls);
+ if (!aff->ls)
+ return isl_aff_free(aff);
+
+ return aff;
+}
+
+/* Lift "maff" to a space with extra dimensions such that the result
+ * has no more existentially quantified variables.
+ * If "ls" is not NULL, then *ls is assigned the local space that lies
+ * at the basis of the lifting applied to "maff".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
+ __isl_give isl_local_space **ls)
+{
+ int i;
+ isl_space *space;
+ unsigned n_div;
+
+ if (ls)
+ *ls = NULL;
+
+ if (!maff)
+ return NULL;
+
+ if (maff->n == 0) {
+ if (ls) {
+ isl_space *space = isl_multi_aff_get_domain_space(maff);
+ *ls = isl_local_space_from_space(space);
+ if (!*ls)
+ return isl_multi_aff_free(maff);
+ }
+ return maff;
+ }
+
+ maff = isl_multi_aff_cow(maff);
+ maff = isl_multi_aff_align_divs(maff);
+ if (!maff)
+ return NULL;
+
+ n_div = isl_aff_dim(maff->p[0], isl_dim_div);
+ space = isl_multi_aff_get_space(maff);
+ space = isl_space_lift(isl_space_domain(space), n_div);
+ space = isl_space_extend_domain_with_range(space,
+ isl_multi_aff_get_space(maff));
+ if (!space)
+ return isl_multi_aff_free(maff);
+ isl_space_free(maff->space);
+ maff->space = space;
+
+ if (ls) {
+ *ls = isl_aff_get_domain_local_space(maff->p[0]);
+ if (!*ls)
+ return isl_multi_aff_free(maff);
+ }
+
+ for (i = 0; i < maff->n; ++i) {
+ maff->p[i] = isl_aff_lift(maff->p[i]);
+ if (!maff->p[i])
+ goto error;
+ }
+
+ return maff;
+error:
+ if (ls)
+ isl_local_space_free(*ls);
+ return isl_multi_aff_free(maff);
+}
+
+
+/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
+ */
+__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
+ __isl_keep isl_pw_multi_aff *pma, int pos)
+{
+ int i;
+ int n_out;
+ isl_space *space;
+ isl_pw_aff *pa;
+
+ if (!pma)
+ return NULL;
+
+ n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
+ if (pos < 0 || pos >= n_out)
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "index out of bounds", return NULL);
+
+ space = isl_pw_multi_aff_get_space(pma);
+ space = isl_space_drop_dims(space, isl_dim_out,
+ pos + 1, n_out - pos - 1);
+ space = isl_space_drop_dims(space, isl_dim_out, 0, pos);
+
+ pa = isl_pw_aff_alloc_size(space, pma->n);
+ for (i = 0; i < pma->n; ++i) {
+ isl_aff *aff;
+ aff = isl_multi_aff_get_aff(pma->p[i].maff, pos);
+ pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff);
+ }
+
+ return pa;
+}
+
+/* Return an isl_pw_multi_aff with the given "set" as domain and
+ * an unnamed zero-dimensional range.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
+ __isl_take isl_set *set)
+{
+ isl_multi_aff *ma;
+ isl_space *space;
+
+ space = isl_set_get_space(set);
+ space = isl_space_from_domain(space);
+ ma = isl_multi_aff_zero(space);
+ return isl_pw_multi_aff_alloc(set, ma);
+}
+
+/* Add an isl_pw_multi_aff with the given "set" as domain and
+ * an unnamed zero-dimensional range to *user.
+ */
+static int add_pw_multi_aff_from_domain(__isl_take isl_set *set, void *user)
+{
+ isl_union_pw_multi_aff **upma = user;
+ isl_pw_multi_aff *pma;
+
+ pma = isl_pw_multi_aff_from_domain(set);
+ *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
+
+ return 0;
+}
+
+/* Return an isl_union_pw_multi_aff with the given "uset" as domain and
+ * an unnamed zero-dimensional range.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
+ __isl_take isl_union_set *uset)
+{
+ isl_space *space;
+ isl_union_pw_multi_aff *upma;
+
+ if (!uset)
+ return NULL;
+
+ space = isl_union_set_get_space(uset);
+ upma = isl_union_pw_multi_aff_empty(space);
+
+ if (isl_union_set_foreach_set(uset,
+ &add_pw_multi_aff_from_domain, &upma) < 0)
+ goto error;
+
+ isl_union_set_free(uset);
+ return upma;
+error:
+ isl_union_set_free(uset);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}
+
+/* Convert "pma" to an isl_map and add it to *umap.
+ */
+static int map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ isl_union_map **umap = user;
+ isl_map *map;
+
+ map = isl_map_from_pw_multi_aff(pma);
+ *umap = isl_union_map_add_map(*umap, map);
+
+ return 0;
+}
+
+/* Construct a union map mapping the domain of the union
+ * piecewise multi-affine expression to its range, with each dimension
+ * in the range equated to the corresponding affine expression on its cell.
+ */
+__isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ isl_space *space;
+ isl_union_map *umap;
+
+ if (!upma)
+ return NULL;
+
+ space = isl_union_pw_multi_aff_get_space(upma);
+ umap = isl_union_map_empty(space);
+
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &map_from_pw_multi_aff, &umap) < 0)
+ goto error;
+
+ isl_union_pw_multi_aff_free(upma);
+ return umap;
+error:
+ isl_union_pw_multi_aff_free(upma);
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+/* Local data for bin_entry and the callback "fn".
+ */
+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;
+ int (*fn)(void **entry, 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 int bin_entry(void **entry, void *user)
+{
+ struct isl_union_pw_multi_aff_bin_data *data = user;
+ isl_pw_multi_aff *pma = *entry;
+
+ data->pma = pma;
+ if (isl_hash_table_foreach(data->upma2->space->ctx, &data->upma2->table,
+ data->fn, data) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
+ * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
+ * passed as user field) and the isl_pw_multi_aff from upma2 is available
+ * as *entry. The callback should adjust data->res if desired.
+ */
+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,
+ int (*fn)(void **entry, void *user))
+{
+ isl_space *space;
+ struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
+
+ space = isl_union_pw_multi_aff_get_space(upma2);
+ upma1 = isl_union_pw_multi_aff_align_params(upma1, space);
+ space = isl_union_pw_multi_aff_get_space(upma1);
+ upma2 = isl_union_pw_multi_aff_align_params(upma2, space);
+
+ if (!upma1 || !upma2)
+ 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,
+ &bin_entry, &data) < 0)
+ goto error;
+
+ isl_union_pw_multi_aff_free(upma1);
+ isl_union_pw_multi_aff_free(upma2);
+ return data.res;
+error:
+ isl_union_pw_multi_aff_free(upma1);
+ isl_union_pw_multi_aff_free(upma2);
+ isl_union_pw_multi_aff_free(data.res);
+ return NULL;
+}
+
+/* Given two aligned isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> [B -> D].
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_range_product(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ isl_space *space;
+
+ space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
+ isl_pw_multi_aff_get_space(pma2));
+ return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
+ &isl_multi_aff_range_product);
+}
+
+/* Given two isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> [B -> D].
+ */
+__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)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_range_product);
+}
+
+/* Given two aligned isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> (B, D).
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+ isl_space *space;
+
+ space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
+ isl_pw_multi_aff_get_space(pma2));
+ space = isl_space_flatten_range(space);
+ return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
+ &isl_multi_aff_flat_range_product);
+}
+
+/* Given two isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> (B, D).
+ */
+__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)
+{
+ return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+ &pw_multi_aff_flat_range_product);
+}
+
+/* If data->pma and *entry have the same domain space, then compute
+ * their flat range product and the result to data->res.
+ */
+static int flat_range_product_entry(void **entry, 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))
+ return 0;
+
+ pma2 = isl_pw_multi_aff_flat_range_product(
+ isl_pw_multi_aff_copy(data->pma),
+ isl_pw_multi_aff_copy(pma2));
+
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
+
+ return 0;
+}
+
+/* Given two isl_union_pw_multi_affs A -> B and C -> D,
+ * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
+ */
+__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)
+{
+ return bin_op(upma1, upma2, &flat_range_product_entry);
+}
+
+/* Replace the affine expressions at position "pos" in "pma" by "pa".
+ * The parameters are assumed to have been aligned.
+ *
+ * The implementation essentially performs an isl_pw_*_on_shared_domain,
+ * except that it works on two different isl_pw_* types.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
+ __isl_take isl_pw_multi_aff *pma, unsigned pos,
+ __isl_take isl_pw_aff *pa)
+{
+ int i, j, n;
+ isl_pw_multi_aff *res = NULL;
+
+ if (!pma || !pa)
+ goto error;
+
+ if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in,
+ pa->dim, isl_dim_in))
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "domains don't match", goto error);
+ if (pos >= isl_pw_multi_aff_dim(pma, isl_dim_out))
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ n = pma->n * pa->n;
+ res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
+
+ for (i = 0; i < pma->n; ++i) {
+ for (j = 0; j < pa->n; ++j) {
+ isl_set *common;
+ isl_multi_aff *res_ij;
+ int empty;
+
+ common = isl_set_intersect(isl_set_copy(pma->p[i].set),
+ isl_set_copy(pa->p[j].set));
+ empty = isl_set_plain_is_empty(common);
+ if (empty < 0 || empty) {
+ isl_set_free(common);
+ if (empty < 0)
+ goto error;
+ continue;
+ }
+
+ res_ij = isl_multi_aff_set_aff(
+ isl_multi_aff_copy(pma->p[i].maff), pos,
+ isl_aff_copy(pa->p[j].aff));
+ res_ij = isl_multi_aff_gist(res_ij,
+ isl_set_copy(common));
+
+ res = isl_pw_multi_aff_add_piece(res, common, res_ij);
+ }
+ }
+
+ isl_pw_multi_aff_free(pma);
+ isl_pw_aff_free(pa);
+ return res;
+error:
+ isl_pw_multi_aff_free(pma);
+ isl_pw_aff_free(pa);
+ return isl_pw_multi_aff_free(res);
+}
+
+/* Replace the affine expressions at position "pos" in "pma" by "pa".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
+ __isl_take isl_pw_multi_aff *pma, unsigned pos,
+ __isl_take isl_pw_aff *pa)
+{
+ if (!pma || !pa)
+ goto error;
+ if (isl_space_match(pma->dim, isl_dim_param, pa->dim, isl_dim_param))
+ return pw_multi_aff_set_pw_aff(pma, pos, pa);
+ if (!isl_space_has_named_params(pma->dim) ||
+ !isl_space_has_named_params(pa->dim))
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa));
+ pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma));
+ return pw_multi_aff_set_pw_aff(pma, pos, pa);
+error:
+ isl_pw_multi_aff_free(pma);
+ isl_pw_aff_free(pa);
+ return NULL;
+}
+
+/* Do the parameters of "pa" match those of "space"?
+ */
+int isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
+ __isl_keep isl_space *space)
+{
+ isl_space *pa_space;
+ int match;
+
+ if (!pa || !space)
+ return -1;
+
+ pa_space = isl_pw_aff_get_space(pa);
+
+ match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+
+ isl_space_free(pa_space);
+ return match;
+}
+
+/* Check that the domain space of "pa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+ __isl_keep isl_space *space)
+{
+ isl_space *pa_space;
+ int match;
+
+ if (!pa || !space)
+ return -1;
+
+ pa_space = isl_pw_aff_get_space(pa);
+
+ match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "parameters don't match", goto error);
+ match = isl_space_tuple_is_equal(space, isl_dim_in,
+ pa_space, isl_dim_in);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "domains don't match", goto error);
+ isl_space_free(pa_space);
+ return 0;
+error:
+ isl_space_free(pa_space);
+ return -1;
+}
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_multi_templ.c>
+
+/* Scale the elements of "pma" by the corresponding elements of "mv".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
+{
+ int i;
+
+ pma = isl_pw_multi_aff_cow(pma);
+ if (!pma || !mv)
+ goto error;
+ if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
+ mv->space, isl_dim_set))
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "spaces don't match", goto error);
+ if (!isl_space_match(pma->dim, isl_dim_param,
+ mv->space, isl_dim_param)) {
+ pma = isl_pw_multi_aff_align_params(pma,
+ isl_multi_val_get_space(mv));
+ mv = isl_multi_val_align_params(mv,
+ isl_pw_multi_aff_get_space(pma));
+ if (!pma || !mv)
+ goto error;
+ }
+
+ for (i = 0; i < pma->n; ++i) {
+ pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
+ isl_multi_val_copy(mv));
+ if (!pma->p[i].maff)
+ goto error;
+ }
+
+ isl_multi_val_free(mv);
+ return pma;
+error:
+ isl_multi_val_free(mv);
+ isl_pw_multi_aff_free(pma);
+ 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.
+ */
+static int union_pw_multi_aff_scale_multi_val_entry(void **entry, void *user)
+{
+ struct isl_union_pw_multi_aff_scale_multi_val_data *data = user;
+ isl_pw_multi_aff *pma = *entry;
+
+ if (!pma)
+ return -1;
+ if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
+ data->mv->space, isl_dim_set))
+ return 0;
+
+ 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 -1;
+
+ return 0;
+}
+
+/* Scale the elements of "upma" by the corresponding elements of "mv",
+ * for those entries that match the space of "mv".
+ */
+__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,
+ isl_union_pw_multi_aff_get_space(upma));
+ 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;
+
+ isl_multi_val_free(mv);
+ isl_union_pw_multi_aff_free(upma);
+ return data.res;
+error:
+ isl_multi_val_free(mv);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}
+
+/* Construct and return a piecewise multi affine expression
+ * in the given space with value zero in each of the output dimensions and
+ * a universe domain.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space)
+{
+ return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space));
+}
+
+/* Construct and return a piecewise multi affine expression
+ * that is equal to the given piecewise affine expression.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
+ __isl_take isl_pw_aff *pa)
+{
+ int i;
+ isl_space *space;
+ isl_pw_multi_aff *pma;
+
+ if (!pa)
+ return NULL;
+
+ space = isl_pw_aff_get_space(pa);
+ pma = isl_pw_multi_aff_alloc_size(space, pa->n);
+
+ for (i = 0; i < pa->n; ++i) {
+ isl_set *set;
+ isl_multi_aff *ma;
+
+ set = isl_set_copy(pa->p[i].set);
+ ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff));
+ pma = isl_pw_multi_aff_add_piece(pma, set, ma);
+ }
+
+ isl_pw_aff_free(pa);
+ return pma;
+}
+
+/* Construct a set or map mapping the shared (parameter) domain
+ * of the piecewise affine expressions to the range of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+static __isl_give isl_map *map_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ int i;
+ isl_space *space;
+ isl_map *map;
+
+ if (!mpa)
+ return NULL;
+
+ if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n)
+ isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+ "invalid space", goto error);
+
+ space = isl_multi_pw_aff_get_domain_space(mpa);
+ map = isl_map_universe(isl_space_from_domain(space));
+
+ for (i = 0; i < mpa->n; ++i) {
+ isl_pw_aff *pa;
+ isl_map *map_i;
+
+ pa = isl_pw_aff_copy(mpa->p[i]);
+ map_i = map_from_pw_aff(pa);
+
+ map = isl_map_flat_range_product(map, map_i);
+ }
+
+ map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa));
+
+ isl_multi_pw_aff_free(mpa);
+ return map;
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct a map mapping the shared domain
+ * of the piecewise affine expressions to the range of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+__isl_give isl_map *isl_map_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
+{
+ if (!mpa)
+ return NULL;
+ if (isl_space_is_set(mpa->space))
+ isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+ "space of input is not a map", goto error);
+
+ return map_from_multi_pw_aff(mpa);
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct a set mapping the shared parameter domain
+ * of the piecewise affine expressions to the space of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+__isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
+{
+ if (!mpa)
+ return NULL;
+ if (!isl_space_is_set(mpa->space))
+ isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+ "space of input is not a set", goto error);
+
+ return map_from_multi_pw_aff(mpa);
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct and return a piecewise multi affine expression
+ * that is equal to the given multi piecewise affine expression
+ * on the shared domain of the piecewise affine expressions.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ int i;
+ isl_space *space;
+ isl_pw_aff *pa;
+ isl_pw_multi_aff *pma;
+
+ if (!mpa)
+ return NULL;
+
+ space = isl_multi_pw_aff_get_space(mpa);
+
+ if (mpa->n == 0) {
+ isl_multi_pw_aff_free(mpa);
+ return isl_pw_multi_aff_zero(space);
+ }
+
+ pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
+ pma = isl_pw_multi_aff_from_pw_aff(pa);
+
+ for (i = 1; i < mpa->n; ++i) {
+ isl_pw_multi_aff *pma_i;
+
+ pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
+ pma_i = isl_pw_multi_aff_from_pw_aff(pa);
+ pma = isl_pw_multi_aff_range_product(pma, pma_i);
+ }
+
+ pma = isl_pw_multi_aff_reset_space(pma, space);
+
+ isl_multi_pw_aff_free(mpa);
+ return pma;
+}
+
+/* Construct and return a multi piecewise affine expression
+ * that is equal to the given multi affine expression.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma)
+{
+ int i, n;
+ isl_multi_pw_aff *mpa;
+
+ if (!ma)
+ return NULL;
+
+ n = isl_multi_aff_dim(ma, isl_dim_out);
+ mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma));
+
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+
+ pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i));
+ mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+ }
+
+ isl_multi_aff_free(ma);
+ return mpa;
+}
+
+/* Construct and return a multi piecewise affine expression
+ * that is equal to the given piecewise multi affine expression.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
+ __isl_take isl_pw_multi_aff *pma)
+{
+ int i, n;
+ isl_space *space;
+ isl_multi_pw_aff *mpa;
+
+ if (!pma)
+ return NULL;
+
+ n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+ space = isl_pw_multi_aff_get_space(pma);
+ mpa = isl_multi_pw_aff_alloc(space);
+
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+
+ pa = isl_pw_multi_aff_get_pw_aff(pma, i);
+ mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+ }
+
+ isl_pw_multi_aff_free(pma);
+ return mpa;
+}
+
+/* Do "pa1" and "pa2" represent the same function?
+ *
+ * We first check if they are obviously equal.
+ * If not, we convert them to maps and check if those are equal.
+ */
+int isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2)
+{
+ int equal;
+ isl_map *map1, *map2;
+
+ if (!pa1 || !pa2)
+ return -1;
+
+ equal = isl_pw_aff_plain_is_equal(pa1, pa2);
+ if (equal < 0 || equal)
+ return equal;
+
+ map1 = map_from_pw_aff(isl_pw_aff_copy(pa1));
+ map2 = map_from_pw_aff(isl_pw_aff_copy(pa2));
+ equal = isl_map_is_equal(map1, map2);
+ isl_map_free(map1);
+ isl_map_free(map2);
+
+ return equal;
+}
+
+/* Do "mpa1" and "mpa2" represent the same function?
+ *
+ * Note that we cannot convert the entire isl_multi_pw_aff
+ * to a map because the domains of the piecewise affine expressions
+ * may not be the same.
+ */
+int isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
+ __isl_keep isl_multi_pw_aff *mpa2)
+{
+ int i;
+ int equal;
+
+ if (!mpa1 || !mpa2)
+ return -1;
+
+ if (!isl_space_match(mpa1->space, isl_dim_param,
+ mpa2->space, isl_dim_param)) {
+ if (!isl_space_has_named_params(mpa1->space))
+ return 0;
+ if (!isl_space_has_named_params(mpa2->space))
+ return 0;
+ mpa1 = isl_multi_pw_aff_copy(mpa1);
+ mpa2 = isl_multi_pw_aff_copy(mpa2);
+ mpa1 = isl_multi_pw_aff_align_params(mpa1,
+ isl_multi_pw_aff_get_space(mpa2));
+ mpa2 = isl_multi_pw_aff_align_params(mpa2,
+ isl_multi_pw_aff_get_space(mpa1));
+ equal = isl_multi_pw_aff_is_equal(mpa1, mpa2);
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa2);
+ return equal;
+ }
+
+ equal = isl_space_is_equal(mpa1->space, mpa2->space);
+ if (equal < 0 || !equal)
+ return equal;
+
+ for (i = 0; i < mpa1->n; ++i) {
+ equal = isl_pw_aff_is_equal(mpa1->p[i], mpa2->p[i]);
+ if (equal < 0 || !equal)
+ return equal;
+ }
+
+ return 1;
+}
+
+/* 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".
+ *
+ * The parameters of "mpa" and "ma" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
+{
+ int i;
+ isl_space *space = NULL;
+
+ mpa = isl_multi_pw_aff_cow(mpa);
+ if (!mpa || !ma)
+ goto error;
+
+ space = isl_space_join(isl_multi_aff_get_space(ma),
+ isl_multi_pw_aff_get_space(mpa));
+ if (!space)
+ goto error;
+
+ for (i = 0; i < mpa->n; ++i) {
+ mpa->p[i] = isl_pw_aff_pullback_multi_aff(mpa->p[i],
+ isl_multi_aff_copy(ma));
+ if (!mpa->p[i])
+ goto error;
+ }
+
+ isl_multi_aff_free(ma);
+ isl_space_free(mpa->space);
+ mpa->space = space;
+ return mpa;
+error:
+ isl_space_free(space);
+ isl_multi_pw_aff_free(mpa);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "ma".
+ * In other words, plug in "ma" in "mpa".
+ */
+__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)
+{
+ if (!mpa || !ma)
+ goto error;
+ if (isl_space_match(mpa->space, isl_dim_param,
+ ma->space, isl_dim_param))
+ return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
+ mpa = isl_multi_pw_aff_align_params(mpa, isl_multi_aff_get_space(ma));
+ ma = isl_multi_aff_align_params(ma, isl_multi_pw_aff_get_space(mpa));
+ return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
+error:
+ isl_multi_pw_aff_free(mpa);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "pma".
+ * In other words, plug in "pma" in "mpa".
+ *
+ * The parameters of "mpa" and "mpa" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
+{
+ int i;
+ isl_space *space = NULL;
+
+ mpa = isl_multi_pw_aff_cow(mpa);
+ if (!mpa || !pma)
+ goto error;
+
+ space = isl_space_join(isl_pw_multi_aff_get_space(pma),
+ isl_multi_pw_aff_get_space(mpa));
+
+ for (i = 0; i < mpa->n; ++i) {
+ mpa->p[i] = isl_pw_aff_pullback_pw_multi_aff_aligned(mpa->p[i],
+ isl_pw_multi_aff_copy(pma));
+ if (!mpa->p[i])
+ goto error;
+ }
+
+ isl_pw_multi_aff_free(pma);
+ isl_space_free(mpa->space);
+ mpa->space = space;
+ return mpa;
+error:
+ isl_space_free(space);
+ isl_multi_pw_aff_free(mpa);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "pma".
+ * In other words, plug in "pma" in "mpa".
+ */
+__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)
+{
+ if (!mpa || !pma)
+ goto error;
+ if (isl_space_match(mpa->space, isl_dim_param, pma->dim, isl_dim_param))
+ return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
+ mpa = isl_multi_pw_aff_align_params(mpa,
+ isl_pw_multi_aff_get_space(pma));
+ pma = isl_pw_multi_aff_align_params(pma,
+ isl_multi_pw_aff_get_space(mpa));
+ return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
+error:
+ isl_multi_pw_aff_free(mpa);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
+ * with the domain of "aff". The domain of the result is the same
+ * as that of "mpa".
+ * "mpa" and "aff" are assumed to have been aligned.
+ *
+ * We first extract the parametric constant from "aff", defined
+ * over the correct domain.
+ * Then we add the appropriate combinations of the members of "mpa".
+ * Finally, we add the integer divisions through recursive calls.
+ */
+static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
+{
+ int i, n_param, n_in, n_div;
+ isl_space *space;
+ isl_val *v;
+ isl_pw_aff *pa;
+ isl_aff *tmp;
+
+ n_param = isl_aff_dim(aff, isl_dim_param);
+ n_in = isl_aff_dim(aff, isl_dim_in);
+ n_div = isl_aff_dim(aff, isl_dim_div);
+
+ space = isl_space_domain(isl_multi_pw_aff_get_space(mpa));
+ tmp = isl_aff_copy(aff);
+ tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div);
+ tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in);
+ tmp = isl_aff_add_dims(tmp, isl_dim_in,
+ isl_space_dim(space, isl_dim_set));
+ tmp = isl_aff_reset_domain_space(tmp, space);
+ pa = isl_pw_aff_from_aff(tmp);
+
+ for (i = 0; i < n_in; ++i) {
+ isl_pw_aff *pa_i;
+
+ if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
+ continue;
+ v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
+ pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i);
+ pa_i = isl_pw_aff_scale_val(pa_i, v);
+ pa = isl_pw_aff_add(pa, pa_i);
+ }
+
+ for (i = 0; i < n_div; ++i) {
+ isl_aff *div;
+ isl_pw_aff *pa_i;
+
+ if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
+ continue;
+ div = isl_aff_get_div(aff, i);
+ pa_i = isl_multi_pw_aff_apply_aff_aligned(
+ isl_multi_pw_aff_copy(mpa), div);
+ pa_i = isl_pw_aff_floor(pa_i);
+ v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
+ pa_i = isl_pw_aff_scale_val(pa_i, v);
+ pa = isl_pw_aff_add(pa, pa_i);
+ }
+
+ isl_multi_pw_aff_free(mpa);
+ isl_aff_free(aff);
+
+ return pa;
+}
+
+/* Apply "aff" to "mpa". The range of "mpa" needs to be compatible
+ * with the domain of "aff". The domain of the result is the same
+ * as that of "mpa".
+ */
+__isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
+{
+ if (!aff || !mpa)
+ goto error;
+ if (isl_space_match(aff->ls->dim, isl_dim_param,
+ mpa->space, isl_dim_param))
+ return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
+
+ aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa));
+ mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff));
+
+ return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
+error:
+ isl_aff_free(aff);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
+ * with the domain of "pa". The domain of the result is the same
+ * as that of "mpa".
+ * "mpa" and "pa" are assumed to have been aligned.
+ *
+ * We consider each piece in turn. Note that the domains of the
+ * pieces are assumed to be disjoint and they remain disjoint
+ * after taking the preimage (over the same function).
+ */
+static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
+{
+ isl_space *space;
+ isl_pw_aff *res;
+ int i;
+
+ if (!mpa || !pa)
+ goto error;
+
+ space = isl_space_join(isl_multi_pw_aff_get_space(mpa),
+ isl_pw_aff_get_space(pa));
+ res = isl_pw_aff_empty(space);
+
+ for (i = 0; i < pa->n; ++i) {
+ isl_pw_aff *pa_i;
+ isl_set *domain;
+
+ pa_i = isl_multi_pw_aff_apply_aff_aligned(
+ isl_multi_pw_aff_copy(mpa),
+ isl_aff_copy(pa->p[i].aff));
+ domain = isl_set_copy(pa->p[i].set);
+ domain = isl_set_preimage_multi_pw_aff(domain,
+ isl_multi_pw_aff_copy(mpa));
+ pa_i = isl_pw_aff_intersect_domain(pa_i, domain);
+ res = isl_pw_aff_add_disjoint(res, pa_i);
+ }
+
+ isl_pw_aff_free(pa);
+ isl_multi_pw_aff_free(mpa);
+ return res;
+error:
+ isl_pw_aff_free(pa);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Apply "pa" to "mpa". The range of "mpa" needs to be compatible
+ * with the domain of "pa". The domain of the result is the same
+ * as that of "mpa".
+ */
+__isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
+{
+ if (!pa || !mpa)
+ goto error;
+ if (isl_space_match(pa->dim, isl_dim_param, mpa->space, isl_dim_param))
+ return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+
+ pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa));
+ mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa));
+
+ return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+error:
+ isl_pw_aff_free(pa);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Compute the pullback of "pa" by the function represented by "mpa".
+ * In other words, plug in "mpa" in "pa".
+ * "pa" and "mpa" are assumed to have been aligned.
+ *
+ * The pullback is computed by applying "pa" to "mpa".
+ */
+static __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff_aligned(
+ __isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
+{
+ return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+}
+
+/* Compute the pullback of "pa" by the function represented by "mpa".
+ * In other words, plug in "mpa" in "pa".
+ *
+ * The pullback is computed by applying "pa" to "mpa".
+ */
+__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)
+{
+ return isl_multi_pw_aff_apply_pw_aff(mpa, pa);
+}
+
+/* Compute the pullback of "mpa1" by the function represented by "mpa2".
+ * In other words, plug in "mpa2" in "mpa1".
+ *
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * We pullback each member of "mpa1" in turn.
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
+{
+ int i;
+ isl_space *space = NULL;
+
+ mpa1 = isl_multi_pw_aff_cow(mpa1);
+ if (!mpa1 || !mpa2)
+ goto error;
+
+ space = isl_space_join(isl_multi_pw_aff_get_space(mpa2),
+ isl_multi_pw_aff_get_space(mpa1));
+
+ for (i = 0; i < mpa1->n; ++i) {
+ mpa1->p[i] = isl_pw_aff_pullback_multi_pw_aff_aligned(
+ mpa1->p[i], isl_multi_pw_aff_copy(mpa2));
+ if (!mpa1->p[i])
+ goto error;
+ }
+
+ mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
+
+ isl_multi_pw_aff_free(mpa2);
+ return mpa1;
+error:
+ isl_space_free(space);
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa2);
+ return NULL;
+}
+
+/* Compute the pullback of "mpa1" by the function represented by "mpa2".
+ * In other words, plug in "mpa2" in "mpa1".
+ */
+__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)
+{
+ return isl_multi_pw_aff_align_params_multi_multi_and(mpa1, mpa2,
+ &isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
+}
+
+/* Compare two isl_affs.
+ *
+ * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
+ * than "aff2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary. We do consider expressions that only involve
+ * earlier dimensions as "smaller".
+ */
+int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
+{
+ int cmp;
+ int last1, last2;
+
+ if (aff1 == aff2)
+ return 0;
+
+ if (!aff1)
+ return -1;
+ if (!aff2)
+ return 1;
+
+ cmp = isl_local_space_cmp(aff1->ls, aff2->ls);
+ if (cmp != 0)
+ return cmp;
+
+ last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1);
+ last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1);
+ if (last1 != last2)
+ return last1 - last2;
+
+ return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size);
+}
+
+/* Compare two isl_pw_affs.
+ *
+ * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
+ * than "pa2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary. We do consider expressions that only involve
+ * earlier dimensions as "smaller".
+ */
+int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
+ __isl_keep isl_pw_aff *pa2)
+{
+ int i;
+ int cmp;
+
+ if (pa1 == pa2)
+ return 0;
+
+ if (!pa1)
+ return -1;
+ if (!pa2)
+ return 1;
+
+ cmp = isl_space_cmp(pa1->dim, pa2->dim);
+ if (cmp != 0)
+ return cmp;
+
+ if (pa1->n != pa2->n)
+ return pa1->n - pa2->n;
+
+ for (i = 0; i < pa1->n; ++i) {
+ cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set);
+ if (cmp != 0)
+ return cmp;
+ cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff);
+ if (cmp != 0)
+ return cmp;
+ }
+
+ return 0;
+}
+
+/* Return a piecewise affine expression that is equal to "v" on "domain".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
+ __isl_take isl_val *v)
+{
+ isl_space *space;
+ isl_local_space *ls;
+ isl_aff *aff;
+
+ space = isl_set_get_space(domain);
+ ls = isl_local_space_from_space(space);
+ aff = isl_aff_val_on_domain(ls, v);
+
+ return isl_pw_aff_alloc(domain, aff);
+}
+
+/* Return a multi affine expression that is equal to "mv" on domain
+ * space "space".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
+ __isl_take isl_space *space, __isl_take isl_multi_val *mv)
+{
+ int i, n;
+ isl_space *space2;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+
+ if (!space || !mv)
+ goto error;
+
+ n = isl_multi_val_dim(mv, isl_dim_set);
+ space2 = isl_multi_val_get_space(mv);
+ space2 = isl_space_align_params(space2, isl_space_copy(space));
+ space = isl_space_align_params(space, isl_space_copy(space2));
+ space = isl_space_map_from_domain_and_range(space, space2);
+ ma = isl_multi_aff_alloc(isl_space_copy(space));
+ ls = isl_local_space_from_space(isl_space_domain(space));
+ for (i = 0; i < n; ++i) {
+ isl_val *v;
+ isl_aff *aff;
+
+ v = isl_multi_val_get_val(mv, i);
+ aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+ isl_local_space_free(ls);
+
+ isl_multi_val_free(mv);
+ return ma;
+error:
+ isl_space_free(space);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Return a piecewise multi-affine expression
+ * that is equal to "mv" on "domain".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_set *domain, __isl_take isl_multi_val *mv)
+{
+ isl_space *space;
+ isl_multi_aff *ma;
+
+ space = isl_set_get_space(domain);
+ ma = isl_multi_aff_multi_val_on_space(space, mv);
+
+ return isl_pw_multi_aff_alloc(domain, ma);
+}
+
+/* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
+ * mv is the value that should be attained on each domain set
+ * res collects the results
+ */
+struct isl_union_pw_multi_aff_multi_val_on_domain_data {
+ isl_multi_val *mv;
+ isl_union_pw_multi_aff *res;
+};
+
+/* Create an isl_pw_multi_aff equal to data->mv on "domain"
+ * and add it to data->res.
+ */
+static int pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain,
+ void *user)
+{
+ struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user;
+ isl_pw_multi_aff *pma;
+ isl_multi_val *mv;
+
+ mv = isl_multi_val_copy(data->mv);
+ pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv);
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+
+ return data->res ? 0 : -1;
+}
+
+/* Return a union piecewise multi-affine expression
+ * that is equal to "mv" on "domain".
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
+{
+ struct isl_union_pw_multi_aff_multi_val_on_domain_data data;
+ isl_space *space;
+
+ space = isl_union_set_get_space(domain);
+ data.res = isl_union_pw_multi_aff_empty(space);
+ data.mv = mv;
+ if (isl_union_set_foreach_set(domain,
+ &pw_multi_aff_multi_val_on_domain, &data) < 0)
+ data.res = isl_union_pw_multi_aff_free(data.res);
+ isl_union_set_free(domain);
+ isl_multi_val_free(mv);
+ return data.res;
+}
diff --git a/polly/lib/External/isl/isl_aff_private.h b/polly/lib/External/isl/isl_aff_private.h
new file mode 100644
index 00000000000..bb959f4bcb3
--- /dev/null
+++ b/polly/lib/External/isl/isl_aff_private.h
@@ -0,0 +1,158 @@
+#ifndef ISL_AFF_PRIVATE_H
+#define ISL_AFF_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/vec.h>
+#include <isl/mat.h>
+#include <isl/local_space.h>
+#include <isl_int.h>
+#include <isl_reordering.h>
+
+/* ls represents the domain space.
+ *
+ * If the first two elements of "v" (the denominator and the constant term)
+ * are zero, then the isl_aff represents NaN.
+ */
+struct isl_aff {
+ int ref;
+
+ isl_local_space *ls;
+ isl_vec *v;
+};
+
+#undef EL
+#define EL isl_aff
+
+#include <isl_list_templ.h>
+
+struct isl_pw_aff_piece {
+ struct isl_set *set;
+ struct isl_aff *aff;
+};
+
+struct isl_pw_aff {
+ int ref;
+
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_pw_aff_piece p[1];
+};
+
+#undef EL
+#define EL isl_pw_aff
+
+#include <isl_list_templ.h>
+
+struct isl_pw_multi_aff_piece {
+ isl_set *set;
+ isl_multi_aff *maff;
+};
+
+struct isl_pw_multi_aff {
+ int ref;
+
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_pw_multi_aff_piece p[1];
+};
+
+__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
+ __isl_take isl_vec *v);
+__isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls);
+
+__isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
+ __isl_take isl_space *space, __isl_take isl_space *domain);
+__isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
+ __isl_take isl_space *dim);
+__isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
+ __isl_take isl_reordering *r);
+
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v);
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+ enum isl_dim_type type, int pos, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v);
+
+__isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
+ __isl_take isl_mat *div, int *exp);
+
+__isl_give isl_pw_aff *isl_pw_aff_alloc_size(__isl_take isl_space *space,
+ int n);
+__isl_give isl_pw_aff *isl_pw_aff_reset_space(__isl_take isl_pw_aff *pwaff,
+ __isl_take isl_space *dim);
+__isl_give isl_pw_aff *isl_pw_aff_reset_domain_space(
+ __isl_take isl_pw_aff *pwaff, __isl_take isl_space *space);
+__isl_give isl_pw_aff *isl_pw_aff_add_disjoint(
+ __isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2);
+
+__isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+ __isl_take isl_pw_aff *pwaff2, int max);
+
+__isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
+ __isl_take isl_pw_aff_list *list);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale(__isl_take isl_pw_aff *pwaff,
+ isl_int f);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+ isl_int f);
+
+int isl_aff_matching_params(__isl_keep isl_aff *aff,
+ __isl_keep isl_space *space);
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+ __isl_keep isl_space *space);
+
+#undef BASE
+#define BASE aff
+
+#include <isl_multi_templ.h>
+
+__isl_give isl_multi_aff *isl_multi_aff_dup(__isl_keep isl_multi_aff *multi);
+
+__isl_give isl_multi_aff *isl_multi_aff_align_divs(
+ __isl_take isl_multi_aff *maff);
+
+__isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
+ __isl_take isl_basic_set *bset);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_domain_space(
+ __isl_take isl_pw_multi_aff *pwmaff, __isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_space(
+ __isl_take isl_pw_multi_aff *pwmaff, __isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add_disjoint(
+ __isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out(
+ __isl_take isl_pw_multi_aff *pma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
+ int p_len, int subs_len, isl_int v);
+void isl_seq_preimage(isl_int *dst, isl_int *src,
+ __isl_keep isl_multi_aff *ma, int n_before, int n_after,
+ int n_div_ma, int n_div_bmap,
+ isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
+ __isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
+ __isl_keep isl_pw_aff *subs);
+
+int isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
+ __isl_keep isl_space *space);
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+ __isl_keep isl_space *space);
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_multi_templ.h>
+
+#endif
diff --git a/polly/lib/External/isl/isl_affine_hull.c b/polly/lib/External/isl/isl_affine_hull.c
new file mode 100644
index 00000000000..81352817071
--- /dev/null
+++ b/polly/lib/External/isl/isl_affine_hull.c
@@ -0,0 +1,1405 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl/lp.h>
+#include <isl/map.h>
+#include "isl_equalities.h"
+#include "isl_sample.h"
+#include "isl_tab.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+struct isl_basic_map *isl_basic_map_implicit_equalities(
+ struct isl_basic_map *bmap)
+{
+ struct isl_tab *tab;
+
+ if (!bmap)
+ return bmap;
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_IMPLICIT))
+ return bmap;
+ if (bmap->n_ineq <= 1)
+ return bmap;
+
+ tab = isl_tab_from_basic_map(bmap, 0);
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
+ goto error;
+ bmap = isl_basic_map_update_from_tab(bmap, tab);
+ isl_tab_free(tab);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+ return bmap;
+error:
+ isl_tab_free(tab);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_implicit_equalities(
+ struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_implicit_equalities((struct isl_basic_map*)bset);
+}
+
+struct isl_map *isl_map_implicit_equalities(struct isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return map;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_implicit_equalities(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Make eq[row][col] of both bmaps equal so we can add the row
+ * add the column to the common matrix.
+ * Note that because of the echelon form, the columns of row row
+ * after column col are zero.
+ */
+static void set_common_multiple(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+ unsigned row, unsigned col)
+{
+ isl_int m, c;
+
+ if (isl_int_eq(bset1->eq[row][col], bset2->eq[row][col]))
+ return;
+
+ isl_int_init(c);
+ isl_int_init(m);
+ isl_int_lcm(m, bset1->eq[row][col], bset2->eq[row][col]);
+ isl_int_divexact(c, m, bset1->eq[row][col]);
+ isl_seq_scale(bset1->eq[row], bset1->eq[row], c, col+1);
+ isl_int_divexact(c, m, bset2->eq[row][col]);
+ isl_seq_scale(bset2->eq[row], bset2->eq[row], c, col+1);
+ isl_int_clear(c);
+ isl_int_clear(m);
+}
+
+/* Delete a given equality, moving all the following equalities one up.
+ */
+static void delete_row(struct isl_basic_set *bset, unsigned row)
+{
+ isl_int *t;
+ int r;
+
+ t = bset->eq[row];
+ bset->n_eq--;
+ for (r = row; r < bset->n_eq; ++r)
+ bset->eq[r] = bset->eq[r+1];
+ bset->eq[bset->n_eq] = t;
+}
+
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using the fact that entry bset1->eq[row][col]=a
+ * is non-zero. Initially, these elements of bset1 are all zero.
+ * For each row i < row, we set
+ * A[i] = a * A[i] + B[i][col] * A[row]
+ * B[i] = a * B[i]
+ * so that
+ * A[i][col] = B[i][col] = a * old(B[i][col])
+ */
+static void construct_column(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+ unsigned row, unsigned col)
+{
+ int r;
+ isl_int a;
+ isl_int b;
+ unsigned total;
+
+ isl_int_init(a);
+ isl_int_init(b);
+ total = 1 + isl_basic_set_n_dim(bset1);
+ for (r = 0; r < row; ++r) {
+ if (isl_int_is_zero(bset2->eq[r][col]))
+ continue;
+ isl_int_gcd(b, bset2->eq[r][col], bset1->eq[row][col]);
+ isl_int_divexact(a, bset1->eq[row][col], b);
+ isl_int_divexact(b, bset2->eq[r][col], b);
+ isl_seq_combine(bset1->eq[r], a, bset1->eq[r],
+ b, bset1->eq[row], total);
+ isl_seq_scale(bset2->eq[r], bset2->eq[r], a, total);
+ }
+ isl_int_clear(a);
+ isl_int_clear(b);
+ delete_row(bset1, row);
+}
+
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using only these entries of the two matrices.
+ * Let t be the last row with different entries.
+ * For each row i < t, we set
+ * A[i] = (A[t][col]-B[t][col]) * A[i] + (B[i][col]-A[i][col) * A[t]
+ * B[i] = (A[t][col]-B[t][col]) * B[i] + (B[i][col]-A[i][col) * B[t]
+ * so that
+ * A[i][col] = B[i][col] = old(A[t][col]*B[i][col]-A[i][col]*B[t][col])
+ */
+static int transform_column(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+ unsigned row, unsigned col)
+{
+ int i, t;
+ isl_int a, b, g;
+ unsigned total;
+
+ for (t = row-1; t >= 0; --t)
+ if (isl_int_ne(bset1->eq[t][col], bset2->eq[t][col]))
+ break;
+ if (t < 0)
+ return 0;
+
+ total = 1 + isl_basic_set_n_dim(bset1);
+ isl_int_init(a);
+ isl_int_init(b);
+ isl_int_init(g);
+ isl_int_sub(b, bset1->eq[t][col], bset2->eq[t][col]);
+ for (i = 0; i < t; ++i) {
+ isl_int_sub(a, bset2->eq[i][col], bset1->eq[i][col]);
+ isl_int_gcd(g, a, b);
+ isl_int_divexact(a, a, g);
+ isl_int_divexact(g, b, g);
+ isl_seq_combine(bset1->eq[i], g, bset1->eq[i], a, bset1->eq[t],
+ total);
+ isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
+ total);
+ }
+ isl_int_clear(a);
+ isl_int_clear(b);
+ isl_int_clear(g);
+ delete_row(bset1, t);
+ delete_row(bset2, t);
+ return 1;
+}
+
+/* The implementation is based on Section 5.2 of Michael Karr,
+ * "Affine Relationships Among Variables of a Program",
+ * except that the echelon form we use starts from the last column
+ * and that we are dealing with integer coefficients.
+ */
+static struct isl_basic_set *affine_hull(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ unsigned total;
+ int col;
+ int row;
+
+ if (!bset1 || !bset2)
+ goto error;
+
+ total = 1 + isl_basic_set_n_dim(bset1);
+
+ row = 0;
+ for (col = total-1; col >= 0; --col) {
+ int is_zero1 = row >= bset1->n_eq ||
+ isl_int_is_zero(bset1->eq[row][col]);
+ int is_zero2 = row >= bset2->n_eq ||
+ isl_int_is_zero(bset2->eq[row][col]);
+ if (!is_zero1 && !is_zero2) {
+ set_common_multiple(bset1, bset2, row, col);
+ ++row;
+ } else if (!is_zero1 && is_zero2) {
+ construct_column(bset1, bset2, row, col);
+ } else if (is_zero1 && !is_zero2) {
+ construct_column(bset2, bset1, row, col);
+ } else {
+ if (transform_column(bset1, bset2, row, col))
+ --row;
+ }
+ }
+ isl_assert(bset1->ctx, row == bset1->n_eq, goto error);
+ isl_basic_set_free(bset2);
+ bset1 = isl_basic_set_normalize_constraints(bset1);
+ return bset1;
+error:
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+/* Find an integer point in the set represented by "tab"
+ * that lies outside of the equality "eq" e(x) = 0.
+ * If "up" is true, look for a point satisfying e(x) - 1 >= 0.
+ * Otherwise, look for a point satisfying -e(x) - 1 >= 0 (i.e., e(x) <= -1).
+ * The point, if found, is returned.
+ * If no point can be found, a zero-length vector is returned.
+ *
+ * Before solving an ILP problem, we first check if simply
+ * adding the normal of the constraint to one of the known
+ * integer points in the basic set represented by "tab"
+ * yields another point inside the basic set.
+ *
+ * The caller of this function ensures that the tableau is bounded or
+ * that tab->basis and tab->n_unbounded have been set appropriately.
+ */
+static struct isl_vec *outside_point(struct isl_tab *tab, isl_int *eq, int up)
+{
+ struct isl_ctx *ctx;
+ struct isl_vec *sample = NULL;
+ struct isl_tab_undo *snap;
+ unsigned dim;
+
+ if (!tab)
+ return NULL;
+ ctx = tab->mat->ctx;
+
+ dim = tab->n_var;
+ sample = isl_vec_alloc(ctx, 1 + dim);
+ if (!sample)
+ return NULL;
+ isl_int_set_si(sample->el[0], 1);
+ isl_seq_combine(sample->el + 1,
+ ctx->one, tab->bmap->sample->el + 1,
+ up ? ctx->one : ctx->negone, eq + 1, dim);
+ if (isl_basic_map_contains(tab->bmap, sample))
+ return sample;
+ isl_vec_free(sample);
+ sample = NULL;
+
+ snap = isl_tab_snap(tab);
+
+ if (!up)
+ isl_seq_neg(eq, eq, 1 + dim);
+ isl_int_sub_ui(eq[0], eq[0], 1);
+
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ goto error;
+ if (isl_tab_add_ineq(tab, eq) < 0)
+ goto error;
+
+ sample = isl_tab_sample(tab);
+
+ isl_int_add_ui(eq[0], eq[0], 1);
+ if (!up)
+ isl_seq_neg(eq, eq, 1 + dim);
+
+ if (sample && isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ return sample;
+error:
+ isl_vec_free(sample);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_recession_cone(struct isl_basic_set *bset)
+{
+ int i;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+ isl_assert(bset->ctx, bset->n_div == 0, goto error);
+
+ for (i = 0; i < bset->n_eq; ++i)
+ isl_int_set_si(bset->eq[i][0], 0);
+
+ for (i = 0; i < bset->n_ineq; ++i)
+ isl_int_set_si(bset->ineq[i][0], 0);
+
+ ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
+ return isl_basic_set_implicit_equalities(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_recession_cone(__isl_take isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return NULL;
+ if (set->n == 0)
+ return set;
+
+ set = isl_set_remove_divs(set);
+ set = isl_set_cow(set);
+ if (!set)
+ return NULL;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_recession_cone(set->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Move "sample" to a point that is one up (or down) from the original
+ * point in dimension "pos".
+ */
+static void adjacent_point(__isl_keep isl_vec *sample, int pos, int up)
+{
+ if (up)
+ isl_int_add_ui(sample->el[1 + pos], sample->el[1 + pos], 1);
+ else
+ isl_int_sub_ui(sample->el[1 + pos], sample->el[1 + pos], 1);
+}
+
+/* Check if any points that are adjacent to "sample" also belong to "bset".
+ * If so, add them to "hull" and return the updated hull.
+ *
+ * Before checking whether and adjacent point belongs to "bset", we first
+ * check whether it already belongs to "hull" as this test is typically
+ * much cheaper.
+ */
+static __isl_give isl_basic_set *add_adjacent_points(
+ __isl_take isl_basic_set *hull, __isl_take isl_vec *sample,
+ __isl_keep isl_basic_set *bset)
+{
+ int i, up;
+ int dim;
+
+ if (!sample)
+ goto error;
+
+ dim = isl_basic_set_dim(hull, isl_dim_set);
+
+ for (i = 0; i < dim; ++i) {
+ for (up = 0; up <= 1; ++up) {
+ int contains;
+ isl_basic_set *point;
+
+ adjacent_point(sample, i, up);
+ contains = isl_basic_set_contains(hull, sample);
+ if (contains < 0)
+ goto error;
+ if (contains) {
+ adjacent_point(sample, i, !up);
+ continue;
+ }
+ contains = isl_basic_set_contains(bset, sample);
+ if (contains < 0)
+ goto error;
+ if (contains) {
+ point = isl_basic_set_from_vec(
+ isl_vec_copy(sample));
+ hull = affine_hull(hull, point);
+ }
+ adjacent_point(sample, i, !up);
+ if (contains)
+ break;
+ }
+ }
+
+ isl_vec_free(sample);
+
+ return hull;
+error:
+ isl_vec_free(sample);
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Extend an initial (under-)approximation of the affine hull of basic
+ * set represented by the tableau "tab"
+ * by looking for points that do not satisfy one of the equalities
+ * in the current approximation and adding them to that approximation
+ * until no such points can be found any more.
+ *
+ * The caller of this function ensures that "tab" is bounded or
+ * that tab->basis and tab->n_unbounded have been set appropriately.
+ *
+ * "bset" may be either NULL or the basic set represented by "tab".
+ * If "bset" is not NULL, we check for any point we find if any
+ * of its adjacent points also belong to "bset".
+ */
+static __isl_give isl_basic_set *extend_affine_hull(struct isl_tab *tab,
+ __isl_take isl_basic_set *hull, __isl_keep isl_basic_set *bset)
+{
+ int i, j;
+ unsigned dim;
+
+ if (!tab || !hull)
+ goto error;
+
+ dim = tab->n_var;
+
+ if (isl_tab_extend_cons(tab, 2 * dim + 1) < 0)
+ goto error;
+
+ for (i = 0; i < dim; ++i) {
+ struct isl_vec *sample;
+ struct isl_basic_set *point;
+ for (j = 0; j < hull->n_eq; ++j) {
+ sample = outside_point(tab, hull->eq[j], 1);
+ if (!sample)
+ goto error;
+ if (sample->size > 0)
+ break;
+ isl_vec_free(sample);
+ sample = outside_point(tab, hull->eq[j], 0);
+ if (!sample)
+ goto error;
+ if (sample->size > 0)
+ break;
+ isl_vec_free(sample);
+
+ if (isl_tab_add_eq(tab, hull->eq[j]) < 0)
+ goto error;
+ }
+ if (j == hull->n_eq)
+ break;
+ if (tab->samples &&
+ isl_tab_add_sample(tab, isl_vec_copy(sample)) < 0)
+ hull = isl_basic_set_free(hull);
+ if (bset)
+ hull = add_adjacent_points(hull, isl_vec_copy(sample),
+ bset);
+ point = isl_basic_set_from_vec(sample);
+ hull = affine_hull(hull, point);
+ if (!hull)
+ return NULL;
+ }
+
+ return hull;
+error:
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Drop all constraints in bmap that involve any of the dimensions
+ * first to first+n-1.
+ */
+static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
+ __isl_take isl_basic_map *bmap, unsigned first, unsigned n)
+{
+ int i;
+
+ if (n == 0)
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+
+ if (!bmap)
+ return NULL;
+
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
+ continue;
+ isl_basic_map_drop_equality(bmap, i);
+ }
+
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
+ continue;
+ isl_basic_map_drop_inequality(bmap, i);
+ }
+
+ bmap = isl_basic_map_add_known_div_constraints(bmap);
+ return bmap;
+}
+
+/* Drop all constraints in bset that involve any of the dimensions
+ * first to first+n-1.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
+ __isl_take isl_basic_set *bset, unsigned first, unsigned n)
+{
+ return isl_basic_map_drop_constraints_involving(bset, first, n);
+}
+
+/* Drop all constraints in bmap that do not involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__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)
+{
+ int i;
+ unsigned dim;
+
+ if (n == 0) {
+ isl_space *space = isl_basic_map_get_space(bmap);
+ isl_basic_map_free(bmap);
+ return isl_basic_map_universe(space);
+ }
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ dim = isl_basic_map_dim(bmap, type);
+ if (first + n > dim || first + n < first)
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "index out of bounds", return isl_basic_map_free(bmap));
+
+ first += isl_basic_map_offset(bmap, type) - 1;
+
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
+ continue;
+ isl_basic_map_drop_equality(bmap, i);
+ }
+
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
+ continue;
+ isl_basic_map_drop_inequality(bmap, i);
+ }
+
+ bmap = isl_basic_map_add_known_div_constraints(bmap);
+ return bmap;
+}
+
+/* Drop all constraints in bset that do not involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_basic_map_drop_constraints_not_involving_dims(bset,
+ type, first, n);
+}
+
+/* Drop all constraints in bmap that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__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)
+{
+ unsigned dim;
+
+ if (!bmap)
+ return NULL;
+ if (n == 0)
+ return bmap;
+
+ dim = isl_basic_map_dim(bmap, type);
+ if (first + n > dim || first + n < first)
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "index out of bounds", return isl_basic_map_free(bmap));
+
+ bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
+ first += isl_basic_map_offset(bmap, type) - 1;
+ return isl_basic_map_drop_constraints_involving(bmap, first, n);
+}
+
+/* Drop all constraints in bset that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_basic_map_drop_constraints_involving_dims(bset,
+ type, first, n);
+}
+
+/* Drop all constraints in map that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_map *isl_map_drop_constraints_involving_dims(
+ __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ unsigned dim;
+
+ if (!map)
+ return NULL;
+ if (n == 0)
+ return map;
+
+ dim = isl_map_dim(map, type);
+ if (first + n > dim || first + n < first)
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "index out of bounds", 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_drop_constraints_involving_dims(
+ map->p[i], type, first, n);
+ if (!map->p[i])
+ return isl_map_free(map);
+ }
+
+ return map;
+}
+
+/* Drop all constraints in set that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_set *isl_set_drop_constraints_involving_dims(
+ __isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_map_drop_constraints_involving_dims(set, type, first, n);
+}
+
+/* Construct an initial underapproximatino of the hull of "bset"
+ * from "sample" and any of its adjacent points that also belong to "bset".
+ */
+static __isl_give isl_basic_set *initialize_hull(__isl_keep isl_basic_set *bset,
+ __isl_take isl_vec *sample)
+{
+ isl_basic_set *hull;
+
+ hull = isl_basic_set_from_vec(isl_vec_copy(sample));
+ hull = add_adjacent_points(hull, sample, bset);
+
+ return hull;
+}
+
+/* Look for all equalities satisfied by the integer points in bset,
+ * which is assumed to be bounded.
+ *
+ * The equalities are obtained by successively looking for
+ * a point that is affinely independent of the points found so far.
+ * In particular, for each equality satisfied by the points so far,
+ * we check if there is any point on a hyperplane parallel to the
+ * corresponding hyperplane shifted by at least one (in either direction).
+ */
+static struct isl_basic_set *uset_affine_hull_bounded(struct isl_basic_set *bset)
+{
+ struct isl_vec *sample = NULL;
+ struct isl_basic_set *hull;
+ struct isl_tab *tab = NULL;
+ unsigned dim;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return bset;
+
+ dim = isl_basic_set_n_dim(bset);
+
+ if (bset->sample && bset->sample->size == 1 + dim) {
+ int contains = isl_basic_set_contains(bset, bset->sample);
+ if (contains < 0)
+ goto error;
+ if (contains) {
+ if (dim == 0)
+ return bset;
+ sample = isl_vec_copy(bset->sample);
+ } else {
+ isl_vec_free(bset->sample);
+ bset->sample = NULL;
+ }
+ }
+
+ tab = isl_tab_from_basic_set(bset, 1);
+ if (!tab)
+ goto error;
+ if (tab->empty) {
+ isl_tab_free(tab);
+ isl_vec_free(sample);
+ return isl_basic_set_set_to_empty(bset);
+ }
+
+ if (!sample) {
+ struct isl_tab_undo *snap;
+ snap = isl_tab_snap(tab);
+ sample = isl_tab_sample(tab);
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+ isl_vec_free(tab->bmap->sample);
+ tab->bmap->sample = isl_vec_copy(sample);
+ }
+
+ if (!sample)
+ goto error;
+ if (sample->size == 0) {
+ isl_tab_free(tab);
+ isl_vec_free(sample);
+ return isl_basic_set_set_to_empty(bset);
+ }
+
+ hull = initialize_hull(bset, sample);
+
+ hull = extend_affine_hull(tab, hull, bset);
+ isl_basic_set_free(bset);
+ isl_tab_free(tab);
+
+ return hull;
+error:
+ isl_vec_free(sample);
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Given an unbounded tableau and an integer point satisfying the tableau,
+ * construct an initial affine hull containing the recession cone
+ * shifted to the given point.
+ *
+ * The unbounded directions are taken from the last rows of the basis,
+ * which is assumed to have been initialized appropriately.
+ */
+static __isl_give isl_basic_set *initial_hull(struct isl_tab *tab,
+ __isl_take isl_vec *vec)
+{
+ int i;
+ int k;
+ struct isl_basic_set *bset = NULL;
+ struct isl_ctx *ctx;
+ unsigned dim;
+
+ if (!vec || !tab)
+ return NULL;
+ ctx = vec->ctx;
+ isl_assert(ctx, vec->size != 0, goto error);
+
+ bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0);
+ if (!bset)
+ goto error;
+ dim = isl_basic_set_n_dim(bset) - tab->n_unbounded;
+ for (i = 0; i < dim; ++i) {
+ k = isl_basic_set_alloc_equality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->eq[k] + 1, tab->basis->row[1 + i] + 1,
+ vec->size - 1);
+ isl_seq_inner_product(bset->eq[k] + 1, vec->el +1,
+ vec->size - 1, &bset->eq[k][0]);
+ isl_int_neg(bset->eq[k][0], bset->eq[k][0]);
+ }
+ bset->sample = vec;
+ bset = isl_basic_set_gauss(bset, NULL);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+/* Given a tableau of a set and a tableau of the corresponding
+ * recession cone, detect and add all equalities to the tableau.
+ * If the tableau is bounded, then we can simply keep the
+ * tableau in its state after the return from extend_affine_hull.
+ * However, if the tableau is unbounded, then
+ * isl_tab_set_initial_basis_with_cone will add some additional
+ * constraints to the tableau that have to be removed again.
+ * In this case, we therefore rollback to the state before
+ * any constraints were added and then add the equalities back in.
+ */
+struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
+ struct isl_tab *tab_cone)
+{
+ int j;
+ struct isl_vec *sample;
+ struct isl_basic_set *hull = NULL;
+ struct isl_tab_undo *snap;
+
+ if (!tab || !tab_cone)
+ goto error;
+
+ snap = isl_tab_snap(tab);
+
+ isl_mat_free(tab->basis);
+ tab->basis = NULL;
+
+ isl_assert(tab->mat->ctx, tab->bmap, goto error);
+ isl_assert(tab->mat->ctx, tab->samples, goto error);
+ isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, goto error);
+ isl_assert(tab->mat->ctx, tab->n_sample > tab->n_outside, goto error);
+
+ if (isl_tab_set_initial_basis_with_cone(tab, tab_cone) < 0)
+ goto error;
+
+ sample = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+ if (!sample)
+ goto error;
+
+ isl_seq_cpy(sample->el, tab->samples->row[tab->n_outside], sample->size);
+
+ isl_vec_free(tab->bmap->sample);
+ tab->bmap->sample = isl_vec_copy(sample);
+
+ if (tab->n_unbounded == 0)
+ hull = isl_basic_set_from_vec(isl_vec_copy(sample));
+ else
+ hull = initial_hull(tab, isl_vec_copy(sample));
+
+ for (j = tab->n_outside + 1; j < tab->n_sample; ++j) {
+ isl_seq_cpy(sample->el, tab->samples->row[j], sample->size);
+ hull = affine_hull(hull,
+ isl_basic_set_from_vec(isl_vec_copy(sample)));
+ }
+
+ isl_vec_free(sample);
+
+ hull = extend_affine_hull(tab, hull, NULL);
+ if (!hull)
+ goto error;
+
+ if (tab->n_unbounded == 0) {
+ isl_basic_set_free(hull);
+ return tab;
+ }
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ if (hull->n_eq > tab->n_zero) {
+ for (j = 0; j < hull->n_eq; ++j) {
+ isl_seq_normalize(tab->mat->ctx, hull->eq[j], 1 + tab->n_var);
+ if (isl_tab_add_eq(tab, hull->eq[j]) < 0)
+ goto error;
+ }
+ }
+
+ isl_basic_set_free(hull);
+
+ return tab;
+error:
+ isl_basic_set_free(hull);
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Compute the affine hull of "bset", where "cone" is the recession cone
+ * of "bset".
+ *
+ * We first compute a unimodular transformation that puts the unbounded
+ * directions in the last dimensions. In particular, we take a transformation
+ * that maps all equalities to equalities (in HNF) on the first dimensions.
+ * Let x be the original dimensions and y the transformed, with y_1 bounded
+ * and y_2 unbounded.
+ *
+ * [ y_1 ] [ y_1 ] [ Q_1 ]
+ * x = U [ y_2 ] [ y_2 ] = [ Q_2 ] x
+ *
+ * Let's call the input basic set S. We compute S' = preimage(S, U)
+ * and drop the final dimensions including any constraints involving them.
+ * This results in set S''.
+ * Then we compute the affine hull A'' of S''.
+ * Let F y_1 >= g be the constraint system of A''. In the transformed
+ * space the y_2 are unbounded, so we can add them back without any constraints,
+ * resulting in
+ *
+ * [ y_1 ]
+ * [ F 0 ] [ y_2 ] >= g
+ * or
+ * [ Q_1 ]
+ * [ F 0 ] [ Q_2 ] x >= g
+ * or
+ * F Q_1 x >= g
+ *
+ * The affine hull in the original space is then obtained as
+ * A = preimage(A'', Q_1).
+ */
+static struct isl_basic_set *affine_hull_with_cone(struct isl_basic_set *bset,
+ struct isl_basic_set *cone)
+{
+ unsigned total;
+ unsigned cone_dim;
+ struct isl_basic_set *hull;
+ struct isl_mat *M, *U, *Q;
+
+ if (!bset || !cone)
+ goto error;
+
+ total = isl_basic_set_total_dim(cone);
+ cone_dim = total - cone->n_eq;
+
+ M = isl_mat_sub_alloc6(bset->ctx, cone->eq, 0, cone->n_eq, 1, total);
+ M = isl_mat_left_hermite(M, 0, &U, &Q);
+ if (!M)
+ goto error;
+ isl_mat_free(M);
+
+ U = isl_mat_lin_to_aff(U);
+ bset = isl_basic_set_preimage(bset, isl_mat_copy(U));
+
+ bset = isl_basic_set_drop_constraints_involving(bset, total - cone_dim,
+ cone_dim);
+ bset = isl_basic_set_drop_dims(bset, total - cone_dim, cone_dim);
+
+ Q = isl_mat_lin_to_aff(Q);
+ Q = isl_mat_drop_rows(Q, 1 + total - cone_dim, cone_dim);
+
+ if (bset && bset->sample && bset->sample->size == 1 + total)
+ bset->sample = isl_mat_vec_product(isl_mat_copy(Q), bset->sample);
+
+ hull = uset_affine_hull_bounded(bset);
+
+ if (!hull) {
+ isl_mat_free(Q);
+ isl_mat_free(U);
+ } else {
+ struct isl_vec *sample = isl_vec_copy(hull->sample);
+ U = isl_mat_drop_cols(U, 1 + total - cone_dim, cone_dim);
+ if (sample && sample->size > 0)
+ sample = isl_mat_vec_product(U, sample);
+ else
+ isl_mat_free(U);
+ hull = isl_basic_set_preimage(hull, Q);
+ if (hull) {
+ isl_vec_free(hull->sample);
+ hull->sample = sample;
+ } else
+ isl_vec_free(sample);
+ }
+
+ isl_basic_set_free(cone);
+
+ return hull;
+error:
+ isl_basic_set_free(bset);
+ isl_basic_set_free(cone);
+ return NULL;
+}
+
+/* Look for all equalities satisfied by the integer points in bset,
+ * which is assumed not to have any explicit equalities.
+ *
+ * The equalities are obtained by successively looking for
+ * a point that is affinely independent of the points found so far.
+ * In particular, for each equality satisfied by the points so far,
+ * we check if there is any point on a hyperplane parallel to the
+ * corresponding hyperplane shifted by at least one (in either direction).
+ *
+ * Before looking for any outside points, we first compute the recession
+ * cone. The directions of this recession cone will always be part
+ * of the affine hull, so there is no need for looking for any points
+ * in these directions.
+ * In particular, if the recession cone is full-dimensional, then
+ * the affine hull is simply the whole universe.
+ */
+static struct isl_basic_set *uset_affine_hull(struct isl_basic_set *bset)
+{
+ struct isl_basic_set *cone;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return bset;
+
+ cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
+ if (!cone)
+ goto error;
+ if (cone->n_eq == 0) {
+ struct isl_basic_set *hull;
+ isl_basic_set_free(cone);
+ hull = isl_basic_set_universe_like(bset);
+ isl_basic_set_free(bset);
+ return hull;
+ }
+
+ if (cone->n_eq < isl_basic_set_total_dim(cone))
+ return affine_hull_with_cone(bset, cone);
+
+ isl_basic_set_free(cone);
+ return uset_affine_hull_bounded(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Look for all equalities satisfied by the integer points in bmap
+ * that are independent of the equalities already explicitly available
+ * in bmap.
+ *
+ * We first remove all equalities already explicitly available,
+ * then look for additional equalities in the reduced space
+ * and then transform the result to the original space.
+ * The original equalities are _not_ added to this set. This is
+ * the responsibility of the calling function.
+ * The resulting basic set has all meaning about the dimensions removed.
+ * In particular, dimensions that correspond to existential variables
+ * in bmap and that are found to be fixed are not removed.
+ */
+static struct isl_basic_set *equalities_in_underlying_set(
+ struct isl_basic_map *bmap)
+{
+ struct isl_mat *T1 = NULL;
+ struct isl_mat *T2 = NULL;
+ struct isl_basic_set *bset = NULL;
+ struct isl_basic_set *hull = NULL;
+
+ bset = isl_basic_map_underlying_set(bmap);
+ if (!bset)
+ return NULL;
+ if (bset->n_eq)
+ bset = isl_basic_set_remove_equalities(bset, &T1, &T2);
+ if (!bset)
+ goto error;
+
+ hull = uset_affine_hull(bset);
+ if (!T2)
+ return hull;
+
+ if (!hull) {
+ isl_mat_free(T1);
+ isl_mat_free(T2);
+ } else {
+ struct isl_vec *sample = isl_vec_copy(hull->sample);
+ if (sample && sample->size > 0)
+ sample = isl_mat_vec_product(T1, sample);
+ else
+ isl_mat_free(T1);
+ hull = isl_basic_set_preimage(hull, T2);
+ if (hull) {
+ isl_vec_free(hull->sample);
+ hull->sample = sample;
+ } else
+ isl_vec_free(sample);
+ }
+
+ return hull;
+error:
+ isl_mat_free(T1);
+ isl_mat_free(T2);
+ isl_basic_set_free(bset);
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Detect and make explicit all equalities satisfied by the (integer)
+ * points in bmap.
+ */
+struct isl_basic_map *isl_basic_map_detect_equalities(
+ struct isl_basic_map *bmap)
+{
+ int i, j;
+ struct isl_basic_set *hull = NULL;
+
+ if (!bmap)
+ return NULL;
+ if (bmap->n_ineq == 0)
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_ALL_EQUALITIES))
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+ return isl_basic_map_implicit_equalities(bmap);
+
+ hull = equalities_in_underlying_set(isl_basic_map_copy(bmap));
+ if (!hull)
+ goto error;
+ if (ISL_F_ISSET(hull, ISL_BASIC_SET_EMPTY)) {
+ isl_basic_set_free(hull);
+ return isl_basic_map_set_to_empty(bmap);
+ }
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), 0,
+ hull->n_eq, 0);
+ for (i = 0; i < hull->n_eq; ++i) {
+ j = isl_basic_map_alloc_equality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_cpy(bmap->eq[j], hull->eq[i],
+ 1 + isl_basic_set_total_dim(hull));
+ }
+ isl_vec_free(bmap->sample);
+ bmap->sample = isl_vec_copy(hull->sample);
+ isl_basic_set_free(hull);
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT | ISL_BASIC_MAP_ALL_EQUALITIES);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_set_free(hull);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_detect_equalities(
+ __isl_take isl_basic_set *bset)
+{
+ return (isl_basic_set *)
+ isl_basic_map_detect_equalities((isl_basic_map *)bset);
+}
+
+__isl_give isl_map *isl_map_detect_equalities(__isl_take isl_map *map)
+{
+ return isl_map_inline_foreach_basic_map(map,
+ &isl_basic_map_detect_equalities);
+}
+
+__isl_give isl_set *isl_set_detect_equalities(__isl_take isl_set *set)
+{
+ return (isl_set *)isl_map_detect_equalities((isl_map *)set);
+}
+
+/* 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.
+ */
+struct isl_basic_map *isl_basic_map_affine_hull(struct isl_basic_map *bmap)
+{
+ bmap = isl_basic_map_detect_equalities(bmap);
+ bmap = isl_basic_map_cow(bmap);
+ if (bmap)
+ isl_basic_map_free_inequality(bmap, bmap->n_ineq);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_affine_hull(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_affine_hull((struct isl_basic_map *)bset);
+}
+
+/* Given a rational affine matrix "M", add stride constraints to "bmap"
+ * that ensure that
+ *
+ * M(x)
+ *
+ * is an integer vector. The variables x include all the variables
+ * of "bmap" except the unknown divs.
+ *
+ * If d is the common denominator of M, then we need to impose that
+ *
+ * d M(x) = 0 mod d
+ *
+ * or
+ *
+ * exists alpha : d M(x) = d alpha
+ *
+ * This function is similar to add_strides in isl_morph.c
+ */
+static __isl_give isl_basic_map *add_strides(__isl_take isl_basic_map *bmap,
+ __isl_keep isl_mat *M, int n_known)
+{
+ int i, div, k;
+ isl_int gcd;
+
+ if (isl_int_is_one(M->row[0][0]))
+ return bmap;
+
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+ M->n_row - 1, M->n_row - 1, 0);
+
+ isl_int_init(gcd);
+ for (i = 1; i < M->n_row; ++i) {
+ isl_seq_gcd(M->row[i], M->n_col, &gcd);
+ if (isl_int_is_divisible_by(gcd, M->row[0][0]))
+ continue;
+ div = isl_basic_map_alloc_div(bmap);
+ if (div < 0)
+ goto error;
+ isl_int_set_si(bmap->div[div][0], 0);
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->eq[k], M->row[i], M->n_col);
+ isl_seq_clr(bmap->eq[k] + M->n_col, bmap->n_div - n_known);
+ isl_int_set(bmap->eq[k][M->n_col - n_known + div],
+ M->row[0][0]);
+ }
+ isl_int_clear(gcd);
+
+ return bmap;
+error:
+ isl_int_clear(gcd);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* If there are any equalities that involve (multiple) unknown divs,
+ * then extract the stride information encoded by those equalities
+ * and make it explicitly available in "bmap".
+ *
+ * We first sort the divs so that the unknown divs appear last and
+ * then we count how many equalities involve these divs.
+ *
+ * Let these equalities be of the form
+ *
+ * A(x) + B y = 0
+ *
+ * where y represents the unknown divs and x the remaining variables.
+ * Let [H 0] be the Hermite Normal Form of B, i.e.,
+ *
+ * B = [H 0] Q
+ *
+ * Then x is a solution of the equalities iff
+ *
+ * H^-1 A(x) (= - [I 0] Q y)
+ *
+ * is an integer vector. Let d be the common denominator of H^-1.
+ * We impose
+ *
+ * d H^-1 A(x) = d alpha
+ *
+ * in add_strides, with alpha fresh existentially quantified variables.
+ */
+static __isl_give isl_basic_map *isl_basic_map_make_strides_explicit(
+ __isl_take isl_basic_map *bmap)
+{
+ int known;
+ int n_known;
+ int n, n_col;
+ int total;
+ isl_ctx *ctx;
+ isl_mat *A, *B, *M;
+
+ known = isl_basic_map_divs_known(bmap);
+ if (known < 0)
+ return isl_basic_map_free(bmap);
+ if (known)
+ return bmap;
+ bmap = isl_basic_map_sort_divs(bmap);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ if (!bmap)
+ return NULL;
+
+ for (n_known = 0; n_known < bmap->n_div; ++n_known)
+ if (isl_int_is_zero(bmap->div[n_known][0]))
+ break;
+ ctx = isl_basic_map_get_ctx(bmap);
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ for (n = 0; n < bmap->n_eq; ++n)
+ if (isl_seq_first_non_zero(bmap->eq[n] + 1 + total + n_known,
+ bmap->n_div - n_known) == -1)
+ break;
+ if (n == 0)
+ return bmap;
+ B = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 0, 1 + total + n_known);
+ n_col = bmap->n_div - n_known;
+ A = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 1 + total + n_known, n_col);
+ A = isl_mat_left_hermite(A, 0, NULL, NULL);
+ A = isl_mat_drop_cols(A, n, n_col - n);
+ A = isl_mat_lin_to_aff(A);
+ A = isl_mat_right_inverse(A);
+ B = isl_mat_insert_zero_rows(B, 0, 1);
+ B = isl_mat_set_element_si(B, 0, 0, 1);
+ M = isl_mat_product(A, B);
+ if (!M)
+ return isl_basic_map_free(bmap);
+ bmap = add_strides(bmap, M, n_known);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ isl_mat_free(M);
+
+ return bmap;
+}
+
+/* Compute the affine hull of each basic map in "map" separately
+ * and make all stride information explicit so that we can remove
+ * all unknown divs without losing this information.
+ * The result is also guaranteed to be gaussed.
+ *
+ * In simple cases where a div is determined by an equality,
+ * calling isl_basic_map_gauss is enough to make the stride information
+ * explicit, as it will derive an explicit representation for the div
+ * from the equality. If, however, the stride information
+ * is encoded through multiple unknown divs then we need to make
+ * some extra effort in isl_basic_map_make_strides_explicit.
+ */
+static __isl_give isl_map *isl_map_local_affine_hull(__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_affine_hull(map->p[i]);
+ map->p[i] = isl_basic_map_gauss(map->p[i], NULL);
+ map->p[i] = isl_basic_map_make_strides_explicit(map->p[i]);
+ if (!map->p[i])
+ return isl_map_free(map);
+ }
+
+ return map;
+}
+
+static __isl_give isl_set *isl_set_local_affine_hull(__isl_take isl_set *set)
+{
+ return isl_map_local_affine_hull(set);
+}
+
+/* Compute the affine hull of "map".
+ *
+ * We first compute the affine hull of each basic map separately.
+ * Then we align the divs and recompute the affine hulls of the basic
+ * maps since some of them may now have extra divs.
+ * In order to avoid performing parametric integer programming to
+ * compute explicit expressions for the divs, possible leading to
+ * an explosion in the number of basic maps, we first drop all unknown
+ * divs before aligning the divs. Note that isl_map_local_affine_hull tries
+ * to make sure that all stride information is explicitly available
+ * in terms of known divs. This involves calling isl_basic_set_gauss,
+ * which is also needed because affine_hull assumes its input has been gaussed,
+ * while isl_map_affine_hull may be called on input that has not been gaussed,
+ * in particular from initial_facet_constraint.
+ * Similarly, align_divs may reorder some divs so that we need to
+ * gauss the result again.
+ * Finally, we combine the individual affine hulls into a single
+ * affine hull.
+ */
+__isl_give isl_basic_map *isl_map_affine_hull(__isl_take isl_map *map)
+{
+ struct isl_basic_map *model = NULL;
+ struct isl_basic_map *hull = NULL;
+ struct isl_set *set;
+ isl_basic_set *bset;
+
+ map = isl_map_detect_equalities(map);
+ map = isl_map_local_affine_hull(map);
+ map = isl_map_remove_empty_parts(map);
+ map = isl_map_remove_unknown_divs(map);
+ map = isl_map_align_divs(map);
+
+ if (!map)
+ return NULL;
+
+ if (map->n == 0) {
+ hull = isl_basic_map_empty_like_map(map);
+ isl_map_free(map);
+ return hull;
+ }
+
+ model = isl_basic_map_copy(map->p[0]);
+ set = isl_map_underlying_set(map);
+ set = isl_set_cow(set);
+ set = isl_set_local_affine_hull(set);
+ if (!set)
+ goto error;
+
+ while (set->n > 1)
+ set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
+
+ bset = isl_basic_set_copy(set->p[0]);
+ hull = isl_basic_map_overlying_set(bset, model);
+ isl_set_free(set);
+ hull = isl_basic_map_simplify(hull);
+ return isl_basic_map_finalize(hull);
+error:
+ isl_basic_map_free(model);
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_basic_set *isl_set_affine_hull(struct isl_set *set)
+{
+ return (struct isl_basic_set *)
+ isl_map_affine_hull((struct isl_map *)set);
+}
diff --git a/polly/lib/External/isl/isl_arg.c b/polly/lib/External/isl/isl_arg.c
new file mode 100644
index 00000000000..fefb67d5c46
--- /dev/null
+++ b/polly/lib/External/isl/isl_arg.c
@@ -0,0 +1,1308 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isl/arg.h>
+#include <isl/ctx.h>
+
+static struct isl_arg help_arg[] = {
+ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
+};
+
+static void set_default_choice(struct isl_arg *arg, void *opt)
+{
+ *(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
+}
+
+static void set_default_flags(struct isl_arg *arg, void *opt)
+{
+ *(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;
+}
+
+static void set_default_bool(struct isl_arg *arg, void *opt)
+{
+ if (arg->offset == (size_t) -1)
+ return;
+ *(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
+}
+
+static void set_default_child(struct isl_arg *arg, void *opt)
+{
+ void *child;
+
+ if (arg->offset == (size_t) -1)
+ child = opt;
+ else {
+ child = calloc(1, arg->u.child.child->options_size);
+ *(void **)(((char *)opt) + arg->offset) = child;
+ }
+
+ if (child)
+ isl_args_set_defaults(arg->u.child.child, child);
+}
+
+static void set_default_user(struct isl_arg *arg, void *opt)
+{
+ arg->u.user.init(((char *)opt) + arg->offset);
+}
+
+static void set_default_int(struct isl_arg *arg, void *opt)
+{
+ *(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
+}
+
+static void set_default_long(struct isl_arg *arg, void *opt)
+{
+ *(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
+}
+
+static void set_default_ulong(struct isl_arg *arg, void *opt)
+{
+ *(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value;
+}
+
+static void set_default_str(struct isl_arg *arg, void *opt)
+{
+ const char *str = NULL;
+ if (arg->u.str.default_value)
+ str = strdup(arg->u.str.default_value);
+ *(const char **)(((char *)opt) + arg->offset) = str;
+}
+
+static void set_default_str_list(struct isl_arg *arg, void *opt)
+{
+ *(const char ***)(((char *) opt) + arg->offset) = NULL;
+ *(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
+}
+
+void isl_args_set_defaults(struct isl_args *args, void *opt)
+{
+ int i;
+
+ for (i = 0; args->args[i].type != isl_arg_end; ++i) {
+ switch (args->args[i].type) {
+ case isl_arg_choice:
+ set_default_choice(&args->args[i], opt);
+ break;
+ case isl_arg_flags:
+ set_default_flags(&args->args[i], opt);
+ break;
+ case isl_arg_bool:
+ set_default_bool(&args->args[i], opt);
+ break;
+ case isl_arg_child:
+ set_default_child(&args->args[i], opt);
+ break;
+ case isl_arg_user:
+ set_default_user(&args->args[i], opt);
+ break;
+ case isl_arg_int:
+ set_default_int(&args->args[i], opt);
+ break;
+ case isl_arg_long:
+ set_default_long(&args->args[i], opt);
+ break;
+ case isl_arg_ulong:
+ set_default_ulong(&args->args[i], opt);
+ break;
+ case isl_arg_arg:
+ case isl_arg_str:
+ set_default_str(&args->args[i], opt);
+ break;
+ case isl_arg_str_list:
+ set_default_str_list(&args->args[i], opt);
+ break;
+ case isl_arg_alias:
+ case isl_arg_footer:
+ case isl_arg_version:
+ case isl_arg_end:
+ break;
+ }
+ }
+}
+
+static void free_args(struct isl_arg *arg, void *opt);
+
+static void free_child(struct isl_arg *arg, void *opt)
+{
+ if (arg->offset == (size_t) -1)
+ free_args(arg->u.child.child->args, opt);
+ else
+ isl_args_free(arg->u.child.child,
+ *(void **)(((char *)opt) + arg->offset));
+}
+
+static void free_str_list(struct isl_arg *arg, void *opt)
+{
+ int i;
+ int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
+ char **list = *(char ***)(((char *) opt) + arg->offset);
+
+ for (i = 0; i < n; ++i)
+ free(list[i]);
+ free(list);
+}
+
+static void free_user(struct isl_arg *arg, void *opt)
+{
+ if (arg->u.user.clear)
+ arg->u.user.clear(((char *)opt) + arg->offset);
+}
+
+static void free_args(struct isl_arg *arg, void *opt)
+{
+ int i;
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i) {
+ switch (arg[i].type) {
+ case isl_arg_child:
+ free_child(&arg[i], opt);
+ break;
+ case isl_arg_arg:
+ case isl_arg_str:
+ free(*(char **)(((char *)opt) + arg[i].offset));
+ break;
+ case isl_arg_str_list:
+ free_str_list(&arg[i], opt);
+ break;
+ case isl_arg_user:
+ free_user(&arg[i], opt);
+ break;
+ case isl_arg_alias:
+ case isl_arg_bool:
+ case isl_arg_choice:
+ case isl_arg_flags:
+ case isl_arg_int:
+ case isl_arg_long:
+ case isl_arg_ulong:
+ case isl_arg_version:
+ case isl_arg_footer:
+ case isl_arg_end:
+ break;
+ }
+ }
+}
+
+void isl_args_free(struct isl_args *args, void *opt)
+{
+ if (!opt)
+ return;
+
+ free_args(args->args, opt);
+
+ free(opt);
+}
+
+/* Data structure for collecting the prefixes of ancestor nodes.
+ *
+ * n is the number of prefixes.
+ * prefix[i] for i < n is a prefix of an ancestor.
+ * len[i] for i < n is the length of prefix[i].
+ */
+struct isl_prefixes {
+ int n;
+ const char *prefix[10];
+ size_t len[10];
+};
+
+/* Add "prefix" to the list of prefixes and return the updated
+ * number of prefixes.
+ */
+static int add_prefix(struct isl_prefixes *prefixes, const char *prefix)
+{
+ int n = prefixes->n;
+
+ if (!prefix)
+ return n;
+
+ if (prefixes->n >= 10) {
+ fprintf(stderr, "too many prefixes\n");
+ exit(EXIT_FAILURE);
+ }
+ prefixes->len[prefixes->n] = strlen(prefix);
+ prefixes->prefix[prefixes->n] = prefix;
+ prefixes->n++;
+
+ return n;
+}
+
+/* Drop all prefixes starting at "first".
+ */
+static void drop_prefix(struct isl_prefixes *prefixes, int first)
+{
+ prefixes->n = first;
+}
+
+/* Print the prefixes in "prefixes".
+ */
+static int print_prefixes(struct isl_prefixes *prefixes)
+{
+ int i;
+ int len = 0;
+
+ if (!prefixes)
+ return 0;
+
+ for (i = 0; i < prefixes->n; ++i) {
+ printf("%s-", prefixes->prefix[i]);
+ len += strlen(prefixes->prefix[i]) + 1;
+ }
+
+ return len;
+}
+
+/* Check if "name" starts with one or more of the prefixes in "prefixes",
+ * starting at *first. If so, advance the pointer beyond the prefixes
+ * and return the updated pointer. Additionally, update *first to
+ * the index after the last prefix found.
+ */
+static const char *skip_prefixes(const char *name,
+ struct isl_prefixes *prefixes, int *first)
+{
+ int i;
+
+ for (i = first ? *first : 0; i < prefixes->n; ++i) {
+ size_t len = prefixes->len[i];
+ const char *prefix = prefixes->prefix[i];
+ if (strncmp(name, prefix, len) == 0 && name[len] == '-') {
+ name += len + 1;
+ if (first)
+ *first = i + 1;
+ }
+ }
+
+ return name;
+}
+
+static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes,
+ int no)
+{
+ int len = 0;
+
+ if (!decl->long_name) {
+ printf(" -%c", decl->short_name);
+ return 4;
+ }
+
+ if (decl->short_name) {
+ printf(" -%c, --", decl->short_name);
+ len += 8;
+ } else if (decl->flags & ISL_ARG_SINGLE_DASH) {
+ printf(" -");
+ len += 3;
+ } else {
+ printf(" --");
+ len += 8;
+ }
+
+ if (no) {
+ printf("no-");
+ len += 3;
+ }
+ len += print_prefixes(prefixes);
+ printf("%s", decl->long_name);
+ len += strlen(decl->long_name);
+
+ while ((++decl)->type == isl_arg_alias) {
+ printf(", --");
+ len += 4;
+ if (no) {
+ printf("no-");
+ len += 3;
+ }
+ printf("%s", decl->long_name);
+ len += strlen(decl->long_name);
+ }
+
+ return len;
+}
+
+const void *isl_memrchr(const void *s, int c, size_t n)
+{
+ const char *p = s;
+ while (n-- > 0)
+ if (p[n] == c)
+ return p + n;
+ return NULL;
+}
+
+static int wrap_msg(const char *s, int indent, int pos)
+{
+ int len;
+ int wrap_len = 75 - indent;
+
+ if (pos + 1 >= indent)
+ printf("\n%*s", indent, "");
+ else
+ printf("%*s", indent - pos, "");
+
+ len = strlen(s);
+ while (len > wrap_len) {
+ const char *space = isl_memrchr(s, ' ', wrap_len);
+ int l;
+
+ if (!space)
+ space = strchr(s + wrap_len, ' ');
+ if (!space)
+ break;
+ l = space - s;
+ printf("%.*s", l, s);
+ s = space + 1;
+ len -= l + 1;
+ printf("\n%*s", indent, "");
+ }
+
+ printf("%s", s);
+ return len;
+}
+
+static int print_help_msg(struct isl_arg *decl, int pos)
+{
+ if (!decl->help_msg)
+ return pos;
+
+ return wrap_msg(decl->help_msg, 30, pos);
+}
+
+static void print_default(struct isl_arg *decl, const char *def, int pos)
+{
+ const char *default_prefix = "[default: ";
+ const char *default_suffix = "]";
+ int len;
+
+ len = strlen(default_prefix) + strlen(def) + strlen(default_suffix);
+
+ if (!decl->help_msg) {
+ if (pos >= 29)
+ printf("\n%30s", "");
+ else
+ printf("%*s", 30 - pos, "");
+ pos = 0;
+ } else {
+ if (pos + len >= 48)
+ printf("\n%30s", "");
+ else
+ printf(" ");
+ }
+ printf("%s%s%s", default_prefix, def, default_suffix);
+}
+
+static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
+{
+ int i;
+ const char *s = "none";
+ unsigned *p;
+
+ p = (unsigned *)(((char *) opt) + decl->offset);
+ for (i = 0; decl->u.choice.choice[i].name; ++i)
+ if (decl->u.choice.choice[i].value == *p) {
+ s = decl->u.choice.choice[i].name;
+ break;
+ }
+
+ print_default(decl, s, pos);
+}
+
+static void print_choice_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int i;
+ int pos;
+
+ pos = print_arg_help(decl, prefixes, 0);
+ printf("=");
+ pos++;
+
+ for (i = 0; decl->u.choice.choice[i].name; ++i) {
+ if (i) {
+ printf("|");
+ pos++;
+ }
+ printf("%s", decl->u.choice.choice[i].name);
+ pos += strlen(decl->u.choice.choice[i].name);
+ }
+
+ pos = print_help_msg(decl, pos);
+ print_default_choice(decl, opt, pos);
+
+ printf("\n");
+}
+
+static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
+{
+ int i, first;
+ const char *default_prefix = "[default: ";
+ const char *default_suffix = "]";
+ int len = strlen(default_prefix) + strlen(default_suffix);
+ unsigned *p;
+
+ p = (unsigned *)(((char *) opt) + decl->offset);
+ for (i = 0; decl->u.flags.flags[i].name; ++i)
+ if ((*p & decl->u.flags.flags[i].mask) ==
+ decl->u.flags.flags[i].value)
+ len += strlen(decl->u.flags.flags[i].name);
+
+ if (!decl->help_msg) {
+ if (pos >= 29)
+ printf("\n%30s", "");
+ else
+ printf("%*s", 30 - pos, "");
+ pos = 0;
+ } else {
+ if (pos + len >= 48)
+ printf("\n%30s", "");
+ else
+ printf(" ");
+ }
+ printf("%s", default_prefix);
+
+ for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
+ if ((*p & decl->u.flags.flags[i].mask) ==
+ decl->u.flags.flags[i].value) {
+ if (!first)
+ printf(",");
+ printf("%s", decl->u.flags.flags[i].name);
+ first = 0;
+ }
+
+ printf("%s", default_suffix);
+}
+
+static void print_flags_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int i, j;
+ int pos;
+
+ pos = print_arg_help(decl, prefixes, 0);
+ printf("=");
+ pos++;
+
+ for (i = 0; decl->u.flags.flags[i].name; ++i) {
+ if (i) {
+ printf(",");
+ pos++;
+ }
+ for (j = i;
+ decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask;
+ ++j) {
+ if (j != i) {
+ printf("|");
+ pos++;
+ }
+ printf("%s", decl->u.flags.flags[j].name);
+ pos += strlen(decl->u.flags.flags[j].name);
+ }
+ i = j - 1;
+ }
+
+ pos = print_help_msg(decl, pos);
+ print_default_flags(decl, opt, pos);
+
+ printf("\n");
+}
+
+static void print_bool_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int pos;
+ unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
+ int no = p ? *p == 1 : 0;
+ pos = print_arg_help(decl, prefixes, no);
+ pos = print_help_msg(decl, pos);
+ if (decl->offset != (size_t) -1)
+ print_default(decl, no ? "yes" : "no", pos);
+ printf("\n");
+}
+
+static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
+{
+ printf("%c<%s>", decl->long_name ? '=' : ' ', name);
+ return pos + 3 + strlen(name);
+}
+
+static void print_int_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int pos;
+ char val[20];
+ int *p = (int *)(((char *) opt) + decl->offset);
+ pos = print_arg_help(decl, prefixes, 0);
+ pos = print_argument_name(decl, decl->argument_name, pos);
+ pos = print_help_msg(decl, pos);
+ snprintf(val, sizeof(val), "%d", *p);
+ print_default(decl, val, pos);
+ printf("\n");
+}
+
+static void print_long_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int pos;
+ long *p = (long *)(((char *) opt) + decl->offset);
+ pos = print_arg_help(decl, prefixes, 0);
+ if (*p != decl->u.l.default_selected) {
+ printf("[");
+ pos++;
+ }
+ printf("=long");
+ pos += 5;
+ if (*p != decl->u.l.default_selected) {
+ printf("]");
+ pos++;
+ }
+ print_help_msg(decl, pos);
+ printf("\n");
+}
+
+static void print_ulong_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes)
+{
+ int pos;
+ pos = print_arg_help(decl, prefixes, 0);
+ printf("=ulong");
+ pos += 6;
+ print_help_msg(decl, pos);
+ printf("\n");
+}
+
+static void print_str_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int pos;
+ const char *a = decl->argument_name ? decl->argument_name : "string";
+ const char **p = (const char **)(((char *) opt) + decl->offset);
+ pos = print_arg_help(decl, prefixes, 0);
+ pos = print_argument_name(decl, a, pos);
+ pos = print_help_msg(decl, pos);
+ if (*p)
+ print_default(decl, *p, pos);
+ printf("\n");
+}
+
+static void print_str_list_help(struct isl_arg *decl,
+ struct isl_prefixes *prefixes)
+{
+ int pos;
+ const char *a = decl->argument_name ? decl->argument_name : "string";
+ pos = print_arg_help(decl, prefixes, 0);
+ pos = print_argument_name(decl, a, pos);
+ pos = print_help_msg(decl, pos);
+ printf("\n");
+}
+
+static void print_help(struct isl_arg *arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int i;
+ int any = 0;
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i) {
+ if (arg[i].flags & ISL_ARG_HIDDEN)
+ continue;
+ switch (arg[i].type) {
+ case isl_arg_flags:
+ print_flags_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_choice:
+ print_choice_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_bool:
+ print_bool_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_int:
+ print_int_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_long:
+ print_long_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_ulong:
+ print_ulong_help(&arg[i], prefixes);
+ any = 1;
+ break;
+ case isl_arg_str:
+ print_str_help(&arg[i], prefixes, opt);
+ any = 1;
+ break;
+ case isl_arg_str_list:
+ print_str_list_help(&arg[i], prefixes);
+ any = 1;
+ break;
+ case isl_arg_alias:
+ case isl_arg_version:
+ case isl_arg_arg:
+ case isl_arg_footer:
+ case isl_arg_child:
+ case isl_arg_user:
+ case isl_arg_end:
+ break;
+ }
+ }
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i) {
+ void *child;
+ int first;
+
+ if (arg[i].type != isl_arg_child)
+ continue;
+ if (arg[i].flags & ISL_ARG_HIDDEN)
+ continue;
+
+ if (any)
+ printf("\n");
+ if (arg[i].help_msg)
+ printf(" %s\n", arg[i].help_msg);
+ if (arg[i].offset == (size_t) -1)
+ child = opt;
+ else
+ child = *(void **)(((char *) opt) + arg[i].offset);
+ first = add_prefix(prefixes, arg[i].long_name);
+ print_help(arg[i].u.child.child->args, prefixes, child);
+ drop_prefix(prefixes, first);
+ any = 1;
+ }
+}
+
+static const char *prog_name(const char *prog)
+{
+ const char *slash;
+
+ slash = strrchr(prog, '/');
+ if (slash)
+ prog = slash + 1;
+ if (strncmp(prog, "lt-", 3) == 0)
+ prog += 3;
+
+ return prog;
+}
+
+static int any_version(struct isl_arg *decl)
+{
+ int i;
+
+ for (i = 0; decl[i].type != isl_arg_end; ++i) {
+ switch (decl[i].type) {
+ case isl_arg_version:
+ return 1;
+ case isl_arg_child:
+ if (any_version(decl[i].u.child.child->args))
+ return 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void print_help_and_exit(struct isl_arg *arg, const char *prog,
+ void *opt)
+{
+ int i;
+ struct isl_prefixes prefixes = { 0 };
+
+ printf("Usage: %s [OPTION...]", prog_name(prog));
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i)
+ if (arg[i].type == isl_arg_arg)
+ printf(" %s", arg[i].argument_name);
+
+ printf("\n\n");
+
+ print_help(arg, &prefixes, opt);
+ printf("\n");
+ if (any_version(arg))
+ printf(" -V, --version\n");
+ print_bool_help(help_arg, NULL, NULL);
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i) {
+ if (arg[i].type != isl_arg_footer)
+ continue;
+ wrap_msg(arg[i].help_msg, 0, 0);
+ printf("\n");
+ }
+
+ exit(0);
+}
+
+static int match_long_name(struct isl_arg *decl,
+ const char *start, const char *end)
+{
+ do {
+ if (end - start == strlen(decl->long_name) &&
+ !strncmp(start, decl->long_name, end - start))
+ return 1;
+ } while ((++decl)->type == isl_arg_alias);
+
+ return 0;
+}
+
+static const char *skip_dash_dash(struct isl_arg *decl, const char *arg)
+{
+ if (!strncmp(arg, "--", 2))
+ return arg + 2;
+ if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-')
+ return arg + 1;
+ return NULL;
+}
+
+static const char *skip_name(struct isl_arg *decl, const char *arg,
+ struct isl_prefixes *prefixes, int need_argument, int *has_argument)
+{
+ const char *equal;
+ const char *name;
+ const char *end;
+
+ if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) {
+ if (need_argument && !arg[2])
+ return NULL;
+ if (has_argument)
+ *has_argument = arg[2] != '\0';
+ return arg + 2;
+ }
+ if (!decl->long_name)
+ return NULL;
+
+ name = skip_dash_dash(decl, arg);
+ if (!name)
+ return NULL;
+
+ equal = strchr(name, '=');
+ if (need_argument && !equal)
+ return NULL;
+
+ if (has_argument)
+ *has_argument = !!equal;
+ end = equal ? equal : name + strlen(name);
+
+ name = skip_prefixes(name, prefixes, NULL);
+
+ if (!match_long_name(decl, name, end))
+ return NULL;
+
+ return equal ? equal + 1 : end;
+}
+
+static int parse_choice_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int i;
+ int has_argument;
+ const char *choice;
+
+ choice = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!choice)
+ return 0;
+
+ if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
+ unsigned u = decl->u.choice.default_selected;
+ *(unsigned *)(((char *)opt) + decl->offset) = u;
+ if (decl->u.choice.set)
+ decl->u.choice.set(opt, u);
+
+ return 1;
+ }
+
+ if (!has_argument)
+ choice = arg[1];
+
+ for (i = 0; decl->u.choice.choice[i].name; ++i) {
+ unsigned u;
+
+ if (strcmp(choice, decl->u.choice.choice[i].name))
+ continue;
+
+ u = decl->u.choice.choice[i].value;
+ *(unsigned *)(((char *)opt) + decl->offset) = u;
+ if (decl->u.choice.set)
+ decl->u.choice.set(opt, u);
+
+ return has_argument ? 1 : 2;
+ }
+
+ return 0;
+}
+
+static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag,
+ size_t len)
+{
+ int i;
+
+ for (i = 0; decl->u.flags.flags[i].name; ++i) {
+ if (strncmp(flag, decl->u.flags.flags[i].name, len))
+ continue;
+
+ *val &= ~decl->u.flags.flags[i].mask;
+ *val |= decl->u.flags.flags[i].value;
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_flags_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *flags;
+ const char *comma;
+ unsigned val;
+
+ flags = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!flags)
+ return 0;
+
+ if (!has_argument && !arg[1])
+ return 0;
+
+ if (!has_argument)
+ flags = arg[1];
+
+ val = 0;
+
+ while ((comma = strchr(flags, ',')) != NULL) {
+ if (!set_flag(decl, &val, flags, comma - flags))
+ return 0;
+ flags = comma + 1;
+ }
+ if (!set_flag(decl, &val, flags, strlen(flags)))
+ return 0;
+
+ *(unsigned *)(((char *)opt) + decl->offset) = val;
+
+ return has_argument ? 1 : 2;
+}
+
+static int parse_bool_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ const char *name;
+ unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
+ int next_prefix;
+
+ if (skip_name(decl, arg[0], prefixes, 0, NULL)) {
+ if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
+ char *endptr;
+ int val = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0' && (val == 0 || val == 1)) {
+ if (decl->offset != (size_t) -1)
+ *p = val;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, val);
+ return 2;
+ }
+ }
+ if (decl->offset != (size_t) -1)
+ *p = 1;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, 1);
+
+ return 1;
+ }
+
+ if (!decl->long_name)
+ return 0;
+
+ name = skip_dash_dash(decl, arg[0]);
+ if (!name)
+ return 0;
+
+ next_prefix = 0;
+ name = skip_prefixes(name, prefixes, &next_prefix);
+
+ if (strncmp(name, "no-", 3))
+ return 0;
+ name += 3;
+
+ name = skip_prefixes(name, prefixes, &next_prefix);
+
+ if (match_long_name(decl, name, name + strlen(name))) {
+ if (decl->offset != (size_t) -1)
+ *p = 0;
+ if (decl->u.b.set)
+ decl->u.b.set(opt, 0);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_str_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *s;
+ char **p = (char **)(((char *)opt) + decl->offset);
+
+ s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!s)
+ return 0;
+
+ if (has_argument) {
+ free(*p);
+ *p = strdup(s);
+ return 1;
+ }
+
+ if (arg[1]) {
+ free(*p);
+ *p = strdup(arg[1]);
+ return 2;
+ }
+
+ return 0;
+}
+
+static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
+ const char *s)
+{
+ int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
+ char **list = *(char ***)(((char *) opt) + decl->offset);
+
+ list = realloc(list, (*n + 1) * sizeof(char *));
+ if (!list)
+ return -1;
+ *(char ***)(((char *) opt) + decl->offset) = list;
+ list[*n] = strdup(s);
+ (*n)++;
+ return 0;
+}
+
+static int parse_str_list_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *s;
+
+ s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!s)
+ return 0;
+
+ if (has_argument) {
+ isl_arg_str_list_append(decl, opt, s);
+ return 1;
+ }
+
+ if (arg[1]) {
+ isl_arg_str_list_append(decl, opt, arg[1]);
+ return 2;
+ }
+
+ return 0;
+}
+
+static int parse_int_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ int *p = (int *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ *p = atoi(val);
+ return 1;
+ }
+
+ if (arg[1]) {
+ int i = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = i;
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_long_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ long *p = (long *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ long l = strtol(val, NULL, 0);
+ *p = l;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, l);
+ return 1;
+ }
+
+ if (arg[1]) {
+ long l = strtol(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = l;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, l);
+ return 2;
+ }
+ }
+
+ if (decl->u.l.default_value != decl->u.l.default_selected) {
+ *p = decl->u.l.default_selected;
+ if (decl->u.l.set)
+ decl->u.l.set(opt, decl->u.l.default_selected);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int parse_ulong_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int has_argument;
+ const char *val;
+ char *endptr;
+ unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
+
+ val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+ if (!val)
+ return 0;
+
+ if (has_argument) {
+ *p = strtoul(val, NULL, 0);
+ return 1;
+ }
+
+ if (arg[1]) {
+ unsigned long ul = strtoul(arg[1], &endptr, 0);
+ if (*endptr == '\0') {
+ *p = ul;
+ return 2;
+ }
+ }
+
+ return 0;
+}
+
+static int parse_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt);
+
+static int parse_child_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ void *child;
+ int first, parsed;
+
+ if (decl->offset == (size_t) -1)
+ child = opt;
+ else
+ child = *(void **)(((char *)opt) + decl->offset);
+
+ first = add_prefix(prefixes, decl->long_name);
+ parsed = parse_option(decl->u.child.child->args, arg, prefixes, child);
+ drop_prefix(prefixes, first);
+
+ return parsed;
+}
+
+static int parse_option(struct isl_arg *decl, char **arg,
+ struct isl_prefixes *prefixes, void *opt)
+{
+ int i;
+
+ for (i = 0; decl[i].type != isl_arg_end; ++i) {
+ int parsed = 0;
+ switch (decl[i].type) {
+ case isl_arg_choice:
+ parsed = parse_choice_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_flags:
+ parsed = parse_flags_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_int:
+ parsed = parse_int_option(&decl[i], arg, prefixes, opt);
+ break;
+ case isl_arg_long:
+ parsed = parse_long_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_ulong:
+ parsed = parse_ulong_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_bool:
+ parsed = parse_bool_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_str:
+ parsed = parse_str_option(&decl[i], arg, prefixes, opt);
+ break;
+ case isl_arg_str_list:
+ parsed = parse_str_list_option(&decl[i], arg, prefixes,
+ opt);
+ break;
+ case isl_arg_child:
+ parsed = parse_child_option(&decl[i], arg,
+ prefixes, opt);
+ break;
+ case isl_arg_alias:
+ case isl_arg_arg:
+ case isl_arg_footer:
+ case isl_arg_user:
+ case isl_arg_version:
+ case isl_arg_end:
+ break;
+ }
+ if (parsed)
+ return parsed;
+ }
+
+ return 0;
+}
+
+static void print_version(struct isl_arg *decl)
+{
+ int i;
+
+ for (i = 0; decl[i].type != isl_arg_end; ++i) {
+ switch (decl[i].type) {
+ case isl_arg_version:
+ decl[i].u.version.print_version();
+ break;
+ case isl_arg_child:
+ print_version(decl[i].u.child.child->args);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void print_version_and_exit(struct isl_arg *decl)
+{
+ print_version(decl);
+
+ exit(0);
+}
+
+static int drop_argument(int argc, char **argv, int drop, int n)
+{
+ for (; drop + n < argc; ++drop)
+ argv[drop] = argv[drop + n];
+
+ return argc - n;
+}
+
+static int n_arg(struct isl_arg *arg)
+{
+ int i;
+ int n_arg = 0;
+
+ for (i = 0; arg[i].type != isl_arg_end; ++i)
+ if (arg[i].type == isl_arg_arg)
+ n_arg++;
+
+ return n_arg;
+}
+
+static int next_arg(struct isl_arg *arg, int a)
+{
+ for (++a; arg[a].type != isl_arg_end; ++a)
+ if (arg[a].type == isl_arg_arg)
+ return a;
+
+ return -1;
+}
+
+/* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
+ * equal to "--help" and if so call print_help_and_exit.
+ */
+static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
+ unsigned flags)
+{
+ if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
+ return;
+
+ if (strcmp(arg, "--help") == 0)
+ print_help_and_exit(args->args, prog, opt);
+}
+
+int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
+ unsigned flags)
+{
+ int a = -1;
+ int skip = 0;
+ int i;
+ int n;
+ struct isl_prefixes prefixes = { 0 };
+
+ n = n_arg(args->args);
+
+ for (i = 1; i < argc; ++i) {
+ if ((strcmp(argv[i], "--version") == 0 ||
+ strcmp(argv[i], "-V") == 0) && any_version(args->args))
+ print_version_and_exit(args->args);
+ }
+
+ while (argc > 1 + skip) {
+ int parsed;
+ if (argv[1 + skip][0] != '-') {
+ a = next_arg(args->args, a);
+ if (a >= 0) {
+ char **p;
+ p = (char **)(((char *)opt)+args->args[a].offset);
+ free(*p);
+ *p = strdup(argv[1 + skip]);
+ argc = drop_argument(argc, argv, 1 + skip, 1);
+ --n;
+ } else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
+ fprintf(stderr, "%s: extra argument: %s\n",
+ prog_name(argv[0]), argv[1 + skip]);
+ exit(-1);
+ } else
+ ++skip;
+ continue;
+ }
+ check_help(args, argv[1 + skip], argv[0], opt, flags);
+ parsed = parse_option(args->args, &argv[1 + skip],
+ &prefixes, opt);
+ if (parsed)
+ argc = drop_argument(argc, argv, 1 + skip, parsed);
+ else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
+ fprintf(stderr, "%s: unrecognized option: %s\n",
+ prog_name(argv[0]), argv[1 + skip]);
+ exit(-1);
+ } else
+ ++skip;
+ }
+
+ if (n > 0) {
+ fprintf(stderr, "%s: expecting %d more argument(s)\n",
+ prog_name(argv[0]), n);
+ exit(-1);
+ }
+
+ return argc;
+}
diff --git a/polly/lib/External/isl/isl_ast.c b/polly/lib/External/isl/isl_ast.c
new file mode 100644
index 00000000000..0d77162cbc9
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast.c
@@ -0,0 +1,2069 @@
+/*
+ * Copyright 2012-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_ast_private.h>
+
+#undef BASE
+#define BASE ast_expr
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_node
+
+#include <isl_list_templ.c>
+
+isl_ctx *isl_ast_print_options_get_ctx(
+ __isl_keep isl_ast_print_options *options)
+{
+ return options ? options->ctx : NULL;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)
+{
+ isl_ast_print_options *options;
+
+ options = isl_calloc_type(ctx, isl_ast_print_options);
+ if (!options)
+ return NULL;
+
+ options->ctx = ctx;
+ isl_ctx_ref(ctx);
+ options->ref = 1;
+
+ return options;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_dup(
+ __isl_keep isl_ast_print_options *options)
+{
+ isl_ctx *ctx;
+ isl_ast_print_options *dup;
+
+ if (!options)
+ return NULL;
+
+ ctx = isl_ast_print_options_get_ctx(options);
+ dup = isl_ast_print_options_alloc(ctx);
+ if (!dup)
+ return NULL;
+
+ dup->print_for = options->print_for;
+ dup->print_for_user = options->print_for_user;
+ dup->print_user = options->print_user;
+ dup->print_user_user = options->print_user_user;
+
+ return dup;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_cow(
+ __isl_take isl_ast_print_options *options)
+{
+ if (!options)
+ return NULL;
+
+ if (options->ref == 1)
+ return options;
+ options->ref--;
+ return isl_ast_print_options_dup(options);
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_copy(
+ __isl_keep isl_ast_print_options *options)
+{
+ if (!options)
+ return NULL;
+
+ options->ref++;
+ return options;
+}
+
+__isl_null isl_ast_print_options *isl_ast_print_options_free(
+ __isl_take isl_ast_print_options *options)
+{
+ if (!options)
+ return NULL;
+
+ if (--options->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(options->ctx);
+
+ free(options);
+ return NULL;
+}
+
+/* Set the print_user callback of "options" to "print_user".
+ *
+ * If this callback is set, then it used to print user nodes in the AST.
+ * Otherwise, the expression associated to the user node is printed.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user)
+{
+ options = isl_ast_print_options_cow(options);
+ if (!options)
+ return NULL;
+
+ options->print_user = print_user;
+ options->print_user_user = user;
+
+ return options;
+}
+
+/* Set the print_for callback of "options" to "print_for".
+ *
+ * If this callback is set, then it used to print for nodes in the AST.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+ __isl_take isl_ast_print_options *options,
+ __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user),
+ void *user)
+{
+ options = isl_ast_print_options_cow(options);
+ if (!options)
+ return NULL;
+
+ options->print_for = print_for;
+ options->print_for_user = user;
+
+ return options;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return NULL;
+
+ expr->ref++;
+ return expr;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_ast_expr *dup;
+
+ if (!expr)
+ return NULL;
+
+ ctx = isl_ast_expr_get_ctx(expr);
+ switch (expr->type) {
+ case isl_ast_expr_int:
+ dup = isl_ast_expr_from_val(isl_val_copy(expr->u.v));
+ break;
+ case isl_ast_expr_id:
+ dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));
+ break;
+ case isl_ast_expr_op:
+ dup = isl_ast_expr_alloc_op(ctx,
+ expr->u.op.op, expr->u.op.n_arg);
+ if (!dup)
+ return NULL;
+ for (i = 0; i < expr->u.op.n_arg; ++i)
+ dup->u.op.args[i] =
+ isl_ast_expr_copy(expr->u.op.args[i]);
+ break;
+ case isl_ast_expr_error:
+ dup = NULL;
+ }
+
+ if (!dup)
+ return NULL;
+
+ return dup;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)
+{
+ if (!expr)
+ return NULL;
+
+ if (expr->ref == 1)
+ return expr;
+ expr->ref--;
+ return isl_ast_expr_dup(expr);
+}
+
+__isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr)
+{
+ int i;
+
+ if (!expr)
+ return NULL;
+
+ if (--expr->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(expr->ctx);
+
+ switch (expr->type) {
+ case isl_ast_expr_int:
+ isl_val_free(expr->u.v);
+ break;
+ case isl_ast_expr_id:
+ isl_id_free(expr->u.id);
+ break;
+ case isl_ast_expr_op:
+ if (expr->u.op.args)
+ for (i = 0; i < expr->u.op.n_arg; ++i)
+ isl_ast_expr_free(expr->u.op.args[i]);
+ free(expr->u.op.args);
+ break;
+ case isl_ast_expr_error:
+ break;
+ }
+
+ free(expr);
+ return NULL;
+}
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)
+{
+ return expr ? expr->ctx : NULL;
+}
+
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
+{
+ return expr ? expr->type : isl_ast_expr_error;
+}
+
+/* Return the integer value represented by "expr".
+ */
+__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return NULL;
+ if (expr->type != isl_ast_expr_int)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an int", return NULL);
+ return isl_val_copy(expr->u.v);
+}
+
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return NULL;
+ if (expr->type != isl_ast_expr_id)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an identifier", return NULL);
+
+ return isl_id_copy(expr->u.id);
+}
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return isl_ast_op_error;
+ if (expr->type != isl_ast_expr_op)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an operation", return isl_ast_op_error);
+ return expr->u.op.op;
+}
+
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return -1;
+ if (expr->type != isl_ast_expr_op)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an operation", return -1);
+ return expr->u.op.n_arg;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+ int pos)
+{
+ if (!expr)
+ return NULL;
+ if (expr->type != isl_ast_expr_op)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an operation", return NULL);
+ if (pos < 0 || pos >= expr->u.op.n_arg)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "index out of bounds", return NULL);
+
+ return isl_ast_expr_copy(expr->u.op.args[pos]);
+}
+
+/* Replace the argument at position "pos" of "expr" by "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+ int pos, __isl_take isl_ast_expr *arg)
+{
+ expr = isl_ast_expr_cow(expr);
+ if (!expr || !arg)
+ goto error;
+ if (expr->type != isl_ast_expr_op)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an operation", goto error);
+ if (pos < 0 || pos >= expr->u.op.n_arg)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ isl_ast_expr_free(expr->u.op.args[pos]);
+ expr->u.op.args[pos] = arg;
+
+ return expr;
+error:
+ isl_ast_expr_free(arg);
+ return isl_ast_expr_free(expr);
+}
+
+/* Is "expr1" equal to "expr2"?
+ */
+int isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
+ __isl_keep isl_ast_expr *expr2)
+{
+ int i;
+
+ if (!expr1 || !expr2)
+ return -1;
+
+ if (expr1 == expr2)
+ return 1;
+ if (expr1->type != expr2->type)
+ return 0;
+ switch (expr1->type) {
+ case isl_ast_expr_int:
+ return isl_val_eq(expr1->u.v, expr2->u.v);
+ case isl_ast_expr_id:
+ return expr1->u.id == expr2->u.id;
+ case isl_ast_expr_op:
+ if (expr1->u.op.op != expr2->u.op.op)
+ return 0;
+ if (expr1->u.op.n_arg != expr2->u.op.n_arg)
+ return 0;
+ for (i = 0; i < expr1->u.op.n_arg; ++i) {
+ int equal;
+ equal = isl_ast_expr_is_equal(expr1->u.op.args[i],
+ expr2->u.op.args[i]);
+ return 0;
+ if (equal < 0 || !equal)
+ return equal;
+ }
+ return 1;
+ case isl_ast_expr_error:
+ return -1;
+ }
+}
+
+/* Create a new operation expression of operation type "op",
+ * with "n_arg" as yet unspecified arguments.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
+ enum isl_ast_op_type op, int n_arg)
+{
+ isl_ast_expr *expr;
+
+ expr = isl_calloc_type(ctx, isl_ast_expr);
+ if (!expr)
+ return NULL;
+
+ expr->ctx = ctx;
+ isl_ctx_ref(ctx);
+ expr->ref = 1;
+ expr->type = isl_ast_expr_op;
+ expr->u.op.op = op;
+ expr->u.op.n_arg = n_arg;
+ expr->u.op.args = isl_calloc_array(ctx, isl_ast_expr *, n_arg);
+
+ if (n_arg && !expr->u.op.args)
+ return isl_ast_expr_free(expr);
+
+ return expr;
+}
+
+/* Create a new id expression representing "id".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr;
+
+ if (!id)
+ return NULL;
+
+ ctx = isl_id_get_ctx(id);
+ expr = isl_calloc_type(ctx, isl_ast_expr);
+ if (!expr)
+ goto error;
+
+ expr->ctx = ctx;
+ isl_ctx_ref(ctx);
+ expr->ref = 1;
+ expr->type = isl_ast_expr_id;
+ expr->u.id = id;
+
+ return expr;
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+/* Create a new integer expression representing "i".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)
+{
+ isl_ast_expr *expr;
+
+ expr = isl_calloc_type(ctx, isl_ast_expr);
+ if (!expr)
+ return NULL;
+
+ expr->ctx = ctx;
+ isl_ctx_ref(ctx);
+ expr->ref = 1;
+ expr->type = isl_ast_expr_int;
+ expr->u.v = isl_val_int_from_si(ctx, i);
+ if (!expr->u.v)
+ return isl_ast_expr_free(expr);
+
+ return expr;
+}
+
+/* Create a new integer expression representing "v".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr;
+
+ if (!v)
+ return NULL;
+ if (!isl_val_is_int(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting integer value", goto error);
+
+ ctx = isl_val_get_ctx(v);
+ expr = isl_calloc_type(ctx, isl_ast_expr);
+ if (!expr)
+ goto error;
+
+ expr->ctx = ctx;
+ isl_ctx_ref(ctx);
+ expr->ref = 1;
+ expr->type = isl_ast_expr_int;
+ expr->u.v = v;
+
+ return expr;
+error:
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Create an expression representing the unary operation "type" applied to
+ * "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_unary(enum isl_ast_op_type type,
+ __isl_take isl_ast_expr *arg)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr = NULL;
+
+ if (!arg)
+ return NULL;
+
+ ctx = isl_ast_expr_get_ctx(arg);
+ expr = isl_ast_expr_alloc_op(ctx, type, 1);
+ if (!expr)
+ goto error;
+
+ expr->u.op.args[0] = arg;
+
+ return expr;
+error:
+ isl_ast_expr_free(arg);
+ return NULL;
+}
+
+/* Create an expression representing the negation of "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)
+{
+ return isl_ast_expr_alloc_unary(isl_ast_op_minus, arg);
+}
+
+/* Create an expression representing the address of "expr".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr)
+{
+ if (!expr)
+ return NULL;
+
+ if (isl_ast_expr_get_type(expr) != isl_ast_expr_op ||
+ isl_ast_expr_get_op_type(expr) != isl_ast_op_access)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "can only take address of access expressions",
+ return isl_ast_expr_free(expr));
+
+ return isl_ast_expr_alloc_unary(isl_ast_op_address_of, expr);
+}
+
+/* Create an expression representing the binary operation "type"
+ * applied to "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+ __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr = NULL;
+
+ if (!expr1 || !expr2)
+ goto error;
+
+ ctx = isl_ast_expr_get_ctx(expr1);
+ expr = isl_ast_expr_alloc_op(ctx, type, 2);
+ if (!expr)
+ goto error;
+
+ expr->u.op.args[0] = expr1;
+ expr->u.op.args[1] = expr2;
+
+ return expr;
+error:
+ isl_ast_expr_free(expr1);
+ isl_ast_expr_free(expr2);
+ return NULL;
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_add, expr1, expr2);
+}
+
+/* Create an expression representing the difference of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_sub, expr1, expr2);
+}
+
+/* Create an expression representing the product of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_mul, expr1, expr2);
+}
+
+/* Create an expression representing the quotient of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_div, expr1, expr2);
+}
+
+/* Create an expression representing the conjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_and, expr1, expr2);
+}
+
+/* Create an expression representing the disjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_or, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" less than or equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_le, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" less than "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_lt, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" greater than or equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_ge, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" greater than "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_gt, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ return isl_ast_expr_alloc_binary(isl_ast_op_eq, expr1, expr2);
+}
+
+/* Create an expression representing an access to "array" with index
+ * expressions "indices".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
+ __isl_take isl_ast_expr_list *indices)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_ast_expr *access = NULL;
+
+ if (!array || !indices)
+ goto error;
+
+ ctx = isl_ast_expr_get_ctx(array);
+ n = isl_ast_expr_list_n_ast_expr(indices);
+ access = isl_ast_expr_alloc_op(ctx, isl_ast_op_access, 1 + n);
+ if (!access)
+ goto error;
+ for (i = 0; i < n; ++i) {
+ isl_ast_expr *index;
+ index = isl_ast_expr_list_get_ast_expr(indices, i);
+ access->u.op.args[1 + i] = index;
+ if (!index)
+ goto error;
+ }
+ access->u.op.args[0] = array;
+
+ isl_ast_expr_list_free(indices);
+ return access;
+error:
+ isl_ast_expr_free(array);
+ isl_ast_expr_list_free(indices);
+ isl_ast_expr_free(access);
+ return NULL;
+}
+
+/* For each subexpression of "expr" of type isl_ast_expr_id,
+ * if it appears in "id2expr", then replace it by the corresponding
+ * expression.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
+ __isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr)
+{
+ int i;
+ isl_id *id;
+
+ if (!expr || !id2expr)
+ goto error;
+
+ switch (expr->type) {
+ case isl_ast_expr_int:
+ break;
+ case isl_ast_expr_id:
+ if (!isl_id_to_ast_expr_has(id2expr, expr->u.id))
+ break;
+ id = isl_id_copy(expr->u.id);
+ isl_ast_expr_free(expr);
+ expr = isl_id_to_ast_expr_get(id2expr, id);
+ break;
+ case isl_ast_expr_op:
+ for (i = 0; i < expr->u.op.n_arg; ++i) {
+ isl_ast_expr *arg;
+ arg = isl_ast_expr_copy(expr->u.op.args[i]);
+ arg = isl_ast_expr_substitute_ids(arg,
+ isl_id_to_ast_expr_copy(id2expr));
+ if (arg == expr->u.op.args[i]) {
+ isl_ast_expr_free(arg);
+ continue;
+ }
+ if (!arg)
+ expr = isl_ast_expr_free(expr);
+ expr = isl_ast_expr_cow(expr);
+ if (!expr) {
+ isl_ast_expr_free(arg);
+ break;
+ }
+ isl_ast_expr_free(expr->u.op.args[i]);
+ expr->u.op.args[i] = arg;
+ }
+ break;
+ case isl_ast_expr_error:
+ expr = isl_ast_expr_free(expr);
+ break;
+ }
+
+ isl_id_to_ast_expr_free(id2expr);
+ return expr;
+error:
+ isl_ast_expr_free(expr);
+ isl_id_to_ast_expr_free(id2expr);
+ return NULL;
+}
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)
+{
+ return node ? node->ctx : NULL;
+}
+
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
+{
+ return node ? node->type : isl_ast_node_error;
+}
+
+__isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,
+ enum isl_ast_node_type type)
+{
+ isl_ast_node *node;
+
+ node = isl_calloc_type(ctx, isl_ast_node);
+ if (!node)
+ return NULL;
+
+ node->ctx = ctx;
+ isl_ctx_ref(ctx);
+ node->ref = 1;
+ node->type = type;
+
+ return node;
+}
+
+/* Create an if node with the given guard.
+ *
+ * The then body needs to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)
+{
+ isl_ast_node *node;
+
+ if (!guard)
+ return NULL;
+
+ node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);
+ if (!node)
+ goto error;
+ node->u.i.guard = guard;
+
+ return node;
+error:
+ isl_ast_expr_free(guard);
+ return NULL;
+}
+
+/* Create a for node with the given iterator.
+ *
+ * The remaining fields need to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)
+{
+ isl_ast_node *node;
+ isl_ctx *ctx;
+
+ if (!id)
+ return NULL;
+
+ ctx = isl_id_get_ctx(id);
+ node = isl_ast_node_alloc(ctx, isl_ast_node_for);
+ if (!node)
+ goto error;
+
+ node->u.f.iterator = isl_ast_expr_from_id(id);
+ if (!node->u.f.iterator)
+ return isl_ast_node_free(node);
+
+ return node;
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+/* Create a user node evaluating "expr".
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)
+{
+ isl_ctx *ctx;
+ isl_ast_node *node;
+
+ if (!expr)
+ return NULL;
+
+ ctx = isl_ast_expr_get_ctx(expr);
+ node = isl_ast_node_alloc(ctx, isl_ast_node_user);
+ if (!node)
+ goto error;
+
+ node->u.e.expr = expr;
+
+ return node;
+error:
+ isl_ast_expr_free(expr);
+ return NULL;
+}
+
+/* Create a block node with the given children.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+ __isl_take isl_ast_node_list *list)
+{
+ isl_ast_node *node;
+ isl_ctx *ctx;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_ast_node_list_get_ctx(list);
+ node = isl_ast_node_alloc(ctx, isl_ast_node_block);
+ if (!node)
+ goto error;
+
+ node->u.b.children = list;
+
+ return node;
+error:
+ isl_ast_node_list_free(list);
+ return NULL;
+}
+
+/* Represent the given list of nodes as a single node, either by
+ * extract the node from a single element list or by creating
+ * a block node with the list of nodes as children.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
+ __isl_take isl_ast_node_list *list)
+{
+ isl_ast_node *node;
+
+ if (isl_ast_node_list_n_ast_node(list) != 1)
+ return isl_ast_node_alloc_block(list);
+
+ node = isl_ast_node_list_get_ast_node(list, 0);
+ isl_ast_node_list_free(list);
+
+ return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+
+ node->ref++;
+ return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)
+{
+ isl_ast_node *dup;
+
+ if (!node)
+ return NULL;
+
+ dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);
+ if (!dup)
+ return NULL;
+
+ switch (node->type) {
+ case isl_ast_node_if:
+ dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);
+ dup->u.i.then = isl_ast_node_copy(node->u.i.then);
+ dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);
+ if (!dup->u.i.guard || !dup->u.i.then ||
+ (node->u.i.else_node && !dup->u.i.else_node))
+ return isl_ast_node_free(dup);
+ break;
+ case isl_ast_node_for:
+ dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);
+ dup->u.f.init = isl_ast_expr_copy(node->u.f.init);
+ dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);
+ dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);
+ dup->u.f.body = isl_ast_node_copy(node->u.f.body);
+ if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.cond ||
+ !dup->u.f.inc || !dup->u.f.body)
+ return isl_ast_node_free(dup);
+ break;
+ case isl_ast_node_block:
+ dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);
+ if (!dup->u.b.children)
+ return isl_ast_node_free(dup);
+ break;
+ case isl_ast_node_user:
+ dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);
+ if (!dup->u.e.expr)
+ return isl_ast_node_free(dup);
+ break;
+ case isl_ast_node_error:
+ break;
+ }
+
+ return dup;
+}
+
+__isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+
+ if (node->ref == 1)
+ return node;
+ node->ref--;
+ return isl_ast_node_dup(node);
+}
+
+__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+
+ if (--node->ref > 0)
+ return NULL;
+
+ switch (node->type) {
+ case isl_ast_node_if:
+ isl_ast_expr_free(node->u.i.guard);
+ isl_ast_node_free(node->u.i.then);
+ isl_ast_node_free(node->u.i.else_node);
+ break;
+ case isl_ast_node_for:
+ isl_ast_expr_free(node->u.f.iterator);
+ isl_ast_expr_free(node->u.f.init);
+ isl_ast_expr_free(node->u.f.cond);
+ isl_ast_expr_free(node->u.f.inc);
+ isl_ast_node_free(node->u.f.body);
+ break;
+ case isl_ast_node_block:
+ isl_ast_node_list_free(node->u.b.children);
+ break;
+ case isl_ast_node_user:
+ isl_ast_expr_free(node->u.e.expr);
+ break;
+ case isl_ast_node_error:
+ break;
+ }
+
+ isl_id_free(node->annotation);
+ isl_ctx_deref(node->ctx);
+ free(node);
+
+ return NULL;
+}
+
+/* Replace the body of the for node "node" by "body".
+ */
+__isl_give isl_ast_node *isl_ast_node_for_set_body(
+ __isl_take isl_ast_node *node, __isl_take isl_ast_node *body)
+{
+ node = isl_ast_node_cow(node);
+ if (!node || !body)
+ goto error;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", goto error);
+
+ isl_ast_node_free(node->u.f.body);
+ node->u.f.body = body;
+
+ return node;
+error:
+ isl_ast_node_free(node);
+ isl_ast_node_free(body);
+ return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return NULL);
+ return isl_ast_node_copy(node->u.f.body);
+}
+
+/* Mark the given for node as being degenerate.
+ */
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+ __isl_take isl_ast_node *node)
+{
+ node = isl_ast_node_cow(node);
+ if (!node)
+ return NULL;
+ node->u.f.degenerate = 1;
+ return node;
+}
+
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return -1;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return -1);
+ return node->u.f.degenerate;
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return NULL);
+ return isl_ast_expr_copy(node->u.f.iterator);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return NULL);
+ return isl_ast_expr_copy(node->u.f.init);
+}
+
+/* Return the condition expression of the given for node.
+ *
+ * If the for node is degenerate, then the condition is not explicitly
+ * stored in the node. Instead, it is constructed as
+ *
+ * iterator <= init
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return NULL);
+ if (!node->u.f.degenerate)
+ return isl_ast_expr_copy(node->u.f.cond);
+
+ return isl_ast_expr_alloc_binary(isl_ast_op_le,
+ isl_ast_expr_copy(node->u.f.iterator),
+ isl_ast_expr_copy(node->u.f.init));
+}
+
+/* Return the increment of the given for node.
+ *
+ * If the for node is degenerate, then the increment is not explicitly
+ * stored in the node. We simply return "1".
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", return NULL);
+ if (!node->u.f.degenerate)
+ return isl_ast_expr_copy(node->u.f.inc);
+ return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);
+}
+
+/* Replace the then branch of the if node "node" by "child".
+ */
+__isl_give isl_ast_node *isl_ast_node_if_set_then(
+ __isl_take isl_ast_node *node, __isl_take isl_ast_node *child)
+{
+ node = isl_ast_node_cow(node);
+ if (!node || !child)
+ goto error;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not an if node", goto error);
+
+ isl_ast_node_free(node->u.i.then);
+ node->u.i.then = child;
+
+ return node;
+error:
+ isl_ast_node_free(node);
+ isl_ast_node_free(child);
+ return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not an if node", return NULL);
+ return isl_ast_node_copy(node->u.i.then);
+}
+
+int isl_ast_node_if_has_else(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return -1;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not an if node", return -1);
+ return node->u.i.else_node != NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not an if node", return NULL);
+ return isl_ast_node_copy(node->u.i.else_node);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a guard node", return NULL);
+ return isl_ast_expr_copy(node->u.i.guard);
+}
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_block)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a block node", return NULL);
+ return isl_ast_node_list_copy(node->u.b.children);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+ __isl_keep isl_ast_node *node)
+{
+ if (!node)
+ return NULL;
+ if (node->type != isl_ast_node_user)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a user node", return NULL);
+
+ return isl_ast_expr_copy(node->u.e.expr);
+}
+
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)
+{
+ return node ? isl_id_copy(node->annotation) : NULL;
+}
+
+/* Replace node->annotation by "annotation".
+ */
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+ __isl_take isl_ast_node *node, __isl_take isl_id *annotation)
+{
+ node = isl_ast_node_cow(node);
+ if (!node || !annotation)
+ goto error;
+
+ isl_id_free(node->annotation);
+ node->annotation = annotation;
+
+ return node;
+error:
+ isl_id_free(annotation);
+ return isl_ast_node_free(node);
+}
+
+/* Textual C representation of the various operators.
+ */
+static char *op_str[] = {
+ [isl_ast_op_and] = "&&",
+ [isl_ast_op_and_then] = "&&",
+ [isl_ast_op_or] = "||",
+ [isl_ast_op_or_else] = "||",
+ [isl_ast_op_max] = "max",
+ [isl_ast_op_min] = "min",
+ [isl_ast_op_minus] = "-",
+ [isl_ast_op_add] = "+",
+ [isl_ast_op_sub] = "-",
+ [isl_ast_op_mul] = "*",
+ [isl_ast_op_pdiv_q] = "/",
+ [isl_ast_op_pdiv_r] = "%",
+ [isl_ast_op_zdiv_r] = "%",
+ [isl_ast_op_div] = "/",
+ [isl_ast_op_eq] = "==",
+ [isl_ast_op_le] = "<=",
+ [isl_ast_op_ge] = ">=",
+ [isl_ast_op_lt] = "<",
+ [isl_ast_op_gt] = ">",
+ [isl_ast_op_member] = ".",
+ [isl_ast_op_address_of] = "&"
+};
+
+/* Precedence in C of the various operators.
+ * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++
+ * Lowest value means highest precedence.
+ */
+static int op_prec[] = {
+ [isl_ast_op_and] = 13,
+ [isl_ast_op_and_then] = 13,
+ [isl_ast_op_or] = 14,
+ [isl_ast_op_or_else] = 14,
+ [isl_ast_op_max] = 2,
+ [isl_ast_op_min] = 2,
+ [isl_ast_op_minus] = 3,
+ [isl_ast_op_add] = 6,
+ [isl_ast_op_sub] = 6,
+ [isl_ast_op_mul] = 5,
+ [isl_ast_op_div] = 5,
+ [isl_ast_op_fdiv_q] = 2,
+ [isl_ast_op_pdiv_q] = 5,
+ [isl_ast_op_pdiv_r] = 5,
+ [isl_ast_op_zdiv_r] = 5,
+ [isl_ast_op_cond] = 15,
+ [isl_ast_op_select] = 15,
+ [isl_ast_op_eq] = 9,
+ [isl_ast_op_le] = 8,
+ [isl_ast_op_ge] = 8,
+ [isl_ast_op_lt] = 8,
+ [isl_ast_op_gt] = 8,
+ [isl_ast_op_call] = 2,
+ [isl_ast_op_access] = 2,
+ [isl_ast_op_member] = 2,
+ [isl_ast_op_address_of] = 3
+};
+
+/* Is the operator left-to-right associative?
+ */
+static int op_left[] = {
+ [isl_ast_op_and] = 1,
+ [isl_ast_op_and_then] = 1,
+ [isl_ast_op_or] = 1,
+ [isl_ast_op_or_else] = 1,
+ [isl_ast_op_max] = 1,
+ [isl_ast_op_min] = 1,
+ [isl_ast_op_minus] = 0,
+ [isl_ast_op_add] = 1,
+ [isl_ast_op_sub] = 1,
+ [isl_ast_op_mul] = 1,
+ [isl_ast_op_div] = 1,
+ [isl_ast_op_fdiv_q] = 1,
+ [isl_ast_op_pdiv_q] = 1,
+ [isl_ast_op_pdiv_r] = 1,
+ [isl_ast_op_zdiv_r] = 1,
+ [isl_ast_op_cond] = 0,
+ [isl_ast_op_select] = 0,
+ [isl_ast_op_eq] = 1,
+ [isl_ast_op_le] = 1,
+ [isl_ast_op_ge] = 1,
+ [isl_ast_op_lt] = 1,
+ [isl_ast_op_gt] = 1,
+ [isl_ast_op_call] = 1,
+ [isl_ast_op_access] = 1,
+ [isl_ast_op_member] = 1,
+ [isl_ast_op_address_of] = 0
+};
+
+static int is_and(enum isl_ast_op_type op)
+{
+ return op == isl_ast_op_and || op == isl_ast_op_and_then;
+}
+
+static int is_or(enum isl_ast_op_type op)
+{
+ return op == isl_ast_op_or || op == isl_ast_op_or_else;
+}
+
+static int is_add_sub(enum isl_ast_op_type op)
+{
+ return op == isl_ast_op_add || op == isl_ast_op_sub;
+}
+
+static int is_div_mod(enum isl_ast_op_type op)
+{
+ return op == isl_ast_op_div ||
+ op == isl_ast_op_pdiv_r ||
+ op == isl_ast_op_zdiv_r;
+}
+
+/* Do we need/want parentheses around "expr" as a subexpression of
+ * an "op" operation? If "left" is set, then "expr" is the left-most
+ * operand.
+ *
+ * We only need parentheses if "expr" represents an operation.
+ *
+ * If op has a higher precedence than expr->u.op.op, then we need
+ * parentheses.
+ * If op and expr->u.op.op have the same precedence, but the operations
+ * are performed in an order that is different from the associativity,
+ * then we need parentheses.
+ *
+ * An and inside an or technically does not require parentheses,
+ * but some compilers complain about that, so we add them anyway.
+ *
+ * Computations such as "a / b * c" and "a % b + c" can be somewhat
+ * difficult to read, so we add parentheses for those as well.
+ */
+static int sub_expr_need_parens(enum isl_ast_op_type op,
+ __isl_keep isl_ast_expr *expr, int left)
+{
+ if (expr->type != isl_ast_expr_op)
+ return 0;
+
+ if (op_prec[expr->u.op.op] > op_prec[op])
+ return 1;
+ if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])
+ return 1;
+
+ if (is_or(op) && is_and(expr->u.op.op))
+ return 1;
+ if (op == isl_ast_op_mul && expr->u.op.op != isl_ast_op_mul &&
+ op_prec[expr->u.op.op] == op_prec[op])
+ return 1;
+ if (is_add_sub(op) && is_div_mod(expr->u.op.op))
+ return 1;
+
+ return 0;
+}
+
+/* Print "expr" as a subexpression of an "op" operation.
+ * If "left" is set, then "expr" is the left-most operand.
+ */
+static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
+ enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
+{
+ int need_parens;
+
+ need_parens = sub_expr_need_parens(op, expr, left);
+
+ if (need_parens)
+ p = isl_printer_print_str(p, "(");
+ p = isl_printer_print_ast_expr(p, expr);
+ if (need_parens)
+ p = isl_printer_print_str(p, ")");
+ return p;
+}
+
+/* Print a min or max reduction "expr".
+ */
+static __isl_give isl_printer *print_min_max(__isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr)
+{
+ int i = 0;
+
+ for (i = 1; i < expr->u.op.n_arg; ++i) {
+ p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+ p = isl_printer_print_str(p, "(");
+ }
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+ for (i = 1; i < expr->u.op.n_arg; ++i) {
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+ p = isl_printer_print_str(p, ")");
+ }
+
+ return p;
+}
+
+/* Print a function call "expr".
+ *
+ * The first argument represents the function to be called.
+ */
+static __isl_give isl_printer *print_call(__isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr)
+{
+ int i = 0;
+
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+ p = isl_printer_print_str(p, "(");
+ for (i = 1; i < expr->u.op.n_arg; ++i) {
+ if (i != 1)
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+ }
+ p = isl_printer_print_str(p, ")");
+
+ return p;
+}
+
+/* Print an array access "expr".
+ *
+ * The first argument represents the array being accessed.
+ */
+static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr)
+{
+ int i = 0;
+
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+ for (i = 1; i < expr->u.op.n_arg; ++i) {
+ p = isl_printer_print_str(p, "[");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+ p = isl_printer_print_str(p, "]");
+ }
+
+ return p;
+}
+
+/* Print "expr" to "p".
+ *
+ * If we are printing in isl format, then we also print an indication
+ * of the size of the expression (if it was computed).
+ */
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+ __isl_keep isl_ast_expr *expr)
+{
+ if (!p)
+ return NULL;
+ if (!expr)
+ return isl_printer_free(p);
+
+ switch (expr->type) {
+ case isl_ast_expr_op:
+ if (expr->u.op.op == isl_ast_op_call) {
+ p = print_call(p, expr);
+ break;
+ }
+ if (expr->u.op.op == isl_ast_op_access) {
+ p = print_access(p, expr);
+ break;
+ }
+ if (expr->u.op.n_arg == 1) {
+ p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+ p = print_sub_expr(p, expr->u.op.op,
+ expr->u.op.args[0], 0);
+ break;
+ }
+ if (expr->u.op.op == isl_ast_op_fdiv_q) {
+ p = isl_printer_print_str(p, "floord(");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+ p = isl_printer_print_str(p, ")");
+ break;
+ }
+ if (expr->u.op.op == isl_ast_op_max ||
+ expr->u.op.op == isl_ast_op_min) {
+ p = print_min_max(p, expr);
+ break;
+ }
+ if (expr->u.op.op == isl_ast_op_cond ||
+ expr->u.op.op == isl_ast_op_select) {
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+ p = isl_printer_print_str(p, " ? ");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+ p = isl_printer_print_str(p, " : ");
+ p = isl_printer_print_ast_expr(p, expr->u.op.args[2]);
+ break;
+ }
+ if (expr->u.op.n_arg != 2)
+ isl_die(isl_printer_get_ctx(p), isl_error_internal,
+ "operation should have two arguments",
+ goto error);
+ p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[0], 1);
+ if (expr->u.op.op != isl_ast_op_member)
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+ if (expr->u.op.op != isl_ast_op_member)
+ p = isl_printer_print_str(p, " ");
+ p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[1], 0);
+ break;
+ case isl_ast_expr_id:
+ p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
+ break;
+ case isl_ast_expr_int:
+ p = isl_printer_print_val(p, expr->u.v);
+ break;
+ case isl_ast_expr_error:
+ break;
+ }
+
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print "node" to "p" in "isl format".
+ */
+static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node)
+{
+ p = isl_printer_print_str(p, "(");
+ switch (node->type) {
+ case isl_ast_node_for:
+ if (node->u.f.degenerate) {
+ p = isl_printer_print_ast_expr(p, node->u.f.init);
+ } else {
+ p = isl_printer_print_str(p, "init: ");
+ p = isl_printer_print_ast_expr(p, node->u.f.init);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "cond: ");
+ p = isl_printer_print_ast_expr(p, node->u.f.cond);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "inc: ");
+ p = isl_printer_print_ast_expr(p, node->u.f.inc);
+ }
+ if (node->u.f.body) {
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "body: ");
+ p = isl_printer_print_ast_node(p, node->u.f.body);
+ }
+ break;
+ case isl_ast_node_user:
+ p = isl_printer_print_ast_expr(p, node->u.e.expr);
+ break;
+ case isl_ast_node_if:
+ p = isl_printer_print_str(p, "guard: ");
+ p = isl_printer_print_ast_expr(p, node->u.i.guard);
+ if (node->u.i.then) {
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "then: ");
+ p = isl_printer_print_ast_node(p, node->u.i.then);
+ }
+ if (node->u.i.else_node) {
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "else: ");
+ p = isl_printer_print_ast_node(p, node->u.i.else_node);
+ }
+ break;
+ case isl_ast_node_block:
+ p = isl_printer_print_ast_node_list(p, node->u.b.children);
+ break;
+ default:
+ break;
+ }
+ p = isl_printer_print_str(p, ")");
+ return p;
+}
+
+/* Do we need to print a block around the body "node" of a for or if node?
+ *
+ * If the node is a block, then we need to print a block.
+ * Also if the node is a degenerate for then we will print it as
+ * an assignment followed by the body of the for loop, so we need a block
+ * as well.
+ * If the node is an if node with an else, then we print a block
+ * to avoid spurious dangling else warnings emitted by some compilers.
+ * If the ast_always_print_block option has been set, then we print a block.
+ */
+static int need_block(__isl_keep isl_ast_node *node)
+{
+ isl_ctx *ctx;
+
+ if (node->type == isl_ast_node_block)
+ return 1;
+ if (node->type == isl_ast_node_for && node->u.f.degenerate)
+ return 1;
+ if (node->type == isl_ast_node_if && node->u.i.else_node)
+ return 1;
+
+ ctx = isl_ast_node_get_ctx(node);
+ return isl_options_get_ast_always_print_block(ctx);
+}
+
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node,
+ __isl_keep isl_ast_print_options *options, int in_block, int in_list);
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node,
+ __isl_keep isl_ast_print_options *options, int new_line);
+
+/* Print the body "node" of a for or if node.
+ * If "else_node" is set, then it is printed as well.
+ *
+ * We first check if we need to print out a block.
+ * We always print out a block if there is an else node to make
+ * sure that the else node is matched to the correct if node.
+ *
+ * If the else node is itself an if, then we print it as
+ *
+ * } else if (..)
+ *
+ * Otherwise the else node is printed as
+ *
+ * } else
+ * node
+ */
+static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,
+ __isl_keep isl_ast_print_options *options)
+{
+ if (!node)
+ return isl_printer_free(p);
+
+ if (!else_node && !need_block(node)) {
+ p = isl_printer_end_line(p);
+ p = isl_printer_indent(p, 2);
+ p = isl_ast_node_print(node, p,
+ isl_ast_print_options_copy(options));
+ p = isl_printer_indent(p, -2);
+ return p;
+ }
+
+ p = isl_printer_print_str(p, " {");
+ p = isl_printer_end_line(p);
+ p = isl_printer_indent(p, 2);
+ p = print_ast_node_c(p, node, options, 1, 0);
+ p = isl_printer_indent(p, -2);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "}");
+ if (else_node) {
+ if (else_node->type == isl_ast_node_if) {
+ p = isl_printer_print_str(p, " else ");
+ p = print_if_c(p, else_node, options, 0);
+ } else {
+ p = isl_printer_print_str(p, " else");
+ p = print_body_c(p, else_node, NULL, options);
+ }
+ } else
+ p = isl_printer_end_line(p);
+
+ return p;
+}
+
+/* Print the start of a compound statement.
+ */
+static __isl_give isl_printer *start_block(__isl_take isl_printer *p)
+{
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "{");
+ p = isl_printer_end_line(p);
+ p = isl_printer_indent(p, 2);
+
+ return p;
+}
+
+/* Print the end of a compound statement.
+ */
+static __isl_give isl_printer *end_block(__isl_take isl_printer *p)
+{
+ p = isl_printer_indent(p, -2);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "}");
+ p = isl_printer_end_line(p);
+
+ return p;
+}
+
+/* Print the for node "node".
+ *
+ * If the for node is degenerate, it is printed as
+ *
+ * type iterator = init;
+ * body
+ *
+ * Otherwise, it is printed as
+ *
+ * for (type iterator = init; cond; iterator += inc)
+ * body
+ *
+ * "in_block" is set if we are currently inside a block.
+ * "in_list" is set if the current node is not alone in the block.
+ * If we are not in a block or if the current not is not alone in the block
+ * then we print a block around a degenerate for loop such that the variable
+ * declaration will not conflict with any potential other declaration
+ * of the same variable.
+ */
+static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node,
+ __isl_keep isl_ast_print_options *options, int in_block, int in_list)
+{
+ isl_id *id;
+ const char *name;
+ const char *type;
+
+ type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));
+ if (!node->u.f.degenerate) {
+ id = isl_ast_expr_get_id(node->u.f.iterator);
+ name = isl_id_get_name(id);
+ isl_id_free(id);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "for (");
+ p = isl_printer_print_str(p, type);
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_str(p, name);
+ p = isl_printer_print_str(p, " = ");
+ p = isl_printer_print_ast_expr(p, node->u.f.init);
+ p = isl_printer_print_str(p, "; ");
+ p = isl_printer_print_ast_expr(p, node->u.f.cond);
+ p = isl_printer_print_str(p, "; ");
+ p = isl_printer_print_str(p, name);
+ p = isl_printer_print_str(p, " += ");
+ p = isl_printer_print_ast_expr(p, node->u.f.inc);
+ p = isl_printer_print_str(p, ")");
+ p = print_body_c(p, node->u.f.body, NULL, options);
+ } else {
+ id = isl_ast_expr_get_id(node->u.f.iterator);
+ name = isl_id_get_name(id);
+ isl_id_free(id);
+ if (!in_block || in_list)
+ p = start_block(p);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, type);
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_str(p, name);
+ p = isl_printer_print_str(p, " = ");
+ p = isl_printer_print_ast_expr(p, node->u.f.init);
+ p = isl_printer_print_str(p, ";");
+ p = isl_printer_end_line(p);
+ p = print_ast_node_c(p, node->u.f.body, options, 1, 0);
+ if (!in_block || in_list)
+ p = end_block(p);
+ }
+
+ return p;
+}
+
+/* Print the if node "node".
+ * If "new_line" is set then the if node should be printed on a new line.
+ */
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node,
+ __isl_keep isl_ast_print_options *options, int new_line)
+{
+ if (new_line)
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "if (");
+ p = isl_printer_print_ast_expr(p, node->u.i.guard);
+ p = isl_printer_print_str(p, ")");
+ p = print_body_c(p, node->u.i.then, node->u.i.else_node, options);
+
+ return p;
+}
+
+/* Print the "node" to "p".
+ *
+ * "in_block" is set if we are currently inside a block.
+ * If so, we do not print a block around the children of a block node.
+ * We do this to avoid an extra block around the body of a degenerate
+ * for node.
+ *
+ * "in_list" is set if the current node is not alone in the block.
+ */
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node,
+ __isl_keep isl_ast_print_options *options, int in_block, int in_list)
+{
+ switch (node->type) {
+ case isl_ast_node_for:
+ if (options->print_for)
+ return options->print_for(p,
+ isl_ast_print_options_copy(options),
+ node, options->print_for_user);
+ p = print_for_c(p, node, options, in_block, in_list);
+ break;
+ case isl_ast_node_if:
+ p = print_if_c(p, node, options, 1);
+ break;
+ case isl_ast_node_block:
+ if (!in_block)
+ p = start_block(p);
+ p = isl_ast_node_list_print(node->u.b.children, p, options);
+ if (!in_block)
+ p = end_block(p);
+ break;
+ case isl_ast_node_user:
+ if (options->print_user)
+ return options->print_user(p,
+ isl_ast_print_options_copy(options),
+ node, options->print_user_user);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_ast_expr(p, node->u.e.expr);
+ p = isl_printer_print_str(p, ";");
+ p = isl_printer_end_line(p);
+ break;
+ case isl_ast_node_error:
+ break;
+ }
+ return p;
+}
+
+/* Print the for node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+ if (!node || !options)
+ goto error;
+ if (node->type != isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not a for node", goto error);
+ p = print_for_c(p, node, options, 0, 0);
+ isl_ast_print_options_free(options);
+ return p;
+error:
+ isl_ast_print_options_free(options);
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print the if node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+ if (!node || !options)
+ goto error;
+ if (node->type != isl_ast_node_if)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+ "not an if node", goto error);
+ p = print_if_c(p, node, options, 1);
+ isl_ast_print_options_free(options);
+ return p;
+error:
+ isl_ast_print_options_free(options);
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+ __isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+ if (!options || !node)
+ goto error;
+ p = print_ast_node_c(p, node, options, 0, 0);
+ isl_ast_print_options_free(options);
+ return p;
+error:
+ isl_ast_print_options_free(options);
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+ __isl_keep isl_ast_node *node)
+{
+ int format;
+ isl_ast_print_options *options;
+
+ if (!p)
+ return NULL;
+
+ format = isl_printer_get_output_format(p);
+ switch (format) {
+ case ISL_FORMAT_ISL:
+ p = print_ast_node_isl(p, node);
+ break;
+ case ISL_FORMAT_C:
+ options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));
+ p = isl_ast_node_print(node, p, options);
+ break;
+ default:
+ isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+ "output format not supported for ast_node",
+ return isl_printer_free(p));
+ }
+
+ return p;
+}
+
+/* Print the list of nodes "list" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_list_print(
+ __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+ __isl_keep isl_ast_print_options *options)
+{
+ int i;
+
+ if (!p || !list || !options)
+ return isl_printer_free(p);
+
+ for (i = 0; i < list->n; ++i)
+ p = print_ast_node_c(p, list->p[i], options, 1, 1);
+
+ return p;
+}
+
+#define ISL_AST_MACRO_FLOORD (1 << 0)
+#define ISL_AST_MACRO_MIN (1 << 1)
+#define ISL_AST_MACRO_MAX (1 << 2)
+#define ISL_AST_MACRO_ALL (ISL_AST_MACRO_FLOORD | \
+ ISL_AST_MACRO_MIN | \
+ ISL_AST_MACRO_MAX)
+
+/* If "expr" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
+{
+ int i;
+
+ if (macros == ISL_AST_MACRO_ALL)
+ return macros;
+
+ if (expr->type != isl_ast_expr_op)
+ return macros;
+
+ if (expr->u.op.op == isl_ast_op_min)
+ macros |= ISL_AST_MACRO_MIN;
+ if (expr->u.op.op == isl_ast_op_max)
+ macros |= ISL_AST_MACRO_MAX;
+ if (expr->u.op.op == isl_ast_op_fdiv_q)
+ macros |= ISL_AST_MACRO_FLOORD;
+
+ for (i = 0; i < expr->u.op.n_arg; ++i)
+ macros = ast_expr_required_macros(expr->u.op.args[i], macros);
+
+ return macros;
+}
+
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+ int macros);
+
+/* If "node" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
+{
+ if (macros == ISL_AST_MACRO_ALL)
+ return macros;
+
+ switch (node->type) {
+ case isl_ast_node_for:
+ macros = ast_expr_required_macros(node->u.f.init, macros);
+ if (!node->u.f.degenerate) {
+ macros = ast_expr_required_macros(node->u.f.cond,
+ macros);
+ macros = ast_expr_required_macros(node->u.f.inc,
+ macros);
+ }
+ macros = ast_node_required_macros(node->u.f.body, macros);
+ break;
+ case isl_ast_node_if:
+ macros = ast_expr_required_macros(node->u.i.guard, macros);
+ macros = ast_node_required_macros(node->u.i.then, macros);
+ if (node->u.i.else_node)
+ macros = ast_node_required_macros(node->u.i.else_node,
+ macros);
+ break;
+ case isl_ast_node_block:
+ macros = ast_node_list_required_macros(node->u.b.children,
+ macros);
+ break;
+ case isl_ast_node_user:
+ macros = ast_expr_required_macros(node->u.e.expr, macros);
+ break;
+ case isl_ast_node_error:
+ break;
+ }
+
+ return macros;
+}
+
+/* If "list" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+ int macros)
+{
+ int i;
+
+ for (i = 0; i < list->n; ++i)
+ macros = ast_node_required_macros(list->p[i], macros);
+
+ return macros;
+}
+
+/* Print a macro definition for the operator "type".
+ */
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+ enum isl_ast_op_type type, __isl_take isl_printer *p)
+{
+ switch (type) {
+ case isl_ast_op_min:
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p,
+ "#define min(x,y) ((x) < (y) ? (x) : (y))");
+ p = isl_printer_end_line(p);
+ break;
+ case isl_ast_op_max:
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p,
+ "#define max(x,y) ((x) > (y) ? (x) : (y))");
+ p = isl_printer_end_line(p);
+ break;
+ case isl_ast_op_fdiv_q:
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p,
+ "#define floord(n,d) "
+ "(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
+ p = isl_printer_end_line(p);
+ break;
+ default:
+ break;
+ }
+
+ return p;
+}
+
+/* Call "fn" for each type of operation that appears in "node"
+ * and that requires a macro definition.
+ */
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+ int (*fn)(enum isl_ast_op_type type, void *user), void *user)
+{
+ int macros;
+
+ if (!node)
+ return -1;
+
+ macros = ast_node_required_macros(node, 0);
+
+ if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_op_min, user) < 0)
+ return -1;
+ if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_op_max, user) < 0)
+ return -1;
+ if (macros & ISL_AST_MACRO_FLOORD && fn(isl_ast_op_fdiv_q, user) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
+{
+ isl_printer **p = user;
+
+ *p = isl_ast_op_type_print_macro(type, *p);
+
+ return 0;
+}
+
+/* Print macro definitions for all the macros used in the result
+ * of printing "node.
+ */
+__isl_give isl_printer *isl_ast_node_print_macros(
+ __isl_keep isl_ast_node *node, __isl_take isl_printer *p)
+{
+ if (isl_ast_node_foreach_ast_op_type(node,
+ &ast_op_type_print_macro, &p) < 0)
+ return isl_printer_free(p);
+ return p;
+}
diff --git a/polly/lib/External/isl/isl_ast_build.c b/polly/lib/External/isl/isl_ast_build.c
new file mode 100644
index 00000000000..61576bb0a51
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_build.c
@@ -0,0 +1,2162 @@
+/*
+ * Copyright 2012 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <isl/map.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_private.h>
+
+/* Construct a map that isolates the current dimension.
+ *
+ * Essentially, the current dimension of "set" is moved to the single output
+ * dimension in the result, with the current dimension in the domain replaced
+ * by an unconstrained variable.
+ */
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ isl_map *map;
+
+ map = isl_map_from_domain(set);
+ map = isl_map_add_dims(map, isl_dim_out, 1);
+
+ if (!build)
+ return isl_map_free(map);
+
+ map = isl_map_equate(map, isl_dim_in, build->depth, isl_dim_out, 0);
+ map = isl_map_eliminate(map, isl_dim_in, build->depth, 1);
+
+ return map;
+}
+
+/* Initialize the information derived during the AST generation to default
+ * values for a schedule domain in "space".
+ *
+ * We also check that the remaining fields are not NULL so that
+ * the calling functions don't have to perform this test.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init_derived(
+ __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+ isl_ctx *ctx;
+ isl_vec *strides;
+
+ build = isl_ast_build_cow(build);
+ if (!build || !build->domain)
+ goto error;
+
+ ctx = isl_ast_build_get_ctx(build);
+ strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+ strides = isl_vec_set_si(strides, 1);
+
+ isl_vec_free(build->strides);
+ build->strides = strides;
+
+ space = isl_space_map_from_set(space);
+ isl_multi_aff_free(build->offsets);
+ build->offsets = isl_multi_aff_zero(isl_space_copy(space));
+ isl_multi_aff_free(build->values);
+ build->values = isl_multi_aff_identity(space);
+
+ if (!build->iterators || !build->domain || !build->generated ||
+ !build->pending || !build->values ||
+ !build->strides || !build->offsets || !build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_space_free(space);
+ return isl_ast_build_free(build);
+}
+
+/* Return an isl_id called "c%d", with "%d" set to "i".
+ * If an isl_id with such a name already appears among the parameters
+ * in build->domain, then adjust the name to "c%d_%d".
+ */
+static __isl_give isl_id *generate_name(isl_ctx *ctx, int i,
+ __isl_keep isl_ast_build *build)
+{
+ int j;
+ char name[16];
+ isl_set *dom = build->domain;
+
+ snprintf(name, sizeof(name), "c%d", i);
+ j = 0;
+ while (isl_set_find_dim_by_name(dom, isl_dim_param, name) >= 0)
+ snprintf(name, sizeof(name), "c%d_%d", i, j++);
+ return isl_id_alloc(ctx, name, NULL);
+}
+
+/* Create an isl_ast_build with "set" as domain.
+ *
+ * The input set is usually a parameter domain, but we currently allow it to
+ * be any kind of set. We set the domain of the returned isl_ast_build
+ * to "set" and initialize all the other fields to default values.
+ */
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_ast_build *build;
+
+ set = isl_set_compute_divs(set);
+ if (!set)
+ return NULL;
+
+ ctx = isl_set_get_ctx(set);
+
+ build = isl_calloc_type(ctx, isl_ast_build);
+ if (!build)
+ goto error;
+
+ build->ref = 1;
+ build->domain = set;
+ build->generated = isl_set_copy(build->domain);
+ build->pending = isl_set_universe(isl_set_get_space(build->domain));
+ build->options = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
+ n = isl_set_dim(set, isl_dim_set);
+ build->depth = n;
+ build->iterators = isl_id_list_alloc(ctx, n);
+ for (i = 0; i < n; ++i) {
+ isl_id *id;
+ if (isl_set_has_dim_id(set, isl_dim_set, i))
+ id = isl_set_get_dim_id(set, isl_dim_set, i);
+ else
+ id = generate_name(ctx, i, build);
+ build->iterators = isl_id_list_add(build->iterators, id);
+ }
+ space = isl_set_get_space(set);
+ if (isl_space_is_params(space))
+ space = isl_space_set_from_params(space);
+
+ return isl_ast_build_init_derived(build, space);
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_copy(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return NULL;
+
+ build->ref++;
+ return build;
+}
+
+__isl_give isl_ast_build *isl_ast_build_dup(__isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_ast_build *dup;
+
+ if (!build)
+ return NULL;
+
+ ctx = isl_ast_build_get_ctx(build);
+ dup = isl_calloc_type(ctx, isl_ast_build);
+ if (!dup)
+ return NULL;
+
+ dup->ref = 1;
+ dup->outer_pos = build->outer_pos;
+ dup->depth = build->depth;
+ dup->iterators = isl_id_list_copy(build->iterators);
+ dup->domain = isl_set_copy(build->domain);
+ dup->generated = isl_set_copy(build->generated);
+ dup->pending = isl_set_copy(build->pending);
+ dup->values = isl_multi_aff_copy(build->values);
+ dup->value = isl_pw_aff_copy(build->value);
+ dup->strides = isl_vec_copy(build->strides);
+ dup->offsets = isl_multi_aff_copy(build->offsets);
+ dup->executed = isl_union_map_copy(build->executed);
+ dup->single_valued = build->single_valued;
+ dup->options = isl_union_map_copy(build->options);
+ dup->at_each_domain = build->at_each_domain;
+ dup->at_each_domain_user = build->at_each_domain_user;
+ dup->before_each_for = build->before_each_for;
+ dup->before_each_for_user = build->before_each_for_user;
+ dup->after_each_for = build->after_each_for;
+ dup->after_each_for_user = build->after_each_for_user;
+ dup->create_leaf = build->create_leaf;
+ dup->create_leaf_user = build->create_leaf_user;
+
+ if (!dup->iterators || !dup->domain || !dup->generated ||
+ !dup->pending || !dup->values ||
+ !dup->strides || !dup->offsets || !dup->options ||
+ (build->executed && !dup->executed) ||
+ (build->value && !dup->value))
+ return isl_ast_build_free(dup);
+
+ return dup;
+}
+
+/* Align the parameters of "build" to those of "model", introducing
+ * additional parameters if needed.
+ */
+__isl_give isl_ast_build *isl_ast_build_align_params(
+ __isl_take isl_ast_build *build, __isl_take isl_space *model)
+{
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ build->domain = isl_set_align_params(build->domain,
+ isl_space_copy(model));
+ build->generated = isl_set_align_params(build->generated,
+ isl_space_copy(model));
+ build->pending = isl_set_align_params(build->pending,
+ isl_space_copy(model));
+ build->values = isl_multi_aff_align_params(build->values,
+ isl_space_copy(model));
+ build->offsets = isl_multi_aff_align_params(build->offsets,
+ isl_space_copy(model));
+ build->options = isl_union_map_align_params(build->options,
+ isl_space_copy(model));
+ isl_space_free(model);
+
+ if (!build->domain || !build->values || !build->offsets ||
+ !build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_space_free(model);
+ return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_cow(__isl_take isl_ast_build *build)
+{
+ if (!build)
+ return NULL;
+
+ if (build->ref == 1)
+ return build;
+ build->ref--;
+ return isl_ast_build_dup(build);
+}
+
+__isl_null isl_ast_build *isl_ast_build_free(
+ __isl_take isl_ast_build *build)
+{
+ if (!build)
+ return NULL;
+
+ if (--build->ref > 0)
+ return NULL;
+
+ isl_id_list_free(build->iterators);
+ isl_set_free(build->domain);
+ isl_set_free(build->generated);
+ isl_set_free(build->pending);
+ isl_multi_aff_free(build->values);
+ isl_pw_aff_free(build->value);
+ isl_vec_free(build->strides);
+ isl_multi_aff_free(build->offsets);
+ isl_multi_aff_free(build->schedule_map);
+ isl_union_map_free(build->executed);
+ isl_union_map_free(build->options);
+
+ free(build);
+
+ return NULL;
+}
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build)
+{
+ return build ? isl_set_get_ctx(build->domain) : NULL;
+}
+
+/* Replace build->options by "options".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_options(
+ __isl_take isl_ast_build *build, __isl_take isl_union_map *options)
+{
+ build = isl_ast_build_cow(build);
+
+ if (!build || !options)
+ goto error;
+
+ isl_union_map_free(build->options);
+ build->options = options;
+
+ return build;
+error:
+ isl_union_map_free(options);
+ return isl_ast_build_free(build);
+}
+
+/* Set the iterators for the next code generation.
+ *
+ * If we still have some iterators left from the previous code generation
+ * (if any) or if iterators have already been set by a previous
+ * call to this function, then we remove them first.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+ __isl_take isl_ast_build *build, __isl_take isl_id_list *iterators)
+{
+ int dim, n_it;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ dim = isl_set_dim(build->domain, isl_dim_set);
+ n_it = isl_id_list_n_id(build->iterators);
+ if (n_it < dim)
+ isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+ "isl_ast_build in inconsistent state", goto error);
+ if (n_it > dim)
+ build->iterators = isl_id_list_drop(build->iterators,
+ dim, n_it - dim);
+ build->iterators = isl_id_list_concat(build->iterators, iterators);
+ if (!build->iterators)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_id_list_free(iterators);
+ return isl_ast_build_free(build);
+}
+
+/* Set the "at_each_domain" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_at_each_domain(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user), void *user)
+{
+ build = isl_ast_build_cow(build);
+
+ if (!build)
+ return NULL;
+
+ build->at_each_domain = fn;
+ build->at_each_domain_user = user;
+
+ return build;
+}
+
+/* Set the "before_each_for" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_before_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_id *(*fn)(__isl_keep isl_ast_build *build,
+ void *user), void *user)
+{
+ build = isl_ast_build_cow(build);
+
+ if (!build)
+ return NULL;
+
+ build->before_each_for = fn;
+ build->before_each_for_user = user;
+
+ return build;
+}
+
+/* Set the "after_each_for" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_after_each_for(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user), void *user)
+{
+ build = isl_ast_build_cow(build);
+
+ if (!build)
+ return NULL;
+
+ build->after_each_for = fn;
+ build->after_each_for_user = user;
+
+ return build;
+}
+
+/* Set the "create_leaf" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+ __isl_take isl_ast_build *build,
+ __isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+ void *user), void *user)
+{
+ build = isl_ast_build_cow(build);
+
+ if (!build)
+ return NULL;
+
+ build->create_leaf = fn;
+ build->create_leaf_user = user;
+
+ return build;
+}
+
+/* Clear all information that is specific to this code generation
+ * and that is (probably) not meaningful to any nested code generation.
+ */
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+ __isl_take isl_ast_build *build)
+{
+ isl_space *space;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ space = isl_union_map_get_space(build->options);
+ isl_union_map_free(build->options);
+ build->options = isl_union_map_empty(space);
+
+ build->at_each_domain = NULL;
+ build->at_each_domain_user = NULL;
+ build->before_each_for = NULL;
+ build->before_each_for_user = NULL;
+ build->after_each_for = NULL;
+ build->after_each_for_user = NULL;
+ build->create_leaf = NULL;
+ build->create_leaf_user = NULL;
+
+ if (!build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+}
+
+/* Have any loops been eliminated?
+ * That is, do any of the original schedule dimensions have a fixed
+ * value that has been substituted?
+ */
+static int any_eliminated(isl_ast_build *build)
+{
+ int i;
+
+ for (i = 0; i < build->depth; ++i)
+ if (isl_ast_build_has_affine_value(build, i))
+ return 1;
+
+ return 0;
+}
+
+/* Clear build->schedule_map.
+ * This function should be called whenever anything that might affect
+ * the result of isl_ast_build_get_schedule_map_multi_aff changes.
+ * In particular, it should be called when the depth is changed or
+ * when an iterator is determined to have a fixed value.
+ */
+static void isl_ast_build_reset_schedule_map(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return;
+ isl_multi_aff_free(build->schedule_map);
+ build->schedule_map = NULL;
+}
+
+/* Do we need a (non-trivial) schedule map?
+ * That is, is the internal schedule space different from
+ * the external schedule space?
+ *
+ * The internal and external schedule spaces are only the same
+ * if code has been generated for the entire schedule and if none
+ * of the loops have been eliminated.
+ */
+__isl_give int isl_ast_build_need_schedule_map(__isl_keep isl_ast_build *build)
+{
+ int dim;
+
+ if (!build)
+ return -1;
+
+ dim = isl_set_dim(build->domain, isl_dim_set);
+ return build->depth != dim || any_eliminated(build);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_multi_aff.
+ * The internal schedule space originally corresponds to that of the
+ * input schedule. This may change during the code generation if
+ * if isl_ast_build_insert_dim is ever called.
+ * The external schedule space corresponds to the
+ * loops that have been generated.
+ *
+ * Currently, the only difference between the internal schedule domain
+ * and the external schedule domain is that some dimensions are projected
+ * out in the external schedule domain. In particular, the dimensions
+ * for which no code has been generated yet and the dimensions that correspond
+ * to eliminated loops.
+ *
+ * We cache a copy of the schedule_map in build->schedule_map.
+ * The cache is cleared through isl_ast_build_reset_schedule_map
+ * whenever anything changes that might affect the result of this function.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
+ __isl_keep isl_ast_build *build)
+{
+ isl_space *space;
+ isl_multi_aff *ma;
+
+ if (!build)
+ return NULL;
+ if (build->schedule_map)
+ return isl_multi_aff_copy(build->schedule_map);
+
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_map_from_set(space);
+ ma = isl_multi_aff_identity(space);
+ if (isl_ast_build_need_schedule_map(build)) {
+ int i;
+ int dim = isl_set_dim(build->domain, isl_dim_set);
+ ma = isl_multi_aff_drop_dims(ma, isl_dim_out,
+ build->depth, dim - build->depth);
+ for (i = build->depth - 1; i >= 0; --i)
+ if (isl_ast_build_has_affine_value(build, i))
+ ma = isl_multi_aff_drop_dims(ma,
+ isl_dim_out, i, 1);
+ }
+
+ build->schedule_map = ma;
+ return isl_multi_aff_copy(build->schedule_map);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_map.
+ */
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+ __isl_keep isl_ast_build *build)
+{
+ isl_multi_aff *ma;
+
+ ma = isl_ast_build_get_schedule_map_multi_aff(build);
+ return isl_map_from_multi_aff(ma);
+}
+
+/* Return the position of the dimension in build->domain for which
+ * an AST node is currently being generated.
+ */
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build)
+{
+ return build ? build->depth : -1;
+}
+
+/* Prepare for generating code for the next level.
+ * In particular, increase the depth and reset any information
+ * that is local to the current depth.
+ */
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+ __isl_take isl_ast_build *build)
+{
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+ build->depth++;
+ isl_ast_build_reset_schedule_map(build);
+ build->value = isl_pw_aff_free(build->value);
+ return build;
+}
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return;
+
+ fprintf(stderr, "domain: ");
+ isl_set_dump(build->domain);
+ fprintf(stderr, "generated: ");
+ isl_set_dump(build->generated);
+ fprintf(stderr, "pending: ");
+ isl_set_dump(build->pending);
+ fprintf(stderr, "iterators: ");
+ isl_id_list_dump(build->iterators);
+ fprintf(stderr, "values: ");
+ isl_multi_aff_dump(build->values);
+ if (build->value) {
+ fprintf(stderr, "value: ");
+ isl_pw_aff_dump(build->value);
+ }
+ fprintf(stderr, "strides: ");
+ isl_vec_dump(build->strides);
+ fprintf(stderr, "offsets: ");
+ isl_multi_aff_dump(build->offsets);
+}
+
+/* Initialize "build" for AST construction in schedule space "space"
+ * in the case that build->domain is a parameter set.
+ *
+ * build->iterators is assumed to have been updated already.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init(
+ __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+ isl_set *set;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ set = isl_set_universe(isl_space_copy(space));
+ build->domain = isl_set_intersect_params(isl_set_copy(set),
+ build->domain);
+ build->pending = isl_set_intersect_params(isl_set_copy(set),
+ build->pending);
+ build->generated = isl_set_intersect_params(set, build->generated);
+
+ return isl_ast_build_init_derived(build, space);
+error:
+ isl_ast_build_free(build);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Assign "aff" to *user and return -1, effectively extracting
+ * the first (and presumably only) affine expression in the isl_pw_aff
+ * on which this function is used.
+ */
+static int extract_single_piece(__isl_take isl_set *set,
+ __isl_take isl_aff *aff, void *user)
+{
+ isl_aff **p = user;
+
+ *p = aff;
+ isl_set_free(set);
+
+ return -1;
+}
+
+/* Intersect "set" with the stride constraint of "build", if any.
+ */
+static __isl_give isl_set *intersect_stride_constraint(__isl_take isl_set *set,
+ __isl_keep isl_ast_build *build)
+{
+ isl_set *stride;
+
+ if (!build)
+ return isl_set_free(set);
+ if (!isl_ast_build_has_stride(build, build->depth))
+ return set;
+
+ stride = isl_ast_build_get_stride_constraint(build);
+ return isl_set_intersect(set, stride);
+}
+
+/* Check if the given bounds on the current dimension (together with
+ * the stride constraint, if any) imply that
+ * this current dimension attains only a single value (in terms of
+ * parameters and outer dimensions).
+ * If so, we record it in build->value.
+ * If, moreover, this value can be represented as a single affine expression,
+ * then we also update build->values, effectively marking the current
+ * dimension as "eliminated".
+ *
+ * When computing the gist of the fixed value that can be represented
+ * as a single affine expression, it is important to only take into
+ * account the domain constraints in the original AST build and
+ * not the domain of the affine expression itself.
+ * Otherwise, a [i/3] is changed into a i/3 because we know that i
+ * is a multiple of 3, but then we end up not expressing anywhere
+ * in the context that i is a multiple of 3.
+ */
+static __isl_give isl_ast_build *update_values(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+ int sv;
+ isl_pw_multi_aff *pma;
+ isl_aff *aff = NULL;
+ isl_map *it_map;
+ isl_set *set;
+
+ set = isl_set_from_basic_set(bounds);
+ set = isl_set_intersect(set, isl_set_copy(build->domain));
+ set = intersect_stride_constraint(set, build);
+ it_map = isl_ast_build_map_to_iterator(build, set);
+
+ sv = isl_map_is_single_valued(it_map);
+ if (sv < 0)
+ build = isl_ast_build_free(build);
+ if (!build || !sv) {
+ isl_map_free(it_map);
+ return build;
+ }
+
+ pma = isl_pw_multi_aff_from_map(it_map);
+ build->value = isl_pw_multi_aff_get_pw_aff(pma, 0);
+ build->value = isl_ast_build_compute_gist_pw_aff(build, build->value);
+ build->value = isl_pw_aff_coalesce(build->value);
+ isl_pw_multi_aff_free(pma);
+
+ if (!build->value)
+ return isl_ast_build_free(build);
+
+ if (isl_pw_aff_n_piece(build->value) != 1)
+ return build;
+
+ isl_pw_aff_foreach_piece(build->value, &extract_single_piece, &aff);
+
+ build->values = isl_multi_aff_set_aff(build->values, build->depth, aff);
+ if (!build->values)
+ return isl_ast_build_free(build);
+ isl_ast_build_reset_schedule_map(build);
+ return build;
+}
+
+/* Update the AST build based on the given loop bounds for
+ * the current dimension and the stride information available in the build.
+ *
+ * We first make sure that the bounds do not refer to any iterators
+ * that have already been eliminated.
+ * Then, we check if the bounds imply that the current iterator
+ * has a fixed value.
+ * If they do and if this fixed value can be expressed as a single
+ * affine expression, we eliminate the iterators from the bounds.
+ * Note that we cannot simply plug in this single value using
+ * isl_basic_set_preimage_multi_aff as the single value may only
+ * be defined on a subset of the domain. Plugging in the value
+ * would restrict the build domain to this subset, while this
+ * restriction may not be reflected in the generated code.
+ * Finally, we intersect build->domain with the updated bounds.
+ * We also add the stride constraint unless we have been able
+ * to find a fixed value expressed as a single affine expression.
+ *
+ * Note that the check for a fixed value in update_values requires
+ * us to intersect the bounds with the current build domain.
+ * When we intersect build->domain with the updated bounds in
+ * the final step, we make sure that these updated bounds have
+ * not been intersected with the old build->domain.
+ * 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.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
+ __isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+ isl_set *set;
+
+ build = isl_ast_build_cow(build);
+ 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));
+ 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);
+ build->pending = isl_set_intersect(build->pending,
+ 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);
+
+ 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.
+ */
+static __isl_give isl_ast_build *isl_ast_build_restrict_internal(
+ __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ set = isl_set_compute_divs(set);
+ build->domain = isl_set_intersect(build->domain, set);
+ build->domain = isl_set_coalesce(build->domain);
+
+ if (!build->domain)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Intersect build->generated 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_generated(
+ __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->generated = isl_set_intersect(build->generated, set);
+ build->generated = isl_set_coalesce(build->generated);
+
+ if (!build->generated)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Replace the set of pending constraints by "guard", which is then
+ * no longer considered as pending.
+ * That is, add "guard" to the generated constraints and clear all pending
+ * constraints, making the domain equal to the generated constraints.
+ */
+__isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
+ __isl_take isl_ast_build *build, __isl_take isl_set *guard)
+{
+ build = isl_ast_build_restrict_generated(build, guard);
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ isl_set_free(build->domain);
+ build->domain = isl_set_copy(build->generated);
+ isl_set_free(build->pending);
+ build->pending = isl_set_universe(isl_set_get_space(build->domain));
+
+ if (!build->pending)
+ return isl_ast_build_free(build);
+
+ 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.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict(
+ __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+ if (isl_set_is_params(set))
+ return isl_ast_build_restrict_generated(build, set);
+
+ if (isl_ast_build_need_schedule_map(build)) {
+ isl_multi_aff *ma;
+ ma = isl_ast_build_get_schedule_map_multi_aff(build);
+ set = isl_set_preimage_multi_aff(set, ma);
+ }
+ return isl_ast_build_restrict_generated(build, set);
+}
+
+/* Replace build->executed by "executed".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+ __isl_take isl_ast_build *build, __isl_take isl_union_map *executed)
+{
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ isl_union_map_free(build->executed);
+ build->executed = executed;
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_union_map_free(executed);
+ return NULL;
+}
+
+/* Return a copy of the current schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_get_domain(__isl_keep isl_ast_build *build)
+{
+ return build ? isl_set_copy(build->domain) : NULL;
+}
+
+/* Return a copy of the set of pending constraints.
+ */
+__isl_give isl_set *isl_ast_build_get_pending(
+ __isl_keep isl_ast_build *build)
+{
+ return build ? isl_set_copy(build->pending) : NULL;
+}
+
+/* Return a copy of the set of generated constraints.
+ */
+__isl_give isl_set *isl_ast_build_get_generated(
+ __isl_keep isl_ast_build *build)
+{
+ return build ? isl_set_copy(build->generated) : NULL;
+}
+
+/* Return the number of variables of the given type
+ * in the (internal) schedule space.
+ */
+unsigned isl_ast_build_dim(__isl_keep isl_ast_build *build,
+ enum isl_dim_type type)
+{
+ if (!build)
+ return 0;
+ return isl_set_dim(build->domain, type);
+}
+
+/* Return the (schedule) space of "build".
+ *
+ * If "internal" is set, then this space is the space of the internal
+ * representation of the entire schedule, including those parts for
+ * which no code has been generated yet.
+ *
+ * If "internal" is not set, then this space is the external representation
+ * of the loops generated so far.
+ */
+__isl_give isl_space *isl_ast_build_get_space(__isl_keep isl_ast_build *build,
+ int internal)
+{
+ int i;
+ int dim;
+ isl_space *space;
+
+ if (!build)
+ return NULL;
+
+ space = isl_set_get_space(build->domain);
+ if (internal)
+ return space;
+
+ if (!isl_ast_build_need_schedule_map(build))
+ return space;
+
+ dim = isl_set_dim(build->domain, isl_dim_set);
+ space = isl_space_drop_dims(space, isl_dim_set,
+ build->depth, dim - build->depth);
+ for (i = build->depth - 1; i >= 0; --i)
+ if (isl_ast_build_has_affine_value(build, i))
+ space = isl_space_drop_dims(space, isl_dim_set, i, 1);
+
+ return space;
+}
+
+/* Return the external representation of the schedule space of "build",
+ * i.e., a space with a dimension for each loop generated so far,
+ * with the names of the dimensions set to the loop iterators.
+ */
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+ __isl_keep isl_ast_build *build)
+{
+ isl_space *space;
+ int i, skip;
+
+ if (!build)
+ return NULL;
+
+ space = isl_ast_build_get_space(build, 0);
+
+ skip = 0;
+ for (i = 0; i < build->depth; ++i) {
+ isl_id *id;
+
+ if (isl_ast_build_has_affine_value(build, i)) {
+ skip++;
+ continue;
+ }
+
+ id = isl_ast_build_get_iterator_id(build, i);
+ space = isl_space_set_dim_id(space, isl_dim_set, i - skip, id);
+ }
+
+ return space;
+}
+
+/* Return the current schedule, as stored in build->executed, in terms
+ * of the external schedule domain.
+ */
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+ __isl_keep isl_ast_build *build)
+{
+ isl_union_map *executed;
+ isl_union_map *schedule;
+
+ if (!build)
+ return NULL;
+
+ executed = isl_union_map_copy(build->executed);
+ if (isl_ast_build_need_schedule_map(build)) {
+ isl_map *proj = isl_ast_build_get_schedule_map(build);
+ executed = isl_union_map_apply_domain(executed,
+ isl_union_map_from_map(proj));
+ }
+ schedule = isl_union_map_reverse(executed);
+
+ return schedule;
+}
+
+/* Return the iterator attached to the internal schedule dimension "pos".
+ */
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+ __isl_keep isl_ast_build *build, int pos)
+{
+ if (!build)
+ return NULL;
+
+ return isl_id_list_get_id(build->iterators, pos);
+}
+
+/* Set the stride and offset of the current dimension to the given
+ * value and expression.
+ *
+ * If we had already found a stride before, then the two strides
+ * are combined into a single stride.
+ *
+ * In particular, if the new stride information is of the form
+ *
+ * i = f + s (...)
+ *
+ * and the old stride information is of the form
+ *
+ * i = f2 + s2 (...)
+ *
+ * then we compute the extended gcd of s and s2
+ *
+ * a s + b s2 = g,
+ *
+ * with g = gcd(s,s2), multiply the first equation with t1 = b s2/g
+ * and the second with t2 = a s1/g.
+ * This results in
+ *
+ * i = (b s2 + a s1)/g i = t1 f + t2 f2 + (s s2)/g (...)
+ *
+ * so that t1 f + t2 f2 is the combined offset and (s s2)/g = lcm(s,s2)
+ * is the combined stride.
+ */
+static __isl_give isl_ast_build *set_stride(__isl_take isl_ast_build *build,
+ __isl_take isl_val *stride, __isl_take isl_aff *offset)
+{
+ int pos;
+
+ build = isl_ast_build_cow(build);
+ if (!build || !stride || !offset)
+ goto error;
+
+ pos = build->depth;
+
+ if (isl_ast_build_has_stride(build, pos)) {
+ isl_val *stride2, *a, *b, *g;
+ isl_aff *offset2;
+
+ stride2 = isl_vec_get_element_val(build->strides, pos);
+ g = isl_val_gcdext(isl_val_copy(stride), isl_val_copy(stride2),
+ &a, &b);
+ a = isl_val_mul(a, isl_val_copy(stride));
+ a = isl_val_div(a, isl_val_copy(g));
+ stride2 = isl_val_div(stride2, g);
+ b = isl_val_mul(b, isl_val_copy(stride2));
+ stride = isl_val_mul(stride, stride2);
+
+ offset2 = isl_multi_aff_get_aff(build->offsets, pos);
+ offset2 = isl_aff_scale_val(offset2, a);
+ offset = isl_aff_scale_val(offset, b);
+ offset = isl_aff_add(offset, offset2);
+ }
+
+ build->strides = isl_vec_set_element_val(build->strides, pos, stride);
+ build->offsets = isl_multi_aff_set_aff(build->offsets, pos, offset);
+ if (!build->strides || !build->offsets)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_val_free(stride);
+ isl_aff_free(offset);
+ return isl_ast_build_free(build);
+}
+
+/* Return a set expressing the stride constraint at the current depth.
+ *
+ * In particular, if the current iterator (i) is known to attain values
+ *
+ * f + s a
+ *
+ * where f is the offset and s is the stride, then the returned set
+ * expresses the constraint
+ *
+ * (f - i) mod s = 0
+ */
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+ __isl_keep isl_ast_build *build)
+{
+ isl_aff *aff;
+ isl_set *set;
+ isl_val *stride;
+ int pos;
+
+ if (!build)
+ return NULL;
+
+ pos = build->depth;
+
+ if (!isl_ast_build_has_stride(build, pos))
+ return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+ stride = isl_ast_build_get_stride(build, pos);
+ aff = isl_ast_build_get_offset(build, pos);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, pos, -1);
+ aff = isl_aff_mod_val(aff, stride);
+ set = isl_set_from_basic_set(isl_aff_zero_basic_set(aff));
+
+ return set;
+}
+
+/* Return the expansion implied by the stride and offset at the current
+ * depth.
+ *
+ * That is, return the mapping
+ *
+ * [i_0, ..., i_{d-1}, i_d, i_{d+1}, ...]
+ * -> [i_0, ..., i_{d-1}, s * i_d + offset(i), i_{d+1}, ...]
+ *
+ * where s is the stride at the current depth d and offset(i) is
+ * the corresponding offset.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+ __isl_keep isl_ast_build *build)
+{
+ isl_space *space;
+ isl_multi_aff *ma;
+ int pos;
+ isl_aff *aff, *offset;
+ isl_val *stride;
+
+ if (!build)
+ return NULL;
+
+ pos = isl_ast_build_get_depth(build);
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_map_from_set(space);
+ ma = isl_multi_aff_identity(space);
+
+ if (!isl_ast_build_has_stride(build, pos))
+ return ma;
+
+ offset = isl_ast_build_get_offset(build, pos);
+ stride = isl_ast_build_get_stride(build, pos);
+ aff = isl_multi_aff_get_aff(ma, pos);
+ aff = isl_aff_scale_val(aff, stride);
+ aff = isl_aff_add(aff, offset);
+ ma = isl_multi_aff_set_aff(ma, pos, aff);
+
+ return ma;
+}
+
+/* Add constraints corresponding to any previously detected
+ * stride on the current dimension to build->domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+ __isl_take isl_ast_build *build)
+{
+ isl_set *set;
+
+ if (!build)
+ return NULL;
+ if (!isl_ast_build_has_stride(build, build->depth))
+ return build;
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ set = isl_ast_build_get_stride_constraint(build);
+
+ build->domain = isl_set_intersect(build->domain, isl_set_copy(set));
+ build->generated = isl_set_intersect(build->generated, set);
+ if (!build->domain || !build->generated)
+ return isl_ast_build_free(build);
+
+ return build;
+}
+
+/* Information used inside detect_stride.
+ *
+ * "build" may be updated by detect_stride to include stride information.
+ * "pos" is equal to build->depth.
+ */
+struct isl_detect_stride_data {
+ isl_ast_build *build;
+ int pos;
+};
+
+/* Check if constraint "c" imposes any stride on dimension data->pos
+ * and, if so, update the stride information in data->build.
+ *
+ * In order to impose a stride on the dimension, "c" needs to be an equality
+ * and it needs to involve the dimension. Note that "c" may also be
+ * a div constraint and thus an inequality that we cannot use.
+ *
+ * Let c be of the form
+ *
+ * h(p) + g * v * i + g * stride * f(alpha) = 0
+ *
+ * with h(p) an expression in terms of the parameters and outer dimensions
+ * and f(alpha) an expression in terms of the existentially quantified
+ * variables. Note that the inner dimensions have been eliminated so
+ * they do not appear in "c".
+ *
+ * If "stride" is not zero and not one, then it represents a non-trivial stride
+ * on "i". We compute a and b such that
+ *
+ * a v + b stride = 1
+ *
+ * We have
+ *
+ * g v i = -h(p) + g stride f(alpha)
+ *
+ * a g v i = -a h(p) + g stride f(alpha)
+ *
+ * a g v i + b g stride i = -a h(p) + g stride * (...)
+ *
+ * g i = -a h(p) + g stride * (...)
+ *
+ * i = -a h(p)/g + stride * (...)
+ *
+ * The expression "-a h(p)/g" can therefore be used as offset.
+ */
+static int detect_stride(__isl_take isl_constraint *c, void *user)
+{
+ struct isl_detect_stride_data *data = user;
+ int i, n_div;
+ isl_ctx *ctx;
+ isl_val *v, *stride, *m;
+
+ if (!isl_constraint_is_equality(c) ||
+ !isl_constraint_involves_dims(c, isl_dim_set, data->pos, 1)) {
+ isl_constraint_free(c);
+ return 0;
+ }
+
+ ctx = isl_constraint_get_ctx(c);
+ stride = isl_val_zero(ctx);
+ n_div = isl_constraint_dim(c, isl_dim_div);
+ for (i = 0; i < n_div; ++i) {
+ v = isl_constraint_get_coefficient_val(c, isl_dim_div, i);
+ stride = isl_val_gcd(stride, v);
+ }
+
+ v = isl_constraint_get_coefficient_val(c, isl_dim_set, data->pos);
+ m = isl_val_gcd(isl_val_copy(stride), isl_val_copy(v));
+ stride = isl_val_div(stride, isl_val_copy(m));
+ v = isl_val_div(v, isl_val_copy(m));
+
+ if (!isl_val_is_zero(stride) && !isl_val_is_one(stride)) {
+ isl_aff *aff;
+ isl_val *gcd, *a, *b;
+
+ gcd = isl_val_gcdext(v, isl_val_copy(stride), &a, &b);
+ isl_val_free(gcd);
+ isl_val_free(b);
+
+ aff = isl_constraint_get_aff(c);
+ for (i = 0; i < n_div; ++i)
+ aff = isl_aff_set_coefficient_si(aff,
+ isl_dim_div, i, 0);
+ aff = isl_aff_set_coefficient_si(aff, isl_dim_in, data->pos, 0);
+ a = isl_val_neg(a);
+ aff = isl_aff_scale_val(aff, a);
+ aff = isl_aff_scale_down_val(aff, m);
+ data->build = set_stride(data->build, stride, aff);
+ } else {
+ isl_val_free(stride);
+ isl_val_free(m);
+ isl_val_free(v);
+ }
+
+ isl_constraint_free(c);
+ return 0;
+}
+
+/* Check if the constraints in "set" imply any stride on the current
+ * dimension and, if so, record the stride information in "build"
+ * and return the updated "build".
+ *
+ * We compute the affine hull and then check if any of the constraints
+ * in the hull imposes any stride on the current dimension.
+ *
+ * We assume that inner dimensions have been eliminated from "set"
+ * by the caller. This is needed because the common stride
+ * may be imposed by different inner dimensions on different parts of
+ * the domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_detect_strides(
+ __isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+ isl_basic_set *hull;
+ struct isl_detect_stride_data data;
+
+ if (!build)
+ goto error;
+
+ data.build = build;
+ data.pos = isl_ast_build_get_depth(build);
+ hull = isl_set_affine_hull(set);
+
+ if (isl_basic_set_foreach_constraint(hull, &detect_stride, &data) < 0)
+ data.build = isl_ast_build_free(data.build);
+
+ isl_basic_set_free(hull);
+ return data.build;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_ast_build_involves_data {
+ int depth;
+ int involves;
+};
+
+/* Check if "map" involves the input dimension data->depth.
+ */
+static int involves_depth(__isl_take isl_map *map, void *user)
+{
+ struct isl_ast_build_involves_data *data = user;
+
+ data->involves = isl_map_involves_dims(map, isl_dim_in, data->depth, 1);
+ isl_map_free(map);
+
+ if (data->involves < 0 || data->involves)
+ return -1;
+ return 0;
+}
+
+/* Do any options depend on the value of the dimension at the current depth?
+ */
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build)
+{
+ struct isl_ast_build_involves_data data;
+
+ if (!build)
+ return -1;
+
+ data.depth = build->depth;
+ data.involves = 0;
+
+ if (isl_union_map_foreach_map(build->options,
+ &involves_depth, &data) < 0) {
+ if (data.involves < 0 || !data.involves)
+ return -1;
+ }
+
+ return data.involves;
+}
+
+/* Construct the map
+ *
+ * { [i] -> [i] : i < pos; [i] -> [i + 1] : i >= pos }
+ *
+ * with "space" the parameter space of the constructed map.
+ */
+static __isl_give isl_map *construct_insertion_map(__isl_take isl_space *space,
+ int pos)
+{
+ isl_constraint *c;
+ isl_basic_map *bmap1, *bmap2;
+
+ space = isl_space_set_from_params(space);
+ space = isl_space_add_dims(space, isl_dim_set, 1);
+ space = isl_space_map_from_set(space);
+ c = isl_equality_alloc(isl_local_space_from_space(space));
+ c = isl_constraint_set_coefficient_si(c, isl_dim_in, 0, 1);
+ c = isl_constraint_set_coefficient_si(c, isl_dim_out, 0, -1);
+ bmap1 = isl_basic_map_from_constraint(isl_constraint_copy(c));
+ c = isl_constraint_set_constant_si(c, 1);
+ bmap2 = isl_basic_map_from_constraint(c);
+
+ bmap1 = isl_basic_map_upper_bound_si(bmap1, isl_dim_in, 0, pos - 1);
+ bmap2 = isl_basic_map_lower_bound_si(bmap2, isl_dim_in, 0, pos);
+
+ return isl_basic_map_union(bmap1, bmap2);
+}
+
+static const char *option_str[] = {
+ [atomic] = "atomic",
+ [unroll] = "unroll",
+ [separate] = "separate"
+};
+
+/* Update the "options" to reflect the insertion of a dimension
+ * at position "pos" in the schedule domain space.
+ * "space" is the original domain space before the insertion and
+ * may be named and/or structured.
+ *
+ * The (relevant) input options all have "space" as domain, which
+ * has to be mapped to the extended space.
+ * The values of the ranges also refer to the schedule domain positions
+ * and they therefore also need to be adjusted. In particular, values
+ * smaller than pos do not need to change, while values greater than or
+ * equal to pos need to be incremented.
+ * That is, we need to apply the following map.
+ *
+ * { atomic[i] -> atomic[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ * unroll[i] -> unroll[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ * separate[i] -> separate[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ * separation_class[[i] -> [c]]
+ * -> separation_class[[i] -> [c]] : i < pos;
+ * separation_class[[i] -> [c]]
+ * -> separation_class[[i + 1] -> [c]] : i >= pos }
+ */
+static __isl_give isl_union_map *options_insert_dim(
+ __isl_take isl_union_map *options, __isl_take isl_space *space, int pos)
+{
+ isl_map *map;
+ isl_union_map *insertion;
+ enum isl_ast_build_domain_type type;
+ const char *name = "separation_class";
+
+ space = isl_space_map_from_set(space);
+ map = isl_map_identity(space);
+ map = isl_map_insert_dims(map, isl_dim_out, pos, 1);
+ options = isl_union_map_apply_domain(options,
+ isl_union_map_from_map(map));
+
+ if (!options)
+ return NULL;
+
+ map = construct_insertion_map(isl_union_map_get_space(options), pos);
+
+ insertion = isl_union_map_empty(isl_union_map_get_space(options));
+
+ for (type = atomic; type <= separate; ++type) {
+ isl_map *map_type = isl_map_copy(map);
+ const char *name = option_str[type];
+ map_type = isl_map_set_tuple_name(map_type, isl_dim_in, name);
+ map_type = isl_map_set_tuple_name(map_type, isl_dim_out, name);
+ insertion = isl_union_map_add_map(insertion, map_type);
+ }
+
+ map = isl_map_product(map, isl_map_identity(isl_map_get_space(map)));
+ map = isl_map_set_tuple_name(map, isl_dim_in, name);
+ map = isl_map_set_tuple_name(map, isl_dim_out, name);
+ insertion = isl_union_map_add_map(insertion, map);
+
+ options = isl_union_map_apply_range(options, insertion);
+
+ return options;
+}
+
+/* Insert a single dimension in the schedule domain at position "pos".
+ * The new dimension is given an isl_id with the empty string as name.
+ *
+ * The main difficulty is updating build->options to reflect the
+ * extra dimension. This is handled in options_insert_dim.
+ *
+ * Note that because of the dimension manipulations, the resulting
+ * schedule domain space will always be unnamed and unstructured.
+ * However, the original schedule domain space may be named and/or
+ * structured, so we have to take this possibility into account
+ * while performing the transformations.
+ */
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+ __isl_take isl_ast_build *build, int pos)
+{
+ isl_ctx *ctx;
+ isl_space *space, *ma_space;
+ isl_id *id;
+ isl_multi_aff *ma;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ ctx = isl_ast_build_get_ctx(build);
+ id = isl_id_alloc(ctx, "", NULL);
+ space = isl_ast_build_get_space(build, 1);
+ build->iterators = isl_id_list_insert(build->iterators, pos, id);
+ build->domain = isl_set_insert_dims(build->domain,
+ isl_dim_set, pos, 1);
+ build->generated = isl_set_insert_dims(build->generated,
+ isl_dim_set, pos, 1);
+ build->pending = isl_set_insert_dims(build->pending,
+ isl_dim_set, pos, 1);
+ build->strides = isl_vec_insert_els(build->strides, pos, 1);
+ build->strides = isl_vec_set_element_si(build->strides, pos, 1);
+ ma_space = isl_space_params(isl_multi_aff_get_space(build->offsets));
+ ma_space = isl_space_set_from_params(ma_space);
+ ma_space = isl_space_add_dims(ma_space, isl_dim_set, 1);
+ ma_space = isl_space_map_from_set(ma_space);
+ ma = isl_multi_aff_zero(isl_space_copy(ma_space));
+ build->offsets = isl_multi_aff_splice(build->offsets, pos, pos, ma);
+ ma = isl_multi_aff_identity(ma_space);
+ build->values = isl_multi_aff_splice(build->values, pos, pos, ma);
+ build->options = options_insert_dim(build->options, space, pos);
+
+ if (!build->iterators || !build->domain || !build->generated ||
+ !build->pending || !build->values ||
+ !build->strides || !build->offsets || !build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+}
+
+/* Scale down the current dimension by a factor of "m".
+ * "umap" is an isl_union_map that implements the scaling down.
+ * That is, it is of the form
+ *
+ * { [.... i ....] -> [.... i' ....] : i = m i' }
+ *
+ * This function is called right after the strides have been
+ * detected, but before any constraints on the current dimension
+ * have been included in build->domain.
+ * We therefore only need to update stride, offset and the options.
+ */
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+ __isl_take isl_ast_build *build, __isl_take isl_val *m,
+ __isl_take isl_union_map *umap)
+{
+ isl_aff *aff;
+ isl_val *v;
+ int depth;
+
+ build = isl_ast_build_cow(build);
+ if (!build || !umap || !m)
+ goto error;
+
+ depth = build->depth;
+
+ v = isl_vec_get_element_val(build->strides, depth);
+ v = isl_val_div(v, isl_val_copy(m));
+ build->strides = isl_vec_set_element_val(build->strides, depth, v);
+
+ aff = isl_multi_aff_get_aff(build->offsets, depth);
+ aff = isl_aff_scale_down_val(aff, m);
+ build->offsets = isl_multi_aff_set_aff(build->offsets, depth, aff);
+ build->options = isl_union_map_apply_domain(build->options, umap);
+ if (!build->strides || !build->offsets || !build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_val_free(m);
+ isl_union_map_free(umap);
+ return isl_ast_build_free(build);
+}
+
+/* Return a list of "n" isl_ids called "c%d", with "%d" starting at "first".
+ * If an isl_id with such a name already appears among the parameters
+ * in build->domain, then adjust the name to "c%d_%d".
+ */
+static __isl_give isl_id_list *generate_names(isl_ctx *ctx, int n, int first,
+ __isl_keep isl_ast_build *build)
+{
+ int i;
+ isl_id_list *names;
+
+ names = isl_id_list_alloc(ctx, n);
+ for (i = 0; i < n; ++i) {
+ isl_id *id;
+
+ id = generate_name(ctx, first + i, build);
+ names = isl_id_list_add(names, id);
+ }
+
+ return names;
+}
+
+/* Embed "options" into the given isl_ast_build space.
+ *
+ * This function is called from within a nested call to
+ * isl_ast_build_ast_from_schedule.
+ * "options" refers to the additional schedule,
+ * while space refers to both the space of the outer isl_ast_build and
+ * that of the additional schedule.
+ * Specifically, space is of the form
+ *
+ * [I -> S]
+ *
+ * while options lives in the space(s)
+ *
+ * S -> *
+ *
+ * We compute
+ *
+ * [I -> S] -> S
+ *
+ * and compose this with options, to obtain the new options
+ * living in the space(s)
+ *
+ * [I -> S] -> *
+ */
+static __isl_give isl_union_map *embed_options(
+ __isl_take isl_union_map *options, __isl_take isl_space *space)
+{
+ isl_map *map;
+
+ map = isl_map_universe(isl_space_unwrap(space));
+ map = isl_map_range_map(map);
+
+ options = isl_union_map_apply_range(
+ isl_union_map_from_map(map), options);
+
+ return options;
+}
+
+/* Update "build" for use in a (possibly nested) code generation. That is,
+ * extend "build" from an AST build on some domain O to an AST build
+ * on domain [O -> S], with S corresponding to "space".
+ * If the original domain is a parameter domain, then the new domain is
+ * simply S.
+ * "iterators" is a list of iterators for S, but the number of elements
+ * may be smaller or greater than the number of set dimensions of S.
+ * If "keep_iterators" is set, then any extra ids in build->iterators
+ * are reused for S. Otherwise, these extra ids are dropped.
+ *
+ * We first update build->outer_pos to the current depth.
+ * This depth is zero in case this is the outermost code generation.
+ *
+ * We then add additional ids such that the number of iterators is at least
+ * equal to the dimension of the new build domain.
+ *
+ * If the original domain is parametric, then we are constructing
+ * an isl_ast_build for the outer code generation and we pass control
+ * to isl_ast_build_init.
+ *
+ * Otherwise, we adjust the fields of "build" to include "space".
+ */
+__isl_give isl_ast_build *isl_ast_build_product(
+ __isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+ isl_ctx *ctx;
+ isl_vec *strides;
+ isl_set *set;
+ isl_multi_aff *embedding;
+ int dim, n_it;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ goto error;
+
+ build->outer_pos = build->depth;
+
+ ctx = isl_ast_build_get_ctx(build);
+ dim = isl_set_dim(build->domain, isl_dim_set);
+ dim += isl_space_dim(space, isl_dim_set);
+ n_it = isl_id_list_n_id(build->iterators);
+ if (n_it < dim) {
+ isl_id_list *l;
+ l = generate_names(ctx, dim - n_it, n_it, build);
+ build->iterators = isl_id_list_concat(build->iterators, l);
+ }
+
+ if (isl_set_is_params(build->domain))
+ return isl_ast_build_init(build, space);
+
+ set = isl_set_universe(isl_space_copy(space));
+ build->domain = isl_set_product(build->domain, isl_set_copy(set));
+ build->pending = isl_set_product(build->pending, isl_set_copy(set));
+ build->generated = isl_set_product(build->generated, set);
+
+ strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+ strides = isl_vec_set_si(strides, 1);
+ build->strides = isl_vec_concat(build->strides, strides);
+
+ space = isl_space_map_from_set(space);
+ build->offsets = isl_multi_aff_align_params(build->offsets,
+ isl_space_copy(space));
+ build->offsets = isl_multi_aff_product(build->offsets,
+ isl_multi_aff_zero(isl_space_copy(space)));
+ build->values = isl_multi_aff_align_params(build->values,
+ isl_space_copy(space));
+ embedding = isl_multi_aff_identity(space);
+ build->values = isl_multi_aff_product(build->values, embedding);
+
+ space = isl_ast_build_get_space(build, 1);
+ build->options = embed_options(build->options, space);
+
+ if (!build->iterators || !build->domain || !build->generated ||
+ !build->pending || !build->values ||
+ !build->strides || !build->offsets || !build->options)
+ return isl_ast_build_free(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Does "aff" only attain non-negative values over build->domain?
+ * That is, does it not attain any negative values?
+ */
+int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
+ __isl_keep isl_aff *aff)
+{
+ isl_set *test;
+ int empty;
+
+ if (!build)
+ return -1;
+
+ aff = isl_aff_copy(aff);
+ test = isl_set_from_basic_set(isl_aff_neg_basic_set(aff));
+ test = isl_set_intersect(test, isl_set_copy(build->domain));
+ empty = isl_set_is_empty(test);
+ isl_set_free(test);
+
+ return empty;
+}
+
+/* Does the dimension at (internal) position "pos" have a non-trivial stride?
+ */
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos)
+{
+ isl_val *v;
+ int has_stride;
+
+ if (!build)
+ return -1;
+
+ v = isl_vec_get_element_val(build->strides, pos);
+ if (!v)
+ return -1;
+ has_stride = !isl_val_is_one(v);
+ isl_val_free(v);
+
+ return has_stride;
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ * f + s a
+ *
+ * with a an integer, return s through *stride.
+ */
+__isl_give isl_val *isl_ast_build_get_stride(__isl_keep isl_ast_build *build,
+ int pos)
+{
+ if (!build)
+ return NULL;
+
+ return isl_vec_get_element_val(build->strides, pos);
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ * f + s a
+ *
+ * with a an integer, return f.
+ */
+__isl_give isl_aff *isl_ast_build_get_offset(
+ __isl_keep isl_ast_build *build, int pos)
+{
+ if (!build)
+ return NULL;
+
+ return isl_multi_aff_get_aff(build->offsets, pos);
+}
+
+/* Is the dimension at position "pos" known to attain only a single
+ * value that, moreover, can be described by a single affine expression
+ * in terms of the outer dimensions and parameters?
+ *
+ * If not, then the correponding affine expression in build->values
+ * is set to be equal to the same input dimension.
+ * Otherwise, it is set to the requested expression in terms of
+ * outer dimensions and parameters.
+ */
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build,
+ int pos)
+{
+ isl_aff *aff;
+ int involves;
+
+ if (!build)
+ return -1;
+
+ aff = isl_multi_aff_get_aff(build->values, pos);
+ involves = isl_aff_involves_dims(aff, isl_dim_in, pos, 1);
+ isl_aff_free(aff);
+
+ if (involves < 0)
+ return -1;
+
+ return !involves;
+}
+
+/* Plug in the known values (fixed affine expressions in terms of
+ * parameters and outer loop iterators) of all loop iterators
+ * in the domain of "umap".
+ *
+ * We simply precompose "umap" with build->values.
+ */
+__isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain(
+ __isl_keep isl_ast_build *build, __isl_take isl_union_map *umap)
+{
+ isl_multi_aff *values;
+
+ if (!build)
+ return isl_union_map_free(umap);
+
+ values = isl_multi_aff_copy(build->values);
+ umap = isl_union_map_preimage_domain_multi_aff(umap, values);
+
+ return umap;
+}
+
+/* Is the current dimension known to attain only a single value?
+ */
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return -1;
+
+ return build->value != NULL;
+}
+
+/* Simplify the basic set "bset" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "bset" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+ if (!build)
+ goto error;
+
+ bset = isl_basic_set_preimage_multi_aff(bset,
+ isl_multi_aff_copy(build->values));
+ bset = isl_basic_set_gist(bset,
+ isl_set_simple_hull(isl_set_copy(build->domain)));
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Simplify the set "set" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "set" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_compute_gist(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ if (!build)
+ goto error;
+
+ set = isl_set_preimage_multi_aff(set,
+ isl_multi_aff_copy(build->values));
+ set = isl_set_gist(set, isl_set_copy(build->domain));
+
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Include information about what we know about the iterators of
+ * already generated loops to "set".
+ *
+ * We currently only plug in the known affine values of outer loop
+ * iterators.
+ * In principle we could also introduce equalities or even other
+ * constraints implied by the intersection of "set" and build->domain.
+ */
+__isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
+ __isl_take isl_set *set)
+{
+ if (!build)
+ return isl_set_free(set);
+
+ return isl_set_preimage_multi_aff(set,
+ isl_multi_aff_copy(build->values));
+}
+
+/* Simplify the map "map" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "map" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+ __isl_keep isl_ast_build *build, __isl_take isl_map *map)
+{
+ if (!build)
+ goto error;
+
+ map = isl_map_gist_domain(map, isl_set_copy(build->domain));
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Simplify the affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "aff" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_aff *aff)
+{
+ if (!build)
+ goto error;
+
+ aff = isl_aff_gist(aff, isl_set_copy(build->domain));
+
+ return aff;
+error:
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Simplify the piecewise affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "pa" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+ if (!build)
+ goto error;
+
+ if (!isl_set_is_params(build->domain))
+ pa = isl_pw_aff_pullback_multi_aff(pa,
+ isl_multi_aff_copy(build->values));
+ pa = isl_pw_aff_gist(pa, isl_set_copy(build->domain));
+
+ return pa;
+error:
+ isl_pw_aff_free(pa);
+ return NULL;
+}
+
+/* Simplify the piecewise multi-affine expression "aff" based on what
+ * we know about the iterators of already generated loops.
+ *
+ * The domain of "pma" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+ if (!build)
+ goto error;
+
+ pma = isl_pw_multi_aff_pullback_multi_aff(pma,
+ isl_multi_aff_copy(build->values));
+ pma = isl_pw_multi_aff_gist(pma, isl_set_copy(build->domain));
+
+ return pma;
+error:
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Extract the schedule domain of the given type from build->options
+ * at the current depth.
+ *
+ * In particular, find the subset of build->options that is of
+ * the following form
+ *
+ * schedule_domain -> type[depth]
+ *
+ * and return the corresponding domain, after eliminating inner dimensions
+ * and divs that depend on the current dimension.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_set *isl_ast_build_get_option_domain(
+ __isl_keep isl_ast_build *build,
+ enum isl_ast_build_domain_type type)
+{
+ const char *name;
+ isl_space *space;
+ isl_map *option;
+ isl_set *domain;
+ int local_pos;
+
+ if (!build)
+ return NULL;
+
+ name = option_str[type];
+ local_pos = build->depth - build->outer_pos;
+
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ space = isl_space_set_tuple_name(space, isl_dim_out, name);
+
+ option = isl_union_map_extract_map(build->options, space);
+ option = isl_map_fix_si(option, isl_dim_out, 0, local_pos);
+
+ domain = isl_map_domain(option);
+ domain = isl_ast_build_eliminate(build, domain);
+
+ return domain;
+}
+
+/* Extract the separation class mapping at the current depth.
+ *
+ * In particular, find and return the subset of build->options that is of
+ * the following form
+ *
+ * schedule_domain -> separation_class[[depth] -> [class]]
+ *
+ * The caller is expected to eliminate inner dimensions from the domain.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_map *isl_ast_build_get_separation_class(
+ __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_space *space_sep, *space;
+ isl_map *res;
+ int local_pos;
+
+ if (!build)
+ return NULL;
+
+ local_pos = build->depth - build->outer_pos;
+ ctx = isl_ast_build_get_ctx(build);
+ space_sep = isl_space_alloc(ctx, 0, 1, 1);
+ space_sep = isl_space_wrap(space_sep);
+ space_sep = isl_space_set_tuple_name(space_sep, isl_dim_set,
+ "separation_class");
+ space = isl_ast_build_get_space(build, 1);
+ space_sep = isl_space_align_params(space_sep, isl_space_copy(space));
+ space = isl_space_map_from_domain_and_range(space, space_sep);
+
+ res = isl_union_map_extract_map(build->options, space);
+ res = isl_map_fix_si(res, isl_dim_out, 0, local_pos);
+ res = isl_map_coalesce(res);
+
+ return res;
+}
+
+/* Eliminate dimensions inner to the current dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ int dim;
+ int depth;
+
+ if (!build)
+ return isl_set_free(set);
+
+ dim = isl_set_dim(set, isl_dim_set);
+ depth = build->depth;
+ set = isl_set_detect_equalities(set);
+ set = isl_set_eliminate(set, isl_dim_set, depth + 1, dim - (depth + 1));
+
+ return set;
+}
+
+/* Eliminate unknown divs and divs that depend on the current dimension.
+ *
+ * Note that during the elimination of unknown divs, we may discover
+ * an explicit representation of some other unknown divs, which may
+ * depend on the current dimension. We therefore need to eliminate
+ * unknown divs first.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ int depth;
+
+ if (!build)
+ return isl_set_free(set);
+
+ set = isl_set_remove_unknown_divs(set);
+ depth = build->depth;
+ set = isl_set_remove_divs_involving_dims(set, isl_dim_set, depth, 1);
+
+ return set;
+}
+
+/* Eliminate dimensions inner to the current dimension as well as
+ * unknown divs and divs that depend on the current dimension.
+ * The result then consists only of constraints that are independent
+ * of the current dimension and upper and lower bounds on the current
+ * dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *domain)
+{
+ domain = isl_ast_build_eliminate_inner(build, domain);
+ domain = isl_ast_build_eliminate_divs(build, domain);
+ return domain;
+}
+
+/* Replace build->single_valued by "sv".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_single_valued(
+ __isl_take isl_ast_build *build, int sv)
+{
+ if (!build)
+ return build;
+ if (build->single_valued == sv)
+ return build;
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return build;
+ build->single_valued = sv;
+
+ return build;
+}
diff --git a/polly/lib/External/isl/isl_ast_build_expr.c b/polly/lib/External/isl/isl_ast_build_expr.c
new file mode 100644
index 00000000000..2c3bfa3a6f1
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_build_expr.c
@@ -0,0 +1,1779 @@
+/*
+ * Copyright 2012-2014 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/ilp.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_private.h>
+
+/* Compute the "opposite" of the (numerator of the) argument of a div
+ * with denonimator "d".
+ *
+ * In particular, compute
+ *
+ * -aff + (d - 1)
+ */
+static __isl_give isl_aff *oppose_div_arg(__isl_take isl_aff *aff,
+ __isl_take isl_val *d)
+{
+ aff = isl_aff_neg(aff);
+ aff = isl_aff_add_constant_val(aff, d);
+ aff = isl_aff_add_constant_si(aff, -1);
+
+ return aff;
+}
+
+/* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
+ * The result is simplified in terms of build->domain.
+ *
+ * *change_sign is set by this function if the sign of
+ * the expression has changed.
+ * "ls" is known to be non-NULL.
+ *
+ * Let the div be of the form floor(e/d).
+ * If the ast_build_prefer_pdiv option is set then we check if "e"
+ * is non-negative, so that we can generate
+ *
+ * (pdiv_q, expr(e), expr(d))
+ *
+ * instead of
+ *
+ * (fdiv_q, expr(e), expr(d))
+ *
+ * If the ast_build_prefer_pdiv option is set and
+ * if "e" is not non-negative, then we check if "-e + d - 1" is non-negative.
+ * If so, we can rewrite
+ *
+ * floor(e/d) = -ceil(-e/d) = -floor((-e + d - 1)/d)
+ *
+ * and still use pdiv_q.
+ */
+static __isl_give isl_ast_expr *var_div(int *change_sign,
+ __isl_keep isl_local_space *ls,
+ int pos, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx = isl_local_space_get_ctx(ls);
+ isl_aff *aff;
+ isl_ast_expr *num, *den;
+ isl_val *d;
+ enum isl_ast_op_type type;
+
+ aff = isl_local_space_get_div(ls, pos);
+ d = isl_aff_get_denominator_val(aff);
+ aff = isl_aff_scale_val(aff, isl_val_copy(d));
+ den = isl_ast_expr_from_val(isl_val_copy(d));
+
+ type = isl_ast_op_fdiv_q;
+ if (isl_options_get_ast_build_prefer_pdiv(ctx)) {
+ int non_neg = isl_ast_build_aff_is_nonneg(build, aff);
+ if (non_neg >= 0 && !non_neg) {
+ isl_aff *opp = oppose_div_arg(isl_aff_copy(aff),
+ isl_val_copy(d));
+ non_neg = isl_ast_build_aff_is_nonneg(build, opp);
+ if (non_neg >= 0 && non_neg) {
+ *change_sign = 1;
+ isl_aff_free(aff);
+ aff = opp;
+ } else
+ isl_aff_free(opp);
+ }
+ if (non_neg < 0)
+ aff = isl_aff_free(aff);
+ else if (non_neg)
+ type = isl_ast_op_pdiv_q;
+ }
+
+ isl_val_free(d);
+ num = isl_ast_expr_from_aff(aff, build);
+ return isl_ast_expr_alloc_binary(type, num, den);
+}
+
+/* Create an isl_ast_expr evaluating the specified dimension of "ls".
+ * The result is simplified in terms of build->domain.
+ *
+ * *change_sign is set by this function if the sign of
+ * the expression has changed.
+ *
+ * The isl_ast_expr is constructed based on the type of the dimension.
+ * - divs are constructed by var_div
+ * - set variables are constructed from the iterator isl_ids in "build"
+ * - parameters are constructed from the isl_ids in "ls"
+ */
+static __isl_give isl_ast_expr *var(int *change_sign,
+ __isl_keep isl_local_space *ls,
+ enum isl_dim_type type, int pos, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx = isl_local_space_get_ctx(ls);
+ isl_id *id;
+
+ if (type == isl_dim_div)
+ return var_div(change_sign, ls, pos, build);
+
+ if (type == isl_dim_set) {
+ id = isl_ast_build_get_iterator_id(build, pos);
+ return isl_ast_expr_from_id(id);
+ }
+
+ if (!isl_local_space_has_dim_id(ls, type, pos))
+ isl_die(ctx, isl_error_internal, "unnamed dimension",
+ return NULL);
+ id = isl_local_space_get_dim_id(ls, type, pos);
+ return isl_ast_expr_from_id(id);
+}
+
+/* Does "expr" represent the zero integer?
+ */
+static int ast_expr_is_zero(__isl_keep isl_ast_expr *expr)
+{
+ if (!expr)
+ return -1;
+ if (expr->type != isl_ast_expr_int)
+ return 0;
+ return isl_val_is_zero(expr->u.v);
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2",
+ * provided neither of the two expressions is identically zero.
+ */
+static __isl_give isl_ast_expr *ast_expr_add(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ if (!expr1 || !expr2)
+ goto error;
+
+ if (ast_expr_is_zero(expr1)) {
+ isl_ast_expr_free(expr1);
+ return expr2;
+ }
+
+ if (ast_expr_is_zero(expr2)) {
+ isl_ast_expr_free(expr2);
+ return expr1;
+ }
+
+ return isl_ast_expr_add(expr1, expr2);
+error:
+ isl_ast_expr_free(expr1);
+ isl_ast_expr_free(expr2);
+ return NULL;
+}
+
+/* Subtract expr2 from expr1.
+ *
+ * If expr2 is zero, we simply return expr1.
+ * If expr1 is zero, we return
+ *
+ * (isl_ast_op_minus, expr2)
+ *
+ * Otherwise, we return
+ *
+ * (isl_ast_op_sub, expr1, expr2)
+ */
+static __isl_give isl_ast_expr *ast_expr_sub(__isl_take isl_ast_expr *expr1,
+ __isl_take isl_ast_expr *expr2)
+{
+ if (!expr1 || !expr2)
+ goto error;
+
+ if (ast_expr_is_zero(expr2)) {
+ isl_ast_expr_free(expr2);
+ return expr1;
+ }
+
+ if (ast_expr_is_zero(expr1)) {
+ isl_ast_expr_free(expr1);
+ return isl_ast_expr_neg(expr2);
+ }
+
+ return isl_ast_expr_sub(expr1, expr2);
+error:
+ isl_ast_expr_free(expr1);
+ isl_ast_expr_free(expr2);
+ return NULL;
+}
+
+/* Return an isl_ast_expr that represents
+ *
+ * v * (aff mod d)
+ *
+ * v is assumed to be non-negative.
+ * The result is simplified in terms of build->domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_mod(__isl_keep isl_val *v,
+ __isl_keep isl_aff *aff, __isl_keep isl_val *d,
+ __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr;
+ isl_ast_expr *c;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
+
+ c = isl_ast_expr_from_val(isl_val_copy(d));
+ expr = isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr, c);
+
+ if (!isl_val_is_one(v)) {
+ c = isl_ast_expr_from_val(isl_val_copy(v));
+ expr = isl_ast_expr_mul(c, expr);
+ }
+
+ return expr;
+}
+
+/* Create an isl_ast_expr that scales "expr" by "v".
+ *
+ * If v is 1, we simply return expr.
+ * If v is -1, we return
+ *
+ * (isl_ast_op_minus, expr)
+ *
+ * Otherwise, we return
+ *
+ * (isl_ast_op_mul, expr(v), expr)
+ */
+static __isl_give isl_ast_expr *scale(__isl_take isl_ast_expr *expr,
+ __isl_take isl_val *v)
+{
+ isl_ast_expr *c;
+
+ if (!expr || !v)
+ goto error;
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return expr;
+ }
+
+ if (isl_val_is_negone(v)) {
+ isl_val_free(v);
+ expr = isl_ast_expr_neg(expr);
+ } else {
+ c = isl_ast_expr_from_val(v);
+ expr = isl_ast_expr_mul(c, expr);
+ }
+
+ return expr;
+error:
+ isl_val_free(v);
+ isl_ast_expr_free(expr);
+ return NULL;
+}
+
+/* Add an expression for "*v" times the specified dimension of "ls"
+ * to expr.
+ *
+ * Let e be the expression for the specified dimension,
+ * multiplied by the absolute value of "*v".
+ * If "*v" is negative, we create
+ *
+ * (isl_ast_op_sub, expr, e)
+ *
+ * except when expr is trivially zero, in which case we create
+ *
+ * (isl_ast_op_minus, e)
+ *
+ * instead.
+ *
+ * If "*v" is positive, we simply create
+ *
+ * (isl_ast_op_add, expr, e)
+ *
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_add_term(
+ __isl_take isl_ast_expr *expr,
+ __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
+ __isl_take isl_val *v, __isl_keep isl_ast_build *build)
+{
+ isl_ast_expr *term;
+ int change_sign;
+
+ if (!expr)
+ return NULL;
+
+ change_sign = 0;
+ term = var(&change_sign, ls, type, pos, build);
+ if (change_sign)
+ v = isl_val_neg(v);
+
+ if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
+ v = isl_val_neg(v);
+ term = scale(term, v);
+ return ast_expr_sub(expr, term);
+ } else {
+ term = scale(term, v);
+ return ast_expr_add(expr, term);
+ }
+}
+
+/* Add an expression for "v" to expr.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_add_int(
+ __isl_take isl_ast_expr *expr, __isl_take isl_val *v)
+{
+ isl_ctx *ctx;
+ isl_ast_expr *expr_int;
+
+ if (!expr || !v)
+ goto error;
+
+ if (isl_val_is_zero(v)) {
+ isl_val_free(v);
+ return expr;
+ }
+
+ ctx = isl_ast_expr_get_ctx(expr);
+ if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
+ v = isl_val_neg(v);
+ expr_int = isl_ast_expr_from_val(v);
+ return ast_expr_sub(expr, expr_int);
+ } else {
+ expr_int = isl_ast_expr_from_val(v);
+ return ast_expr_add(expr, expr_int);
+ }
+error:
+ isl_ast_expr_free(expr);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Internal data structure used inside extract_modulos.
+ *
+ * If any modulo expressions are detected in "aff", then the
+ * expression is removed from "aff" and added to either "pos" or "neg"
+ * depending on the sign of the coefficient of the modulo expression
+ * inside "aff".
+ *
+ * "add" is an expression that needs to be added to "aff" at the end of
+ * the computation. It is NULL as long as no modulos have been extracted.
+ *
+ * "i" is the position in "aff" of the div under investigation
+ * "v" is the coefficient in "aff" of the div
+ * "div" is the argument of the div, with the denominator removed
+ * "d" is the original denominator of the argument of the div
+ *
+ * "nonneg" is an affine expression that is non-negative over "build"
+ * and that can be used to extract a modulo expression from "div".
+ * In particular, if "sign" is 1, then the coefficients of "nonneg"
+ * are equal to those of "div" modulo "d". If "sign" is -1, then
+ * the coefficients of "nonneg" are opposite to those of "div" modulo "d".
+ * If "sign" is 0, then no such affine expression has been found (yet).
+ */
+struct isl_extract_mod_data {
+ isl_ast_build *build;
+ isl_aff *aff;
+
+ isl_ast_expr *pos;
+ isl_ast_expr *neg;
+
+ isl_aff *add;
+
+ int i;
+ isl_val *v;
+ isl_val *d;
+ isl_aff *div;
+
+ isl_aff *nonneg;
+ int sign;
+};
+
+/* Given that data->v * div_i in data->aff is equal to
+ *
+ * f * (term - (arg mod d))
+ *
+ * with data->d * f = data->v, add
+ *
+ * f * term
+ *
+ * to data->add and
+ *
+ * abs(f) * (arg mod d)
+ *
+ * to data->neg or data->pos depending on the sign of -f.
+ */
+static int extract_term_and_mod(struct isl_extract_mod_data *data,
+ __isl_take isl_aff *term, __isl_take isl_aff *arg)
+{
+ isl_ast_expr *expr;
+ int s;
+
+ data->v = isl_val_div(data->v, isl_val_copy(data->d));
+ s = isl_val_sgn(data->v);
+ data->v = isl_val_abs(data->v);
+ expr = isl_ast_expr_mod(data->v, arg, data->d, data->build);
+ isl_aff_free(arg);
+ if (s > 0)
+ data->neg = ast_expr_add(data->neg, expr);
+ else
+ data->pos = ast_expr_add(data->pos, expr);
+ data->aff = isl_aff_set_coefficient_si(data->aff,
+ isl_dim_div, data->i, 0);
+ if (s < 0)
+ data->v = isl_val_neg(data->v);
+ term = isl_aff_scale_val(data->div, isl_val_copy(data->v));
+
+ if (!data->add)
+ data->add = term;
+ else
+ data->add = isl_aff_add(data->add, term);
+ if (!data->add)
+ return -1;
+
+ return 0;
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ * f * d * floor(div/d)
+ *
+ * with div nonnegative on data->build, rewrite it as
+ *
+ * f * (div - (div mod d)) = f * div - f * (div mod d)
+ *
+ * and add
+ *
+ * f * div
+ *
+ * to data->add and
+ *
+ * abs(f) * (div mod d)
+ *
+ * to data->neg or data->pos depending on the sign of -f.
+ */
+static int extract_mod(struct isl_extract_mod_data *data)
+{
+ return extract_term_and_mod(data, isl_aff_copy(data->div),
+ isl_aff_copy(data->div));
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ * f * d * floor(div/d) (1)
+ *
+ * check if div is non-negative on data->build and, if so,
+ * extract the corresponding modulo from data->aff.
+ * If not, then check if
+ *
+ * -div + d - 1
+ *
+ * is non-negative on data->build. If so, replace (1) by
+ *
+ * -f * d * floor((-div + d - 1)/d)
+ *
+ * and extract the corresponding modulo from data->aff.
+ *
+ * This function may modify data->div.
+ */
+static int extract_nonneg_mod(struct isl_extract_mod_data *data)
+{
+ int mod;
+
+ mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
+ if (mod < 0)
+ goto error;
+ if (mod)
+ return extract_mod(data);
+
+ data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
+ mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
+ if (mod < 0)
+ goto error;
+ if (mod) {
+ data->v = isl_val_neg(data->v);
+ return extract_mod(data);
+ }
+
+ return 0;
+error:
+ data->aff = isl_aff_free(data->aff);
+ return -1;
+}
+
+/* Is the affine expression of constraint "c" "simpler" than data->nonneg
+ * for use in extracting a modulo expression?
+ *
+ * We currently only consider the constant term of the affine expression.
+ * In particular, we prefer the affine expression with the smallest constant
+ * term.
+ * This means that if there are two constraints, say x >= 0 and -x + 10 >= 0,
+ * then we would pick x >= 0
+ *
+ * More detailed heuristics could be used if it turns out that there is a need.
+ */
+static int mod_constraint_is_simpler(struct isl_extract_mod_data *data,
+ __isl_keep isl_constraint *c)
+{
+ isl_val *v1, *v2;
+ int simpler;
+
+ if (!data->nonneg)
+ return 1;
+
+ v1 = isl_val_abs(isl_constraint_get_constant_val(c));
+ v2 = isl_val_abs(isl_aff_get_constant_val(data->nonneg));
+ simpler = isl_val_lt(v1, v2);
+ isl_val_free(v1);
+ isl_val_free(v2);
+
+ return simpler;
+}
+
+/* Check if the coefficients of "c" are either equal or opposite to those
+ * of data->div modulo data->d. If so, and if "c" is "simpler" than
+ * data->nonneg, then replace data->nonneg by the affine expression of "c"
+ * and set data->sign accordingly.
+ *
+ * Both "c" and data->div are assumed not to involve any integer divisions.
+ *
+ * Before we start the actual comparison, we first quickly check if
+ * "c" and data->div have the same non-zero coefficients.
+ * If not, then we assume that "c" is not of the desired form.
+ * Note that while the coefficients of data->div can be reasonably expected
+ * 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.
+ */
+static int check_parallel_or_opposite(__isl_take isl_constraint *c, void *user)
+{
+ struct isl_extract_mod_data *data = user;
+ enum isl_dim_type c_type[2] = { isl_dim_param, isl_dim_set };
+ enum isl_dim_type a_type[2] = { isl_dim_param, isl_dim_in };
+ int i, t;
+ int n[2];
+ int parallel = 1, opposite = 1;
+
+ for (t = 0; t < 2; ++t) {
+ n[t] = isl_constraint_dim(c, c_type[t]);
+ for (i = 0; i < n[t]; ++i) {
+ int a, b;
+
+ a = isl_constraint_involves_dims(c, c_type[t], i, 1);
+ b = isl_aff_involves_dims(data->div, a_type[t], i, 1);
+ if (a != b)
+ parallel = opposite = 0;
+ }
+ }
+
+ for (t = 0; t < 2; ++t) {
+ for (i = 0; i < n[t]; ++i) {
+ isl_val *v1, *v2;
+
+ if (!parallel && !opposite)
+ break;
+ v1 = isl_constraint_get_coefficient_val(c,
+ c_type[t], i);
+ v2 = isl_aff_get_coefficient_val(data->div,
+ a_type[t], i);
+ if (parallel) {
+ v1 = isl_val_sub(v1, isl_val_copy(v2));
+ parallel = isl_val_is_divisible_by(v1, data->d);
+ v1 = isl_val_add(v1, isl_val_copy(v2));
+ }
+ if (opposite) {
+ v1 = isl_val_add(v1, isl_val_copy(v2));
+ opposite = isl_val_is_divisible_by(v1, data->d);
+ }
+ isl_val_free(v1);
+ isl_val_free(v2);
+ }
+ }
+
+ if ((parallel || opposite) && mod_constraint_is_simpler(data, c)) {
+ isl_aff_free(data->nonneg);
+ data->nonneg = isl_constraint_get_aff(c);
+ data->sign = parallel ? 1 : -1;
+ }
+
+ isl_constraint_free(c);
+
+ if (data->sign != 0 && data->nonneg == NULL)
+ return -1;
+
+ return 0;
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ * f * d * floor(div/d) (1)
+ *
+ * see if we can find an expression div' that is non-negative over data->build
+ * and that is related to div through
+ *
+ * div' = div + d * e
+ *
+ * or
+ *
+ * div' = -div + d - 1 + d * e
+ *
+ * with e some affine expression.
+ * If so, we write (1) as
+ *
+ * f * div + f * (div' mod d)
+ *
+ * or
+ *
+ * -f * (-div + d - 1) - f * (div' mod d)
+ *
+ * exploiting (in the second case) the fact that
+ *
+ * f * d * floor(div/d) = -f * d * floor((-div + d - 1)/d)
+ *
+ *
+ * We first try to find an appropriate expression for div'
+ * from the constraints of data->build->domain (which is therefore
+ * guaranteed to be non-negative on data->build), where we remove
+ * any integer divisions from the constraints and skip this step
+ * if "div" itself involves any integer divisions.
+ * If we cannot find an appropriate expression this way, then
+ * we pass control to extract_nonneg_mod where check
+ * if div or "-div + d -1" themselves happen to be
+ * non-negative on data->build.
+ *
+ * While looking for an appropriate constraint in data->build->domain,
+ * we ignore the constant term, so after finding such a constraint,
+ * we still need to fix up the constant term.
+ * In particular, if a is the constant term of "div"
+ * (or d - 1 - the constant term of "div" if data->sign < 0)
+ * and b is the constant term of the constraint, then we need to find
+ * a non-negative constant c such that
+ *
+ * b + c \equiv a mod d
+ *
+ * We therefore take
+ *
+ * c = (a - b) mod d
+ *
+ * and add it to b to obtain the constant term of div'.
+ * If this constant term is "too negative", then we add an appropriate
+ * multiple of d to make it positive.
+ *
+ *
+ * Note that the above is a only a very simple heuristic for finding an
+ * appropriate expression. We could try a bit harder by also considering
+ * sums of constraints that involve disjoint sets of variables or
+ * we could consider arbitrary linear combinations of constraints,
+ * although that could potentially be much more expensive as it involves
+ * the solution of an LP problem.
+ *
+ * In particular, if v_i is a column vector representing constraint i,
+ * w represents div and e_i is the i-th unit vector, then we are looking
+ * for a solution of the constraints
+ *
+ * \sum_i lambda_i v_i = w + \sum_i alpha_i d e_i
+ *
+ * with \lambda_i >= 0 and alpha_i of unrestricted sign.
+ * If we are not just interested in a non-negative expression, but
+ * also in one with a minimal range, then we don't just want
+ * c = \sum_i lambda_i v_i to be non-negative over the domain,
+ * but also beta - c = \sum_i mu_i v_i, where beta is a scalar
+ * that we want to minimize and we now also have to take into account
+ * the constant terms of the constraints.
+ * Alternatively, we could first compute the dual of the domain
+ * and plug in the constraints on the coefficients.
+ */
+static int try_extract_mod(struct isl_extract_mod_data *data)
+{
+ isl_basic_set *hull;
+ isl_val *v1, *v2;
+ int r;
+
+ if (!data->build)
+ goto error;
+
+ int n = isl_aff_dim(data->div, isl_dim_div);
+
+ if (isl_aff_involves_dims(data->div, isl_dim_div, 0, n))
+ return extract_nonneg_mod(data);
+
+ hull = isl_set_simple_hull(isl_set_copy(data->build->domain));
+ hull = isl_basic_set_remove_divs(hull);
+ data->sign = 0;
+ data->nonneg = NULL;
+ r = isl_basic_set_foreach_constraint(hull, &check_parallel_or_opposite,
+ data);
+ isl_basic_set_free(hull);
+
+ if (!data->sign || r < 0) {
+ isl_aff_free(data->nonneg);
+ if (r < 0)
+ goto error;
+ return extract_nonneg_mod(data);
+ }
+
+ v1 = isl_aff_get_constant_val(data->div);
+ v2 = isl_aff_get_constant_val(data->nonneg);
+ if (data->sign < 0) {
+ v1 = isl_val_neg(v1);
+ v1 = isl_val_add(v1, isl_val_copy(data->d));
+ v1 = isl_val_sub_ui(v1, 1);
+ }
+ v1 = isl_val_sub(v1, isl_val_copy(v2));
+ v1 = isl_val_mod(v1, isl_val_copy(data->d));
+ v1 = isl_val_add(v1, v2);
+ v2 = isl_val_div(isl_val_copy(v1), isl_val_copy(data->d));
+ v2 = isl_val_ceil(v2);
+ if (isl_val_is_neg(v2)) {
+ v2 = isl_val_mul(v2, isl_val_copy(data->d));
+ v1 = isl_val_sub(v1, isl_val_copy(v2));
+ }
+ data->nonneg = isl_aff_set_constant_val(data->nonneg, v1);
+ isl_val_free(v2);
+
+ if (data->sign < 0) {
+ data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
+ data->v = isl_val_neg(data->v);
+ }
+
+ return extract_term_and_mod(data,
+ isl_aff_copy(data->div), data->nonneg);
+error:
+ data->aff = isl_aff_free(data->aff);
+ return -1;
+}
+
+/* Check if "data->aff" involves any (implicit) modulo computations based
+ * on div "data->i".
+ * If so, remove them from aff and add expressions corresponding
+ * to those modulo computations to data->pos and/or data->neg.
+ *
+ * "aff" is assumed to be an integer affine expression.
+ *
+ * In particular, check if (v * div_j) is of the form
+ *
+ * f * m * floor(a / m)
+ *
+ * and, if so, rewrite it as
+ *
+ * f * (a - (a mod m)) = f * a - f * (a mod m)
+ *
+ * and extract out -f * (a mod m).
+ * In particular, if f > 0, we add (f * (a mod m)) to *neg.
+ * If f < 0, we add ((-f) * (a mod m)) to *pos.
+ *
+ * Note that in order to represent "a mod m" as
+ *
+ * (isl_ast_op_pdiv_r, a, m)
+ *
+ * we need to make sure that a is non-negative.
+ * If not, we check if "-a + m - 1" is non-negative.
+ * If so, we can rewrite
+ *
+ * floor(a/m) = -ceil(-a/m) = -floor((-a + m - 1)/m)
+ *
+ * and still extract a modulo.
+ */
+static int extract_modulo(struct isl_extract_mod_data *data)
+{
+ data->div = isl_aff_get_div(data->aff, data->i);
+ data->d = isl_aff_get_denominator_val(data->div);
+ if (isl_val_is_divisible_by(data->v, data->d)) {
+ data->div = isl_aff_scale_val(data->div, isl_val_copy(data->d));
+ if (try_extract_mod(data) < 0)
+ data->aff = isl_aff_free(data->aff);
+ }
+ isl_aff_free(data->div);
+ isl_val_free(data->d);
+ return 0;
+}
+
+/* Check if "aff" involves any (implicit) modulo computations.
+ * If so, remove them from aff and add expressions corresponding
+ * to those modulo computations to *pos and/or *neg.
+ * We only do this if the option ast_build_prefer_pdiv is set.
+ *
+ * "aff" is assumed to be an integer affine expression.
+ *
+ * A modulo expression is of the form
+ *
+ * a mod m = a - m * floor(a / m)
+ *
+ * To detect them in aff, we look for terms of the form
+ *
+ * f * m * floor(a / m)
+ *
+ * rewrite them as
+ *
+ * f * (a - (a mod m)) = f * a - f * (a mod m)
+ *
+ * and extract out -f * (a mod m).
+ * In particular, if f > 0, we add (f * (a mod m)) to *neg.
+ * If f < 0, we add ((-f) * (a mod m)) to *pos.
+ */
+static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
+ __isl_keep isl_ast_expr **pos, __isl_keep isl_ast_expr **neg,
+ __isl_keep isl_ast_build *build)
+{
+ struct isl_extract_mod_data data = { build, aff, *pos, *neg };
+ isl_ctx *ctx;
+ int n;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ if (!isl_options_get_ast_build_prefer_pdiv(ctx))
+ return aff;
+
+ n = isl_aff_dim(data.aff, isl_dim_div);
+ for (data.i = 0; data.i < n; ++data.i) {
+ data.v = isl_aff_get_coefficient_val(data.aff,
+ isl_dim_div, data.i);
+ if (!data.v)
+ return isl_aff_free(aff);
+ if (isl_val_is_zero(data.v) ||
+ isl_val_is_one(data.v) || isl_val_is_negone(data.v)) {
+ isl_val_free(data.v);
+ continue;
+ }
+ if (extract_modulo(&data) < 0)
+ data.aff = isl_aff_free(data.aff);
+ isl_val_free(data.v);
+ if (!data.aff)
+ break;
+ }
+
+ if (data.add)
+ data.aff = isl_aff_add(data.aff, data.add);
+
+ *pos = data.pos;
+ *neg = data.neg;
+ return data.aff;
+}
+
+/* Check if aff involves any non-integer coefficients.
+ * If so, split aff into
+ *
+ * aff = aff1 + (aff2 / d)
+ *
+ * with both aff1 and aff2 having only integer coefficients.
+ * Return aff1 and add (aff2 / d) to *expr.
+ */
+static __isl_give isl_aff *extract_rational(__isl_take isl_aff *aff,
+ __isl_keep isl_ast_expr **expr, __isl_keep isl_ast_build *build)
+{
+ int i, j, n;
+ isl_aff *rat = NULL;
+ isl_local_space *ls = NULL;
+ isl_ast_expr *rat_expr;
+ isl_val *v, *d;
+ enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
+ enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
+
+ if (!aff)
+ return NULL;
+ d = isl_aff_get_denominator_val(aff);
+ if (!d)
+ goto error;
+ if (isl_val_is_one(d)) {
+ isl_val_free(d);
+ return aff;
+ }
+
+ aff = isl_aff_scale_val(aff, isl_val_copy(d));
+
+ ls = isl_aff_get_domain_local_space(aff);
+ rat = isl_aff_zero_on_domain(isl_local_space_copy(ls));
+
+ for (i = 0; i < 3; ++i) {
+ n = isl_aff_dim(aff, t[i]);
+ for (j = 0; j < n; ++j) {
+ isl_aff *rat_j;
+
+ v = isl_aff_get_coefficient_val(aff, t[i], j);
+ if (!v)
+ goto error;
+ if (isl_val_is_divisible_by(v, d)) {
+ isl_val_free(v);
+ continue;
+ }
+ rat_j = isl_aff_var_on_domain(isl_local_space_copy(ls),
+ l[i], j);
+ rat_j = isl_aff_scale_val(rat_j, v);
+ rat = isl_aff_add(rat, rat_j);
+ }
+ }
+
+ v = isl_aff_get_constant_val(aff);
+ if (isl_val_is_divisible_by(v, d)) {
+ isl_val_free(v);
+ } else {
+ isl_aff *rat_0;
+
+ rat_0 = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
+ rat = isl_aff_add(rat, rat_0);
+ }
+
+ isl_local_space_free(ls);
+
+ aff = isl_aff_sub(aff, isl_aff_copy(rat));
+ aff = isl_aff_scale_down_val(aff, isl_val_copy(d));
+
+ rat_expr = isl_ast_expr_from_aff(rat, build);
+ rat_expr = isl_ast_expr_div(rat_expr, isl_ast_expr_from_val(d));
+ *expr = ast_expr_add(*expr, rat_expr);
+
+ return aff;
+error:
+ isl_aff_free(rat);
+ isl_local_space_free(ls);
+ isl_aff_free(aff);
+ isl_val_free(d);
+ return NULL;
+}
+
+/* Construct an isl_ast_expr that evaluates the affine expression "aff",
+ * The result is simplified in terms of build->domain.
+ *
+ * We first extract hidden modulo computations from the affine expression
+ * and then add terms for each variable with a non-zero coefficient.
+ * Finally, if the affine expression has a non-trivial denominator,
+ * we divide the resulting isl_ast_expr by this denominator.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+ __isl_keep isl_ast_build *build)
+{
+ int i, j;
+ int n;
+ isl_val *v;
+ isl_ctx *ctx = isl_aff_get_ctx(aff);
+ isl_ast_expr *expr, *expr_neg;
+ enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
+ enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
+ isl_local_space *ls;
+
+ if (!aff)
+ return NULL;
+
+ expr = isl_ast_expr_alloc_int_si(ctx, 0);
+ expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+ aff = extract_rational(aff, &expr, build);
+
+ aff = extract_modulos(aff, &expr, &expr_neg, build);
+ expr = ast_expr_sub(expr, expr_neg);
+
+ ls = isl_aff_get_domain_local_space(aff);
+
+ for (i = 0; i < 3; ++i) {
+ n = isl_aff_dim(aff, t[i]);
+ for (j = 0; j < n; ++j) {
+ v = isl_aff_get_coefficient_val(aff, t[i], j);
+ if (!v)
+ expr = isl_ast_expr_free(expr);
+ if (isl_val_is_zero(v)) {
+ isl_val_free(v);
+ continue;
+ }
+ expr = isl_ast_expr_add_term(expr,
+ ls, l[i], j, v, build);
+ }
+ }
+
+ v = isl_aff_get_constant_val(aff);
+ expr = isl_ast_expr_add_int(expr, v);
+
+ isl_local_space_free(ls);
+ isl_aff_free(aff);
+ return expr;
+}
+
+/* Add terms to "expr" for each variable in "aff" with a coefficient
+ * with sign equal to "sign".
+ * The result is simplified in terms of build->domain.
+ */
+static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
+ __isl_keep isl_aff *aff, int sign, __isl_keep isl_ast_build *build)
+{
+ int i, j;
+ isl_val *v;
+ enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
+ enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
+ isl_local_space *ls;
+
+ ls = isl_aff_get_domain_local_space(aff);
+
+ for (i = 0; i < 3; ++i) {
+ int n = isl_aff_dim(aff, t[i]);
+ for (j = 0; j < n; ++j) {
+ v = isl_aff_get_coefficient_val(aff, t[i], j);
+ if (sign * isl_val_sgn(v) <= 0) {
+ isl_val_free(v);
+ continue;
+ }
+ v = isl_val_abs(v);
+ expr = isl_ast_expr_add_term(expr,
+ ls, l[i], j, v, build);
+ }
+ }
+
+ isl_local_space_free(ls);
+
+ return expr;
+}
+
+/* Should the constant term "v" be considered positive?
+ *
+ * A positive constant will be added to "pos" by the caller,
+ * while a negative constant will be added to "neg".
+ * If either "pos" or "neg" is exactly zero, then we prefer
+ * to add the constant "v" to that side, irrespective of the sign of "v".
+ * This results in slightly shorter expressions and may reduce the risk
+ * of overflows.
+ */
+static int constant_is_considered_positive(__isl_keep isl_val *v,
+ __isl_keep isl_ast_expr *pos, __isl_keep isl_ast_expr *neg)
+{
+ if (ast_expr_is_zero(pos))
+ return 1;
+ if (ast_expr_is_zero(neg))
+ return 0;
+ return isl_val_is_pos(v);
+}
+
+/* Check if the equality
+ *
+ * aff = 0
+ *
+ * represents a stride constraint on the integer division "pos".
+ *
+ * In particular, if the integer division "pos" is equal to
+ *
+ * floor(e/d)
+ *
+ * then check if aff is equal to
+ *
+ * e - d floor(e/d)
+ *
+ * or its opposite.
+ *
+ * If so, the equality is exactly
+ *
+ * e mod d = 0
+ *
+ * Note that in principle we could also accept
+ *
+ * e - d floor(e'/d)
+ *
+ * where e and e' differ by a constant.
+ */
+static int is_stride_constraint(__isl_keep isl_aff *aff, int pos)
+{
+ isl_aff *div;
+ isl_val *c, *d;
+ int eq;
+
+ div = isl_aff_get_div(aff, pos);
+ c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
+ d = isl_aff_get_denominator_val(div);
+ eq = isl_val_abs_eq(c, d);
+ if (eq >= 0 && eq) {
+ aff = isl_aff_copy(aff);
+ aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
+ div = isl_aff_scale_val(div, d);
+ if (isl_val_is_pos(c))
+ div = isl_aff_neg(div);
+ eq = isl_aff_plain_is_equal(div, aff);
+ isl_aff_free(aff);
+ } else
+ isl_val_free(d);
+ isl_val_free(c);
+ isl_aff_free(div);
+
+ return eq;
+}
+
+/* Are all coefficients of "aff" (zero or) negative?
+ */
+static int all_negative_coefficients(__isl_keep isl_aff *aff)
+{
+ int i, n;
+
+ if (!aff)
+ return 0;
+
+ n = isl_aff_dim(aff, isl_dim_param);
+ for (i = 0; i < n; ++i)
+ if (isl_aff_coefficient_sgn(aff, isl_dim_param, i) > 0)
+ return 0;
+
+ n = isl_aff_dim(aff, isl_dim_in);
+ for (i = 0; i < n; ++i)
+ if (isl_aff_coefficient_sgn(aff, isl_dim_in, i) > 0)
+ return 0;
+
+ return 1;
+}
+
+/* Give an equality of the form
+ *
+ * aff = e - d floor(e/d) = 0
+ *
+ * or
+ *
+ * aff = -e + d floor(e/d) = 0
+ *
+ * with the integer division "pos" equal to floor(e/d),
+ * construct the AST expression
+ *
+ * (isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(e), expr(d)), expr(0))
+ *
+ * If e only has negative coefficients, then construct
+ *
+ * (isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(-e), expr(d)), expr(0))
+ *
+ * instead.
+ */
+static __isl_give isl_ast_expr *extract_stride_constraint(
+ __isl_take isl_aff *aff, int pos, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_val *c;
+ isl_ast_expr *expr, *cst;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+
+ c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
+ aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
+
+ if (all_negative_coefficients(aff))
+ aff = isl_aff_neg(aff);
+
+ cst = isl_ast_expr_from_val(isl_val_abs(c));
+ expr = isl_ast_expr_from_aff(aff, build);
+
+ expr = isl_ast_expr_alloc_binary(isl_ast_op_zdiv_r, expr, cst);
+ cst = isl_ast_expr_alloc_int_si(ctx, 0);
+ expr = isl_ast_expr_alloc_binary(isl_ast_op_eq, expr, cst);
+
+ return expr;
+}
+
+/* Construct an isl_ast_expr that evaluates the condition "constraint",
+ * The result is simplified in terms of build->domain.
+ *
+ * We first check if the constraint is an equality of the form
+ *
+ * e - d floor(e/d) = 0
+ *
+ * i.e.,
+ *
+ * e mod d = 0
+ *
+ * If so, we convert it to
+ *
+ * (isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(e), expr(d)), expr(0))
+ *
+ * Otherwise, let the constraint by either "a >= 0" or "a == 0".
+ * We first extract hidden modulo computations from "a"
+ * and then collect all the terms with a positive coefficient in cons_pos
+ * and the terms with a negative coefficient in cons_neg.
+ *
+ * The result is then of the form
+ *
+ * (isl_ast_op_ge, expr(pos), expr(-neg)))
+ *
+ * or
+ *
+ * (isl_ast_op_eq, expr(pos), expr(-neg)))
+ *
+ * However, if the first expression is an integer constant (and the second
+ * is not), then we swap the two expressions. This ensures that we construct,
+ * e.g., "i <= 5" rather than "5 >= i".
+ *
+ * Furthermore, is there are no terms with positive coefficients (or no terms
+ * with negative coefficients), then the constant term is added to "pos"
+ * (or "neg"), ignoring the sign of the constant term.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
+ __isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_ast_expr *expr_pos;
+ isl_ast_expr *expr_neg;
+ isl_ast_expr *expr;
+ isl_aff *aff;
+ isl_val *v;
+ int eq;
+ enum isl_ast_op_type type;
+
+ if (!constraint)
+ return NULL;
+
+ aff = isl_constraint_get_aff(constraint);
+ eq = isl_constraint_is_equality(constraint);
+ isl_constraint_free(constraint);
+
+ n = isl_aff_dim(aff, isl_dim_div);
+ if (eq && n > 0)
+ for (i = 0; i < n; ++i) {
+ int is_stride;
+ is_stride = is_stride_constraint(aff, i);
+ if (is_stride < 0)
+ goto error;
+ if (is_stride)
+ return extract_stride_constraint(aff, i, build);
+ }
+
+ ctx = isl_aff_get_ctx(aff);
+ expr_pos = isl_ast_expr_alloc_int_si(ctx, 0);
+ expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+ aff = extract_modulos(aff, &expr_pos, &expr_neg, build);
+
+ expr_pos = add_signed_terms(expr_pos, aff, 1, build);
+ expr_neg = add_signed_terms(expr_neg, aff, -1, build);
+
+ v = isl_aff_get_constant_val(aff);
+ if (constant_is_considered_positive(v, expr_pos, expr_neg)) {
+ expr_pos = isl_ast_expr_add_int(expr_pos, v);
+ } else {
+ v = isl_val_neg(v);
+ expr_neg = isl_ast_expr_add_int(expr_neg, v);
+ }
+
+ if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
+ isl_ast_expr_get_type(expr_neg) != isl_ast_expr_int) {
+ type = eq ? isl_ast_op_eq : isl_ast_op_le;
+ expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
+ } else {
+ type = eq ? isl_ast_op_eq : isl_ast_op_ge;
+ expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
+ }
+
+ isl_aff_free(aff);
+ return expr;
+error:
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Wrapper around isl_constraint_cmp_last_non_zero for use
+ * as a callback to isl_constraint_list_sort.
+ * If isl_constraint_cmp_last_non_zero cannot tell the constraints
+ * apart, then use isl_constraint_plain_cmp instead.
+ */
+static int cmp_constraint(__isl_keep isl_constraint *a,
+ __isl_keep isl_constraint *b, void *user)
+{
+ int cmp;
+
+ cmp = isl_constraint_cmp_last_non_zero(a, b);
+ if (cmp != 0)
+ return cmp;
+ return isl_constraint_plain_cmp(a, b);
+}
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "bset".
+ * The result is simplified in terms of build->domain.
+ *
+ * If "bset" is not bounded by any constraint, then we contruct
+ * the expression "1", i.e., "true".
+ *
+ * Otherwise, we sort the constraints, putting constraints that involve
+ * integer divisions after those that do not, and construct an "and"
+ * of the ast expressions of the individual constraints.
+ *
+ * Each constraint is added to the generated constraints of the build
+ * after it has been converted to an AST expression so that it can be used
+ * to simplify the following constraints. This may change the truth value
+ * of subsequent constraints that do not satisfy the earlier constraints,
+ * but this does not affect the outcome of the conjunction as it is
+ * only true if all the conjuncts are true (no matter in what order
+ * they are evaluated). In particular, the constraints that do not
+ * involve integer divisions may serve to simplify some constraints
+ * that do involve integer divisions.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+ int i, n;
+ isl_constraint *c;
+ isl_constraint_list *list;
+ isl_ast_expr *res;
+ isl_set *set;
+
+ list = isl_basic_set_get_constraint_list(bset);
+ isl_basic_set_free(bset);
+ list = isl_constraint_list_sort(list, &cmp_constraint, NULL);
+ if (!list)
+ return NULL;
+ n = isl_constraint_list_n_constraint(list);
+ if (n == 0) {
+ isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+ isl_constraint_list_free(list);
+ return isl_ast_expr_alloc_int_si(ctx, 1);
+ }
+
+ build = isl_ast_build_copy(build);
+
+ c = isl_constraint_list_get_constraint(list, 0);
+ bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
+ set = isl_set_from_basic_set(bset);
+ res = isl_ast_expr_from_constraint(c, build);
+ build = isl_ast_build_restrict_generated(build, set);
+
+ for (i = 1; i < n; ++i) {
+ isl_ast_expr *expr;
+
+ c = isl_constraint_list_get_constraint(list, i);
+ bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
+ set = isl_set_from_basic_set(bset);
+ expr = isl_ast_expr_from_constraint(c, build);
+ build = isl_ast_build_restrict_generated(build, set);
+ res = isl_ast_expr_and(res, expr);
+ }
+
+ isl_constraint_list_free(list);
+ isl_ast_build_free(build);
+ 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 int 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 -1;
+ return 0;
+}
+
+/* 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".
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+ struct isl_expr_from_set_data data = { build, 1, NULL };
+
+ if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
+ data.res = isl_ast_expr_free(data.res);
+ else if (data.first) {
+ isl_ctx *ctx = isl_ast_build_get_ctx(build);
+ data.res = isl_ast_expr_from_val(isl_val_zero(ctx));
+ }
+
+ isl_set_free(set);
+ return data.res;
+}
+
+struct isl_from_pw_aff_data {
+ isl_ast_build *build;
+ int n;
+ isl_ast_expr **next;
+ isl_set *dom;
+};
+
+/* This function is called during the construction of an isl_ast_expr
+ * that evaluates an isl_pw_aff.
+ * Adjust data->next to take into account this piece.
+ *
+ * data->n is the number of pairs of set and aff to go.
+ * data->dom is the domain of the entire isl_pw_aff.
+ *
+ * If this is the last pair, then data->next is set to evaluate aff
+ * and the domain is ignored.
+ * Otherwise, data->next is set to a select operation that selects
+ * an isl_ast_expr correponding to "aff" on "set" and to an expression
+ * that will be filled in by later calls otherwise.
+ *
+ * In both cases, the constraints of "set" are added to the generated
+ * constraints of the build such that they can be exploited to simplify
+ * the AST expression constructed from "aff".
+ */
+static int ast_expr_from_pw_aff(__isl_take isl_set *set,
+ __isl_take isl_aff *aff, void *user)
+{
+ struct isl_from_pw_aff_data *data = user;
+ isl_ctx *ctx;
+ isl_ast_build *build;
+
+ ctx = isl_set_get_ctx(set);
+ data->n--;
+ if (data->n == 0) {
+ build = isl_ast_build_copy(data->build);
+ build = isl_ast_build_restrict_generated(build, set);
+ *data->next = isl_ast_expr_from_aff(aff, build);
+ isl_ast_build_free(build);
+ if (!*data->next)
+ return -1;
+ } else {
+ isl_ast_expr *ternary, *arg;
+ isl_set *gist;
+
+ ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
+ gist = isl_set_gist(isl_set_copy(set), isl_set_copy(data->dom));
+ arg = isl_ast_build_expr_from_set(data->build, gist);
+ ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
+ build = isl_ast_build_copy(data->build);
+ build = isl_ast_build_restrict_generated(build, set);
+ arg = isl_ast_expr_from_aff(aff, build);
+ isl_ast_build_free(build);
+ ternary = isl_ast_expr_set_op_arg(ternary, 1, arg);
+ if (!ternary)
+ return -1;
+
+ *data->next = ternary;
+ data->next = &ternary->u.op.args[2];
+ }
+
+ return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the internal schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+ struct isl_from_pw_aff_data data;
+ isl_ast_expr *res = NULL;
+
+ pa = isl_ast_build_compute_gist_pw_aff(build, pa);
+ pa = isl_pw_aff_coalesce(pa);
+ if (!pa)
+ return NULL;
+
+ data.build = build;
+ data.n = isl_pw_aff_n_piece(pa);
+ data.next = &res;
+ data.dom = isl_pw_aff_domain(isl_pw_aff_copy(pa));
+
+ if (isl_pw_aff_foreach_piece(pa, &ast_expr_from_pw_aff, &data) < 0)
+ res = isl_ast_expr_free(res);
+ else if (!res)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "cannot handle void expression", res = NULL);
+
+ isl_pw_aff_free(pa);
+ isl_set_free(data.dom);
+ return res;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the external schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+ isl_ast_expr *expr;
+
+ if (isl_ast_build_need_schedule_map(build)) {
+ isl_multi_aff *ma;
+ ma = isl_ast_build_get_schedule_map_multi_aff(build);
+ pa = isl_pw_aff_pullback_multi_aff(pa, ma);
+ }
+ expr = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+ return expr;
+}
+
+/* Set the ids of the input dimensions of "mpa" to the iterator ids
+ * of "build".
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_multi_pw_aff *set_iterator_names(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+ int i, n;
+
+ n = isl_multi_pw_aff_dim(mpa, isl_dim_in);
+ for (i = 0; i < n; ++i) {
+ isl_id *id;
+
+ id = isl_ast_build_get_iterator_id(build, i);
+ mpa = isl_multi_pw_aff_set_dim_id(mpa, isl_dim_in, i, id);
+ }
+
+ return mpa;
+}
+
+/* Construct an isl_ast_expr of type "type" with as first argument "arg0" and
+ * the remaining arguments derived from "mpa".
+ * That is, construct a call or access expression that calls/accesses "arg0"
+ * with arguments/indices specified by "mpa".
+ */
+static __isl_give isl_ast_expr *isl_ast_build_with_arguments(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_ast_expr *arg0, __isl_take isl_multi_pw_aff *mpa)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_ast_expr *expr;
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
+ expr = isl_ast_expr_alloc_op(ctx, type, 1 + n);
+ expr = isl_ast_expr_set_op_arg(expr, 0, arg0);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ isl_ast_expr *arg;
+
+ pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
+ arg = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+ expr = isl_ast_expr_set_op_arg(expr, 1 + i, arg);
+ }
+
+ isl_multi_pw_aff_free(mpa);
+ return expr;
+}
+
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_multi_pw_aff *mpa);
+
+/* Construct an isl_ast_expr that accesses the member specified by "mpa".
+ * The range of "mpa" is assumed to be wrapped relation.
+ * The domain of this wrapped relation specifies the structure being
+ * accessed, while the range of this wrapped relation spacifies the
+ * member of the structure being accessed.
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+ isl_id *id;
+ isl_multi_pw_aff *domain;
+ isl_ast_expr *domain_expr, *expr;
+ enum isl_ast_op_type type = isl_ast_op_access;
+
+ domain = isl_multi_pw_aff_copy(mpa);
+ domain = isl_multi_pw_aff_range_factor_domain(domain);
+ domain_expr = isl_ast_build_from_multi_pw_aff_internal(build,
+ type, domain);
+ mpa = isl_multi_pw_aff_range_factor_range(mpa);
+ if (!isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
+ isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
+ "missing field name", goto error);
+ id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
+ expr = isl_ast_expr_from_id(id);
+ expr = isl_ast_expr_alloc_binary(isl_ast_op_member, domain_expr, expr);
+ return isl_ast_build_with_arguments(build, type, expr, mpa);
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "mpa".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * If the range of "mpa" is a mapped relation, then we assume it
+ * represents an access to a member of a structure.
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ isl_ctx *ctx;
+ isl_id *id;
+ isl_ast_expr *expr;
+
+ if (!mpa)
+ goto error;
+
+ if (type == isl_ast_op_access &&
+ isl_multi_pw_aff_range_is_wrapping(mpa))
+ return isl_ast_build_from_multi_pw_aff_member(build, mpa);
+
+ mpa = set_iterator_names(build, mpa);
+ if (!build || !mpa)
+ goto error;
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ if (isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
+ id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
+ else
+ id = isl_id_alloc(ctx, "", NULL);
+
+ expr = isl_ast_expr_from_id(id);
+ return isl_ast_build_with_arguments(build, type, expr, mpa);
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "pma".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff_internal(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ isl_multi_pw_aff *mpa;
+
+ mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
+ return isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "mpa".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ int is_domain;
+ isl_ast_expr *expr;
+ isl_space *space_build, *space_mpa;
+
+ space_build = isl_ast_build_get_space(build, 0);
+ space_mpa = isl_multi_pw_aff_get_space(mpa);
+ is_domain = isl_space_tuple_is_equal(space_build, isl_dim_set,
+ space_mpa, isl_dim_in);
+ isl_space_free(space_build);
+ isl_space_free(space_mpa);
+ if (is_domain < 0)
+ goto error;
+ if (!is_domain)
+ isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ if (isl_ast_build_need_schedule_map(build)) {
+ isl_multi_aff *ma;
+ ma = isl_ast_build_get_schedule_map_multi_aff(build);
+ mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
+ }
+
+ expr = isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
+ return expr;
+error:
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "mpa".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+ return isl_ast_build_from_multi_pw_aff(build, isl_ast_op_call, mpa);
+}
+
+/* Construct an isl_ast_expr that accesses the array element specified by "mpa".
+ * The name of the array is obtained from the output tuple name.
+ * The index expressions are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+ return isl_ast_build_from_multi_pw_aff(build, isl_ast_op_access, mpa);
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "pma".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ isl_multi_pw_aff *mpa;
+
+ mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
+ return isl_ast_build_from_multi_pw_aff(build, type, mpa);
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "pma".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+ return isl_ast_build_from_pw_multi_aff(build, isl_ast_op_call, pma);
+}
+
+/* Construct an isl_ast_expr that accesses the array element specified by "pma".
+ * The name of the array is obtained from the output tuple name.
+ * The index expressions are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+ return isl_ast_build_from_pw_multi_aff(build, isl_ast_op_access, pma);
+}
+
+/* Construct an isl_ast_expr that calls the domain element
+ * specified by "executed".
+ *
+ * "executed" is assumed to be single-valued, with a domain that lives
+ * in the internal schedule space.
+ */
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+ __isl_keep isl_ast_build *build, __isl_take isl_map *executed)
+{
+ isl_pw_multi_aff *iteration;
+ isl_ast_expr *expr;
+
+ iteration = isl_pw_multi_aff_from_map(executed);
+ iteration = isl_ast_build_compute_gist_pw_multi_aff(build, iteration);
+ iteration = isl_pw_multi_aff_intersect_domain(iteration,
+ isl_ast_build_get_domain(build));
+ expr = isl_ast_build_from_pw_multi_aff_internal(build, isl_ast_op_call,
+ iteration);
+ return isl_ast_node_alloc_user(expr);
+}
diff --git a/polly/lib/External/isl/isl_ast_build_expr.h b/polly/lib/External/isl/isl_ast_build_expr.h
new file mode 100644
index 00000000000..bf3af04cb06
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_build_expr.h
@@ -0,0 +1,22 @@
+#ifndef ISL_AST_BUILD_EXPR_PRIVATE_H
+#define ISL_AST_BUILD_EXPR_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+ __isl_keep isl_ast_build *build);
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+ int pos, __isl_take isl_ast_expr *arg);
+
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+ __isl_keep isl_ast_build *build, __isl_take isl_map *executed);
+
+#endif
diff --git a/polly/lib/External/isl/isl_ast_build_private.h b/polly/lib/External/isl/isl_ast_build_private.h
new file mode 100644
index 00000000000..62c66b8263c
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_build_private.h
@@ -0,0 +1,267 @@
+#ifndef ISL_AST_BUILD_PRIVATE_H
+#define ISL_AST_BUILD_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+#include <isl/set.h>
+#include <isl/list.h>
+
+enum isl_ast_build_domain_type {
+ atomic,
+ unroll,
+ separate
+};
+
+/* An isl_ast_build represents the context in which AST is being
+ * generated. That is, it (mostly) contains information about outer
+ * loops that can be used to simplify inner loops.
+ *
+ * "domain" represents constraints on the internal schedule domain,
+ * corresponding to the context of the AST generation and the constraints
+ * implied by the loops that have already been generated.
+ * When an isl_ast_build is first created, outside any AST generation,
+ * the domain is typically a parameter set. It is only when a AST
+ * generation phase is initiated that the domain of the isl_ast_build
+ * is changed to refer to the internal schedule domain.
+ * The domain then lives in a space of the form
+ *
+ * S
+ *
+ * or
+ *
+ * [O -> S]
+ *
+ * O represents the loops generated in outer AST generations.
+ * S represents the loops (both generated and to be generated)
+ * of the current AST generation.
+ * Both include eliminated loops.
+ * "domain" is expected not to have any unknown divs because
+ * it is used as the context argument in a call to isl_basic_set_gist
+ * in isl_ast_build_compute_gist_basic_set.
+ *
+ * "depth" is equal to the number of loops that have already
+ * been generated (including those in outer AST generations).
+ * "outer_pos" is equal to the number of loops in outer AST generations.
+ *
+ * "generated" is a superset of "domain" corresponding to those
+ * constraints that were either given by the user or that have
+ * effectively been generated (as bounds on a for loop).
+ *
+ * "pending" is a superset of "domain" corresponding to the constraints
+ * that still need to be generated (as guards), but that may end up
+ * not getting generated if they are implied by any constraints
+ * enforced by inner loops.
+ *
+ * "strides" contains the stride of each loop. The number of elements
+ * is equal to the number of dimensions in "domain".
+ * "offsets" constains the offsets of strided loops. If s is the stride
+ * for a given dimension and f is the corresponding offset, then the
+ * dimension takes on values
+ *
+ * f + s a
+ *
+ * with a an integer. For non-strided loops, the offset is zero.
+ *
+ * "iterators" contains the loop iterators of both generated and
+ * to be generated loops. The number of elements is at least as
+ * large as the dimension of the internal schedule domain. The
+ * number may be larger, in which case the additional ids can be
+ * used in a nested AST generation should the schedule be non-injective.
+ *
+ * "values" lives in the space
+ *
+ * [O -> S] -> [O -> S] (or S -> S)
+ *
+ * and expresses (if possible) loop iterators in terms of parameters
+ * and outer loop iterators. If the value of a given loop iterator
+ * cannot be expressed as an affine expression (either because the iterator
+ * attains multiple values or because the single value is a piecewise
+ * affine expression), then it is expressed in "values" as being equal
+ * to itself.
+ *
+ * "value" is the value of the loop iterator at the current depth.
+ * It is NULL if it has not been computed yet or if the value of the
+ * given loop iterator cannot be expressed as a piecewise affine expression
+ * (because the iterator attains multiple values).
+ *
+ * "schedule_map" maps the internal schedule domain to the external schedule
+ * domain. It may be NULL if it hasn't been computed yet.
+ * See isl_ast_build_get_schedule_map_multi_aff.
+ *
+ * The "create_leaf" callback is called for every leaf in the generated AST.
+ * The callback is responsible for creating the node to be placed at those
+ * leaves. If this callback is not set, then isl will generated user
+ * nodes with call expressions corresponding to an element of the domain.
+ *
+ * The "at_each_domain" callback is called on every node created to represent
+ * an element of the domain. Each of these nodes is a user node
+ * with as expression a call expression.
+ *
+ * The "before_each_for" callback is called on each for node before
+ * its children have been created.
+ *
+ * The "after_each_for" callback is called on each for node after
+ * its children have been created.
+ *
+ * "executed" contains the inverse schedule at this point
+ * of the AST generation.
+ * It is currently only used in isl_ast_build_get_schedule, which is
+ * in turn only used by user code from within a callback.
+ * The value is set right before we may be calling such a callback.
+ *
+ * "single_valued" is set if the current inverse schedule (which may or may
+ * not be stored in "executed") is known to be single valued, specifically
+ * an inverse schedule that was not (appeared not to be) single valued
+ * is extended to a single valued inverse schedule. This is mainly used
+ * to avoid an infinite recursion when we fail to detect later on that
+ * the extended inverse schedule is single valued.
+ */
+struct isl_ast_build {
+ int ref;
+
+ int outer_pos;
+ int depth;
+
+ isl_id_list *iterators;
+
+ isl_set *domain;
+ isl_set *generated;
+ isl_set *pending;
+ isl_multi_aff *values;
+
+ isl_pw_aff *value;
+
+ isl_vec *strides;
+ isl_multi_aff *offsets;
+
+ isl_multi_aff *schedule_map;
+
+ isl_union_map *options;
+
+ __isl_give isl_ast_node *(*at_each_domain)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user);
+ void *at_each_domain_user;
+
+ __isl_give isl_id *(*before_each_for)(
+ __isl_keep isl_ast_build *context, void *user);
+ void *before_each_for_user;
+ __isl_give isl_ast_node *(*after_each_for)(
+ __isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *context, void *user);
+ void *after_each_for_user;
+
+ __isl_give isl_ast_node *(*create_leaf)(
+ __isl_take isl_ast_build *build, void *user);
+ void *create_leaf_user;
+
+ isl_union_map *executed;
+ int single_valued;
+};
+
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+ __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+ __isl_take isl_ast_build *build);
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build);
+unsigned isl_ast_build_dim(__isl_keep isl_ast_build *build,
+ enum isl_dim_type type);
+__isl_give isl_space *isl_ast_build_get_space(
+ __isl_keep isl_ast_build *build, int internal);
+__isl_give isl_ast_build *isl_ast_build_align_params(
+ __isl_take isl_ast_build *build, __isl_take isl_space *model);
+__isl_give isl_ast_build *isl_ast_build_cow(
+ __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+ __isl_take isl_ast_build *build, int pos);
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+ __isl_take isl_ast_build *build, __isl_take isl_val *m,
+ __isl_take isl_union_map *umap);
+__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_detect_strides(
+ __isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+ __isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_union_map *executed);
+__isl_give isl_ast_build *isl_ast_build_set_single_valued(
+ __isl_take isl_ast_build *build, int sv);
+__isl_give isl_set *isl_ast_build_get_domain(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_get_pending(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_get_generated(
+ __isl_keep isl_ast_build *build);
+__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(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+ __isl_keep isl_ast_build *build);
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build, int pos);
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build);
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+ __isl_keep isl_ast_build *build, int pos);
+
+__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,
+ __isl_take isl_set *set);
+__isl_give isl_set *isl_ast_build_compute_gist(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+ __isl_keep isl_ast_build *build, __isl_take isl_map *map);
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+ __isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain(
+ __isl_keep isl_ast_build *build, __isl_take isl_union_map *umap);
+
+int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
+ __isl_keep isl_aff *aff);
+
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos);
+__isl_give isl_aff *isl_ast_build_get_offset(__isl_keep isl_ast_build *build,
+ int pos);
+__isl_give isl_val *isl_ast_build_get_stride(__isl_keep isl_ast_build *build,
+ int pos);
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+ __isl_keep isl_ast_build *build);
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build);
+
+__isl_give isl_set *isl_ast_build_get_option_domain(
+ __isl_keep isl_ast_build *build,
+ enum isl_ast_build_domain_type type);
+__isl_give isl_map *isl_ast_build_get_separation_class(
+ __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_eliminate(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *domain);
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+ __isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build);
+
+#endif
diff --git a/polly/lib/External/isl/isl_ast_codegen.c b/polly/lib/External/isl/isl_ast_codegen.c
new file mode 100644
index 00000000000..679d2612d69
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_codegen.c
@@ -0,0 +1,3921 @@
+/*
+ * Copyright 2012-2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <limits.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include <isl/ilp.h>
+#include <isl/union_map.h>
+#include <isl_sort.h>
+#include <isl_tarjan.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+
+/* Data used in generate_domain.
+ *
+ * "build" is the input build.
+ * "list" collects the results.
+ */
+struct isl_generate_domain_data {
+ isl_ast_build *build;
+
+ isl_ast_graft_list *list;
+};
+
+static __isl_give isl_ast_graft_list *generate_next_level(
+ __isl_take isl_union_map *executed,
+ __isl_take isl_ast_build *build);
+static __isl_give isl_ast_graft_list *generate_code(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+ int internal);
+
+/* Generate an AST for a single domain based on
+ * the (non single valued) inverse schedule "executed".
+ *
+ * We extend the schedule with the iteration domain
+ * and continue generating through a call to generate_code.
+ *
+ * In particular, if executed has the form
+ *
+ * S -> D
+ *
+ * then we continue generating code on
+ *
+ * [S -> D] -> D
+ *
+ * The extended inverse schedule is clearly single valued
+ * ensuring that the nested generate_code will not reach this function,
+ * but will instead create calls to all elements of D that need
+ * to be executed from the current schedule domain.
+ */
+static int generate_non_single_valued(__isl_take isl_map *executed,
+ struct isl_generate_domain_data *data)
+{
+ isl_map *identity;
+ isl_ast_build *build;
+ isl_ast_graft_list *list;
+
+ build = isl_ast_build_copy(data->build);
+
+ identity = isl_set_identity(isl_map_range(isl_map_copy(executed)));
+ executed = isl_map_domain_product(executed, identity);
+ build = isl_ast_build_set_single_valued(build, 1);
+
+ list = generate_code(isl_union_map_from_map(executed), build, 1);
+
+ data->list = isl_ast_graft_list_concat(data->list, list);
+
+ return 0;
+}
+
+/* Call the at_each_domain callback, if requested by the user,
+ * after recording the current inverse schedule in the build.
+ */
+static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
+ __isl_keep isl_map *executed, __isl_keep isl_ast_build *build)
+{
+ if (!graft || !build)
+ return isl_ast_graft_free(graft);
+ if (!build->at_each_domain)
+ return graft;
+
+ build = isl_ast_build_copy(build);
+ build = isl_ast_build_set_executed(build,
+ isl_union_map_from_map(isl_map_copy(executed)));
+ if (!build)
+ return isl_ast_graft_free(graft);
+
+ graft->node = build->at_each_domain(graft->node,
+ build, build->at_each_domain_user);
+ isl_ast_build_free(build);
+
+ if (!graft->node)
+ graft = isl_ast_graft_free(graft);
+
+ return graft;
+}
+
+/* Generate an AST for a single domain based on
+ * the inverse schedule "executed" and add it to data->list.
+ *
+ * If there is more than one domain element associated to the current
+ * schedule "time", then we need to continue the generation process
+ * in generate_non_single_valued.
+ * Note that the inverse schedule being single-valued may depend
+ * on constraints that are only available in the original context
+ * domain specified by the user. We therefore first introduce
+ * some of the constraints of data->build->domain. In particular,
+ * we intersect with a single-disjunct approximation of this set.
+ * We perform this approximation to avoid further splitting up
+ * the executed relation, possibly introducing a disjunctive guard
+ * on the statement.
+ *
+ * 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.
+ * 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
+ * from the recursive call through generate_non_single_valued
+ * as we would then end up in an infinite recursion.
+ * We therefore check if we are inside a call to generate_non_single_valued
+ * 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.
+ */
+static int 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_map *map = NULL;
+ int empty, sv;
+
+ domain = isl_ast_build_get_domain(data->build);
+ domain = isl_set_from_basic_set(isl_set_simple_hull(domain));
+ executed = isl_map_intersect_domain(executed, domain);
+ empty = isl_map_is_empty(executed);
+ if (empty < 0)
+ goto error;
+ if (empty) {
+ isl_map_free(executed);
+ return 0;
+ }
+
+ executed = isl_map_coalesce(executed);
+ map = isl_map_copy(executed);
+ map = isl_ast_build_compute_gist_map_domain(data->build, map);
+ sv = isl_map_is_single_valued(map);
+ if (sv < 0)
+ goto error;
+ if (!sv) {
+ isl_map_free(map);
+ if (data->build->single_valued)
+ map = isl_map_copy(executed);
+ 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 0;
+error:
+ isl_map_free(map);
+ isl_map_free(executed);
+ return -1;
+}
+
+/* Call build->create_leaf to a create "leaf" node in the AST,
+ * encapsulate the result in an isl_ast_graft and return the result
+ * as a 1-element list.
+ *
+ * Note that the node returned by the user may be an entire tree.
+ *
+ * Since the node itself cannot enforce any constraints, we turn
+ * all pending constraints into guards and add them to the resulting
+ * graft to ensure that they will be generated.
+ *
+ * Before we pass control to the user, we first clear some information
+ * from the build that is (presumbably) only meaningful
+ * for the current code generation.
+ * This includes the create_leaf callback itself, so we make a copy
+ * of the build first.
+ */
+static __isl_give isl_ast_graft_list *call_create_leaf(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+ isl_set *guard;
+ isl_ast_node *node;
+ isl_ast_graft *graft;
+ isl_ast_build *user_build;
+
+ guard = isl_ast_build_get_pending(build);
+ user_build = isl_ast_build_copy(build);
+ user_build = isl_ast_build_replace_pending_by_guard(user_build,
+ isl_set_copy(guard));
+ user_build = isl_ast_build_set_executed(user_build, executed);
+ user_build = isl_ast_build_clear_local_info(user_build);
+ if (!user_build)
+ node = NULL;
+ else
+ node = build->create_leaf(user_build, build->create_leaf_user);
+ graft = isl_ast_graft_alloc(node, build);
+ graft = isl_ast_graft_add_guard(graft, guard, build);
+ isl_ast_build_free(build);
+ return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Generate an AST after having handled the complete schedule
+ * of this call to the code generator.
+ *
+ * If the user has specified a create_leaf callback, control
+ * is passed to the user in call_create_leaf.
+ *
+ * Otherwise, we generate one or more calls for each individual
+ * domain in generate_domain.
+ */
+static __isl_give isl_ast_graft_list *generate_inner_level(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ struct isl_generate_domain_data data = { build };
+
+ if (!build || !executed)
+ goto error;
+
+ if (build->create_leaf)
+ return call_create_leaf(executed, build);
+
+ ctx = isl_union_map_get_ctx(executed);
+ data.list = isl_ast_graft_list_alloc(ctx, 0);
+ if (isl_union_map_foreach_map(executed, &generate_domain, &data) < 0)
+ data.list = isl_ast_graft_list_free(data.list);
+
+ if (0)
+error: data.list = NULL;
+ isl_ast_build_free(build);
+ isl_union_map_free(executed);
+ return data.list;
+}
+
+/* Call the before_each_for callback, if requested by the user.
+ */
+static __isl_give isl_ast_node *before_each_for(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build)
+{
+ isl_id *id;
+
+ if (!node || !build)
+ return isl_ast_node_free(node);
+ if (!build->before_each_for)
+ return node;
+ id = build->before_each_for(build, build->before_each_for_user);
+ node = isl_ast_node_set_annotation(node, id);
+ return node;
+}
+
+/* Call the after_each_for callback, if requested by the user.
+ */
+static __isl_give isl_ast_graft *after_each_for(__isl_take isl_ast_graft *graft,
+ __isl_keep isl_ast_build *build)
+{
+ if (!graft || !build)
+ return isl_ast_graft_free(graft);
+ if (!build->after_each_for)
+ return graft;
+ graft->node = build->after_each_for(graft->node, build,
+ build->after_each_for_user);
+ if (!graft->node)
+ return isl_ast_graft_free(graft);
+ return graft;
+}
+
+/* Plug in all the know values of the current and outer dimensions
+ * in the domain of "executed". In principle, we only need to plug
+ * in the known value of the current dimension since the values of
+ * outer dimensions have been plugged in already.
+ * However, it turns out to be easier to just plug in all known values.
+ */
+static __isl_give isl_union_map *plug_in_values(
+ __isl_take isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+ return isl_ast_build_substitute_values_union_map_domain(build,
+ executed);
+}
+
+/* Check if the constraint "c" is a lower bound on dimension "pos",
+ * an upper bound, or independent of dimension "pos".
+ */
+static int constraint_type(isl_constraint *c, int pos)
+{
+ if (isl_constraint_is_lower_bound(c, isl_dim_set, pos))
+ return 1;
+ if (isl_constraint_is_upper_bound(c, isl_dim_set, pos))
+ return 2;
+ return 0;
+}
+
+/* Compare the types of the constraints "a" and "b",
+ * resulting in constraints that are independent of "depth"
+ * to be sorted before the lower bounds on "depth", which in
+ * turn are sorted before the upper bounds on "depth".
+ */
+static int cmp_constraint(__isl_keep isl_constraint *a,
+ __isl_keep isl_constraint *b, void *user)
+{
+ int *depth = user;
+ int t1 = constraint_type(a, *depth);
+ int t2 = constraint_type(b, *depth);
+
+ return t1 - t2;
+}
+
+/* Extract a lower bound on dimension "pos" from constraint "c".
+ *
+ * If the constraint is of the form
+ *
+ * a x + f(...) >= 0
+ *
+ * then we essentially return
+ *
+ * l = ceil(-f(...)/a)
+ *
+ * However, if the current dimension is strided, then we need to make
+ * sure that the lower bound we construct is of the form
+ *
+ * f + s a
+ *
+ * with f the offset and s the stride.
+ * We therefore compute
+ *
+ * f + s * ceil((l - f)/s)
+ */
+static __isl_give isl_aff *lower_bound(__isl_keep isl_constraint *c,
+ int pos, __isl_keep isl_ast_build *build)
+{
+ isl_aff *aff;
+
+ aff = isl_constraint_get_bound(c, isl_dim_set, pos);
+ aff = isl_aff_ceil(aff);
+
+ if (isl_ast_build_has_stride(build, pos)) {
+ isl_aff *offset;
+ isl_val *stride;
+
+ offset = isl_ast_build_get_offset(build, pos);
+ stride = isl_ast_build_get_stride(build, pos);
+
+ aff = isl_aff_sub(aff, isl_aff_copy(offset));
+ aff = isl_aff_scale_down_val(aff, isl_val_copy(stride));
+ aff = isl_aff_ceil(aff);
+ aff = isl_aff_scale_val(aff, stride);
+ aff = isl_aff_add(aff, offset);
+ }
+
+ aff = isl_ast_build_compute_gist_aff(build, aff);
+
+ return aff;
+}
+
+/* Return the exact lower bound (or upper bound if "upper" is set)
+ * of "domain" as a piecewise affine expression.
+ *
+ * If we are computing a lower bound (of a strided dimension), then
+ * we need to make sure it is of the form
+ *
+ * f + s a
+ *
+ * where f is the offset and s is the stride.
+ * We therefore need to include the stride constraint before computing
+ * the minimum.
+ */
+static __isl_give isl_pw_aff *exact_bound(__isl_keep isl_set *domain,
+ __isl_keep isl_ast_build *build, int upper)
+{
+ isl_set *stride;
+ isl_map *it_map;
+ isl_pw_aff *pa;
+ isl_pw_multi_aff *pma;
+
+ domain = isl_set_copy(domain);
+ if (!upper) {
+ stride = isl_ast_build_get_stride_constraint(build);
+ domain = isl_set_intersect(domain, stride);
+ }
+ it_map = isl_ast_build_map_to_iterator(build, domain);
+ if (upper)
+ pma = isl_map_lexmax_pw_multi_aff(it_map);
+ else
+ pma = isl_map_lexmin_pw_multi_aff(it_map);
+ pa = isl_pw_multi_aff_get_pw_aff(pma, 0);
+ isl_pw_multi_aff_free(pma);
+ pa = isl_ast_build_compute_gist_pw_aff(build, pa);
+ pa = isl_pw_aff_coalesce(pa);
+
+ return pa;
+}
+
+/* Callback for sorting the isl_pw_aff_list passed to reduce_list and
+ * remove_redundant_lower_bounds.
+ */
+static int reduce_list_cmp(__isl_keep isl_pw_aff *a, __isl_keep isl_pw_aff *b,
+ void *user)
+{
+ return isl_pw_aff_plain_cmp(a, b);
+}
+
+/* Given a list of lower bounds "list", remove those that are redundant
+ * with respect to the other bounds in "list" and the domain of "build".
+ *
+ * We first sort the bounds in the same way as they would be sorted
+ * by set_for_node_expressions so that we can try and remove the last
+ * bounds first.
+ *
+ * For a lower bound to be effective, there needs to be at least
+ * one domain element for which it is larger than all other lower bounds.
+ * For each lower bound we therefore intersect the domain with
+ * the conditions that it is larger than all other bounds and
+ * check whether the result is empty. If so, the bound can be removed.
+ */
+static __isl_give isl_pw_aff_list *remove_redundant_lower_bounds(
+ __isl_take isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+ int i, j, n;
+ isl_set *domain;
+
+ list = isl_pw_aff_list_sort(list, &reduce_list_cmp, NULL);
+ if (!list)
+ return NULL;
+
+ n = isl_pw_aff_list_n_pw_aff(list);
+ if (n <= 1)
+ return list;
+
+ domain = isl_ast_build_get_domain(build);
+
+ for (i = n - 1; i >= 0; --i) {
+ isl_pw_aff *pa_i;
+ isl_set *domain_i;
+ int empty;
+
+ domain_i = isl_set_copy(domain);
+ pa_i = isl_pw_aff_list_get_pw_aff(list, i);
+
+ for (j = 0; j < n; ++j) {
+ isl_pw_aff *pa_j;
+ isl_set *better;
+
+ if (j == i)
+ continue;
+
+ pa_j = isl_pw_aff_list_get_pw_aff(list, j);
+ better = isl_pw_aff_gt_set(isl_pw_aff_copy(pa_i), pa_j);
+ domain_i = isl_set_intersect(domain_i, better);
+ }
+
+ empty = isl_set_is_empty(domain_i);
+
+ isl_set_free(domain_i);
+ isl_pw_aff_free(pa_i);
+
+ if (empty < 0)
+ goto error;
+ if (!empty)
+ continue;
+ list = isl_pw_aff_list_drop(list, i, 1);
+ n--;
+ }
+
+ isl_set_free(domain);
+
+ return list;
+error:
+ isl_set_free(domain);
+ return isl_pw_aff_list_free(list);
+}
+
+/* Extract a lower bound on dimension "pos" from each constraint
+ * in "constraints" and return the list of lower bounds.
+ * If "constraints" has zero elements, then we extract a lower bound
+ * from "domain" instead.
+ *
+ * If the current dimension is strided, then the lower bound
+ * is adjusted by lower_bound to match the stride information.
+ * This modification may make one or more lower bounds redundant
+ * with respect to the other lower bounds. We therefore check
+ * for this condition and remove the redundant lower bounds.
+ */
+static __isl_give isl_pw_aff_list *lower_bounds(
+ __isl_keep isl_constraint_list *constraints, int pos,
+ __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_pw_aff_list *list;
+ int i, n;
+
+ if (!build)
+ return NULL;
+
+ n = isl_constraint_list_n_constraint(constraints);
+ if (n == 0) {
+ isl_pw_aff *pa;
+ pa = exact_bound(domain, build, 0);
+ return isl_pw_aff_list_from_pw_aff(pa);
+ }
+
+ ctx = isl_ast_build_get_ctx(build);
+ list = isl_pw_aff_list_alloc(ctx,n);
+
+ for (i = 0; i < n; ++i) {
+ isl_aff *aff;
+ isl_constraint *c;
+
+ c = isl_constraint_list_get_constraint(constraints, i);
+ aff = lower_bound(c, pos, build);
+ isl_constraint_free(c);
+ list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+ }
+
+ if (isl_ast_build_has_stride(build, pos))
+ list = remove_redundant_lower_bounds(list, build);
+
+ return list;
+}
+
+/* Extract an upper bound on dimension "pos" from each constraint
+ * in "constraints" and return the list of upper bounds.
+ * If "constraints" has zero elements, then we extract an upper bound
+ * from "domain" instead.
+ */
+static __isl_give isl_pw_aff_list *upper_bounds(
+ __isl_keep isl_constraint_list *constraints, int pos,
+ __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_pw_aff_list *list;
+ int i, n;
+
+ n = isl_constraint_list_n_constraint(constraints);
+ if (n == 0) {
+ isl_pw_aff *pa;
+ pa = exact_bound(domain, build, 1);
+ return isl_pw_aff_list_from_pw_aff(pa);
+ }
+
+ ctx = isl_ast_build_get_ctx(build);
+ list = isl_pw_aff_list_alloc(ctx,n);
+
+ for (i = 0; i < n; ++i) {
+ isl_aff *aff;
+ isl_constraint *c;
+
+ c = isl_constraint_list_get_constraint(constraints, i);
+ aff = isl_constraint_get_bound(c, isl_dim_set, pos);
+ isl_constraint_free(c);
+ aff = isl_aff_floor(aff);
+ list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+ }
+
+ return list;
+}
+
+/* Return an isl_ast_expr that performs the reduction of type "type"
+ * on AST expressions corresponding to the elements in "list".
+ *
+ * The list is assumed to contain at least one element.
+ * If the list contains exactly one element, then the returned isl_ast_expr
+ * simply computes that affine expression.
+ * If the list contains more than one element, then we sort it
+ * using a fairly abitrary but hopefully reasonably stable order.
+ */
+static __isl_give isl_ast_expr *reduce_list(enum isl_ast_op_type type,
+ __isl_keep isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_ast_expr *expr;
+
+ if (!list)
+ return NULL;
+
+ n = isl_pw_aff_list_n_pw_aff(list);
+
+ if (n == 1)
+ return isl_ast_build_expr_from_pw_aff_internal(build,
+ isl_pw_aff_list_get_pw_aff(list, 0));
+
+ ctx = isl_pw_aff_list_get_ctx(list);
+ expr = isl_ast_expr_alloc_op(ctx, type, n);
+ if (!expr)
+ return NULL;
+
+ list = isl_pw_aff_list_copy(list);
+ list = isl_pw_aff_list_sort(list, &reduce_list_cmp, NULL);
+ if (!list)
+ return isl_ast_expr_free(expr);
+
+ for (i = 0; i < n; ++i) {
+ isl_ast_expr *expr_i;
+
+ expr_i = isl_ast_build_expr_from_pw_aff_internal(build,
+ isl_pw_aff_list_get_pw_aff(list, i));
+ if (!expr_i)
+ goto error;
+ expr->u.op.args[i] = expr_i;
+ }
+
+ isl_pw_aff_list_free(list);
+ return expr;
+error:
+ isl_pw_aff_list_free(list);
+ isl_ast_expr_free(expr);
+ return NULL;
+}
+
+/* Add guards implied by the "generated constraints",
+ * but not (necessarily) enforced by the generated AST to "guard".
+ * In particular, if there is any stride constraints,
+ * then add the guard implied by those constraints.
+ * If we have generated a degenerate loop, then add the guard
+ * implied by "bounds" on the outer dimensions, i.e., the guard
+ * that ensures that the single value actually exists.
+ */
+static __isl_give isl_set *add_implied_guards(__isl_take isl_set *guard,
+ int degenerate, __isl_keep isl_basic_set *bounds,
+ __isl_keep isl_ast_build *build)
+{
+ int depth, has_stride;
+ isl_set *dom;
+
+ depth = isl_ast_build_get_depth(build);
+ has_stride = isl_ast_build_has_stride(build, depth);
+ if (!has_stride && !degenerate)
+ return guard;
+
+ if (degenerate) {
+ bounds = isl_basic_set_copy(bounds);
+ bounds = isl_basic_set_drop_constraints_not_involving_dims(
+ bounds, isl_dim_set, depth, 1);
+ dom = isl_set_from_basic_set(bounds);
+ dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
+ dom = isl_ast_build_compute_gist(build, dom);
+ guard = isl_set_intersect(guard, dom);
+ }
+
+ if (has_stride) {
+ dom = isl_ast_build_get_stride_constraint(build);
+ dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
+ dom = isl_ast_build_compute_gist(build, dom);
+ guard = isl_set_intersect(guard, dom);
+ }
+
+ return guard;
+}
+
+/* Update "graft" based on "sub_build" for the degenerate case.
+ *
+ * "build" is the build in which graft->node was created
+ * "sub_build" contains information about the current level itself,
+ * including the single value attained.
+ *
+ * We set the initialization part of the for loop to the single
+ * value attained by the current dimension.
+ * The increment and condition are not strictly needed as the are known
+ * to be "1" and "iterator <= value" respectively.
+ */
+static __isl_give isl_ast_graft *refine_degenerate(
+ __isl_take isl_ast_graft *graft, __isl_keep isl_ast_build *build,
+ __isl_keep isl_ast_build *sub_build)
+{
+ isl_pw_aff *value;
+
+ if (!graft || !sub_build)
+ return isl_ast_graft_free(graft);
+
+ value = isl_pw_aff_copy(sub_build->value);
+
+ graft->node->u.f.init = isl_ast_build_expr_from_pw_aff_internal(build,
+ value);
+ if (!graft->node->u.f.init)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+}
+
+/* Return the intersection of constraints in "list" as a set.
+ */
+static __isl_give isl_set *intersect_constraints(
+ __isl_keep isl_constraint_list *list)
+{
+ int i, n;
+ isl_basic_set *bset;
+
+ n = isl_constraint_list_n_constraint(list);
+ if (n < 1)
+ isl_die(isl_constraint_list_get_ctx(list), isl_error_internal,
+ "expecting at least one constraint", return NULL);
+
+ bset = isl_basic_set_from_constraint(
+ isl_constraint_list_get_constraint(list, 0));
+ for (i = 1; i < n; ++i) {
+ isl_basic_set *bset_i;
+
+ bset_i = isl_basic_set_from_constraint(
+ isl_constraint_list_get_constraint(list, i));
+ bset = isl_basic_set_intersect(bset, bset_i);
+ }
+
+ return isl_set_from_basic_set(bset);
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as a set "upper".
+ *
+ * In particular, if l(...) is a lower bound in "lower", and
+ *
+ * -a i + f(...) >= 0 or a i <= f(...)
+ *
+ * is an upper bound ocnstraint on the current dimension i,
+ * then the for loop enforces the constraint
+ *
+ * -a l(...) + f(...) >= 0 or a l(...) <= f(...)
+ *
+ * We therefore simply take each lower bound in turn, plug it into
+ * the upper bounds and compute the intersection over all lower bounds.
+ *
+ * If a lower bound is a rational expression, then
+ * isl_basic_set_preimage_multi_aff will force this rational
+ * expression to have only integer values. However, the loop
+ * itself does not enforce this integrality constraint. We therefore
+ * use the ceil of the lower bounds instead of the lower bounds themselves.
+ * Other constraints will make sure that the for loop is only executed
+ * when each of the lower bounds attains an integral value.
+ * In particular, potentially rational values only occur in
+ * lower_bound if the offset is a (seemingly) rational expression,
+ * but then outer conditions will make sure that this rational expression
+ * only attains integer values.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_set(
+ __isl_take isl_ast_graft *graft,
+ __isl_keep isl_pw_aff_list *lower, int pos, __isl_keep isl_set *upper)
+{
+ isl_space *space;
+ isl_basic_set *enforced;
+ isl_pw_multi_aff *pma;
+ int i, n;
+
+ if (!graft || !lower)
+ return isl_ast_graft_free(graft);
+
+ space = isl_set_get_space(upper);
+ enforced = isl_basic_set_universe(isl_space_copy(space));
+
+ space = isl_space_map_from_set(space);
+ pma = isl_pw_multi_aff_identity(space);
+
+ n = isl_pw_aff_list_n_pw_aff(lower);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ isl_set *enforced_i;
+ isl_basic_set *hull;
+ isl_pw_multi_aff *pma_i;
+
+ pa = isl_pw_aff_list_get_pw_aff(lower, i);
+ pa = isl_pw_aff_ceil(pa);
+ pma_i = isl_pw_multi_aff_copy(pma);
+ pma_i = isl_pw_multi_aff_set_pw_aff(pma_i, pos, pa);
+ enforced_i = isl_set_copy(upper);
+ enforced_i = isl_set_preimage_pw_multi_aff(enforced_i, pma_i);
+ hull = isl_set_simple_hull(enforced_i);
+ enforced = isl_basic_set_intersect(enforced, hull);
+ }
+
+ isl_pw_multi_aff_free(pma);
+
+ graft = isl_ast_graft_enforce(graft, enforced);
+
+ return graft;
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as
+ * a list of affine expressions "upper".
+ *
+ * The enforced condition is that each lower bound expression is less
+ * than or equal to each upper bound expression.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_list(
+ __isl_take isl_ast_graft *graft,
+ __isl_keep isl_pw_aff_list *lower, __isl_keep isl_pw_aff_list *upper)
+{
+ isl_set *cond;
+ isl_basic_set *enforced;
+
+ lower = isl_pw_aff_list_copy(lower);
+ upper = isl_pw_aff_list_copy(upper);
+ cond = isl_pw_aff_list_le_set(lower, upper);
+ enforced = isl_set_simple_hull(cond);
+ graft = isl_ast_graft_enforce(graft, enforced);
+
+ return graft;
+}
+
+/* Does "aff" have a negative constant term?
+ */
+static int aff_constant_is_negative(__isl_take isl_set *set,
+ __isl_take isl_aff *aff, void *user)
+{
+ int *neg = user;
+ isl_val *v;
+
+ v = isl_aff_get_constant_val(aff);
+ *neg = isl_val_is_neg(v);
+ isl_val_free(v);
+ isl_set_free(set);
+ isl_aff_free(aff);
+
+ return *neg ? 0 : -1;
+}
+
+/* Does "pa" have a negative constant term over its entire domain?
+ */
+static int pw_aff_constant_is_negative(__isl_take isl_pw_aff *pa, void *user)
+{
+ int r;
+ int *neg = user;
+
+ r = isl_pw_aff_foreach_piece(pa, &aff_constant_is_negative, user);
+ isl_pw_aff_free(pa);
+
+ return *neg ? 0 : -1;
+}
+
+/* Does each element in "list" have a negative constant term?
+ *
+ * The callback terminates the iteration as soon an element has been
+ * found that does not have a negative constant term.
+ */
+static int list_constant_is_negative(__isl_keep isl_pw_aff_list *list)
+{
+ int neg = 1;
+
+ if (isl_pw_aff_list_foreach(list,
+ &pw_aff_constant_is_negative, &neg) < 0 && neg)
+ return -1;
+
+ return neg;
+}
+
+/* Add 1 to each of the elements in "list", where each of these elements
+ * is defined over the internal schedule space of "build".
+ */
+static __isl_give isl_pw_aff_list *list_add_one(
+ __isl_take isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ isl_space *space;
+ isl_aff *aff;
+ isl_pw_aff *one;
+
+ space = isl_ast_build_get_space(build, 1);
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+ aff = isl_aff_add_constant_si(aff, 1);
+ one = isl_pw_aff_from_aff(aff);
+
+ n = isl_pw_aff_list_n_pw_aff(list);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ pa = isl_pw_aff_list_get_pw_aff(list, i);
+ pa = isl_pw_aff_add(pa, isl_pw_aff_copy(one));
+ list = isl_pw_aff_list_set_pw_aff(list, i, pa);
+ }
+
+ isl_pw_aff_free(one);
+
+ return list;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a list of piecewise affine expressions.
+ *
+ * In particular, set the condition to
+ *
+ * iterator <= min(list of upper bounds)
+ *
+ * If each of the upper bounds has a negative constant term, then
+ * set the condition to
+ *
+ * iterator < min(list of (upper bound + 1)s)
+ *
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_list(
+ __isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ int neg;
+ isl_ast_expr *bound, *iterator, *cond;
+ enum isl_ast_op_type type = isl_ast_op_le;
+
+ if (!graft || !list)
+ return isl_ast_graft_free(graft);
+
+ neg = list_constant_is_negative(list);
+ if (neg < 0)
+ return isl_ast_graft_free(graft);
+ list = isl_pw_aff_list_copy(list);
+ if (neg) {
+ list = list_add_one(list, build);
+ type = isl_ast_op_lt;
+ }
+
+ bound = reduce_list(isl_ast_op_min, list, build);
+ iterator = isl_ast_expr_copy(graft->node->u.f.iterator);
+ cond = isl_ast_expr_alloc_binary(type, iterator, bound);
+ graft->node->u.f.cond = cond;
+
+ isl_pw_aff_list_free(list);
+ if (!graft->node->u.f.cond)
+ return isl_ast_graft_free(graft);
+ return graft;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a set.
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_set(
+ __isl_take isl_ast_graft *graft, __isl_keep isl_set *set,
+ __isl_keep isl_ast_build *build)
+{
+ isl_ast_expr *cond;
+
+ if (!graft)
+ return NULL;
+
+ cond = isl_ast_build_expr_from_set(build, isl_set_copy(set));
+ graft->node->u.f.cond = cond;
+ if (!graft->node->u.f.cond)
+ return isl_ast_graft_free(graft);
+ return graft;
+}
+
+/* Construct an isl_ast_expr for the increment (i.e., stride) of
+ * the current dimension.
+ */
+static __isl_give isl_ast_expr *for_inc(__isl_keep isl_ast_build *build)
+{
+ int depth;
+ isl_val *v;
+ isl_ctx *ctx;
+
+ if (!build)
+ return NULL;
+ ctx = isl_ast_build_get_ctx(build);
+ depth = isl_ast_build_get_depth(build);
+
+ if (!isl_ast_build_has_stride(build, depth))
+ return isl_ast_expr_alloc_int_si(ctx, 1);
+
+ v = isl_ast_build_get_stride(build, depth);
+ return isl_ast_expr_from_val(v);
+}
+
+/* Should we express the loop condition as
+ *
+ * iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints?
+ *
+ * The first is constructed from a list of upper bounds.
+ * The second is constructed from a set.
+ *
+ * If there are no upper bounds in "constraints", then this could mean
+ * that "domain" simply doesn't have an upper bound or that we didn't
+ * pick any upper bound. In the first case, we want to generate the
+ * loop condition as a(n empty) conjunction of constraints
+ * In the second case, we will compute
+ * a single upper bound from "domain" and so we use the list form.
+ *
+ * If there are upper bounds in "constraints",
+ * then we use the list form iff the atomic_upper_bound option is set.
+ */
+static int use_upper_bound_list(isl_ctx *ctx, int n_upper,
+ __isl_keep isl_set *domain, int depth)
+{
+ if (n_upper > 0)
+ return isl_options_get_ast_build_atomic_upper_bound(ctx);
+ else
+ return isl_set_dim_has_upper_bound(domain, isl_dim_set, depth);
+}
+
+/* Fill in the expressions of the for node in graft->node.
+ *
+ * In particular,
+ * - set the initialization part of the loop to the maximum of the lower bounds
+ * - extract the increment from the stride of the current dimension
+ * - construct the for condition either based on a list of upper bounds
+ * or on a set of upper bound constraints.
+ */
+static __isl_give isl_ast_graft *set_for_node_expressions(
+ __isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *lower,
+ int use_list, __isl_keep isl_pw_aff_list *upper_list,
+ __isl_keep isl_set *upper_set, __isl_keep isl_ast_build *build)
+{
+ isl_ast_node *node;
+
+ if (!graft)
+ return NULL;
+
+ build = isl_ast_build_copy(build);
+
+ node = graft->node;
+ node->u.f.init = reduce_list(isl_ast_op_max, lower, build);
+ node->u.f.inc = for_inc(build);
+
+ if (use_list)
+ graft = set_for_cond_from_list(graft, upper_list, build);
+ else
+ graft = set_for_cond_from_set(graft, upper_set, build);
+
+ isl_ast_build_free(build);
+
+ if (!node->u.f.iterator || !node->u.f.init ||
+ !node->u.f.cond || !node->u.f.inc)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "c_lower" and "c_upper" contain the lower and upper bounds
+ * that the loop node should express.
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ *
+ * There may be zero lower bounds or zero upper bounds in "constraints"
+ * in case the list of constraints was created
+ * based on the atomic option or based on separation with explicit bounds.
+ * In that case, we use "domain" to derive lower and/or upper bounds.
+ *
+ * We first compute a list of one or more lower bounds.
+ *
+ * Then we decide if we want to express the condition as
+ *
+ * iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints.
+ *
+ * The set of enforced constraints is then computed either based on
+ * a list of upper bounds or on a set of upper bound constraints.
+ * We do not compute any enforced constraints if we were forced
+ * to compute a lower or upper bound using exact_bound. The domains
+ * of the resulting expressions may imply some bounds on outer dimensions
+ * that we do not want to appear in the enforced constraints since
+ * they are not actually enforced by the corresponding code.
+ *
+ * Finally, we fill in the expressions of the for node.
+ */
+static __isl_give isl_ast_graft *refine_generic_bounds(
+ __isl_take isl_ast_graft *graft,
+ __isl_take isl_constraint_list *c_lower,
+ __isl_take isl_constraint_list *c_upper,
+ __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+ int depth;
+ isl_ctx *ctx;
+ isl_pw_aff_list *lower;
+ int use_list;
+ isl_set *upper_set = NULL;
+ isl_pw_aff_list *upper_list = NULL;
+ int n_lower, n_upper;
+
+ if (!graft || !c_lower || !c_upper || !build)
+ goto error;
+
+ depth = isl_ast_build_get_depth(build);
+ ctx = isl_ast_graft_get_ctx(graft);
+
+ n_lower = isl_constraint_list_n_constraint(c_lower);
+ n_upper = isl_constraint_list_n_constraint(c_upper);
+
+ use_list = use_upper_bound_list(ctx, n_upper, domain, depth);
+
+ lower = lower_bounds(c_lower, depth, domain, build);
+
+ if (use_list)
+ upper_list = upper_bounds(c_upper, depth, domain, build);
+ else if (n_upper > 0)
+ upper_set = intersect_constraints(c_upper);
+ else
+ upper_set = isl_set_universe(isl_set_get_space(domain));
+
+ if (n_lower == 0 || n_upper == 0)
+ ;
+ else if (use_list)
+ graft = set_enforced_from_list(graft, lower, upper_list);
+ else
+ graft = set_enforced_from_set(graft, lower, depth, upper_set);
+
+ graft = set_for_node_expressions(graft, lower, use_list, upper_list,
+ upper_set, build);
+
+ isl_pw_aff_list_free(lower);
+ isl_pw_aff_list_free(upper_list);
+ isl_set_free(upper_set);
+ isl_constraint_list_free(c_lower);
+ isl_constraint_list_free(c_upper);
+
+ return graft;
+error:
+ isl_constraint_list_free(c_lower);
+ isl_constraint_list_free(c_upper);
+ return isl_ast_graft_free(graft);
+}
+
+/* Internal data structure used inside count_constraints to keep
+ * track of the number of constraints that are independent of dimension "pos",
+ * the lower bounds in "pos" and the upper bounds in "pos".
+ */
+struct isl_ast_count_constraints_data {
+ int pos;
+
+ int n_indep;
+ int n_lower;
+ int n_upper;
+};
+
+/* Increment data->n_indep, data->lower or data->upper depending
+ * on whether "c" is independenct of dimensions data->pos,
+ * a lower bound or an upper bound.
+ */
+static int count_constraints(__isl_take isl_constraint *c, void *user)
+{
+ struct isl_ast_count_constraints_data *data = user;
+
+ if (isl_constraint_is_lower_bound(c, isl_dim_set, data->pos))
+ data->n_lower++;
+ else if (isl_constraint_is_upper_bound(c, isl_dim_set, data->pos))
+ data->n_upper++;
+ else
+ data->n_indep++;
+
+ isl_constraint_free(c);
+
+ return 0;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "list" respresent the list of bounds that need to be encoded by
+ * the for loop. Only the constraints that involve the iterator
+ * are relevant here. The other constraints are taken care of by
+ * the caller and are included in the generated constraints of "build".
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We separate lower bounds, upper bounds and constraints that
+ * are independent of the loop iterator.
+ *
+ * The actual for loop bounds are generated in refine_generic_bounds.
+ */
+static __isl_give isl_ast_graft *refine_generic_split(
+ __isl_take isl_ast_graft *graft, __isl_take isl_constraint_list *list,
+ __isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+ struct isl_ast_count_constraints_data data;
+ isl_constraint_list *lower;
+ isl_constraint_list *upper;
+
+ if (!list)
+ return isl_ast_graft_free(graft);
+
+ data.pos = isl_ast_build_get_depth(build);
+
+ list = isl_constraint_list_sort(list, &cmp_constraint, &data.pos);
+ if (!list)
+ return isl_ast_graft_free(graft);
+
+ data.n_indep = data.n_lower = data.n_upper = 0;
+ if (isl_constraint_list_foreach(list, &count_constraints, &data) < 0) {
+ isl_constraint_list_free(list);
+ return isl_ast_graft_free(graft);
+ }
+
+ lower = isl_constraint_list_drop(list, 0, data.n_indep);
+ upper = isl_constraint_list_copy(lower);
+ lower = isl_constraint_list_drop(lower, data.n_lower, data.n_upper);
+ upper = isl_constraint_list_drop(upper, 0, data.n_lower);
+
+ return refine_generic_bounds(graft, lower, upper, domain, build);
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "bounds" respresent the bounds that need to be encoded by
+ * the for loop (or a guard around the for loop).
+ * "domain" is the subset of "bounds" for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We break up "bounds" into a list of constraints and continue with
+ * refine_generic_split.
+ */
+static __isl_give isl_ast_graft *refine_generic(
+ __isl_take isl_ast_graft *graft,
+ __isl_keep isl_basic_set *bounds, __isl_keep isl_set *domain,
+ __isl_keep isl_ast_build *build)
+{
+ isl_constraint_list *list;
+
+ if (!build || !graft)
+ return isl_ast_graft_free(graft);
+
+ list = isl_basic_set_get_constraint_list(bounds);
+
+ graft = refine_generic_split(graft, list, domain, build);
+
+ return graft;
+}
+
+/* Create a for node for the current level.
+ *
+ * Mark the for node degenerate if "degenerate" is set.
+ */
+static __isl_give isl_ast_node *create_for(__isl_keep isl_ast_build *build,
+ int degenerate)
+{
+ int depth;
+ isl_id *id;
+ isl_ast_node *node;
+
+ if (!build)
+ return NULL;
+
+ depth = isl_ast_build_get_depth(build);
+ id = isl_ast_build_get_iterator_id(build, depth);
+ node = isl_ast_node_alloc_for(id);
+ if (degenerate)
+ node = isl_ast_node_for_mark_degenerate(node);
+
+ return node;
+}
+
+/* If the ast_build_exploit_nested_bounds option is set, then return
+ * the constraints enforced by all elements in "list".
+ * Otherwise, return the universe.
+ */
+static __isl_give isl_basic_set *extract_shared_enforced(
+ __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_space *space;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_ast_graft_list_get_ctx(list);
+ if (isl_options_get_ast_build_exploit_nested_bounds(ctx))
+ return isl_ast_graft_list_extract_shared_enforced(list, build);
+
+ space = isl_ast_build_get_space(build, 1);
+ return isl_basic_set_universe(space);
+}
+
+/* Return the pending constraints of "build" that are not already taken
+ * care of (by a combination of "enforced" and the generated constraints
+ * of "build").
+ */
+static __isl_give isl_set *extract_pending(__isl_keep isl_ast_build *build,
+ __isl_keep isl_basic_set *enforced)
+{
+ isl_set *guard, *context;
+
+ guard = isl_ast_build_get_pending(build);
+ context = isl_set_from_basic_set(isl_basic_set_copy(enforced));
+ context = isl_set_intersect(context,
+ isl_ast_build_get_generated(build));
+ return isl_set_gist(guard, context);
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ * It may be a strict subset of "bounds" in case "bounds" was created
+ * based on the atomic option or based on separation with explicit bounds.
+ *
+ * "domain" may satisfy additional equalities that result
+ * from intersecting "executed" with "bounds" in add_node.
+ * It may also satisfy some global constraints that were dropped out because
+ * we performed separation with explicit bounds.
+ * The very first step is then to copy these constraints to "bounds".
+ *
+ * Since we may be calling before_each_for and after_each_for
+ * callbacks, we record the current inverse schedule in the build.
+ *
+ * We consider three builds,
+ * "build" is the one in which the current level is created,
+ * "body_build" is the build in which the next level is created,
+ * "sub_build" is essentially the same as "body_build", except that
+ * the depth has not been increased yet.
+ *
+ * "build" already contains information (in strides and offsets)
+ * about the strides at the current level, but this information is not
+ * reflected in the build->domain.
+ * We first add this information and the "bounds" to the sub_build->domain.
+ * isl_ast_build_set_loop_bounds adds the stride information and
+ * checks whether the current dimension attains
+ * only a single value and whether this single value can be represented using
+ * a single affine expression.
+ * In the first case, the current level is considered "degenerate".
+ * In the second, sub-case, the current level is considered "eliminated".
+ * Eliminated levels don't need to be reflected in the AST since we can
+ * simply plug in the affine expression. For degenerate, but non-eliminated,
+ * levels, we do introduce a for node, but mark is as degenerate so that
+ * it can be printed as an assignment of the single value to the loop
+ * "iterator".
+ *
+ * If the current level is eliminated, we explicitly plug in the value
+ * for the current level found by isl_ast_build_set_loop_bounds in the
+ * inverse schedule. This ensures that if we are working on a slice
+ * of the domain based on information available in the inverse schedule
+ * and the build domain, that then this information is also reflected
+ * in the inverse schedule. This operation also eliminates the current
+ * dimension from the inverse schedule making sure no inner dimensions depend
+ * on the current dimension. Otherwise, we create a for node, marking
+ * it degenerate if appropriate. The initial for node is still incomplete
+ * and will be completed in either refine_degenerate or refine_generic.
+ *
+ * We then generate a sequence of grafts for the next level,
+ * create a surrounding graft for the current level and insert
+ * the for node we created (if the current level is not eliminated).
+ * Before creating a graft for the current level, we first extract
+ * hoistable constraints from the child guards and combine them
+ * with the pending constraints in the build. These constraints
+ * are used to simplify the child guards and then added to the guard
+ * of the current graft to ensure that they will be generated.
+ * If the hoisted guard is a disjunction, then we use it directly
+ * to gist the guards on the children before intersect it with the
+ * pending constraints. We do so because this disjunction is typically
+ * identical to the guards on the children such that these guards
+ * can be effectively removed completely. After the intersection,
+ * the gist operation would have a harder time figuring this out.
+ *
+ * Finally, we set the bounds of the for loop in either
+ * refine_degenerate or refine_generic.
+ * We do so in a context where the pending constraints of the build
+ * have been replaced by the guard of the current graft.
+ */
+static __isl_give isl_ast_graft *create_node_scaled(
+ __isl_take isl_union_map *executed,
+ __isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+ __isl_take isl_ast_build *build)
+{
+ int depth;
+ int degenerate, eliminated;
+ isl_basic_set *hull;
+ isl_basic_set *enforced;
+ isl_set *guard, *hoisted;
+ isl_ast_node *node = NULL;
+ isl_ast_graft *graft;
+ isl_ast_graft_list *children;
+ isl_ast_build *sub_build;
+ isl_ast_build *body_build;
+
+ domain = isl_ast_build_eliminate_divs(build, domain);
+ domain = isl_set_detect_equalities(domain);
+ hull = isl_set_unshifted_simple_hull(isl_set_copy(domain));
+ bounds = isl_basic_set_intersect(bounds, hull);
+ build = isl_ast_build_set_executed(build, isl_union_map_copy(executed));
+
+ depth = isl_ast_build_get_depth(build);
+ sub_build = isl_ast_build_copy(build);
+ 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 (eliminated)
+ executed = plug_in_values(executed, sub_build);
+ else
+ node = create_for(build, degenerate);
+
+ body_build = isl_ast_build_copy(sub_build);
+ body_build = isl_ast_build_increase_depth(body_build);
+ if (!eliminated)
+ node = before_each_for(node, body_build);
+ children = generate_next_level(executed,
+ isl_ast_build_copy(body_build));
+
+ enforced = extract_shared_enforced(children, build);
+ guard = extract_pending(sub_build, enforced);
+ hoisted = isl_ast_graft_list_extract_hoistable_guard(children, build);
+ if (isl_set_n_basic_set(hoisted) > 1)
+ children = isl_ast_graft_list_gist_guards(children,
+ isl_set_copy(hoisted));
+ guard = isl_set_intersect(guard, hoisted);
+ if (!eliminated)
+ guard = add_implied_guards(guard, degenerate, bounds, build);
+
+ 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;
+
+ graft = isl_ast_graft_insert_for(graft, node);
+ for_build = isl_ast_build_copy(build);
+ for_build = isl_ast_build_replace_pending_by_guard(for_build,
+ isl_set_copy(guard));
+ if (degenerate)
+ graft = refine_degenerate(graft, for_build, sub_build);
+ else
+ graft = refine_generic(graft, bounds,
+ domain, for_build);
+ isl_ast_build_free(for_build);
+ }
+ isl_set_free(guard);
+ if (!eliminated)
+ graft = after_each_for(graft, body_build);
+
+ isl_ast_build_free(body_build);
+ isl_ast_build_free(sub_build);
+ isl_ast_build_free(build);
+ isl_basic_set_free(bounds);
+ isl_set_free(domain);
+
+ return graft;
+}
+
+/* Internal data structure for checking if all constraints involving
+ * the input dimension "depth" are such that the other coefficients
+ * are multiples of "m", reducing "m" if they are not.
+ * If "m" is reduced all the way down to "1", then the check has failed
+ * and we break out of the iteration.
+ */
+struct isl_check_scaled_data {
+ int depth;
+ isl_val *m;
+};
+
+/* If constraint "c" involves the input dimension data->depth,
+ * then make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int constraint_check_scaled(__isl_take isl_constraint *c, void *user)
+{
+ struct isl_check_scaled_data *data = user;
+ int i, j, n;
+ enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_out,
+ isl_dim_div };
+
+ if (!isl_constraint_involves_dims(c, isl_dim_in, data->depth, 1)) {
+ isl_constraint_free(c);
+ return 0;
+ }
+
+ for (i = 0; i < 4; ++i) {
+ n = isl_constraint_dim(c, t[i]);
+ for (j = 0; j < n; ++j) {
+ isl_val *d;
+
+ if (t[i] == isl_dim_in && j == data->depth)
+ continue;
+ if (!isl_constraint_involves_dims(c, t[i], j, 1))
+ continue;
+ d = isl_constraint_get_coefficient_val(c, t[i], j);
+ data->m = isl_val_gcd(data->m, d);
+ if (isl_val_is_one(data->m))
+ break;
+ }
+ if (j < n)
+ break;
+ }
+
+ isl_constraint_free(c);
+
+ return i < 4 ? -1 : 0;
+}
+
+/* For each constraint of "bmap" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int basic_map_check_scaled(__isl_take isl_basic_map *bmap, void *user)
+{
+ int r;
+
+ r = isl_basic_map_foreach_constraint(bmap,
+ &constraint_check_scaled, user);
+ isl_basic_map_free(bmap);
+
+ return r;
+}
+
+/* For each constraint of "map" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int map_check_scaled(__isl_take isl_map *map, void *user)
+{
+ int r;
+
+ r = isl_map_foreach_basic_map(map, &basic_map_check_scaled, user);
+ isl_map_free(map);
+
+ return r;
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ *
+ *
+ * Before moving on to the actual AST node construction in create_node_scaled,
+ * we first check if the current dimension is strided and if we can scale
+ * down this stride. Note that we only do this if the ast_build_scale_strides
+ * option is set.
+ *
+ * In particular, let the current dimension take on values
+ *
+ * f + s a
+ *
+ * with a an integer. We check if we can find an integer m that (obviously)
+ * divides both f and s.
+ *
+ * If so, we check if the current dimension only appears in constraints
+ * where the coefficients of the other variables are multiples of m.
+ * We perform this extra check to avoid the risk of introducing
+ * divisions by scaling down the current dimension.
+ *
+ * If so, we scale the current dimension down by a factor of m.
+ * That is, we plug in
+ *
+ * i = m i' (1)
+ *
+ * Note that in principle we could always scale down strided loops
+ * by plugging in
+ *
+ * i = f + s i'
+ *
+ * but this may result in i' taking on larger values than the original i,
+ * due to the shift by "f".
+ * By constrast, the scaling in (1) can only reduce the (absolute) value "i".
+ */
+static __isl_give isl_ast_graft *create_node(__isl_take isl_union_map *executed,
+ __isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+ __isl_take isl_ast_build *build)
+{
+ struct isl_check_scaled_data data;
+ isl_ctx *ctx;
+ isl_aff *offset;
+ isl_val *d;
+
+ ctx = isl_ast_build_get_ctx(build);
+ if (!isl_options_get_ast_build_scale_strides(ctx))
+ return create_node_scaled(executed, bounds, domain, build);
+
+ data.depth = isl_ast_build_get_depth(build);
+ if (!isl_ast_build_has_stride(build, data.depth))
+ return create_node_scaled(executed, bounds, domain, build);
+
+ offset = isl_ast_build_get_offset(build, data.depth);
+ data.m = isl_ast_build_get_stride(build, data.depth);
+ if (!data.m)
+ offset = isl_aff_free(offset);
+ offset = isl_aff_scale_down_val(offset, isl_val_copy(data.m));
+ d = isl_aff_get_denominator_val(offset);
+ if (!d)
+ executed = isl_union_map_free(executed);
+
+ if (executed && isl_val_is_divisible_by(data.m, d))
+ data.m = isl_val_div(data.m, d);
+ else {
+ data.m = isl_val_set_si(data.m, 1);
+ isl_val_free(d);
+ }
+
+ if (!isl_val_is_one(data.m)) {
+ if (isl_union_map_foreach_map(executed, &map_check_scaled,
+ &data) < 0 &&
+ !isl_val_is_one(data.m))
+ executed = isl_union_map_free(executed);
+ }
+
+ if (!isl_val_is_one(data.m)) {
+ isl_space *space;
+ isl_multi_aff *ma;
+ isl_aff *aff;
+ isl_map *map;
+ isl_union_map *umap;
+
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_map_from_set(space);
+ ma = isl_multi_aff_identity(space);
+ aff = isl_multi_aff_get_aff(ma, data.depth);
+ aff = isl_aff_scale_val(aff, isl_val_copy(data.m));
+ ma = isl_multi_aff_set_aff(ma, data.depth, aff);
+
+ bounds = isl_basic_set_preimage_multi_aff(bounds,
+ isl_multi_aff_copy(ma));
+ domain = isl_set_preimage_multi_aff(domain,
+ isl_multi_aff_copy(ma));
+ map = isl_map_reverse(isl_map_from_multi_aff(ma));
+ umap = isl_union_map_from_map(map);
+ executed = isl_union_map_apply_domain(executed,
+ isl_union_map_copy(umap));
+ build = isl_ast_build_scale_down(build, isl_val_copy(data.m),
+ umap);
+ }
+ isl_aff_free(offset);
+ isl_val_free(data.m);
+
+ return create_node_scaled(executed, bounds, domain, build);
+}
+
+/* Add the basic set to the list that "user" points to.
+ */
+static int collect_basic_set(__isl_take isl_basic_set *bset, void *user)
+{
+ isl_basic_set_list **list = user;
+
+ *list = isl_basic_set_list_add(*list, bset);
+
+ return 0;
+}
+
+/* Extract the basic sets of "set" and collect them in an isl_basic_set_list.
+ */
+static __isl_give isl_basic_set_list *isl_basic_set_list_from_set(
+ __isl_take isl_set *set)
+{
+ int n;
+ isl_ctx *ctx;
+ isl_basic_set_list *list;
+
+ if (!set)
+ return NULL;
+
+ ctx = isl_set_get_ctx(set);
+
+ n = isl_set_n_basic_set(set);
+ list = isl_basic_set_list_alloc(ctx, n);
+ if (isl_set_foreach_basic_set(set, &collect_basic_set, &list) < 0)
+ list = isl_basic_set_list_free(list);
+
+ isl_set_free(set);
+ return list;
+}
+
+/* Generate code for the schedule domain "bounds"
+ * and add the result to "list".
+ *
+ * We mainly detect strides here and check if the bounds do not
+ * conflict with the current build domain
+ * and then pass over control to create_node.
+ *
+ * "bounds" reflects the bounds on the current dimension and possibly
+ * some extra conditions on outer dimensions.
+ * It does not, however, include any divs involving the current dimension,
+ * so it does not capture any stride constraints.
+ * We therefore need to compute that part of the schedule domain that
+ * intersects with "bounds" and derive the strides from the result.
+ */
+static __isl_give isl_ast_graft_list *add_node(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_union_map *executed,
+ __isl_take isl_basic_set *bounds, __isl_take isl_ast_build *build)
+{
+ isl_ast_graft *graft;
+ isl_set *domain = NULL;
+ isl_union_set *uset;
+ int empty, disjoint;
+
+ uset = isl_union_set_from_basic_set(isl_basic_set_copy(bounds));
+ executed = isl_union_map_intersect_domain(executed, uset);
+ empty = isl_union_map_is_empty(executed);
+ if (empty < 0)
+ goto error;
+ if (empty)
+ goto done;
+
+ uset = isl_union_map_domain(isl_union_map_copy(executed));
+ domain = isl_set_from_union_set(uset);
+ domain = isl_ast_build_specialize(build, domain);
+
+ domain = isl_set_compute_divs(domain);
+ domain = isl_ast_build_eliminate_inner(build, domain);
+ disjoint = isl_set_is_disjoint(domain, build->domain);
+ if (disjoint < 0)
+ goto error;
+ if (disjoint)
+ goto done;
+
+ build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+
+ graft = create_node(executed, bounds, domain,
+ isl_ast_build_copy(build));
+ list = isl_ast_graft_list_add(list, graft);
+ isl_ast_build_free(build);
+ return list;
+error:
+ list = isl_ast_graft_list_free(list);
+done:
+ isl_set_free(domain);
+ isl_basic_set_free(bounds);
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+ return list;
+}
+
+/* Does any element of i follow or coincide with any element of j
+ * at the current depth for equal values of the outer dimensions?
+ */
+static int domain_follows_at_depth(__isl_keep isl_basic_set *i,
+ __isl_keep isl_basic_set *j, void *user)
+{
+ int depth = *(int *) user;
+ isl_basic_map *test;
+ int empty;
+ int l;
+
+ test = isl_basic_map_from_domain_and_range(isl_basic_set_copy(i),
+ isl_basic_set_copy(j));
+ for (l = 0; l < depth; ++l)
+ test = isl_basic_map_equate(test, isl_dim_in, l,
+ isl_dim_out, l);
+ test = isl_basic_map_order_ge(test, isl_dim_in, depth,
+ isl_dim_out, depth);
+ empty = isl_basic_map_is_empty(test);
+ isl_basic_map_free(test);
+
+ return empty < 0 ? -1 : !empty;
+}
+
+/* Split up each element of "list" into a part that is related to "bset"
+ * according to "gt" and a part that is not.
+ * Return a list that consist of "bset" and all the pieces.
+ */
+static __isl_give isl_basic_set_list *add_split_on(
+ __isl_take isl_basic_set_list *list, __isl_take isl_basic_set *bset,
+ __isl_keep isl_basic_map *gt)
+{
+ int i, n;
+ isl_basic_set_list *res;
+
+ if (!list)
+ bset = isl_basic_set_free(bset);
+
+ gt = isl_basic_map_copy(gt);
+ gt = isl_basic_map_intersect_domain(gt, isl_basic_set_copy(bset));
+ n = isl_basic_set_list_n_basic_set(list);
+ res = isl_basic_set_list_from_basic_set(bset);
+ for (i = 0; res && i < n; ++i) {
+ isl_basic_set *bset;
+ isl_set *set1, *set2;
+ isl_basic_map *bmap;
+ int empty;
+
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ bmap = isl_basic_map_copy(gt);
+ bmap = isl_basic_map_intersect_range(bmap, bset);
+ bset = isl_basic_map_range(bmap);
+ empty = isl_basic_set_is_empty(bset);
+ if (empty < 0)
+ res = isl_basic_set_list_free(res);
+ if (empty) {
+ isl_basic_set_free(bset);
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ res = isl_basic_set_list_add(res, bset);
+ continue;
+ }
+
+ res = isl_basic_set_list_add(res, isl_basic_set_copy(bset));
+ set1 = isl_set_from_basic_set(bset);
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ set2 = isl_set_from_basic_set(bset);
+ set1 = isl_set_subtract(set2, set1);
+ set1 = isl_set_make_disjoint(set1);
+
+ res = isl_basic_set_list_concat(res,
+ isl_basic_set_list_from_set(set1));
+ }
+ isl_basic_map_free(gt);
+ isl_basic_set_list_free(list);
+ return res;
+}
+
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+ __isl_keep isl_basic_set_list *domain_list,
+ __isl_keep isl_union_map *executed,
+ __isl_keep isl_ast_build *build);
+
+/* Internal data structure for add_nodes.
+ *
+ * "executed" and "build" are extra arguments to be passed to add_node.
+ * "list" collects the results.
+ */
+struct isl_add_nodes_data {
+ isl_union_map *executed;
+ isl_ast_build *build;
+
+ isl_ast_graft_list *list;
+};
+
+/* Generate code for the schedule domains in "scc"
+ * and add the results to "list".
+ *
+ * The domains in "scc" form a strongly connected component in the ordering.
+ * If the number of domains in "scc" is larger than 1, then this means
+ * that we cannot determine a valid ordering for the domains in the component.
+ * This should be fairly rare because the individual domains
+ * have been made disjoint first.
+ * The problem is that the domains may be integrally disjoint but not
+ * rationally disjoint. For example, we may have domains
+ *
+ * { [i,i] : 0 <= i <= 1 } and { [i,1-i] : 0 <= i <= 1 }
+ *
+ * These two domains have an empty intersection, but their rational
+ * relaxations do intersect. It is impossible to order these domains
+ * in the second dimension because the first should be ordered before
+ * the second for outer dimension equal to 0, while it should be ordered
+ * after for outer dimension equal to 1.
+ *
+ * This may happen in particular in case of unrolling since the domain
+ * of each slice is replaced by its simple hull.
+ *
+ * For each basic set i in "scc" and for each of the following basic sets j,
+ * we split off that part of the basic set i that shares the outer dimensions
+ * with j and lies before j in the current dimension.
+ * We collect all the pieces in a new list that replaces "scc".
+ *
+ * While the elements in "scc" should be disjoint, we double-check
+ * this property to avoid running into an infinite recursion in case
+ * they intersect due to some internal error.
+ */
+static int add_nodes(__isl_take isl_basic_set_list *scc, void *user)
+{
+ struct isl_add_nodes_data *data = user;
+ int i, n, depth;
+ isl_basic_set *bset, *first;
+ isl_basic_set_list *list;
+ isl_space *space;
+ isl_basic_map *gt;
+
+ n = isl_basic_set_list_n_basic_set(scc);
+ bset = isl_basic_set_list_get_basic_set(scc, 0);
+ if (n == 1) {
+ isl_basic_set_list_free(scc);
+ data->list = add_node(data->list,
+ isl_union_map_copy(data->executed), bset,
+ isl_ast_build_copy(data->build));
+ return data->list ? 0 : -1;
+ }
+
+ depth = isl_ast_build_get_depth(data->build);
+ space = isl_basic_set_get_space(bset);
+ space = isl_space_map_from_set(space);
+ gt = isl_basic_map_universe(space);
+ for (i = 0; i < depth; ++i)
+ gt = isl_basic_map_equate(gt, isl_dim_in, i, isl_dim_out, i);
+ gt = isl_basic_map_order_gt(gt, isl_dim_in, depth, isl_dim_out, depth);
+
+ first = isl_basic_set_copy(bset);
+ list = isl_basic_set_list_from_basic_set(bset);
+ for (i = 1; i < n; ++i) {
+ int disjoint;
+
+ bset = isl_basic_set_list_get_basic_set(scc, i);
+
+ disjoint = isl_basic_set_is_disjoint(bset, first);
+ if (disjoint < 0)
+ list = isl_basic_set_list_free(list);
+ else if (!disjoint)
+ isl_die(isl_basic_set_list_get_ctx(scc),
+ isl_error_internal,
+ "basic sets in scc are assumed to be disjoint",
+ list = isl_basic_set_list_free(list));
+
+ list = add_split_on(list, bset, gt);
+ }
+ isl_basic_set_free(first);
+ isl_basic_map_free(gt);
+ isl_basic_set_list_free(scc);
+ scc = list;
+ data->list = isl_ast_graft_list_concat(data->list,
+ generate_sorted_domains(scc, data->executed, data->build));
+ isl_basic_set_list_free(scc);
+
+ return data->list ? 0 : -1;
+}
+
+/* Sort the domains in "domain_list" according to the execution order
+ * at the current depth (for equal values of the outer dimensions),
+ * generate code for each of them, collecting the results in a list.
+ * If no code is generated (because the intersection of the inverse schedule
+ * with the domains turns out to be empty), then an empty list is returned.
+ *
+ * The caller is responsible for ensuring that the basic sets in "domain_list"
+ * are pair-wise disjoint. It can, however, in principle happen that
+ * two basic sets should be ordered one way for one value of the outer
+ * dimensions and the other way for some other value of the outer dimensions.
+ * We therefore play safe and look for strongly connected components.
+ * The function add_nodes takes care of handling non-trivial components.
+ */
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+ __isl_keep isl_basic_set_list *domain_list,
+ __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ struct isl_add_nodes_data data;
+ int depth;
+ int n;
+
+ if (!domain_list)
+ return NULL;
+
+ ctx = isl_basic_set_list_get_ctx(domain_list);
+ n = isl_basic_set_list_n_basic_set(domain_list);
+ data.list = isl_ast_graft_list_alloc(ctx, n);
+ if (n == 0)
+ return data.list;
+ if (n == 1)
+ return add_node(data.list, isl_union_map_copy(executed),
+ isl_basic_set_list_get_basic_set(domain_list, 0),
+ isl_ast_build_copy(build));
+
+ depth = isl_ast_build_get_depth(build);
+ data.executed = executed;
+ data.build = build;
+ if (isl_basic_set_list_foreach_scc(domain_list,
+ &domain_follows_at_depth, &depth,
+ &add_nodes, &data) < 0)
+ data.list = isl_ast_graft_list_free(data.list);
+
+ return data.list;
+}
+
+/* Do i and j share any values for the outer dimensions?
+ */
+static int shared_outer(__isl_keep isl_basic_set *i,
+ __isl_keep isl_basic_set *j, void *user)
+{
+ int depth = *(int *) user;
+ isl_basic_map *test;
+ int empty;
+ int l;
+
+ test = isl_basic_map_from_domain_and_range(isl_basic_set_copy(i),
+ isl_basic_set_copy(j));
+ for (l = 0; l < depth; ++l)
+ test = isl_basic_map_equate(test, isl_dim_in, l,
+ isl_dim_out, l);
+ empty = isl_basic_map_is_empty(test);
+ isl_basic_map_free(test);
+
+ return empty < 0 ? -1 : !empty;
+}
+
+/* Internal data structure for generate_sorted_domains_wrap.
+ *
+ * "n" is the total number of basic sets
+ * "executed" and "build" are extra arguments to be passed
+ * to generate_sorted_domains.
+ *
+ * "single" is set to 1 by generate_sorted_domains_wrap if there
+ * is only a single component.
+ * "list" collects the results.
+ */
+struct isl_ast_generate_parallel_domains_data {
+ int n;
+ isl_union_map *executed;
+ isl_ast_build *build;
+
+ int single;
+ isl_ast_graft_list *list;
+};
+
+/* Call generate_sorted_domains on "scc", fuse the result into a list
+ * with either zero or one graft and collect the these single element
+ * lists into data->list.
+ *
+ * If there is only one component, i.e., if the number of basic sets
+ * in the current component is equal to the total number of basic sets,
+ * then data->single is set to 1 and the result of generate_sorted_domains
+ * is not fused.
+ */
+static int generate_sorted_domains_wrap(__isl_take isl_basic_set_list *scc,
+ void *user)
+{
+ struct isl_ast_generate_parallel_domains_data *data = user;
+ isl_ast_graft_list *list;
+
+ list = generate_sorted_domains(scc, data->executed, data->build);
+ data->single = isl_basic_set_list_n_basic_set(scc) == data->n;
+ if (!data->single)
+ list = isl_ast_graft_list_fuse(list, data->build);
+ if (!data->list)
+ data->list = list;
+ else
+ data->list = isl_ast_graft_list_concat(data->list, list);
+
+ isl_basic_set_list_free(scc);
+ if (!data->list)
+ return -1;
+
+ return 0;
+}
+
+/* Look for any (weakly connected) components in the "domain_list"
+ * of domains that share some values of the outer dimensions.
+ * That is, domains in different components do not share any values
+ * of the outer dimensions. This means that these components
+ * can be freely reordered.
+ * Within each of the components, we sort the domains according
+ * to the execution order at the current depth.
+ *
+ * If there is more than one component, then generate_sorted_domains_wrap
+ * fuses the result of each call to generate_sorted_domains
+ * into a list with either zero or one graft and collects these (at most)
+ * single element lists into a bigger list. This means that the elements of the
+ * final list can be freely reordered. In particular, we sort them
+ * according to an arbitrary but fixed ordering to ease merging of
+ * graft lists from different components.
+ */
+static __isl_give isl_ast_graft_list *generate_parallel_domains(
+ __isl_keep isl_basic_set_list *domain_list,
+ __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+ int depth;
+ struct isl_ast_generate_parallel_domains_data data;
+
+ if (!domain_list)
+ return NULL;
+
+ data.n = isl_basic_set_list_n_basic_set(domain_list);
+ if (data.n <= 1)
+ return generate_sorted_domains(domain_list, executed, build);
+
+ depth = isl_ast_build_get_depth(build);
+ data.list = NULL;
+ data.executed = executed;
+ data.build = build;
+ data.single = 0;
+ if (isl_basic_set_list_foreach_scc(domain_list, &shared_outer, &depth,
+ &generate_sorted_domains_wrap,
+ &data) < 0)
+ data.list = isl_ast_graft_list_free(data.list);
+
+ if (!data.single)
+ data.list = isl_ast_graft_list_sort_guard(data.list);
+
+ return data.list;
+}
+
+/* Internal data for separate_domain.
+ *
+ * "explicit" is set if we only want to use explicit bounds.
+ *
+ * "domain" collects the separated domains.
+ */
+struct isl_separate_domain_data {
+ isl_ast_build *build;
+ int explicit;
+ isl_set *domain;
+};
+
+/* Extract implicit bounds on the current dimension for the executed "map".
+ *
+ * The domain of "map" may involve inner dimensions, so we
+ * need to eliminate them.
+ */
+static __isl_give isl_set *implicit_bounds(__isl_take isl_map *map,
+ __isl_keep isl_ast_build *build)
+{
+ isl_set *domain;
+
+ domain = isl_map_domain(map);
+ domain = isl_ast_build_eliminate(build, domain);
+
+ return domain;
+}
+
+/* Extract explicit bounds on the current dimension for the executed "map".
+ *
+ * Rather than eliminating the inner dimensions as in implicit_bounds,
+ * we simply drop any constraints involving those inner dimensions.
+ * The idea is that most bounds that are implied by constraints on the
+ * inner dimensions will be enforced by for loops and not by explicit guards.
+ * There is then no need to separate along those bounds.
+ */
+static __isl_give isl_set *explicit_bounds(__isl_take isl_map *map,
+ __isl_keep isl_ast_build *build)
+{
+ isl_set *domain;
+ int depth, dim;
+
+ dim = isl_map_dim(map, isl_dim_out);
+ map = isl_map_drop_constraints_involving_dims(map, isl_dim_out, 0, dim);
+
+ domain = isl_map_domain(map);
+ depth = isl_ast_build_get_depth(build);
+ dim = isl_set_dim(domain, isl_dim_set);
+ domain = isl_set_detect_equalities(domain);
+ domain = isl_set_drop_constraints_involving_dims(domain,
+ isl_dim_set, depth + 1, dim - (depth + 1));
+ domain = isl_set_remove_divs_involving_dims(domain,
+ isl_dim_set, depth, 1);
+ domain = isl_set_remove_unknown_divs(domain);
+
+ return domain;
+}
+
+/* Split data->domain into pieces that intersect with the range of "map"
+ * and pieces that do not intersect with the range of "map"
+ * and then add that part of the range of "map" that does not intersect
+ * with data->domain.
+ */
+static int separate_domain(__isl_take isl_map *map, void *user)
+{
+ struct isl_separate_domain_data *data = user;
+ isl_set *domain;
+ isl_set *d1, *d2;
+
+ if (data->explicit)
+ domain = explicit_bounds(map, data->build);
+ else
+ domain = implicit_bounds(map, data->build);
+
+ domain = isl_set_coalesce(domain);
+ domain = isl_set_make_disjoint(domain);
+ d1 = isl_set_subtract(isl_set_copy(domain), isl_set_copy(data->domain));
+ d2 = isl_set_subtract(isl_set_copy(data->domain), isl_set_copy(domain));
+ data->domain = isl_set_intersect(data->domain, domain);
+ data->domain = isl_set_union(data->domain, d1);
+ data->domain = isl_set_union(data->domain, d2);
+
+ return 0;
+}
+
+/* Separate the schedule domains of "executed".
+ *
+ * That is, break up the domain of "executed" into basic sets,
+ * such that for each basic set S, every element in S is associated with
+ * the same domain spaces.
+ *
+ * "space" is the (single) domain space of "executed".
+ */
+static __isl_give isl_set *separate_schedule_domains(
+ __isl_take isl_space *space, __isl_take isl_union_map *executed,
+ __isl_keep isl_ast_build *build)
+{
+ struct isl_separate_domain_data data = { build };
+ isl_ctx *ctx;
+
+ ctx = isl_ast_build_get_ctx(build);
+ data.explicit = isl_options_get_ast_build_separation_bounds(ctx) ==
+ ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT;
+ data.domain = isl_set_empty(space);
+ if (isl_union_map_foreach_map(executed, &separate_domain, &data) < 0)
+ data.domain = isl_set_free(data.domain);
+
+ isl_union_map_free(executed);
+ return data.domain;
+}
+
+/* Temporary data used during the search for a lower bound for unrolling.
+ *
+ * "domain" is the original set for which to find a lower bound
+ * "depth" is the dimension for which to find a lower boudn
+ *
+ * "lower" is the best lower bound found so far. It is NULL if we have not
+ * found any yet.
+ * "n" is the corresponding size. If lower is NULL, then the value of n
+ * is undefined.
+ */
+struct isl_find_unroll_data {
+ isl_set *domain;
+ int depth;
+
+ isl_aff *lower;
+ int *n;
+};
+
+/* Check if we can use "c" as a lower bound and if it is better than
+ * any previously found lower bound.
+ *
+ * If "c" does not involve the dimension at the current depth,
+ * then we cannot use it.
+ * Otherwise, let "c" be of the form
+ *
+ * i >= f(j)/a
+ *
+ * We compute the maximal value of
+ *
+ * -ceil(f(j)/a)) + i + 1
+ *
+ * over the domain. If there is such a value "n", then we know
+ *
+ * -ceil(f(j)/a)) + i + 1 <= n
+ *
+ * or
+ *
+ * i < ceil(f(j)/a)) + n
+ *
+ * meaning that we can use ceil(f(j)/a)) as a lower bound for unrolling.
+ * We just need to check if we have found any lower bound before and
+ * if the new lower bound is better (smaller n) than the previously found
+ * lower bounds.
+ */
+static int update_unrolling_lower_bound(struct isl_find_unroll_data *data,
+ __isl_keep isl_constraint *c)
+{
+ isl_aff *aff, *lower;
+ isl_val *max;
+
+ if (!isl_constraint_is_lower_bound(c, isl_dim_set, data->depth))
+ return 0;
+
+ lower = isl_constraint_get_bound(c, isl_dim_set, data->depth);
+ lower = isl_aff_ceil(lower);
+ aff = isl_aff_copy(lower);
+ aff = isl_aff_neg(aff);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, data->depth, 1);
+ aff = isl_aff_add_constant_si(aff, 1);
+ max = isl_set_max_val(data->domain, aff);
+ isl_aff_free(aff);
+
+ if (!max)
+ goto error;
+ if (isl_val_is_infty(max)) {
+ isl_val_free(max);
+ isl_aff_free(lower);
+ return 0;
+ }
+
+ if (isl_val_cmp_si(max, INT_MAX) <= 0 &&
+ (!data->lower || isl_val_cmp_si(max, *data->n) < 0)) {
+ isl_aff_free(data->lower);
+ data->lower = lower;
+ *data->n = isl_val_get_num_si(max);
+ } else
+ isl_aff_free(lower);
+ isl_val_free(max);
+
+ return 1;
+error:
+ isl_aff_free(lower);
+ return -1;
+}
+
+/* Check if we can use "c" as a lower bound and if it is better than
+ * any previously found lower bound.
+ */
+static int constraint_find_unroll(__isl_take isl_constraint *c, void *user)
+{
+ struct isl_find_unroll_data *data;
+ int r;
+
+ data = (struct isl_find_unroll_data *) user;
+ r = update_unrolling_lower_bound(data, c);
+ isl_constraint_free(c);
+
+ return r;
+}
+
+/* Look for a lower bound l(i) on the dimension at "depth"
+ * and a size n such that "domain" is a subset of
+ *
+ * { [i] : l(i) <= i_d < l(i) + n }
+ *
+ * where d is "depth" and l(i) depends only on earlier dimensions.
+ * Furthermore, try and find a lower bound such that n is as small as possible.
+ * In particular, "n" needs to be finite.
+ *
+ * Inner dimensions have been eliminated from "domain" by the caller.
+ *
+ * We first construct a collection of lower bounds on the input set
+ * by computing its simple hull. We then iterate through them,
+ * discarding those that we cannot use (either because they do not
+ * involve the dimension at "depth" or because they have no corresponding
+ * upper bound, meaning that "n" would be unbounded) and pick out the
+ * best from the remaining ones.
+ *
+ * If we cannot find a suitable lower bound, then we consider that
+ * to be an error.
+ */
+static __isl_give isl_aff *find_unroll_lower_bound(__isl_keep isl_set *domain,
+ int depth, int *n)
+{
+ struct isl_find_unroll_data data = { domain, depth, NULL, n };
+ isl_basic_set *hull;
+
+ hull = isl_set_simple_hull(isl_set_copy(domain));
+
+ if (isl_basic_set_foreach_constraint(hull,
+ &constraint_find_unroll, &data) < 0)
+ goto error;
+
+ isl_basic_set_free(hull);
+
+ if (!data.lower)
+ isl_die(isl_set_get_ctx(domain), isl_error_invalid,
+ "cannot find lower bound for unrolling", return NULL);
+
+ return data.lower;
+error:
+ isl_basic_set_free(hull);
+ return isl_aff_free(data.lower);
+}
+
+/* Return the constraint
+ *
+ * i_"depth" = aff + offset
+ */
+static __isl_give isl_constraint *at_offset(int depth, __isl_keep isl_aff *aff,
+ int offset)
+{
+ aff = isl_aff_copy(aff);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, depth, -1);
+ aff = isl_aff_add_constant_si(aff, offset);
+ return isl_equality_from_aff(aff);
+}
+
+/* Data structure for storing the results and the intermediate objects
+ * of compute_domains.
+ *
+ * "list" is the main result of the function and contains a list
+ * of disjoint basic sets for which code should be generated.
+ *
+ * "executed" and "build" are inputs to compute_domains.
+ * "schedule_domain" is the domain of "executed".
+ *
+ * "option" constains the domains at the current depth that should by
+ * atomic, separated or unrolled. These domains are as specified by
+ * the user, except that inner dimensions have been eliminated and
+ * that they have been made pair-wise disjoint.
+ *
+ * "sep_class" contains the user-specified split into separation classes
+ * specialized to the current depth.
+ * "done" contains the union of the separation domains that have already
+ * been handled.
+ */
+struct isl_codegen_domains {
+ isl_basic_set_list *list;
+
+ isl_union_map *executed;
+ isl_ast_build *build;
+ isl_set *schedule_domain;
+
+ isl_set *option[3];
+
+ isl_map *sep_class;
+ isl_set *done;
+};
+
+/* Extend domains->list with a list of basic sets, one for each value
+ * of the current dimension in "domain" and remove the corresponding
+ * sets from the class domain. Return the updated class domain.
+ * The divs that involve the current dimension have not been projected out
+ * from this domain.
+ *
+ * Since we are going to be iterating over the individual values,
+ * we first check if there are any strides on the current dimension.
+ * If there is, we rewrite the current dimension i as
+ *
+ * i = stride i' + offset
+ *
+ * and then iterate over individual values of i' instead.
+ *
+ * We then look for a lower bound on i' and a size such that the domain
+ * is a subset of
+ *
+ * { [j,i'] : l(j) <= i' < l(j) + n }
+ *
+ * and then take slices of the domain at values of i'
+ * between l(j) and l(j) + n - 1.
+ *
+ * We compute the unshifted simple hull of each slice to ensure that
+ * we have a single basic set per offset. The slicing constraint
+ * may get simplified away before the unshifted simple hull is taken
+ * and may therefore in some rare cases disappear from the result.
+ * We therefore explicitly add the constraint back after computing
+ * the unshifted simple hull to ensure that the basic sets
+ * remain disjoint. The constraints that are dropped by taking the hull
+ * will be taken into account at the next level, as in the case of the
+ * atomic option.
+ *
+ * Finally, we map i' back to i and add each basic set to the list.
+ * Since we may have dropped some constraints, we intersect with
+ * the class domain again to ensure that each element in the list
+ * is disjoint from the other class domains.
+ */
+static __isl_give isl_set *do_unroll(struct isl_codegen_domains *domains,
+ __isl_take isl_set *domain, __isl_take isl_set *class_domain)
+{
+ int i, n;
+ int depth;
+ isl_ctx *ctx;
+ isl_aff *lower;
+ isl_multi_aff *expansion;
+ isl_basic_map *bmap;
+ isl_set *unroll_domain;
+ isl_ast_build *build;
+
+ if (!domain)
+ return isl_set_free(class_domain);
+
+ ctx = isl_set_get_ctx(domain);
+ depth = isl_ast_build_get_depth(domains->build);
+ build = isl_ast_build_copy(domains->build);
+ domain = isl_ast_build_eliminate_inner(build, domain);
+ domain = isl_set_intersect(domain, isl_ast_build_get_domain(build));
+ build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+ expansion = isl_ast_build_get_stride_expansion(build);
+
+ domain = isl_set_preimage_multi_aff(domain,
+ isl_multi_aff_copy(expansion));
+ domain = isl_ast_build_eliminate_divs(build, domain);
+
+ isl_ast_build_free(build);
+
+ lower = find_unroll_lower_bound(domain, depth, &n);
+ if (!lower)
+ class_domain = isl_set_free(class_domain);
+
+ bmap = isl_basic_map_from_multi_aff(expansion);
+
+ unroll_domain = isl_set_empty(isl_set_get_space(domain));
+
+ for (i = 0; class_domain && i < n; ++i) {
+ isl_set *set;
+ isl_basic_set *bset;
+ isl_constraint *slice;
+ isl_basic_set_list *list;
+
+ slice = at_offset(depth, lower, i);
+ set = isl_set_copy(domain);
+ set = isl_set_add_constraint(set, isl_constraint_copy(slice));
+ bset = isl_set_unshifted_simple_hull(set);
+ bset = isl_basic_set_add_constraint(bset, slice);
+ bset = isl_basic_set_apply(bset, isl_basic_map_copy(bmap));
+ set = isl_set_from_basic_set(bset);
+ unroll_domain = isl_set_union(unroll_domain, isl_set_copy(set));
+ set = isl_set_intersect(set, isl_set_copy(class_domain));
+ set = isl_set_make_disjoint(set);
+ list = isl_basic_set_list_from_set(set);
+ domains->list = isl_basic_set_list_concat(domains->list, list);
+ }
+
+ class_domain = isl_set_subtract(class_domain, unroll_domain);
+
+ isl_aff_free(lower);
+ isl_set_free(domain);
+ isl_basic_map_free(bmap);
+
+ return class_domain;
+}
+
+/* Add domains to domains->list for each individual value of the current
+ * dimension, for that part of the schedule domain that lies in the
+ * intersection of the option domain and the class domain.
+ * Remove the corresponding sets from the class domain and
+ * return the updated class domain.
+ *
+ * We first break up the unroll option domain into individual pieces
+ * and then handle each of them separately. The unroll option domain
+ * has been made disjoint in compute_domains_init_options,
+ *
+ * Note that we actively want to combine different pieces of the
+ * schedule domain that have the same value at the current dimension.
+ * We therefore need to break up the unroll option domain before
+ * intersecting with class and schedule domain, hoping that the
+ * unroll option domain specified by the user is relatively simple.
+ */
+static __isl_give isl_set *compute_unroll_domains(
+ struct isl_codegen_domains *domains, __isl_take isl_set *class_domain)
+{
+ isl_set *unroll_domain;
+ isl_basic_set_list *unroll_list;
+ int i, n;
+ int empty;
+
+ empty = isl_set_is_empty(domains->option[unroll]);
+ if (empty < 0)
+ return isl_set_free(class_domain);
+ if (empty)
+ return class_domain;
+
+ unroll_domain = isl_set_copy(domains->option[unroll]);
+ unroll_list = isl_basic_set_list_from_set(unroll_domain);
+
+ n = isl_basic_set_list_n_basic_set(unroll_list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset;
+
+ bset = isl_basic_set_list_get_basic_set(unroll_list, i);
+ unroll_domain = isl_set_from_basic_set(bset);
+ unroll_domain = isl_set_intersect(unroll_domain,
+ isl_set_copy(class_domain));
+ unroll_domain = isl_set_intersect(unroll_domain,
+ isl_set_copy(domains->schedule_domain));
+
+ empty = isl_set_is_empty(unroll_domain);
+ if (empty >= 0 && empty) {
+ isl_set_free(unroll_domain);
+ continue;
+ }
+
+ class_domain = do_unroll(domains, unroll_domain, class_domain);
+ }
+
+ isl_basic_set_list_free(unroll_list);
+
+ return class_domain;
+}
+
+/* Try and construct a single basic set that includes the intersection of
+ * the schedule domain, the atomic option domain and the class domain.
+ * Add the resulting basic set(s) to domains->list and remove them
+ * from class_domain. Return the updated class domain.
+ *
+ * We construct a single domain rather than trying to combine
+ * the schedule domains of individual domains because we are working
+ * within a single component so that non-overlapping schedule domains
+ * should already have been separated.
+ * We do however need to make sure that this single domains is a subset
+ * of the class domain so that it would not intersect with any other
+ * class domains. This means that we may end up splitting up the atomic
+ * domain in case separation classes are being used.
+ *
+ * "domain" is the intersection of the schedule domain and the class domain,
+ * with inner dimensions projected out.
+ */
+static __isl_give isl_set *compute_atomic_domain(
+ struct isl_codegen_domains *domains, __isl_take isl_set *class_domain)
+{
+ isl_basic_set *bset;
+ isl_basic_set_list *list;
+ isl_set *domain, *atomic_domain;
+ int empty;
+
+ domain = isl_set_copy(domains->option[atomic]);
+ domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+ domain = isl_set_intersect(domain,
+ isl_set_copy(domains->schedule_domain));
+ empty = isl_set_is_empty(domain);
+ if (empty < 0)
+ class_domain = isl_set_free(class_domain);
+ if (empty) {
+ isl_set_free(domain);
+ return class_domain;
+ }
+
+ domain = isl_ast_build_eliminate(domains->build, domain);
+ domain = isl_set_coalesce(domain);
+ bset = isl_set_unshifted_simple_hull(domain);
+ domain = isl_set_from_basic_set(bset);
+ atomic_domain = isl_set_copy(domain);
+ domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+ class_domain = isl_set_subtract(class_domain, atomic_domain);
+ domain = isl_set_make_disjoint(domain);
+ list = isl_basic_set_list_from_set(domain);
+ domains->list = isl_basic_set_list_concat(domains->list, list);
+
+ return class_domain;
+}
+
+/* Split up the schedule domain into uniform basic sets,
+ * in the sense that each element in a basic set is associated to
+ * elements of the same domains, and add the result to domains->list.
+ * Do this for that part of the schedule domain that lies in the
+ * intersection of "class_domain" and the separate option domain.
+ *
+ * "class_domain" may or may not include the constraints
+ * of the schedule domain, but this does not make a difference
+ * since we are going to intersect it with the domain of the inverse schedule.
+ * If it includes schedule domain constraints, then they may involve
+ * inner dimensions, but we will eliminate them in separation_domain.
+ */
+static int compute_separate_domain(struct isl_codegen_domains *domains,
+ __isl_keep isl_set *class_domain)
+{
+ isl_space *space;
+ isl_set *domain;
+ isl_union_map *executed;
+ isl_basic_set_list *list;
+ int empty;
+
+ domain = isl_set_copy(domains->option[separate]);
+ domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+ executed = isl_union_map_copy(domains->executed);
+ executed = isl_union_map_intersect_domain(executed,
+ isl_union_set_from_set(domain));
+ empty = isl_union_map_is_empty(executed);
+ if (empty < 0 || empty) {
+ isl_union_map_free(executed);
+ return empty < 0 ? -1 : 0;
+ }
+
+ space = isl_set_get_space(class_domain);
+ domain = separate_schedule_domains(space, executed, domains->build);
+
+ list = isl_basic_set_list_from_set(domain);
+ domains->list = isl_basic_set_list_concat(domains->list, list);
+
+ return 0;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the given separation class domain.
+ *
+ * If any separation classes have been defined, then "class_domain"
+ * is the domain of the current class and does not refer to inner dimensions.
+ * Otherwise, "class_domain" is the universe domain.
+ *
+ * We first make sure that the class domain is disjoint from
+ * previously considered class domains.
+ *
+ * The separate domains can be computed directly from the "class_domain".
+ *
+ * The unroll, atomic and remainder domains need the constraints
+ * from the schedule domain.
+ *
+ * For unrolling, the actual schedule domain is needed (with divs that
+ * may refer to the current dimension) so that stride detection can be
+ * performed.
+ *
+ * For atomic and remainder domains, inner dimensions and divs involving
+ * the current dimensions should be eliminated.
+ * In case we are working within a separation class, we need to intersect
+ * the result with the current "class_domain" to ensure that the domains
+ * are disjoint from those generated from other class domains.
+ *
+ * The domain that has been made atomic may be larger than specified
+ * by the user since it needs to be representable as a single basic set.
+ * This possibly larger domain is removed from class_domain by
+ * compute_atomic_domain. It is computed first so that the extended domain
+ * would not overlap with any domains computed before.
+ * Similary, the unrolled domains may have some constraints removed and
+ * may therefore also be larger than specified by the user.
+ *
+ * If anything is left after handling separate, unroll and atomic,
+ * we split it up into basic sets and append the basic sets to domains->list.
+ */
+static int compute_partial_domains(struct isl_codegen_domains *domains,
+ __isl_take isl_set *class_domain)
+{
+ isl_basic_set_list *list;
+ isl_set *domain;
+
+ class_domain = isl_set_subtract(class_domain,
+ isl_set_copy(domains->done));
+ domains->done = isl_set_union(domains->done,
+ isl_set_copy(class_domain));
+
+ class_domain = compute_atomic_domain(domains, class_domain);
+ class_domain = compute_unroll_domains(domains, class_domain);
+
+ domain = isl_set_copy(class_domain);
+
+ if (compute_separate_domain(domains, domain) < 0)
+ goto error;
+ domain = isl_set_subtract(domain,
+ isl_set_copy(domains->option[separate]));
+
+ domain = isl_set_intersect(domain,
+ isl_set_copy(domains->schedule_domain));
+
+ domain = isl_ast_build_eliminate(domains->build, domain);
+ domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+
+ domain = isl_set_coalesce(domain);
+ domain = isl_set_make_disjoint(domain);
+
+ list = isl_basic_set_list_from_set(domain);
+ domains->list = isl_basic_set_list_concat(domains->list, list);
+
+ isl_set_free(class_domain);
+
+ return 0;
+error:
+ isl_set_free(domain);
+ isl_set_free(class_domain);
+ return -1;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the separation class identified by "pnt".
+ *
+ * We extract the corresponding class domain from domains->sep_class,
+ * eliminate inner dimensions and pass control to compute_partial_domains.
+ */
+static int compute_class_domains(__isl_take isl_point *pnt, void *user)
+{
+ struct isl_codegen_domains *domains = user;
+ isl_set *class_set;
+ isl_set *domain;
+ int disjoint;
+
+ class_set = isl_set_from_point(pnt);
+ domain = isl_map_domain(isl_map_intersect_range(
+ isl_map_copy(domains->sep_class), class_set));
+ domain = isl_ast_build_compute_gist(domains->build, domain);
+ domain = isl_ast_build_eliminate(domains->build, domain);
+
+ disjoint = isl_set_plain_is_disjoint(domain, domains->schedule_domain);
+ if (disjoint < 0)
+ return -1;
+ if (disjoint) {
+ isl_set_free(domain);
+ return 0;
+ }
+
+ return compute_partial_domains(domains, domain);
+}
+
+/* Extract the domains at the current depth that should be atomic,
+ * separated or unrolled and store them in option.
+ *
+ * The domains specified by the user might overlap, so we make
+ * them disjoint by subtracting earlier domains from later domains.
+ */
+static void compute_domains_init_options(isl_set *option[3],
+ __isl_keep isl_ast_build *build)
+{
+ enum isl_ast_build_domain_type type, type2;
+
+ for (type = atomic; type <= separate; ++type) {
+ option[type] = isl_ast_build_get_option_domain(build, type);
+ for (type2 = atomic; type2 < type; ++type2)
+ option[type] = isl_set_subtract(option[type],
+ isl_set_copy(option[type2]));
+ }
+
+ option[unroll] = isl_set_coalesce(option[unroll]);
+ option[unroll] = isl_set_make_disjoint(option[unroll]);
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately,
+ * based on the user-specified options.
+ * Return the list of disjoint basic sets.
+ *
+ * There are three kinds of domains that we need to keep track of.
+ * - the "schedule domain" is the domain of "executed"
+ * - the "class domain" is the domain corresponding to the currrent
+ * separation class
+ * - the "option domain" is the domain corresponding to one of the options
+ * atomic, unroll or separate
+ *
+ * We first consider the individial values of the separation classes
+ * and split up the domain for each of them separately.
+ * Finally, we consider the remainder. If no separation classes were
+ * specified, then we call compute_partial_domains with the universe
+ * "class_domain". Otherwise, we take the "schedule_domain" as "class_domain",
+ * with inner dimensions removed. We do this because we want to
+ * avoid computing the complement of the class domains (i.e., the difference
+ * between the universe and domains->done).
+ */
+static __isl_give isl_basic_set_list *compute_domains(
+ __isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+ struct isl_codegen_domains domains;
+ isl_ctx *ctx;
+ isl_set *domain;
+ isl_union_set *schedule_domain;
+ isl_set *classes;
+ isl_space *space;
+ int n_param;
+ enum isl_ast_build_domain_type type;
+ int empty;
+
+ if (!executed)
+ return NULL;
+
+ ctx = isl_union_map_get_ctx(executed);
+ domains.list = isl_basic_set_list_alloc(ctx, 0);
+
+ schedule_domain = isl_union_map_domain(isl_union_map_copy(executed));
+ domain = isl_set_from_union_set(schedule_domain);
+
+ compute_domains_init_options(domains.option, build);
+
+ domains.sep_class = isl_ast_build_get_separation_class(build);
+ classes = isl_map_range(isl_map_copy(domains.sep_class));
+ n_param = isl_set_dim(classes, isl_dim_param);
+ classes = isl_set_project_out(classes, isl_dim_param, 0, n_param);
+
+ space = isl_set_get_space(domain);
+ domains.build = build;
+ domains.schedule_domain = isl_set_copy(domain);
+ domains.executed = executed;
+ domains.done = isl_set_empty(space);
+
+ if (isl_set_foreach_point(classes, &compute_class_domains, &domains) < 0)
+ domains.list = isl_basic_set_list_free(domains.list);
+ isl_set_free(classes);
+
+ empty = isl_set_is_empty(domains.done);
+ if (empty < 0) {
+ domains.list = isl_basic_set_list_free(domains.list);
+ domain = isl_set_free(domain);
+ } else if (empty) {
+ isl_set_free(domain);
+ domain = isl_set_universe(isl_set_get_space(domains.done));
+ } else {
+ domain = isl_ast_build_eliminate(build, domain);
+ }
+ if (compute_partial_domains(&domains, domain) < 0)
+ domains.list = isl_basic_set_list_free(domains.list);
+
+ isl_set_free(domains.schedule_domain);
+ isl_set_free(domains.done);
+ isl_map_free(domains.sep_class);
+ for (type = atomic; type <= separate; ++type)
+ isl_set_free(domains.option[type]);
+
+ return domains.list;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * We first split up the domain at the current depth into disjoint
+ * basic sets based on the user-specified options.
+ * Then we generated code for each of them and concatenate the results.
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+ isl_basic_set_list *domain_list;
+ isl_ast_graft_list *list = NULL;
+
+ domain_list = compute_domains(executed, build);
+ list = generate_parallel_domains(domain_list, executed, build);
+
+ isl_basic_set_list_free(domain_list);
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+
+ return list;
+}
+
+struct isl_set_map_pair {
+ isl_set *set;
+ isl_map *map;
+};
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * return the union of the "map" fields of the elements
+ * indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_union_map *construct_component_executed(
+ struct isl_set_map_pair *domain, int *order, int n)
+{
+ int i;
+ isl_map *map;
+ isl_union_map *executed;
+
+ map = isl_map_copy(domain[order[0]].map);
+ executed = isl_union_map_from_map(map);
+ for (i = 1; i < n; ++i) {
+ map = isl_map_copy(domain[order[i]].map);
+ executed = isl_union_map_add_map(executed, map);
+ }
+
+ return executed;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component_from_list(
+ struct isl_set_map_pair *domain, int *order, int n,
+ __isl_take isl_ast_build *build)
+{
+ isl_union_map *executed;
+
+ executed = construct_component_executed(domain, order, n);
+ return generate_shifted_component(executed, build);
+}
+
+/* Does set dimension "pos" of "set" have an obviously fixed value?
+ */
+static int dim_is_fixed(__isl_keep isl_set *set, int pos)
+{
+ int fixed;
+ isl_val *v;
+
+ v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, pos);
+ if (!v)
+ return -1;
+ fixed = !isl_val_is_nan(v);
+ isl_val_free(v);
+
+ return fixed;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * do all (except for at most one) of the "set" field of the elements
+ * indexed by the first "n" elements of "order" have a fixed value
+ * at position "depth"?
+ */
+static int at_most_one_non_fixed(struct isl_set_map_pair *domain,
+ int *order, int n, int depth)
+{
+ int i;
+ int non_fixed = -1;
+
+ for (i = 0; i < n; ++i) {
+ int f;
+
+ f = dim_is_fixed(domain[order[i]].set, depth);
+ if (f < 0)
+ return -1;
+ if (f)
+ continue;
+ if (non_fixed >= 0)
+ return 0;
+ non_fixed = i;
+ }
+
+ return 1;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * eliminate the inner dimensions from the "set" field of the elements
+ * indexed by the first "n" elements of "order", provided the current
+ * dimension does not have a fixed value.
+ *
+ * Return the index of the first element in "order" with a corresponding
+ * "set" field that does not have an (obviously) fixed value.
+ */
+static int eliminate_non_fixed(struct isl_set_map_pair *domain,
+ int *order, int n, int depth, __isl_keep isl_ast_build *build)
+{
+ int i;
+ int base = -1;
+
+ for (i = n - 1; i >= 0; --i) {
+ int f;
+ f = dim_is_fixed(domain[order[i]].set, depth);
+ if (f < 0)
+ return -1;
+ if (f)
+ continue;
+ domain[order[i]].set = isl_ast_build_eliminate_inner(build,
+ domain[order[i]].set);
+ base = i;
+ }
+
+ return base;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * find the element of "domain" (amongst those indexed by the first "n"
+ * elements of "order") with the "set" field that has the smallest
+ * value for the current iterator.
+ *
+ * Note that the domain with the smallest value may depend on the parameters
+ * and/or outer loop dimension. Since the result of this function is only
+ * used as heuristic, we only make a reasonable attempt at finding the best
+ * domain, one that should work in case a single domain provides the smallest
+ * value for the current dimension over all values of the parameters
+ * and outer dimensions.
+ *
+ * In particular, we compute the smallest value of the first domain
+ * and replace it by that of any later domain if that later domain
+ * has a smallest value that is smaller for at least some value
+ * of the parameters and outer dimensions.
+ */
+static int first_offset(struct isl_set_map_pair *domain, int *order, int n,
+ __isl_keep isl_ast_build *build)
+{
+ int i;
+ isl_map *min_first;
+ int first = 0;
+
+ min_first = isl_ast_build_map_to_iterator(build,
+ isl_set_copy(domain[order[0]].set));
+ min_first = isl_map_lexmin(min_first);
+
+ for (i = 1; i < n; ++i) {
+ isl_map *min, *test;
+ int empty;
+
+ min = isl_ast_build_map_to_iterator(build,
+ isl_set_copy(domain[order[i]].set));
+ min = isl_map_lexmin(min);
+ test = isl_map_copy(min);
+ test = isl_map_apply_domain(isl_map_copy(min_first), test);
+ test = isl_map_order_lt(test, isl_dim_in, 0, isl_dim_out, 0);
+ empty = isl_map_is_empty(test);
+ isl_map_free(test);
+ if (empty >= 0 && !empty) {
+ isl_map_free(min_first);
+ first = i;
+ min_first = min;
+ } else
+ isl_map_free(min);
+
+ if (empty < 0)
+ break;
+ }
+
+ isl_map_free(min_first);
+
+ return i < n ? -1 : first;
+}
+
+/* Construct a shifted inverse schedule based on the original inverse schedule,
+ * the stride and the offset.
+ *
+ * The original inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * "stride" and "offset" are such that the difference
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ * stride * integer + offset[i]
+ *
+ * Moreover, 0 <= offset[i] < stride.
+ *
+ * For each domain, we create a map
+ *
+ * { [..., j, ...] -> [..., j - offset[i], offset[i], ....] }
+ *
+ * where j refers to the current dimension and the other dimensions are
+ * unchanged, and apply this map to the original schedule domain.
+ *
+ * For example, for the original schedule
+ *
+ * { A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * and assuming the offset is 0 for the A domain and 1 for the B domain,
+ * we apply the mapping
+ *
+ * { [j] -> [j, 0] }
+ *
+ * to the schedule of the "A" domain and the mapping
+ *
+ * { [j - 1] -> [j, 1] }
+ *
+ * to the schedule of the "B" domain.
+ *
+ *
+ * Note that after the transformation, the differences between pairs
+ * of values of the current dimension over all domains are multiples
+ * of stride and that we have therefore exposed the stride.
+ *
+ *
+ * To see that the mapping preserves the lexicographic order,
+ * first note that each of the individual maps above preserves the order.
+ * If the value of the current iterator is j1 in one domain and j2 in another,
+ * then if j1 = j2, we know that the same map is applied to both domains
+ * and the order is preserved.
+ * Otherwise, let us assume, without loss of generality, that j1 < j2.
+ * If c1 >= c2 (with c1 and c2 the corresponding offsets), then
+ *
+ * j1 - c1 < j2 - c2
+ *
+ * and the order is preserved.
+ * If c1 < c2, then we know
+ *
+ * 0 <= c2 - c1 < s
+ *
+ * We also have
+ *
+ * j2 - j1 = n * s + r
+ *
+ * with n >= 0 and 0 <= r < s.
+ * In other words, r = c2 - c1.
+ * If n > 0, then
+ *
+ * j1 - c1 < j2 - c2
+ *
+ * If n = 0, then
+ *
+ * j1 - c1 = j2 - c2
+ *
+ * and so
+ *
+ * (j1 - c1, c1) << (j2 - c2, c2)
+ *
+ * with "<<" the lexicographic order, proving that the order is preserved
+ * in all cases.
+ */
+static __isl_give isl_union_map *contruct_shifted_executed(
+ struct isl_set_map_pair *domain, int *order, int n,
+ __isl_keep isl_val *stride, __isl_keep isl_multi_val *offset,
+ __isl_take isl_ast_build *build)
+{
+ int i;
+ isl_union_map *executed;
+ isl_space *space;
+ isl_map *map;
+ int depth;
+ isl_constraint *c;
+
+ depth = isl_ast_build_get_depth(build);
+ space = isl_ast_build_get_space(build, 1);
+ executed = isl_union_map_empty(isl_space_copy(space));
+ space = isl_space_map_from_set(space);
+ map = isl_map_identity(isl_space_copy(space));
+ map = isl_map_eliminate(map, isl_dim_out, depth, 1);
+ map = isl_map_insert_dims(map, isl_dim_out, depth + 1, 1);
+ space = isl_space_insert_dims(space, isl_dim_out, depth + 1, 1);
+
+ c = isl_equality_alloc(isl_local_space_from_space(space));
+ c = isl_constraint_set_coefficient_si(c, isl_dim_in, depth, 1);
+ c = isl_constraint_set_coefficient_si(c, isl_dim_out, depth, -1);
+
+ for (i = 0; i < n; ++i) {
+ isl_map *map_i;
+ isl_val *v;
+
+ v = isl_multi_val_get_val(offset, i);
+ if (!v)
+ break;
+ map_i = isl_map_copy(map);
+ map_i = isl_map_fix_val(map_i, isl_dim_out, depth + 1,
+ isl_val_copy(v));
+ v = isl_val_neg(v);
+ c = isl_constraint_set_constant_val(c, v);
+ map_i = isl_map_add_constraint(map_i, isl_constraint_copy(c));
+
+ map_i = isl_map_apply_domain(isl_map_copy(domain[order[i]].map),
+ map_i);
+ executed = isl_union_map_add_map(executed, map_i);
+ }
+
+ isl_constraint_free(c);
+ isl_map_free(map);
+
+ if (i < n)
+ executed = isl_union_map_free(executed);
+
+ return executed;
+}
+
+/* Generate code for a single component, after exposing the stride,
+ * given that the schedule domain is "shifted strided".
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * The schedule domain being "shifted strided" means that the differences
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ * stride * integer + offset[i]
+ *
+ * We first look for the domain with the "smallest" value for the current
+ * dimension and adjust the offsets such that the offset of the "smallest"
+ * domain is equal to zero. The other offsets are reduced modulo stride.
+ *
+ * Based on this information, we construct a new inverse schedule in
+ * contruct_shifted_executed that exposes the stride.
+ * Since this involves the introduction of a new schedule dimension,
+ * the build needs to be changed accodingly.
+ * After computing the AST, the newly introduced dimension needs
+ * to be removed again from the list of grafts. We do this by plugging
+ * in a mapping that represents the new schedule domain in terms of the
+ * old schedule domain.
+ */
+static __isl_give isl_ast_graft_list *generate_shift_component(
+ struct isl_set_map_pair *domain, int *order, int n,
+ __isl_keep isl_val *stride, __isl_keep isl_multi_val *offset,
+ __isl_take isl_ast_build *build)
+{
+ isl_ast_graft_list *list;
+ int first;
+ int depth;
+ isl_ctx *ctx;
+ isl_val *val;
+ isl_multi_val *mv;
+ isl_space *space;
+ isl_multi_aff *ma, *zero;
+ isl_union_map *executed;
+
+ ctx = isl_ast_build_get_ctx(build);
+ depth = isl_ast_build_get_depth(build);
+
+ first = first_offset(domain, order, n, build);
+ if (first < 0)
+ goto error;
+
+ mv = isl_multi_val_copy(offset);
+ val = isl_multi_val_get_val(offset, first);
+ val = isl_val_neg(val);
+ mv = isl_multi_val_add_val(mv, val);
+ mv = isl_multi_val_mod_val(mv, isl_val_copy(stride));
+
+ executed = contruct_shifted_executed(domain, order, n, stride, mv,
+ build);
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_map_from_set(space);
+ ma = isl_multi_aff_identity(isl_space_copy(space));
+ space = isl_space_from_domain(isl_space_domain(space));
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ zero = isl_multi_aff_zero(space);
+ ma = isl_multi_aff_range_splice(ma, depth + 1, zero);
+ build = isl_ast_build_insert_dim(build, depth + 1);
+ list = generate_shifted_component(executed, build);
+
+ list = isl_ast_graft_list_preimage_multi_aff(list, ma);
+
+ isl_multi_val_free(mv);
+
+ return list;
+error:
+ isl_ast_build_free(build);
+ return NULL;
+}
+
+/* Generate code for a single component.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * This function may modify the "set" fields of "domain".
+ *
+ * Before proceeding with the actual code generation for the component,
+ * we first check if there are any "shifted" strides, meaning that
+ * the schedule domains of the individual domains are all strided,
+ * but that they have different offsets, resulting in the union
+ * of schedule domains not being strided anymore.
+ *
+ * The simplest example is the schedule
+ *
+ * { A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * Both schedule domains are strided, but their union is not.
+ * This function detects such cases and then rewrites the schedule to
+ *
+ * { A[i] -> [2i, 0]: 0 <= i < 10; B[i] -> [2i, 1] : 0 <= i < 10 }
+ *
+ * In the new schedule, the schedule domains have the same offset (modulo
+ * the stride), ensuring that the union of schedule domains is also strided.
+ *
+ *
+ * If there is only a single domain in the component, then there is
+ * nothing to do. Similarly, if the current schedule dimension has
+ * a fixed value for almost all domains then there is nothing to be done.
+ * In particular, we need at least two domains where the current schedule
+ * dimension does not have a fixed value.
+ * Finally, if any of the options refer to the current schedule dimension,
+ * then we bail out as well. It would be possible to reformulate the options
+ * in terms of the new schedule domain, but that would introduce constraints
+ * that separate the domains in the options and that is something we would
+ * like to avoid.
+ *
+ *
+ * To see if there is any shifted stride, we look at the differences
+ * between the values of the current dimension in pairs of domains
+ * for equal values of outer dimensions. These differences should be
+ * of the form
+ *
+ * m x + r
+ *
+ * with "m" the stride and "r" a constant. Note that we cannot perform
+ * this analysis on individual domains as the lower bound in each domain
+ * may depend on parameters or outer dimensions and so the current dimension
+ * itself may not have a fixed remainder on division by the stride.
+ *
+ * In particular, we compare the first domain that does not have an
+ * obviously fixed value for the current dimension to itself and all
+ * other domains and collect the offsets and the gcd of the strides.
+ * If the gcd becomes one, then we failed to find shifted strides.
+ * If the gcd is zero, then the differences were all fixed, meaning
+ * that some domains had non-obviously fixed values for the current dimension.
+ * If all the offsets are the same (for those domains that do not have
+ * an obviously fixed value for the current dimension), then we do not
+ * apply the transformation.
+ * If none of the domains were skipped, then there is nothing to do.
+ * If some of them were skipped, then if we apply separation, the schedule
+ * domain should get split in pieces with a (non-shifted) stride.
+ *
+ * Otherwise, we apply a shift to expose the stride in
+ * generate_shift_component.
+ */
+static __isl_give isl_ast_graft_list *generate_component(
+ struct isl_set_map_pair *domain, int *order, int n,
+ __isl_take isl_ast_build *build)
+{
+ int i, d;
+ int depth;
+ isl_ctx *ctx;
+ isl_map *map;
+ isl_set *deltas;
+ isl_val *gcd = NULL;
+ isl_multi_val *mv;
+ int fixed, skip;
+ int base;
+ isl_ast_graft_list *list;
+ int res = 0;
+
+ depth = isl_ast_build_get_depth(build);
+
+ skip = n == 1;
+ if (skip >= 0 && !skip)
+ skip = at_most_one_non_fixed(domain, order, n, depth);
+ if (skip >= 0 && !skip)
+ skip = isl_ast_build_options_involve_depth(build);
+ if (skip < 0)
+ goto error;
+ if (skip)
+ return generate_shifted_component_from_list(domain,
+ order, n, build);
+
+ base = eliminate_non_fixed(domain, order, n, depth, build);
+ if (base < 0)
+ goto error;
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ mv = isl_multi_val_zero(isl_space_set_alloc(ctx, 0, n));
+
+ fixed = 1;
+ for (i = 0; i < n; ++i) {
+ isl_val *r, *m;
+
+ map = isl_map_from_domain_and_range(
+ isl_set_copy(domain[order[base]].set),
+ isl_set_copy(domain[order[i]].set));
+ for (d = 0; d < depth; ++d)
+ map = isl_map_equate(map, isl_dim_in, d,
+ isl_dim_out, d);
+ deltas = isl_map_deltas(map);
+ res = isl_set_dim_residue_class_val(deltas, depth, &m, &r);
+ isl_set_free(deltas);
+ if (res < 0)
+ break;
+
+ if (i == 0)
+ gcd = m;
+ else
+ gcd = isl_val_gcd(gcd, m);
+ if (isl_val_is_one(gcd)) {
+ isl_val_free(r);
+ break;
+ }
+ mv = isl_multi_val_set_val(mv, i, r);
+
+ res = dim_is_fixed(domain[order[i]].set, depth);
+ if (res < 0)
+ break;
+ if (res)
+ continue;
+
+ if (fixed && i > base) {
+ isl_val *a, *b;
+ a = isl_multi_val_get_val(mv, i);
+ b = isl_multi_val_get_val(mv, base);
+ if (isl_val_ne(a, b))
+ fixed = 0;
+ isl_val_free(a);
+ isl_val_free(b);
+ }
+ }
+
+ if (res < 0 || !gcd) {
+ isl_ast_build_free(build);
+ list = NULL;
+ } else if (i < n || fixed || isl_val_is_zero(gcd)) {
+ list = generate_shifted_component_from_list(domain,
+ order, n, build);
+ } else {
+ list = generate_shift_component(domain, order, n, gcd, mv,
+ build);
+ }
+
+ isl_val_free(gcd);
+ isl_multi_val_free(mv);
+
+ return list;
+error:
+ isl_ast_build_free(build);
+ return NULL;
+}
+
+/* Store both "map" itself and its domain in the
+ * structure pointed to by *next and advance to the next array element.
+ */
+static int extract_domain(__isl_take isl_map *map, void *user)
+{
+ struct isl_set_map_pair **next = user;
+
+ (*next)->map = isl_map_copy(map);
+ (*next)->set = isl_map_domain(map);
+ (*next)++;
+
+ return 0;
+}
+
+/* Internal data for any_scheduled_after.
+ *
+ * "depth" is the number of loops that have already been generated
+ * "group_coscheduled" is a local copy of options->ast_build_group_coscheduled
+ * "domain" is an array of set-map pairs corresponding to the different
+ * iteration domains. The set is the schedule domain, i.e., the domain
+ * of the inverse schedule, while the map is the inverse schedule itself.
+ */
+struct isl_any_scheduled_after_data {
+ int depth;
+ int group_coscheduled;
+ struct isl_set_map_pair *domain;
+};
+
+/* Is any element of domain "i" scheduled after any element of domain "j"
+ * (for a common iteration of the first data->depth loops)?
+ *
+ * data->domain[i].set contains the domain of the inverse schedule
+ * for domain "i", i.e., elements in the schedule domain.
+ *
+ * If data->group_coscheduled is set, then we also return 1 if there
+ * is any pair of elements in the two domains that are scheduled together.
+ */
+static int any_scheduled_after(int i, int j, void *user)
+{
+ struct isl_any_scheduled_after_data *data = user;
+ int dim = isl_set_dim(data->domain[i].set, isl_dim_set);
+ int pos;
+
+ for (pos = data->depth; pos < dim; ++pos) {
+ int follows;
+
+ follows = isl_set_follows_at(data->domain[i].set,
+ data->domain[j].set, pos);
+
+ if (follows < -1)
+ return -1;
+ if (follows > 0)
+ return 1;
+ if (follows < 0)
+ return 0;
+ }
+
+ return data->group_coscheduled;
+}
+
+/* Look for independent components at the current depth and generate code
+ * for each component separately. The resulting lists of grafts are
+ * merged in an attempt to combine grafts with identical guards.
+ *
+ * Code for two domains can be generated separately if all the elements
+ * of one domain are scheduled before (or together with) all the elements
+ * of the other domain. We therefore consider the graph with as nodes
+ * the domains and an edge between two nodes if any element of the first
+ * node is scheduled after any element of the second node.
+ * If the ast_build_group_coscheduled is set, then we also add an edge if
+ * there is any pair of elements in the two domains that are scheduled
+ * together.
+ * Code is then generated (by generate_component)
+ * for each of the strongly connected components in this graph
+ * in their topological order.
+ *
+ * Since the test is performed on the domain of the inverse schedules of
+ * the different domains, we precompute these domains and store
+ * them in data.domain.
+ */
+static __isl_give isl_ast_graft_list *generate_components(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+ int i;
+ isl_ctx *ctx = isl_ast_build_get_ctx(build);
+ int n = isl_union_map_n_map(executed);
+ struct isl_any_scheduled_after_data data;
+ struct isl_set_map_pair *next;
+ struct isl_tarjan_graph *g = NULL;
+ isl_ast_graft_list *list = NULL;
+ int n_domain = 0;
+
+ data.domain = isl_calloc_array(ctx, struct isl_set_map_pair, n);
+ if (!data.domain)
+ goto error;
+ n_domain = n;
+
+ next = data.domain;
+ if (isl_union_map_foreach_map(executed, &extract_domain, &next) < 0)
+ goto error;
+
+ if (!build)
+ goto error;
+ data.depth = isl_ast_build_get_depth(build);
+ data.group_coscheduled = isl_options_get_ast_build_group_coscheduled(ctx);
+ g = isl_tarjan_graph_init(ctx, n, &any_scheduled_after, &data);
+ if (!g)
+ goto error;
+
+ list = isl_ast_graft_list_alloc(ctx, 0);
+
+ i = 0;
+ while (list && n) {
+ isl_ast_graft_list *list_c;
+ int first = i;
+
+ if (g->order[i] == -1)
+ isl_die(ctx, isl_error_internal, "cannot happen",
+ goto error);
+ ++i; --n;
+ while (g->order[i] != -1) {
+ ++i; --n;
+ }
+
+ list_c = generate_component(data.domain,
+ g->order + first, i - first,
+ isl_ast_build_copy(build));
+ list = isl_ast_graft_list_merge(list, list_c, build);
+
+ ++i;
+ }
+
+ if (0)
+error: list = isl_ast_graft_list_free(list);
+ isl_tarjan_graph_free(g);
+ for (i = 0; i < n_domain; ++i) {
+ isl_map_free(data.domain[i].map);
+ isl_set_free(data.domain[i].set);
+ }
+ free(data.domain);
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+
+ return list;
+}
+
+/* Generate code for the next level (and all inner levels).
+ *
+ * If "executed" is empty, i.e., no code needs to be generated,
+ * then we return an empty list.
+ *
+ * If we have already generated code for all loop levels, then we pass
+ * control to generate_inner_level.
+ *
+ * If "executed" lives in a single space, i.e., if code needs to be
+ * generated for a single domain, then there can only be a single
+ * component and we go directly to generate_shifted_component.
+ * Otherwise, we call generate_components to detect the components
+ * and to call generate_component on each of them separately.
+ */
+static __isl_give isl_ast_graft_list *generate_next_level(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+ int depth;
+
+ if (!build || !executed)
+ goto error;
+
+ if (isl_union_map_is_empty(executed)) {
+ isl_ctx *ctx = isl_ast_build_get_ctx(build);
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+ return isl_ast_graft_list_alloc(ctx, 0);
+ }
+
+ depth = isl_ast_build_get_depth(build);
+ if (depth >= isl_ast_build_dim(build, isl_dim_set))
+ return generate_inner_level(executed, build);
+
+ if (isl_union_map_n_map(executed) == 1)
+ return generate_shifted_component(executed, build);
+
+ return generate_components(executed, build);
+error:
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+ return NULL;
+}
+
+/* Internal data structure used by isl_ast_build_ast_from_schedule.
+ * internal, executed and build are the inputs to generate_code.
+ * list collects the output.
+ */
+struct isl_generate_code_data {
+ int internal;
+ isl_union_map *executed;
+ isl_ast_build *build;
+
+ isl_ast_graft_list *list;
+};
+
+/* Given an inverse schedule in terms of the external build schedule, i.e.,
+ *
+ * [E -> S] -> D
+ *
+ * with E the external build schedule and S the additional schedule "space",
+ * reformulate the inverse schedule in terms of the internal schedule domain,
+ * i.e., return
+ *
+ * [I -> S] -> D
+ *
+ * We first obtain a mapping
+ *
+ * I -> E
+ *
+ * take the inverse and the product with S -> S, resulting in
+ *
+ * [I -> S] -> [E -> S]
+ *
+ * Applying the map to the input produces the desired result.
+ */
+static __isl_give isl_union_map *internal_executed(
+ __isl_take isl_union_map *executed, __isl_keep isl_space *space,
+ __isl_keep isl_ast_build *build)
+{
+ isl_map *id, *proj;
+
+ proj = isl_ast_build_get_schedule_map(build);
+ proj = isl_map_reverse(proj);
+ space = isl_space_map_from_set(isl_space_copy(space));
+ id = isl_map_identity(space);
+ proj = isl_map_product(proj, id);
+ executed = isl_union_map_apply_domain(executed,
+ isl_union_map_from_map(proj));
+ return executed;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding domain element(s)
+ * for those domain elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ * "space" is the space of the additional part of the schedule.
+ * It is equal to the space of "set" if build->domain is parametric.
+ * Otherwise, it is equal to the range of the wrapped space of "set".
+ *
+ * If the build space is not parametric and if isl_ast_build_ast_from_schedule
+ * was called from an outside user (data->internal not set), then
+ * the (inverse) schedule refers to the external build domain and needs to
+ * be transformed to refer to the internal build domain.
+ *
+ * If the build space is parametric, then we add some of the parameter
+ * constraints to the executed relation. Adding these constraints
+ * allows for an earlier detection of conflicts in some cases.
+ * However, we do not want to divide the executed relation into
+ * more disjuncts than necessary. We therefore approximate
+ * the constraints on the parameters by a single disjunct set.
+ *
+ * The build is extended to include the additional part of the schedule.
+ * If the original build space was not parametric, then the options
+ * in data->build refer only to the additional part of the schedule
+ * and they need to be adjusted to refer to the complete AST build
+ * domain.
+ *
+ * After having adjusted inverse schedule and build, we start generating
+ * code with the outer loop of the current code generation
+ * in generate_next_level.
+ *
+ * If the original build space was not parametric, we undo the embedding
+ * on the resulting isl_ast_node_list so that it can be used within
+ * the outer AST build.
+ */
+static int generate_code_in_space(struct isl_generate_code_data *data,
+ __isl_take isl_set *set, __isl_take isl_space *space)
+{
+ isl_union_map *executed;
+ isl_ast_build *build;
+ isl_ast_graft_list *list;
+ int embed;
+
+ executed = isl_union_map_copy(data->executed);
+ executed = isl_union_map_intersect_domain(executed,
+ isl_union_set_from_set(set));
+
+ embed = !isl_set_is_params(data->build->domain);
+ if (embed && !data->internal)
+ executed = internal_executed(executed, space, data->build);
+ if (!embed) {
+ isl_set *domain;
+ domain = isl_ast_build_get_domain(data->build);
+ domain = isl_set_from_basic_set(isl_set_simple_hull(domain));
+ executed = isl_union_map_intersect_params(executed, domain);
+ }
+
+ build = isl_ast_build_copy(data->build);
+ build = isl_ast_build_product(build, space);
+
+ list = generate_next_level(executed, build);
+
+ list = isl_ast_graft_list_unembed(list, embed);
+
+ data->list = isl_ast_graft_list_concat(data->list, list);
+
+ return 0;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding domain element(s)
+ * for those domain elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ *
+ * If the build space S is not parametric, then the space of "set"
+ * need to be a wrapped relation with S as domain. That is, it needs
+ * to be of the form
+ *
+ * [S -> T]
+ *
+ * Check this property and pass control to generate_code_in_space
+ * passing along T.
+ * If the build space is not parametric, then T is the space of "set".
+ */
+static int generate_code_set(__isl_take isl_set *set, void *user)
+{
+ struct isl_generate_code_data *data = user;
+ isl_space *space, *build_space;
+ int is_domain;
+
+ space = isl_set_get_space(set);
+
+ if (isl_set_is_params(data->build->domain))
+ return generate_code_in_space(data, set, space);
+
+ build_space = isl_ast_build_get_space(data->build, data->internal);
+ space = isl_space_unwrap(space);
+ is_domain = isl_space_is_domain(build_space, space);
+ isl_space_free(build_space);
+ space = isl_space_range(space);
+
+ if (is_domain < 0)
+ goto error;
+ if (!is_domain)
+ isl_die(isl_set_get_ctx(set), isl_error_invalid,
+ "invalid nested schedule space", goto error);
+
+ return generate_code_in_space(data, set, space);
+error:
+ isl_set_free(set);
+ isl_space_free(space);
+ return -1;
+}
+
+/* Generate an AST that visits the elements in the range of "executed"
+ * in the relative order specified by the corresponding domain element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the domain space(s) of "executed"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the domain of "executed" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * If "internal" is set, then the domain "S" above refers to the internal
+ * schedule domain representation. Otherwise, it refers to the external
+ * representation, as returned by isl_ast_build_get_schedule_space.
+ *
+ * We essentially run over all the spaces in the domain of "executed"
+ * and call generate_code_set on each of them.
+ */
+static __isl_give isl_ast_graft_list *generate_code(
+ __isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+ int internal)
+{
+ isl_ctx *ctx;
+ struct isl_generate_code_data data = { 0 };
+ isl_space *space;
+ isl_union_set *schedule_domain;
+ isl_union_map *universe;
+
+ if (!build)
+ goto error;
+ space = isl_ast_build_get_space(build, 1);
+ space = isl_space_align_params(space,
+ isl_union_map_get_space(executed));
+ space = isl_space_align_params(space,
+ isl_union_map_get_space(build->options));
+ build = isl_ast_build_align_params(build, isl_space_copy(space));
+ executed = isl_union_map_align_params(executed, space);
+ if (!executed || !build)
+ goto error;
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ data.internal = internal;
+ data.executed = executed;
+ data.build = build;
+ data.list = isl_ast_graft_list_alloc(ctx, 0);
+
+ universe = isl_union_map_universe(isl_union_map_copy(executed));
+ schedule_domain = isl_union_map_domain(universe);
+ if (isl_union_set_foreach_set(schedule_domain, &generate_code_set,
+ &data) < 0)
+ data.list = isl_ast_graft_list_free(data.list);
+
+ isl_union_set_free(schedule_domain);
+ isl_union_map_free(executed);
+
+ isl_ast_build_free(build);
+ return data.list;
+error:
+ isl_union_map_free(executed);
+ isl_ast_build_free(build);
+ return NULL;
+}
+
+/* Generate an AST that visits the elements in the domain of "schedule"
+ * in the relative order specified by the corresponding image element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the range space(s) of "schedule"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the range of "schedule" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * We first initialize the local copies of the relevant options.
+ * We do this here rather than when the isl_ast_build is created
+ * because the options may have changed between the construction
+ * of the isl_ast_build and the call to isl_generate_code.
+ *
+ * The main computation is performed on an inverse schedule (with
+ * the schedule domain in the domain and the elements to be executed
+ * in the range) called "executed".
+ */
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+ __isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule)
+{
+ isl_ast_graft_list *list;
+ isl_ast_node *node;
+ isl_union_map *executed;
+
+ build = isl_ast_build_copy(build);
+ build = isl_ast_build_set_single_valued(build, 0);
+ schedule = isl_union_map_coalesce(schedule);
+ executed = isl_union_map_reverse(schedule);
+ list = generate_code(executed, isl_ast_build_copy(build), 0);
+ node = isl_ast_node_from_graft_list(list, build);
+ isl_ast_build_free(build);
+
+ return node;
+}
diff --git a/polly/lib/External/isl/isl_ast_graft.c b/polly/lib/External/isl/isl_ast_graft.c
new file mode 100644
index 00000000000..611ef5dcf6e
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_graft.c
@@ -0,0 +1,1242 @@
+/*
+ * Copyright 2012 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <isl_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+ __isl_keep isl_ast_graft *graft);
+
+#undef BASE
+#define BASE ast_graft
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_graft
+#include <print_templ.c>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft)
+{
+ if (!graft)
+ return NULL;
+ return isl_basic_set_get_ctx(graft->enforced);
+}
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+ __isl_keep isl_ast_graft *graft)
+{
+ return graft ? isl_ast_node_copy(graft->node) : NULL;
+}
+
+/* Create a graft for "node" with no guards and no enforced conditions.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc(
+ __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_ast_graft *graft;
+
+ if (!node)
+ return NULL;
+
+ ctx = isl_ast_node_get_ctx(node);
+ graft = isl_calloc_type(ctx, isl_ast_graft);
+ if (!graft)
+ goto error;
+
+ space = isl_ast_build_get_space(build, 1);
+
+ graft->ref = 1;
+ graft->node = node;
+ graft->guard = isl_set_universe(isl_space_copy(space));
+ graft->enforced = isl_basic_set_universe(space);
+
+ if (!graft->guard || !graft->enforced)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+error:
+ isl_ast_node_free(node);
+ return NULL;
+}
+
+/* Create a graft with no guards and no enforced conditions
+ * encapsulating a call to the domain element specified by "executed".
+ * "executed" is assumed to be single-valued.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+ __isl_take isl_map *executed, __isl_keep isl_ast_build *build)
+{
+ isl_ast_node *node;
+
+ node = isl_ast_build_call_from_executed(build, executed);
+
+ return isl_ast_graft_alloc(node, build);
+}
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+ __isl_keep isl_ast_graft *graft)
+{
+ if (!graft)
+ return NULL;
+
+ graft->ref++;
+ return graft;
+}
+
+/* Do all the grafts in "list" have the same guard and is this guard
+ * independent of the current depth?
+ */
+static int equal_independent_guards(__isl_keep isl_ast_graft_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ int depth;
+ isl_ast_graft *graft_0;
+ int equal = 1;
+ int skip;
+
+ graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+ if (!graft_0)
+ return -1;
+
+ depth = isl_ast_build_get_depth(build);
+ skip = isl_set_involves_dims(graft_0->guard, isl_dim_set, depth, 1);
+ if (skip < 0 || skip) {
+ isl_ast_graft_free(graft_0);
+ return skip < 0 ? -1 : 0;
+ }
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ for (i = 1; i < n; ++i) {
+ isl_ast_graft *graft;
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ if (!graft)
+ equal = -1;
+ else
+ equal = isl_set_is_equal(graft_0->guard, graft->guard);
+ isl_ast_graft_free(graft);
+ if (equal < 0 || !equal)
+ break;
+ }
+
+ isl_ast_graft_free(graft_0);
+
+ return equal;
+}
+
+/* Hoist "guard" out of the current level (given by "build").
+ *
+ * In particular, eliminate the dimension corresponding to the current depth.
+ */
+static __isl_give isl_set *hoist_guard(__isl_take isl_set *guard,
+ __isl_keep isl_ast_build *build)
+{
+ int depth;
+
+ depth = isl_ast_build_get_depth(build);
+ if (depth < isl_set_dim(guard, isl_dim_set)) {
+ guard = isl_set_remove_divs_involving_dims(guard,
+ isl_dim_set, depth, 1);
+ guard = isl_set_eliminate(guard, isl_dim_set, depth, 1);
+ guard = isl_set_compute_divs(guard);
+ }
+
+ return guard;
+}
+
+/* Extract a common guard from the grafts in "list" that can be hoisted
+ * out of the current level. If no such guard can be found, then return
+ * a universal set.
+ *
+ * If all the grafts in the list have the same guard and if this guard
+ * is independent of the current level, then it can be hoisted out.
+ * If there is only one graft in the list and if its guard
+ * depends on the current level, then we eliminate this level and
+ * return the result.
+ *
+ * Otherwise, we return the unshifted simple hull of the guards.
+ * In order to be able to hoist as many constraints as possible,
+ * but at the same time avoid hoisting constraints that did not
+ * appear in the guards in the first place, we intersect the guards
+ * with all the information that is available (i.e., the domain
+ * from the build and the enforced constraints of the graft) and
+ * compute the unshifted hull of the result using only constraints
+ * from the original guards.
+ * In particular, intersecting the guards with other known information
+ * allows us to hoist guards that are only explicit is some of
+ * the grafts and implicit in the others.
+ *
+ * The special case for equal guards is needed in case those guards
+ * are non-convex. Taking the simple hull would remove information
+ * and would not allow for these guards to be hoisted completely.
+ */
+__isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard(
+ __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ int equal;
+ isl_ctx *ctx;
+ isl_set *guard;
+ isl_set_list *set_list;
+ isl_basic_set *hull;
+
+ if (!list || !build)
+ return NULL;
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ if (n == 0)
+ return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+ equal = equal_independent_guards(list, build);
+ if (equal < 0)
+ return NULL;
+
+ if (equal || n == 1) {
+ isl_ast_graft *graft_0;
+
+ graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+ if (!graft_0)
+ return NULL;
+ guard = isl_set_copy(graft_0->guard);
+ if (!equal)
+ guard = hoist_guard(guard, build);
+ isl_ast_graft_free(graft_0);
+ return guard;
+ }
+
+ ctx = isl_ast_build_get_ctx(build);
+ set_list = isl_set_list_alloc(ctx, n);
+ guard = isl_set_empty(isl_ast_build_get_space(build, 1));
+ for (i = 0; i < n; ++i) {
+ isl_ast_graft *graft;
+ isl_basic_set *enforced;
+ isl_set *guard_i;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ enforced = isl_ast_graft_get_enforced(graft);
+ guard_i = isl_set_copy(graft->guard);
+ isl_ast_graft_free(graft);
+ set_list = isl_set_list_add(set_list, isl_set_copy(guard_i));
+ guard_i = isl_set_intersect(guard_i,
+ isl_set_from_basic_set(enforced));
+ guard_i = isl_set_intersect(guard_i,
+ isl_ast_build_get_domain(build));
+ guard = isl_set_union(guard, guard_i);
+ }
+ hull = isl_set_unshifted_simple_hull_from_set_list(guard, set_list);
+ guard = isl_set_from_basic_set(hull);
+ return hoist_guard(guard, build);
+}
+
+/* Internal data structure used inside insert_if.
+ *
+ * list is the list of guarded nodes created by each call to insert_if.
+ * node is the original node that is guarded by insert_if.
+ * build is the build in which the AST is constructed.
+ */
+struct isl_insert_if_data {
+ isl_ast_node_list *list;
+ isl_ast_node *node;
+ isl_ast_build *build;
+};
+
+static int insert_if(__isl_take isl_basic_set *bset, void *user);
+
+/* Insert an if node around "node" testing the condition encoded
+ * in guard "guard".
+ *
+ * If the user does not want any disjunctions in the if conditions
+ * and if "guard" does involve a disjunction, then we make the different
+ * disjuncts disjoint and insert an if node corresponding to each disjunct
+ * around a copy of "node". The result is then a block node containing
+ * this sequence of guarded copies of "node".
+ */
+static __isl_give isl_ast_node *ast_node_insert_if(
+ __isl_take isl_ast_node *node, __isl_take isl_set *guard,
+ __isl_keep isl_ast_build *build)
+{
+ struct isl_insert_if_data data;
+ isl_ctx *ctx;
+
+ ctx = isl_ast_build_get_ctx(build);
+ if (isl_options_get_ast_build_allow_or(ctx) ||
+ isl_set_n_basic_set(guard) <= 1) {
+ isl_ast_node *if_node;
+ isl_ast_expr *expr;
+
+ expr = isl_ast_build_expr_from_set(build, guard);
+
+ if_node = isl_ast_node_alloc_if(expr);
+ return isl_ast_node_if_set_then(if_node, node);
+ }
+
+ guard = isl_set_make_disjoint(guard);
+
+ data.list = isl_ast_node_list_alloc(ctx, 0);
+ data.node = node;
+ data.build = build;
+ if (isl_set_foreach_basic_set(guard, &insert_if, &data) < 0)
+ data.list = isl_ast_node_list_free(data.list);
+
+ isl_set_free(guard);
+ isl_ast_node_free(data.node);
+ return isl_ast_node_alloc_block(data.list);
+}
+
+/* Insert an if node around a copy of "data->node" testing the condition
+ * encoded in guard "bset" and add the result to data->list.
+ */
+static int insert_if(__isl_take isl_basic_set *bset, void *user)
+{
+ struct isl_insert_if_data *data = user;
+ isl_ast_node *node;
+ isl_set *set;
+
+ set = isl_set_from_basic_set(bset);
+ node = isl_ast_node_copy(data->node);
+ node = ast_node_insert_if(node, set, data->build);
+ data->list = isl_ast_node_list_add(data->list, node);
+
+ return 0;
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in guard "guard", assuming guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_if_node(
+ __isl_take isl_ast_graft *graft, __isl_take isl_set *guard,
+ __isl_keep isl_ast_build *build)
+{
+ int univ;
+
+ if (!graft)
+ goto error;
+
+ univ = isl_set_plain_is_universe(guard);
+ if (univ < 0)
+ goto error;
+ if (univ) {
+ isl_set_free(guard);
+ return graft;
+ }
+
+ build = isl_ast_build_copy(build);
+ graft->node = ast_node_insert_if(graft->node, guard, build);
+ isl_ast_build_free(build);
+
+ if (!graft->node)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+error:
+ isl_set_free(guard);
+ return isl_ast_graft_free(graft);
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_pending_guard_node(
+ __isl_take isl_ast_graft *graft, __isl_keep isl_ast_build *build)
+{
+ if (!graft)
+ return NULL;
+
+ return insert_if_node(graft, isl_set_copy(graft->guard), build);
+}
+
+/* Replace graft->enforced by "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_set_enforced(
+ __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+ if (!graft || !enforced)
+ goto error;
+
+ isl_basic_set_free(graft->enforced);
+ graft->enforced = enforced;
+
+ return graft;
+error:
+ isl_basic_set_free(enforced);
+ return isl_ast_graft_free(graft);
+}
+
+/* Update "enforced" such that it only involves constraints that are
+ * also enforced by "graft".
+ */
+static __isl_give isl_basic_set *update_enforced(
+ __isl_take isl_basic_set *enforced, __isl_keep isl_ast_graft *graft,
+ int depth)
+{
+ isl_basic_set *enforced_g;
+
+ enforced_g = isl_ast_graft_get_enforced(graft);
+ if (depth < isl_basic_set_dim(enforced_g, isl_dim_set))
+ enforced_g = isl_basic_set_eliminate(enforced_g,
+ isl_dim_set, depth, 1);
+ enforced_g = isl_basic_set_remove_unknown_divs(enforced_g);
+ enforced_g = isl_basic_set_align_params(enforced_g,
+ isl_basic_set_get_space(enforced));
+ enforced = isl_basic_set_align_params(enforced,
+ isl_basic_set_get_space(enforced_g));
+ enforced = isl_set_simple_hull(isl_basic_set_union(enforced,
+ enforced_g));
+
+ return enforced;
+}
+
+/* Extend the node at *body with node.
+ *
+ * If body points to the else branch, then *body may still be NULL.
+ * If so, we simply attach node to this else branch.
+ * Otherwise, we attach a list containing the statements already
+ * attached at *body followed by node.
+ */
+static void extend_body(__isl_keep isl_ast_node **body,
+ __isl_take isl_ast_node *node)
+{
+ isl_ast_node_list *list;
+
+ if (!*body) {
+ *body = node;
+ return;
+ }
+
+ if ((*body)->type == isl_ast_node_block) {
+ list = isl_ast_node_block_get_children(*body);
+ isl_ast_node_free(*body);
+ } else
+ list = isl_ast_node_list_from_ast_node(*body);
+ list = isl_ast_node_list_add(list, node);
+ *body = isl_ast_node_alloc_block(list);
+}
+
+/* Merge "graft" into the last graft of "list".
+ * body points to the then or else branch of an if node in that last graft.
+ *
+ * We attach graft->node to this branch and update the enforced
+ * set of the last graft of "list" to take into account the enforced
+ * set of "graft".
+ */
+static __isl_give isl_ast_graft_list *graft_extend_body(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_node **body, __isl_take isl_ast_graft *graft,
+ __isl_keep isl_ast_build *build)
+{
+ int n;
+ int depth;
+ isl_ast_graft *last;
+ isl_space *space;
+ isl_basic_set *enforced;
+
+ if (!list || !graft)
+ goto error;
+ extend_body(body, isl_ast_node_copy(graft->node));
+ if (!*body)
+ goto error;
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ last = isl_ast_graft_list_get_ast_graft(list, n - 1);
+
+ depth = isl_ast_build_get_depth(build);
+ space = isl_ast_build_get_space(build, 1);
+ enforced = isl_basic_set_empty(space);
+ enforced = update_enforced(enforced, last, depth);
+ enforced = update_enforced(enforced, graft, depth);
+ last = isl_ast_graft_set_enforced(last, enforced);
+
+ list = isl_ast_graft_list_set_ast_graft(list, n - 1, last);
+ isl_ast_graft_free(graft);
+ return list;
+error:
+ isl_ast_graft_free(graft);
+ return isl_ast_graft_list_free(list);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the then branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_then(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+ __isl_keep isl_ast_build *build)
+{
+ return graft_extend_body(list, &last_if->u.i.then, graft, build);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the else branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_else(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+ __isl_keep isl_ast_build *build)
+{
+ return graft_extend_body(list, &last_if->u.i.else_node, graft, build);
+}
+
+/* This data structure keeps track of an if node.
+ *
+ * "node" is the actual if-node
+ * "guard" is the original, non-simplified guard of the node
+ * "complement" is the complement of "guard" in the context of outer if nodes
+ */
+struct isl_if_node {
+ isl_ast_node *node;
+ isl_set *guard;
+ isl_set *complement;
+};
+
+/* Given a list of "n" if nodes, clear those starting at "first"
+ * and return "first" (i.e., the updated size of the array).
+ */
+static int clear_if_nodes(struct isl_if_node *if_node, int first, int n)
+{
+ int i;
+
+ for (i = first; i < n; ++i) {
+ isl_set_free(if_node[i].guard);
+ isl_set_free(if_node[i].complement);
+ }
+
+ return first;
+}
+
+/* For each graft in "list",
+ * insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ *
+ * We keep track of a list of generated if nodes that can be extended
+ * without changing the order of the elements in "list".
+ * If the guard of a graft is a subset of either the guard or its complement
+ * of one of those if nodes, then the node
+ * of the new graft is inserted into the then or else branch of the last graft
+ * and the current graft is discarded.
+ * The guard of the node is then simplified based on the conditions
+ * enforced at that then or else branch.
+ * Otherwise, the current graft is appended to the list.
+ *
+ * We only construct else branches if allowed by the user.
+ */
+static __isl_give isl_ast_graft_list *insert_pending_guard_nodes(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ int i, j, n, n_if;
+ int allow_else;
+ isl_ctx *ctx;
+ isl_ast_graft_list *res;
+ struct isl_if_node *if_node = NULL;
+
+ if (!build || !list)
+ return isl_ast_graft_list_free(list);
+
+ ctx = isl_ast_build_get_ctx(build);
+ n = isl_ast_graft_list_n_ast_graft(list);
+
+ allow_else = isl_options_get_ast_build_allow_else(ctx);
+
+ n_if = 0;
+ if (n > 1) {
+ if_node = isl_alloc_array(ctx, struct isl_if_node, n - 1);
+ if (!if_node)
+ return isl_ast_graft_list_free(list);
+ }
+
+ res = isl_ast_graft_list_alloc(ctx, n);
+
+ for (i = 0; i < n; ++i) {
+ isl_set *guard;
+ isl_ast_graft *graft;
+ int subset, found_then, found_else;
+ isl_ast_node *node;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ if (!graft)
+ break;
+ subset = 0;
+ found_then = found_else = -1;
+ if (n_if > 0) {
+ isl_set *test;
+ test = isl_set_copy(graft->guard);
+ test = isl_set_intersect(test,
+ isl_set_copy(build->domain));
+ for (j = n_if - 1; j >= 0; --j) {
+ subset = isl_set_is_subset(test,
+ if_node[j].guard);
+ if (subset < 0 || subset) {
+ found_then = j;
+ break;
+ }
+ if (!allow_else)
+ continue;
+ subset = isl_set_is_subset(test,
+ if_node[j].complement);
+ if (subset < 0 || subset) {
+ found_else = j;
+ break;
+ }
+ }
+ n_if = clear_if_nodes(if_node, j + 1, n_if);
+ isl_set_free(test);
+ }
+ if (subset < 0) {
+ graft = isl_ast_graft_free(graft);
+ break;
+ }
+
+ guard = isl_set_copy(graft->guard);
+ if (found_then >= 0)
+ graft->guard = isl_set_gist(graft->guard,
+ isl_set_copy(if_node[found_then].guard));
+ else if (found_else >= 0)
+ graft->guard = isl_set_gist(graft->guard,
+ isl_set_copy(if_node[found_else].complement));
+
+ node = graft->node;
+ if (!graft->guard)
+ graft = isl_ast_graft_free(graft);
+ graft = insert_pending_guard_node(graft, build);
+ if (graft && graft->node != node && i != n - 1) {
+ isl_set *set;
+ if_node[n_if].node = graft->node;
+ if_node[n_if].guard = guard;
+ if (found_then >= 0)
+ set = if_node[found_then].guard;
+ else if (found_else >= 0)
+ set = if_node[found_else].complement;
+ else
+ set = build->domain;
+ set = isl_set_copy(set);
+ set = isl_set_subtract(set, isl_set_copy(guard));
+ if_node[n_if].complement = set;
+ n_if++;
+ } else
+ isl_set_free(guard);
+ if (!graft)
+ break;
+
+ if (found_then >= 0)
+ res = extend_then(res, if_node[found_then].node,
+ graft, build);
+ else if (found_else >= 0)
+ res = extend_else(res, if_node[found_else].node,
+ graft, build);
+ else
+ res = isl_ast_graft_list_add(res, graft);
+ }
+ if (i < n)
+ res = isl_ast_graft_list_free(res);
+
+ isl_ast_graft_list_free(list);
+ clear_if_nodes(if_node, 0, n_if);
+ free(if_node);
+ return res;
+}
+
+/* Collect the nodes contained in the grafts in "list" in a node list.
+ */
+static __isl_give isl_ast_node_list *extract_node_list(
+ __isl_keep isl_ast_graft_list *list)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_ast_node_list *node_list;
+
+ if (!list)
+ return NULL;
+ ctx = isl_ast_graft_list_get_ctx(list);
+ n = isl_ast_graft_list_n_ast_graft(list);
+ node_list = isl_ast_node_list_alloc(ctx, n);
+ for (i = 0; i < n; ++i) {
+ isl_ast_node *node;
+ isl_ast_graft *graft;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ node = isl_ast_graft_get_node(graft);
+ node_list = isl_ast_node_list_add(node_list, node);
+ isl_ast_graft_free(graft);
+ }
+
+ return 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.
+ */
+__isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
+ __isl_keep isl_ast_graft_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ int i, n;
+ int depth;
+ isl_space *space;
+ isl_basic_set *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);
+ for (i = 0; i < n; ++i) {
+ isl_ast_graft *graft;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ enforced = update_enforced(enforced, graft, depth);
+ isl_ast_graft_free(graft);
+ }
+
+ return enforced;
+}
+
+/* Record "guard" in "graft" so that it will be enforced somewhere
+ * up the tree. If the graft already has a guard, then it may be partially
+ * redundant in combination with the new guard and in the context
+ * the generated constraints of "build". In fact, the new guard
+ * may in itself have some redundant constraints.
+ * We therefore (re)compute the gist of the intersection
+ * and coalesce the result.
+ */
+static __isl_give isl_ast_graft *store_guard(__isl_take isl_ast_graft *graft,
+ __isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+ int is_universe;
+
+ if (!graft)
+ goto error;
+
+ is_universe = isl_set_plain_is_universe(guard);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_set_free(guard);
+ return graft;
+ }
+
+ graft->guard = isl_set_intersect(graft->guard, guard);
+ graft->guard = isl_set_gist(graft->guard,
+ isl_ast_build_get_generated(build));
+ graft->guard = isl_set_coalesce(graft->guard);
+ if (!graft->guard)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+error:
+ isl_set_free(guard);
+ return isl_ast_graft_free(graft);
+}
+
+/* For each graft in "list", replace its guard with the gist with
+ * respect to "context".
+ */
+static __isl_give isl_ast_graft_list *gist_guards(
+ __isl_take isl_ast_graft_list *list, __isl_keep isl_set *context)
+{
+ int i, n;
+
+ if (!list)
+ return NULL;
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ for (i = 0; i < n; ++i) {
+ isl_ast_graft *graft;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ if (!graft)
+ break;
+ graft->guard = isl_set_gist(graft->guard,
+ isl_set_copy(context));
+ if (!graft->guard)
+ graft = isl_ast_graft_free(graft);
+ list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+ }
+ if (i < n)
+ return isl_ast_graft_list_free(list);
+
+ return list;
+}
+
+/* For each graft in "list", replace its guard with the gist with
+ * respect to "context".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_gist_guards(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_set *context)
+{
+ list = gist_guards(list, context);
+ isl_set_free(context);
+
+ return list;
+}
+
+/* Allocate a graft in "build" based on the list of grafts in "sub_build".
+ * "guard" and "enforced" are the guard and enforced constraints
+ * of the allocated graft. The guard is used to simplify the guards
+ * of the elements in "list".
+ *
+ * The node is initialized to either a block containing the nodes of "children"
+ * or, if there is only a single child, the node of that child.
+ * If the current level requires a for node, it should be inserted by
+ * a subsequent call to isl_ast_graft_insert_for.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_from_children(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_set *guard,
+ __isl_take isl_basic_set *enforced, __isl_keep isl_ast_build *build,
+ __isl_keep isl_ast_build *sub_build)
+{
+ isl_ast_build *guard_build;
+ isl_ast_node *node;
+ isl_ast_node_list *node_list;
+ isl_ast_graft *graft;
+
+ guard_build = isl_ast_build_copy(sub_build);
+ guard_build = isl_ast_build_replace_pending_by_guard(guard_build,
+ isl_set_copy(guard));
+ list = gist_guards(list, guard);
+ list = insert_pending_guard_nodes(list, guard_build);
+ isl_ast_build_free(guard_build);
+
+ node_list = extract_node_list(list);
+ node = isl_ast_node_from_ast_node_list(node_list);
+ isl_ast_graft_list_free(list);
+
+ graft = isl_ast_graft_alloc(node, build);
+ graft = store_guard(graft, guard, build);
+ graft = isl_ast_graft_enforce(graft, enforced);
+
+ return graft;
+}
+
+/* Combine the grafts in the list into a single graft.
+ *
+ * The guard is initialized to the shared guard of the list elements (if any),
+ * provided it does not depend on the current dimension.
+ * The guards in the elements are then simplified with respect to the
+ * hoisted guard and materialized as if nodes around the contained AST nodes
+ * in the context of "sub_build".
+ *
+ * The enforced set is initialized to the simple hull of the enforced sets
+ * of the elements, provided the ast_build_exploit_nested_bounds option is set
+ * or the new graft will be used at the same level.
+ *
+ * The node is initialized to either a block containing the nodes of "list"
+ * or, if there is only a single element, the node of that element.
+ */
+static __isl_give isl_ast_graft *ast_graft_list_fuse(
+ __isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+ isl_ast_graft *graft;
+ isl_basic_set *enforced;
+ isl_set *guard;
+
+ if (!list)
+ return NULL;
+
+ enforced = isl_ast_graft_list_extract_shared_enforced(list, build);
+ guard = isl_ast_graft_list_extract_hoistable_guard(list, build);
+ graft = isl_ast_graft_alloc_from_children(list, guard, enforced,
+ build, build);
+
+ return graft;
+}
+
+/* Combine the grafts in the list into a single graft.
+ * Return a list containing this single graft.
+ * If the original list is empty, then return an empty list.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ isl_ast_graft *graft;
+
+ if (!list)
+ return NULL;
+ if (isl_ast_graft_list_n_ast_graft(list) <= 1)
+ return list;
+ graft = ast_graft_list_fuse(list, build);
+ return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Combine the two grafts into a single graft.
+ * Return a list containing this single graft.
+ */
+static __isl_give isl_ast_graft *isl_ast_graft_fuse(
+ __isl_take isl_ast_graft *graft1, __isl_take isl_ast_graft *graft2,
+ __isl_keep isl_ast_build *build)
+{
+ isl_ctx *ctx;
+ isl_ast_graft_list *list;
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ list = isl_ast_graft_list_alloc(ctx, 2);
+ list = isl_ast_graft_list_add(list, graft1);
+ list = isl_ast_graft_list_add(list, graft2);
+
+ return ast_graft_list_fuse(list, build);
+}
+
+/* Insert a for node enclosing the current graft->node.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+ __isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node)
+{
+ if (!graft)
+ goto error;
+
+ graft->node = isl_ast_node_for_set_body(node, graft->node);
+ if (!graft->node)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+error:
+ isl_ast_node_free(node);
+ isl_ast_graft_free(graft);
+ return NULL;
+}
+
+/* Represent the graft list as an AST node.
+ * This operation drops the information about guards in the grafts, so
+ * if there are any pending guards, then they are materialized as if nodes.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+ __isl_take isl_ast_graft_list *list,
+ __isl_keep isl_ast_build *build)
+{
+ isl_ast_node_list *node_list;
+
+ list = insert_pending_guard_nodes(list, build);
+ node_list = extract_node_list(list);
+ isl_ast_graft_list_free(list);
+
+ return isl_ast_node_from_ast_node_list(node_list);
+}
+
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft)
+{
+ if (!graft)
+ return NULL;
+
+ if (--graft->ref > 0)
+ return NULL;
+
+ isl_ast_node_free(graft->node);
+ isl_set_free(graft->guard);
+ isl_basic_set_free(graft->enforced);
+ free(graft);
+
+ return NULL;
+}
+
+/* Record that the grafted tree enforces
+ * "enforced" by intersecting graft->enforced with "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+ __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+ if (!graft || !enforced)
+ goto error;
+
+ enforced = isl_basic_set_align_params(enforced,
+ isl_basic_set_get_space(graft->enforced));
+ graft->enforced = isl_basic_set_align_params(graft->enforced,
+ isl_basic_set_get_space(enforced));
+ graft->enforced = isl_basic_set_intersect(graft->enforced, enforced);
+ if (!graft->enforced)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+error:
+ isl_basic_set_free(enforced);
+ return isl_ast_graft_free(graft);
+}
+
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+ __isl_keep isl_ast_graft *graft)
+{
+ return graft ? isl_basic_set_copy(graft->enforced) : NULL;
+}
+
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft)
+{
+ return graft ? isl_set_copy(graft->guard) : NULL;
+}
+
+/* Record that "guard" needs to be inserted in "graft".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+ __isl_take isl_ast_graft *graft,
+ __isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+ return store_guard(graft, guard, build);
+}
+
+/* Reformulate the "graft", which was generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ *
+ * If "product" is set, then the domain of the inner code generation build is
+ *
+ * [O -> S]
+ *
+ * with O the domain of the outer code generation build.
+ * We essentially need to project out S.
+ *
+ * If "product" is not set, then we need to project the domains onto
+ * their parameter spaces.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_unembed(__isl_take isl_ast_graft *graft,
+ int product)
+{
+ isl_basic_set *enforced;
+
+ if (!graft)
+ return NULL;
+
+ if (product) {
+ enforced = graft->enforced;
+ enforced = isl_basic_map_domain(isl_basic_set_unwrap(enforced));
+ graft->enforced = enforced;
+ graft->guard = isl_map_domain(isl_set_unwrap(graft->guard));
+ } else {
+ graft->enforced = isl_basic_set_params(graft->enforced);
+ graft->guard = isl_set_params(graft->guard);
+ }
+ graft->guard = isl_set_compute_divs(graft->guard);
+
+ if (!graft->enforced || !graft->guard)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+}
+
+/* Reformulate the grafts in "list", which were generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+ __isl_take isl_ast_graft_list *list, int product)
+{
+ int i, n;
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ for (i = 0; i < n; ++i) {
+ isl_ast_graft *graft;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ graft = isl_ast_graft_unembed(graft, product);
+ list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+ }
+
+ return list;
+}
+
+/* Compute the preimage of "graft" under the function represented by "ma".
+ * In other words, plug in "ma" in "enforced" and "guard" fields of "graft".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_preimage_multi_aff(
+ __isl_take isl_ast_graft *graft, __isl_take isl_multi_aff *ma)
+{
+ isl_basic_set *enforced;
+
+ if (!graft)
+ return NULL;
+
+ enforced = graft->enforced;
+ graft->enforced = isl_basic_set_preimage_multi_aff(enforced,
+ isl_multi_aff_copy(ma));
+ graft->guard = isl_set_preimage_multi_aff(graft->guard, ma);
+
+ if (!graft->enforced || !graft->guard)
+ return isl_ast_graft_free(graft);
+
+ return graft;
+}
+
+/* Compute the preimage of all the grafts in "list" under
+ * the function represented by "ma".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma)
+{
+ int i, n;
+
+ n = isl_ast_graft_list_n_ast_graft(list);
+ for (i = 0; i < n; ++i) {
+ isl_ast_graft *graft;
+
+ graft = isl_ast_graft_list_get_ast_graft(list, i);
+ graft = isl_ast_graft_preimage_multi_aff(graft,
+ isl_multi_aff_copy(ma));
+ list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+ }
+
+ isl_multi_aff_free(ma);
+ return list;
+}
+
+/* Compare two grafts based on their guards.
+ */
+static int cmp_graft(__isl_keep isl_ast_graft *a, __isl_keep isl_ast_graft *b,
+ void *user)
+{
+ return isl_set_plain_cmp(a->guard, b->guard);
+}
+
+/* Order the elements in "list" based on their guards.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort_guard(
+ __isl_take isl_ast_graft_list *list)
+{
+ return isl_ast_graft_list_sort(list, &cmp_graft, NULL);
+}
+
+/* Merge the given two lists into a single list of grafts,
+ * merging grafts with the same guard into a single graft.
+ *
+ * "list2" has been sorted using isl_ast_graft_list_sort.
+ * "list1" may be the result of a previous call to isl_ast_graft_list_merge
+ * and may therefore not be completely sorted.
+ *
+ * The elements in "list2" need to be executed after those in "list1",
+ * but if the guard of a graft in "list2" is disjoint from the guards
+ * of some final elements in "list1", then it can be moved up to before
+ * those final elements.
+ *
+ * In particular, we look at each element g of "list2" in turn
+ * and move it up beyond elements of "list1" that would be sorted
+ * after g as long as each of these elements has a guard that is disjoint
+ * from that of g.
+ *
+ * We do not allow the second or any later element of "list2" to be moved
+ * before a previous elements of "list2" even if the reason that
+ * that element didn't move up further was that its guard was not disjoint
+ * from that of the previous element in "list1".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+ __isl_take isl_ast_graft_list *list1,
+ __isl_take isl_ast_graft_list *list2,
+ __isl_keep isl_ast_build *build)
+{
+ int i, j, first;
+
+ if (!list1 || !list2 || !build)
+ goto error;
+ if (list2->n == 0) {
+ isl_ast_graft_list_free(list2);
+ return list1;
+ }
+ if (list1->n == 0) {
+ isl_ast_graft_list_free(list1);
+ return list2;
+ }
+
+ first = 0;
+ for (i = 0; i < list2->n; ++i) {
+ isl_ast_graft *graft;
+ graft = isl_ast_graft_list_get_ast_graft(list2, i);
+ if (!graft)
+ break;
+
+ for (j = list1->n; j >= 0; --j) {
+ int cmp, disjoint;
+ isl_ast_graft *graft_j;
+
+ if (j == first)
+ cmp = -1;
+ else
+ cmp = isl_set_plain_cmp(list1->p[j - 1]->guard,
+ graft->guard);
+ if (cmp > 0) {
+ disjoint = isl_set_is_disjoint(graft->guard,
+ list1->p[j - 1]->guard);
+ if (disjoint < 0) {
+ list1 = isl_ast_graft_list_free(list1);
+ break;
+ }
+ if (!disjoint)
+ cmp = -1;
+ }
+ if (cmp > 0)
+ continue;
+ if (cmp < 0) {
+ list1 = isl_ast_graft_list_insert(list1, j,
+ graft);
+ break;
+ }
+
+ --j;
+
+ graft_j = isl_ast_graft_list_get_ast_graft(list1, j);
+ graft_j = isl_ast_graft_fuse(graft_j, graft, build);
+ list1 = isl_ast_graft_list_set_ast_graft(list1, j,
+ graft_j);
+ break;
+ }
+
+ if (j < 0)
+ isl_die(isl_ast_build_get_ctx(build),
+ isl_error_internal,
+ "element failed to get inserted", break);
+
+ first = j + 1;
+ if (!list1)
+ break;
+ }
+ if (i < list2->n)
+ list1 = isl_ast_graft_list_free(list1);
+ isl_ast_graft_list_free(list2);
+
+ return list1;
+error:
+ isl_ast_graft_list_free(list1);
+ isl_ast_graft_list_free(list2);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+ __isl_keep isl_ast_graft *graft)
+{
+ if (!p)
+ return NULL;
+ if (!graft)
+ return isl_printer_free(p);
+
+ p = isl_printer_print_str(p, "(");
+ p = isl_printer_print_str(p, "guard: ");
+ p = isl_printer_print_set(p, graft->guard);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "enforced: ");
+ p = isl_printer_print_basic_set(p, graft->enforced);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_str(p, "node: ");
+ p = isl_printer_print_ast_node(p, graft->node);
+ p = isl_printer_print_str(p, ")");
+
+ return p;
+}
diff --git a/polly/lib/External/isl/isl_ast_graft_private.h b/polly/lib/External/isl/isl_ast_graft_private.h
new file mode 100644
index 00000000000..82b1c1ccaa0
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_graft_private.h
@@ -0,0 +1,97 @@
+#ifndef ISL_AST_GRAFT_PRIVATE_H
+#define ISL_AST_GRAFT_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+struct isl_ast_graft;
+typedef struct isl_ast_graft isl_ast_graft;
+
+/* Representation of part of an AST ("node") with some additional polyhedral
+ * information about the tree.
+ *
+ * "guard" contains conditions that should still be enforced by
+ * some ancestor of the current tree. In particular, the already
+ * generated tree assumes that these conditions hold, but may not
+ * have enforced them itself.
+ * The guard should not contain any unknown divs as it will be used
+ * to generate an if condition.
+ *
+ * "enforced" expresses constraints that are already enforced by the for
+ * nodes in the current tree and that therefore do not need to be enforced
+ * by any ancestor.
+ * The constraints only involve outer loop iterators.
+ */
+struct isl_ast_graft {
+ int ref;
+
+ isl_ast_node *node;
+
+ isl_set *guard;
+ isl_basic_set *enforced;
+};
+
+ISL_DECLARE_LIST(ast_graft)
+
+#undef EL
+#define EL isl_ast_graft
+
+#include <isl_list_templ.h>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_alloc(
+ __isl_take isl_ast_node *node, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_from_children(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_set *guard,
+ __isl_take isl_basic_set *enforced, __isl_keep isl_ast_build *build,
+ __isl_keep isl_ast_build *sub_build);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+ __isl_take isl_ast_graft_list *children,
+ __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+ __isl_take isl_map *schedule, __isl_keep isl_ast_build *build);
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort_guard(
+ __isl_take isl_ast_graft_list *list);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+ __isl_take isl_ast_graft_list *list1,
+ __isl_take isl_ast_graft_list *list2,
+ __isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+ __isl_keep isl_ast_graft *graft);
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+ __isl_keep isl_ast_graft *graft);
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+ __isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node);
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+ __isl_take isl_ast_graft *graft,
+ __isl_take isl_set *guard, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+ __isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+ __isl_take isl_ast_graft_list *list, int product);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma);
+
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+ __isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+
+__isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
+ __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard(
+ __isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_gist_guards(
+ __isl_take isl_ast_graft_list *list, __isl_take isl_set *context);
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+ __isl_keep isl_ast_graft *graft);
+
+#endif
diff --git a/polly/lib/External/isl/isl_ast_int.c b/polly/lib/External/isl/isl_ast_int.c
new file mode 100644
index 00000000000..178c38cf32a
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_int.c
@@ -0,0 +1,13 @@
+#include <isl/deprecated/ast_int.h>
+#include <isl/deprecated/val_int.h>
+#include <isl_ast_private.h>
+
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v)
+{
+ if (!expr)
+ return -1;
+ if (expr->type != isl_ast_expr_int)
+ isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+ "expression not an int", return -1);
+ return isl_val_get_num_isl_int(expr->u.v, v);
+}
diff --git a/polly/lib/External/isl/isl_ast_private.h b/polly/lib/External/isl/isl_ast_private.h
new file mode 100644
index 00000000000..c1bf334403b
--- /dev/null
+++ b/polly/lib/External/isl/isl_ast_private.h
@@ -0,0 +1,114 @@
+#ifndef ISL_AST_PRIVATE_H
+#define ISL_AST_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/vec.h>
+#include <isl/list.h>
+
+/* An expression is either an integer, an identifier or an operation
+ * with zero or more arguments.
+ */
+struct isl_ast_expr {
+ int ref;
+
+ isl_ctx *ctx;
+
+ enum isl_ast_expr_type type;
+
+ union {
+ isl_val *v;
+ isl_id *id;
+ struct {
+ enum isl_ast_op_type op;
+ unsigned n_arg;
+ isl_ast_expr **args;
+ } op;
+ } u;
+};
+
+#undef EL
+#define EL isl_ast_expr
+
+#include <isl_list_templ.h>
+
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
+ enum isl_ast_op_type op, int n_arg);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+ __isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
+
+#undef EL
+#define EL isl_ast_node
+
+#include <isl_list_templ.h>
+
+/* A node is either a block, an if, a for or a user node.
+ * "else_node" is NULL if the if node does not have an else branch.
+ * "cond" and "inc" are NULL for degenerate for nodes.
+ */
+struct isl_ast_node {
+ int ref;
+
+ isl_ctx *ctx;
+ enum isl_ast_node_type type;
+
+ union {
+ struct {
+ isl_ast_node_list *children;
+ } b;
+ struct {
+ isl_ast_expr *guard;
+ isl_ast_node *then;
+ isl_ast_node *else_node;
+ } i;
+ struct {
+ unsigned degenerate : 1;
+ isl_ast_expr *iterator;
+ isl_ast_expr *init;
+ isl_ast_expr *cond;
+ isl_ast_expr *inc;
+ isl_ast_node *body;
+ } f;
+ struct {
+ isl_ast_expr *expr;
+ } e;
+ } u;
+
+ isl_id *annotation;
+};
+
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id);
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+ __isl_take isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard);
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+ __isl_take isl_ast_node_list *list);
+__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
+ __isl_take isl_ast_node_list *list);
+__isl_give isl_ast_node *isl_ast_node_for_set_body(
+ __isl_take isl_ast_node *node, __isl_take isl_ast_node *body);
+__isl_give isl_ast_node *isl_ast_node_if_set_then(
+ __isl_take isl_ast_node *node, __isl_take isl_ast_node *child);
+
+struct isl_ast_print_options {
+ int ref;
+ isl_ctx *ctx;
+
+ __isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user);
+ void *print_for_user;
+ __isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+ __isl_take isl_ast_print_options *options,
+ __isl_keep isl_ast_node *node, void *user);
+ void *print_user_user;
+};
+
+__isl_give isl_printer *isl_ast_node_list_print(
+ __isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+ __isl_keep isl_ast_print_options *options);
+
+#endif
diff --git a/polly/lib/External/isl/isl_band.c b/polly/lib/External/isl/isl_band.c
new file mode 100644
index 00000000000..aaee1f1c951
--- /dev/null
+++ b/polly/lib/External/isl/isl_band.c
@@ -0,0 +1,726 @@
+/*
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2012-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_band_private.h>
+#include <isl_schedule_private.h>
+
+#undef BASE
+#define BASE band
+
+#include <isl_list_templ.c>
+
+isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band)
+{
+ return band ? isl_union_pw_multi_aff_get_ctx(band->pma) : NULL;
+}
+
+__isl_give isl_band *isl_band_alloc(isl_ctx *ctx)
+{
+ isl_band *band;
+
+ band = isl_calloc_type(ctx, isl_band);
+ if (!band)
+ return NULL;
+
+ band->ref = 1;
+
+ return band;
+}
+
+/* Create a duplicate of the given band. The duplicate refers
+ * to the same schedule and parent as the input, but does not
+ * increment their reference counts.
+ */
+__isl_give isl_band *isl_band_dup(__isl_keep isl_band *band)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_band *dup;
+
+ if (!band)
+ return NULL;
+
+ ctx = isl_band_get_ctx(band);
+ dup = isl_band_alloc(ctx);
+ if (!dup)
+ return NULL;
+
+ dup->n = band->n;
+ dup->coincident = isl_alloc_array(ctx, int, band->n);
+ if (band->n && !dup->coincident)
+ goto error;
+
+ for (i = 0; i < band->n; ++i)
+ dup->coincident[i] = band->coincident[i];
+
+ dup->pma = isl_union_pw_multi_aff_copy(band->pma);
+ dup->schedule = band->schedule;
+ dup->parent = band->parent;
+
+ if (!dup->pma)
+ goto error;
+
+ return dup;
+error:
+ isl_band_free(dup);
+ return NULL;
+}
+
+/* We not only increment the reference count of the band,
+ * but also that of the schedule that contains this band.
+ * This ensures that the schedule won't disappear while there
+ * is still a reference to the band outside of the schedule.
+ * There is no need to increment the reference count of the parent
+ * band as the parent band is part of the same schedule.
+ */
+__isl_give isl_band *isl_band_copy(__isl_keep isl_band *band)
+{
+ if (!band)
+ return NULL;
+
+ band->ref++;
+ band->schedule->ref++;
+ return band;
+}
+
+/* If this is not the last reference to the band (the one from within the
+ * schedule), then we also need to decrement the reference count of the
+ * containing schedule as it was incremented in isl_band_copy.
+ */
+__isl_null isl_band *isl_band_free(__isl_take isl_band *band)
+{
+ if (!band)
+ return NULL;
+
+ if (--band->ref > 0) {
+ isl_schedule_free(band->schedule);
+ return NULL;
+ }
+
+ isl_union_pw_multi_aff_free(band->pma);
+ isl_band_list_free(band->children);
+ free(band->coincident);
+ free(band);
+
+ return NULL;
+}
+
+int isl_band_has_children(__isl_keep isl_band *band)
+{
+ if (!band)
+ return -1;
+
+ return band->children != NULL;
+}
+
+__isl_give isl_band_list *isl_band_get_children(
+ __isl_keep isl_band *band)
+{
+ if (!band)
+ return NULL;
+ if (!band->children)
+ isl_die(isl_band_get_ctx(band), isl_error_invalid,
+ "band has no children", return NULL);
+ return isl_band_list_dup(band->children);
+}
+
+int isl_band_n_member(__isl_keep isl_band *band)
+{
+ return band ? band->n : 0;
+}
+
+/* Is the given scheduling dimension coincident within the band and
+ * with respect to the coincidence constraints.
+ */
+int isl_band_member_is_coincident(__isl_keep isl_band *band, int pos)
+{
+ if (!band)
+ return -1;
+
+ if (pos < 0 || pos >= band->n)
+ isl_die(isl_band_get_ctx(band), isl_error_invalid,
+ "invalid member position", return -1);
+
+ return band->coincident[pos];
+}
+
+/* Return the schedule that leads up to this band.
+ */
+__isl_give isl_union_map *isl_band_get_prefix_schedule(
+ __isl_keep isl_band *band)
+{
+ isl_union_set *domain;
+ isl_union_pw_multi_aff *prefix;
+ isl_band *a;
+
+ if (!band)
+ return NULL;
+
+ prefix = isl_union_pw_multi_aff_copy(band->pma);
+ domain = isl_union_pw_multi_aff_domain(prefix);
+ prefix = isl_union_pw_multi_aff_from_domain(domain);
+
+ for (a = band->parent; a; a = a->parent) {
+ isl_union_pw_multi_aff *partial;
+
+ partial = isl_union_pw_multi_aff_copy(a->pma);
+ prefix = isl_union_pw_multi_aff_flat_range_product(partial,
+ prefix);
+ }
+
+ return isl_union_map_from_union_pw_multi_aff(prefix);
+}
+
+/* Return the schedule of the band in isolation.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_partial_schedule_union_pw_multi_aff(__isl_keep isl_band *band)
+{
+ return band ? isl_union_pw_multi_aff_copy(band->pma) : NULL;
+}
+
+/* Return the schedule of the band in isolation.
+ */
+__isl_give isl_union_map *isl_band_get_partial_schedule(
+ __isl_keep isl_band *band)
+{
+ isl_union_pw_multi_aff *sched;
+
+ sched = isl_band_get_partial_schedule_union_pw_multi_aff(band);
+ return isl_union_map_from_union_pw_multi_aff(sched);
+}
+
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_suffix_schedule_union_pw_multi_aff(__isl_keep isl_band *band);
+
+/* Return the schedule for the given band list.
+ * For each band in the list, the schedule is composed of the partial
+ * and suffix schedules of that band.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_list_get_suffix_schedule_union_pw_multi_aff(
+ __isl_keep isl_band_list *list)
+{
+ isl_ctx *ctx;
+ int i, n;
+ isl_space *space;
+ isl_union_pw_multi_aff *suffix;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_band_list_get_ctx(list);
+ space = isl_space_alloc(ctx, 0, 0, 0);
+ suffix = isl_union_pw_multi_aff_empty(space);
+ n = isl_band_list_n_band(list);
+ for (i = 0; i < n; ++i) {
+ isl_band *el;
+ isl_union_pw_multi_aff *partial;
+ isl_union_pw_multi_aff *suffix_i;
+
+ el = isl_band_list_get_band(list, i);
+ partial = isl_band_get_partial_schedule_union_pw_multi_aff(el);
+ suffix_i = isl_band_get_suffix_schedule_union_pw_multi_aff(el);
+ suffix_i = isl_union_pw_multi_aff_flat_range_product(
+ partial, suffix_i);
+ suffix = isl_union_pw_multi_aff_union_add(suffix, suffix_i);
+
+ isl_band_free(el);
+ }
+
+ return suffix;
+}
+
+/* Return the schedule for the given band list.
+ * For each band in the list, the schedule is composed of the partial
+ * and suffix schedules of that band.
+ */
+__isl_give isl_union_map *isl_band_list_get_suffix_schedule(
+ __isl_keep isl_band_list *list)
+{
+ isl_union_pw_multi_aff *suffix;
+
+ suffix = isl_band_list_get_suffix_schedule_union_pw_multi_aff(list);
+ return isl_union_map_from_union_pw_multi_aff(suffix);
+}
+
+/* Return the schedule for the forest underneath the given band.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_suffix_schedule_union_pw_multi_aff(__isl_keep isl_band *band)
+{
+ isl_union_pw_multi_aff *suffix;
+
+ if (!band)
+ return NULL;
+
+ if (!isl_band_has_children(band)) {
+ isl_union_set *domain;
+
+ suffix = isl_union_pw_multi_aff_copy(band->pma);
+ domain = isl_union_pw_multi_aff_domain(suffix);
+ suffix = isl_union_pw_multi_aff_from_domain(domain);
+ } else {
+ isl_band_list *list;
+
+ list = isl_band_get_children(band);
+ suffix =
+ isl_band_list_get_suffix_schedule_union_pw_multi_aff(list);
+ isl_band_list_free(list);
+ }
+
+ return suffix;
+}
+
+/* Return the schedule for the forest underneath the given band.
+ */
+__isl_give isl_union_map *isl_band_get_suffix_schedule(
+ __isl_keep isl_band *band)
+{
+ isl_union_pw_multi_aff *suffix;
+
+ suffix = isl_band_get_suffix_schedule_union_pw_multi_aff(band);
+ return isl_union_map_from_union_pw_multi_aff(suffix);
+}
+
+/* Call "fn" on each band (recursively) in the list
+ * in depth-first post-order.
+ */
+int isl_band_list_foreach_band(__isl_keep isl_band_list *list,
+ int (*fn)(__isl_keep isl_band *band, void *user), void *user)
+{
+ int i, n;
+
+ if (!list)
+ return -1;
+
+ n = isl_band_list_n_band(list);
+ for (i = 0; i < n; ++i) {
+ isl_band *band;
+ int r = 0;
+
+ band = isl_band_list_get_band(list, i);
+ if (isl_band_has_children(band)) {
+ isl_band_list *children;
+
+ children = isl_band_get_children(band);
+ r = isl_band_list_foreach_band(children, fn, user);
+ isl_band_list_free(children);
+ }
+
+ if (!band)
+ r = -1;
+ if (r == 0)
+ r = fn(band, user);
+
+ isl_band_free(band);
+ if (r)
+ return r;
+ }
+
+ return 0;
+}
+
+/* Internal data used during the construction of the schedule
+ * for the tile loops.
+ *
+ * sizes contains the tile sizes
+ * scale is set if the tile loops should be scaled
+ * tiled collects the result for a single statement
+ * res collects the result for all statements
+ */
+struct isl_band_tile_data {
+ isl_multi_val *sizes;
+ isl_union_pw_multi_aff *res;
+ isl_pw_multi_aff *tiled;
+ int scale;
+};
+
+/* Given part of the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the tile sizes in data->sizes
+ * and add the result to data->tiled.
+ *
+ * If data->scale is set, then dimension i of the schedule will be
+ * of the form
+ *
+ * m_i * floor(s_i(x) / m_i)
+ *
+ * where s_i(x) refers to the original schedule and m_i is the tile size.
+ * If data->scale is not set, then dimension i of the schedule will be
+ * of the form
+ *
+ * floor(s_i(x) / m_i)
+ *
+ */
+static int multi_aff_tile(__isl_take isl_set *set,
+ __isl_take isl_multi_aff *ma, void *user)
+{
+ struct isl_band_tile_data *data = user;
+ isl_pw_multi_aff *pma;
+ int i, n;
+ isl_val *v;
+
+ n = isl_multi_aff_dim(ma, isl_dim_out);
+
+ for (i = 0; i < n; ++i) {
+ isl_aff *aff;
+
+ aff = isl_multi_aff_get_aff(ma, i);
+ v = isl_multi_val_get_val(data->sizes, i);
+
+ aff = isl_aff_scale_down_val(aff, isl_val_copy(v));
+ aff = isl_aff_floor(aff);
+ if (data->scale)
+ aff = isl_aff_scale_val(aff, isl_val_copy(v));
+ isl_val_free(v);
+
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ pma = isl_pw_multi_aff_alloc(set, ma);
+ data->tiled = isl_pw_multi_aff_union_add(data->tiled, pma);
+
+ return 0;
+}
+
+/* Given part of the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the tile sizes in data->sizes
+ * and add the result to data->res.
+ */
+static int pw_multi_aff_tile(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ struct isl_band_tile_data *data = user;
+
+ data->tiled = isl_pw_multi_aff_empty(isl_pw_multi_aff_get_space(pma));
+
+ if (isl_pw_multi_aff_foreach_piece(pma, &multi_aff_tile, data) < 0)
+ goto error;
+
+ isl_pw_multi_aff_free(pma);
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res,
+ data->tiled);
+
+ return 0;
+error:
+ isl_pw_multi_aff_free(pma);
+ isl_pw_multi_aff_free(data->tiled);
+ return -1;
+}
+
+/* Given the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the given tile sizes
+ * and return the result.
+ */
+static isl_union_pw_multi_aff *isl_union_pw_multi_aff_tile(
+ __isl_take isl_union_pw_multi_aff *sched,
+ __isl_keep isl_multi_val *sizes)
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ struct isl_band_tile_data data = { sizes };
+
+ ctx = isl_multi_val_get_ctx(sizes);
+
+ space = isl_union_pw_multi_aff_get_space(sched);
+ data.res = isl_union_pw_multi_aff_empty(space);
+ data.scale = isl_options_get_tile_scale_tile_loops(ctx);
+
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(sched,
+ &pw_multi_aff_tile, &data) < 0)
+ goto error;
+
+ isl_union_pw_multi_aff_free(sched);
+ return data.res;
+error:
+ isl_union_pw_multi_aff_free(sched);
+ isl_union_pw_multi_aff_free(data.res);
+ return NULL;
+}
+
+/* Extract the range space from "pma" and store it in *user.
+ * All entries are expected to have the same range space, so we can
+ * stop after extracting the range space from the first entry.
+ */
+static int extract_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ isl_space **space = user;
+
+ *space = isl_space_range(isl_pw_multi_aff_get_space(pma));
+ isl_pw_multi_aff_free(pma);
+
+ return -1;
+}
+
+/* Extract the range space of "band". All entries in band->pma should
+ * have the same range space. Furthermore, band->pma should have at least
+ * one entry.
+ */
+static __isl_give isl_space *band_get_range_space(__isl_keep isl_band *band)
+{
+ isl_space *space;
+
+ if (!band)
+ return NULL;
+
+ space = NULL;
+ isl_union_pw_multi_aff_foreach_pw_multi_aff(band->pma,
+ &extract_range_space, &space);
+
+ return space;
+}
+
+/* Construct and return an isl_multi_val in the given space, with as entries
+ * the first elements of "v", padded with ones if the size of "v" is smaller
+ * than the dimension of "space".
+ */
+static __isl_give isl_multi_val *multi_val_from_vec(__isl_take isl_space *space,
+ __isl_take isl_vec *v)
+{
+ isl_ctx *ctx;
+ isl_multi_val *mv;
+ int i, n, size;
+
+ if (!space || !v)
+ goto error;
+
+ ctx = isl_space_get_ctx(space);
+ mv = isl_multi_val_zero(space);
+ n = isl_multi_val_dim(mv, isl_dim_set);
+ size = isl_vec_size(v);
+ if (n < size)
+ size = n;
+
+ for (i = 0; i < size; ++i) {
+ isl_val *val = isl_vec_get_element_val(v, i);
+ mv = isl_multi_val_set_val(mv, i, val);
+ }
+ for (i = size; i < n; ++i)
+ mv = isl_multi_val_set_val(mv, i, isl_val_one(ctx));
+
+ isl_vec_free(v);
+ return mv;
+error:
+ isl_space_free(space);
+ isl_vec_free(v);
+ return NULL;
+}
+
+/* Tile the given band using the specified tile sizes.
+ * The given band is modified to refer to the tile loops and
+ * a child band is created to refer to the point loops.
+ * The children of this point loop band are the children
+ * of the original band.
+ *
+ * If the scale tile loops option is set, then the tile loops
+ * are scaled by the tile sizes. If the shift point loops option is set,
+ * then the point loops are shifted to start at zero.
+ * In particular, these options affect the tile and point loop schedules
+ * as follows
+ *
+ * scale shift original tile point
+ *
+ * 0 0 i floor(i/s) i
+ * 1 0 i s * floor(i/s) i
+ * 0 1 i floor(i/s) i - s * floor(i/s)
+ * 1 1 i s * floor(i/s) i - s * floor(i/s)
+ */
+int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes)
+{
+ isl_ctx *ctx;
+ isl_band *child;
+ isl_band_list *list = NULL;
+ isl_union_pw_multi_aff *sched = NULL, *child_sched = NULL;
+ isl_space *space;
+ isl_multi_val *mv_sizes;
+
+ if (!band || !sizes)
+ goto error;
+
+ ctx = isl_vec_get_ctx(sizes);
+ child = isl_band_dup(band);
+ list = isl_band_list_alloc(ctx, 1);
+ list = isl_band_list_add(list, child);
+ if (!list)
+ goto error;
+
+ space = band_get_range_space(band);
+ mv_sizes = multi_val_from_vec(space, isl_vec_copy(sizes));
+ sched = isl_union_pw_multi_aff_copy(band->pma);
+ sched = isl_union_pw_multi_aff_tile(sched, mv_sizes);
+
+ child_sched = isl_union_pw_multi_aff_copy(child->pma);
+ if (isl_options_get_tile_shift_point_loops(ctx)) {
+ isl_union_pw_multi_aff *scaled;
+ scaled = isl_union_pw_multi_aff_copy(sched);
+ if (!isl_options_get_tile_scale_tile_loops(ctx))
+ scaled = isl_union_pw_multi_aff_scale_multi_val(scaled,
+ isl_multi_val_copy(mv_sizes));
+ child_sched = isl_union_pw_multi_aff_sub(child_sched, scaled);
+ }
+ isl_multi_val_free(mv_sizes);
+ if (!sched || !child_sched)
+ goto error;
+
+ child->children = band->children;
+ band->children = list;
+ child->parent = band;
+ isl_union_pw_multi_aff_free(band->pma);
+ band->pma = sched;
+ isl_union_pw_multi_aff_free(child->pma);
+ child->pma = child_sched;
+
+ isl_vec_free(sizes);
+ return 0;
+error:
+ isl_union_pw_multi_aff_free(sched);
+ isl_union_pw_multi_aff_free(child_sched);
+ isl_band_list_free(list);
+ isl_vec_free(sizes);
+ return -1;
+}
+
+/* Internal data structure used inside isl_union_pw_multi_aff_drop.
+ *
+ * "pos" is the position of the first dimension to drop.
+ * "n" is the number of dimensions to drop.
+ * "res" accumulates the result.
+ */
+struct isl_union_pw_multi_aff_drop_data {
+ int pos;
+ int n;
+ isl_union_pw_multi_aff *res;
+};
+
+/* Drop the data->n output dimensions starting at data->pos from "pma"
+ * and add the result to data->res.
+ */
+static int pw_multi_aff_drop(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ struct isl_union_pw_multi_aff_drop_data *data = user;
+
+ pma = isl_pw_multi_aff_drop_dims(pma, isl_dim_out, data->pos, data->n);
+
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Drop the "n" output dimensions starting at "pos" from "sched".
+ */
+static isl_union_pw_multi_aff *isl_union_pw_multi_aff_drop(
+ __isl_take isl_union_pw_multi_aff *sched, int pos, int n)
+{
+ isl_space *space;
+ struct isl_union_pw_multi_aff_drop_data data = { pos, n };
+
+ space = isl_union_pw_multi_aff_get_space(sched);
+ data.res = isl_union_pw_multi_aff_empty(space);
+
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(sched,
+ &pw_multi_aff_drop, &data) < 0)
+ data.res = isl_union_pw_multi_aff_free(data.res);
+
+ isl_union_pw_multi_aff_free(sched);
+ return data.res;
+}
+
+/* Drop the "n" dimensions starting at "pos" from "band".
+ */
+static int isl_band_drop(__isl_keep isl_band *band, int pos, int n)
+{
+ int i;
+ isl_union_pw_multi_aff *sched;
+
+ if (!band)
+ return -1;
+ if (n == 0)
+ return 0;
+
+ sched = isl_union_pw_multi_aff_copy(band->pma);
+ sched = isl_union_pw_multi_aff_drop(sched, pos, n);
+ if (!sched)
+ return -1;
+
+ isl_union_pw_multi_aff_free(band->pma);
+ band->pma = sched;
+
+ for (i = pos + n; i < band->n; ++i)
+ band->coincident[i - n] = band->coincident[i];
+
+ band->n -= n;
+
+ return 0;
+}
+
+/* Split the given band into two nested bands, one with the first "pos"
+ * dimensions of "band" and one with the remaining band->n - pos dimensions.
+ */
+int isl_band_split(__isl_keep isl_band *band, int pos)
+{
+ isl_ctx *ctx;
+ isl_band *child;
+ isl_band_list *list;
+
+ if (!band)
+ return -1;
+
+ ctx = isl_band_get_ctx(band);
+
+ if (pos < 0 || pos > band->n)
+ isl_die(ctx, isl_error_invalid, "position out of bounds",
+ return -1);
+
+ child = isl_band_dup(band);
+ if (isl_band_drop(child, 0, pos) < 0)
+ child = isl_band_free(child);
+ list = isl_band_list_alloc(ctx, 1);
+ list = isl_band_list_add(list, child);
+ if (!list)
+ return -1;
+
+ if (isl_band_drop(band, pos, band->n - pos) < 0) {
+ isl_band_list_free(list);
+ return -1;
+ }
+
+ child->children = band->children;
+ band->children = list;
+ child->parent = band;
+
+ return 0;
+}
+
+__isl_give isl_printer *isl_printer_print_band(__isl_take isl_printer *p,
+ __isl_keep isl_band *band)
+{
+ isl_union_map *prefix, *partial, *suffix;
+
+ prefix = isl_band_get_prefix_schedule(band);
+ partial = isl_band_get_partial_schedule(band);
+ suffix = isl_band_get_suffix_schedule(band);
+
+ p = isl_printer_print_str(p, "(");
+ p = isl_printer_print_union_map(p, prefix);
+ p = isl_printer_print_str(p, ",");
+ p = isl_printer_print_union_map(p, partial);
+ p = isl_printer_print_str(p, ",");
+ p = isl_printer_print_union_map(p, suffix);
+ p = isl_printer_print_str(p, ")");
+
+ isl_union_map_free(prefix);
+ isl_union_map_free(partial);
+ isl_union_map_free(suffix);
+
+ return p;
+}
diff --git a/polly/lib/External/isl/isl_band_private.h b/polly/lib/External/isl/isl_band_private.h
new file mode 100644
index 00000000000..8b9c0b77da7
--- /dev/null
+++ b/polly/lib/External/isl/isl_band_private.h
@@ -0,0 +1,47 @@
+#ifndef ISL_BAND_PRIVATE_H
+#define ISL_BAND_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/band.h>
+#include <isl/list.h>
+#include <isl/schedule.h>
+
+/* Information about a band within a schedule.
+ *
+ * n is the number of scheduling dimensions within the band.
+ * coincident is an array of length n, indicating whether a scheduling dimension
+ * satisfies the coincidence constraints in the sense that
+ * the corresponding dependence distances are zero.
+ * pma is the partial schedule corresponding to this band.
+ * schedule is the schedule that contains this band.
+ * parent is the parent of this band (or NULL if the band is a root).
+ * children are the children of this band (or NULL if the band is a leaf).
+ *
+ * To avoid circular dependences in the reference counting,
+ * the schedule and parent pointers are not reference counted.
+ * isl_band_copy increments the reference count of schedule to ensure
+ * that outside references to the band keep the schedule alive.
+ */
+struct isl_band {
+ int ref;
+
+ int n;
+ int *coincident;
+
+ isl_union_pw_multi_aff *pma;
+ isl_schedule *schedule;
+ isl_band *parent;
+ isl_band_list *children;
+};
+
+#undef EL
+#define EL isl_band
+
+#include <isl_list_templ.h>
+
+__isl_give isl_band *isl_band_alloc(isl_ctx *ctx);
+
+__isl_give isl_union_map *isl_band_list_get_suffix_schedule(
+ __isl_keep isl_band_list *list);
+
+#endif
diff --git a/polly/lib/External/isl/isl_basis_reduction.h b/polly/lib/External/isl/isl_basis_reduction.h
new file mode 100644
index 00000000000..2517c2f1605
--- /dev/null
+++ b/polly/lib/External/isl/isl_basis_reduction.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_BASIS_REDUCTION_H
+#define ISL_BASIS_REDUCTION_H
+
+#include <isl/set.h>
+#include <isl_mat_private.h>
+#include "isl_tab.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_tab *isl_tab_compute_reduced_basis(struct isl_tab *tab);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_bernstein.c b/polly/lib/External/isl/isl_bernstein.c
new file mode 100644
index 00000000000..a34a0d5f947
--- /dev/null
+++ b/polly/lib/External/isl/isl_bernstein.c
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2006-2007 Universiteit Leiden
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
+ * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
+ * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
+ * B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_morph.h>
+#include <isl_factorization.h>
+#include <isl_vertices_private.h>
+#include <isl_polynomial_private.h>
+#include <isl_options_private.h>
+#include <isl_vec_private.h>
+#include <isl_bernstein.h>
+
+struct bernstein_data {
+ enum isl_fold type;
+ isl_qpolynomial *poly;
+ int check_tight;
+
+ isl_cell *cell;
+
+ isl_qpolynomial_fold *fold;
+ isl_qpolynomial_fold *fold_tight;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_pw_qpolynomial_fold *pwf_tight;
+};
+
+static int vertex_is_integral(__isl_keep isl_basic_set *vertex)
+{
+ unsigned nvar;
+ unsigned nparam;
+ int i;
+
+ nvar = isl_basic_set_dim(vertex, isl_dim_set);
+ nparam = isl_basic_set_dim(vertex, isl_dim_param);
+ for (i = 0; i < nvar; ++i) {
+ int r = nvar - 1 - i;
+ if (!isl_int_is_one(vertex->eq[r][1 + nparam + i]) &&
+ !isl_int_is_negone(vertex->eq[r][1 + nparam + i]))
+ return 0;
+ }
+
+ return 1;
+}
+
+static __isl_give isl_qpolynomial *vertex_coordinate(
+ __isl_keep isl_basic_set *vertex, int i, __isl_take isl_space *dim)
+{
+ unsigned nvar;
+ unsigned nparam;
+ int r;
+ isl_int denom;
+ isl_qpolynomial *v;
+
+ nvar = isl_basic_set_dim(vertex, isl_dim_set);
+ nparam = isl_basic_set_dim(vertex, isl_dim_param);
+ r = nvar - 1 - i;
+
+ isl_int_init(denom);
+ isl_int_set(denom, vertex->eq[r][1 + nparam + i]);
+ isl_assert(vertex->ctx, !isl_int_is_zero(denom), goto error);
+
+ if (isl_int_is_pos(denom))
+ isl_seq_neg(vertex->eq[r], vertex->eq[r],
+ 1 + isl_basic_set_total_dim(vertex));
+ else
+ isl_int_neg(denom, denom);
+
+ v = isl_qpolynomial_from_affine(dim, vertex->eq[r], denom);
+ isl_int_clear(denom);
+
+ return v;
+error:
+ isl_space_free(dim);
+ isl_int_clear(denom);
+ return NULL;
+}
+
+/* Check whether the bound associated to the selection "k" is tight,
+ * which is the case if we select exactly one vertex and if that vertex
+ * is integral for all values of the parameters.
+ */
+static int is_tight(int *k, int n, int d, isl_cell *cell)
+{
+ int i;
+
+ for (i = 0; i < n; ++i) {
+ int v;
+ if (k[i] != d) {
+ if (k[i])
+ return 0;
+ continue;
+ }
+ v = cell->ids[n - 1 - i];
+ return vertex_is_integral(cell->vertices->v[v].vertex);
+ }
+
+ return 0;
+}
+
+static void add_fold(__isl_take isl_qpolynomial *b, __isl_keep isl_set *dom,
+ int *k, int n, int d, struct bernstein_data *data)
+{
+ isl_qpolynomial_fold *fold;
+
+ fold = isl_qpolynomial_fold_alloc(data->type, b);
+
+ if (data->check_tight && is_tight(k, n, d, data->cell))
+ data->fold_tight = isl_qpolynomial_fold_fold_on_domain(dom,
+ data->fold_tight, fold);
+ else
+ data->fold = isl_qpolynomial_fold_fold_on_domain(dom,
+ data->fold, fold);
+}
+
+/* Extract the coefficients of the Bernstein base polynomials and store
+ * them in data->fold and data->fold_tight.
+ *
+ * In particular, the coefficient of each monomial
+ * of multi-degree (k[0], k[1], ..., k[n-1]) is divided by the corresponding
+ * multinomial coefficient d!/k[0]! k[1]! ... k[n-1]!
+ *
+ * c[i] contains the coefficient of the selected powers of the first i+1 vars.
+ * multinom[i] contains the partial multinomial coefficient.
+ */
+static void extract_coefficients(isl_qpolynomial *poly,
+ __isl_keep isl_set *dom, struct bernstein_data *data)
+{
+ int i;
+ int d;
+ int n;
+ isl_ctx *ctx;
+ isl_qpolynomial **c = NULL;
+ int *k = NULL;
+ int *left = NULL;
+ isl_vec *multinom = NULL;
+
+ if (!poly)
+ return;
+
+ ctx = isl_qpolynomial_get_ctx(poly);
+ n = isl_qpolynomial_dim(poly, isl_dim_in);
+ d = isl_qpolynomial_degree(poly);
+ isl_assert(ctx, n >= 2, return);
+
+ c = isl_calloc_array(ctx, isl_qpolynomial *, n);
+ k = isl_alloc_array(ctx, int, n);
+ left = isl_alloc_array(ctx, int, n);
+ multinom = isl_vec_alloc(ctx, n);
+ if (!c || !k || !left || !multinom)
+ goto error;
+
+ isl_int_set_si(multinom->el[0], 1);
+ for (k[0] = d; k[0] >= 0; --k[0]) {
+ int i = 1;
+ isl_qpolynomial_free(c[0]);
+ c[0] = isl_qpolynomial_coeff(poly, isl_dim_in, n - 1, k[0]);
+ left[0] = d - k[0];
+ k[1] = -1;
+ isl_int_set(multinom->el[1], multinom->el[0]);
+ while (i > 0) {
+ if (i == n - 1) {
+ int j;
+ isl_space *dim;
+ isl_qpolynomial *b;
+ isl_qpolynomial *f;
+ for (j = 2; j <= left[i - 1]; ++j)
+ isl_int_divexact_ui(multinom->el[i],
+ multinom->el[i], j);
+ b = isl_qpolynomial_coeff(c[i - 1], isl_dim_in,
+ n - 1 - i, left[i - 1]);
+ b = isl_qpolynomial_project_domain_on_params(b);
+ dim = isl_qpolynomial_get_domain_space(b);
+ f = isl_qpolynomial_rat_cst_on_domain(dim, ctx->one,
+ multinom->el[i]);
+ b = isl_qpolynomial_mul(b, f);
+ k[n - 1] = left[n - 2];
+ add_fold(b, dom, k, n, d, data);
+ --i;
+ continue;
+ }
+ if (k[i] >= left[i - 1]) {
+ --i;
+ continue;
+ }
+ ++k[i];
+ if (k[i])
+ isl_int_divexact_ui(multinom->el[i],
+ multinom->el[i], k[i]);
+ isl_qpolynomial_free(c[i]);
+ c[i] = isl_qpolynomial_coeff(c[i - 1], isl_dim_in,
+ n - 1 - i, k[i]);
+ left[i] = left[i - 1] - k[i];
+ k[i + 1] = -1;
+ isl_int_set(multinom->el[i + 1], multinom->el[i]);
+ ++i;
+ }
+ isl_int_mul_ui(multinom->el[0], multinom->el[0], k[0]);
+ }
+
+ for (i = 0; i < n; ++i)
+ isl_qpolynomial_free(c[i]);
+
+ isl_vec_free(multinom);
+ free(left);
+ free(k);
+ free(c);
+ return;
+error:
+ isl_vec_free(multinom);
+ free(left);
+ free(k);
+ if (c)
+ for (i = 0; i < n; ++i)
+ isl_qpolynomial_free(c[i]);
+ free(c);
+ return;
+}
+
+/* Perform bernstein expansion on the parametric vertices that are active
+ * on "cell".
+ *
+ * data->poly has been homogenized in the calling function.
+ *
+ * We plug in the barycentric coordinates for the set variables
+ *
+ * \vec x = \sum_i \alpha_i v_i(\vec p)
+ *
+ * and the constant "1 = \sum_i \alpha_i" for the homogeneous dimension.
+ * Next, we extract the coefficients of the Bernstein base polynomials.
+ */
+static int bernstein_coefficients_cell(__isl_take isl_cell *cell, void *user)
+{
+ int i, j;
+ struct bernstein_data *data = (struct bernstein_data *)user;
+ isl_space *dim_param;
+ isl_space *dim_dst;
+ isl_qpolynomial *poly = data->poly;
+ unsigned nvar;
+ int n_vertices;
+ isl_qpolynomial **subs;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_set *dom;
+ isl_ctx *ctx;
+
+ if (!poly)
+ goto error;
+
+ nvar = isl_qpolynomial_dim(poly, isl_dim_in) - 1;
+ n_vertices = cell->n_vertices;
+
+ ctx = isl_qpolynomial_get_ctx(poly);
+ if (n_vertices > nvar + 1 && ctx->opt->bernstein_triangulate)
+ return isl_cell_foreach_simplex(cell,
+ &bernstein_coefficients_cell, user);
+
+ subs = isl_alloc_array(ctx, isl_qpolynomial *, 1 + nvar);
+ if (!subs)
+ goto error;
+
+ dim_param = isl_basic_set_get_space(cell->dom);
+ dim_dst = isl_qpolynomial_get_domain_space(poly);
+ dim_dst = isl_space_add_dims(dim_dst, isl_dim_set, n_vertices);
+
+ for (i = 0; i < 1 + nvar; ++i)
+ subs[i] = isl_qpolynomial_zero_on_domain(isl_space_copy(dim_dst));
+
+ for (i = 0; i < n_vertices; ++i) {
+ isl_qpolynomial *c;
+ c = isl_qpolynomial_var_on_domain(isl_space_copy(dim_dst), isl_dim_set,
+ 1 + nvar + i);
+ for (j = 0; j < nvar; ++j) {
+ int k = cell->ids[i];
+ isl_qpolynomial *v;
+ v = vertex_coordinate(cell->vertices->v[k].vertex, j,
+ isl_space_copy(dim_param));
+ v = isl_qpolynomial_add_dims(v, isl_dim_in,
+ 1 + nvar + n_vertices);
+ v = isl_qpolynomial_mul(v, isl_qpolynomial_copy(c));
+ subs[1 + j] = isl_qpolynomial_add(subs[1 + j], v);
+ }
+ subs[0] = isl_qpolynomial_add(subs[0], c);
+ }
+ isl_space_free(dim_dst);
+
+ poly = isl_qpolynomial_copy(poly);
+
+ poly = isl_qpolynomial_add_dims(poly, isl_dim_in, n_vertices);
+ poly = isl_qpolynomial_substitute(poly, isl_dim_in, 0, 1 + nvar, subs);
+ poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, 0, 1 + nvar);
+
+ data->cell = cell;
+ dom = isl_set_from_basic_set(isl_basic_set_copy(cell->dom));
+ data->fold = isl_qpolynomial_fold_empty(data->type, isl_space_copy(dim_param));
+ data->fold_tight = isl_qpolynomial_fold_empty(data->type, dim_param);
+ extract_coefficients(poly, dom, data);
+
+ pwf = isl_pw_qpolynomial_fold_alloc(data->type, isl_set_copy(dom),
+ data->fold);
+ data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, pwf);
+ pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, data->fold_tight);
+ data->pwf_tight = isl_pw_qpolynomial_fold_fold(data->pwf_tight, pwf);
+
+ isl_qpolynomial_free(poly);
+ isl_cell_free(cell);
+ for (i = 0; i < 1 + nvar; ++i)
+ isl_qpolynomial_free(subs[i]);
+ free(subs);
+ return 0;
+error:
+ isl_cell_free(cell);
+ return -1;
+}
+
+/* Base case of applying bernstein expansion.
+ *
+ * We compute the chamber decomposition of the parametric polytope "bset"
+ * and then perform bernstein expansion on the parametric vertices
+ * that are active on each chamber.
+ */
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+ unsigned nvar;
+ isl_space *dim;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_vertices *vertices;
+ int covers;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ if (nvar == 0) {
+ isl_set *dom;
+ isl_qpolynomial_fold *fold;
+
+ fold = isl_qpolynomial_fold_alloc(data->type, poly);
+ dom = isl_set_from_basic_set(bset);
+ if (tight)
+ *tight = 1;
+ pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
+ return isl_pw_qpolynomial_fold_project_domain_on_params(pwf);
+ }
+
+ if (isl_qpolynomial_is_zero(poly)) {
+ isl_set *dom;
+ isl_qpolynomial_fold *fold;
+ fold = isl_qpolynomial_fold_alloc(data->type, poly);
+ dom = isl_set_from_basic_set(bset);
+ pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
+ if (tight)
+ *tight = 1;
+ return isl_pw_qpolynomial_fold_project_domain_on_params(pwf);
+ }
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_params(dim);
+ dim = isl_space_from_domain(dim);
+ dim = isl_space_add_dims(dim, isl_dim_set, 1);
+ data->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim), data->type);
+ data->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, data->type);
+ data->poly = isl_qpolynomial_homogenize(isl_qpolynomial_copy(poly));
+ vertices = isl_basic_set_compute_vertices(bset);
+ isl_vertices_foreach_disjoint_cell(vertices,
+ &bernstein_coefficients_cell, data);
+ isl_vertices_free(vertices);
+ isl_qpolynomial_free(data->poly);
+
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+
+ covers = isl_pw_qpolynomial_fold_covers(data->pwf_tight, data->pwf);
+ if (covers < 0)
+ goto error;
+
+ if (tight)
+ *tight = covers;
+
+ if (covers) {
+ isl_pw_qpolynomial_fold_free(data->pwf);
+ return data->pwf_tight;
+ }
+
+ data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, data->pwf_tight);
+
+ return data->pwf;
+error:
+ isl_pw_qpolynomial_fold_free(data->pwf_tight);
+ isl_pw_qpolynomial_fold_free(data->pwf);
+ return NULL;
+}
+
+/* Apply bernstein expansion recursively by working in on len[i]
+ * set variables at a time, with i ranging from n_group - 1 to 0.
+ */
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_recursive(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ int n_group, int *len, struct bernstein_data *data, int *tight)
+{
+ int i;
+ unsigned nparam;
+ unsigned nvar;
+ isl_pw_qpolynomial_fold *pwf;
+
+ if (!pwqp)
+ return NULL;
+
+ nparam = isl_pw_qpolynomial_dim(pwqp, isl_dim_param);
+ nvar = isl_pw_qpolynomial_dim(pwqp, isl_dim_in);
+
+ pwqp = isl_pw_qpolynomial_move_dims(pwqp, isl_dim_param, nparam,
+ isl_dim_in, 0, nvar - len[n_group - 1]);
+ pwf = isl_pw_qpolynomial_bound(pwqp, data->type, tight);
+
+ for (i = n_group - 2; i >= 0; --i) {
+ nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param);
+ pwf = isl_pw_qpolynomial_fold_move_dims(pwf, isl_dim_in, 0,
+ isl_dim_param, nparam - len[i], len[i]);
+ if (tight && !*tight)
+ tight = NULL;
+ pwf = isl_pw_qpolynomial_fold_bound(pwf, tight);
+ }
+
+ return pwf;
+}
+
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_factors(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+ isl_factorizer *f;
+ isl_set *set;
+ isl_pw_qpolynomial *pwqp;
+ isl_pw_qpolynomial_fold *pwf;
+
+ f = isl_basic_set_factorizer(bset);
+ if (!f)
+ goto error;
+ if (f->n_group == 0) {
+ isl_factorizer_free(f);
+ return bernstein_coefficients_base(bset, poly, data, tight);
+ }
+
+ set = isl_set_from_basic_set(bset);
+ pwqp = isl_pw_qpolynomial_alloc(set, poly);
+ pwqp = isl_pw_qpolynomial_morph_domain(pwqp, isl_morph_copy(f->morph));
+
+ pwf = bernstein_coefficients_recursive(pwqp, f->n_group, f->len, data,
+ tight);
+
+ isl_factorizer_free(f);
+
+ return pwf;
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ return NULL;
+}
+
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_full_recursive(
+ __isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+ int i;
+ int *len;
+ unsigned nvar;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_set *set;
+ isl_pw_qpolynomial *pwqp;
+
+ if (!bset || !poly)
+ goto error;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ len = isl_alloc_array(bset->ctx, int, nvar);
+ if (nvar && !len)
+ goto error;
+
+ for (i = 0; i < nvar; ++i)
+ len[i] = 1;
+
+ set = isl_set_from_basic_set(bset);
+ pwqp = isl_pw_qpolynomial_alloc(set, poly);
+
+ pwf = bernstein_coefficients_recursive(pwqp, nvar, len, data, tight);
+
+ free(len);
+
+ return pwf;
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ return NULL;
+}
+
+/* Compute a bound on the polynomial defined over the parametric polytope
+ * using bernstein expansion and store the result
+ * in bound->pwf and bound->pwf_tight.
+ *
+ * If bernstein_recurse is set to ISL_BERNSTEIN_FACTORS, we check if
+ * the polytope can be factorized and apply bernstein expansion recursively
+ * on the factors.
+ * If bernstein_recurse is set to ISL_BERNSTEIN_INTERVALS, we apply
+ * bernstein expansion recursively on each dimension.
+ * Otherwise, we apply bernstein expansion on the entire polytope.
+ */
+int isl_qpolynomial_bound_on_domain_bernstein(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct isl_bound *bound)
+{
+ struct bernstein_data data;
+ isl_pw_qpolynomial_fold *pwf;
+ unsigned nvar;
+ int tight = 0;
+ int *tp = bound->check_tight ? &tight : NULL;
+
+ if (!bset || !poly)
+ goto error;
+
+ data.type = bound->type;
+ data.check_tight = bound->check_tight;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ if (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_FACTORS)
+ pwf = bernstein_coefficients_factors(bset, poly, &data, tp);
+ else if (nvar > 1 &&
+ (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_INTERVALS))
+ pwf = bernstein_coefficients_full_recursive(bset, poly, &data, tp);
+ else
+ pwf = bernstein_coefficients_base(bset, poly, &data, tp);
+
+ if (tight)
+ bound->pwf_tight = isl_pw_qpolynomial_fold_fold(bound->pwf_tight, pwf);
+ else
+ bound->pwf = isl_pw_qpolynomial_fold_fold(bound->pwf, pwf);
+
+ return 0;
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_bernstein.h b/polly/lib/External/isl/isl_bernstein.h
new file mode 100644
index 00000000000..7694b04e566
--- /dev/null
+++ b/polly/lib/External/isl/isl_bernstein.h
@@ -0,0 +1,4 @@
+#include <isl_bound.h>
+
+int isl_qpolynomial_bound_on_domain_bernstein(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct isl_bound *bound);
diff --git a/polly/lib/External/isl/isl_blk.c b/polly/lib/External/isl/isl_blk.c
new file mode 100644
index 00000000000..d9f80dbb032
--- /dev/null
+++ b/polly/lib/External/isl/isl_blk.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_blk.h>
+#include <isl_ctx_private.h>
+
+/* The maximal number of cache misses before first element is evicted */
+#define ISL_BLK_MAX_MISS 100
+
+struct isl_blk isl_blk_empty()
+{
+ struct isl_blk block;
+ block.size = 0;
+ block.data = NULL;
+ return block;
+}
+
+static int isl_blk_is_empty(struct isl_blk block)
+{
+ return block.size == 0 && block.data == NULL;
+}
+
+static struct isl_blk isl_blk_error()
+{
+ struct isl_blk block;
+ block.size = -1;
+ block.data = NULL;
+ return block;
+}
+
+int isl_blk_is_error(struct isl_blk block)
+{
+ return block.size == -1 && block.data == NULL;
+}
+
+static struct isl_blk extend(struct isl_ctx *ctx, struct isl_blk block,
+ size_t new_n)
+{
+ int i;
+ isl_int *p;
+
+ if (block.size >= new_n)
+ return block;
+
+ p = block.data;
+ block.data = isl_realloc_array(ctx, block.data, isl_int, new_n);
+ if (!block.data) {
+ free(p);
+ return isl_blk_error();
+ }
+
+ for (i = block.size; i < new_n; ++i)
+ isl_int_init(block.data[i]);
+ block.size = new_n;
+
+ return block;
+}
+
+static void isl_blk_free_force(struct isl_ctx *ctx, struct isl_blk block)
+{
+ int i;
+
+ for (i = 0; i < block.size; ++i)
+ isl_int_clear(block.data[i]);
+ free(block.data);
+}
+
+struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n)
+{
+ int i;
+ struct isl_blk block;
+
+ block = isl_blk_empty();
+ if (n && ctx->n_cached) {
+ int best = 0;
+ for (i = 1; ctx->cache[best].size != n && i < ctx->n_cached; ++i) {
+ if (ctx->cache[best].size < n) {
+ if (ctx->cache[i].size > ctx->cache[best].size)
+ best = i;
+ } else if (ctx->cache[i].size >= n &&
+ ctx->cache[i].size < ctx->cache[best].size)
+ best = i;
+ }
+ if (ctx->cache[best].size < 2 * n + 100) {
+ block = ctx->cache[best];
+ if (--ctx->n_cached != best)
+ ctx->cache[best] = ctx->cache[ctx->n_cached];
+ if (best == 0)
+ ctx->n_miss = 0;
+ } else if (ctx->n_miss++ >= ISL_BLK_MAX_MISS) {
+ isl_blk_free_force(ctx, ctx->cache[0]);
+ if (--ctx->n_cached != 0)
+ ctx->cache[0] = ctx->cache[ctx->n_cached];
+ ctx->n_miss = 0;
+ }
+ }
+
+ return extend(ctx, block, n);
+}
+
+struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block,
+ size_t new_n)
+{
+ if (isl_blk_is_empty(block))
+ return isl_blk_alloc(ctx, new_n);
+
+ return extend(ctx, block, new_n);
+}
+
+void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block)
+{
+ if (isl_blk_is_empty(block) || isl_blk_is_error(block))
+ return;
+
+ if (ctx->n_cached < ISL_BLK_CACHE_SIZE)
+ ctx->cache[ctx->n_cached++] = block;
+ else
+ isl_blk_free_force(ctx, block);
+}
+
+void isl_blk_clear_cache(struct isl_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ctx->n_cached; ++i)
+ isl_blk_free_force(ctx, ctx->cache[i]);
+ ctx->n_cached = 0;
+}
diff --git a/polly/lib/External/isl/isl_blk.h b/polly/lib/External/isl/isl_blk.h
new file mode 100644
index 00000000000..7756e010ec2
--- /dev/null
+++ b/polly/lib/External/isl/isl_blk.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_BLK_H
+#define ISL_BLK_H
+
+#include <isl_int.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_blk {
+ size_t size;
+ isl_int *data;
+};
+
+#define ISL_BLK_CACHE_SIZE 20
+
+struct isl_ctx;
+
+struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n);
+struct isl_blk isl_blk_empty(void);
+int isl_blk_is_error(struct isl_blk block);
+struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block,
+ size_t new_n);
+void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block);
+void isl_blk_clear_cache(struct isl_ctx *ctx);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_bound.c b/polly/lib/External/isl/isl_bound.c
new file mode 100644
index 00000000000..04c76a0ffb2
--- /dev/null
+++ b/polly/lib/External/isl/isl_bound.c
@@ -0,0 +1,331 @@
+/*
+ * 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_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_bound.h>
+#include <isl_bernstein.h>
+#include <isl_range.h>
+#include <isl_polynomial_private.h>
+#include <isl_options_private.h>
+
+/* Compute a bound on the polynomial defined over the parametric polytope
+ * using either range propagation or bernstein expansion and
+ * store the result in bound->pwf and bound->pwf_tight.
+ * Since bernstein expansion requires bounded domains, we apply
+ * range propagation on unbounded domains. Otherwise, we respect the choice
+ * of the user.
+ */
+static int compressed_guarded_poly_bound(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+ int bounded;
+
+ if (!bset || !poly)
+ goto error;
+
+ if (bset->ctx->opt->bound == ISL_BOUND_RANGE)
+ return isl_qpolynomial_bound_on_domain_range(bset, poly, bound);
+
+ bounded = isl_basic_set_is_bounded(bset);
+ if (bounded < 0)
+ goto error;
+ if (bounded)
+ return isl_qpolynomial_bound_on_domain_bernstein(bset, poly, bound);
+ else
+ return isl_qpolynomial_bound_on_domain_range(bset, poly, bound);
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ return -1;
+}
+
+static int unwrapped_guarded_poly_bound(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+ isl_pw_qpolynomial_fold *top_pwf;
+ isl_pw_qpolynomial_fold *top_pwf_tight;
+ isl_space *dim;
+ isl_morph *morph;
+ int r;
+
+ bset = isl_basic_set_detect_equalities(bset);
+
+ if (!bset)
+ goto error;
+
+ if (bset->n_eq == 0)
+ return compressed_guarded_poly_bound(bset, poly, user);
+
+ morph = isl_basic_set_full_compression(bset);
+
+ bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+ poly = isl_qpolynomial_morph_domain(poly, isl_morph_copy(morph));
+
+ dim = isl_morph_get_ran_space(morph);
+ dim = isl_space_params(dim);
+
+ top_pwf = bound->pwf;
+ top_pwf_tight = bound->pwf_tight;
+
+ dim = isl_space_from_domain(dim);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ bound->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim),
+ bound->type);
+ bound->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, bound->type);
+
+ r = compressed_guarded_poly_bound(bset, poly, user);
+
+ morph = isl_morph_dom_params(morph);
+ morph = isl_morph_ran_params(morph);
+ morph = isl_morph_inverse(morph);
+
+ bound->pwf = isl_pw_qpolynomial_fold_morph_domain(bound->pwf,
+ isl_morph_copy(morph));
+ bound->pwf_tight = isl_pw_qpolynomial_fold_morph_domain(
+ bound->pwf_tight, morph);
+
+ bound->pwf = isl_pw_qpolynomial_fold_fold(top_pwf, bound->pwf);
+ bound->pwf_tight = isl_pw_qpolynomial_fold_fold(top_pwf_tight,
+ bound->pwf_tight);
+
+ return r;
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ return -1;
+}
+
+static int guarded_poly_bound(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+ isl_space *dim;
+ isl_pw_qpolynomial_fold *top_pwf;
+ isl_pw_qpolynomial_fold *top_pwf_tight;
+ int nparam;
+ int n_in;
+ int r;
+
+ if (!bound->wrapping)
+ return unwrapped_guarded_poly_bound(bset, poly, user);
+
+ nparam = isl_space_dim(bound->dim, isl_dim_param);
+ n_in = isl_space_dim(bound->dim, isl_dim_in);
+
+ bset = isl_basic_set_move_dims(bset, isl_dim_param, nparam,
+ isl_dim_set, 0, n_in);
+ poly = isl_qpolynomial_move_dims(poly, isl_dim_param, nparam,
+ isl_dim_in, 0, n_in);
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_params(dim);
+
+ top_pwf = bound->pwf;
+ top_pwf_tight = bound->pwf_tight;
+
+ dim = isl_space_from_domain(dim);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ bound->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim),
+ bound->type);
+ bound->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, bound->type);
+
+ r = unwrapped_guarded_poly_bound(bset, poly, user);
+
+ bound->pwf = isl_pw_qpolynomial_fold_reset_space(bound->pwf,
+ isl_space_copy(bound->dim));
+ bound->pwf_tight = isl_pw_qpolynomial_fold_reset_space(bound->pwf_tight,
+ isl_space_copy(bound->dim));
+
+ bound->pwf = isl_pw_qpolynomial_fold_fold(top_pwf, bound->pwf);
+ bound->pwf_tight = isl_pw_qpolynomial_fold_fold(top_pwf_tight,
+ bound->pwf_tight);
+
+ return r;
+}
+
+static int guarded_qp(__isl_take isl_qpolynomial *qp, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+ int r;
+
+ r = isl_qpolynomial_as_polynomial_on_domain(qp, bound->bset,
+ &guarded_poly_bound, user);
+ isl_qpolynomial_free(qp);
+ return r;
+}
+
+static int basic_guarded_fold(__isl_take isl_basic_set *bset, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+ int r;
+
+ bound->bset = bset;
+ r = isl_qpolynomial_fold_foreach_qpolynomial(bound->fold,
+ &guarded_qp, user);
+ isl_basic_set_free(bset);
+ return r;
+}
+
+static int guarded_fold(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold, void *user)
+{
+ struct isl_bound *bound = (struct isl_bound *)user;
+
+ if (!set || !fold)
+ goto error;
+
+ set = isl_set_make_disjoint(set);
+
+ bound->fold = fold;
+ bound->type = isl_qpolynomial_fold_get_type(fold);
+
+ if (isl_set_foreach_basic_set(set, &basic_guarded_fold, bound) < 0)
+ goto error;
+
+ isl_set_free(set);
+ isl_qpolynomial_fold_free(fold);
+
+ return 0;
+error:
+ isl_set_free(set);
+ isl_qpolynomial_fold_free(fold);
+ return -1;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
+ __isl_take isl_pw_qpolynomial_fold *pwf, int *tight)
+{
+ unsigned nvar;
+ struct isl_bound bound;
+ int covers;
+
+ if (!pwf)
+ return NULL;
+
+ bound.dim = isl_pw_qpolynomial_fold_get_domain_space(pwf);
+
+ bound.wrapping = isl_space_is_wrapping(bound.dim);
+ if (bound.wrapping)
+ bound.dim = isl_space_unwrap(bound.dim);
+ nvar = isl_space_dim(bound.dim, isl_dim_out);
+ bound.dim = isl_space_domain(bound.dim);
+ bound.dim = isl_space_from_domain(bound.dim);
+ bound.dim = isl_space_add_dims(bound.dim, isl_dim_out, 1);
+
+ if (nvar == 0) {
+ if (tight)
+ *tight = 1;
+ return isl_pw_qpolynomial_fold_reset_space(pwf, bound.dim);
+ }
+
+ if (isl_pw_qpolynomial_fold_is_zero(pwf)) {
+ enum isl_fold type = pwf->type;
+ isl_pw_qpolynomial_fold_free(pwf);
+ if (tight)
+ *tight = 1;
+ return isl_pw_qpolynomial_fold_zero(bound.dim, type);
+ }
+
+ bound.pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(bound.dim),
+ pwf->type);
+ bound.pwf_tight = isl_pw_qpolynomial_fold_zero(isl_space_copy(bound.dim),
+ pwf->type);
+ bound.check_tight = !!tight;
+
+ if (isl_pw_qpolynomial_fold_foreach_lifted_piece(pwf,
+ guarded_fold, &bound) < 0)
+ goto error;
+
+ covers = isl_pw_qpolynomial_fold_covers(bound.pwf_tight, bound.pwf);
+ if (covers < 0)
+ goto error;
+
+ if (tight)
+ *tight = covers;
+
+ isl_space_free(bound.dim);
+ isl_pw_qpolynomial_fold_free(pwf);
+
+ if (covers) {
+ isl_pw_qpolynomial_fold_free(bound.pwf);
+ return bound.pwf_tight;
+ }
+
+ bound.pwf = isl_pw_qpolynomial_fold_fold(bound.pwf, bound.pwf_tight);
+
+ return bound.pwf;
+error:
+ isl_pw_qpolynomial_fold_free(bound.pwf_tight);
+ isl_pw_qpolynomial_fold_free(bound.pwf);
+ isl_pw_qpolynomial_fold_free(pwf);
+ isl_space_free(bound.dim);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
+ __isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type, int *tight)
+{
+ isl_pw_qpolynomial_fold *pwf;
+
+ pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(type, pwqp);
+ return isl_pw_qpolynomial_fold_bound(pwf, tight);
+}
+
+struct isl_union_bound_data {
+ enum isl_fold type;
+ int tight;
+ isl_union_pw_qpolynomial_fold *res;
+};
+
+static int bound_pw(__isl_take isl_pw_qpolynomial *pwqp, void *user)
+{
+ struct isl_union_bound_data *data = user;
+ isl_pw_qpolynomial_fold *pwf;
+
+ pwf = isl_pw_qpolynomial_bound(pwqp, data->type,
+ data->tight ? &data->tight : NULL);
+ data->res = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+ data->res, pwf);
+
+ return 0;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_bound(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_fold type, int *tight)
+{
+ isl_space *dim;
+ struct isl_union_bound_data data = { type, 1, NULL };
+
+ if (!upwqp)
+ return NULL;
+
+ if (!tight)
+ data.tight = 0;
+
+ dim = isl_union_pw_qpolynomial_get_space(upwqp);
+ data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);
+ if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp,
+ &bound_pw, &data) < 0)
+ goto error;
+
+ isl_union_pw_qpolynomial_free(upwqp);
+ if (tight)
+ *tight = data.tight;
+
+ return data.res;
+error:
+ isl_union_pw_qpolynomial_free(upwqp);
+ isl_union_pw_qpolynomial_fold_free(data.res);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_bound.h b/polly/lib/External/isl/isl_bound.h
new file mode 100644
index 00000000000..1a9d390eab9
--- /dev/null
+++ b/polly/lib/External/isl/isl_bound.h
@@ -0,0 +1,20 @@
+#ifndef ISL_BOUND_H
+#define ISL_BOUND_H
+
+#include <isl/polynomial.h>
+
+struct isl_bound {
+ /* input */
+ int check_tight;
+ int wrapping;
+ enum isl_fold type;
+ isl_space *dim;
+ isl_basic_set *bset;
+ isl_qpolynomial_fold *fold;
+
+ /* output */
+ isl_pw_qpolynomial_fold *pwf;
+ isl_pw_qpolynomial_fold *pwf_tight;
+};
+
+#endif
diff --git a/polly/lib/External/isl/isl_coalesce.c b/polly/lib/External/isl/isl_coalesce.c
new file mode 100644
index 00000000000..2899e03b2d3
--- /dev/null
+++ b/polly/lib/External/isl/isl_coalesce.c
@@ -0,0 +1,1745 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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_map_private.h"
+#include <isl_seq.h>
+#include <isl/options.h>
+#include "isl_tab.h"
+#include <isl_mat_private.h>
+#include <isl_local_space_private.h>
+#include <isl_vec_private.h>
+
+#define STATUS_ERROR -1
+#define STATUS_REDUNDANT 1
+#define STATUS_VALID 2
+#define STATUS_SEPARATE 3
+#define STATUS_CUT 4
+#define STATUS_ADJ_EQ 5
+#define STATUS_ADJ_INEQ 6
+
+static int status_in(isl_int *ineq, struct isl_tab *tab)
+{
+ enum isl_ineq_type type = isl_tab_ineq_type(tab, ineq);
+ switch (type) {
+ default:
+ case isl_ineq_error: return STATUS_ERROR;
+ case isl_ineq_redundant: return STATUS_VALID;
+ case isl_ineq_separate: return STATUS_SEPARATE;
+ case isl_ineq_cut: return STATUS_CUT;
+ case isl_ineq_adj_eq: return STATUS_ADJ_EQ;
+ case isl_ineq_adj_ineq: return STATUS_ADJ_INEQ;
+ }
+}
+
+/* Compute the position of the equalities of basic map "bmap_i"
+ * with respect to the basic map represented by "tab_j".
+ * The resulting array has twice as many entries as the number
+ * of equalities corresponding to the two inequalties to which
+ * each equality corresponds.
+ */
+static int *eq_status_in(__isl_keep isl_basic_map *bmap_i,
+ struct isl_tab *tab_j)
+{
+ int k, l;
+ int *eq = isl_calloc_array(bmap_i->ctx, int, 2 * bmap_i->n_eq);
+ unsigned dim;
+
+ if (!eq)
+ return NULL;
+
+ dim = isl_basic_map_total_dim(bmap_i);
+ for (k = 0; k < bmap_i->n_eq; ++k) {
+ for (l = 0; l < 2; ++l) {
+ isl_seq_neg(bmap_i->eq[k], bmap_i->eq[k], 1+dim);
+ eq[2 * k + l] = status_in(bmap_i->eq[k], tab_j);
+ if (eq[2 * k + l] == STATUS_ERROR)
+ goto error;
+ }
+ if (eq[2 * k] == STATUS_SEPARATE ||
+ eq[2 * k + 1] == STATUS_SEPARATE)
+ break;
+ }
+
+ return eq;
+error:
+ free(eq);
+ return NULL;
+}
+
+/* Compute the position of the inequalities of basic map "bmap_i"
+ * (also represented by "tab_i", if not NULL) with respect to the basic map
+ * represented by "tab_j".
+ */
+static int *ineq_status_in(__isl_keep isl_basic_map *bmap_i,
+ struct isl_tab *tab_i, struct isl_tab *tab_j)
+{
+ int k;
+ unsigned n_eq = bmap_i->n_eq;
+ int *ineq = isl_calloc_array(bmap_i->ctx, int, bmap_i->n_ineq);
+
+ if (!ineq)
+ return NULL;
+
+ for (k = 0; k < bmap_i->n_ineq; ++k) {
+ if (tab_i && isl_tab_is_redundant(tab_i, n_eq + k)) {
+ ineq[k] = STATUS_REDUNDANT;
+ continue;
+ }
+ ineq[k] = status_in(bmap_i->ineq[k], tab_j);
+ if (ineq[k] == STATUS_ERROR)
+ goto error;
+ if (ineq[k] == STATUS_SEPARATE)
+ break;
+ }
+
+ return ineq;
+error:
+ free(ineq);
+ return NULL;
+}
+
+static int any(int *con, unsigned len, int status)
+{
+ int i;
+
+ for (i = 0; i < len ; ++i)
+ if (con[i] == status)
+ return 1;
+ return 0;
+}
+
+static int count(int *con, unsigned len, int status)
+{
+ int i;
+ int c = 0;
+
+ for (i = 0; i < len ; ++i)
+ if (con[i] == status)
+ c++;
+ return c;
+}
+
+static int all(int *con, unsigned len, int status)
+{
+ int i;
+
+ for (i = 0; i < len ; ++i) {
+ if (con[i] == STATUS_REDUNDANT)
+ continue;
+ if (con[i] != status)
+ return 0;
+ }
+ return 1;
+}
+
+static void drop(struct isl_map *map, int i, struct isl_tab **tabs)
+{
+ isl_basic_map_free(map->p[i]);
+ isl_tab_free(tabs[i]);
+
+ if (i != map->n - 1) {
+ map->p[i] = map->p[map->n - 1];
+ tabs[i] = tabs[map->n - 1];
+ }
+ tabs[map->n - 1] = NULL;
+ map->n--;
+}
+
+/* Replace the pair of basic maps i and j by the basic map bounded
+ * by the valid constraints in both basic maps and the constraint
+ * in extra (if not NULL).
+ */
+static int fuse(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j,
+ __isl_keep isl_mat *extra)
+{
+ int k, l;
+ struct isl_basic_map *fused = NULL;
+ struct isl_tab *fused_tab = NULL;
+ unsigned total = isl_basic_map_total_dim(map->p[i]);
+ unsigned extra_rows = extra ? extra->n_row : 0;
+
+ fused = isl_basic_map_alloc_space(isl_space_copy(map->p[i]->dim),
+ map->p[i]->n_div,
+ map->p[i]->n_eq + map->p[j]->n_eq,
+ map->p[i]->n_ineq + map->p[j]->n_ineq + extra_rows);
+ if (!fused)
+ goto error;
+
+ for (k = 0; k < map->p[i]->n_eq; ++k) {
+ if (eq_i && (eq_i[2 * k] != STATUS_VALID ||
+ eq_i[2 * k + 1] != STATUS_VALID))
+ continue;
+ l = isl_basic_map_alloc_equality(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->eq[l], map->p[i]->eq[k], 1 + total);
+ }
+
+ for (k = 0; k < map->p[j]->n_eq; ++k) {
+ if (eq_j && (eq_j[2 * k] != STATUS_VALID ||
+ eq_j[2 * k + 1] != STATUS_VALID))
+ continue;
+ l = isl_basic_map_alloc_equality(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->eq[l], map->p[j]->eq[k], 1 + total);
+ }
+
+ for (k = 0; k < map->p[i]->n_ineq; ++k) {
+ if (ineq_i[k] != STATUS_VALID)
+ continue;
+ l = isl_basic_map_alloc_inequality(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->ineq[l], map->p[i]->ineq[k], 1 + total);
+ }
+
+ for (k = 0; k < map->p[j]->n_ineq; ++k) {
+ if (ineq_j[k] != STATUS_VALID)
+ continue;
+ l = isl_basic_map_alloc_inequality(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->ineq[l], map->p[j]->ineq[k], 1 + total);
+ }
+
+ for (k = 0; k < map->p[i]->n_div; ++k) {
+ int l = isl_basic_map_alloc_div(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->div[l], map->p[i]->div[k], 1 + 1 + total);
+ }
+
+ for (k = 0; k < extra_rows; ++k) {
+ l = isl_basic_map_alloc_inequality(fused);
+ if (l < 0)
+ goto error;
+ isl_seq_cpy(fused->ineq[l], extra->row[k], 1 + total);
+ }
+
+ fused = isl_basic_map_gauss(fused, NULL);
+ ISL_F_SET(fused, ISL_BASIC_MAP_FINAL);
+ if (ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_RATIONAL) &&
+ ISL_F_ISSET(map->p[j], ISL_BASIC_MAP_RATIONAL))
+ ISL_F_SET(fused, ISL_BASIC_MAP_RATIONAL);
+
+ fused_tab = isl_tab_from_basic_map(fused, 0);
+ if (isl_tab_detect_redundant(fused_tab) < 0)
+ goto error;
+
+ isl_basic_map_free(map->p[i]);
+ map->p[i] = fused;
+ isl_tab_free(tabs[i]);
+ tabs[i] = fused_tab;
+ drop(map, j, tabs);
+
+ return 1;
+error:
+ isl_tab_free(fused_tab);
+ isl_basic_map_free(fused);
+ return -1;
+}
+
+/* Given a pair of basic maps i and j such that all constraints are either
+ * "valid" or "cut", check if the facets corresponding to the "cut"
+ * constraints of i lie entirely within basic map j.
+ * If so, replace the pair by the basic map consisting of the valid
+ * constraints in both basic maps.
+ *
+ * To see that we are not introducing any extra points, call the
+ * two basic maps A and B and the resulting map U and let x
+ * be an element of U \setminus ( A \cup B ).
+ * Then there is a pair of cut constraints c_1 and c_2 in A and B such that x
+ * violates them. Let X be the intersection of U with the opposites
+ * of these constraints. Then x \in X.
+ * The facet corresponding to c_1 contains the corresponding facet of A.
+ * This facet is entirely contained in B, so c_2 is valid on the facet.
+ * However, since it is also (part of) a facet of X, -c_2 is also valid
+ * on the facet. This means c_2 is saturated on the facet, so c_1 and
+ * c_2 must be opposites of each other, but then x could not violate
+ * both of them.
+ */
+static int check_facets(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *ineq_i, int *ineq_j)
+{
+ int k, l;
+ struct isl_tab_undo *snap;
+ unsigned n_eq = map->p[i]->n_eq;
+
+ snap = isl_tab_snap(tabs[i]);
+
+ for (k = 0; k < map->p[i]->n_ineq; ++k) {
+ if (ineq_i[k] != STATUS_CUT)
+ continue;
+ if (isl_tab_select_facet(tabs[i], n_eq + k) < 0)
+ return -1;
+ for (l = 0; l < map->p[j]->n_ineq; ++l) {
+ int stat;
+ if (ineq_j[l] != STATUS_CUT)
+ continue;
+ stat = status_in(map->p[j]->ineq[l], tabs[i]);
+ if (stat != STATUS_VALID)
+ break;
+ }
+ if (isl_tab_rollback(tabs[i], snap) < 0)
+ return -1;
+ if (l < map->p[j]->n_ineq)
+ break;
+ }
+
+ if (k < map->p[i]->n_ineq)
+ /* BAD CUT PAIR */
+ return 0;
+ return fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL);
+}
+
+/* Check if basic map "i" contains the basic map represented
+ * by the tableau "tab".
+ */
+static int contains(struct isl_map *map, int i, int *ineq_i,
+ struct isl_tab *tab)
+{
+ int k, l;
+ unsigned dim;
+
+ dim = isl_basic_map_total_dim(map->p[i]);
+ for (k = 0; k < map->p[i]->n_eq; ++k) {
+ for (l = 0; l < 2; ++l) {
+ int stat;
+ isl_seq_neg(map->p[i]->eq[k], map->p[i]->eq[k], 1+dim);
+ stat = status_in(map->p[i]->eq[k], tab);
+ if (stat != STATUS_VALID)
+ return 0;
+ }
+ }
+
+ for (k = 0; k < map->p[i]->n_ineq; ++k) {
+ int stat;
+ if (ineq_i[k] == STATUS_REDUNDANT)
+ continue;
+ stat = status_in(map->p[i]->ineq[k], tab);
+ if (stat != STATUS_VALID)
+ return 0;
+ }
+ return 1;
+}
+
+/* Basic map "i" has an inequality (say "k") that is adjacent
+ * to some inequality of basic map "j". All the other inequalities
+ * are valid for "j".
+ * Check if basic map "j" forms an extension of basic map "i".
+ *
+ * Note that this function is only called if some of the equalities or
+ * inequalities of basic map "j" do cut basic map "i". The function is
+ * correct even if there are no such cut constraints, but in that case
+ * the additional checks performed by this function are overkill.
+ *
+ * In particular, we replace constraint k, say f >= 0, by constraint
+ * f <= -1, add the inequalities of "j" that are valid for "i"
+ * and check if the result is a subset of basic map "j".
+ * If so, then we know that this result is exactly equal to basic map "j"
+ * since all its constraints are valid for basic map "j".
+ * By combining the valid constraints of "i" (all equalities and all
+ * inequalities except "k") and the valid constraints of "j" we therefore
+ * obtain a basic map that is equal to their union.
+ * In this case, there is no need to perform a rollback of the tableau
+ * since it is going to be destroyed in fuse().
+ *
+ *
+ * |\__ |\__
+ * | \__ | \__
+ * | \_ => | \__
+ * |_______| _ |_________\
+ *
+ *
+ * |\ |\
+ * | \ | \
+ * | \ | \
+ * | | | \
+ * | ||\ => | \
+ * | || \ | \
+ * | || | | |
+ * |__||_/ |_____/
+ */
+static int is_adj_ineq_extension(__isl_keep isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int k;
+ struct isl_tab_undo *snap;
+ unsigned n_eq = map->p[i]->n_eq;
+ unsigned total = isl_basic_map_total_dim(map->p[i]);
+ int r;
+
+ if (isl_tab_extend_cons(tabs[i], 1 + map->p[j]->n_ineq) < 0)
+ return -1;
+
+ for (k = 0; k < map->p[i]->n_ineq; ++k)
+ if (ineq_i[k] == STATUS_ADJ_INEQ)
+ break;
+ if (k >= map->p[i]->n_ineq)
+ isl_die(isl_map_get_ctx(map), isl_error_internal,
+ "ineq_i should have exactly one STATUS_ADJ_INEQ",
+ return -1);
+
+ snap = isl_tab_snap(tabs[i]);
+
+ if (isl_tab_unrestrict(tabs[i], n_eq + k) < 0)
+ return -1;
+
+ isl_seq_neg(map->p[i]->ineq[k], map->p[i]->ineq[k], 1 + total);
+ isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ r = isl_tab_add_ineq(tabs[i], map->p[i]->ineq[k]);
+ isl_seq_neg(map->p[i]->ineq[k], map->p[i]->ineq[k], 1 + total);
+ isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ if (r < 0)
+ return -1;
+
+ for (k = 0; k < map->p[j]->n_ineq; ++k) {
+ if (ineq_j[k] != STATUS_VALID)
+ continue;
+ if (isl_tab_add_ineq(tabs[i], map->p[j]->ineq[k]) < 0)
+ return -1;
+ }
+
+ if (contains(map, j, ineq_j, tabs[i]))
+ return fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, NULL);
+
+ if (isl_tab_rollback(tabs[i], snap) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+/* Both basic maps have at least one inequality with and adjacent
+ * (but opposite) inequality in the other basic map.
+ * Check that there are no cut constraints and that there is only
+ * a single pair of adjacent inequalities.
+ * If so, we can replace the pair by a single basic map described
+ * by all but the pair of adjacent inequalities.
+ * Any additional points introduced lie strictly between the two
+ * adjacent hyperplanes and can therefore be integral.
+ *
+ * ____ _____
+ * / ||\ / \
+ * / || \ / \
+ * \ || \ => \ \
+ * \ || / \ /
+ * \___||_/ \_____/
+ *
+ * The test for a single pair of adjancent inequalities is important
+ * for avoiding the combination of two basic maps like the following
+ *
+ * /|
+ * / |
+ * /__|
+ * _____
+ * | |
+ * | |
+ * |___|
+ *
+ * If there are some cut constraints on one side, then we may
+ * still be able to fuse the two basic maps, but we need to perform
+ * some additional checks in is_adj_ineq_extension.
+ */
+static int check_adj_ineq(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int count_i, count_j;
+ int cut_i, cut_j;
+
+ count_i = count(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ);
+ count_j = count(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ);
+
+ if (count_i != 1 && count_j != 1)
+ return 0;
+
+ cut_i = any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT) ||
+ any(ineq_i, map->p[i]->n_ineq, STATUS_CUT);
+ cut_j = any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT) ||
+ any(ineq_j, map->p[j]->n_ineq, STATUS_CUT);
+
+ if (!cut_i && !cut_j && count_i == 1 && count_j == 1)
+ return fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL);
+
+ if (count_i == 1 && !cut_i)
+ return is_adj_ineq_extension(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+
+ if (count_j == 1 && !cut_j)
+ return is_adj_ineq_extension(map, j, i, tabs,
+ eq_j, ineq_j, eq_i, ineq_i);
+
+ return 0;
+}
+
+/* Basic map "i" has an inequality "k" that is adjacent to some equality
+ * of basic map "j". All the other inequalities are valid for "j".
+ * Check if basic map "j" forms an extension of basic map "i".
+ *
+ * In particular, we relax constraint "k", compute the corresponding
+ * facet and check whether it is included in the other basic map.
+ * If so, we know that relaxing the constraint extends the basic
+ * map with exactly the other basic map (we already know that this
+ * other basic map is included in the extension, because there
+ * were no "cut" inequalities in "i") and we can replace the
+ * two basic maps by this extension.
+ * ____ _____
+ * / || / |
+ * / || / |
+ * \ || => \ |
+ * \ || \ |
+ * \___|| \____|
+ */
+static int is_adj_eq_extension(struct isl_map *map, int i, int j, int k,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+ int super;
+ struct isl_tab_undo *snap, *snap2;
+ unsigned n_eq = map->p[i]->n_eq;
+
+ if (isl_tab_is_equality(tabs[i], n_eq + k))
+ return 0;
+
+ snap = isl_tab_snap(tabs[i]);
+ tabs[i] = isl_tab_relax(tabs[i], n_eq + k);
+ snap2 = isl_tab_snap(tabs[i]);
+ if (isl_tab_select_facet(tabs[i], n_eq + k) < 0)
+ return -1;
+ super = contains(map, j, ineq_j, tabs[i]);
+ if (super) {
+ if (isl_tab_rollback(tabs[i], snap2) < 0)
+ return -1;
+ map->p[i] = isl_basic_map_cow(map->p[i]);
+ if (!map->p[i])
+ return -1;
+ isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ ISL_F_SET(map->p[i], ISL_BASIC_MAP_FINAL);
+ drop(map, j, tabs);
+ changed = 1;
+ } else
+ if (isl_tab_rollback(tabs[i], snap) < 0)
+ return -1;
+
+ return changed;
+}
+
+/* Data structure that keeps track of the wrapping constraints
+ * and of information to bound the coefficients of those constraints.
+ *
+ * bound is set if we want to apply a bound on the coefficients
+ * mat contains the wrapping constraints
+ * max is the bound on the coefficients (if bound is set)
+ */
+struct isl_wraps {
+ int bound;
+ isl_mat *mat;
+ isl_int max;
+};
+
+/* Update wraps->max to be greater than or equal to the coefficients
+ * in the equalities and inequalities of bmap that can be removed if we end up
+ * applying wrapping.
+ */
+static void wraps_update_max(struct isl_wraps *wraps,
+ __isl_keep isl_basic_map *bmap, int *eq, int *ineq)
+{
+ int k;
+ isl_int max_k;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ isl_int_init(max_k);
+
+ for (k = 0; k < bmap->n_eq; ++k) {
+ if (eq[2 * k] == STATUS_VALID &&
+ eq[2 * k + 1] == STATUS_VALID)
+ continue;
+ isl_seq_abs_max(bmap->eq[k] + 1, total, &max_k);
+ if (isl_int_abs_gt(max_k, wraps->max))
+ isl_int_set(wraps->max, max_k);
+ }
+
+ for (k = 0; k < bmap->n_ineq; ++k) {
+ if (ineq[k] == STATUS_VALID || ineq[k] == STATUS_REDUNDANT)
+ continue;
+ isl_seq_abs_max(bmap->ineq[k] + 1, total, &max_k);
+ if (isl_int_abs_gt(max_k, wraps->max))
+ isl_int_set(wraps->max, max_k);
+ }
+
+ isl_int_clear(max_k);
+}
+
+/* Initialize the isl_wraps data structure.
+ * If we want to bound the coefficients of the wrapping constraints,
+ * we set wraps->max to the largest coefficient
+ * in the equalities and inequalities that can be removed if we end up
+ * applying wrapping.
+ */
+static void wraps_init(struct isl_wraps *wraps, __isl_take isl_mat *mat,
+ __isl_keep isl_map *map, int i, int j,
+ int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ isl_ctx *ctx;
+
+ wraps->bound = 0;
+ wraps->mat = mat;
+ if (!mat)
+ return;
+ ctx = isl_mat_get_ctx(mat);
+ wraps->bound = isl_options_get_coalesce_bounded_wrapping(ctx);
+ if (!wraps->bound)
+ return;
+ isl_int_init(wraps->max);
+ isl_int_set_si(wraps->max, 0);
+ wraps_update_max(wraps, map->p[i], eq_i, ineq_i);
+ wraps_update_max(wraps, map->p[j], eq_j, ineq_j);
+}
+
+/* Free the contents of the isl_wraps data structure.
+ */
+static void wraps_free(struct isl_wraps *wraps)
+{
+ isl_mat_free(wraps->mat);
+ if (wraps->bound)
+ isl_int_clear(wraps->max);
+}
+
+/* Is the wrapping constraint in row "row" allowed?
+ *
+ * If wraps->bound is set, we check that none of the coefficients
+ * is greater than wraps->max.
+ */
+static int allow_wrap(struct isl_wraps *wraps, int row)
+{
+ int i;
+
+ if (!wraps->bound)
+ return 1;
+
+ for (i = 1; i < wraps->mat->n_col; ++i)
+ if (isl_int_abs_gt(wraps->mat->row[row][i], wraps->max))
+ return 0;
+
+ return 1;
+}
+
+/* For each non-redundant constraint in "bmap" (as determined by "tab"),
+ * wrap the constraint around "bound" such that it includes the whole
+ * set "set" and append the resulting constraint to "wraps".
+ * "wraps" is assumed to have been pre-allocated to the appropriate size.
+ * wraps->n_row is the number of actual wrapped constraints that have
+ * been added.
+ * If any of the wrapping problems results in a constraint that is
+ * identical to "bound", then this means that "set" is unbounded in such
+ * way that no wrapping is possible. If this happens then wraps->n_row
+ * is reset to zero.
+ * Similarly, if we want to bound the coefficients of the wrapping
+ * constraints and a newly added wrapping constraint does not
+ * satisfy the bound, then wraps->n_row is also reset to zero.
+ */
+static int add_wraps(struct isl_wraps *wraps, __isl_keep isl_basic_map *bmap,
+ struct isl_tab *tab, isl_int *bound, __isl_keep isl_set *set)
+{
+ int l;
+ int w;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ w = wraps->mat->n_row;
+
+ for (l = 0; l < bmap->n_ineq; ++l) {
+ if (isl_seq_is_neg(bound, bmap->ineq[l], 1 + total))
+ continue;
+ if (isl_seq_eq(bound, bmap->ineq[l], 1 + total))
+ continue;
+ if (isl_tab_is_redundant(tab, bmap->n_eq + l))
+ continue;
+
+ isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
+ if (!isl_set_wrap_facet(set, wraps->mat->row[w], bmap->ineq[l]))
+ return -1;
+ if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
+ goto unbounded;
+ if (!allow_wrap(wraps, w))
+ goto unbounded;
+ ++w;
+ }
+ for (l = 0; l < bmap->n_eq; ++l) {
+ if (isl_seq_is_neg(bound, bmap->eq[l], 1 + total))
+ continue;
+ if (isl_seq_eq(bound, bmap->eq[l], 1 + total))
+ continue;
+
+ isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
+ isl_seq_neg(wraps->mat->row[w + 1], bmap->eq[l], 1 + total);
+ if (!isl_set_wrap_facet(set, wraps->mat->row[w],
+ wraps->mat->row[w + 1]))
+ return -1;
+ if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
+ goto unbounded;
+ if (!allow_wrap(wraps, w))
+ goto unbounded;
+ ++w;
+
+ isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
+ if (!isl_set_wrap_facet(set, wraps->mat->row[w], bmap->eq[l]))
+ return -1;
+ if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
+ goto unbounded;
+ if (!allow_wrap(wraps, w))
+ goto unbounded;
+ ++w;
+ }
+
+ wraps->mat->n_row = w;
+ return 0;
+unbounded:
+ wraps->mat->n_row = 0;
+ return 0;
+}
+
+/* Check if the constraints in "wraps" from "first" until the last
+ * are all valid for the basic set represented by "tab".
+ * If not, wraps->n_row is set to zero.
+ */
+static int check_wraps(__isl_keep isl_mat *wraps, int first,
+ struct isl_tab *tab)
+{
+ int i;
+
+ for (i = first; i < wraps->n_row; ++i) {
+ enum isl_ineq_type type;
+ type = isl_tab_ineq_type(tab, wraps->row[i]);
+ if (type == isl_ineq_error)
+ return -1;
+ if (type == isl_ineq_redundant)
+ continue;
+ wraps->n_row = 0;
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Return a set that corresponds to the non-redudant constraints
+ * (as recorded in tab) of bmap.
+ *
+ * It's important to remove the redundant constraints as some
+ * of the other constraints may have been modified after the
+ * constraints were marked redundant.
+ * In particular, a constraint may have been relaxed.
+ * Redundant constraints are ignored when a constraint is relaxed
+ * and should therefore continue to be ignored ever after.
+ * Otherwise, the relaxation might be thwarted by some of
+ * these constraints.
+ */
+static __isl_give isl_set *set_from_updated_bmap(__isl_keep isl_basic_map *bmap,
+ struct isl_tab *tab)
+{
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_update_from_tab(bmap, tab);
+ return isl_set_from_basic_set(isl_basic_map_underlying_set(bmap));
+}
+
+/* Given a basic set i with a constraint k that is adjacent to either the
+ * whole of basic set j or a facet of basic set j, check if we can wrap
+ * both the facet corresponding to k and the facet of j (or the whole of j)
+ * around their ridges to include the other set.
+ * If so, replace the pair of basic sets by their union.
+ *
+ * All constraints of i (except k) are assumed to be valid for j.
+ *
+ * However, the constraints of j may not be valid for i and so
+ * we have to check that the wrapping constraints for j are valid for i.
+ *
+ * In the case where j has a facet adjacent to i, tab[j] is assumed
+ * to have been restricted to this facet, so that the non-redundant
+ * constraints in tab[j] are the ridges of the facet.
+ * Note that for the purpose of wrapping, it does not matter whether
+ * we wrap the ridges of i around the whole of j or just around
+ * the facet since all the other constraints are assumed to be valid for j.
+ * In practice, we wrap to include the whole of j.
+ * ____ _____
+ * / | / \
+ * / || / |
+ * \ || => \ |
+ * \ || \ |
+ * \___|| \____|
+ *
+ */
+static int can_wrap_in_facet(struct isl_map *map, int i, int j, int k,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+ struct isl_wraps wraps;
+ isl_mat *mat;
+ struct isl_set *set_i = NULL;
+ struct isl_set *set_j = NULL;
+ struct isl_vec *bound = NULL;
+ unsigned total = isl_basic_map_total_dim(map->p[i]);
+ struct isl_tab_undo *snap;
+ int n;
+
+ set_i = set_from_updated_bmap(map->p[i], tabs[i]);
+ set_j = set_from_updated_bmap(map->p[j], tabs[j]);
+ mat = isl_mat_alloc(map->ctx, 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
+ map->p[i]->n_ineq + map->p[j]->n_ineq,
+ 1 + total);
+ wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
+ bound = isl_vec_alloc(map->ctx, 1 + total);
+ if (!set_i || !set_j || !wraps.mat || !bound)
+ goto error;
+
+ isl_seq_cpy(bound->el, map->p[i]->ineq[k], 1 + total);
+ isl_int_add_ui(bound->el[0], bound->el[0], 1);
+
+ isl_seq_cpy(wraps.mat->row[0], bound->el, 1 + total);
+ wraps.mat->n_row = 1;
+
+ if (add_wraps(&wraps, map->p[j], tabs[j], bound->el, set_i) < 0)
+ goto error;
+ if (!wraps.mat->n_row)
+ goto unbounded;
+
+ snap = isl_tab_snap(tabs[i]);
+
+ if (isl_tab_select_facet(tabs[i], map->p[i]->n_eq + k) < 0)
+ goto error;
+ if (isl_tab_detect_redundant(tabs[i]) < 0)
+ goto error;
+
+ isl_seq_neg(bound->el, map->p[i]->ineq[k], 1 + total);
+
+ n = wraps.mat->n_row;
+ if (add_wraps(&wraps, map->p[i], tabs[i], bound->el, set_j) < 0)
+ goto error;
+
+ if (isl_tab_rollback(tabs[i], snap) < 0)
+ goto error;
+ if (check_wraps(wraps.mat, n, tabs[i]) < 0)
+ goto error;
+ if (!wraps.mat->n_row)
+ goto unbounded;
+
+ changed = fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+
+unbounded:
+ wraps_free(&wraps);
+
+ isl_set_free(set_i);
+ isl_set_free(set_j);
+
+ isl_vec_free(bound);
+
+ return changed;
+error:
+ wraps_free(&wraps);
+ isl_vec_free(bound);
+ isl_set_free(set_i);
+ isl_set_free(set_j);
+ return -1;
+}
+
+/* Set the is_redundant property of the "n" constraints in "cuts",
+ * except "k" to "v".
+ * This is a fairly tricky operation as it bypasses isl_tab.c.
+ * The reason we want to temporarily mark some constraints redundant
+ * is that we want to ignore them in add_wraps.
+ *
+ * Initially all cut constraints are non-redundant, but the
+ * selection of a facet right before the call to this function
+ * may have made some of them redundant.
+ * Likewise, the same constraints are marked non-redundant
+ * in the second call to this function, before they are officially
+ * made non-redundant again in the subsequent rollback.
+ */
+static void set_is_redundant(struct isl_tab *tab, unsigned n_eq,
+ int *cuts, int n, int k, int v)
+{
+ int l;
+
+ for (l = 0; l < n; ++l) {
+ if (l == k)
+ continue;
+ tab->con[n_eq + cuts[l]].is_redundant = v;
+ }
+}
+
+/* Given a pair of basic maps i and j such that j sticks out
+ * of i at n cut constraints, each time by at most one,
+ * try to compute wrapping constraints and replace the two
+ * basic maps by a single basic map.
+ * The other constraints of i are assumed to be valid for j.
+ *
+ * The facets of i corresponding to the cut constraints are
+ * wrapped around their ridges, except those ridges determined
+ * by any of the other cut constraints.
+ * The intersections of cut constraints need to be ignored
+ * as the result of wrapping one cut constraint around another
+ * would result in a constraint cutting the union.
+ * In each case, the facets are wrapped to include the union
+ * of the two basic maps.
+ *
+ * The pieces of j that lie at an offset of exactly one from
+ * one of the cut constraints of i are wrapped around their edges.
+ * Here, there is no need to ignore intersections because we
+ * are wrapping around the union of the two basic maps.
+ *
+ * If any wrapping fails, i.e., if we cannot wrap to touch
+ * the union, then we give up.
+ * Otherwise, the pair of basic maps is replaced by their union.
+ */
+static int wrap_in_facets(struct isl_map *map, int i, int j,
+ int *cuts, int n, struct isl_tab **tabs,
+ int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+ struct isl_wraps wraps;
+ isl_mat *mat;
+ isl_set *set = NULL;
+ isl_vec *bound = NULL;
+ unsigned total = isl_basic_map_total_dim(map->p[i]);
+ int max_wrap;
+ int k;
+ struct isl_tab_undo *snap_i, *snap_j;
+
+ if (isl_tab_extend_cons(tabs[j], 1) < 0)
+ goto error;
+
+ max_wrap = 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
+ map->p[i]->n_ineq + map->p[j]->n_ineq;
+ max_wrap *= n;
+
+ set = isl_set_union(set_from_updated_bmap(map->p[i], tabs[i]),
+ set_from_updated_bmap(map->p[j], tabs[j]));
+ mat = isl_mat_alloc(map->ctx, max_wrap, 1 + total);
+ wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
+ bound = isl_vec_alloc(map->ctx, 1 + total);
+ if (!set || !wraps.mat || !bound)
+ goto error;
+
+ snap_i = isl_tab_snap(tabs[i]);
+ snap_j = isl_tab_snap(tabs[j]);
+
+ wraps.mat->n_row = 0;
+
+ for (k = 0; k < n; ++k) {
+ if (isl_tab_select_facet(tabs[i], map->p[i]->n_eq + cuts[k]) < 0)
+ goto error;
+ if (isl_tab_detect_redundant(tabs[i]) < 0)
+ goto error;
+ set_is_redundant(tabs[i], map->p[i]->n_eq, cuts, n, k, 1);
+
+ isl_seq_neg(bound->el, map->p[i]->ineq[cuts[k]], 1 + total);
+ if (!tabs[i]->empty &&
+ add_wraps(&wraps, map->p[i], tabs[i], bound->el, set) < 0)
+ goto error;
+
+ set_is_redundant(tabs[i], map->p[i]->n_eq, cuts, n, k, 0);
+ if (isl_tab_rollback(tabs[i], snap_i) < 0)
+ goto error;
+
+ if (tabs[i]->empty)
+ break;
+ if (!wraps.mat->n_row)
+ break;
+
+ isl_seq_cpy(bound->el, map->p[i]->ineq[cuts[k]], 1 + total);
+ isl_int_add_ui(bound->el[0], bound->el[0], 1);
+ if (isl_tab_add_eq(tabs[j], bound->el) < 0)
+ goto error;
+ if (isl_tab_detect_redundant(tabs[j]) < 0)
+ goto error;
+
+ if (!tabs[j]->empty &&
+ add_wraps(&wraps, map->p[j], tabs[j], bound->el, set) < 0)
+ goto error;
+
+ if (isl_tab_rollback(tabs[j], snap_j) < 0)
+ goto error;
+
+ if (!wraps.mat->n_row)
+ break;
+ }
+
+ if (k == n)
+ changed = fuse(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+
+ isl_vec_free(bound);
+ wraps_free(&wraps);
+ isl_set_free(set);
+
+ return changed;
+error:
+ isl_vec_free(bound);
+ wraps_free(&wraps);
+ isl_set_free(set);
+ return -1;
+}
+
+/* Given two basic sets i and j such that i has no cut equalities,
+ * check if relaxing all the cut inequalities of i by one turns
+ * them into valid constraint for j and check if we can wrap in
+ * the bits that are sticking out.
+ * If so, replace the pair by their union.
+ *
+ * We first check if all relaxed cut inequalities of i are valid for j
+ * and then try to wrap in the intersections of the relaxed cut inequalities
+ * with j.
+ *
+ * During this wrapping, we consider the points of j that lie at a distance
+ * of exactly 1 from i. In particular, we ignore the points that lie in
+ * between this lower-dimensional space and the basic map i.
+ * We can therefore only apply this to integer maps.
+ * ____ _____
+ * / ___|_ / \
+ * / | | / |
+ * \ | | => \ |
+ * \|____| \ |
+ * \___| \____/
+ *
+ * _____ ______
+ * | ____|_ | \
+ * | | | | |
+ * | | | => | |
+ * |_| | | |
+ * |_____| \______|
+ *
+ * _______
+ * | |
+ * | |\ |
+ * | | \ |
+ * | | \ |
+ * | | \|
+ * | | \
+ * | |_____\
+ * | |
+ * |_______|
+ *
+ * Wrapping can fail if the result of wrapping one of the facets
+ * around its edges does not produce any new facet constraint.
+ * In particular, this happens when we try to wrap in unbounded sets.
+ *
+ * _______________________________________________________________________
+ * |
+ * | ___
+ * | | |
+ * |_| |_________________________________________________________________
+ * |___|
+ *
+ * The following is not an acceptable result of coalescing the above two
+ * sets as it includes extra integer points.
+ * _______________________________________________________________________
+ * |
+ * |
+ * |
+ * |
+ * \______________________________________________________________________
+ */
+static int can_wrap_in_set(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+ int k, m;
+ int n;
+ int *cuts = NULL;
+
+ if (ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_RATIONAL) ||
+ ISL_F_ISSET(map->p[j], ISL_BASIC_MAP_RATIONAL))
+ return 0;
+
+ n = count(ineq_i, map->p[i]->n_ineq, STATUS_CUT);
+ if (n == 0)
+ return 0;
+
+ cuts = isl_alloc_array(map->ctx, int, n);
+ if (!cuts)
+ return -1;
+
+ for (k = 0, m = 0; m < n; ++k) {
+ enum isl_ineq_type type;
+
+ if (ineq_i[k] != STATUS_CUT)
+ continue;
+
+ isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ type = isl_tab_ineq_type(tabs[j], map->p[i]->ineq[k]);
+ isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ if (type == isl_ineq_error)
+ goto error;
+ if (type != isl_ineq_redundant)
+ break;
+ cuts[m] = k;
+ ++m;
+ }
+
+ if (m == n)
+ changed = wrap_in_facets(map, i, j, cuts, n, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+
+ free(cuts);
+
+ return changed;
+error:
+ free(cuts);
+ return -1;
+}
+
+/* Check if either i or j has a single cut constraint that can
+ * be used to wrap in (a facet of) the other basic set.
+ * if so, replace the pair by their union.
+ */
+static int check_wrap(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+
+ if (!any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT))
+ changed = can_wrap_in_set(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ if (changed)
+ return changed;
+
+ if (!any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT))
+ changed = can_wrap_in_set(map, j, i, tabs,
+ eq_j, ineq_j, eq_i, ineq_i);
+ return changed;
+}
+
+/* At least one of the basic maps has an equality that is adjacent
+ * to inequality. Make sure that only one of the basic maps has
+ * such an equality and that the other basic map has exactly one
+ * inequality adjacent to an equality.
+ * We call the basic map that has the inequality "i" and the basic
+ * map that has the equality "j".
+ * If "i" has any "cut" (in)equality, then relaxing the inequality
+ * by one would not result in a basic map that contains the other
+ * basic map.
+ */
+static int check_adj_eq(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int changed = 0;
+ int k;
+
+ if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ) &&
+ any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ))
+ /* ADJ EQ TOO MANY */
+ return 0;
+
+ if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ))
+ return check_adj_eq(map, j, i, tabs,
+ eq_j, ineq_j, eq_i, ineq_i);
+
+ /* j has an equality adjacent to an inequality in i */
+
+ if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT))
+ return 0;
+ if (any(ineq_i, map->p[i]->n_ineq, STATUS_CUT))
+ /* ADJ EQ CUT */
+ return 0;
+ if (count(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_EQ) != 1 ||
+ any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_EQ) ||
+ any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) ||
+ any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ))
+ /* ADJ EQ TOO MANY */
+ return 0;
+
+ for (k = 0; k < map->p[i]->n_ineq; ++k)
+ if (ineq_i[k] == STATUS_ADJ_EQ)
+ break;
+
+ changed = is_adj_eq_extension(map, i, j, k, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ if (changed)
+ return changed;
+
+ if (count(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ) != 1)
+ return 0;
+
+ changed = can_wrap_in_facet(map, i, j, k, tabs, eq_i, ineq_i, eq_j, ineq_j);
+
+ return changed;
+}
+
+/* The two basic maps lie on adjacent hyperplanes. In particular,
+ * basic map "i" has an equality that lies parallel to basic map "j".
+ * Check if we can wrap the facets around the parallel hyperplanes
+ * to include the other set.
+ *
+ * We perform basically the same operations as can_wrap_in_facet,
+ * except that we don't need to select a facet of one of the sets.
+ * _
+ * \\ \\
+ * \\ => \\
+ * \ \|
+ *
+ * We only allow one equality of "i" to be adjacent to an equality of "j"
+ * to avoid coalescing
+ *
+ * [m, n] -> { [x, y] -> [x, 1 + y] : x >= 1 and y >= 1 and
+ * x <= 10 and y <= 10;
+ * [x, y] -> [1 + x, y] : x >= 1 and x <= 20 and
+ * y >= 5 and y <= 15 }
+ *
+ * to
+ *
+ * [m, n] -> { [x, y] -> [x2, y2] : x >= 1 and 10y2 <= 20 - x + 10y and
+ * 4y2 >= 5 + 3y and 5y2 <= 15 + 4y and
+ * y2 <= 1 + x + y - x2 and y2 >= y and
+ * y2 >= 1 + x + y - x2 }
+ */
+static int check_eq_adj_eq(struct isl_map *map, int i, int j,
+ struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+{
+ int k;
+ int changed = 0;
+ struct isl_wraps wraps;
+ isl_mat *mat;
+ struct isl_set *set_i = NULL;
+ struct isl_set *set_j = NULL;
+ struct isl_vec *bound = NULL;
+ unsigned total = isl_basic_map_total_dim(map->p[i]);
+
+ if (count(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_EQ) != 1)
+ return 0;
+
+ for (k = 0; k < 2 * map->p[i]->n_eq ; ++k)
+ if (eq_i[k] == STATUS_ADJ_EQ)
+ break;
+
+ set_i = set_from_updated_bmap(map->p[i], tabs[i]);
+ set_j = set_from_updated_bmap(map->p[j], tabs[j]);
+ mat = isl_mat_alloc(map->ctx, 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
+ map->p[i]->n_ineq + map->p[j]->n_ineq,
+ 1 + total);
+ wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
+ bound = isl_vec_alloc(map->ctx, 1 + total);
+ if (!set_i || !set_j || !wraps.mat || !bound)
+ goto error;
+
+ if (k % 2 == 0)
+ isl_seq_neg(bound->el, map->p[i]->eq[k / 2], 1 + total);
+ else
+ isl_seq_cpy(bound->el, map->p[i]->eq[k / 2], 1 + total);
+ isl_int_add_ui(bound->el[0], bound->el[0], 1);
+
+ isl_seq_cpy(wraps.mat->row[0], bound->el, 1 + total);
+ wraps.mat->n_row = 1;
+
+ if (add_wraps(&wraps, map->p[j], tabs[j], bound->el, set_i) < 0)
+ goto error;
+ if (!wraps.mat->n_row)
+ goto unbounded;
+
+ isl_int_sub_ui(bound->el[0], bound->el[0], 1);
+ isl_seq_neg(bound->el, bound->el, 1 + total);
+
+ isl_seq_cpy(wraps.mat->row[wraps.mat->n_row], bound->el, 1 + total);
+ wraps.mat->n_row++;
+
+ if (add_wraps(&wraps, map->p[i], tabs[i], bound->el, set_j) < 0)
+ goto error;
+ if (!wraps.mat->n_row)
+ goto unbounded;
+
+ changed = fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+
+ if (0) {
+error: changed = -1;
+ }
+unbounded:
+
+ wraps_free(&wraps);
+ isl_set_free(set_i);
+ isl_set_free(set_j);
+ isl_vec_free(bound);
+
+ return changed;
+}
+
+/* Check if the union of the given pair of basic maps
+ * can be represented by a single basic map.
+ * If so, replace the pair by the single basic map and return 1.
+ * Otherwise, return 0;
+ * The two basic maps are assumed to live in the same local space.
+ *
+ * We first check the effect of each constraint of one basic map
+ * on the other basic map.
+ * The constraint may be
+ * redundant the constraint is redundant in its own
+ * basic map and should be ignore and removed
+ * in the end
+ * valid all (integer) points of the other basic map
+ * satisfy the constraint
+ * separate no (integer) point of the other basic map
+ * satisfies the constraint
+ * cut some but not all points of the other basic map
+ * satisfy the constraint
+ * adj_eq the given constraint is adjacent (on the outside)
+ * to an equality of the other basic map
+ * adj_ineq the given constraint is adjacent (on the outside)
+ * to an inequality of the other basic map
+ *
+ * We consider seven cases in which we can replace the pair by a single
+ * basic map. We ignore all "redundant" constraints.
+ *
+ * 1. all constraints of one basic map are valid
+ * => the other basic map is a subset and can be removed
+ *
+ * 2. all constraints of both basic maps are either "valid" or "cut"
+ * and the facets corresponding to the "cut" constraints
+ * of one of the basic maps lies entirely inside the other basic map
+ * => the pair can be replaced by a basic map consisting
+ * of the valid constraints in both basic maps
+ *
+ * 3. there is a single pair of adjacent inequalities
+ * (all other constraints are "valid")
+ * => the pair can be replaced by a basic map consisting
+ * of the valid constraints in both basic maps
+ *
+ * 4. one basic map has a single adjacent inequality, while the other
+ * constraints are "valid". The other basic map has some
+ * "cut" constraints, but replacing the adjacent inequality by
+ * its opposite and adding the valid constraints of the other
+ * basic map results in a subset of the other basic map
+ * => the pair can be replaced by a basic map consisting
+ * of the valid constraints in both basic maps
+ *
+ * 5. there is a single adjacent pair of an inequality and an equality,
+ * the other constraints of the basic map containing the inequality are
+ * "valid". Moreover, if the inequality the basic map is relaxed
+ * and then turned into an equality, then resulting facet lies
+ * entirely inside the other basic map
+ * => the pair can be replaced by the basic map containing
+ * the inequality, with the inequality relaxed.
+ *
+ * 6. there is a single adjacent pair of an inequality and an equality,
+ * the other constraints of the basic map containing the inequality are
+ * "valid". Moreover, the facets corresponding to both
+ * the inequality and the equality can be wrapped around their
+ * ridges to include the other basic map
+ * => the pair can be replaced by a basic map consisting
+ * of the valid constraints in both basic maps together
+ * with all wrapping constraints
+ *
+ * 7. one of the basic maps extends beyond the other by at most one.
+ * Moreover, the facets corresponding to the cut constraints and
+ * the pieces of the other basic map at offset one from these cut
+ * constraints can be wrapped around their ridges to include
+ * the union of the two basic maps
+ * => the pair can be replaced by a basic map consisting
+ * of the valid constraints in both basic maps together
+ * with all wrapping constraints
+ *
+ * 8. the two basic maps live in adjacent hyperplanes. In principle
+ * such sets can always be combined through wrapping, but we impose
+ * that there is only one such pair, to avoid overeager coalescing.
+ *
+ * Throughout the computation, we maintain a collection of tableaus
+ * corresponding to the basic maps. When the basic maps are dropped
+ * or combined, the tableaus are modified accordingly.
+ */
+static int coalesce_local_pair(__isl_keep isl_map *map, int i, int j,
+ struct isl_tab **tabs)
+{
+ int changed = 0;
+ int *eq_i = NULL;
+ int *eq_j = NULL;
+ int *ineq_i = NULL;
+ int *ineq_j = NULL;
+
+ eq_i = eq_status_in(map->p[i], tabs[j]);
+ if (map->p[i]->n_eq && !eq_i)
+ goto error;
+ if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ERROR))
+ goto error;
+ if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_SEPARATE))
+ goto done;
+
+ eq_j = eq_status_in(map->p[j], tabs[i]);
+ if (map->p[j]->n_eq && !eq_j)
+ goto error;
+ if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_ERROR))
+ goto error;
+ if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_SEPARATE))
+ goto done;
+
+ ineq_i = ineq_status_in(map->p[i], tabs[i], tabs[j]);
+ if (map->p[i]->n_ineq && !ineq_i)
+ goto error;
+ if (any(ineq_i, map->p[i]->n_ineq, STATUS_ERROR))
+ goto error;
+ if (any(ineq_i, map->p[i]->n_ineq, STATUS_SEPARATE))
+ goto done;
+
+ ineq_j = ineq_status_in(map->p[j], tabs[j], tabs[i]);
+ if (map->p[j]->n_ineq && !ineq_j)
+ goto error;
+ if (any(ineq_j, map->p[j]->n_ineq, STATUS_ERROR))
+ goto error;
+ if (any(ineq_j, map->p[j]->n_ineq, STATUS_SEPARATE))
+ goto done;
+
+ if (all(eq_i, 2 * map->p[i]->n_eq, STATUS_VALID) &&
+ all(ineq_i, map->p[i]->n_ineq, STATUS_VALID)) {
+ drop(map, j, tabs);
+ changed = 1;
+ } else if (all(eq_j, 2 * map->p[j]->n_eq, STATUS_VALID) &&
+ all(ineq_j, map->p[j]->n_ineq, STATUS_VALID)) {
+ drop(map, i, tabs);
+ changed = 1;
+ } else if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_EQ)) {
+ changed = check_eq_adj_eq(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ } else if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_EQ)) {
+ changed = check_eq_adj_eq(map, j, i, tabs,
+ eq_j, ineq_j, eq_i, ineq_i);
+ } else if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ) ||
+ any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ)) {
+ changed = check_adj_eq(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ } else if (any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_EQ) ||
+ any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_EQ)) {
+ /* Can't happen */
+ /* BAD ADJ INEQ */
+ } else if (any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) ||
+ any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ)) {
+ changed = check_adj_ineq(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ } else {
+ if (!any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT) &&
+ !any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT))
+ changed = check_facets(map, i, j, tabs, ineq_i, ineq_j);
+ if (!changed)
+ changed = check_wrap(map, i, j, tabs,
+ eq_i, ineq_i, eq_j, ineq_j);
+ }
+
+done:
+ free(eq_i);
+ free(eq_j);
+ free(ineq_i);
+ free(ineq_j);
+ return changed;
+error:
+ free(eq_i);
+ free(eq_j);
+ free(ineq_i);
+ free(ineq_j);
+ return -1;
+}
+
+/* Do the two basic maps live in the same local space, i.e.,
+ * do they have the same (known) divs?
+ * If either basic map has any unknown divs, then we can only assume
+ * that they do not live in the same local space.
+ */
+static int same_divs(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2)
+{
+ int i;
+ int known;
+ int total;
+
+ if (!bmap1 || !bmap2)
+ return -1;
+ if (bmap1->n_div != bmap2->n_div)
+ return 0;
+
+ if (bmap1->n_div == 0)
+ return 1;
+
+ known = isl_basic_map_divs_known(bmap1);
+ if (known < 0 || !known)
+ return known;
+ known = isl_basic_map_divs_known(bmap2);
+ if (known < 0 || !known)
+ return known;
+
+ total = isl_basic_map_total_dim(bmap1);
+ for (i = 0; i < bmap1->n_div; ++i)
+ if (!isl_seq_eq(bmap1->div[i], bmap2->div[i], 2 + total))
+ return 0;
+
+ return 1;
+}
+
+/* Given two basic maps "i" and "j", where the divs of "i" form a subset
+ * of those of "j", check if basic map "j" is a subset of basic map "i"
+ * and, if so, drop basic map "j".
+ *
+ * We first expand the divs of basic map "i" to match those of basic map "j",
+ * using the divs and expansion computed by the caller.
+ * Then we check if all constraints of the expanded "i" are valid for "j".
+ */
+static int coalesce_subset(__isl_keep isl_map *map, int i, int j,
+ struct isl_tab **tabs, __isl_keep isl_mat *div, int *exp)
+{
+ isl_basic_map *bmap;
+ int changed = 0;
+ int *eq_i = NULL;
+ int *ineq_i = NULL;
+
+ bmap = isl_basic_map_copy(map->p[i]);
+ bmap = isl_basic_set_expand_divs(bmap, isl_mat_copy(div), exp);
+
+ if (!bmap)
+ goto error;
+
+ eq_i = eq_status_in(bmap, tabs[j]);
+ if (bmap->n_eq && !eq_i)
+ goto error;
+ if (any(eq_i, 2 * bmap->n_eq, STATUS_ERROR))
+ goto error;
+ if (any(eq_i, 2 * bmap->n_eq, STATUS_SEPARATE))
+ goto done;
+
+ ineq_i = ineq_status_in(bmap, NULL, tabs[j]);
+ if (bmap->n_ineq && !ineq_i)
+ goto error;
+ if (any(ineq_i, bmap->n_ineq, STATUS_ERROR))
+ goto error;
+ if (any(ineq_i, bmap->n_ineq, STATUS_SEPARATE))
+ goto done;
+
+ if (all(eq_i, 2 * map->p[i]->n_eq, STATUS_VALID) &&
+ all(ineq_i, map->p[i]->n_ineq, STATUS_VALID)) {
+ drop(map, j, tabs);
+ changed = 1;
+ }
+
+done:
+ isl_basic_map_free(bmap);
+ free(eq_i);
+ free(ineq_i);
+ return 0;
+error:
+ isl_basic_map_free(bmap);
+ free(eq_i);
+ free(ineq_i);
+ return -1;
+}
+
+/* Check if the basic map "j" is a subset of basic map "i",
+ * assuming that "i" has fewer divs that "j".
+ * If not, then we change the order.
+ *
+ * If the two basic maps have the same number of divs, then
+ * they must necessarily be different. Otherwise, we would have
+ * called coalesce_local_pair. We therefore don't try anything
+ * in this case.
+ *
+ * We first check if the divs of "i" are all known and form a subset
+ * of those of "j". If so, we pass control over to coalesce_subset.
+ */
+static int check_coalesce_subset(__isl_keep isl_map *map, int i, int j,
+ struct isl_tab **tabs)
+{
+ int known;
+ isl_mat *div_i, *div_j, *div;
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_ctx *ctx;
+ int subset;
+
+ if (map->p[i]->n_div == map->p[j]->n_div)
+ return 0;
+ if (map->p[j]->n_div < map->p[i]->n_div)
+ return check_coalesce_subset(map, j, i, tabs);
+
+ known = isl_basic_map_divs_known(map->p[i]);
+ if (known < 0 || !known)
+ return known;
+
+ ctx = isl_map_get_ctx(map);
+
+ div_i = isl_basic_map_get_divs(map->p[i]);
+ div_j = isl_basic_map_get_divs(map->p[j]);
+
+ if (!div_i || !div_j)
+ goto error;
+
+ exp1 = isl_alloc_array(ctx, int, div_i->n_row);
+ exp2 = isl_alloc_array(ctx, int, div_j->n_row);
+ if ((div_i->n_row && !exp1) || (div_j->n_row && !exp2))
+ goto error;
+
+ div = isl_merge_divs(div_i, div_j, exp1, exp2);
+ if (!div)
+ goto error;
+
+ if (div->n_row == div_j->n_row)
+ subset = coalesce_subset(map, i, j, tabs, div, exp1);
+ else
+ subset = 0;
+
+ isl_mat_free(div);
+
+ isl_mat_free(div_i);
+ isl_mat_free(div_j);
+
+ free(exp2);
+ free(exp1);
+
+ return subset;
+error:
+ isl_mat_free(div_i);
+ isl_mat_free(div_j);
+ free(exp1);
+ free(exp2);
+ return -1;
+}
+
+/* Check if the union of the given pair of basic maps
+ * can be represented by a single basic map.
+ * If so, replace the pair by the single basic map and return 1.
+ * Otherwise, return 0;
+ *
+ * We first check if the two basic maps live in the same local space.
+ * If so, we do the complete check. Otherwise, we check if one is
+ * an obvious subset of the other.
+ */
+static int coalesce_pair(__isl_keep isl_map *map, int i, int j,
+ struct isl_tab **tabs)
+{
+ int same;
+
+ same = same_divs(map->p[i], map->p[j]);
+ if (same < 0)
+ return -1;
+ if (same)
+ return coalesce_local_pair(map, i, j, tabs);
+
+ return check_coalesce_subset(map, i, j, tabs);
+}
+
+static struct isl_map *coalesce(struct isl_map *map, struct isl_tab **tabs)
+{
+ int i, j;
+
+ for (i = map->n - 2; i >= 0; --i)
+restart:
+ for (j = i + 1; j < map->n; ++j) {
+ int changed;
+ changed = coalesce_pair(map, i, j, tabs);
+ if (changed < 0)
+ goto error;
+ if (changed)
+ goto restart;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* For each pair of basic maps in the map, check if the union of the two
+ * can be represented by a single basic map.
+ * If so, replace the pair by the single basic map and start over.
+ *
+ * Since we are constructing the tableaus of the basic maps anyway,
+ * we exploit them to detect implicit equalities and redundant constraints.
+ * This also helps the coalescing as it can ignore the redundant constraints.
+ * In order to avoid confusion, we make all implicit equalities explicit
+ * in the basic maps. We don't call isl_basic_map_gauss, though,
+ * as that may affect the number of constraints.
+ * This means that we have to call isl_basic_map_gauss at the end
+ * of the computation to ensure that the basic maps are not left
+ * in an unexpected state.
+ */
+struct isl_map *isl_map_coalesce(struct isl_map *map)
+{
+ int i;
+ unsigned n;
+ struct isl_tab **tabs = NULL;
+
+ map = isl_map_remove_empty_parts(map);
+ if (!map)
+ return NULL;
+
+ if (map->n <= 1)
+ return map;
+
+ map = isl_map_sort_divs(map);
+ map = isl_map_cow(map);
+
+ if (!map)
+ return NULL;
+
+ tabs = isl_calloc_array(map->ctx, struct isl_tab *, map->n);
+ if (!tabs)
+ goto error;
+
+ n = map->n;
+ for (i = 0; i < map->n; ++i) {
+ tabs[i] = isl_tab_from_basic_map(map->p[i], 0);
+ if (!tabs[i])
+ goto error;
+ if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_IMPLICIT))
+ if (isl_tab_detect_implicit_equalities(tabs[i]) < 0)
+ goto error;
+ map->p[i] = isl_tab_make_equalities_explicit(tabs[i],
+ map->p[i]);
+ if (!map->p[i])
+ goto error;
+ if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_REDUNDANT))
+ if (isl_tab_detect_redundant(tabs[i]) < 0)
+ goto error;
+ }
+ for (i = map->n - 1; i >= 0; --i)
+ if (tabs[i]->empty)
+ drop(map, i, tabs);
+
+ map = coalesce(map, tabs);
+
+ if (map)
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_update_from_tab(map->p[i],
+ tabs[i]);
+ map->p[i] = isl_basic_map_gauss(map->p[i], NULL);
+ map->p[i] = isl_basic_map_finalize(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ ISL_F_SET(map->p[i], ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_SET(map->p[i], ISL_BASIC_MAP_NO_REDUNDANT);
+ }
+
+ for (i = 0; i < n; ++i)
+ isl_tab_free(tabs[i]);
+
+ free(tabs);
+
+ return map;
+error:
+ if (tabs)
+ for (i = 0; i < n; ++i)
+ isl_tab_free(tabs[i]);
+ free(tabs);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* For each pair of basic sets in the set, check if the union of the two
+ * can be represented by a single basic set.
+ * If so, replace the pair by the single basic set and start over.
+ */
+struct isl_set *isl_set_coalesce(struct isl_set *set)
+{
+ return (struct isl_set *)isl_map_coalesce((struct isl_map *)set);
+}
diff --git a/polly/lib/External/isl/isl_config.h b/polly/lib/External/isl/isl_config.h
new file mode 100644
index 00000000000..906614f6a01
--- /dev/null
+++ b/polly/lib/External/isl/isl_config.h
@@ -0,0 +1,169 @@
+/* isl_config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if HeaderSearchOptions::AddPath takes 4 arguments */
+#undef ADDPATH_TAKES_4_ARGUMENTS
+
+/* Clang installation prefix */
+#undef CLANG_PREFIX
+
+/* Define if CompilerInstance::createDiagnostics takes argc and argv */
+#undef CREATEDIAGNOSTICS_TAKES_ARG
+
+/* Define if CompilerInstance::createPreprocessor takes TranslationUnitKind */
+#undef CREATEPREPROCESSOR_TAKES_TUKIND
+
+/* Define if TargetInfo::CreateTargetInfo takes pointer */
+#undef CREATETARGETINFO_TAKES_POINTER
+
+/* Define if TargetInfo::CreateTargetInfo takes shared_ptr */
+#undef CREATETARGETINFO_TAKES_SHARED_PTR
+
+/* Define if Driver constructor takes default image name */
+#undef DRIVER_CTOR_TAKES_DEFAULTIMAGENAME
+
+/* Define to Diagnostic for older versions of clang */
+#undef DiagnosticsEngine
+
+/* most gcc compilers know a function __attribute__((__warn_unused_result__))
+ */
+#undef GCC_WARN_UNUSED_RESULT
+
+/* Define if llvm/ADT/OwningPtr.h exists */
+#undef HAVE_ADT_OWNINGPTR_H
+
+/* Define if clang/Basic/DiagnosticOptions.h exists */
+#undef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+
+/* Define if Driver constructor takes CXXIsProduction argument */
+#undef HAVE_CXXISPRODUCTION
+
+/* Define to 1 if you have the declaration of `ffs', and to 0 if you don't. */
+#undef HAVE_DECL_FFS
+
+/* Define to 1 if you have the declaration of `mp_get_memory_functions', and
+ to 0 if you don't. */
+#undef HAVE_DECL_MP_GET_MEMORY_FUNCTIONS
+
+/* Define to 1 if you have the declaration of `__builtin_ffs', and to 0 if you
+ don't. */
+#undef HAVE_DECL___BUILTIN_FFS
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if Driver constructor takes IsProduction argument */
+#undef HAVE_ISPRODUCTION
+
+/* Define to 1 if you have the `gmp' library (-lgmp). */
+#undef HAVE_LIBGMP
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if SourceManager has a setMainFileID method */
+#undef HAVE_SETMAINFILEID
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Return type of HandleTopLevelDeclReturn */
+#undef HandleTopLevelDeclContinue
+
+/* Return type of HandleTopLevelDeclReturn */
+#undef HandleTopLevelDeclReturn
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#undef LT_OBJDIR
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `char', as computed by sizeof. */
+#undef SIZEOF_CHAR
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `void*', as computed by sizeof. */
+#undef SIZEOF_VOIDP
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if Driver::BuildCompilation takes ArrayRef */
+#undef USE_ARRAYREF
+
+/* use gmp to implement isl_int */
+#undef USE_GMP_FOR_MP
+
+/* use imath to implement isl_int */
+#define USE_IMATH_FOR_MP 1
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to getParamType for newer versions of clang */
+#undef getArgType
+
+/* Define to getHostTriple for older versions of clang */
+#undef getDefaultTargetTriple
+
+/* Define to getInstantiationLineNumber for older versions of clang */
+#undef getExpansionLineNumber
+
+/* Define to getNumParams for newer versions of clang */
+#undef getNumArgs
+
+/* Define to getResultType for older versions of clang */
+#undef getReturnType
+
+#include <isl_config_post.h>
diff --git a/polly/lib/External/isl/isl_config_post.h b/polly/lib/External/isl/isl_config_post.h
new file mode 100644
index 00000000000..5d67aae406d
--- /dev/null
+++ b/polly/lib/External/isl/isl_config_post.h
@@ -0,0 +1,13 @@
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+#if (HAVE_DECL_FFS==0) && (HAVE_DECL___BUILTIN_FFS==1)
+#define ffs __builtin_ffs
+#endif
+
+#ifdef GCC_WARN_UNUSED_RESULT
+#define WARN_UNUSED GCC_WARN_UNUSED_RESULT
+#else
+#define WARN_UNUSED
+#endif
diff --git a/polly/lib/External/isl/isl_constraint.c b/polly/lib/External/isl/isl_constraint.c
new file mode 100644
index 00000000000..049175ba7f9
--- /dev/null
+++ b/polly/lib/External/isl/isl_constraint.c
@@ -0,0 +1,1437 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_map_private.h>
+#include <isl_constraint_private.h>
+#include <isl_space_private.h>
+#include <isl_seq.h>
+#include <isl_aff_private.h>
+#include <isl_local_space_private.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+#include <isl/deprecated/constraint_int.h>
+
+#undef BASE
+#define BASE constraint
+
+#include <isl_list_templ.c>
+
+isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c)
+{
+ return c ? isl_local_space_get_ctx(c->ls) : NULL;
+}
+
+static unsigned n(struct isl_constraint *c, enum isl_dim_type type)
+{
+ return isl_local_space_dim(c->ls, type);
+}
+
+static unsigned offset(struct isl_constraint *c, enum isl_dim_type type)
+{
+ return isl_local_space_offset(c->ls, type);
+}
+
+static unsigned basic_map_offset(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type)
+{
+ return type == isl_dim_div ? 1 + isl_space_dim(bmap->dim, isl_dim_all)
+ : 1 + isl_space_offset(bmap->dim, type);
+}
+
+static unsigned basic_set_offset(struct isl_basic_set *bset,
+ enum isl_dim_type type)
+{
+ isl_space *dim = bset->dim;
+ switch (type) {
+ case isl_dim_param: return 1;
+ case isl_dim_in: return 1 + dim->nparam;
+ case isl_dim_out: return 1 + dim->nparam + dim->n_in;
+ case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out;
+ default: return 0;
+ }
+}
+
+__isl_give isl_constraint *isl_constraint_alloc_vec(int eq,
+ __isl_take isl_local_space *ls, __isl_take isl_vec *v)
+{
+ isl_constraint *constraint;
+
+ if (!ls || !v)
+ goto error;
+
+ constraint = isl_alloc_type(isl_vec_get_ctx(v), isl_constraint);
+ if (!constraint)
+ goto error;
+
+ constraint->ref = 1;
+ constraint->eq = eq;
+ constraint->ls = ls;
+ constraint->v = v;
+
+ return constraint;
+error:
+ isl_local_space_free(ls);
+ isl_vec_free(v);
+ return NULL;
+}
+
+__isl_give isl_constraint *isl_constraint_alloc(int eq,
+ __isl_take isl_local_space *ls)
+{
+ isl_ctx *ctx;
+ isl_vec *v;
+
+ if (!ls)
+ return NULL;
+
+ ctx = isl_local_space_get_ctx(ls);
+ v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
+ v = isl_vec_clr(v);
+ return isl_constraint_alloc_vec(eq, ls, v);
+}
+
+struct isl_constraint *isl_basic_map_constraint(struct isl_basic_map *bmap,
+ isl_int **line)
+{
+ int eq;
+ isl_ctx *ctx;
+ isl_vec *v;
+ isl_local_space *ls = NULL;
+ isl_constraint *constraint;
+
+ if (!bmap || !line)
+ goto error;
+
+ eq = line >= bmap->eq;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ ls = isl_basic_map_get_local_space(bmap);
+ v = isl_vec_alloc(ctx, 1 + isl_local_space_dim(ls, isl_dim_all));
+ if (!v)
+ goto error;
+ isl_seq_cpy(v->el, line[0], v->size);
+ constraint = isl_constraint_alloc_vec(eq, ls, v);
+
+ isl_basic_map_free(bmap);
+ return constraint;
+error:
+ isl_local_space_free(ls);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_constraint *isl_basic_set_constraint(struct isl_basic_set *bset,
+ isl_int **line)
+{
+ return isl_basic_map_constraint((struct isl_basic_map *)bset, line);
+}
+
+__isl_give isl_constraint *isl_equality_alloc(__isl_take isl_local_space *ls)
+{
+ return isl_constraint_alloc(1, ls);
+}
+
+__isl_give isl_constraint *isl_inequality_alloc(__isl_take isl_local_space *ls)
+{
+ return isl_constraint_alloc(0, ls);
+}
+
+struct isl_constraint *isl_constraint_dup(struct isl_constraint *c)
+{
+ if (!c)
+ return NULL;
+
+ return isl_constraint_alloc_vec(c->eq, isl_local_space_copy(c->ls),
+ isl_vec_copy(c->v));
+}
+
+struct isl_constraint *isl_constraint_cow(struct isl_constraint *c)
+{
+ if (!c)
+ return NULL;
+
+ if (c->ref == 1)
+ return c;
+ c->ref--;
+ return isl_constraint_dup(c);
+}
+
+struct isl_constraint *isl_constraint_copy(struct isl_constraint *constraint)
+{
+ if (!constraint)
+ return NULL;
+
+ constraint->ref++;
+ return constraint;
+}
+
+__isl_null isl_constraint *isl_constraint_free(__isl_take isl_constraint *c)
+{
+ if (!c)
+ return NULL;
+
+ if (--c->ref > 0)
+ return NULL;
+
+ isl_local_space_free(c->ls);
+ isl_vec_free(c->v);
+ free(c);
+
+ return NULL;
+}
+
+/* Return the number of constraints in "bmap", i.e., the
+ * number of times isl_basic_map_foreach_constraint will
+ * call the callback.
+ */
+int isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+
+ return bmap->n_eq + bmap->n_ineq;
+}
+
+/* Return the number of constraints in "bset", i.e., the
+ * number of times isl_basic_set_foreach_constraint will
+ * call the callback.
+ */
+int isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_n_constraint(bset);
+}
+
+int isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap,
+ int (*fn)(__isl_take isl_constraint *c, void *user), void *user)
+{
+ int i;
+ struct isl_constraint *c;
+
+ if (!bmap)
+ return -1;
+
+ isl_assert(bmap->ctx, ISL_F_ISSET(bmap, ISL_BASIC_MAP_FINAL),
+ return -1);
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
+ &bmap->eq[i]);
+ if (!c)
+ return -1;
+ if (fn(c, user) < 0)
+ return -1;
+ }
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
+ &bmap->ineq[i]);
+ if (!c)
+ return -1;
+ if (fn(c, user) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset,
+ int (*fn)(__isl_take isl_constraint *c, void *user), void *user)
+{
+ return isl_basic_map_foreach_constraint((isl_basic_map *)bset, fn, user);
+}
+
+/* Add the constraint to the list that "user" points to, if it is not
+ * a div constraint.
+ */
+static int collect_constraint(__isl_take isl_constraint *constraint,
+ void *user)
+{
+ isl_constraint_list **list = user;
+
+ if (isl_constraint_is_div_constraint(constraint))
+ isl_constraint_free(constraint);
+ else
+ *list = isl_constraint_list_add(*list, constraint);
+
+ return 0;
+}
+
+/* Return a list of constraints that, when combined, are equivalent
+ * to "bmap". The input is required to have only known divs.
+ *
+ * There is no need to include the div constraints as they are
+ * implied by the div expressions.
+ */
+__isl_give isl_constraint_list *isl_basic_map_get_constraint_list(
+ __isl_keep isl_basic_map *bmap)
+{
+ int n;
+ int known;
+ isl_ctx *ctx;
+ isl_constraint_list *list;
+
+ known = isl_basic_map_divs_known(bmap);
+ if (known < 0)
+ return NULL;
+ ctx = isl_basic_map_get_ctx(bmap);
+ if (!known)
+ isl_die(ctx, isl_error_invalid,
+ "input involves unknown divs", return NULL);
+
+ n = isl_basic_map_n_constraint(bmap);
+ list = isl_constraint_list_alloc(ctx, n);
+ if (isl_basic_map_foreach_constraint(bmap,
+ &collect_constraint, &list) < 0)
+ list = isl_constraint_list_free(list);
+
+ return list;
+}
+
+/* Return a list of constraints that, when combined, are equivalent
+ * to "bset". The input is required to have only known divs.
+ */
+__isl_give isl_constraint_list *isl_basic_set_get_constraint_list(
+ __isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_get_constraint_list(bset);
+}
+
+int isl_constraint_is_equal(struct isl_constraint *constraint1,
+ struct isl_constraint *constraint2)
+{
+ int equal;
+
+ if (!constraint1 || !constraint2)
+ return 0;
+ if (constraint1->eq != constraint2->eq)
+ return 0;
+ equal = isl_local_space_is_equal(constraint1->ls, constraint2->ls);
+ if (equal < 0 || !equal)
+ return equal;
+ return isl_vec_is_equal(constraint1->v, constraint2->v);
+}
+
+struct isl_basic_map *isl_basic_map_add_constraint(
+ struct isl_basic_map *bmap, struct isl_constraint *constraint)
+{
+ isl_ctx *ctx;
+ isl_space *dim;
+ int equal_space;
+
+ if (!bmap || !constraint)
+ goto error;
+
+ ctx = isl_constraint_get_ctx(constraint);
+ dim = isl_constraint_get_space(constraint);
+ equal_space = isl_space_is_equal(bmap->dim, dim);
+ isl_space_free(dim);
+ isl_assert(ctx, equal_space, goto error);
+
+ bmap = isl_basic_map_intersect(bmap,
+ isl_basic_map_from_constraint(constraint));
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_constraint_free(constraint);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_add_constraint(
+ struct isl_basic_set *bset, struct isl_constraint *constraint)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_add_constraint((struct isl_basic_map *)bset,
+ constraint);
+}
+
+__isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map,
+ __isl_take isl_constraint *constraint)
+{
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_from_constraint(constraint);
+ map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+ return map;
+}
+
+__isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
+ __isl_take isl_constraint *constraint)
+{
+ return isl_map_add_constraint(set, constraint);
+}
+
+__isl_give isl_space *isl_constraint_get_space(
+ __isl_keep isl_constraint *constraint)
+{
+ return constraint ? isl_local_space_get_space(constraint->ls) : NULL;
+}
+
+__isl_give isl_local_space *isl_constraint_get_local_space(
+ __isl_keep isl_constraint *constraint)
+{
+ return constraint ? isl_local_space_copy(constraint->ls) : NULL;
+}
+
+int isl_constraint_dim(struct isl_constraint *constraint,
+ enum isl_dim_type type)
+{
+ if (!constraint)
+ return -1;
+ return n(constraint, type);
+}
+
+int isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ isl_ctx *ctx;
+ int *active = NULL;
+ int involves = 0;
+
+ if (!constraint)
+ return -1;
+ if (n == 0)
+ return 0;
+
+ ctx = isl_constraint_get_ctx(constraint);
+ if (first + n > isl_constraint_dim(constraint, type))
+ isl_die(ctx, isl_error_invalid,
+ "range out of bounds", return -1);
+
+ active = isl_local_space_get_active(constraint->ls,
+ constraint->v->el + 1);
+ if (!active)
+ goto error;
+
+ first += isl_local_space_offset(constraint->ls, type) - 1;
+ for (i = 0; i < n; ++i)
+ if (active[first + i]) {
+ involves = 1;
+ break;
+ }
+
+ free(active);
+
+ return involves;
+error:
+ free(active);
+ return -1;
+}
+
+/* Does the given constraint represent a lower bound on the given
+ * dimension?
+ */
+int isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!constraint)
+ return -1;
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "position out of bounds", return -1);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ return isl_int_is_pos(constraint->v->el[pos]);
+}
+
+/* Does the given constraint represent an upper bound on the given
+ * dimension?
+ */
+int isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!constraint)
+ return -1;
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "position out of bounds", return -1);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ return isl_int_is_neg(constraint->v->el[pos]);
+}
+
+const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, unsigned pos)
+{
+ return constraint ?
+ isl_local_space_get_dim_name(constraint->ls, type, pos) : NULL;
+}
+
+void isl_constraint_get_constant(struct isl_constraint *constraint, isl_int *v)
+{
+ if (!constraint)
+ return;
+ isl_int_set(*v, constraint->v->el[0]);
+}
+
+/* Return the constant term of "constraint".
+ */
+__isl_give isl_val *isl_constraint_get_constant_val(
+ __isl_keep isl_constraint *constraint)
+{
+ isl_ctx *ctx;
+
+ if (!constraint)
+ return NULL;
+
+ ctx = isl_constraint_get_ctx(constraint);
+ return isl_val_int_from_isl_int(ctx, constraint->v->el[0]);
+}
+
+void isl_constraint_get_coefficient(struct isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int *v)
+{
+ if (!constraint)
+ return;
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(constraint->v->ctx, isl_error_invalid,
+ "position out of bounds", return);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ isl_int_set(*v, constraint->v->el[pos]);
+}
+
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "constraint".
+ */
+__isl_give isl_val *isl_constraint_get_coefficient_val(
+ __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos)
+{
+ isl_ctx *ctx;
+
+ if (!constraint)
+ return NULL;
+
+ ctx = isl_constraint_get_ctx(constraint);
+ if (pos < 0 || pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(ctx, isl_error_invalid,
+ "position out of bounds", return NULL);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ return isl_val_int_from_isl_int(ctx, constraint->v->el[pos]);
+}
+
+__isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint,
+ int pos)
+{
+ if (!constraint)
+ return NULL;
+
+ return isl_local_space_get_div(constraint->ls, pos);
+}
+
+__isl_give isl_constraint *isl_constraint_set_constant(
+ __isl_take isl_constraint *constraint, isl_int v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ constraint->v = isl_vec_cow(constraint->v);
+ if (!constraint->v)
+ return isl_constraint_free(constraint);
+
+ isl_int_set(constraint->v->el[0], v);
+ return constraint;
+}
+
+/* Replace the constant term of "constraint" by "v".
+ */
+__isl_give isl_constraint *isl_constraint_set_constant_val(
+ __isl_take isl_constraint *constraint, __isl_take isl_val *v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint || !v)
+ goto error;
+ if (!isl_val_is_int(v))
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "expecting integer value", goto error);
+ constraint->v = isl_vec_set_element_val(constraint->v, 0, v);
+ if (!constraint->v)
+ constraint = isl_constraint_free(constraint);
+ return constraint;
+error:
+ isl_val_free(v);
+ return isl_constraint_free(constraint);
+}
+
+__isl_give isl_constraint *isl_constraint_set_constant_si(
+ __isl_take isl_constraint *constraint, int v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ constraint->v = isl_vec_cow(constraint->v);
+ if (!constraint->v)
+ return isl_constraint_free(constraint);
+
+ isl_int_set_si(constraint->v->el[0], v);
+ return constraint;
+}
+
+__isl_give isl_constraint *isl_constraint_set_coefficient(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(constraint->v->ctx, isl_error_invalid,
+ "position out of bounds",
+ return isl_constraint_free(constraint));
+
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ constraint->v = isl_vec_cow(constraint->v);
+ if (!constraint->v)
+ return isl_constraint_free(constraint);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ isl_int_set(constraint->v->el[pos], v);
+
+ return constraint;
+}
+
+/* Replace the coefficient of the variable of type "type" at position "pos"
+ * of "constraint" by "v".
+ */
+__isl_give isl_constraint *isl_constraint_set_coefficient_val(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint || !v)
+ goto error;
+ if (!isl_val_is_int(v))
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "expecting integer value", goto error);
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "position out of bounds", goto error);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ constraint->v = isl_vec_set_element_val(constraint->v, pos, v);
+ if (!constraint->v)
+ constraint = isl_constraint_free(constraint);
+ return constraint;
+error:
+ isl_val_free(v);
+ return isl_constraint_free(constraint);
+}
+
+__isl_give isl_constraint *isl_constraint_set_coefficient_si(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, int v)
+{
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ if (pos >= isl_local_space_dim(constraint->ls, type))
+ isl_die(constraint->v->ctx, isl_error_invalid,
+ "position out of bounds",
+ return isl_constraint_free(constraint));
+
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ constraint->v = isl_vec_cow(constraint->v);
+ if (!constraint->v)
+ return isl_constraint_free(constraint);
+
+ pos += isl_local_space_offset(constraint->ls, type);
+ isl_int_set_si(constraint->v->el[pos], v);
+
+ return constraint;
+}
+
+/* Drop any constraint from "bset" that is identical to "constraint".
+ * In particular, this means that the local spaces of "bset" and
+ * "constraint" need to be the same.
+ *
+ * Since the given constraint may actually be a pointer into the bset,
+ * we have to be careful not to reorder the constraints as the user
+ * may be holding on to other constraints from the same bset.
+ * This should be cleaned up when the internal representation of
+ * isl_constraint is changed to use isl_aff.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraint(
+ __isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint)
+{
+ int i;
+ unsigned n;
+ isl_int **row;
+ unsigned total;
+ isl_local_space *ls1;
+ int equal;
+
+ if (!bset || !constraint)
+ goto error;
+
+ ls1 = isl_basic_set_get_local_space(bset);
+ equal = isl_local_space_is_equal(ls1, constraint->ls);
+ isl_local_space_free(ls1);
+ if (equal < 0)
+ goto error;
+ if (!equal) {
+ isl_constraint_free(constraint);
+ return bset;
+ }
+
+ if (isl_constraint_is_equality(constraint)) {
+ n = bset->n_eq;
+ row = bset->eq;
+ } else {
+ n = bset->n_ineq;
+ row = bset->ineq;
+ }
+
+ total = isl_constraint_dim(constraint, isl_dim_all);
+ for (i = 0; i < n; ++i)
+ if (isl_seq_eq(row[i], constraint->v->el, 1 + total))
+ isl_seq_clr(row[i], 1 + total);
+
+ isl_constraint_free(constraint);
+ return bset;
+error:
+ isl_constraint_free(constraint);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint)
+{
+ isl_ctx *ctx;
+
+ constraint = isl_constraint_cow(constraint);
+ if (!constraint)
+ return NULL;
+
+ ctx = isl_constraint_get_ctx(constraint);
+ if (isl_constraint_is_equality(constraint))
+ isl_die(ctx, isl_error_invalid, "cannot negate equality",
+ return isl_constraint_free(constraint));
+ constraint->v = isl_vec_neg(constraint->v);
+ constraint->v = isl_vec_cow(constraint->v);
+ if (!constraint->v)
+ return isl_constraint_free(constraint);
+ isl_int_sub_ui(constraint->v->el[0], constraint->v->el[0], 1);
+ return constraint;
+}
+
+int isl_constraint_is_equality(struct isl_constraint *constraint)
+{
+ if (!constraint)
+ return -1;
+ return constraint->eq;
+}
+
+int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint)
+{
+ int i;
+ int n_div;
+
+ if (!constraint)
+ return -1;
+ if (isl_constraint_is_equality(constraint))
+ return 0;
+ n_div = isl_constraint_dim(constraint, isl_dim_div);
+ for (i = 0; i < n_div; ++i) {
+ if (isl_local_space_is_div_constraint(constraint->ls,
+ constraint->v->el, i))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* We manually set ISL_BASIC_SET_FINAL instead of calling
+ * isl_basic_map_finalize because we want to keep the position
+ * of the divs and we therefore do not want to throw away redundant divs.
+ * This is arguably a bit fragile.
+ */
+__isl_give isl_basic_map *isl_basic_map_from_constraint(
+ __isl_take isl_constraint *constraint)
+{
+ int k;
+ isl_local_space *ls;
+ struct isl_basic_map *bmap;
+ isl_int *c;
+ unsigned total;
+
+ if (!constraint)
+ return NULL;
+
+ ls = isl_local_space_copy(constraint->ls);
+ bmap = isl_basic_map_from_local_space(ls);
+ bmap = isl_basic_map_extend_constraints(bmap, 1, 1);
+ if (isl_constraint_is_equality(constraint)) {
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ c = bmap->eq[k];
+ }
+ else {
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ c = bmap->ineq[k];
+ }
+ total = isl_basic_map_total_dim(bmap);
+ isl_seq_cpy(c, constraint->v->el, 1 + total);
+ isl_constraint_free(constraint);
+ if (bmap)
+ ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
+ return bmap;
+error:
+ isl_constraint_free(constraint);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_from_constraint(
+ struct isl_constraint *constraint)
+{
+ if (!constraint)
+ return NULL;
+
+ if (isl_constraint_dim(constraint, isl_dim_in) != 0)
+ isl_die(isl_constraint_get_ctx(constraint), isl_error_invalid,
+ "not a set constraint", goto error);
+ return (isl_basic_set *)isl_basic_map_from_constraint(constraint);
+error:
+ isl_constraint_free(constraint);
+ return NULL;
+}
+
+/* Is the variable of "type" at position "pos" of "bmap" defined
+ * in terms of earlier dimensions through an equality?
+ *
+ * If so, and if c is not NULL, then return a copy of this equality in *c.
+ */
+int isl_basic_map_has_defining_equality(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type type, int pos,
+ __isl_give isl_constraint **c)
+{
+ int i;
+ unsigned offset;
+ unsigned total;
+
+ if (!bmap)
+ return -1;
+ offset = basic_map_offset(bmap, type);
+ total = isl_basic_map_total_dim(bmap);
+ isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
+ for (i = 0; i < bmap->n_eq; ++i) {
+ if (isl_int_is_zero(bmap->eq[i][offset + pos]) ||
+ isl_seq_first_non_zero(bmap->eq[i]+offset+pos+1,
+ 1+total-offset-pos-1) != -1)
+ continue;
+ if (c)
+ *c = isl_basic_map_constraint(isl_basic_map_copy(bmap),
+ &bmap->eq[i]);
+ return 1;
+ }
+ return 0;
+}
+
+/* Is the variable of "type" at position "pos" of "bset" defined
+ * in terms of earlier dimensions through an equality?
+ *
+ * If so, and if c is not NULL, then return a copy of this equality in *c.
+ */
+int isl_basic_set_has_defining_equality(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type type, int pos,
+ __isl_give isl_constraint **c)
+{
+ return isl_basic_map_has_defining_equality((isl_basic_map *)bset,
+ type, pos, c);
+}
+
+int isl_basic_set_has_defining_inequalities(
+ struct isl_basic_set *bset, enum isl_dim_type type, int pos,
+ struct isl_constraint **lower,
+ struct isl_constraint **upper)
+{
+ int i, j;
+ unsigned offset;
+ unsigned total;
+ isl_int m;
+ isl_int **lower_line, **upper_line;
+
+ if (!bset)
+ return -1;
+ offset = basic_set_offset(bset, type);
+ total = isl_basic_set_total_dim(bset);
+ isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
+ isl_int_init(m);
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_zero(bset->ineq[i][offset + pos]))
+ continue;
+ if (isl_int_is_one(bset->ineq[i][offset + pos]))
+ continue;
+ if (isl_int_is_negone(bset->ineq[i][offset + pos]))
+ continue;
+ if (isl_seq_first_non_zero(bset->ineq[i]+offset+pos+1,
+ 1+total-offset-pos-1) != -1)
+ continue;
+ for (j = i + 1; j < bset->n_ineq; ++j) {
+ if (!isl_seq_is_neg(bset->ineq[i]+1, bset->ineq[j]+1,
+ total))
+ continue;
+ isl_int_add(m, bset->ineq[i][0], bset->ineq[j][0]);
+ if (isl_int_abs_ge(m, bset->ineq[i][offset+pos]))
+ continue;
+
+ if (isl_int_is_pos(bset->ineq[i][offset+pos])) {
+ lower_line = &bset->ineq[i];
+ upper_line = &bset->ineq[j];
+ } else {
+ lower_line = &bset->ineq[j];
+ upper_line = &bset->ineq[i];
+ }
+ *lower = isl_basic_set_constraint(
+ isl_basic_set_copy(bset), lower_line);
+ *upper = isl_basic_set_constraint(
+ isl_basic_set_copy(bset), upper_line);
+ isl_int_clear(m);
+ return 1;
+ }
+ }
+ *lower = NULL;
+ *upper = NULL;
+ isl_int_clear(m);
+ return 0;
+}
+
+/* Given two constraints "a" and "b" on the variable at position "abs_pos"
+ * (in "a" and "b"), add a constraint to "bset" that ensures that the
+ * bound implied by "a" is (strictly) larger than the bound implied by "b".
+ *
+ * If both constraints imply lower bounds, then this means that "a" is
+ * active in the result.
+ * If both constraints imply upper bounds, then this means that "b" is
+ * active in the result.
+ */
+static __isl_give isl_basic_set *add_larger_bound_constraint(
+ __isl_take isl_basic_set *bset, isl_int *a, isl_int *b,
+ unsigned abs_pos, int strict)
+{
+ int k;
+ isl_int t;
+ unsigned total;
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+
+ total = isl_basic_set_dim(bset, isl_dim_all);
+
+ isl_int_init(t);
+ isl_int_neg(t, b[1 + abs_pos]);
+
+ isl_seq_combine(bset->ineq[k], t, a, a[1 + abs_pos], b, 1 + abs_pos);
+ isl_seq_combine(bset->ineq[k] + 1 + abs_pos,
+ t, a + 1 + abs_pos + 1, a[1 + abs_pos], b + 1 + abs_pos + 1,
+ total - abs_pos);
+
+ if (strict)
+ isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+
+ isl_int_clear(t);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Add constraints to "context" that ensure that "u" is the smallest
+ * (and therefore active) upper bound on "abs_pos" in "bset" and return
+ * the resulting basic set.
+ */
+static __isl_give isl_basic_set *set_smallest_upper_bound(
+ __isl_keep isl_basic_set *context,
+ __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_upper, int u)
+{
+ int j;
+
+ context = isl_basic_set_copy(context);
+ context = isl_basic_set_cow(context);
+
+ context = isl_basic_set_extend_constraints(context, 0, n_upper - 1);
+
+ for (j = 0; j < bset->n_ineq; ++j) {
+ if (j == u)
+ continue;
+ if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos]))
+ continue;
+ context = add_larger_bound_constraint(context,
+ bset->ineq[j], bset->ineq[u], abs_pos, j > u);
+ }
+
+ context = isl_basic_set_simplify(context);
+ context = isl_basic_set_finalize(context);
+
+ return context;
+}
+
+/* Add constraints to "context" that ensure that "u" is the largest
+ * (and therefore active) upper bound on "abs_pos" in "bset" and return
+ * the resulting basic set.
+ */
+static __isl_give isl_basic_set *set_largest_lower_bound(
+ __isl_keep isl_basic_set *context,
+ __isl_keep isl_basic_set *bset, unsigned abs_pos, int n_lower, int l)
+{
+ int j;
+
+ context = isl_basic_set_copy(context);
+ context = isl_basic_set_cow(context);
+
+ context = isl_basic_set_extend_constraints(context, 0, n_lower - 1);
+
+ for (j = 0; j < bset->n_ineq; ++j) {
+ if (j == l)
+ continue;
+ if (!isl_int_is_pos(bset->ineq[j][1 + abs_pos]))
+ continue;
+ context = add_larger_bound_constraint(context,
+ bset->ineq[l], bset->ineq[j], abs_pos, j > l);
+ }
+
+ context = isl_basic_set_simplify(context);
+ context = isl_basic_set_finalize(context);
+
+ return context;
+}
+
+static int foreach_upper_bound(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned abs_pos,
+ __isl_take isl_basic_set *context, int n_upper,
+ int (*fn)(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper,
+ __isl_take isl_basic_set *bset, void *user), void *user)
+{
+ isl_basic_set *context_i;
+ isl_constraint *upper = NULL;
+ int i;
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_zero(bset->ineq[i][1 + abs_pos]))
+ continue;
+
+ context_i = set_smallest_upper_bound(context, bset,
+ abs_pos, n_upper, i);
+ if (isl_basic_set_is_empty(context_i)) {
+ isl_basic_set_free(context_i);
+ continue;
+ }
+ upper = isl_basic_set_constraint(isl_basic_set_copy(bset),
+ &bset->ineq[i]);
+ if (!upper || !context_i)
+ goto error;
+ if (fn(NULL, upper, context_i, user) < 0)
+ break;
+ }
+
+ isl_basic_set_free(context);
+
+ if (i < bset->n_ineq)
+ return -1;
+
+ return 0;
+error:
+ isl_constraint_free(upper);
+ isl_basic_set_free(context_i);
+ isl_basic_set_free(context);
+ return -1;
+}
+
+static int foreach_lower_bound(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned abs_pos,
+ __isl_take isl_basic_set *context, int n_lower,
+ int (*fn)(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper,
+ __isl_take isl_basic_set *bset, void *user), void *user)
+{
+ isl_basic_set *context_i;
+ isl_constraint *lower = NULL;
+ int i;
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_zero(bset->ineq[i][1 + abs_pos]))
+ continue;
+
+ context_i = set_largest_lower_bound(context, bset,
+ abs_pos, n_lower, i);
+ if (isl_basic_set_is_empty(context_i)) {
+ isl_basic_set_free(context_i);
+ continue;
+ }
+ lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
+ &bset->ineq[i]);
+ if (!lower || !context_i)
+ goto error;
+ if (fn(lower, NULL, context_i, user) < 0)
+ break;
+ }
+
+ isl_basic_set_free(context);
+
+ if (i < bset->n_ineq)
+ return -1;
+
+ return 0;
+error:
+ isl_constraint_free(lower);
+ isl_basic_set_free(context_i);
+ isl_basic_set_free(context);
+ return -1;
+}
+
+static int foreach_bound_pair(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned abs_pos,
+ __isl_take isl_basic_set *context, int n_lower, int n_upper,
+ int (*fn)(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper,
+ __isl_take isl_basic_set *bset, void *user), void *user)
+{
+ isl_basic_set *context_i, *context_j;
+ isl_constraint *lower = NULL;
+ isl_constraint *upper = NULL;
+ int i, j;
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (!isl_int_is_pos(bset->ineq[i][1 + abs_pos]))
+ continue;
+
+ context_i = set_largest_lower_bound(context, bset,
+ abs_pos, n_lower, i);
+ if (isl_basic_set_is_empty(context_i)) {
+ isl_basic_set_free(context_i);
+ continue;
+ }
+
+ for (j = 0; j < bset->n_ineq; ++j) {
+ if (!isl_int_is_neg(bset->ineq[j][1 + abs_pos]))
+ continue;
+
+ context_j = set_smallest_upper_bound(context_i, bset,
+ abs_pos, n_upper, j);
+ context_j = isl_basic_set_extend_constraints(context_j,
+ 0, 1);
+ context_j = add_larger_bound_constraint(context_j,
+ bset->ineq[i], bset->ineq[j], abs_pos, 0);
+ context_j = isl_basic_set_simplify(context_j);
+ context_j = isl_basic_set_finalize(context_j);
+ if (isl_basic_set_is_empty(context_j)) {
+ isl_basic_set_free(context_j);
+ continue;
+ }
+ lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
+ &bset->ineq[i]);
+ upper = isl_basic_set_constraint(isl_basic_set_copy(bset),
+ &bset->ineq[j]);
+ if (!lower || !upper || !context_j)
+ goto error;
+ if (fn(lower, upper, context_j, user) < 0)
+ break;
+ }
+
+ isl_basic_set_free(context_i);
+
+ if (j < bset->n_ineq)
+ break;
+ }
+
+ isl_basic_set_free(context);
+
+ if (i < bset->n_ineq)
+ return -1;
+
+ return 0;
+error:
+ isl_constraint_free(lower);
+ isl_constraint_free(upper);
+ isl_basic_set_free(context_i);
+ isl_basic_set_free(context_j);
+ isl_basic_set_free(context);
+ return -1;
+}
+
+/* For each pair of lower and upper bounds on the variable "pos"
+ * of type "type", call "fn" with these lower and upper bounds and the
+ * set of constraints on the remaining variables where these bounds
+ * are active, i.e., (stricly) larger/smaller than the other lower/upper bounds.
+ *
+ * If the designated variable is equal to an affine combination of the
+ * other variables then fn is called with both lower and upper
+ * set to the corresponding equality.
+ *
+ * If there is no lower (or upper) bound, then NULL is passed
+ * as the corresponding bound.
+ *
+ * We first check if the variable is involved in any equality.
+ * If not, we count the number of lower and upper bounds and
+ * act accordingly.
+ */
+int isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos,
+ int (*fn)(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper,
+ __isl_take isl_basic_set *bset, void *user), void *user)
+{
+ int i;
+ isl_constraint *lower = NULL;
+ isl_constraint *upper = NULL;
+ isl_basic_set *context = NULL;
+ unsigned abs_pos;
+ int n_lower, n_upper;
+
+ if (!bset)
+ return -1;
+ isl_assert(bset->ctx, pos < isl_basic_set_dim(bset, type), return -1);
+ isl_assert(bset->ctx, type == isl_dim_param || type == isl_dim_set,
+ return -1);
+
+ abs_pos = pos;
+ if (type == isl_dim_set)
+ abs_pos += isl_basic_set_dim(bset, isl_dim_param);
+
+ for (i = 0; i < bset->n_eq; ++i) {
+ if (isl_int_is_zero(bset->eq[i][1 + abs_pos]))
+ continue;
+
+ lower = isl_basic_set_constraint(isl_basic_set_copy(bset),
+ &bset->eq[i]);
+ upper = isl_constraint_copy(lower);
+ context = isl_basic_set_remove_dims(isl_basic_set_copy(bset),
+ type, pos, 1);
+ if (!lower || !upper || !context)
+ goto error;
+ return fn(lower, upper, context, user);
+ }
+
+ n_lower = 0;
+ n_upper = 0;
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_pos(bset->ineq[i][1 + abs_pos]))
+ n_lower++;
+ else if (isl_int_is_neg(bset->ineq[i][1 + abs_pos]))
+ n_upper++;
+ }
+
+ context = isl_basic_set_copy(bset);
+ context = isl_basic_set_cow(context);
+ if (!context)
+ goto error;
+ for (i = context->n_ineq - 1; i >= 0; --i)
+ if (!isl_int_is_zero(context->ineq[i][1 + abs_pos]))
+ isl_basic_set_drop_inequality(context, i);
+
+ context = isl_basic_set_drop(context, type, pos, 1);
+ if (!n_lower && !n_upper)
+ return fn(NULL, NULL, context, user);
+ if (!n_lower)
+ return foreach_upper_bound(bset, type, abs_pos, context, n_upper,
+ fn, user);
+ if (!n_upper)
+ return foreach_lower_bound(bset, type, abs_pos, context, n_lower,
+ fn, user);
+ return foreach_bound_pair(bset, type, abs_pos, context, n_lower, n_upper,
+ fn, user);
+error:
+ isl_constraint_free(lower);
+ isl_constraint_free(upper);
+ isl_basic_set_free(context);
+ return -1;
+}
+
+__isl_give isl_aff *isl_constraint_get_bound(
+ __isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos)
+{
+ isl_aff *aff;
+ isl_ctx *ctx;
+
+ if (!constraint)
+ return NULL;
+ ctx = isl_constraint_get_ctx(constraint);
+ if (pos >= isl_constraint_dim(constraint, type))
+ isl_die(ctx, isl_error_invalid,
+ "index out of bounds", return NULL);
+ if (isl_constraint_dim(constraint, isl_dim_in) != 0)
+ isl_die(ctx, isl_error_invalid,
+ "not a set constraint", return NULL);
+
+ pos += offset(constraint, type);
+ if (isl_int_is_zero(constraint->v->el[pos]))
+ isl_die(ctx, isl_error_invalid,
+ "constraint does not define a bound on given dimension",
+ return NULL);
+
+ aff = isl_aff_alloc(isl_local_space_copy(constraint->ls));
+ if (!aff)
+ return NULL;
+
+ if (isl_int_is_neg(constraint->v->el[pos]))
+ isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
+ else
+ isl_seq_neg(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
+ isl_int_set_si(aff->v->el[1 + pos], 0);
+ isl_int_abs(aff->v->el[0], constraint->v->el[pos]);
+
+ return aff;
+}
+
+/* For an inequality constraint
+ *
+ * f >= 0
+ *
+ * or an equality constraint
+ *
+ * f = 0
+ *
+ * return the affine expression f.
+ */
+__isl_give isl_aff *isl_constraint_get_aff(
+ __isl_keep isl_constraint *constraint)
+{
+ isl_aff *aff;
+
+ if (!constraint)
+ return NULL;
+
+ aff = isl_aff_alloc(isl_local_space_copy(constraint->ls));
+ if (!aff)
+ return NULL;
+
+ isl_seq_cpy(aff->v->el + 1, constraint->v->el, aff->v->size - 1);
+ isl_int_set_si(aff->v->el[0], 1);
+
+ return aff;
+}
+
+/* Construct an inequality (eq = 0) or equality (eq = 1) constraint from "aff".
+ * In particular, construct aff >= 0 or aff = 0.
+ *
+ * The denominator of "aff" can be ignored.
+ */
+static __isl_give isl_constraint *isl_constraint_alloc_aff(int eq,
+ __isl_take isl_aff *aff)
+{
+ isl_local_space *ls;
+ isl_vec *v;
+
+ if (!aff)
+ return NULL;
+ ls = isl_aff_get_domain_local_space(aff);
+ v = isl_vec_drop_els(isl_vec_copy(aff->v), 0, 1);
+ isl_aff_free(aff);
+
+ return isl_constraint_alloc_vec(eq, ls, v);
+}
+
+/* Construct an equality constraint equating the given affine expression
+ * to zero.
+ */
+__isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff)
+{
+ return isl_constraint_alloc_aff(1, aff);
+}
+
+/* Construct an inequality constraint enforcing the given affine expression
+ * to be non-negative.
+ */
+__isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff)
+{
+ return isl_constraint_alloc_aff(0, aff);
+}
+
+/* Compare two isl_constraints.
+ *
+ * Return -1 if "c1" is "smaller" than "c2", 1 if "c1" is "greater"
+ * than "c2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary. We do consider constraints that only involve
+ * earlier dimensions as "smaller".
+ */
+int isl_constraint_plain_cmp(__isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2)
+{
+ int cmp;
+ int last1, last2;
+
+ if (c1 == c2)
+ return 0;
+ if (!c1)
+ return -1;
+ if (!c2)
+ return 1;
+ cmp = isl_local_space_cmp(c1->ls, c2->ls);
+ if (cmp != 0)
+ return cmp;
+
+ last1 = isl_seq_last_non_zero(c1->v->el + 1, c1->v->size - 1);
+ last2 = isl_seq_last_non_zero(c2->v->el + 1, c1->v->size - 1);
+ if (last1 != last2)
+ return last1 - last2;
+
+ return isl_seq_cmp(c1->v->el, c2->v->el, c1->v->size);
+}
+
+/* Compare two constraints based on their final (non-zero) coefficients.
+ * In particular, the constraint that involves later variables or
+ * that has a larger coefficient for a shared latest variable
+ * is considered "greater" than the other constraint.
+ *
+ * Return -1 if "c1" is "smaller" than "c2", 1 if "c1" is "greater"
+ * than "c2" and 0 if they are equal.
+ *
+ * If the constraints live in different local spaces, then we cannot
+ * really compare the constraints so we compare the local spaces instead.
+ */
+int isl_constraint_cmp_last_non_zero(__isl_keep isl_constraint *c1,
+ __isl_keep isl_constraint *c2)
+{
+ int cmp;
+ int last1, last2;
+
+ if (c1 == c2)
+ return 0;
+ if (!c1)
+ return -1;
+ if (!c2)
+ return 1;
+ cmp = isl_local_space_cmp(c1->ls, c2->ls);
+ if (cmp != 0)
+ return cmp;
+
+ last1 = isl_seq_last_non_zero(c1->v->el + 1, c1->v->size - 1);
+ last2 = isl_seq_last_non_zero(c2->v->el + 1, c1->v->size - 1);
+ if (last1 != last2)
+ return last1 - last2;
+ if (last1 == -1)
+ return 0;
+ return isl_int_abs_cmp(c1->v->el[1 + last1], c2->v->el[1 + last2]);
+}
diff --git a/polly/lib/External/isl/isl_constraint_private.h b/polly/lib/External/isl/isl_constraint_private.h
new file mode 100644
index 00000000000..5cef0170e80
--- /dev/null
+++ b/polly/lib/External/isl/isl_constraint_private.h
@@ -0,0 +1,32 @@
+#ifndef ISL_CONSTRAINT_PRIVATE_H
+#define ISL_CONSTRAINT_PRIVATE_H
+
+#include <isl/constraint.h>
+#include <isl/local_space.h>
+#include <isl/vec.h>
+
+struct isl_constraint {
+ int ref;
+
+ int eq;
+ isl_local_space *ls;
+ isl_vec *v;
+};
+
+#undef EL
+#define EL isl_constraint
+
+#include <isl_list_templ.h>
+
+struct isl_constraint *isl_basic_set_constraint(struct isl_basic_set *bset,
+ isl_int **line);
+
+void isl_constraint_get_coefficient(__isl_keep isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_constraint *isl_constraint_set_constant(
+ __isl_take isl_constraint *constraint, isl_int v);
+__isl_give isl_constraint *isl_constraint_set_coefficient(
+ __isl_take isl_constraint *constraint,
+ enum isl_dim_type type, int pos, isl_int v);
+
+#endif
diff --git a/polly/lib/External/isl/isl_convex_hull.c b/polly/lib/External/isl/isl_convex_hull.c
new file mode 100644
index 00000000000..b1254be1783
--- /dev/null
+++ b/polly/lib/External/isl/isl_convex_hull.c
@@ -0,0 +1,2829 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_lp_private.h>
+#include <isl/map.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_options_private.h>
+#include "isl_equalities.h"
+#include "isl_tab.h"
+#include <isl_sort.h>
+
+static struct isl_basic_set *uset_convex_hull_wrap_bounded(struct isl_set *set);
+
+/* Return 1 if constraint c is redundant with respect to the constraints
+ * in bmap. If c is a lower [upper] bound in some variable and bmap
+ * does not have a lower [upper] bound in that variable, then c cannot
+ * be redundant and we do not need solve any lp.
+ */
+int isl_basic_map_constraint_is_redundant(struct isl_basic_map **bmap,
+ isl_int *c, isl_int *opt_n, isl_int *opt_d)
+{
+ enum isl_lp_result res;
+ unsigned total;
+ int i, j;
+
+ if (!bmap)
+ return -1;
+
+ total = isl_basic_map_total_dim(*bmap);
+ for (i = 0; i < total; ++i) {
+ int sign;
+ if (isl_int_is_zero(c[1+i]))
+ continue;
+ sign = isl_int_sgn(c[1+i]);
+ for (j = 0; j < (*bmap)->n_ineq; ++j)
+ if (sign == isl_int_sgn((*bmap)->ineq[j][1+i]))
+ break;
+ if (j == (*bmap)->n_ineq)
+ break;
+ }
+ if (i < total)
+ return 0;
+
+ res = isl_basic_map_solve_lp(*bmap, 0, c, (*bmap)->ctx->one,
+ opt_n, opt_d, NULL);
+ if (res == isl_lp_unbounded)
+ return 0;
+ if (res == isl_lp_error)
+ return -1;
+ if (res == isl_lp_empty) {
+ *bmap = isl_basic_map_set_to_empty(*bmap);
+ return 0;
+ }
+ return !isl_int_is_neg(*opt_n);
+}
+
+int isl_basic_set_constraint_is_redundant(struct isl_basic_set **bset,
+ isl_int *c, isl_int *opt_n, isl_int *opt_d)
+{
+ return isl_basic_map_constraint_is_redundant(
+ (struct isl_basic_map **)bset, c, opt_n, opt_d);
+}
+
+/* Remove redundant
+ * constraints. If the minimal value along the normal of a constraint
+ * is the same if the constraint is removed, then the constraint is redundant.
+ *
+ * Alternatively, we could have intersected the basic map with the
+ * corresponding equality and the checked if the dimension was that
+ * of a facet.
+ */
+__isl_give isl_basic_map *isl_basic_map_remove_redundancies(
+ __isl_take isl_basic_map *bmap)
+{
+ struct isl_tab *tab;
+
+ if (!bmap)
+ return NULL;
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_REDUNDANT))
+ return bmap;
+ if (bmap->n_ineq <= 1)
+ return bmap;
+
+ tab = isl_tab_from_basic_map(bmap, 0);
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
+ goto error;
+ if (isl_tab_detect_redundant(tab) < 0)
+ goto error;
+ bmap = isl_basic_map_update_from_tab(bmap, tab);
+ isl_tab_free(tab);
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+ return bmap;
+error:
+ isl_tab_free(tab);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_remove_redundancies(
+ __isl_take isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_remove_redundancies((struct isl_basic_map *)bset);
+}
+
+/* Remove redundant constraints in each of the basic maps.
+ */
+__isl_give isl_map *isl_map_remove_redundancies(__isl_take isl_map *map)
+{
+ return isl_map_inline_foreach_basic_map(map,
+ &isl_basic_map_remove_redundancies);
+}
+
+__isl_give isl_set *isl_set_remove_redundancies(__isl_take isl_set *set)
+{
+ return isl_map_remove_redundancies(set);
+}
+
+/* Check if the set set is bound in the direction of the affine
+ * constraint c and if so, set the constant term such that the
+ * resulting constraint is a bounding constraint for the set.
+ */
+static int uset_is_bound(struct isl_set *set, isl_int *c, unsigned len)
+{
+ int first;
+ int j;
+ isl_int opt;
+ isl_int opt_denom;
+
+ isl_int_init(opt);
+ isl_int_init(opt_denom);
+ first = 1;
+ for (j = 0; j < set->n; ++j) {
+ enum isl_lp_result res;
+
+ if (ISL_F_ISSET(set->p[j], ISL_BASIC_SET_EMPTY))
+ continue;
+
+ res = isl_basic_set_solve_lp(set->p[j],
+ 0, c, set->ctx->one, &opt, &opt_denom, NULL);
+ if (res == isl_lp_unbounded)
+ break;
+ if (res == isl_lp_error)
+ goto error;
+ if (res == isl_lp_empty) {
+ set->p[j] = isl_basic_set_set_to_empty(set->p[j]);
+ if (!set->p[j])
+ goto error;
+ continue;
+ }
+ if (first || isl_int_is_neg(opt)) {
+ if (!isl_int_is_one(opt_denom))
+ isl_seq_scale(c, c, opt_denom, len);
+ isl_int_sub(c[0], c[0], opt);
+ }
+ first = 0;
+ }
+ isl_int_clear(opt);
+ isl_int_clear(opt_denom);
+ return j >= set->n;
+error:
+ isl_int_clear(opt);
+ isl_int_clear(opt_denom);
+ return -1;
+}
+
+__isl_give isl_basic_map *isl_basic_map_set_rational(
+ __isl_take isl_basic_set *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
+
+ return isl_basic_map_finalize(bmap);
+}
+
+__isl_give isl_basic_set *isl_basic_set_set_rational(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_set_rational(bset);
+}
+
+__isl_give isl_map *isl_map_set_rational(__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_set_rational(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set)
+{
+ return isl_map_set_rational(set);
+}
+
+static struct isl_basic_set *isl_basic_set_add_equality(
+ struct isl_basic_set *bset, isl_int *c)
+{
+ int i;
+ unsigned dim;
+
+ if (!bset)
+ return NULL;
+
+ if (ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY))
+ return bset;
+
+ isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
+ isl_assert(bset->ctx, bset->n_div == 0, goto error);
+ dim = isl_basic_set_n_dim(bset);
+ bset = isl_basic_set_cow(bset);
+ bset = isl_basic_set_extend(bset, 0, dim, 0, 1, 0);
+ i = isl_basic_set_alloc_equality(bset);
+ if (i < 0)
+ goto error;
+ isl_seq_cpy(bset->eq[i], c, 1 + dim);
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static struct isl_set *isl_set_add_basic_set_equality(struct isl_set *set, isl_int *c)
+{
+ int i;
+
+ set = isl_set_cow(set);
+ if (!set)
+ return NULL;
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_add_equality(set->p[i], c);
+ if (!set->p[i])
+ goto error;
+ }
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Given a union of basic sets, construct the constraints for wrapping
+ * a facet around one of its ridges.
+ * In particular, if each of n the d-dimensional basic sets i in "set"
+ * contains the origin, satisfies the constraints x_1 >= 0 and x_2 >= 0
+ * and is defined by the constraints
+ * [ 1 ]
+ * A_i [ x ] >= 0
+ *
+ * then the resulting set is of dimension n*(1+d) and has as constraints
+ *
+ * [ a_i ]
+ * A_i [ x_i ] >= 0
+ *
+ * a_i >= 0
+ *
+ * \sum_i x_{i,1} = 1
+ */
+static struct isl_basic_set *wrap_constraints(struct isl_set *set)
+{
+ struct isl_basic_set *lp;
+ unsigned n_eq;
+ unsigned n_ineq;
+ int i, j, k;
+ unsigned dim, lp_dim;
+
+ if (!set)
+ return NULL;
+
+ dim = 1 + isl_set_n_dim(set);
+ n_eq = 1;
+ n_ineq = set->n;
+ for (i = 0; i < set->n; ++i) {
+ n_eq += set->p[i]->n_eq;
+ n_ineq += set->p[i]->n_ineq;
+ }
+ lp = isl_basic_set_alloc(set->ctx, 0, dim * set->n, 0, n_eq, n_ineq);
+ lp = isl_basic_set_set_rational(lp);
+ if (!lp)
+ return NULL;
+ lp_dim = isl_basic_set_n_dim(lp);
+ k = isl_basic_set_alloc_equality(lp);
+ isl_int_set_si(lp->eq[k][0], -1);
+ for (i = 0; i < set->n; ++i) {
+ isl_int_set_si(lp->eq[k][1+dim*i], 0);
+ isl_int_set_si(lp->eq[k][1+dim*i+1], 1);
+ isl_seq_clr(lp->eq[k]+1+dim*i+2, dim-2);
+ }
+ for (i = 0; i < set->n; ++i) {
+ k = isl_basic_set_alloc_inequality(lp);
+ isl_seq_clr(lp->ineq[k], 1+lp_dim);
+ isl_int_set_si(lp->ineq[k][1+dim*i], 1);
+
+ for (j = 0; j < set->p[i]->n_eq; ++j) {
+ k = isl_basic_set_alloc_equality(lp);
+ isl_seq_clr(lp->eq[k], 1+dim*i);
+ isl_seq_cpy(lp->eq[k]+1+dim*i, set->p[i]->eq[j], dim);
+ isl_seq_clr(lp->eq[k]+1+dim*(i+1), dim*(set->n-i-1));
+ }
+
+ for (j = 0; j < set->p[i]->n_ineq; ++j) {
+ k = isl_basic_set_alloc_inequality(lp);
+ isl_seq_clr(lp->ineq[k], 1+dim*i);
+ isl_seq_cpy(lp->ineq[k]+1+dim*i, set->p[i]->ineq[j], dim);
+ isl_seq_clr(lp->ineq[k]+1+dim*(i+1), dim*(set->n-i-1));
+ }
+ }
+ return lp;
+}
+
+/* Given a facet "facet" of the convex hull of "set" and a facet "ridge"
+ * of that facet, compute the other facet of the convex hull that contains
+ * the ridge.
+ *
+ * We first transform the set such that the facet constraint becomes
+ *
+ * x_1 >= 0
+ *
+ * I.e., the facet lies in
+ *
+ * x_1 = 0
+ *
+ * and on that facet, the constraint that defines the ridge is
+ *
+ * x_2 >= 0
+ *
+ * (This transformation is not strictly needed, all that is needed is
+ * that the ridge contains the origin.)
+ *
+ * Since the ridge contains the origin, the cone of the convex hull
+ * will be of the form
+ *
+ * x_1 >= 0
+ * x_2 >= a x_1
+ *
+ * with this second constraint defining the new facet.
+ * The constant a is obtained by settting x_1 in the cone of the
+ * convex hull to 1 and minimizing x_2.
+ * Now, each element in the cone of the convex hull is the sum
+ * of elements in the cones of the basic sets.
+ * If a_i is the dilation factor of basic set i, then the problem
+ * we need to solve is
+ *
+ * min \sum_i x_{i,2}
+ * st
+ * \sum_i x_{i,1} = 1
+ * a_i >= 0
+ * [ a_i ]
+ * A [ x_i ] >= 0
+ *
+ * with
+ * [ 1 ]
+ * A_i [ x_i ] >= 0
+ *
+ * the constraints of each (transformed) basic set.
+ * If a = n/d, then the constraint defining the new facet (in the transformed
+ * space) is
+ *
+ * -n x_1 + d x_2 >= 0
+ *
+ * In the original space, we need to take the same combination of the
+ * corresponding constraints "facet" and "ridge".
+ *
+ * If a = -infty = "-1/0", then we just return the original facet constraint.
+ * This means that the facet is unbounded, but has a bounded intersection
+ * with the union of sets.
+ */
+isl_int *isl_set_wrap_facet(__isl_keep isl_set *set,
+ isl_int *facet, isl_int *ridge)
+{
+ int i;
+ isl_ctx *ctx;
+ struct isl_mat *T = NULL;
+ struct isl_basic_set *lp = NULL;
+ struct isl_vec *obj;
+ enum isl_lp_result res;
+ isl_int num, den;
+ unsigned dim;
+
+ if (!set)
+ return NULL;
+ ctx = set->ctx;
+ set = isl_set_copy(set);
+ set = isl_set_set_rational(set);
+
+ dim = 1 + isl_set_n_dim(set);
+ T = isl_mat_alloc(ctx, 3, dim);
+ if (!T)
+ goto error;
+ isl_int_set_si(T->row[0][0], 1);
+ isl_seq_clr(T->row[0]+1, dim - 1);
+ isl_seq_cpy(T->row[1], facet, dim);
+ isl_seq_cpy(T->row[2], ridge, dim);
+ T = isl_mat_right_inverse(T);
+ set = isl_set_preimage(set, T);
+ T = NULL;
+ if (!set)
+ goto error;
+ lp = wrap_constraints(set);
+ obj = isl_vec_alloc(ctx, 1 + dim*set->n);
+ if (!obj)
+ goto error;
+ isl_int_set_si(obj->block.data[0], 0);
+ for (i = 0; i < set->n; ++i) {
+ isl_seq_clr(obj->block.data + 1 + dim*i, 2);
+ isl_int_set_si(obj->block.data[1 + dim*i+2], 1);
+ isl_seq_clr(obj->block.data + 1 + dim*i+3, dim-3);
+ }
+ isl_int_init(num);
+ isl_int_init(den);
+ res = isl_basic_set_solve_lp(lp, 0,
+ obj->block.data, ctx->one, &num, &den, NULL);
+ if (res == isl_lp_ok) {
+ isl_int_neg(num, num);
+ isl_seq_combine(facet, num, facet, den, ridge, dim);
+ isl_seq_normalize(ctx, facet, dim);
+ }
+ isl_int_clear(num);
+ isl_int_clear(den);
+ isl_vec_free(obj);
+ isl_basic_set_free(lp);
+ isl_set_free(set);
+ if (res == isl_lp_error)
+ return NULL;
+ isl_assert(ctx, res == isl_lp_ok || res == isl_lp_unbounded,
+ return NULL);
+ return facet;
+error:
+ isl_basic_set_free(lp);
+ isl_mat_free(T);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Compute the constraint of a facet of "set".
+ *
+ * We first compute the intersection with a bounding constraint
+ * that is orthogonal to one of the coordinate axes.
+ * If the affine hull of this intersection has only one equality,
+ * we have found a facet.
+ * Otherwise, we wrap the current bounding constraint around
+ * one of the equalities of the face (one that is not equal to
+ * the current bounding constraint).
+ * This process continues until we have found a facet.
+ * The dimension of the intersection increases by at least
+ * one on each iteration, so termination is guaranteed.
+ */
+static __isl_give isl_mat *initial_facet_constraint(__isl_keep isl_set *set)
+{
+ struct isl_set *slice = NULL;
+ struct isl_basic_set *face = NULL;
+ int i;
+ unsigned dim = isl_set_n_dim(set);
+ int is_bound;
+ isl_mat *bounds = NULL;
+
+ isl_assert(set->ctx, set->n > 0, goto error);
+ bounds = isl_mat_alloc(set->ctx, 1, 1 + dim);
+ if (!bounds)
+ return NULL;
+
+ isl_seq_clr(bounds->row[0], dim);
+ isl_int_set_si(bounds->row[0][1 + dim - 1], 1);
+ is_bound = uset_is_bound(set, bounds->row[0], 1 + dim);
+ if (is_bound < 0)
+ goto error;
+ isl_assert(set->ctx, is_bound, goto error);
+ isl_seq_normalize(set->ctx, bounds->row[0], 1 + dim);
+ bounds->n_row = 1;
+
+ for (;;) {
+ slice = isl_set_copy(set);
+ slice = isl_set_add_basic_set_equality(slice, bounds->row[0]);
+ face = isl_set_affine_hull(slice);
+ if (!face)
+ goto error;
+ if (face->n_eq == 1) {
+ isl_basic_set_free(face);
+ break;
+ }
+ for (i = 0; i < face->n_eq; ++i)
+ if (!isl_seq_eq(bounds->row[0], face->eq[i], 1 + dim) &&
+ !isl_seq_is_neg(bounds->row[0],
+ face->eq[i], 1 + dim))
+ break;
+ isl_assert(set->ctx, i < face->n_eq, goto error);
+ if (!isl_set_wrap_facet(set, bounds->row[0], face->eq[i]))
+ goto error;
+ isl_seq_normalize(set->ctx, bounds->row[0], bounds->n_col);
+ isl_basic_set_free(face);
+ }
+
+ return bounds;
+error:
+ isl_basic_set_free(face);
+ isl_mat_free(bounds);
+ return NULL;
+}
+
+/* Given the bounding constraint "c" of a facet of the convex hull of "set",
+ * compute a hyperplane description of the facet, i.e., compute the facets
+ * of the facet.
+ *
+ * We compute an affine transformation that transforms the constraint
+ *
+ * [ 1 ]
+ * c [ x ] = 0
+ *
+ * to the constraint
+ *
+ * z_1 = 0
+ *
+ * by computing the right inverse U of a matrix that starts with the rows
+ *
+ * [ 1 0 ]
+ * [ c ]
+ *
+ * Then
+ * [ 1 ] [ 1 ]
+ * [ x ] = U [ z ]
+ * and
+ * [ 1 ] [ 1 ]
+ * [ z ] = Q [ x ]
+ *
+ * with Q = U^{-1}
+ * Since z_1 is zero, we can drop this variable as well as the corresponding
+ * column of U to obtain
+ *
+ * [ 1 ] [ 1 ]
+ * [ x ] = U' [ z' ]
+ * and
+ * [ 1 ] [ 1 ]
+ * [ z' ] = Q' [ x ]
+ *
+ * with Q' equal to Q, but without the corresponding row.
+ * After computing the facets of the facet in the z' space,
+ * we convert them back to the x space through Q.
+ */
+static struct isl_basic_set *compute_facet(struct isl_set *set, isl_int *c)
+{
+ struct isl_mat *m, *U, *Q;
+ struct isl_basic_set *facet = NULL;
+ struct isl_ctx *ctx;
+ unsigned dim;
+
+ ctx = set->ctx;
+ set = isl_set_copy(set);
+ dim = isl_set_n_dim(set);
+ m = isl_mat_alloc(set->ctx, 2, 1 + dim);
+ if (!m)
+ goto error;
+ isl_int_set_si(m->row[0][0], 1);
+ isl_seq_clr(m->row[0]+1, dim);
+ isl_seq_cpy(m->row[1], c, 1+dim);
+ U = isl_mat_right_inverse(m);
+ Q = isl_mat_right_inverse(isl_mat_copy(U));
+ U = isl_mat_drop_cols(U, 1, 1);
+ Q = isl_mat_drop_rows(Q, 1, 1);
+ set = isl_set_preimage(set, U);
+ facet = uset_convex_hull_wrap_bounded(set);
+ facet = isl_basic_set_preimage(facet, Q);
+ if (facet)
+ isl_assert(ctx, facet->n_eq == 0, goto error);
+ return facet;
+error:
+ isl_basic_set_free(facet);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Given an initial facet constraint, compute the remaining facets.
+ * We do this by running through all facets found so far and computing
+ * the adjacent facets through wrapping, adding those facets that we
+ * hadn't already found before.
+ *
+ * For each facet we have found so far, we first compute its facets
+ * in the resulting convex hull. That is, we compute the ridges
+ * of the resulting convex hull contained in the facet.
+ * We also compute the corresponding facet in the current approximation
+ * of the convex hull. There is no need to wrap around the ridges
+ * in this facet since that would result in a facet that is already
+ * present in the current approximation.
+ *
+ * This function can still be significantly optimized by checking which of
+ * the facets of the basic sets are also facets of the convex hull and
+ * using all the facets so far to help in constructing the facets of the
+ * facets
+ * and/or
+ * using the technique in section "3.1 Ridge Generation" of
+ * "Extended Convex Hull" by Fukuda et al.
+ */
+static struct isl_basic_set *extend(struct isl_basic_set *hull,
+ struct isl_set *set)
+{
+ int i, j, f;
+ int k;
+ struct isl_basic_set *facet = NULL;
+ struct isl_basic_set *hull_facet = NULL;
+ unsigned dim;
+
+ if (!hull)
+ return NULL;
+
+ isl_assert(set->ctx, set->n > 0, goto error);
+
+ dim = isl_set_n_dim(set);
+
+ for (i = 0; i < hull->n_ineq; ++i) {
+ facet = compute_facet(set, hull->ineq[i]);
+ facet = isl_basic_set_add_equality(facet, hull->ineq[i]);
+ facet = isl_basic_set_gauss(facet, NULL);
+ facet = isl_basic_set_normalize_constraints(facet);
+ hull_facet = isl_basic_set_copy(hull);
+ hull_facet = isl_basic_set_add_equality(hull_facet, hull->ineq[i]);
+ hull_facet = isl_basic_set_gauss(hull_facet, NULL);
+ hull_facet = isl_basic_set_normalize_constraints(hull_facet);
+ if (!facet || !hull_facet)
+ goto error;
+ hull = isl_basic_set_cow(hull);
+ hull = isl_basic_set_extend_space(hull,
+ isl_space_copy(hull->dim), 0, 0, facet->n_ineq);
+ if (!hull)
+ goto error;
+ for (j = 0; j < facet->n_ineq; ++j) {
+ for (f = 0; f < hull_facet->n_ineq; ++f)
+ if (isl_seq_eq(facet->ineq[j],
+ hull_facet->ineq[f], 1 + dim))
+ break;
+ if (f < hull_facet->n_ineq)
+ continue;
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(hull->ineq[k], hull->ineq[i], 1+dim);
+ if (!isl_set_wrap_facet(set, hull->ineq[k], facet->ineq[j]))
+ goto error;
+ }
+ isl_basic_set_free(hull_facet);
+ isl_basic_set_free(facet);
+ }
+ hull = isl_basic_set_simplify(hull);
+ hull = isl_basic_set_finalize(hull);
+ return hull;
+error:
+ isl_basic_set_free(hull_facet);
+ isl_basic_set_free(facet);
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Special case for computing the convex hull of a one dimensional set.
+ * We simply collect the lower and upper bounds of each basic set
+ * and the biggest of those.
+ */
+static struct isl_basic_set *convex_hull_1d(struct isl_set *set)
+{
+ struct isl_mat *c = NULL;
+ isl_int *lower = NULL;
+ isl_int *upper = NULL;
+ int i, j, k;
+ isl_int a, b;
+ struct isl_basic_set *hull;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_simplify(set->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+ set = isl_set_remove_empty_parts(set);
+ if (!set)
+ goto error;
+ isl_assert(set->ctx, set->n > 0, goto error);
+ c = isl_mat_alloc(set->ctx, 2, 2);
+ if (!c)
+ goto error;
+
+ if (set->p[0]->n_eq > 0) {
+ isl_assert(set->ctx, set->p[0]->n_eq == 1, goto error);
+ lower = c->row[0];
+ upper = c->row[1];
+ if (isl_int_is_pos(set->p[0]->eq[0][1])) {
+ isl_seq_cpy(lower, set->p[0]->eq[0], 2);
+ isl_seq_neg(upper, set->p[0]->eq[0], 2);
+ } else {
+ isl_seq_neg(lower, set->p[0]->eq[0], 2);
+ isl_seq_cpy(upper, set->p[0]->eq[0], 2);
+ }
+ } else {
+ for (j = 0; j < set->p[0]->n_ineq; ++j) {
+ if (isl_int_is_pos(set->p[0]->ineq[j][1])) {
+ lower = c->row[0];
+ isl_seq_cpy(lower, set->p[0]->ineq[j], 2);
+ } else {
+ upper = c->row[1];
+ isl_seq_cpy(upper, set->p[0]->ineq[j], 2);
+ }
+ }
+ }
+
+ isl_int_init(a);
+ isl_int_init(b);
+ for (i = 0; i < set->n; ++i) {
+ struct isl_basic_set *bset = set->p[i];
+ int has_lower = 0;
+ int has_upper = 0;
+
+ for (j = 0; j < bset->n_eq; ++j) {
+ has_lower = 1;
+ has_upper = 1;
+ if (lower) {
+ isl_int_mul(a, lower[0], bset->eq[j][1]);
+ isl_int_mul(b, lower[1], bset->eq[j][0]);
+ if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
+ isl_seq_cpy(lower, bset->eq[j], 2);
+ if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
+ isl_seq_neg(lower, bset->eq[j], 2);
+ }
+ if (upper) {
+ isl_int_mul(a, upper[0], bset->eq[j][1]);
+ isl_int_mul(b, upper[1], bset->eq[j][0]);
+ if (isl_int_lt(a, b) && isl_int_is_pos(bset->eq[j][1]))
+ isl_seq_neg(upper, bset->eq[j], 2);
+ if (isl_int_gt(a, b) && isl_int_is_neg(bset->eq[j][1]))
+ isl_seq_cpy(upper, bset->eq[j], 2);
+ }
+ }
+ for (j = 0; j < bset->n_ineq; ++j) {
+ if (isl_int_is_pos(bset->ineq[j][1]))
+ has_lower = 1;
+ if (isl_int_is_neg(bset->ineq[j][1]))
+ has_upper = 1;
+ if (lower && isl_int_is_pos(bset->ineq[j][1])) {
+ isl_int_mul(a, lower[0], bset->ineq[j][1]);
+ isl_int_mul(b, lower[1], bset->ineq[j][0]);
+ if (isl_int_lt(a, b))
+ isl_seq_cpy(lower, bset->ineq[j], 2);
+ }
+ if (upper && isl_int_is_neg(bset->ineq[j][1])) {
+ isl_int_mul(a, upper[0], bset->ineq[j][1]);
+ isl_int_mul(b, upper[1], bset->ineq[j][0]);
+ if (isl_int_gt(a, b))
+ isl_seq_cpy(upper, bset->ineq[j], 2);
+ }
+ }
+ if (!has_lower)
+ lower = NULL;
+ if (!has_upper)
+ upper = NULL;
+ }
+ isl_int_clear(a);
+ isl_int_clear(b);
+
+ hull = isl_basic_set_alloc(set->ctx, 0, 1, 0, 0, 2);
+ hull = isl_basic_set_set_rational(hull);
+ if (!hull)
+ goto error;
+ if (lower) {
+ k = isl_basic_set_alloc_inequality(hull);
+ isl_seq_cpy(hull->ineq[k], lower, 2);
+ }
+ if (upper) {
+ k = isl_basic_set_alloc_inequality(hull);
+ isl_seq_cpy(hull->ineq[k], upper, 2);
+ }
+ hull = isl_basic_set_finalize(hull);
+ isl_set_free(set);
+ isl_mat_free(c);
+ return hull;
+error:
+ isl_set_free(set);
+ isl_mat_free(c);
+ return NULL;
+}
+
+static struct isl_basic_set *convex_hull_0d(struct isl_set *set)
+{
+ struct isl_basic_set *convex_hull;
+
+ if (!set)
+ return NULL;
+
+ if (isl_set_is_empty(set))
+ convex_hull = isl_basic_set_empty(isl_space_copy(set->dim));
+ else
+ convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
+ isl_set_free(set);
+ return convex_hull;
+}
+
+/* Compute the convex hull of a pair of basic sets without any parameters or
+ * integer divisions using Fourier-Motzkin elimination.
+ * The convex hull is the set of all points that can be written as
+ * the sum of points from both basic sets (in homogeneous coordinates).
+ * We set up the constraints in a space with dimensions for each of
+ * the three sets and then project out the dimensions corresponding
+ * to the two original basic sets, retaining only those corresponding
+ * to the convex hull.
+ */
+static struct isl_basic_set *convex_hull_pair_elim(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2)
+{
+ int i, j, k;
+ struct isl_basic_set *bset[2];
+ struct isl_basic_set *hull = NULL;
+ unsigned dim;
+
+ if (!bset1 || !bset2)
+ goto error;
+
+ dim = isl_basic_set_n_dim(bset1);
+ hull = isl_basic_set_alloc(bset1->ctx, 0, 2 + 3 * dim, 0,
+ 1 + dim + bset1->n_eq + bset2->n_eq,
+ 2 + bset1->n_ineq + bset2->n_ineq);
+ bset[0] = bset1;
+ bset[1] = bset2;
+ for (i = 0; i < 2; ++i) {
+ for (j = 0; j < bset[i]->n_eq; ++j) {
+ k = isl_basic_set_alloc_equality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(hull->eq[k], (i+1) * (1+dim));
+ isl_seq_clr(hull->eq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
+ isl_seq_cpy(hull->eq[k]+(i+1)*(1+dim), bset[i]->eq[j],
+ 1+dim);
+ }
+ for (j = 0; j < bset[i]->n_ineq; ++j) {
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(hull->ineq[k], (i+1) * (1+dim));
+ isl_seq_clr(hull->ineq[k]+(i+2)*(1+dim), (1-i)*(1+dim));
+ isl_seq_cpy(hull->ineq[k]+(i+1)*(1+dim),
+ bset[i]->ineq[j], 1+dim);
+ }
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(hull->ineq[k], 1+2+3*dim);
+ isl_int_set_si(hull->ineq[k][(i+1)*(1+dim)], 1);
+ }
+ for (j = 0; j < 1+dim; ++j) {
+ k = isl_basic_set_alloc_equality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(hull->eq[k], 1+2+3*dim);
+ isl_int_set_si(hull->eq[k][j], -1);
+ isl_int_set_si(hull->eq[k][1+dim+j], 1);
+ isl_int_set_si(hull->eq[k][2*(1+dim)+j], 1);
+ }
+ hull = isl_basic_set_set_rational(hull);
+ hull = isl_basic_set_remove_dims(hull, isl_dim_set, dim, 2*(1+dim));
+ hull = isl_basic_set_remove_redundancies(hull);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return hull;
+error:
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Is the set bounded for each value of the parameters?
+ */
+int isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset)
+{
+ struct isl_tab *tab;
+ int bounded;
+
+ if (!bset)
+ return -1;
+ if (isl_basic_set_plain_is_empty(bset))
+ return 1;
+
+ tab = isl_tab_from_recession_cone(bset, 1);
+ bounded = isl_tab_cone_is_bounded(tab);
+ isl_tab_free(tab);
+ return bounded;
+}
+
+/* Is the image bounded for each value of the parameters and
+ * the domain variables?
+ */
+int isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap)
+{
+ unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ int bounded;
+
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_move_dims(bmap, isl_dim_param, nparam,
+ isl_dim_in, 0, n_in);
+ bounded = isl_basic_set_is_bounded((isl_basic_set *)bmap);
+ isl_basic_map_free(bmap);
+
+ return bounded;
+}
+
+/* Is the set bounded for each value of the parameters?
+ */
+int isl_set_is_bounded(__isl_keep isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return -1;
+
+ for (i = 0; i < set->n; ++i) {
+ int bounded = isl_basic_set_is_bounded(set->p[i]);
+ if (!bounded || bounded < 0)
+ return bounded;
+ }
+ return 1;
+}
+
+/* Compute the lineality space of the convex hull of bset1 and bset2.
+ *
+ * We first compute the intersection of the recession cone of bset1
+ * with the negative of the recession cone of bset2 and then compute
+ * the linear hull of the resulting cone.
+ */
+static struct isl_basic_set *induced_lineality_space(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ int i, k;
+ struct isl_basic_set *lin = NULL;
+ unsigned dim;
+
+ if (!bset1 || !bset2)
+ goto error;
+
+ dim = isl_basic_set_total_dim(bset1);
+ lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset1), 0,
+ bset1->n_eq + bset2->n_eq,
+ bset1->n_ineq + bset2->n_ineq);
+ lin = isl_basic_set_set_rational(lin);
+ if (!lin)
+ goto error;
+ for (i = 0; i < bset1->n_eq; ++i) {
+ k = isl_basic_set_alloc_equality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->eq[k][0], 0);
+ isl_seq_cpy(lin->eq[k] + 1, bset1->eq[i] + 1, dim);
+ }
+ for (i = 0; i < bset1->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->ineq[k][0], 0);
+ isl_seq_cpy(lin->ineq[k] + 1, bset1->ineq[i] + 1, dim);
+ }
+ for (i = 0; i < bset2->n_eq; ++i) {
+ k = isl_basic_set_alloc_equality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->eq[k][0], 0);
+ isl_seq_neg(lin->eq[k] + 1, bset2->eq[i] + 1, dim);
+ }
+ for (i = 0; i < bset2->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->ineq[k][0], 0);
+ isl_seq_neg(lin->ineq[k] + 1, bset2->ineq[i] + 1, dim);
+ }
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return isl_basic_set_affine_hull(lin);
+error:
+ isl_basic_set_free(lin);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+static struct isl_basic_set *uset_convex_hull(struct isl_set *set);
+
+/* Given a set and a linear space "lin" of dimension n > 0,
+ * project the linear space from the set, compute the convex hull
+ * and then map the set back to the original space.
+ *
+ * Let
+ *
+ * M x = 0
+ *
+ * describe the linear space. We first compute the Hermite normal
+ * form H = M U of M = H Q, to obtain
+ *
+ * H Q x = 0
+ *
+ * The last n rows of H will be zero, so the last n variables of x' = Q x
+ * are the one we want to project out. We do this by transforming each
+ * basic set A x >= b to A U x' >= b and then removing the last n dimensions.
+ * After computing the convex hull in x'_1, i.e., A' x'_1 >= b',
+ * we transform the hull back to the original space as A' Q_1 x >= b',
+ * with Q_1 all but the last n rows of Q.
+ */
+static struct isl_basic_set *modulo_lineality(struct isl_set *set,
+ struct isl_basic_set *lin)
+{
+ unsigned total = isl_basic_set_total_dim(lin);
+ unsigned lin_dim;
+ struct isl_basic_set *hull;
+ struct isl_mat *M, *U, *Q;
+
+ if (!set || !lin)
+ goto error;
+ lin_dim = total - lin->n_eq;
+ M = isl_mat_sub_alloc6(set->ctx, lin->eq, 0, lin->n_eq, 1, total);
+ M = isl_mat_left_hermite(M, 0, &U, &Q);
+ if (!M)
+ goto error;
+ isl_mat_free(M);
+ isl_basic_set_free(lin);
+
+ Q = isl_mat_drop_rows(Q, Q->n_row - lin_dim, lin_dim);
+
+ U = isl_mat_lin_to_aff(U);
+ Q = isl_mat_lin_to_aff(Q);
+
+ set = isl_set_preimage(set, U);
+ set = isl_set_remove_dims(set, isl_dim_set, total - lin_dim, lin_dim);
+ hull = uset_convex_hull(set);
+ hull = isl_basic_set_preimage(hull, Q);
+
+ return hull;
+error:
+ isl_basic_set_free(lin);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Given two polyhedra with as constraints h_{ij} x >= 0 in homegeneous space,
+ * set up an LP for solving
+ *
+ * \sum_j \alpha_{1j} h_{1j} = \sum_j \alpha_{2j} h_{2j}
+ *
+ * \alpha{i0} corresponds to the (implicit) positivity constraint 1 >= 0
+ * The next \alpha{ij} correspond to the equalities and come in pairs.
+ * The final \alpha{ij} correspond to the inequalities.
+ */
+static struct isl_basic_set *valid_direction_lp(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ isl_space *dim;
+ struct isl_basic_set *lp;
+ unsigned d;
+ int n;
+ int i, j, k;
+
+ if (!bset1 || !bset2)
+ goto error;
+ d = 1 + isl_basic_set_total_dim(bset1);
+ n = 2 +
+ 2 * bset1->n_eq + bset1->n_ineq + 2 * bset2->n_eq + bset2->n_ineq;
+ dim = isl_space_set_alloc(bset1->ctx, 0, n);
+ lp = isl_basic_set_alloc_space(dim, 0, d, n);
+ if (!lp)
+ goto error;
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_set_alloc_inequality(lp);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(lp->ineq[k] + 1, n);
+ isl_int_set_si(lp->ineq[k][0], -1);
+ isl_int_set_si(lp->ineq[k][1 + i], 1);
+ }
+ for (i = 0; i < d; ++i) {
+ k = isl_basic_set_alloc_equality(lp);
+ if (k < 0)
+ goto error;
+ n = 0;
+ isl_int_set_si(lp->eq[k][n], 0); n++;
+ /* positivity constraint 1 >= 0 */
+ isl_int_set_si(lp->eq[k][n], i == 0); n++;
+ for (j = 0; j < bset1->n_eq; ++j) {
+ isl_int_set(lp->eq[k][n], bset1->eq[j][i]); n++;
+ isl_int_neg(lp->eq[k][n], bset1->eq[j][i]); n++;
+ }
+ for (j = 0; j < bset1->n_ineq; ++j) {
+ isl_int_set(lp->eq[k][n], bset1->ineq[j][i]); n++;
+ }
+ /* positivity constraint 1 >= 0 */
+ isl_int_set_si(lp->eq[k][n], -(i == 0)); n++;
+ for (j = 0; j < bset2->n_eq; ++j) {
+ isl_int_neg(lp->eq[k][n], bset2->eq[j][i]); n++;
+ isl_int_set(lp->eq[k][n], bset2->eq[j][i]); n++;
+ }
+ for (j = 0; j < bset2->n_ineq; ++j) {
+ isl_int_neg(lp->eq[k][n], bset2->ineq[j][i]); n++;
+ }
+ }
+ lp = isl_basic_set_gauss(lp, NULL);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return lp;
+error:
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+/* Compute a vector s in the homogeneous space such that <s, r> > 0
+ * for all rays in the homogeneous space of the two cones that correspond
+ * to the input polyhedra bset1 and bset2.
+ *
+ * We compute s as a vector that satisfies
+ *
+ * s = \sum_j \alpha_{ij} h_{ij} for i = 1,2 (*)
+ *
+ * with h_{ij} the normals of the facets of polyhedron i
+ * (including the "positivity constraint" 1 >= 0) and \alpha_{ij}
+ * strictly positive numbers. For simplicity we impose \alpha_{ij} >= 1.
+ * We first set up an LP with as variables the \alpha{ij}.
+ * In this formulation, for each polyhedron i,
+ * the first constraint is the positivity constraint, followed by pairs
+ * of variables for the equalities, followed by variables for the inequalities.
+ * We then simply pick a feasible solution and compute s using (*).
+ *
+ * Note that we simply pick any valid direction and make no attempt
+ * to pick a "good" or even the "best" valid direction.
+ */
+static struct isl_vec *valid_direction(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ struct isl_basic_set *lp;
+ struct isl_tab *tab;
+ struct isl_vec *sample = NULL;
+ struct isl_vec *dir;
+ unsigned d;
+ int i;
+ int n;
+
+ if (!bset1 || !bset2)
+ goto error;
+ lp = valid_direction_lp(isl_basic_set_copy(bset1),
+ isl_basic_set_copy(bset2));
+ tab = isl_tab_from_basic_set(lp, 0);
+ sample = isl_tab_get_sample_value(tab);
+ isl_tab_free(tab);
+ isl_basic_set_free(lp);
+ if (!sample)
+ goto error;
+ d = isl_basic_set_total_dim(bset1);
+ dir = isl_vec_alloc(bset1->ctx, 1 + d);
+ if (!dir)
+ goto error;
+ isl_seq_clr(dir->block.data + 1, dir->size - 1);
+ n = 1;
+ /* positivity constraint 1 >= 0 */
+ isl_int_set(dir->block.data[0], sample->block.data[n]); n++;
+ for (i = 0; i < bset1->n_eq; ++i) {
+ isl_int_sub(sample->block.data[n],
+ sample->block.data[n], sample->block.data[n+1]);
+ isl_seq_combine(dir->block.data,
+ bset1->ctx->one, dir->block.data,
+ sample->block.data[n], bset1->eq[i], 1 + d);
+
+ n += 2;
+ }
+ for (i = 0; i < bset1->n_ineq; ++i)
+ isl_seq_combine(dir->block.data,
+ bset1->ctx->one, dir->block.data,
+ sample->block.data[n++], bset1->ineq[i], 1 + d);
+ isl_vec_free(sample);
+ isl_seq_normalize(bset1->ctx, dir->el, dir->size);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return dir;
+error:
+ isl_vec_free(sample);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+/* Given a polyhedron b_i + A_i x >= 0 and a map T = S^{-1},
+ * compute b_i' + A_i' x' >= 0, with
+ *
+ * [ b_i A_i ] [ y' ] [ y' ]
+ * [ 1 0 ] S^{-1} [ x' ] >= 0 or [ b_i' A_i' ] [ x' ] >= 0
+ *
+ * In particular, add the "positivity constraint" and then perform
+ * the mapping.
+ */
+static struct isl_basic_set *homogeneous_map(struct isl_basic_set *bset,
+ struct isl_mat *T)
+{
+ int k;
+
+ if (!bset)
+ goto error;
+ bset = isl_basic_set_extend_constraints(bset, 0, 1);
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[k] + 1, isl_basic_set_total_dim(bset));
+ isl_int_set_si(bset->ineq[k][0], 1);
+ bset = isl_basic_set_preimage(bset, T);
+ return bset;
+error:
+ isl_mat_free(T);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Compute the convex hull of a pair of basic sets without any parameters or
+ * integer divisions, where the convex hull is known to be pointed,
+ * but the basic sets may be unbounded.
+ *
+ * We turn this problem into the computation of a convex hull of a pair
+ * _bounded_ polyhedra by "changing the direction of the homogeneous
+ * dimension". This idea is due to Matthias Koeppe.
+ *
+ * Consider the cones in homogeneous space that correspond to the
+ * input polyhedra. The rays of these cones are also rays of the
+ * polyhedra if the coordinate that corresponds to the homogeneous
+ * dimension is zero. That is, if the inner product of the rays
+ * with the homogeneous direction is zero.
+ * The cones in the homogeneous space can also be considered to
+ * correspond to other pairs of polyhedra by chosing a different
+ * homogeneous direction. To ensure that both of these polyhedra
+ * are bounded, we need to make sure that all rays of the cones
+ * correspond to vertices and not to rays.
+ * Let s be a direction such that <s, r> > 0 for all rays r of both cones.
+ * Then using s as a homogeneous direction, we obtain a pair of polytopes.
+ * The vector s is computed in valid_direction.
+ *
+ * Note that we need to consider _all_ rays of the cones and not just
+ * the rays that correspond to rays in the polyhedra. If we were to
+ * only consider those rays and turn them into vertices, then we
+ * may inadvertently turn some vertices into rays.
+ *
+ * The standard homogeneous direction is the unit vector in the 0th coordinate.
+ * We therefore transform the two polyhedra such that the selected
+ * direction is mapped onto this standard direction and then proceed
+ * with the normal computation.
+ * Let S be a non-singular square matrix with s as its first row,
+ * then we want to map the polyhedra to the space
+ *
+ * [ y' ] [ y ] [ y ] [ y' ]
+ * [ x' ] = S [ x ] i.e., [ x ] = S^{-1} [ x' ]
+ *
+ * We take S to be the unimodular completion of s to limit the growth
+ * of the coefficients in the following computations.
+ *
+ * Let b_i + A_i x >= 0 be the constraints of polyhedron i.
+ * We first move to the homogeneous dimension
+ *
+ * b_i y + A_i x >= 0 [ b_i A_i ] [ y ] [ 0 ]
+ * y >= 0 or [ 1 0 ] [ x ] >= [ 0 ]
+ *
+ * Then we change directoin
+ *
+ * [ b_i A_i ] [ y' ] [ y' ]
+ * [ 1 0 ] S^{-1} [ x' ] >= 0 or [ b_i' A_i' ] [ x' ] >= 0
+ *
+ * Then we compute the convex hull of the polytopes b_i' + A_i' x' >= 0
+ * resulting in b' + A' x' >= 0, which we then convert back
+ *
+ * [ y ] [ y ]
+ * [ b' A' ] S [ x ] >= 0 or [ b A ] [ x ] >= 0
+ *
+ * The polyhedron b + A x >= 0 is then the convex hull of the input polyhedra.
+ */
+static struct isl_basic_set *convex_hull_pair_pointed(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ struct isl_ctx *ctx = NULL;
+ struct isl_vec *dir = NULL;
+ struct isl_mat *T = NULL;
+ struct isl_mat *T2 = NULL;
+ struct isl_basic_set *hull;
+ struct isl_set *set;
+
+ if (!bset1 || !bset2)
+ goto error;
+ ctx = bset1->ctx;
+ dir = valid_direction(isl_basic_set_copy(bset1),
+ isl_basic_set_copy(bset2));
+ if (!dir)
+ goto error;
+ T = isl_mat_alloc(bset1->ctx, dir->size, dir->size);
+ if (!T)
+ goto error;
+ isl_seq_cpy(T->row[0], dir->block.data, dir->size);
+ T = isl_mat_unimodular_complete(T, 1);
+ T2 = isl_mat_right_inverse(isl_mat_copy(T));
+
+ bset1 = homogeneous_map(bset1, isl_mat_copy(T2));
+ bset2 = homogeneous_map(bset2, T2);
+ set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
+ set = isl_set_add_basic_set(set, bset1);
+ set = isl_set_add_basic_set(set, bset2);
+ hull = uset_convex_hull(set);
+ hull = isl_basic_set_preimage(hull, T);
+
+ isl_vec_free(dir);
+
+ return hull;
+error:
+ isl_vec_free(dir);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+static struct isl_basic_set *uset_convex_hull_wrap(struct isl_set *set);
+static struct isl_basic_set *modulo_affine_hull(
+ struct isl_set *set, struct isl_basic_set *affine_hull);
+
+/* Compute the convex hull of a pair of basic sets without any parameters or
+ * integer divisions.
+ *
+ * This function is called from uset_convex_hull_unbounded, which
+ * means that the complete convex hull is unbounded. Some pairs
+ * of basic sets may still be bounded, though.
+ * They may even lie inside a lower dimensional space, in which
+ * case they need to be handled inside their affine hull since
+ * the main algorithm assumes that the result is full-dimensional.
+ *
+ * If the convex hull of the two basic sets would have a non-trivial
+ * lineality space, we first project out this lineality space.
+ */
+static struct isl_basic_set *convex_hull_pair(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2)
+{
+ isl_basic_set *lin, *aff;
+ int bounded1, bounded2;
+
+ if (bset1->ctx->opt->convex == ISL_CONVEX_HULL_FM)
+ return convex_hull_pair_elim(bset1, bset2);
+
+ aff = isl_set_affine_hull(isl_basic_set_union(isl_basic_set_copy(bset1),
+ isl_basic_set_copy(bset2)));
+ if (!aff)
+ goto error;
+ if (aff->n_eq != 0)
+ return modulo_affine_hull(isl_basic_set_union(bset1, bset2), aff);
+ isl_basic_set_free(aff);
+
+ bounded1 = isl_basic_set_is_bounded(bset1);
+ bounded2 = isl_basic_set_is_bounded(bset2);
+
+ if (bounded1 < 0 || bounded2 < 0)
+ goto error;
+
+ if (bounded1 && bounded2)
+ return uset_convex_hull_wrap(isl_basic_set_union(bset1, bset2));
+
+ if (bounded1 || bounded2)
+ return convex_hull_pair_pointed(bset1, bset2);
+
+ lin = induced_lineality_space(isl_basic_set_copy(bset1),
+ isl_basic_set_copy(bset2));
+ if (!lin)
+ goto error;
+ if (isl_basic_set_is_universe(lin)) {
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return lin;
+ }
+ if (lin->n_eq < isl_basic_set_total_dim(lin)) {
+ struct isl_set *set;
+ set = isl_set_alloc_space(isl_basic_set_get_space(bset1), 2, 0);
+ set = isl_set_add_basic_set(set, bset1);
+ set = isl_set_add_basic_set(set, bset2);
+ return modulo_lineality(set, lin);
+ }
+ isl_basic_set_free(lin);
+
+ return convex_hull_pair_pointed(bset1, bset2);
+error:
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ return NULL;
+}
+
+/* Compute the lineality space of a basic set.
+ * We currently do not allow the basic set to have any divs.
+ * We basically just drop the constants and turn every inequality
+ * into an equality.
+ */
+struct isl_basic_set *isl_basic_set_lineality_space(struct isl_basic_set *bset)
+{
+ int i, k;
+ struct isl_basic_set *lin = NULL;
+ unsigned dim;
+
+ if (!bset)
+ goto error;
+ isl_assert(bset->ctx, bset->n_div == 0, goto error);
+ dim = isl_basic_set_total_dim(bset);
+
+ lin = isl_basic_set_alloc_space(isl_basic_set_get_space(bset), 0, dim, 0);
+ if (!lin)
+ goto error;
+ for (i = 0; i < bset->n_eq; ++i) {
+ k = isl_basic_set_alloc_equality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->eq[k][0], 0);
+ isl_seq_cpy(lin->eq[k] + 1, bset->eq[i] + 1, dim);
+ }
+ lin = isl_basic_set_gauss(lin, NULL);
+ if (!lin)
+ goto error;
+ for (i = 0; i < bset->n_ineq && lin->n_eq < dim; ++i) {
+ k = isl_basic_set_alloc_equality(lin);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(lin->eq[k][0], 0);
+ isl_seq_cpy(lin->eq[k] + 1, bset->ineq[i] + 1, dim);
+ lin = isl_basic_set_gauss(lin, NULL);
+ if (!lin)
+ goto error;
+ }
+ isl_basic_set_free(bset);
+ return lin;
+error:
+ isl_basic_set_free(lin);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Compute the (linear) hull of the lineality spaces of the basic sets in the
+ * "underlying" set "set".
+ */
+static struct isl_basic_set *uset_combined_lineality_space(struct isl_set *set)
+{
+ int i;
+ struct isl_set *lin = NULL;
+
+ if (!set)
+ return NULL;
+ if (set->n == 0) {
+ isl_space *dim = isl_set_get_space(set);
+ isl_set_free(set);
+ return isl_basic_set_empty(dim);
+ }
+
+ lin = isl_set_alloc_space(isl_set_get_space(set), set->n, 0);
+ for (i = 0; i < set->n; ++i)
+ lin = isl_set_add_basic_set(lin,
+ isl_basic_set_lineality_space(isl_basic_set_copy(set->p[i])));
+ isl_set_free(set);
+ return isl_set_affine_hull(lin);
+}
+
+/* Compute the convex hull of a set without any parameters or
+ * integer divisions.
+ * In each step, we combined two basic sets until only one
+ * basic set is left.
+ * The input basic sets are assumed not to have a non-trivial
+ * lineality space. If any of the intermediate results has
+ * a non-trivial lineality space, it is projected out.
+ */
+static struct isl_basic_set *uset_convex_hull_unbounded(struct isl_set *set)
+{
+ struct isl_basic_set *convex_hull = NULL;
+
+ convex_hull = isl_set_copy_basic_set(set);
+ set = isl_set_drop_basic_set(set, convex_hull);
+ if (!set)
+ goto error;
+ while (set->n > 0) {
+ struct isl_basic_set *t;
+ t = isl_set_copy_basic_set(set);
+ if (!t)
+ goto error;
+ set = isl_set_drop_basic_set(set, t);
+ if (!set)
+ goto error;
+ convex_hull = convex_hull_pair(convex_hull, t);
+ if (set->n == 0)
+ break;
+ t = isl_basic_set_lineality_space(isl_basic_set_copy(convex_hull));
+ if (!t)
+ goto error;
+ if (isl_basic_set_is_universe(t)) {
+ isl_basic_set_free(convex_hull);
+ convex_hull = t;
+ break;
+ }
+ if (t->n_eq < isl_basic_set_total_dim(t)) {
+ set = isl_set_add_basic_set(set, convex_hull);
+ return modulo_lineality(set, t);
+ }
+ isl_basic_set_free(t);
+ }
+ isl_set_free(set);
+ return convex_hull;
+error:
+ isl_set_free(set);
+ isl_basic_set_free(convex_hull);
+ return NULL;
+}
+
+/* Compute an initial hull for wrapping containing a single initial
+ * facet.
+ * This function assumes that the given set is bounded.
+ */
+static struct isl_basic_set *initial_hull(struct isl_basic_set *hull,
+ struct isl_set *set)
+{
+ struct isl_mat *bounds = NULL;
+ unsigned dim;
+ int k;
+
+ if (!hull)
+ goto error;
+ bounds = initial_facet_constraint(set);
+ if (!bounds)
+ goto error;
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ goto error;
+ dim = isl_set_n_dim(set);
+ isl_assert(set->ctx, 1 + dim == bounds->n_col, goto error);
+ isl_seq_cpy(hull->ineq[k], bounds->row[0], bounds->n_col);
+ isl_mat_free(bounds);
+
+ return hull;
+error:
+ isl_basic_set_free(hull);
+ isl_mat_free(bounds);
+ return NULL;
+}
+
+struct max_constraint {
+ struct isl_mat *c;
+ int count;
+ int ineq;
+};
+
+static int max_constraint_equal(const void *entry, const void *val)
+{
+ struct max_constraint *a = (struct max_constraint *)entry;
+ isl_int *b = (isl_int *)val;
+
+ return isl_seq_eq(a->c->row[0] + 1, b, a->c->n_col - 1);
+}
+
+static void update_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
+ isl_int *con, unsigned len, int n, int ineq)
+{
+ struct isl_hash_table_entry *entry;
+ struct max_constraint *c;
+ uint32_t c_hash;
+
+ c_hash = isl_seq_get_hash(con + 1, len);
+ entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
+ con + 1, 0);
+ if (!entry)
+ return;
+ c = entry->data;
+ if (c->count < n) {
+ isl_hash_table_remove(ctx, table, entry);
+ return;
+ }
+ c->count++;
+ if (isl_int_gt(c->c->row[0][0], con[0]))
+ return;
+ if (isl_int_eq(c->c->row[0][0], con[0])) {
+ if (ineq)
+ c->ineq = ineq;
+ return;
+ }
+ c->c = isl_mat_cow(c->c);
+ isl_int_set(c->c->row[0][0], con[0]);
+ c->ineq = ineq;
+}
+
+/* Check whether the constraint hash table "table" constains the constraint
+ * "con".
+ */
+static int has_constraint(struct isl_ctx *ctx, struct isl_hash_table *table,
+ isl_int *con, unsigned len, int n)
+{
+ struct isl_hash_table_entry *entry;
+ struct max_constraint *c;
+ uint32_t c_hash;
+
+ c_hash = isl_seq_get_hash(con + 1, len);
+ entry = isl_hash_table_find(ctx, table, c_hash, max_constraint_equal,
+ con + 1, 0);
+ if (!entry)
+ return 0;
+ c = entry->data;
+ if (c->count < n)
+ return 0;
+ return isl_int_eq(c->c->row[0][0], con[0]);
+}
+
+/* Check for inequality constraints of a basic set without equalities
+ * such that the same or more stringent copies of the constraint appear
+ * in all of the basic sets. Such constraints are necessarily facet
+ * constraints of the convex hull.
+ *
+ * If the resulting basic set is by chance identical to one of
+ * the basic sets in "set", then we know that this basic set contains
+ * all other basic sets and is therefore the convex hull of set.
+ * In this case we set *is_hull to 1.
+ */
+static struct isl_basic_set *common_constraints(struct isl_basic_set *hull,
+ struct isl_set *set, int *is_hull)
+{
+ int i, j, s, n;
+ int min_constraints;
+ int best;
+ struct max_constraint *constraints = NULL;
+ struct isl_hash_table *table = NULL;
+ unsigned total;
+
+ *is_hull = 0;
+
+ for (i = 0; i < set->n; ++i)
+ if (set->p[i]->n_eq == 0)
+ break;
+ if (i >= set->n)
+ return hull;
+ min_constraints = set->p[i]->n_ineq;
+ best = i;
+ for (i = best + 1; i < set->n; ++i) {
+ if (set->p[i]->n_eq != 0)
+ continue;
+ if (set->p[i]->n_ineq >= min_constraints)
+ continue;
+ min_constraints = set->p[i]->n_ineq;
+ best = i;
+ }
+ constraints = isl_calloc_array(hull->ctx, struct max_constraint,
+ min_constraints);
+ if (!constraints)
+ return hull;
+ table = isl_alloc_type(hull->ctx, struct isl_hash_table);
+ if (isl_hash_table_init(hull->ctx, table, min_constraints))
+ goto error;
+
+ total = isl_space_dim(set->dim, isl_dim_all);
+ for (i = 0; i < set->p[best]->n_ineq; ++i) {
+ constraints[i].c = isl_mat_sub_alloc6(hull->ctx,
+ set->p[best]->ineq + i, 0, 1, 0, 1 + total);
+ if (!constraints[i].c)
+ goto error;
+ constraints[i].ineq = 1;
+ }
+ for (i = 0; i < min_constraints; ++i) {
+ struct isl_hash_table_entry *entry;
+ uint32_t c_hash;
+ c_hash = isl_seq_get_hash(constraints[i].c->row[0] + 1, total);
+ entry = isl_hash_table_find(hull->ctx, table, c_hash,
+ max_constraint_equal, constraints[i].c->row[0] + 1, 1);
+ if (!entry)
+ goto error;
+ isl_assert(hull->ctx, !entry->data, goto error);
+ entry->data = &constraints[i];
+ }
+
+ n = 0;
+ for (s = 0; s < set->n; ++s) {
+ if (s == best)
+ continue;
+
+ for (i = 0; i < set->p[s]->n_eq; ++i) {
+ isl_int *eq = set->p[s]->eq[i];
+ for (j = 0; j < 2; ++j) {
+ isl_seq_neg(eq, eq, 1 + total);
+ update_constraint(hull->ctx, table,
+ eq, total, n, 0);
+ }
+ }
+ for (i = 0; i < set->p[s]->n_ineq; ++i) {
+ isl_int *ineq = set->p[s]->ineq[i];
+ update_constraint(hull->ctx, table, ineq, total, n,
+ set->p[s]->n_eq == 0);
+ }
+ ++n;
+ }
+
+ for (i = 0; i < min_constraints; ++i) {
+ if (constraints[i].count < n)
+ continue;
+ if (!constraints[i].ineq)
+ continue;
+ j = isl_basic_set_alloc_inequality(hull);
+ if (j < 0)
+ goto error;
+ isl_seq_cpy(hull->ineq[j], constraints[i].c->row[0], 1 + total);
+ }
+
+ for (s = 0; s < set->n; ++s) {
+ if (set->p[s]->n_eq)
+ continue;
+ if (set->p[s]->n_ineq != hull->n_ineq)
+ continue;
+ for (i = 0; i < set->p[s]->n_ineq; ++i) {
+ isl_int *ineq = set->p[s]->ineq[i];
+ if (!has_constraint(hull->ctx, table, ineq, total, n))
+ break;
+ }
+ if (i == set->p[s]->n_ineq)
+ *is_hull = 1;
+ }
+
+ isl_hash_table_clear(table);
+ for (i = 0; i < min_constraints; ++i)
+ isl_mat_free(constraints[i].c);
+ free(constraints);
+ free(table);
+ return hull;
+error:
+ isl_hash_table_clear(table);
+ free(table);
+ if (constraints)
+ for (i = 0; i < min_constraints; ++i)
+ isl_mat_free(constraints[i].c);
+ free(constraints);
+ return hull;
+}
+
+/* Create a template for the convex hull of "set" and fill it up
+ * obvious facet constraints, if any. If the result happens to
+ * be the convex hull of "set" then *is_hull is set to 1.
+ */
+static struct isl_basic_set *proto_hull(struct isl_set *set, int *is_hull)
+{
+ struct isl_basic_set *hull;
+ unsigned n_ineq;
+ int i;
+
+ n_ineq = 1;
+ for (i = 0; i < set->n; ++i) {
+ n_ineq += set->p[i]->n_eq;
+ n_ineq += set->p[i]->n_ineq;
+ }
+ hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
+ hull = isl_basic_set_set_rational(hull);
+ if (!hull)
+ return NULL;
+ return common_constraints(hull, set, is_hull);
+}
+
+static struct isl_basic_set *uset_convex_hull_wrap(struct isl_set *set)
+{
+ struct isl_basic_set *hull;
+ int is_hull;
+
+ hull = proto_hull(set, &is_hull);
+ if (hull && !is_hull) {
+ if (hull->n_ineq == 0)
+ hull = initial_hull(hull, set);
+ hull = extend(hull, set);
+ }
+ isl_set_free(set);
+
+ return hull;
+}
+
+/* Compute the convex hull of a set without any parameters or
+ * integer divisions. Depending on whether the set is bounded,
+ * we pass control to the wrapping based convex hull or
+ * the Fourier-Motzkin elimination based convex hull.
+ * We also handle a few special cases before checking the boundedness.
+ */
+static struct isl_basic_set *uset_convex_hull(struct isl_set *set)
+{
+ struct isl_basic_set *convex_hull = NULL;
+ struct isl_basic_set *lin;
+
+ if (isl_set_n_dim(set) == 0)
+ return convex_hull_0d(set);
+
+ set = isl_set_coalesce(set);
+ set = isl_set_set_rational(set);
+
+ if (!set)
+ goto error;
+ if (!set)
+ return NULL;
+ if (set->n == 1) {
+ convex_hull = isl_basic_set_copy(set->p[0]);
+ isl_set_free(set);
+ return convex_hull;
+ }
+ if (isl_set_n_dim(set) == 1)
+ return convex_hull_1d(set);
+
+ if (isl_set_is_bounded(set) &&
+ set->ctx->opt->convex == ISL_CONVEX_HULL_WRAP)
+ return uset_convex_hull_wrap(set);
+
+ lin = uset_combined_lineality_space(isl_set_copy(set));
+ if (!lin)
+ goto error;
+ if (isl_basic_set_is_universe(lin)) {
+ isl_set_free(set);
+ return lin;
+ }
+ if (lin->n_eq < isl_basic_set_total_dim(lin))
+ return modulo_lineality(set, lin);
+ isl_basic_set_free(lin);
+
+ return uset_convex_hull_unbounded(set);
+error:
+ isl_set_free(set);
+ isl_basic_set_free(convex_hull);
+ return NULL;
+}
+
+/* This is the core procedure, where "set" is a "pure" set, i.e.,
+ * without parameters or divs and where the convex hull of set is
+ * known to be full-dimensional.
+ */
+static struct isl_basic_set *uset_convex_hull_wrap_bounded(struct isl_set *set)
+{
+ struct isl_basic_set *convex_hull = NULL;
+
+ if (!set)
+ goto error;
+
+ if (isl_set_n_dim(set) == 0) {
+ convex_hull = isl_basic_set_universe(isl_space_copy(set->dim));
+ isl_set_free(set);
+ convex_hull = isl_basic_set_set_rational(convex_hull);
+ return convex_hull;
+ }
+
+ set = isl_set_set_rational(set);
+ set = isl_set_coalesce(set);
+ if (!set)
+ goto error;
+ if (set->n == 1) {
+ convex_hull = isl_basic_set_copy(set->p[0]);
+ isl_set_free(set);
+ convex_hull = isl_basic_map_remove_redundancies(convex_hull);
+ return convex_hull;
+ }
+ if (isl_set_n_dim(set) == 1)
+ return convex_hull_1d(set);
+
+ return uset_convex_hull_wrap(set);
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Compute the convex hull of set "set" with affine hull "affine_hull",
+ * We first remove the equalities (transforming the set), compute the
+ * convex hull of the transformed set and then add the equalities back
+ * (after performing the inverse transformation.
+ */
+static struct isl_basic_set *modulo_affine_hull(
+ struct isl_set *set, struct isl_basic_set *affine_hull)
+{
+ struct isl_mat *T;
+ struct isl_mat *T2;
+ struct isl_basic_set *dummy;
+ struct isl_basic_set *convex_hull;
+
+ dummy = isl_basic_set_remove_equalities(
+ isl_basic_set_copy(affine_hull), &T, &T2);
+ if (!dummy)
+ goto error;
+ isl_basic_set_free(dummy);
+ set = isl_set_preimage(set, T);
+ convex_hull = uset_convex_hull(set);
+ convex_hull = isl_basic_set_preimage(convex_hull, T2);
+ convex_hull = isl_basic_set_intersect(convex_hull, affine_hull);
+ return convex_hull;
+error:
+ isl_basic_set_free(affine_hull);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Compute the convex hull of a map.
+ *
+ * The implementation was inspired by "Extended Convex Hull" by Fukuda et al.,
+ * specifically, the wrapping of facets to obtain new facets.
+ */
+struct isl_basic_map *isl_map_convex_hull(struct isl_map *map)
+{
+ struct isl_basic_set *bset;
+ struct isl_basic_map *model = NULL;
+ struct isl_basic_set *affine_hull = NULL;
+ struct isl_basic_map *convex_hull = NULL;
+ struct isl_set *set = NULL;
+ struct isl_ctx *ctx;
+
+ map = isl_map_detect_equalities(map);
+ map = isl_map_align_divs(map);
+ if (!map)
+ goto error;
+
+ ctx = map->ctx;
+ if (map->n == 0) {
+ convex_hull = isl_basic_map_empty_like_map(map);
+ isl_map_free(map);
+ return convex_hull;
+ }
+
+ model = isl_basic_map_copy(map->p[0]);
+ set = isl_map_underlying_set(map);
+ if (!set)
+ goto error;
+
+ affine_hull = isl_set_affine_hull(isl_set_copy(set));
+ if (!affine_hull)
+ goto error;
+ if (affine_hull->n_eq != 0)
+ bset = modulo_affine_hull(set, affine_hull);
+ else {
+ isl_basic_set_free(affine_hull);
+ bset = uset_convex_hull(set);
+ }
+
+ convex_hull = isl_basic_map_overlying_set(bset, model);
+ if (!convex_hull)
+ return NULL;
+
+ ISL_F_SET(convex_hull, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_SET(convex_hull, ISL_BASIC_MAP_ALL_EQUALITIES);
+ ISL_F_CLR(convex_hull, ISL_BASIC_MAP_RATIONAL);
+ return convex_hull;
+error:
+ isl_set_free(set);
+ isl_basic_map_free(model);
+ return NULL;
+}
+
+struct isl_basic_set *isl_set_convex_hull(struct isl_set *set)
+{
+ return (struct isl_basic_set *)
+ isl_map_convex_hull((struct isl_map *)set);
+}
+
+__isl_give isl_basic_map *isl_map_polyhedral_hull(__isl_take isl_map *map)
+{
+ isl_basic_map *hull;
+
+ hull = isl_map_convex_hull(map);
+ return isl_basic_map_remove_divs(hull);
+}
+
+__isl_give isl_basic_set *isl_set_polyhedral_hull(__isl_take isl_set *set)
+{
+ return (isl_basic_set *)isl_map_polyhedral_hull((isl_map *)set);
+}
+
+struct sh_data_entry {
+ struct isl_hash_table *table;
+ struct isl_tab *tab;
+};
+
+/* Holds the data needed during the simple hull computation.
+ * In particular,
+ * n the number of basic sets in the original set
+ * hull_table a hash table of already computed constraints
+ * in the simple hull
+ * p for each basic set,
+ * table a hash table of the constraints
+ * tab the tableau corresponding to the basic set
+ */
+struct sh_data {
+ struct isl_ctx *ctx;
+ unsigned n;
+ struct isl_hash_table *hull_table;
+ struct sh_data_entry p[1];
+};
+
+static void sh_data_free(struct sh_data *data)
+{
+ int i;
+
+ if (!data)
+ return;
+ isl_hash_table_free(data->ctx, data->hull_table);
+ for (i = 0; i < data->n; ++i) {
+ isl_hash_table_free(data->ctx, data->p[i].table);
+ isl_tab_free(data->p[i].tab);
+ }
+ free(data);
+}
+
+struct ineq_cmp_data {
+ unsigned len;
+ isl_int *p;
+};
+
+static int has_ineq(const void *entry, const void *val)
+{
+ isl_int *row = (isl_int *)entry;
+ struct ineq_cmp_data *v = (struct ineq_cmp_data *)val;
+
+ return isl_seq_eq(row + 1, v->p + 1, v->len) ||
+ isl_seq_is_neg(row + 1, v->p + 1, v->len);
+}
+
+static int hash_ineq(struct isl_ctx *ctx, struct isl_hash_table *table,
+ isl_int *ineq, unsigned len)
+{
+ uint32_t c_hash;
+ struct ineq_cmp_data v;
+ struct isl_hash_table_entry *entry;
+
+ v.len = len;
+ v.p = ineq;
+ c_hash = isl_seq_get_hash(ineq + 1, len);
+ entry = isl_hash_table_find(ctx, table, c_hash, has_ineq, &v, 1);
+ if (!entry)
+ return - 1;
+ entry->data = ineq;
+ return 0;
+}
+
+/* Fill hash table "table" with the constraints of "bset".
+ * Equalities are added as two inequalities.
+ * The value in the hash table is a pointer to the (in)equality of "bset".
+ */
+static int hash_basic_set(struct isl_hash_table *table,
+ struct isl_basic_set *bset)
+{
+ int i, j;
+ unsigned dim = isl_basic_set_total_dim(bset);
+
+ for (i = 0; i < bset->n_eq; ++i) {
+ for (j = 0; j < 2; ++j) {
+ isl_seq_neg(bset->eq[i], bset->eq[i], 1 + dim);
+ if (hash_ineq(bset->ctx, table, bset->eq[i], dim) < 0)
+ return -1;
+ }
+ }
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (hash_ineq(bset->ctx, table, bset->ineq[i], dim) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static struct sh_data *sh_data_alloc(struct isl_set *set, unsigned n_ineq)
+{
+ struct sh_data *data;
+ int i;
+
+ data = isl_calloc(set->ctx, struct sh_data,
+ sizeof(struct sh_data) +
+ (set->n - 1) * sizeof(struct sh_data_entry));
+ if (!data)
+ return NULL;
+ data->ctx = set->ctx;
+ data->n = set->n;
+ data->hull_table = isl_hash_table_alloc(set->ctx, n_ineq);
+ if (!data->hull_table)
+ goto error;
+ for (i = 0; i < set->n; ++i) {
+ data->p[i].table = isl_hash_table_alloc(set->ctx,
+ 2 * set->p[i]->n_eq + set->p[i]->n_ineq);
+ if (!data->p[i].table)
+ goto error;
+ if (hash_basic_set(data->p[i].table, set->p[i]) < 0)
+ goto error;
+ }
+ return data;
+error:
+ sh_data_free(data);
+ return NULL;
+}
+
+/* Check if inequality "ineq" is a bound for basic set "j" or if
+ * it can be relaxed (by increasing the constant term) to become
+ * a bound for that basic set. In the latter case, the constant
+ * term is updated.
+ * Relaxation of the constant term is only allowed if "shift" is set.
+ *
+ * Return 1 if "ineq" is a bound
+ * 0 if "ineq" may attain arbitrarily small values on basic set "j"
+ * -1 if some error occurred
+ */
+static int is_bound(struct sh_data *data, struct isl_set *set, int j,
+ isl_int *ineq, int shift)
+{
+ enum isl_lp_result res;
+ isl_int opt;
+
+ if (!data->p[j].tab) {
+ data->p[j].tab = isl_tab_from_basic_set(set->p[j], 0);
+ if (!data->p[j].tab)
+ return -1;
+ }
+
+ isl_int_init(opt);
+
+ res = isl_tab_min(data->p[j].tab, ineq, data->ctx->one,
+ &opt, NULL, 0);
+ if (res == isl_lp_ok && isl_int_is_neg(opt)) {
+ if (shift)
+ isl_int_sub(ineq[0], ineq[0], opt);
+ else
+ res = isl_lp_unbounded;
+ }
+
+ isl_int_clear(opt);
+
+ return (res == isl_lp_ok || res == isl_lp_empty) ? 1 :
+ res == isl_lp_unbounded ? 0 : -1;
+}
+
+/* Check if inequality "ineq" from basic set "i" is or can be relaxed to
+ * become a bound on the whole set. If so, add the (relaxed) inequality
+ * to "hull". Relaxation is only allowed if "shift" is set.
+ *
+ * We first check if "hull" already contains a translate of the inequality.
+ * If so, we are done.
+ * Then, we check if any of the previous basic sets contains a translate
+ * of the inequality. If so, then we have already considered this
+ * inequality and we are done.
+ * Otherwise, for each basic set other than "i", we check if the inequality
+ * is a bound on the basic set.
+ * For previous basic sets, we know that they do not contain a translate
+ * of the inequality, so we directly call is_bound.
+ * For following basic sets, we first check if a translate of the
+ * inequality appears in its description and if so directly update
+ * the inequality accordingly.
+ */
+static struct isl_basic_set *add_bound(struct isl_basic_set *hull,
+ struct sh_data *data, struct isl_set *set, int i, isl_int *ineq,
+ int shift)
+{
+ uint32_t c_hash;
+ struct ineq_cmp_data v;
+ struct isl_hash_table_entry *entry;
+ int j, k;
+
+ if (!hull)
+ return NULL;
+
+ v.len = isl_basic_set_total_dim(hull);
+ v.p = ineq;
+ c_hash = isl_seq_get_hash(ineq + 1, v.len);
+
+ entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
+ has_ineq, &v, 0);
+ if (entry)
+ return hull;
+
+ for (j = 0; j < i; ++j) {
+ entry = isl_hash_table_find(hull->ctx, data->p[j].table,
+ c_hash, has_ineq, &v, 0);
+ if (entry)
+ break;
+ }
+ if (j < i)
+ return hull;
+
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
+
+ for (j = 0; j < i; ++j) {
+ int bound;
+ bound = is_bound(data, set, j, hull->ineq[k], shift);
+ if (bound < 0)
+ goto error;
+ if (!bound)
+ break;
+ }
+ if (j < i) {
+ isl_basic_set_free_inequality(hull, 1);
+ return hull;
+ }
+
+ for (j = i + 1; j < set->n; ++j) {
+ int bound, neg;
+ isl_int *ineq_j;
+ entry = isl_hash_table_find(hull->ctx, data->p[j].table,
+ c_hash, has_ineq, &v, 0);
+ if (entry) {
+ ineq_j = entry->data;
+ neg = isl_seq_is_neg(ineq_j + 1,
+ hull->ineq[k] + 1, v.len);
+ if (neg)
+ isl_int_neg(ineq_j[0], ineq_j[0]);
+ if (isl_int_gt(ineq_j[0], hull->ineq[k][0]))
+ isl_int_set(hull->ineq[k][0], ineq_j[0]);
+ if (neg)
+ isl_int_neg(ineq_j[0], ineq_j[0]);
+ continue;
+ }
+ bound = is_bound(data, set, j, hull->ineq[k], shift);
+ if (bound < 0)
+ goto error;
+ if (!bound)
+ break;
+ }
+ if (j < set->n) {
+ isl_basic_set_free_inequality(hull, 1);
+ return hull;
+ }
+
+ entry = isl_hash_table_find(hull->ctx, data->hull_table, c_hash,
+ has_ineq, &v, 1);
+ if (!entry)
+ goto error;
+ entry->data = hull->ineq[k];
+
+ return hull;
+error:
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Check if any inequality from basic set "i" is or can be relaxed to
+ * become a bound on the whole set. If so, add the (relaxed) inequality
+ * to "hull". Relaxation is only allowed if "shift" is set.
+ */
+static struct isl_basic_set *add_bounds(struct isl_basic_set *bset,
+ struct sh_data *data, struct isl_set *set, int i, int shift)
+{
+ int j, k;
+ unsigned dim = isl_basic_set_total_dim(bset);
+
+ for (j = 0; j < set->p[i]->n_eq; ++j) {
+ for (k = 0; k < 2; ++k) {
+ isl_seq_neg(set->p[i]->eq[j], set->p[i]->eq[j], 1+dim);
+ bset = add_bound(bset, data, set, i, set->p[i]->eq[j],
+ shift);
+ }
+ }
+ for (j = 0; j < set->p[i]->n_ineq; ++j)
+ bset = add_bound(bset, data, set, i, set->p[i]->ineq[j], shift);
+ return bset;
+}
+
+/* Compute a superset of the convex hull of set that is described
+ * by only (translates of) the constraints in the constituents of set.
+ * Translation is only allowed if "shift" is set.
+ */
+static __isl_give isl_basic_set *uset_simple_hull(__isl_take isl_set *set,
+ int shift)
+{
+ struct sh_data *data = NULL;
+ struct isl_basic_set *hull = NULL;
+ unsigned n_ineq;
+ int i;
+
+ if (!set)
+ return NULL;
+
+ n_ineq = 0;
+ for (i = 0; i < set->n; ++i) {
+ if (!set->p[i])
+ goto error;
+ n_ineq += 2 * set->p[i]->n_eq + set->p[i]->n_ineq;
+ }
+
+ hull = isl_basic_set_alloc_space(isl_space_copy(set->dim), 0, 0, n_ineq);
+ if (!hull)
+ goto error;
+
+ data = sh_data_alloc(set, n_ineq);
+ if (!data)
+ goto error;
+
+ for (i = 0; i < set->n; ++i)
+ hull = add_bounds(hull, data, set, i, shift);
+
+ sh_data_free(data);
+ isl_set_free(set);
+
+ return hull;
+error:
+ sh_data_free(data);
+ isl_basic_set_free(hull);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* 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,
+ int shift)
+{
+ struct isl_set *set = NULL;
+ struct isl_basic_map *model = NULL;
+ struct isl_basic_map *hull;
+ struct isl_basic_map *affine_hull;
+ struct isl_basic_set *bset = NULL;
+
+ if (!map)
+ return NULL;
+ if (map->n == 0) {
+ hull = isl_basic_map_empty_like_map(map);
+ isl_map_free(map);
+ return hull;
+ }
+ if (map->n == 1) {
+ hull = isl_basic_map_copy(map->p[0]);
+ isl_map_free(map);
+ return hull;
+ }
+
+ map = isl_map_detect_equalities(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;
+
+ set = isl_map_underlying_set(map);
+
+ bset = uset_simple_hull(set, shift);
+
+ hull = isl_basic_map_overlying_set(bset, model);
+
+ hull = isl_basic_map_intersect(hull, affine_hull);
+ hull = isl_basic_map_remove_redundancies(hull);
+
+ if (!hull)
+ return NULL;
+ ISL_F_SET(hull, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_SET(hull, ISL_BASIC_MAP_ALL_EQUALITIES);
+
+ hull = isl_basic_map_finalize(hull);
+
+ 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.
+ */
+__isl_give isl_basic_map *isl_map_simple_hull(__isl_take isl_map *map)
+{
+ return map_simple_hull(map, 1);
+}
+
+struct isl_basic_set *isl_set_simple_hull(struct isl_set *set)
+{
+ return (struct isl_basic_set *)
+ isl_map_simple_hull((struct isl_map *)set);
+}
+
+/* Compute a superset of the convex hull of map that is described
+ * by only the constraints in the constituents of map.
+ */
+__isl_give isl_basic_map *isl_map_unshifted_simple_hull(
+ __isl_take isl_map *map)
+{
+ return map_simple_hull(map, 0);
+}
+
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull(
+ __isl_take isl_set *set)
+{
+ return isl_map_unshifted_simple_hull(set);
+}
+
+/* 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
+ * contains a translate of "ineq". If this translate is more relaxed,
+ * then we assume that "ineq" is not a bound on this basic set.
+ * Otherwise, we know that it is a bound.
+ * If the basic set does not contain a translate of "ineq", then
+ * we call is_bound to perform the test.
+ */
+static __isl_give isl_basic_set *add_bound_from_constraint(
+ __isl_take isl_basic_set *hull, struct sh_data *data,
+ __isl_keep isl_set *set, isl_int *ineq)
+{
+ int i, k;
+ isl_ctx *ctx;
+ uint32_t c_hash;
+ struct ineq_cmp_data v;
+
+ if (!hull || !set)
+ return isl_basic_set_free(hull);
+
+ v.len = isl_basic_set_total_dim(hull);
+ v.p = ineq;
+ c_hash = isl_seq_get_hash(ineq + 1, v.len);
+
+ ctx = isl_basic_set_get_ctx(hull);
+ for (i = 0; i < set->n; ++i) {
+ int bound;
+ struct isl_hash_table_entry *entry;
+
+ entry = isl_hash_table_find(ctx, data->p[i].table,
+ c_hash, &has_ineq, &v, 0);
+ if (entry) {
+ isl_int *ineq_i = entry->data;
+ int neg, more_relaxed;
+
+ neg = isl_seq_is_neg(ineq_i + 1, ineq + 1, v.len);
+ if (neg)
+ isl_int_neg(ineq_i[0], ineq_i[0]);
+ more_relaxed = isl_int_gt(ineq_i[0], ineq[0]);
+ if (neg)
+ isl_int_neg(ineq_i[0], ineq_i[0]);
+ if (more_relaxed)
+ break;
+ else
+ continue;
+ }
+ bound = is_bound(data, set, i, ineq, 0);
+ if (bound < 0)
+ return isl_basic_set_free(hull);
+ if (!bound)
+ break;
+ }
+ if (i < set->n)
+ return hull;
+
+ k = isl_basic_set_alloc_inequality(hull);
+ if (k < 0)
+ return isl_basic_set_free(hull);
+ isl_seq_cpy(hull->ineq[k], ineq, 1 + v.len);
+
+ return hull;
+}
+
+/* Compute a superset of the convex hull of "set" that is described
+ * by only some of the "n_ineq" constraints in the list "ineq", where "set"
+ * has no parameters or integer divisions.
+ *
+ * The inequalities in "ineq" are assumed to have been sorted such
+ * that constraints with the same linear part appear together and
+ * that among constraints with the same linear part, those with
+ * smaller constant term appear first.
+ *
+ * We reuse the same data structure that is used by uset_simple_hull,
+ * but we do not need the hull table since we will not consider the
+ * same constraint more than once. We therefore allocate it with zero size.
+ *
+ * We run through the constraints and try to add them one by one,
+ * skipping identical constraints. If we have added a constraint and
+ * the next constraint is a more relaxed translate, then we skip this
+ * next constraint as well.
+ */
+static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_constraints(
+ __isl_take isl_set *set, int n_ineq, isl_int **ineq)
+{
+ int i;
+ int last_added = 0;
+ struct sh_data *data = NULL;
+ isl_basic_set *hull = NULL;
+ unsigned dim;
+
+ hull = isl_basic_set_alloc_space(isl_set_get_space(set), 0, 0, n_ineq);
+ if (!hull)
+ goto error;
+
+ data = sh_data_alloc(set, 0);
+ if (!data)
+ goto error;
+
+ dim = isl_set_dim(set, isl_dim_set);
+ for (i = 0; i < n_ineq; ++i) {
+ int hull_n_ineq = hull->n_ineq;
+ int parallel;
+
+ parallel = i > 0 && isl_seq_eq(ineq[i - 1] + 1, ineq[i] + 1,
+ dim);
+ if (parallel &&
+ (last_added || isl_int_eq(ineq[i - 1][0], ineq[i][0])))
+ continue;
+ hull = add_bound_from_constraint(hull, data, set, ineq[i]);
+ if (!hull)
+ goto error;
+ last_added = hull->n_ineq > hull_n_ineq;
+ }
+
+ sh_data_free(data);
+ isl_set_free(set);
+ return hull;
+error:
+ sh_data_free(data);
+ isl_set_free(set);
+ isl_basic_set_free(hull);
+ return NULL;
+}
+
+/* Collect pointers to all the inequalities in the elements of "list"
+ * in "ineq". For equalities, store both a pointer to the equality and
+ * a pointer to its opposite, which is first copied to "mat".
+ * "ineq" and "mat" are assumed to have been preallocated to the right size
+ * (the number of inequalities + 2 times the number of equalites and
+ * the number of equalities, respectively).
+ */
+static __isl_give isl_mat *collect_inequalities(__isl_take isl_mat *mat,
+ __isl_keep isl_basic_set_list *list, isl_int **ineq)
+{
+ int i, j, n, n_eq, n_ineq;
+
+ if (!mat)
+ return NULL;
+
+ n_eq = 0;
+ n_ineq = 0;
+ n = isl_basic_set_list_n_basic_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset;
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ if (!bset)
+ return isl_mat_free(mat);
+ for (j = 0; j < bset->n_eq; ++j) {
+ ineq[n_ineq++] = mat->row[n_eq];
+ ineq[n_ineq++] = bset->eq[j];
+ isl_seq_neg(mat->row[n_eq++], bset->eq[j], mat->n_col);
+ }
+ for (j = 0; j < bset->n_ineq; ++j)
+ ineq[n_ineq++] = bset->ineq[j];
+ isl_basic_set_free(bset);
+ }
+
+ return mat;
+}
+
+/* Comparison routine for use as an isl_sort callback.
+ *
+ * Constraints with the same linear part are sorted together and
+ * among constraints with the same linear part, those with smaller
+ * constant term are sorted first.
+ */
+static int cmp_ineq(const void *a, const void *b, void *arg)
+{
+ unsigned dim = *(unsigned *) arg;
+ isl_int * const *ineq1 = a;
+ isl_int * const *ineq2 = b;
+ int cmp;
+
+ cmp = isl_seq_cmp((*ineq1) + 1, (*ineq2) + 1, dim);
+ if (cmp != 0)
+ return cmp;
+ return isl_int_cmp((*ineq1)[0], (*ineq2)[0]);
+}
+
+/* Compute a superset of the convex hull of "set" that is described
+ * by only constraints in the elements of "list", where "set" has
+ * no parameters or integer divisions.
+ *
+ * We collect all the constraints in those elements and then
+ * sort the constraints such that constraints with the same linear part
+ * are sorted together and that those with smaller constant term are
+ * sorted first.
+ */
+static __isl_give isl_basic_set *uset_unshifted_simple_hull_from_basic_set_list(
+ __isl_take isl_set *set, __isl_take isl_basic_set_list *list)
+{
+ int i, n, n_eq, n_ineq;
+ unsigned dim;
+ isl_ctx *ctx;
+ isl_mat *mat = NULL;
+ isl_int **ineq = NULL;
+ isl_basic_set *hull;
+
+ if (!set)
+ goto error;
+ ctx = isl_set_get_ctx(set);
+
+ n_eq = 0;
+ n_ineq = 0;
+ n = isl_basic_set_list_n_basic_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset;
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ if (!bset)
+ goto error;
+ n_eq += bset->n_eq;
+ n_ineq += 2 * bset->n_eq + bset->n_ineq;
+ isl_basic_set_free(bset);
+ }
+
+ ineq = isl_alloc_array(ctx, isl_int *, n_ineq);
+ if (n_ineq > 0 && !ineq)
+ goto error;
+
+ dim = isl_set_dim(set, isl_dim_set);
+ mat = isl_mat_alloc(ctx, n_eq, 1 + dim);
+ mat = collect_inequalities(mat, list, ineq);
+ if (!mat)
+ goto error;
+
+ if (isl_sort(ineq, n_ineq, sizeof(ineq[0]), &cmp_ineq, &dim) < 0)
+ goto error;
+
+ hull = uset_unshifted_simple_hull_from_constraints(set, n_ineq, ineq);
+
+ isl_mat_free(mat);
+ free(ineq);
+ isl_basic_set_list_free(list);
+ return hull;
+error:
+ isl_mat_free(mat);
+ free(ineq);
+ isl_set_free(set);
+ isl_basic_set_list_free(list);
+ return NULL;
+}
+
+/* Compute a superset of the convex hull of "set" that is described
+ * by only constraints in the elements of "list".
+ *
+ * If the list is empty, then we can only describe the universe set.
+ * If the input set is empty, then all constraints are valid, so
+ * we return the intersection of the elements in "list".
+ *
+ * Otherwise, we align all divs and temporarily treat them
+ * as regular variables, computing the unshifted simple hull in
+ * uset_unshifted_simple_hull_from_basic_set_list.
+ */
+static __isl_give isl_basic_set *set_unshifted_simple_hull_from_basic_set_list(
+ __isl_take isl_set *set, __isl_take isl_basic_set_list *list)
+{
+ isl_basic_set *model;
+ isl_basic_set *hull;
+
+ if (!set || !list)
+ goto error;
+
+ if (isl_basic_set_list_n_basic_set(list) == 0) {
+ isl_space *space;
+
+ space = isl_set_get_space(set);
+ isl_set_free(set);
+ isl_basic_set_list_free(list);
+ return isl_basic_set_universe(space);
+ }
+ if (isl_set_plain_is_empty(set)) {
+ isl_set_free(set);
+ return isl_basic_set_list_intersect(list);
+ }
+
+ set = isl_set_align_divs_to_basic_set_list(set, list);
+ if (!set)
+ goto error;
+ list = isl_basic_set_list_align_divs_to_basic_set(list, set->p[0]);
+
+ model = isl_basic_set_list_get_basic_set(list, 0);
+
+ set = isl_set_to_underlying_set(set);
+ list = isl_basic_set_list_underlying_set(list);
+
+ hull = uset_unshifted_simple_hull_from_basic_set_list(set, list);
+ hull = isl_basic_map_overlying_set(hull, model);
+
+ return hull;
+error:
+ isl_set_free(set);
+ isl_basic_set_list_free(list);
+ return NULL;
+}
+
+/* Return a sequence of the basic sets that make up the sets in "list".
+ */
+static __isl_give isl_basic_set_list *collect_basic_sets(
+ __isl_take isl_set_list *list)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_basic_set_list *bset_list;
+
+ if (!list)
+ return NULL;
+ n = isl_set_list_n_set(list);
+ ctx = isl_set_list_get_ctx(list);
+ bset_list = isl_basic_set_list_alloc(ctx, 0);
+
+ for (i = 0; i < n; ++i) {
+ isl_set *set;
+ isl_basic_set_list *list_i;
+
+ set = isl_set_list_get_set(list, i);
+ set = isl_set_compute_divs(set);
+ list_i = isl_set_get_basic_set_list(set);
+ isl_set_free(set);
+ bset_list = isl_basic_set_list_concat(bset_list, list_i);
+ }
+
+ isl_set_list_free(list);
+ return bset_list;
+}
+
+/* Compute a superset of the convex hull of "set" that is described
+ * by only constraints in the elements of "list".
+ *
+ * If "set" is the universe, then the convex hull (and therefore
+ * any superset of the convexhull) is the universe as well.
+ *
+ * Otherwise, we collect all the basic sets in the set list and
+ * continue with set_unshifted_simple_hull_from_basic_set_list.
+ */
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
+ __isl_take isl_set *set, __isl_take isl_set_list *list)
+{
+ isl_basic_set_list *bset_list;
+ int is_universe;
+
+ is_universe = isl_set_plain_is_universe(set);
+ if (is_universe < 0)
+ set = isl_set_free(set);
+ if (is_universe < 0 || is_universe) {
+ isl_set_list_free(list);
+ return isl_set_unshifted_simple_hull(set);
+ }
+
+ bset_list = collect_basic_sets(list);
+ return set_unshifted_simple_hull_from_basic_set_list(set, bset_list);
+}
+
+/* Given a set "set", return parametric bounds on the dimension "dim".
+ */
+static struct isl_basic_set *set_bounds(struct isl_set *set, int dim)
+{
+ unsigned set_dim = isl_set_dim(set, isl_dim_set);
+ set = isl_set_copy(set);
+ set = isl_set_eliminate_dims(set, dim + 1, set_dim - (dim + 1));
+ set = isl_set_eliminate_dims(set, 0, dim);
+ return isl_set_convex_hull(set);
+}
+
+/* Computes a "simple hull" and then check if each dimension in the
+ * resulting hull is bounded by a symbolic constant. If not, the
+ * hull is intersected with the corresponding bounds on the whole set.
+ */
+struct isl_basic_set *isl_set_bounded_simple_hull(struct isl_set *set)
+{
+ int i, j;
+ struct isl_basic_set *hull;
+ unsigned nparam, left;
+ int removed_divs = 0;
+
+ hull = isl_set_simple_hull(isl_set_copy(set));
+ if (!hull)
+ goto error;
+
+ nparam = isl_basic_set_dim(hull, isl_dim_param);
+ for (i = 0; i < isl_basic_set_dim(hull, isl_dim_set); ++i) {
+ int lower = 0, upper = 0;
+ struct isl_basic_set *bounds;
+
+ left = isl_basic_set_total_dim(hull) - nparam - i - 1;
+ for (j = 0; j < hull->n_eq; ++j) {
+ if (isl_int_is_zero(hull->eq[j][1 + nparam + i]))
+ continue;
+ if (isl_seq_first_non_zero(hull->eq[j]+1+nparam+i+1,
+ left) == -1)
+ break;
+ }
+ if (j < hull->n_eq)
+ continue;
+
+ for (j = 0; j < hull->n_ineq; ++j) {
+ if (isl_int_is_zero(hull->ineq[j][1 + nparam + i]))
+ continue;
+ if (isl_seq_first_non_zero(hull->ineq[j]+1+nparam+i+1,
+ left) != -1 ||
+ isl_seq_first_non_zero(hull->ineq[j]+1+nparam,
+ i) != -1)
+ continue;
+ if (isl_int_is_pos(hull->ineq[j][1 + nparam + i]))
+ lower = 1;
+ else
+ upper = 1;
+ if (lower && upper)
+ break;
+ }
+
+ if (lower && upper)
+ continue;
+
+ if (!removed_divs) {
+ set = isl_set_remove_divs(set);
+ if (!set)
+ goto error;
+ removed_divs = 1;
+ }
+ bounds = set_bounds(set, i);
+ hull = isl_basic_set_intersect(hull, bounds);
+ if (!hull)
+ goto error;
+ }
+
+ isl_set_free(set);
+ return hull;
+error:
+ isl_set_free(set);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_ctx.c b/polly/lib/External/isl/isl_ctx.c
new file mode 100644
index 00000000000..95880345ab8
--- /dev/null
+++ b/polly/lib/External/isl/isl_ctx.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl/vec.h>
+#include <isl_options_private.h>
+
+#define __isl_calloc(type,size) ((type *)calloc(1, size))
+#define __isl_calloc_type(type) __isl_calloc(type,sizeof(type))
+
+/* Check that the result of an allocation ("p") is not NULL and
+ * complain if it is.
+ * The only exception is when allocation size ("size") is equal to zero.
+ */
+static void *check_non_null(isl_ctx *ctx, void *p, size_t size)
+{
+ if (p || size == 0)
+ return p;
+ isl_die(ctx, isl_error_alloc, "allocation failure", return NULL);
+}
+
+/* Prepare for performing the next "operation" in the context.
+ * Return 0 if we are allowed to perform this operation and
+ * return -1 if we should abort the computation.
+ *
+ * In particular, we should stop if the user has explicitly aborted
+ * the computation or if the maximal number of operations has been exceeded.
+ */
+int isl_ctx_next_operation(isl_ctx *ctx)
+{
+ if (!ctx)
+ return -1;
+ if (ctx->abort) {
+ isl_ctx_set_error(ctx, isl_error_abort);
+ return -1;
+ }
+ if (ctx->max_operations && ctx->operations >= ctx->max_operations)
+ isl_die(ctx, isl_error_quota,
+ "maximal number of operations exceeded", return -1);
+ ctx->operations++;
+ return 0;
+}
+
+/* Call malloc and complain if it fails.
+ * If ctx is NULL, then return NULL.
+ */
+void *isl_malloc_or_die(isl_ctx *ctx, size_t size)
+{
+ if (isl_ctx_next_operation(ctx) < 0)
+ return NULL;
+ return ctx ? check_non_null(ctx, malloc(size), size) : NULL;
+}
+
+/* Call calloc and complain if it fails.
+ * If ctx is NULL, then return NULL.
+ */
+void *isl_calloc_or_die(isl_ctx *ctx, size_t nmemb, size_t size)
+{
+ if (isl_ctx_next_operation(ctx) < 0)
+ return NULL;
+ return ctx ? check_non_null(ctx, calloc(nmemb, size), nmemb) : NULL;
+}
+
+/* Call realloc and complain if it fails.
+ * If ctx is NULL, then return NULL.
+ */
+void *isl_realloc_or_die(isl_ctx *ctx, void *ptr, size_t size)
+{
+ if (isl_ctx_next_operation(ctx) < 0)
+ return NULL;
+ return ctx ? check_non_null(ctx, realloc(ptr, size), size) : NULL;
+}
+
+void isl_handle_error(isl_ctx *ctx, enum isl_error error, const char *msg,
+ const char *file, int line)
+{
+ if (!ctx)
+ return;
+
+ isl_ctx_set_error(ctx, error);
+
+ switch (ctx->opt->on_error) {
+ case ISL_ON_ERROR_WARN:
+ fprintf(stderr, "%s:%d: %s\n", file, line, msg);
+ return;
+ case ISL_ON_ERROR_CONTINUE:
+ return;
+ case ISL_ON_ERROR_ABORT:
+ fprintf(stderr, "%s:%d: %s\n", file, line, msg);
+ abort();
+ return;
+ }
+}
+
+static struct isl_options *find_nested_options(struct isl_args *args,
+ void *opt, struct isl_args *wanted)
+{
+ int i;
+ struct isl_options *options;
+
+ if (args == wanted)
+ return opt;
+
+ for (i = 0; args->args[i].type != isl_arg_end; ++i) {
+ struct isl_arg *arg = &args->args[i];
+ void *child;
+
+ if (arg->type != isl_arg_child)
+ continue;
+
+ if (arg->offset == (size_t) -1)
+ child = opt;
+ else
+ child = *(void **)(((char *)opt) + arg->offset);
+
+ options = find_nested_options(arg->u.child.child,
+ child, wanted);
+ if (options)
+ return options;
+ }
+
+ return NULL;
+}
+
+static struct isl_options *find_nested_isl_options(struct isl_args *args,
+ void *opt)
+{
+ return find_nested_options(args, opt, &isl_options_args);
+}
+
+void *isl_ctx_peek_options(isl_ctx *ctx, struct isl_args *args)
+{
+ if (!ctx)
+ return NULL;
+ if (args == &isl_options_args)
+ return ctx->opt;
+ return find_nested_options(ctx->user_args, ctx->user_opt, args);
+}
+
+isl_ctx *isl_ctx_alloc_with_options(struct isl_args *args, void *user_opt)
+{
+ struct isl_ctx *ctx = NULL;
+ struct isl_options *opt = NULL;
+ int opt_allocated = 0;
+
+ if (!user_opt)
+ return NULL;
+
+ opt = find_nested_isl_options(args, user_opt);
+ if (!opt) {
+ opt = isl_options_new_with_defaults();
+ if (!opt)
+ goto error;
+ opt_allocated = 1;
+ }
+
+ ctx = __isl_calloc_type(struct isl_ctx);
+ if (!ctx)
+ goto error;
+
+ if (isl_hash_table_init(ctx, &ctx->id_table, 0))
+ goto error;
+
+ ctx->stats = isl_calloc_type(ctx, struct isl_stats);
+ if (!ctx->stats)
+ goto error;
+
+ ctx->user_args = args;
+ ctx->user_opt = user_opt;
+ ctx->opt_allocated = opt_allocated;
+ ctx->opt = opt;
+ ctx->ref = 0;
+
+ isl_int_init(ctx->zero);
+ isl_int_set_si(ctx->zero, 0);
+
+ isl_int_init(ctx->one);
+ isl_int_set_si(ctx->one, 1);
+
+ isl_int_init(ctx->two);
+ isl_int_set_si(ctx->two, 2);
+
+ isl_int_init(ctx->negone);
+ isl_int_set_si(ctx->negone, -1);
+
+ isl_int_init(ctx->normalize_gcd);
+
+ ctx->n_cached = 0;
+ ctx->n_miss = 0;
+
+ ctx->error = isl_error_none;
+
+ ctx->operations = 0;
+ isl_ctx_set_max_operations(ctx, ctx->opt->max_operations);
+
+ return ctx;
+error:
+ isl_args_free(args, user_opt);
+ if (opt_allocated)
+ isl_options_free(opt);
+ free(ctx);
+ return NULL;
+}
+
+struct isl_ctx *isl_ctx_alloc()
+{
+ struct isl_options *opt;
+
+ opt = isl_options_new_with_defaults();
+
+ return isl_ctx_alloc_with_options(&isl_options_args, opt);
+}
+
+void isl_ctx_ref(struct isl_ctx *ctx)
+{
+ ctx->ref++;
+}
+
+void isl_ctx_deref(struct isl_ctx *ctx)
+{
+ isl_assert(ctx, ctx->ref > 0, return);
+ ctx->ref--;
+}
+
+/* Print statistics on usage.
+ */
+static void print_stats(isl_ctx *ctx)
+{
+ fprintf(stderr, "operations: %lu\n", ctx->operations);
+}
+
+void isl_ctx_free(struct isl_ctx *ctx)
+{
+ if (!ctx)
+ return;
+ if (ctx->ref != 0)
+ isl_die(ctx, isl_error_invalid,
+ "isl_ctx freed, but some objects still reference it",
+ return);
+
+ if (ctx->opt->print_stats)
+ print_stats(ctx);
+
+ isl_hash_table_clear(&ctx->id_table);
+ isl_blk_clear_cache(ctx);
+ isl_int_clear(ctx->zero);
+ isl_int_clear(ctx->one);
+ isl_int_clear(ctx->two);
+ isl_int_clear(ctx->negone);
+ isl_int_clear(ctx->normalize_gcd);
+ isl_args_free(ctx->user_args, ctx->user_opt);
+ if (ctx->opt_allocated)
+ isl_options_free(ctx->opt);
+ free(ctx->stats);
+ free(ctx);
+}
+
+struct isl_options *isl_ctx_options(isl_ctx *ctx)
+{
+ if (!ctx)
+ return NULL;
+ return ctx->opt;
+}
+
+enum isl_error isl_ctx_last_error(isl_ctx *ctx)
+{
+ return ctx->error;
+}
+
+void isl_ctx_reset_error(isl_ctx *ctx)
+{
+ ctx->error = isl_error_none;
+}
+
+void isl_ctx_set_error(isl_ctx *ctx, enum isl_error error)
+{
+ if (ctx)
+ ctx->error = error;
+}
+
+void isl_ctx_abort(isl_ctx *ctx)
+{
+ if (ctx)
+ ctx->abort = 1;
+}
+
+void isl_ctx_resume(isl_ctx *ctx)
+{
+ if (ctx)
+ ctx->abort = 0;
+}
+
+int isl_ctx_aborted(isl_ctx *ctx)
+{
+ return ctx ? ctx->abort : -1;
+}
+
+int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags)
+{
+ if (!ctx)
+ return -1;
+ return isl_args_parse(ctx->user_args, argc, argv, ctx->user_opt, flags);
+}
+
+/* Set the maximal number of iterations of "ctx" to "max_operations".
+ */
+void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations)
+{
+ if (!ctx)
+ return;
+ ctx->max_operations = max_operations;
+}
+
+/* Return the maximal number of iterations of "ctx".
+ */
+unsigned long isl_ctx_get_max_operations(isl_ctx *ctx)
+{
+ return ctx ? ctx->max_operations : 0;
+}
+
+/* Reset the number of operations performed by "ctx".
+ */
+void isl_ctx_reset_operations(isl_ctx *ctx)
+{
+ if (!ctx)
+ return;
+ ctx->operations = 0;
+}
diff --git a/polly/lib/External/isl/isl_ctx_private.h b/polly/lib/External/isl/isl_ctx_private.h
new file mode 100644
index 00000000000..b4bb2a5e46c
--- /dev/null
+++ b/polly/lib/External/isl/isl_ctx_private.h
@@ -0,0 +1,34 @@
+#include <isl/ctx.h>
+#include <isl_blk.h>
+
+struct isl_ctx {
+ int ref;
+
+ struct isl_stats *stats;
+
+ int opt_allocated;
+ struct isl_options *opt;
+ void *user_opt;
+ struct isl_args *user_args;
+
+ isl_int zero;
+ isl_int one;
+ isl_int two;
+ isl_int negone;
+
+ isl_int normalize_gcd;
+
+ int n_cached;
+ int n_miss;
+ struct isl_blk cache[ISL_BLK_CACHE_SIZE];
+ struct isl_hash_table id_table;
+
+ enum isl_error error;
+
+ int abort;
+
+ unsigned long operations;
+ unsigned long max_operations;
+};
+
+int isl_ctx_next_operation(isl_ctx *ctx);
diff --git a/polly/lib/External/isl/isl_deprecated.c b/polly/lib/External/isl/isl_deprecated.c
new file mode 100644
index 00000000000..babe0def461
--- /dev/null
+++ b/polly/lib/External/isl/isl_deprecated.c
@@ -0,0 +1,10 @@
+#include <isl/set.h>
+
+/* This function was never documented and has been replaced by
+ * isl_basic_set_add_dims.
+ */
+__isl_give isl_basic_set *isl_basic_set_add(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned n)
+{
+ return isl_basic_set_add_dims(bset, type, n);
+}
diff --git a/polly/lib/External/isl/isl_dim.c b/polly/lib/External/isl/isl_dim.c
new file mode 100644
index 00000000000..914d666b38e
--- /dev/null
+++ b/polly/lib/External/isl/isl_dim.c
@@ -0,0 +1,258 @@
+#include <isl/dim.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl/set.h>
+#include <isl/polynomial.h>
+
+isl_ctx *isl_dim_get_ctx(__isl_keep isl_space *dim)
+{
+ return isl_space_get_ctx(dim);
+}
+
+__isl_give isl_space *isl_dim_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned n_in, unsigned n_out)
+{
+ return isl_space_alloc(ctx, nparam, n_in, n_out);
+}
+__isl_give isl_space *isl_dim_set_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned dim)
+{
+ return isl_space_set_alloc(ctx, nparam, dim);
+}
+__isl_give isl_space *isl_dim_copy(__isl_keep isl_space *dim)
+{
+ return isl_space_copy(dim);
+}
+void isl_dim_free(__isl_take isl_space *dim)
+{
+ isl_space_free(dim);
+}
+
+unsigned isl_dim_size(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ return isl_space_dim(dim, type);
+}
+
+__isl_give isl_space *isl_dim_set_dim_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ return isl_space_set_dim_id(dim, type, pos, id);
+}
+int isl_dim_has_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_space_has_dim_id(dim, type, pos);
+}
+__isl_give isl_id *isl_dim_get_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_space_get_dim_id(dim, type, pos);
+}
+
+int isl_dim_find_dim_by_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, __isl_keep isl_id *id)
+{
+ return isl_space_find_dim_by_id(dim, type, id);
+}
+
+__isl_give isl_space *isl_dim_set_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ return isl_space_set_tuple_id(dim, type, id);
+}
+__isl_give isl_space *isl_dim_reset_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type)
+{
+ return isl_space_reset_tuple_id(dim, type);
+}
+int isl_dim_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ return isl_space_has_tuple_id(dim, type);
+}
+__isl_give isl_id *isl_dim_get_tuple_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ return isl_space_get_tuple_id(dim, type);
+}
+
+__isl_give isl_space *isl_dim_set_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_keep const char *name)
+{
+ return isl_space_set_dim_name(dim, type, pos, name);
+}
+__isl_keep const char *isl_dim_get_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_space_get_dim_name(dim, type, pos);
+}
+
+__isl_give isl_space *isl_dim_set_tuple_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, const char *s)
+{
+ return isl_space_set_tuple_name(dim, type, s);
+}
+const char *isl_dim_get_tuple_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ return isl_space_get_tuple_name(dim, type);
+}
+
+int isl_dim_is_wrapping(__isl_keep isl_space *dim)
+{
+ return isl_space_is_wrapping(dim);
+}
+__isl_give isl_space *isl_dim_wrap(__isl_take isl_space *dim)
+{
+ return isl_space_wrap(dim);
+}
+__isl_give isl_space *isl_dim_unwrap(__isl_take isl_space *dim)
+{
+ return isl_space_unwrap(dim);
+}
+
+__isl_give isl_space *isl_dim_domain(__isl_take isl_space *dim)
+{
+ return isl_space_domain(dim);
+}
+__isl_give isl_space *isl_dim_from_domain(__isl_take isl_space *dim)
+{
+ return isl_space_from_domain(dim);
+}
+__isl_give isl_space *isl_dim_range(__isl_take isl_space *dim)
+{
+ return isl_space_range(dim);
+}
+__isl_give isl_space *isl_dim_from_range(__isl_take isl_space *dim)
+{
+ return isl_space_from_range(dim);
+}
+__isl_give isl_space *isl_dim_reverse(__isl_take isl_space *dim)
+{
+ return isl_space_reverse(dim);
+}
+__isl_give isl_space *isl_dim_join(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ return isl_space_join(left, right);
+}
+__isl_give isl_space *isl_dim_align_params(__isl_take isl_space *dim1,
+ __isl_take isl_space *dim2)
+{
+ return isl_space_align_params(dim1, dim2);
+}
+__isl_give isl_space *isl_dim_insert(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return isl_space_insert_dims(dim, type, pos, n);
+}
+__isl_give isl_space *isl_dim_add(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned n)
+{
+ return isl_space_add_dims(dim, type, n);
+}
+__isl_give isl_space *isl_dim_drop(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_space_drop_dims(dim, type, first, n);
+}
+__isl_give isl_space *isl_dim_move(__isl_take isl_space *dim,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ return isl_space_move_dims(dim, dst_type, dst_pos, src_type, src_pos, n);
+}
+__isl_give isl_space *isl_dim_map_from_set(__isl_take isl_space *dim)
+{
+ return isl_space_map_from_set(dim);
+}
+__isl_give isl_space *isl_dim_zip(__isl_take isl_space *dim)
+{
+ return isl_space_zip(dim);
+}
+
+__isl_give isl_local_space *isl_local_space_from_dim(
+ __isl_take isl_space *dim)
+{
+ return isl_local_space_from_space(dim);
+}
+__isl_give isl_space *isl_local_space_get_dim(
+ __isl_keep isl_local_space *ls)
+{
+ return isl_local_space_get_space(ls);
+}
+
+__isl_give isl_space *isl_aff_get_dim(__isl_keep isl_aff *aff)
+{
+ return isl_aff_get_space(aff);
+}
+__isl_give isl_space *isl_pw_aff_get_dim(__isl_keep isl_pw_aff *pwaff)
+{
+ return isl_pw_aff_get_space(pwaff);
+}
+
+__isl_give isl_space *isl_constraint_get_dim(
+ __isl_keep isl_constraint *constraint)
+{
+ return isl_constraint_get_space(constraint);
+}
+
+__isl_give isl_space *isl_basic_map_get_dim(__isl_keep isl_basic_map *bmap)
+{
+ return isl_basic_map_get_space(bmap);
+}
+__isl_give isl_space *isl_map_get_dim(__isl_keep isl_map *map)
+{
+ return isl_map_get_space(map);
+}
+__isl_give isl_space *isl_union_map_get_dim(__isl_keep isl_union_map *umap)
+{
+ return isl_union_map_get_space(umap);
+}
+
+__isl_give isl_space *isl_basic_set_get_dim(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_set_get_space(bset);
+}
+__isl_give isl_space *isl_set_get_dim(__isl_keep isl_set *set)
+{
+ return isl_set_get_space(set);
+}
+__isl_give isl_space *isl_union_set_get_dim(__isl_keep isl_union_set *uset)
+{
+ return isl_union_set_get_space(uset);
+}
+
+__isl_give isl_space *isl_point_get_dim(__isl_keep isl_point *pnt)
+{
+ return isl_point_get_space(pnt);
+}
+
+__isl_give isl_space *isl_qpolynomial_get_dim(__isl_keep isl_qpolynomial *qp)
+{
+ return isl_qpolynomial_get_space(qp);
+}
+__isl_give isl_space *isl_pw_qpolynomial_get_dim(
+ __isl_keep isl_pw_qpolynomial *pwqp)
+{
+ return isl_pw_qpolynomial_get_space(pwqp);
+}
+__isl_give isl_space *isl_qpolynomial_fold_get_dim(
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ return isl_qpolynomial_fold_get_space(fold);
+}
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_dim(
+ __isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ return isl_pw_qpolynomial_fold_get_space(pwf);
+}
+__isl_give isl_space *isl_union_pw_qpolynomial_get_dim(
+ __isl_keep isl_union_pw_qpolynomial *upwqp)
+{
+ return isl_union_pw_qpolynomial_get_space(upwqp);
+}
+__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_dim(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf)
+{
+ return isl_union_pw_qpolynomial_fold_get_space(upwf);
+}
diff --git a/polly/lib/External/isl/isl_dim_map.c b/polly/lib/External/isl/isl_dim_map.c
new file mode 100644
index 00000000000..102b8e8a6a4
--- /dev/null
+++ b/polly/lib/External/isl/isl_dim_map.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010-2011 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_map_private.h>
+#include <isl_space_private.h>
+#include <isl_dim_map.h>
+#include <isl_reordering.h>
+
+struct isl_dim_map_entry {
+ int pos;
+ int sgn;
+};
+
+/* Maps dst positions to src positions */
+struct isl_dim_map {
+ unsigned len;
+ struct isl_dim_map_entry m[1];
+};
+
+__isl_give isl_dim_map *isl_dim_map_alloc(isl_ctx *ctx, unsigned len)
+{
+ int i;
+ struct isl_dim_map *dim_map;
+ dim_map = isl_alloc(ctx, struct isl_dim_map,
+ sizeof(struct isl_dim_map) + len * sizeof(struct isl_dim_map_entry));
+ if (!dim_map)
+ return NULL;
+ dim_map->len = 1 + len;
+ dim_map->m[0].pos = 0;
+ dim_map->m[0].sgn = 1;
+ for (i = 0; i < len; ++i)
+ dim_map->m[1 + i].sgn = 0;
+ return dim_map;
+}
+
+void isl_dim_map_range(__isl_keep isl_dim_map *dim_map,
+ unsigned dst_pos, unsigned dst_stride,
+ unsigned src_pos, unsigned src_stride,
+ unsigned n, int sign)
+{
+ int i;
+
+ if (!dim_map)
+ return;
+
+ for (i = 0; i < n; ++i) {
+ unsigned d = 1 + dst_pos + dst_stride * i;
+ unsigned s = 1 + src_pos + src_stride * i;
+ dim_map->m[d].pos = s;
+ dim_map->m[d].sgn = sign;
+ }
+}
+
+void isl_dim_map_dim_range(__isl_keep isl_dim_map *dim_map,
+ __isl_keep isl_space *dim, enum isl_dim_type type,
+ unsigned first, unsigned n, unsigned dst_pos)
+{
+ int i;
+ unsigned src_pos;
+
+ if (!dim_map || !dim)
+ return;
+
+ src_pos = 1 + isl_space_offset(dim, type);
+ for (i = 0; i < n; ++i) {
+ dim_map->m[1 + dst_pos + i].pos = src_pos + first + i;
+ dim_map->m[1 + dst_pos + i].sgn = 1;
+ }
+}
+
+void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map, __isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned dst_pos)
+{
+ isl_dim_map_dim_range(dim_map, dim, type,
+ 0, isl_space_dim(dim, type), dst_pos);
+}
+
+void isl_dim_map_div(__isl_keep isl_dim_map *dim_map,
+ __isl_keep isl_basic_map *bmap, unsigned dst_pos)
+{
+ int i;
+ unsigned src_pos;
+
+ if (!dim_map || !bmap)
+ return;
+
+ src_pos = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+ for (i = 0; i < bmap->n_div; ++i) {
+ dim_map->m[1 + dst_pos + i].pos = src_pos + i;
+ dim_map->m[1 + dst_pos + i].sgn = 1;
+ }
+}
+
+void isl_dim_map_dump(struct isl_dim_map *dim_map)
+{
+ int i;
+
+ for (i = 0; i < dim_map->len; ++i)
+ fprintf(stderr, "%d -> %d * %d; ", i,
+ dim_map->m[i].sgn, dim_map->m[i].pos);
+ fprintf(stderr, "\n");
+}
+
+static void copy_constraint_dim_map(isl_int *dst, isl_int *src,
+ struct isl_dim_map *dim_map)
+{
+ int i;
+
+ for (i = 0; i < dim_map->len; ++i) {
+ if (dim_map->m[i].sgn == 0)
+ isl_int_set_si(dst[i], 0);
+ else if (dim_map->m[i].sgn > 0)
+ isl_int_set(dst[i], src[dim_map->m[i].pos]);
+ else
+ isl_int_neg(dst[i], src[dim_map->m[i].pos]);
+ }
+}
+
+static void copy_div_dim_map(isl_int *dst, isl_int *src,
+ struct isl_dim_map *dim_map)
+{
+ isl_int_set(dst[0], src[0]);
+ copy_constraint_dim_map(dst+1, src+1, dim_map);
+}
+
+__isl_give isl_basic_map *isl_basic_map_add_constraints_dim_map(
+ __isl_take isl_basic_map *dst, __isl_take isl_basic_map *src,
+ __isl_take isl_dim_map *dim_map)
+{
+ int i;
+
+ if (!src || !dst || !dim_map)
+ goto error;
+
+ for (i = 0; i < src->n_eq; ++i) {
+ int i1 = isl_basic_map_alloc_equality(dst);
+ if (i1 < 0)
+ goto error;
+ copy_constraint_dim_map(dst->eq[i1], src->eq[i], dim_map);
+ }
+
+ for (i = 0; i < src->n_ineq; ++i) {
+ int i1 = isl_basic_map_alloc_inequality(dst);
+ if (i1 < 0)
+ goto error;
+ copy_constraint_dim_map(dst->ineq[i1], src->ineq[i], dim_map);
+ }
+
+ for (i = 0; i < src->n_div; ++i) {
+ int i1 = isl_basic_map_alloc_div(dst);
+ if (i1 < 0)
+ goto error;
+ copy_div_dim_map(dst->div[i1], src->div[i], dim_map);
+ }
+
+ free(dim_map);
+ isl_basic_map_free(src);
+
+ return dst;
+error:
+ free(dim_map);
+ isl_basic_map_free(src);
+ isl_basic_map_free(dst);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_add_constraints_dim_map(
+ __isl_take isl_basic_set *dst, __isl_take isl_basic_set *src,
+ __isl_take isl_dim_map *dim_map)
+{
+ return isl_basic_map_add_constraints_dim_map(dst, src, dim_map);
+}
+
+/* Extend the given dim_map with mappings for the divs in bmap.
+ */
+__isl_give isl_dim_map *isl_dim_map_extend(__isl_keep isl_dim_map *dim_map,
+ __isl_keep isl_basic_map *bmap)
+{
+ int i;
+ struct isl_dim_map *res;
+ int offset;
+
+ offset = isl_basic_map_offset(bmap, isl_dim_div);
+
+ res = isl_dim_map_alloc(bmap->ctx, dim_map->len - 1 + bmap->n_div);
+ if (!res)
+ return NULL;
+
+ for (i = 0; i < dim_map->len; ++i)
+ res->m[i] = dim_map->m[i];
+ for (i = 0; i < bmap->n_div; ++i) {
+ res->m[dim_map->len + i].pos = offset + i;
+ res->m[dim_map->len + i].sgn = 1;
+ }
+
+ return res;
+}
+
+/* Extract a dim_map from a reordering.
+ * We essentially need to reverse the mapping, and add an offset
+ * of 1 for the constant term.
+ */
+__isl_give isl_dim_map *isl_dim_map_from_reordering(
+ __isl_keep isl_reordering *exp)
+{
+ int i;
+ isl_ctx *ctx;
+ struct isl_dim_map *dim_map;
+
+ if (!exp)
+ return NULL;
+
+ ctx = isl_space_get_ctx(exp->dim);
+ dim_map = isl_dim_map_alloc(ctx, isl_space_dim(exp->dim, isl_dim_all));
+ if (!dim_map)
+ return NULL;
+
+ for (i = 0; i < exp->len; ++i) {
+ dim_map->m[1 + exp->pos[i]].pos = 1 + i;
+ dim_map->m[1 + exp->pos[i]].sgn = 1;
+ }
+
+ return dim_map;
+}
diff --git a/polly/lib/External/isl/isl_dim_map.h b/polly/lib/External/isl/isl_dim_map.h
new file mode 100644
index 00000000000..0f988c3166d
--- /dev/null
+++ b/polly/lib/External/isl/isl_dim_map.h
@@ -0,0 +1,36 @@
+#ifndef ISL_DIM_MAP_H
+#define ISL_DIM_MAP_H
+
+#include <isl/ctx.h>
+#include <isl/space.h>
+#include <isl/map.h>
+
+struct isl_dim_map;
+typedef struct isl_dim_map isl_dim_map;
+
+__isl_give isl_dim_map *isl_dim_map_alloc(isl_ctx *ctx, unsigned len);
+void isl_dim_map_range(__isl_keep isl_dim_map *dim_map,
+ unsigned dst_pos, unsigned dst_stride,
+ unsigned src_pos, unsigned src_stride,
+ unsigned n, int sign);
+void isl_dim_map_dim_range(__isl_keep isl_dim_map *dim_map,
+ isl_space *dim, enum isl_dim_type type,
+ unsigned first, unsigned n, unsigned dst_pos);
+void isl_dim_map_dim(__isl_keep isl_dim_map *dim_map, __isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned dst_pos);
+void isl_dim_map_div(__isl_keep isl_dim_map *dim_map,
+ __isl_keep isl_basic_map *bmap, unsigned dst_pos);
+__isl_give isl_basic_set *isl_basic_set_add_constraints_dim_map(
+ __isl_take isl_basic_set *dst, __isl_take isl_basic_set *src,
+ __isl_take isl_dim_map *dim_map);
+__isl_give isl_basic_map *isl_basic_map_add_constraints_dim_map(
+ __isl_take isl_basic_map *dst, __isl_take isl_basic_map *src,
+ __isl_take isl_dim_map *dim_map);
+
+__isl_give isl_dim_map *isl_dim_map_extend(__isl_keep isl_dim_map *dim_map,
+ __isl_keep isl_basic_map *bmap);
+
+__isl_give isl_dim_map *isl_dim_map_from_reordering(
+ __isl_keep isl_reordering *exp);
+
+#endif
diff --git a/polly/lib/External/isl/isl_equalities.c b/polly/lib/External/isl/isl_equalities.c
new file mode 100644
index 00000000000..e257f705f53
--- /dev/null
+++ b/polly/lib/External/isl/isl_equalities.c
@@ -0,0 +1,782 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_seq.h>
+#include "isl_map_private.h"
+#include "isl_equalities.h"
+#include <isl_val_private.h>
+
+/* Given a set of modulo constraints
+ *
+ * c + A y = 0 mod d
+ *
+ * this function computes a particular solution y_0
+ *
+ * The input is given as a matrix B = [ c A ] and a vector d.
+ *
+ * The output is matrix containing the solution y_0 or
+ * a zero-column matrix if the constraints admit no integer solution.
+ *
+ * The given set of constrains is equivalent to
+ *
+ * c + A y = -D x
+ *
+ * with D = diag d and x a fresh set of variables.
+ * Reducing both c and A modulo d does not change the
+ * value of y in the solution and may lead to smaller coefficients.
+ * Let M = [ D A ] and [ H 0 ] = M U, the Hermite normal form of M.
+ * Then
+ * [ x ]
+ * M [ y ] = - c
+ * and so
+ * [ x ]
+ * [ H 0 ] U^{-1} [ y ] = - c
+ * Let
+ * [ A ] [ x ]
+ * [ B ] = U^{-1} [ y ]
+ * then
+ * H A + 0 B = -c
+ *
+ * so B may be chosen arbitrarily, e.g., B = 0, and then
+ *
+ * [ x ] = [ -c ]
+ * U^{-1} [ y ] = [ 0 ]
+ * or
+ * [ x ] [ -c ]
+ * [ y ] = U [ 0 ]
+ * specifically,
+ *
+ * y = U_{2,1} (-c)
+ *
+ * If any of the coordinates of this y are non-integer
+ * then the constraints admit no integer solution and
+ * a zero-column matrix is returned.
+ */
+static struct isl_mat *particular_solution(struct isl_mat *B, struct isl_vec *d)
+{
+ int i, j;
+ struct isl_mat *M = NULL;
+ struct isl_mat *C = NULL;
+ struct isl_mat *U = NULL;
+ struct isl_mat *H = NULL;
+ struct isl_mat *cst = NULL;
+ struct isl_mat *T = NULL;
+
+ M = isl_mat_alloc(B->ctx, B->n_row, B->n_row + B->n_col - 1);
+ C = isl_mat_alloc(B->ctx, 1 + B->n_row, 1);
+ if (!M || !C)
+ goto error;
+ isl_int_set_si(C->row[0][0], 1);
+ for (i = 0; i < B->n_row; ++i) {
+ isl_seq_clr(M->row[i], B->n_row);
+ isl_int_set(M->row[i][i], d->block.data[i]);
+ isl_int_neg(C->row[1 + i][0], B->row[i][0]);
+ isl_int_fdiv_r(C->row[1+i][0], C->row[1+i][0], M->row[i][i]);
+ for (j = 0; j < B->n_col - 1; ++j)
+ isl_int_fdiv_r(M->row[i][B->n_row + j],
+ B->row[i][1 + j], M->row[i][i]);
+ }
+ M = isl_mat_left_hermite(M, 0, &U, NULL);
+ if (!M || !U)
+ goto error;
+ H = isl_mat_sub_alloc(M, 0, B->n_row, 0, B->n_row);
+ H = isl_mat_lin_to_aff(H);
+ C = isl_mat_inverse_product(H, C);
+ if (!C)
+ goto error;
+ for (i = 0; i < B->n_row; ++i) {
+ if (!isl_int_is_divisible_by(C->row[1+i][0], C->row[0][0]))
+ break;
+ isl_int_divexact(C->row[1+i][0], C->row[1+i][0], C->row[0][0]);
+ }
+ if (i < B->n_row)
+ cst = isl_mat_alloc(B->ctx, B->n_row, 0);
+ else
+ cst = isl_mat_sub_alloc(C, 1, B->n_row, 0, 1);
+ T = isl_mat_sub_alloc(U, B->n_row, B->n_col - 1, 0, B->n_row);
+ cst = isl_mat_product(T, cst);
+ isl_mat_free(M);
+ isl_mat_free(C);
+ isl_mat_free(U);
+ return cst;
+error:
+ isl_mat_free(M);
+ isl_mat_free(C);
+ isl_mat_free(U);
+ return NULL;
+}
+
+/* Compute and return the matrix
+ *
+ * U_1^{-1} diag(d_1, 1, ..., 1)
+ *
+ * with U_1 the unimodular completion of the first (and only) row of B.
+ * The columns of this matrix generate the lattice that satisfies
+ * the single (linear) modulo constraint.
+ */
+static struct isl_mat *parameter_compression_1(
+ struct isl_mat *B, struct isl_vec *d)
+{
+ struct isl_mat *U;
+
+ U = isl_mat_alloc(B->ctx, B->n_col - 1, B->n_col - 1);
+ if (!U)
+ return NULL;
+ isl_seq_cpy(U->row[0], B->row[0] + 1, B->n_col - 1);
+ U = isl_mat_unimodular_complete(U, 1);
+ U = isl_mat_right_inverse(U);
+ if (!U)
+ return NULL;
+ isl_mat_col_mul(U, 0, d->block.data[0], 0);
+ U = isl_mat_lin_to_aff(U);
+ return U;
+}
+
+/* Compute a common lattice of solutions to the linear modulo
+ * constraints specified by B and d.
+ * See also the documentation of isl_mat_parameter_compression.
+ * We put the matrix
+ *
+ * A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ]
+ *
+ * on a common denominator. This denominator D is the lcm of modulos d.
+ * Since L_i = U_i^{-1} diag(d_i, 1, ... 1), we have
+ * L_i^{-T} = U_i^T diag(d_i, 1, ... 1)^{-T} = U_i^T diag(1/d_i, 1, ..., 1).
+ * Putting this on the common denominator, we have
+ * D * L_i^{-T} = U_i^T diag(D/d_i, D, ..., D).
+ */
+static struct isl_mat *parameter_compression_multi(
+ struct isl_mat *B, struct isl_vec *d)
+{
+ int i, j, k;
+ isl_int D;
+ struct isl_mat *A = NULL, *U = NULL;
+ struct isl_mat *T;
+ unsigned size;
+
+ isl_int_init(D);
+
+ isl_vec_lcm(d, &D);
+
+ size = B->n_col - 1;
+ A = isl_mat_alloc(B->ctx, size, B->n_row * size);
+ U = isl_mat_alloc(B->ctx, size, size);
+ if (!U || !A)
+ goto error;
+ for (i = 0; i < B->n_row; ++i) {
+ isl_seq_cpy(U->row[0], B->row[i] + 1, size);
+ U = isl_mat_unimodular_complete(U, 1);
+ if (!U)
+ goto error;
+ isl_int_divexact(D, D, d->block.data[i]);
+ for (k = 0; k < U->n_col; ++k)
+ isl_int_mul(A->row[k][i*size+0], D, U->row[0][k]);
+ isl_int_mul(D, D, d->block.data[i]);
+ for (j = 1; j < U->n_row; ++j)
+ for (k = 0; k < U->n_col; ++k)
+ isl_int_mul(A->row[k][i*size+j],
+ D, U->row[j][k]);
+ }
+ A = isl_mat_left_hermite(A, 0, NULL, NULL);
+ T = isl_mat_sub_alloc(A, 0, A->n_row, 0, A->n_row);
+ T = isl_mat_lin_to_aff(T);
+ if (!T)
+ goto error;
+ isl_int_set(T->row[0][0], D);
+ T = isl_mat_right_inverse(T);
+ if (!T)
+ goto error;
+ isl_assert(T->ctx, isl_int_is_one(T->row[0][0]), goto error);
+ T = isl_mat_transpose(T);
+ isl_mat_free(A);
+ isl_mat_free(U);
+
+ isl_int_clear(D);
+ return T;
+error:
+ isl_mat_free(A);
+ isl_mat_free(U);
+ isl_int_clear(D);
+ return NULL;
+}
+
+/* Given a set of modulo constraints
+ *
+ * c + A y = 0 mod d
+ *
+ * this function returns an affine transformation T,
+ *
+ * y = T y'
+ *
+ * that bijectively maps the integer vectors y' to integer
+ * vectors y that satisfy the modulo constraints.
+ *
+ * This function is inspired by Section 2.5.3
+ * of B. Meister, "Stating and Manipulating Periodicity in the Polytope
+ * Model. Applications to Program Analysis and Optimization".
+ * However, the implementation only follows the algorithm of that
+ * section for computing a particular solution and not for computing
+ * a general homogeneous solution. The latter is incomplete and
+ * may remove some valid solutions.
+ * Instead, we use an adaptation of the algorithm in Section 7 of
+ * B. Meister, S. Verdoolaege, "Polynomial Approximations in the Polytope
+ * Model: Bringing the Power of Quasi-Polynomials to the Masses".
+ *
+ * The input is given as a matrix B = [ c A ] and a vector d.
+ * Each element of the vector d corresponds to a row in B.
+ * The output is a lower triangular matrix.
+ * If no integer vector y satisfies the given constraints then
+ * a matrix with zero columns is returned.
+ *
+ * We first compute a particular solution y_0 to the given set of
+ * modulo constraints in particular_solution. If no such solution
+ * exists, then we return a zero-columned transformation matrix.
+ * Otherwise, we compute the generic solution to
+ *
+ * A y = 0 mod d
+ *
+ * That is we want to compute G such that
+ *
+ * y = G y''
+ *
+ * with y'' integer, describes the set of solutions.
+ *
+ * We first remove the common factors of each row.
+ * In particular if gcd(A_i,d_i) != 1, then we divide the whole
+ * row i (including d_i) by this common factor. If afterwards gcd(A_i) != 1,
+ * then we divide this row of A by the common factor, unless gcd(A_i) = 0.
+ * In the later case, we simply drop the row (in both A and d).
+ *
+ * If there are no rows left in A, then G is the identity matrix. Otherwise,
+ * for each row i, we now determine the lattice of integer vectors
+ * that satisfies this row. Let U_i be the unimodular extension of the
+ * row A_i. This unimodular extension exists because gcd(A_i) = 1.
+ * The first component of
+ *
+ * y' = U_i y
+ *
+ * needs to be a multiple of d_i. Let y' = diag(d_i, 1, ..., 1) y''.
+ * Then,
+ *
+ * y = U_i^{-1} diag(d_i, 1, ..., 1) y''
+ *
+ * for arbitrary integer vectors y''. That is, y belongs to the lattice
+ * generated by the columns of L_i = U_i^{-1} diag(d_i, 1, ..., 1).
+ * If there is only one row, then G = L_1.
+ *
+ * If there is more than one row left, we need to compute the intersection
+ * of the lattices. That is, we need to compute an L such that
+ *
+ * L = L_i L_i' for all i
+ *
+ * with L_i' some integer matrices. Let A be constructed as follows
+ *
+ * A = [ L_1^{-T} L_2^{-T} ... L_k^{-T} ]
+ *
+ * and computed the Hermite Normal Form of A = [ H 0 ] U
+ * Then,
+ *
+ * L_i^{-T} = H U_{1,i}
+ *
+ * or
+ *
+ * H^{-T} = L_i U_{1,i}^T
+ *
+ * In other words G = L = H^{-T}.
+ * To ensure that G is lower triangular, we compute and use its Hermite
+ * normal form.
+ *
+ * The affine transformation matrix returned is then
+ *
+ * [ 1 0 ]
+ * [ y_0 G ]
+ *
+ * as any y = y_0 + G y' with y' integer is a solution to the original
+ * modulo constraints.
+ */
+struct isl_mat *isl_mat_parameter_compression(
+ struct isl_mat *B, struct isl_vec *d)
+{
+ int i;
+ struct isl_mat *cst = NULL;
+ struct isl_mat *T = NULL;
+ isl_int D;
+
+ if (!B || !d)
+ goto error;
+ isl_assert(B->ctx, B->n_row == d->size, goto error);
+ cst = particular_solution(B, d);
+ if (!cst)
+ goto error;
+ if (cst->n_col == 0) {
+ T = isl_mat_alloc(B->ctx, B->n_col, 0);
+ isl_mat_free(cst);
+ isl_mat_free(B);
+ isl_vec_free(d);
+ return T;
+ }
+ isl_int_init(D);
+ /* Replace a*g*row = 0 mod g*m by row = 0 mod m */
+ for (i = 0; i < B->n_row; ++i) {
+ isl_seq_gcd(B->row[i] + 1, B->n_col - 1, &D);
+ if (isl_int_is_one(D))
+ continue;
+ if (isl_int_is_zero(D)) {
+ B = isl_mat_drop_rows(B, i, 1);
+ d = isl_vec_cow(d);
+ if (!B || !d)
+ goto error2;
+ isl_seq_cpy(d->block.data+i, d->block.data+i+1,
+ d->size - (i+1));
+ d->size--;
+ i--;
+ continue;
+ }
+ B = isl_mat_cow(B);
+ if (!B)
+ goto error2;
+ isl_seq_scale_down(B->row[i] + 1, B->row[i] + 1, D, B->n_col-1);
+ isl_int_gcd(D, D, d->block.data[i]);
+ d = isl_vec_cow(d);
+ if (!d)
+ goto error2;
+ isl_int_divexact(d->block.data[i], d->block.data[i], D);
+ }
+ isl_int_clear(D);
+ if (B->n_row == 0)
+ T = isl_mat_identity(B->ctx, B->n_col);
+ else if (B->n_row == 1)
+ T = parameter_compression_1(B, d);
+ else
+ T = parameter_compression_multi(B, d);
+ T = isl_mat_left_hermite(T, 0, NULL, NULL);
+ if (!T)
+ goto error;
+ isl_mat_sub_copy(T->ctx, T->row + 1, cst->row, cst->n_row, 0, 0, 1);
+ isl_mat_free(cst);
+ isl_mat_free(B);
+ isl_vec_free(d);
+ return T;
+error2:
+ isl_int_clear(D);
+error:
+ isl_mat_free(cst);
+ isl_mat_free(B);
+ isl_vec_free(d);
+ return NULL;
+}
+
+/* Given a set of equalities
+ *
+ * B(y) + A x = 0 (*)
+ *
+ * compute and return an affine transformation T,
+ *
+ * y = T y'
+ *
+ * that bijectively maps the integer vectors y' to integer
+ * vectors y that satisfy the modulo constraints for some value of x.
+ *
+ * Let [H 0] be the Hermite Normal Form of A, i.e.,
+ *
+ * A = [H 0] Q
+ *
+ * Then y is a solution of (*) iff
+ *
+ * H^-1 B(y) (= - [I 0] Q x)
+ *
+ * is an integer vector. Let d be the common denominator of H^-1.
+ * We impose
+ *
+ * d H^-1 B(y) = 0 mod d
+ *
+ * and compute the solution using isl_mat_parameter_compression.
+ */
+__isl_give isl_mat *isl_mat_parameter_compression_ext(__isl_take isl_mat *B,
+ __isl_take isl_mat *A)
+{
+ isl_ctx *ctx;
+ isl_vec *d;
+ int n_row, n_col;
+
+ if (!A)
+ return isl_mat_free(B);
+
+ ctx = isl_mat_get_ctx(A);
+ n_row = A->n_row;
+ n_col = A->n_col;
+ A = isl_mat_left_hermite(A, 0, NULL, NULL);
+ A = isl_mat_drop_cols(A, n_row, n_col - n_row);
+ A = isl_mat_lin_to_aff(A);
+ A = isl_mat_right_inverse(A);
+ d = isl_vec_alloc(ctx, n_row);
+ if (A)
+ d = isl_vec_set(d, A->row[0][0]);
+ A = isl_mat_drop_rows(A, 0, 1);
+ A = isl_mat_drop_cols(A, 0, 1);
+ B = isl_mat_product(A, B);
+
+ return isl_mat_parameter_compression(B, d);
+}
+
+/* Given a set of equalities
+ *
+ * M x - c = 0
+ *
+ * this function computes a unimodular transformation from a lower-dimensional
+ * space to the original space that bijectively maps the integer points x'
+ * in the lower-dimensional space to the integer points x in the original
+ * space that satisfy the equalities.
+ *
+ * The input is given as a matrix B = [ -c M ] and the output is a
+ * matrix that maps [1 x'] to [1 x].
+ * If T2 is not NULL, then *T2 is set to a matrix mapping [1 x] to [1 x'].
+ *
+ * First compute the (left) Hermite normal form of M,
+ *
+ * M [U1 U2] = M U = H = [H1 0]
+ * or
+ * M = H Q = [H1 0] [Q1]
+ * [Q2]
+ *
+ * with U, Q unimodular, Q = U^{-1} (and H lower triangular).
+ * Define the transformed variables as
+ *
+ * x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x
+ * [ x2' ] [Q2]
+ *
+ * The equalities then become
+ *
+ * H1 x1' - c = 0 or x1' = H1^{-1} c = c'
+ *
+ * If any of the c' is non-integer, then the original set has no
+ * integer solutions (since the x' are a unimodular transformation
+ * of the x) and a zero-column matrix is returned.
+ * Otherwise, the transformation is given by
+ *
+ * x = U1 H1^{-1} c + U2 x2'
+ *
+ * The inverse transformation is simply
+ *
+ * x2' = Q2 x
+ */
+__isl_give isl_mat *isl_mat_variable_compression(__isl_take isl_mat *B,
+ __isl_give isl_mat **T2)
+{
+ int i;
+ struct isl_mat *H = NULL, *C = NULL, *H1, *U = NULL, *U1, *U2, *TC;
+ unsigned dim;
+
+ if (T2)
+ *T2 = NULL;
+ if (!B)
+ goto error;
+
+ dim = B->n_col - 1;
+ H = isl_mat_sub_alloc(B, 0, B->n_row, 1, dim);
+ H = isl_mat_left_hermite(H, 0, &U, T2);
+ if (!H || !U || (T2 && !*T2))
+ goto error;
+ if (T2) {
+ *T2 = isl_mat_drop_rows(*T2, 0, B->n_row);
+ *T2 = isl_mat_lin_to_aff(*T2);
+ if (!*T2)
+ goto error;
+ }
+ C = isl_mat_alloc(B->ctx, 1+B->n_row, 1);
+ if (!C)
+ goto error;
+ isl_int_set_si(C->row[0][0], 1);
+ isl_mat_sub_neg(C->ctx, C->row+1, B->row, B->n_row, 0, 0, 1);
+ H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row);
+ H1 = isl_mat_lin_to_aff(H1);
+ TC = isl_mat_inverse_product(H1, C);
+ if (!TC)
+ goto error;
+ isl_mat_free(H);
+ if (!isl_int_is_one(TC->row[0][0])) {
+ for (i = 0; i < B->n_row; ++i) {
+ if (!isl_int_is_divisible_by(TC->row[1+i][0], TC->row[0][0])) {
+ struct isl_ctx *ctx = B->ctx;
+ isl_mat_free(B);
+ isl_mat_free(TC);
+ isl_mat_free(U);
+ if (T2) {
+ isl_mat_free(*T2);
+ *T2 = NULL;
+ }
+ return isl_mat_alloc(ctx, 1 + dim, 0);
+ }
+ isl_seq_scale_down(TC->row[1+i], TC->row[1+i], TC->row[0][0], 1);
+ }
+ isl_int_set_si(TC->row[0][0], 1);
+ }
+ U1 = isl_mat_sub_alloc(U, 0, U->n_row, 0, B->n_row);
+ U1 = isl_mat_lin_to_aff(U1);
+ U2 = isl_mat_sub_alloc(U, 0, U->n_row, B->n_row, U->n_row - B->n_row);
+ U2 = isl_mat_lin_to_aff(U2);
+ isl_mat_free(U);
+ TC = isl_mat_product(U1, TC);
+ TC = isl_mat_aff_direct_sum(TC, U2);
+
+ isl_mat_free(B);
+
+ return TC;
+error:
+ isl_mat_free(B);
+ isl_mat_free(H);
+ isl_mat_free(U);
+ if (T2) {
+ isl_mat_free(*T2);
+ *T2 = NULL;
+ }
+ return NULL;
+}
+
+/* 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
+ * transformed variables x2'. The matrix pointed to by T maps
+ * the new variables x2' back to the original variables x, while T2
+ * maps the original variables to the new variables.
+ */
+static struct isl_basic_set *compress_variables(
+ struct isl_basic_set *bset, struct isl_mat **T, struct isl_mat **T2)
+{
+ struct isl_mat *B, *TC;
+ unsigned dim;
+
+ if (T)
+ *T = NULL;
+ if (T2)
+ *T2 = NULL;
+ if (!bset)
+ goto error;
+ isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
+ isl_assert(bset->ctx, bset->n_div == 0, goto error);
+ dim = isl_basic_set_n_dim(bset);
+ isl_assert(bset->ctx, bset->n_eq <= dim, goto error);
+ if (bset->n_eq == 0)
+ return bset;
+
+ B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 0, 1 + dim);
+ TC = isl_mat_variable_compression(B, T2);
+ if (!TC)
+ goto error;
+ if (TC->n_col == 0) {
+ isl_mat_free(TC);
+ if (T2) {
+ isl_mat_free(*T2);
+ *T2 = NULL;
+ }
+ return isl_basic_set_set_to_empty(bset);
+ }
+
+ bset = isl_basic_set_preimage(bset, T ? isl_mat_copy(TC) : TC);
+ if (T)
+ *T = TC;
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_remove_equalities(
+ struct isl_basic_set *bset, struct isl_mat **T, struct isl_mat **T2)
+{
+ if (T)
+ *T = NULL;
+ if (T2)
+ *T2 = NULL;
+ if (!bset)
+ return NULL;
+ 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;
+ bset = compress_variables(bset, T, T2);
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ *T = NULL;
+ return NULL;
+}
+
+/* Check if dimension dim belongs to a residue class
+ * i_dim \equiv r mod m
+ * with m != 1 and if so return m in *modulo and r in *residue.
+ * As a special case, when i_dim has a fixed value v, then
+ * *modulo is set to 0 and *residue to v.
+ *
+ * If i_dim does not belong to such a residue class, then *modulo
+ * is set to 1 and *residue is set to 0.
+ */
+int isl_basic_set_dim_residue_class(struct isl_basic_set *bset,
+ int pos, isl_int *modulo, isl_int *residue)
+{
+ struct isl_ctx *ctx;
+ struct isl_mat *H = NULL, *U = NULL, *C, *H1, *U1;
+ unsigned total;
+ unsigned nparam;
+
+ if (!bset || !modulo || !residue)
+ return -1;
+
+ if (isl_basic_set_plain_dim_is_fixed(bset, pos, residue)) {
+ isl_int_set_si(*modulo, 0);
+ return 0;
+ }
+
+ ctx = bset->ctx;
+ total = isl_basic_set_total_dim(bset);
+ nparam = isl_basic_set_n_param(bset);
+ H = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq, 1, total);
+ H = isl_mat_left_hermite(H, 0, &U, NULL);
+ if (!H)
+ return -1;
+
+ isl_seq_gcd(U->row[nparam + pos]+bset->n_eq,
+ total-bset->n_eq, modulo);
+ if (isl_int_is_zero(*modulo))
+ isl_int_set_si(*modulo, 1);
+ if (isl_int_is_one(*modulo)) {
+ isl_int_set_si(*residue, 0);
+ isl_mat_free(H);
+ isl_mat_free(U);
+ return 0;
+ }
+
+ C = isl_mat_alloc(bset->ctx, 1+bset->n_eq, 1);
+ if (!C)
+ goto error;
+ isl_int_set_si(C->row[0][0], 1);
+ isl_mat_sub_neg(C->ctx, C->row+1, bset->eq, bset->n_eq, 0, 0, 1);
+ H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row);
+ H1 = isl_mat_lin_to_aff(H1);
+ C = isl_mat_inverse_product(H1, C);
+ isl_mat_free(H);
+ U1 = isl_mat_sub_alloc(U, nparam+pos, 1, 0, bset->n_eq);
+ U1 = isl_mat_lin_to_aff(U1);
+ isl_mat_free(U);
+ C = isl_mat_product(U1, C);
+ if (!C)
+ return -1;
+ if (!isl_int_is_divisible_by(C->row[1][0], C->row[0][0])) {
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_set_to_empty(bset);
+ isl_basic_set_free(bset);
+ isl_int_set_si(*modulo, 1);
+ isl_int_set_si(*residue, 0);
+ return 0;
+ }
+ isl_int_divexact(*residue, C->row[1][0], C->row[0][0]);
+ isl_int_fdiv_r(*residue, *residue, *modulo);
+ isl_mat_free(C);
+ return 0;
+error:
+ isl_mat_free(H);
+ isl_mat_free(U);
+ return -1;
+}
+
+/* Check if dimension dim belongs to a residue class
+ * i_dim \equiv r mod m
+ * with m != 1 and if so return m in *modulo and r in *residue.
+ * As a special case, when i_dim has a fixed value v, then
+ * *modulo is set to 0 and *residue to v.
+ *
+ * If i_dim does not belong to such a residue class, then *modulo
+ * is set to 1 and *residue is set to 0.
+ */
+int isl_set_dim_residue_class(struct isl_set *set,
+ int pos, isl_int *modulo, isl_int *residue)
+{
+ isl_int m;
+ isl_int r;
+ int i;
+
+ if (!set || !modulo || !residue)
+ return -1;
+
+ if (set->n == 0) {
+ isl_int_set_si(*modulo, 0);
+ isl_int_set_si(*residue, 0);
+ return 0;
+ }
+
+ if (isl_basic_set_dim_residue_class(set->p[0], pos, modulo, residue)<0)
+ return -1;
+
+ if (set->n == 1)
+ return 0;
+
+ if (isl_int_is_one(*modulo))
+ return 0;
+
+ isl_int_init(m);
+ isl_int_init(r);
+
+ for (i = 1; i < set->n; ++i) {
+ if (isl_basic_set_dim_residue_class(set->p[i], pos, &m, &r) < 0)
+ goto error;
+ isl_int_gcd(*modulo, *modulo, m);
+ isl_int_sub(m, *residue, r);
+ isl_int_gcd(*modulo, *modulo, m);
+ if (!isl_int_is_zero(*modulo))
+ isl_int_fdiv_r(*residue, *residue, *modulo);
+ if (isl_int_is_one(*modulo))
+ break;
+ }
+
+ isl_int_clear(m);
+ isl_int_clear(r);
+
+ return 0;
+error:
+ isl_int_clear(m);
+ isl_int_clear(r);
+ return -1;
+}
+
+/* Check if dimension "dim" belongs to a residue class
+ * i_dim \equiv r mod m
+ * with m != 1 and if so return m in *modulo and r in *residue.
+ * As a special case, when i_dim has a fixed value v, then
+ * *modulo is set to 0 and *residue to v.
+ *
+ * If i_dim does not belong to such a residue class, then *modulo
+ * is set to 1 and *residue is set to 0.
+ */
+int isl_set_dim_residue_class_val(__isl_keep isl_set *set,
+ int pos, __isl_give isl_val **modulo, __isl_give isl_val **residue)
+{
+ *modulo = NULL;
+ *residue = NULL;
+ if (!set)
+ return -1;
+ *modulo = isl_val_alloc(isl_set_get_ctx(set));
+ *residue = isl_val_alloc(isl_set_get_ctx(set));
+ if (!*modulo || !*residue)
+ goto error;
+ if (isl_set_dim_residue_class(set, pos,
+ &(*modulo)->n, &(*residue)->n) < 0)
+ goto error;
+ isl_int_set_si((*modulo)->d, 1);
+ isl_int_set_si((*residue)->d, 1);
+ return 0;
+error:
+ isl_val_free(*modulo);
+ isl_val_free(*residue);
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_equalities.h b/polly/lib/External/isl/isl_equalities.h
new file mode 100644
index 00000000000..0206cd1c222
--- /dev/null
+++ b/polly/lib/External/isl/isl_equalities.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_EQUALITIES_H
+#define ISL_EQUALITIES_H
+
+#include <isl/set.h>
+#include <isl/mat.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_mat *isl_mat_variable_compression(__isl_take isl_mat *B,
+ __isl_give isl_mat **T2);
+struct isl_mat *isl_mat_parameter_compression(
+ struct isl_mat *B, struct isl_vec *d);
+__isl_give isl_mat *isl_mat_parameter_compression_ext(__isl_take isl_mat *B,
+ __isl_take isl_mat *A);
+struct isl_basic_set *isl_basic_set_remove_equalities(
+ struct isl_basic_set *bset, struct isl_mat **T, struct isl_mat **T2);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_factorization.c b/polly/lib/External/isl/isl_factorization.c
new file mode 100644
index 00000000000..f692cdbcd0b
--- /dev/null
+++ b/polly/lib/External/isl/isl_factorization.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2005-2007 Universiteit Leiden
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
+ * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
+ * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
+ * B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_map_private.h>
+#include <isl_factorization.h>
+#include <isl_space_private.h>
+#include <isl_mat_private.h>
+
+static __isl_give isl_factorizer *isl_factorizer_alloc(
+ __isl_take isl_morph *morph, int n_group)
+{
+ isl_factorizer *f = NULL;
+ int *len = NULL;
+
+ if (!morph)
+ return NULL;
+
+ if (n_group > 0) {
+ len = isl_alloc_array(morph->dom->ctx, int, n_group);
+ if (!len)
+ goto error;
+ }
+
+ f = isl_alloc_type(morph->dom->ctx, struct isl_factorizer);
+ if (!f)
+ goto error;
+
+ f->morph = morph;
+ f->n_group = n_group;
+ f->len = len;
+
+ return f;
+error:
+ free(len);
+ isl_morph_free(morph);
+ return NULL;
+}
+
+void isl_factorizer_free(__isl_take isl_factorizer *f)
+{
+ if (!f)
+ return;
+
+ isl_morph_free(f->morph);
+ free(f->len);
+ free(f);
+}
+
+void isl_factorizer_dump(__isl_take isl_factorizer *f)
+{
+ int i;
+
+ if (!f)
+ return;
+
+ isl_morph_print_internal(f->morph, stderr);
+ fprintf(stderr, "[");
+ for (i = 0; i < f->n_group; ++i) {
+ if (i)
+ fprintf(stderr, ", ");
+ fprintf(stderr, "%d", f->len[i]);
+ }
+ fprintf(stderr, "]\n");
+}
+
+__isl_give isl_factorizer *isl_factorizer_identity(__isl_keep isl_basic_set *bset)
+{
+ return isl_factorizer_alloc(isl_morph_identity(bset), 0);
+}
+
+__isl_give isl_factorizer *isl_factorizer_groups(__isl_keep isl_basic_set *bset,
+ __isl_take isl_mat *Q, __isl_take isl_mat *U, int n, int *len)
+{
+ int i;
+ unsigned nvar;
+ unsigned ovar;
+ isl_space *dim;
+ isl_basic_set *dom;
+ isl_basic_set *ran;
+ isl_morph *morph;
+ isl_factorizer *f;
+ isl_mat *id;
+
+ if (!bset || !Q || !U)
+ goto error;
+
+ ovar = 1 + isl_space_offset(bset->dim, isl_dim_set);
+ id = isl_mat_identity(bset->ctx, ovar);
+ Q = isl_mat_diagonal(isl_mat_copy(id), Q);
+ U = isl_mat_diagonal(id, U);
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ dim = isl_basic_set_get_space(bset);
+ dom = isl_basic_set_universe(isl_space_copy(dim));
+ dim = isl_space_drop_dims(dim, isl_dim_set, 0, nvar);
+ dim = isl_space_add_dims(dim, isl_dim_set, nvar);
+ ran = isl_basic_set_universe(dim);
+ morph = isl_morph_alloc(dom, ran, Q, U);
+ f = isl_factorizer_alloc(morph, n);
+ if (!f)
+ return NULL;
+ for (i = 0; i < n; ++i)
+ f->len[i] = len[i];
+ return f;
+error:
+ isl_mat_free(Q);
+ isl_mat_free(U);
+ return NULL;
+}
+
+struct isl_factor_groups {
+ int *pos; /* for each column: row position of pivot */
+ int *group; /* group to which a column belongs */
+ int *cnt; /* number of columns in the group */
+ int *rowgroup; /* group to which a constraint belongs */
+};
+
+/* Initialize isl_factor_groups structure: find pivot row positions,
+ * each column initially belongs to its own group and the groups
+ * of the constraints are still unknown.
+ */
+static int init_groups(struct isl_factor_groups *g, __isl_keep isl_mat *H)
+{
+ int i, j;
+
+ if (!H)
+ return -1;
+
+ g->pos = isl_alloc_array(H->ctx, int, H->n_col);
+ g->group = isl_alloc_array(H->ctx, int, H->n_col);
+ g->cnt = isl_alloc_array(H->ctx, int, H->n_col);
+ g->rowgroup = isl_alloc_array(H->ctx, int, H->n_row);
+
+ if (!g->pos || !g->group || !g->cnt || !g->rowgroup)
+ return -1;
+
+ for (i = 0; i < H->n_row; ++i)
+ g->rowgroup[i] = -1;
+ for (i = 0, j = 0; i < H->n_col; ++i) {
+ for ( ; j < H->n_row; ++j)
+ if (!isl_int_is_zero(H->row[j][i]))
+ break;
+ g->pos[i] = j;
+ }
+ for (i = 0; i < H->n_col; ++i) {
+ g->group[i] = i;
+ g->cnt[i] = 1;
+ }
+
+ return 0;
+}
+
+/* Update group[k] to the group column k belongs to.
+ * When merging two groups, only the group of the current
+ * group leader is changed. Here we change the group of
+ * the other members to also point to the group that the
+ * old group leader now points to.
+ */
+static void update_group(struct isl_factor_groups *g, int k)
+{
+ int p = g->group[k];
+ while (g->cnt[p] == 0)
+ p = g->group[p];
+ g->group[k] = p;
+}
+
+/* Merge group i with all groups of the subsequent columns
+ * with non-zero coefficients in row j of H.
+ * (The previous columns are all zero; otherwise we would have handled
+ * the row before.)
+ */
+static int update_group_i_with_row_j(struct isl_factor_groups *g, int i, int j,
+ __isl_keep isl_mat *H)
+{
+ int k;
+
+ g->rowgroup[j] = g->group[i];
+ for (k = i + 1; k < H->n_col && j >= g->pos[k]; ++k) {
+ update_group(g, k);
+ update_group(g, i);
+ if (g->group[k] != g->group[i] &&
+ !isl_int_is_zero(H->row[j][k])) {
+ isl_assert(H->ctx, g->cnt[g->group[k]] != 0, return -1);
+ isl_assert(H->ctx, g->cnt[g->group[i]] != 0, return -1);
+ if (g->group[i] < g->group[k]) {
+ g->cnt[g->group[i]] += g->cnt[g->group[k]];
+ g->cnt[g->group[k]] = 0;
+ g->group[g->group[k]] = g->group[i];
+ } else {
+ g->cnt[g->group[k]] += g->cnt[g->group[i]];
+ g->cnt[g->group[i]] = 0;
+ g->group[g->group[i]] = g->group[k];
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Update the group information based on the constraint matrix.
+ */
+static int update_groups(struct isl_factor_groups *g, __isl_keep isl_mat *H)
+{
+ int i, j;
+
+ for (i = 0; i < H->n_col && g->cnt[0] < H->n_col; ++i) {
+ if (g->pos[i] == H->n_row)
+ continue; /* A line direction */
+ if (g->rowgroup[g->pos[i]] == -1)
+ g->rowgroup[g->pos[i]] = i;
+ for (j = g->pos[i] + 1; j < H->n_row; ++j) {
+ if (isl_int_is_zero(H->row[j][i]))
+ continue;
+ if (g->rowgroup[j] != -1)
+ continue;
+ if (update_group_i_with_row_j(g, i, j, H) < 0)
+ return -1;
+ }
+ }
+ for (i = 1; i < H->n_col; ++i)
+ update_group(g, i);
+
+ return 0;
+}
+
+static void clear_groups(struct isl_factor_groups *g)
+{
+ if (!g)
+ return;
+ free(g->pos);
+ free(g->group);
+ free(g->cnt);
+ free(g->rowgroup);
+}
+
+/* Determine if the set variables of the basic set can be factorized and
+ * return the results in an isl_factorizer.
+ *
+ * The algorithm works by first computing the Hermite normal form
+ * and then grouping columns linked by one or more constraints together,
+ * where a constraints "links" two or more columns if the constraint
+ * has nonzero coefficients in the columns.
+ */
+__isl_give isl_factorizer *isl_basic_set_factorizer(
+ __isl_keep isl_basic_set *bset)
+{
+ int i, j, n, done;
+ isl_mat *H, *U, *Q;
+ unsigned nvar;
+ struct isl_factor_groups g = { 0 };
+ isl_factorizer *f;
+
+ if (!bset)
+ return NULL;
+
+ isl_assert(bset->ctx, isl_basic_set_dim(bset, isl_dim_div) == 0,
+ return NULL);
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ if (nvar <= 1)
+ return isl_factorizer_identity(bset);
+
+ H = isl_mat_alloc(bset->ctx, bset->n_eq + bset->n_ineq, nvar);
+ if (!H)
+ return NULL;
+ isl_mat_sub_copy(bset->ctx, H->row, bset->eq, bset->n_eq,
+ 0, 1 + isl_space_offset(bset->dim, isl_dim_set), nvar);
+ isl_mat_sub_copy(bset->ctx, H->row + bset->n_eq, bset->ineq, bset->n_ineq,
+ 0, 1 + isl_space_offset(bset->dim, isl_dim_set), nvar);
+ H = isl_mat_left_hermite(H, 0, &U, &Q);
+
+ if (init_groups(&g, H) < 0)
+ goto error;
+ if (update_groups(&g, H) < 0)
+ goto error;
+
+ if (g.cnt[0] == nvar) {
+ isl_mat_free(H);
+ isl_mat_free(U);
+ isl_mat_free(Q);
+ clear_groups(&g);
+
+ return isl_factorizer_identity(bset);
+ }
+
+ done = 0;
+ n = 0;
+ while (done != nvar) {
+ int group = g.group[done];
+ for (i = 1; i < g.cnt[group]; ++i) {
+ if (g.group[done + i] == group)
+ continue;
+ for (j = done + g.cnt[group]; j < nvar; ++j)
+ if (g.group[j] == group)
+ break;
+ if (j == nvar)
+ isl_die(bset->ctx, isl_error_internal,
+ "internal error", goto error);
+ g.group[j] = g.group[done + i];
+ Q = isl_mat_swap_rows(Q, done + i, j);
+ U = isl_mat_swap_cols(U, done + i, j);
+ }
+ done += g.cnt[group];
+ g.pos[n++] = g.cnt[group];
+ }
+
+ f = isl_factorizer_groups(bset, Q, U, n, g.pos);
+
+ isl_mat_free(H);
+ clear_groups(&g);
+
+ return f;
+error:
+ isl_mat_free(H);
+ isl_mat_free(U);
+ isl_mat_free(Q);
+ clear_groups(&g);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_factorization.h b/polly/lib/External/isl/isl_factorization.h
new file mode 100644
index 00000000000..4687b9cfd97
--- /dev/null
+++ b/polly/lib/External/isl/isl_factorization.h
@@ -0,0 +1,29 @@
+#include <isl/set.h>
+#include <isl_morph.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Data for factorizing a particular basic set.
+ * After applying "morph" to the basic set, there are "n_group"
+ * groups of consecutive set variables, each of length "len[i]",
+ * with 0 <= i < n_group.
+ * If no factorization is possible, then "n_group" is set to 0.
+ */
+struct isl_factorizer {
+ isl_morph *morph;
+ int n_group;
+ int *len;
+};
+typedef struct isl_factorizer isl_factorizer;
+
+__isl_give isl_factorizer *isl_basic_set_factorizer(
+ __isl_keep isl_basic_set *bset);
+
+void isl_factorizer_free(__isl_take isl_factorizer *f);
+void isl_factorizer_dump(__isl_take isl_factorizer *f);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/polly/lib/External/isl/isl_farkas.c b/polly/lib/External/isl/isl_farkas.c
new file mode 100644
index 00000000000..dddb49a76c2
--- /dev/null
+++ b/polly/lib/External/isl/isl_farkas.c
@@ -0,0 +1,403 @@
+/*
+ * 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_map_private.h>
+#include <isl/set.h>
+#include <isl_space_private.h>
+#include <isl_seq.h>
+
+/*
+ * Let C be a cone and define
+ *
+ * C' := { y | forall x in C : y x >= 0 }
+ *
+ * C' contains the coefficients of all linear constraints
+ * that are valid for C.
+ * Furthermore, C'' = C.
+ *
+ * If C is defined as { x | A x >= 0 }
+ * then any element in C' must be a non-negative combination
+ * of the rows of A, i.e., y = t A with t >= 0. That is,
+ *
+ * C' = { y | exists t >= 0 : y = t A }
+ *
+ * If any of the rows in A actually represents an equality, then
+ * also negative combinations of this row are allowed and so the
+ * non-negativity constraint on the corresponding element of t
+ * can be dropped.
+ *
+ * A polyhedron P = { x | b + A x >= 0 } can be represented
+ * in homogeneous coordinates by the cone
+ * C = { [z,x] | b z + A x >= and z >= 0 }
+ * The valid linear constraints on C correspond to the valid affine
+ * constraints on P.
+ * This is essentially Farkas' lemma.
+ *
+ * Since
+ * [ 1 0 ]
+ * [ w y ] = [t_0 t] [ b A ]
+ *
+ * we have
+ *
+ * C' = { w, y | exists t_0, t >= 0 : y = t A and w = t_0 + t b }
+ * or
+ *
+ * C' = { w, y | exists t >= 0 : y = t A and w - t b >= 0 }
+ *
+ * In practice, we introduce an extra variable (w), shifting all
+ * other variables to the right, and an extra inequality
+ * (w - t b >= 0) corresponding to the positivity constraint on
+ * the homogeneous coordinate.
+ *
+ * When going back from coefficients to solutions, we immediately
+ * plug in 1 for z, which corresponds to shifting all variables
+ * to the left, with the leftmost ending up in the constant position.
+ */
+
+/* Add the given prefix to all named isl_dim_set dimensions in "dim".
+ */
+static __isl_give isl_space *isl_space_prefix(__isl_take isl_space *dim,
+ const char *prefix)
+{
+ int i;
+ isl_ctx *ctx;
+ unsigned nvar;
+ size_t prefix_len = strlen(prefix);
+
+ if (!dim)
+ return NULL;
+
+ ctx = isl_space_get_ctx(dim);
+ nvar = isl_space_dim(dim, isl_dim_set);
+
+ for (i = 0; i < nvar; ++i) {
+ const char *name;
+ char *prefix_name;
+
+ name = isl_space_get_dim_name(dim, isl_dim_set, i);
+ if (!name)
+ continue;
+
+ prefix_name = isl_alloc_array(ctx, char,
+ prefix_len + strlen(name) + 1);
+ if (!prefix_name)
+ goto error;
+ memcpy(prefix_name, prefix, prefix_len);
+ strcpy(prefix_name + prefix_len, name);
+
+ dim = isl_space_set_dim_name(dim, isl_dim_set, i, prefix_name);
+ free(prefix_name);
+ }
+
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Given a dimension specification of the solutions space, construct
+ * a dimension specification for the space of coefficients.
+ *
+ * In particular transform
+ *
+ * [params] -> { S }
+ *
+ * to
+ *
+ * { coefficients[[cst, params] -> S] }
+ *
+ * and prefix each dimension name with "c_".
+ */
+static __isl_give isl_space *isl_space_coefficients(__isl_take isl_space *dim)
+{
+ isl_space *dim_param;
+ unsigned nvar;
+ unsigned nparam;
+
+ nvar = isl_space_dim(dim, isl_dim_set);
+ nparam = isl_space_dim(dim, isl_dim_param);
+ dim_param = isl_space_copy(dim);
+ dim_param = isl_space_drop_dims(dim_param, isl_dim_set, 0, nvar);
+ dim_param = isl_space_move_dims(dim_param, isl_dim_set, 0,
+ isl_dim_param, 0, nparam);
+ dim_param = isl_space_prefix(dim_param, "c_");
+ dim_param = isl_space_insert_dims(dim_param, isl_dim_set, 0, 1);
+ dim_param = isl_space_set_dim_name(dim_param, isl_dim_set, 0, "c_cst");
+ dim = isl_space_drop_dims(dim, isl_dim_param, 0, nparam);
+ dim = isl_space_prefix(dim, "c_");
+ dim = isl_space_join(isl_space_from_domain(dim_param),
+ isl_space_from_range(dim));
+ dim = isl_space_wrap(dim);
+ dim = isl_space_set_tuple_name(dim, isl_dim_set, "coefficients");
+
+ return dim;
+}
+
+/* Drop the given prefix from all named dimensions of type "type" in "dim".
+ */
+static __isl_give isl_space *isl_space_unprefix(__isl_take isl_space *dim,
+ enum isl_dim_type type, const char *prefix)
+{
+ int i;
+ unsigned n;
+ size_t prefix_len = strlen(prefix);
+
+ n = isl_space_dim(dim, type);
+
+ for (i = 0; i < n; ++i) {
+ const char *name;
+
+ name = isl_space_get_dim_name(dim, type, i);
+ if (!name)
+ continue;
+ if (strncmp(name, prefix, prefix_len))
+ continue;
+
+ dim = isl_space_set_dim_name(dim, type, i, name + prefix_len);
+ }
+
+ return dim;
+}
+
+/* Given a dimension specification of the space of coefficients, construct
+ * a dimension specification for the space of solutions.
+ *
+ * In particular transform
+ *
+ * { coefficients[[cst, params] -> S] }
+ *
+ * to
+ *
+ * [params] -> { S }
+ *
+ * and drop the "c_" prefix from the dimension names.
+ */
+static __isl_give isl_space *isl_space_solutions(__isl_take isl_space *dim)
+{
+ unsigned nparam;
+
+ dim = isl_space_unwrap(dim);
+ dim = isl_space_drop_dims(dim, isl_dim_in, 0, 1);
+ dim = isl_space_unprefix(dim, isl_dim_in, "c_");
+ dim = isl_space_unprefix(dim, isl_dim_out, "c_");
+ nparam = isl_space_dim(dim, isl_dim_in);
+ dim = isl_space_move_dims(dim, isl_dim_param, 0, isl_dim_in, 0, nparam);
+ dim = isl_space_range(dim);
+
+ return dim;
+}
+
+/* Return the rational universe basic set in the given space.
+ */
+static __isl_give isl_basic_set *rational_universe(__isl_take isl_space *space)
+{
+ isl_basic_set *bset;
+
+ bset = isl_basic_set_universe(space);
+ bset = isl_basic_set_set_rational(bset);
+
+ return bset;
+}
+
+/* Compute the dual of "bset" by applying Farkas' lemma.
+ * As explained above, we add an extra dimension to represent
+ * the coefficient of the constant term when going from solutions
+ * to coefficients (shift == 1) and we drop the extra dimension when going
+ * in the opposite direction (shift == -1). "dim" is the space in which
+ * the dual should be created.
+ *
+ * If "bset" is (obviously) empty, then the way this emptiness
+ * is represented by the constraints does not allow for the application
+ * of the standard farkas algorithm. We therefore handle this case
+ * specifically and return the universe basic set.
+ */
+static __isl_give isl_basic_set *farkas(__isl_take isl_space *space,
+ __isl_take isl_basic_set *bset, int shift)
+{
+ int i, j, k;
+ isl_basic_set *dual = NULL;
+ unsigned total;
+
+ if (isl_basic_set_plain_is_empty(bset)) {
+ isl_basic_set_free(bset);
+ return rational_universe(space);
+ }
+
+ total = isl_basic_set_total_dim(bset);
+
+ dual = isl_basic_set_alloc_space(space, bset->n_eq + bset->n_ineq,
+ total, bset->n_ineq + (shift > 0));
+ dual = isl_basic_set_set_rational(dual);
+
+ for (i = 0; i < bset->n_eq + bset->n_ineq; ++i) {
+ k = isl_basic_set_alloc_div(dual);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(dual->div[k][0], 0);
+ }
+
+ for (i = 0; i < total; ++i) {
+ k = isl_basic_set_alloc_equality(dual);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(dual->eq[k], 1 + shift + total);
+ isl_int_set_si(dual->eq[k][1 + shift + i], -1);
+ for (j = 0; j < bset->n_eq; ++j)
+ isl_int_set(dual->eq[k][1 + shift + total + j],
+ bset->eq[j][1 + i]);
+ for (j = 0; j < bset->n_ineq; ++j)
+ isl_int_set(dual->eq[k][1 + shift + total + bset->n_eq + j],
+ bset->ineq[j][1 + i]);
+ }
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(dual);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(dual->ineq[k],
+ 1 + shift + total + bset->n_eq + bset->n_ineq);
+ isl_int_set_si(dual->ineq[k][1 + shift + total + bset->n_eq + i], 1);
+ }
+
+ if (shift > 0) {
+ k = isl_basic_set_alloc_inequality(dual);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(dual->ineq[k], 2 + total);
+ isl_int_set_si(dual->ineq[k][1], 1);
+ for (j = 0; j < bset->n_eq; ++j)
+ isl_int_neg(dual->ineq[k][2 + total + j],
+ bset->eq[j][0]);
+ for (j = 0; j < bset->n_ineq; ++j)
+ isl_int_neg(dual->ineq[k][2 + total + bset->n_eq + j],
+ bset->ineq[j][0]);
+ }
+
+ dual = isl_basic_set_remove_divs(dual);
+ isl_basic_set_simplify(dual);
+ isl_basic_set_finalize(dual);
+
+ isl_basic_set_free(bset);
+ return dual;
+error:
+ isl_basic_set_free(bset);
+ isl_basic_set_free(dual);
+ return NULL;
+}
+
+/* Construct a basic set containing the tuples of coefficients of all
+ * valid affine constraints on the given basic set.
+ */
+__isl_give isl_basic_set *isl_basic_set_coefficients(
+ __isl_take isl_basic_set *bset)
+{
+ isl_space *dim;
+
+ if (!bset)
+ return NULL;
+ if (bset->n_div)
+ isl_die(bset->ctx, isl_error_invalid,
+ "input set not allowed to have local variables",
+ goto error);
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_coefficients(dim);
+
+ return farkas(dim, bset, 1);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Construct a basic set containing the elements that satisfy all
+ * affine constraints whose coefficient tuples are
+ * contained in the given basic set.
+ */
+__isl_give isl_basic_set *isl_basic_set_solutions(
+ __isl_take isl_basic_set *bset)
+{
+ isl_space *dim;
+
+ if (!bset)
+ return NULL;
+ if (bset->n_div)
+ isl_die(bset->ctx, isl_error_invalid,
+ "input set not allowed to have local variables",
+ goto error);
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_solutions(dim);
+
+ return farkas(dim, bset, -1);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Construct a basic set containing the tuples of coefficients of all
+ * valid affine constraints on the given set.
+ */
+__isl_give isl_basic_set *isl_set_coefficients(__isl_take isl_set *set)
+{
+ int i;
+ isl_basic_set *coeff;
+
+ if (!set)
+ return NULL;
+ if (set->n == 0) {
+ isl_space *space = isl_set_get_space(set);
+ space = isl_space_coefficients(space);
+ isl_set_free(set);
+ return rational_universe(space);
+ }
+
+ coeff = isl_basic_set_coefficients(isl_basic_set_copy(set->p[0]));
+
+ for (i = 1; i < set->n; ++i) {
+ isl_basic_set *bset, *coeff_i;
+ bset = isl_basic_set_copy(set->p[i]);
+ coeff_i = isl_basic_set_coefficients(bset);
+ coeff = isl_basic_set_intersect(coeff, coeff_i);
+ }
+
+ isl_set_free(set);
+ return coeff;
+}
+
+/* Construct a basic set containing the elements that satisfy all
+ * affine constraints whose coefficient tuples are
+ * contained in the given set.
+ */
+__isl_give isl_basic_set *isl_set_solutions(__isl_take isl_set *set)
+{
+ int i;
+ isl_basic_set *sol;
+
+ if (!set)
+ return NULL;
+ if (set->n == 0) {
+ isl_space *space = isl_set_get_space(set);
+ space = isl_space_solutions(space);
+ isl_set_free(set);
+ return rational_universe(space);
+ }
+
+ sol = isl_basic_set_solutions(isl_basic_set_copy(set->p[0]));
+
+ for (i = 1; i < set->n; ++i) {
+ isl_basic_set *bset, *sol_i;
+ bset = isl_basic_set_copy(set->p[i]);
+ sol_i = isl_basic_set_solutions(bset);
+ sol = isl_basic_set_intersect(sol, sol_i);
+ }
+
+ isl_set_free(set);
+ return sol;
+}
diff --git a/polly/lib/External/isl/isl_flow.c b/polly/lib/External/isl/isl_flow.c
new file mode 100644
index 00000000000..36ba0ed51f6
--- /dev/null
+++ b/polly/lib/External/isl/isl_flow.c
@@ -0,0 +1,1496 @@
+/*
+ * Copyright 2005-2007 Universiteit Leiden
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012 Universiteit Leiden
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
+ * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
+ * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
+ * B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/flow.h>
+#include <isl_sort.h>
+
+enum isl_restriction_type {
+ isl_restriction_type_empty,
+ isl_restriction_type_none,
+ isl_restriction_type_input,
+ isl_restriction_type_output
+};
+
+struct isl_restriction {
+ enum isl_restriction_type type;
+
+ isl_set *source;
+ isl_set *sink;
+};
+
+/* Create a restriction of the given type.
+ */
+static __isl_give isl_restriction *isl_restriction_alloc(
+ __isl_take isl_map *source_map, enum isl_restriction_type type)
+{
+ isl_ctx *ctx;
+ isl_restriction *restr;
+
+ if (!source_map)
+ return NULL;
+
+ ctx = isl_map_get_ctx(source_map);
+ restr = isl_calloc_type(ctx, struct isl_restriction);
+ if (!restr)
+ goto error;
+
+ restr->type = type;
+
+ isl_map_free(source_map);
+ return restr;
+error:
+ isl_map_free(source_map);
+ return NULL;
+}
+
+/* Create a restriction that doesn't restrict anything.
+ */
+__isl_give isl_restriction *isl_restriction_none(__isl_take isl_map *source_map)
+{
+ return isl_restriction_alloc(source_map, isl_restriction_type_none);
+}
+
+/* Create a restriction that removes everything.
+ */
+__isl_give isl_restriction *isl_restriction_empty(
+ __isl_take isl_map *source_map)
+{
+ return isl_restriction_alloc(source_map, isl_restriction_type_empty);
+}
+
+/* Create a restriction on the input of the maximization problem
+ * based on the given source and sink restrictions.
+ */
+__isl_give isl_restriction *isl_restriction_input(
+ __isl_take isl_set *source_restr, __isl_take isl_set *sink_restr)
+{
+ isl_ctx *ctx;
+ isl_restriction *restr;
+
+ if (!source_restr || !sink_restr)
+ goto error;
+
+ ctx = isl_set_get_ctx(source_restr);
+ restr = isl_calloc_type(ctx, struct isl_restriction);
+ if (!restr)
+ goto error;
+
+ restr->type = isl_restriction_type_input;
+ restr->source = source_restr;
+ restr->sink = sink_restr;
+
+ return restr;
+error:
+ isl_set_free(source_restr);
+ isl_set_free(sink_restr);
+ return NULL;
+}
+
+/* Create a restriction on the output of the maximization problem
+ * based on the given source restriction.
+ */
+__isl_give isl_restriction *isl_restriction_output(
+ __isl_take isl_set *source_restr)
+{
+ isl_ctx *ctx;
+ isl_restriction *restr;
+
+ if (!source_restr)
+ return NULL;
+
+ ctx = isl_set_get_ctx(source_restr);
+ restr = isl_calloc_type(ctx, struct isl_restriction);
+ if (!restr)
+ goto error;
+
+ restr->type = isl_restriction_type_output;
+ restr->source = source_restr;
+
+ return restr;
+error:
+ isl_set_free(source_restr);
+ return NULL;
+}
+
+__isl_null isl_restriction *isl_restriction_free(
+ __isl_take isl_restriction *restr)
+{
+ if (!restr)
+ return NULL;
+
+ isl_set_free(restr->source);
+ isl_set_free(restr->sink);
+ free(restr);
+ return NULL;
+}
+
+isl_ctx *isl_restriction_get_ctx(__isl_keep isl_restriction *restr)
+{
+ return restr ? isl_set_get_ctx(restr->source) : NULL;
+}
+
+/* A private structure to keep track of a mapping together with
+ * a user-specified identifier and a boolean indicating whether
+ * the map represents a must or may access/dependence.
+ */
+struct isl_labeled_map {
+ struct isl_map *map;
+ void *data;
+ int must;
+};
+
+/* A structure containing the input for dependence analysis:
+ * - a sink
+ * - n_must + n_may (<= max_source) sources
+ * - a function for determining the relative order of sources and sink
+ * The must sources are placed before the may sources.
+ *
+ * domain_map is an auxiliary map that maps the sink access relation
+ * to the domain of this access relation.
+ *
+ * restrict_fn is a callback that (if not NULL) will be called
+ * right before any lexicographical maximization.
+ */
+struct isl_access_info {
+ isl_map *domain_map;
+ struct isl_labeled_map sink;
+ isl_access_level_before level_before;
+
+ isl_access_restrict restrict_fn;
+ void *restrict_user;
+
+ int max_source;
+ int n_must;
+ int n_may;
+ struct isl_labeled_map source[1];
+};
+
+/* A structure containing the output of dependence analysis:
+ * - n_source dependences
+ * - a wrapped subset of the sink for which definitely no source could be found
+ * - a wrapped subset of the sink for which possibly no source could be found
+ */
+struct isl_flow {
+ isl_set *must_no_source;
+ isl_set *may_no_source;
+ int n_source;
+ struct isl_labeled_map *dep;
+};
+
+/* Construct an isl_access_info structure and fill it up with
+ * the given data. The number of sources is set to 0.
+ */
+__isl_give isl_access_info *isl_access_info_alloc(__isl_take isl_map *sink,
+ void *sink_user, isl_access_level_before fn, int max_source)
+{
+ isl_ctx *ctx;
+ struct isl_access_info *acc;
+
+ if (!sink)
+ return NULL;
+
+ ctx = isl_map_get_ctx(sink);
+ isl_assert(ctx, max_source >= 0, goto error);
+
+ acc = isl_calloc(ctx, struct isl_access_info,
+ sizeof(struct isl_access_info) +
+ (max_source - 1) * sizeof(struct isl_labeled_map));
+ if (!acc)
+ goto error;
+
+ acc->sink.map = sink;
+ acc->sink.data = sink_user;
+ acc->level_before = fn;
+ acc->max_source = max_source;
+ acc->n_must = 0;
+ acc->n_may = 0;
+
+ return acc;
+error:
+ isl_map_free(sink);
+ return NULL;
+}
+
+/* Free the given isl_access_info structure.
+ */
+__isl_null isl_access_info *isl_access_info_free(
+ __isl_take isl_access_info *acc)
+{
+ int i;
+
+ if (!acc)
+ return NULL;
+ isl_map_free(acc->domain_map);
+ isl_map_free(acc->sink.map);
+ for (i = 0; i < acc->n_must + acc->n_may; ++i)
+ isl_map_free(acc->source[i].map);
+ free(acc);
+ return NULL;
+}
+
+isl_ctx *isl_access_info_get_ctx(__isl_keep isl_access_info *acc)
+{
+ return acc ? isl_map_get_ctx(acc->sink.map) : NULL;
+}
+
+__isl_give isl_access_info *isl_access_info_set_restrict(
+ __isl_take isl_access_info *acc, isl_access_restrict fn, void *user)
+{
+ if (!acc)
+ return NULL;
+ acc->restrict_fn = fn;
+ acc->restrict_user = user;
+ return acc;
+}
+
+/* Add another source to an isl_access_info structure, making
+ * sure the "must" sources are placed before the "may" sources.
+ * This function may be called at most max_source times on a
+ * given isl_access_info structure, with max_source as specified
+ * in the call to isl_access_info_alloc that constructed the structure.
+ */
+__isl_give isl_access_info *isl_access_info_add_source(
+ __isl_take isl_access_info *acc, __isl_take isl_map *source,
+ int must, void *source_user)
+{
+ isl_ctx *ctx;
+
+ if (!acc)
+ goto error;
+ ctx = isl_map_get_ctx(acc->sink.map);
+ isl_assert(ctx, acc->n_must + acc->n_may < acc->max_source, goto error);
+
+ if (must) {
+ if (acc->n_may)
+ acc->source[acc->n_must + acc->n_may] =
+ acc->source[acc->n_must];
+ acc->source[acc->n_must].map = source;
+ acc->source[acc->n_must].data = source_user;
+ acc->source[acc->n_must].must = 1;
+ acc->n_must++;
+ } else {
+ acc->source[acc->n_must + acc->n_may].map = source;
+ acc->source[acc->n_must + acc->n_may].data = source_user;
+ acc->source[acc->n_must + acc->n_may].must = 0;
+ acc->n_may++;
+ }
+
+ return acc;
+error:
+ isl_map_free(source);
+ isl_access_info_free(acc);
+ return NULL;
+}
+
+/* Return -n, 0 or n (with n a positive value), depending on whether
+ * the source access identified by p1 should be sorted before, together
+ * or after that identified by p2.
+ *
+ * If p1 appears before p2, then it should be sorted first.
+ * For more generic initial schedules, it is possible that neither
+ * p1 nor p2 appears before the other, or at least not in any obvious way.
+ * We therefore also check if p2 appears before p1, in which case p2
+ * should be sorted first.
+ * If not, we try to order the two statements based on the description
+ * of the iteration domains. This results in an arbitrary, but fairly
+ * stable ordering.
+ */
+static int access_sort_cmp(const void *p1, const void *p2, void *user)
+{
+ isl_access_info *acc = user;
+ const struct isl_labeled_map *i1, *i2;
+ int level1, level2;
+ uint32_t h1, h2;
+ i1 = (const struct isl_labeled_map *) p1;
+ i2 = (const struct isl_labeled_map *) p2;
+
+ level1 = acc->level_before(i1->data, i2->data);
+ if (level1 % 2)
+ return -1;
+
+ level2 = acc->level_before(i2->data, i1->data);
+ if (level2 % 2)
+ return 1;
+
+ h1 = isl_map_get_hash(i1->map);
+ h2 = isl_map_get_hash(i2->map);
+ return h1 > h2 ? 1 : h1 < h2 ? -1 : 0;
+}
+
+/* Sort the must source accesses in their textual order.
+ */
+static __isl_give isl_access_info *isl_access_info_sort_sources(
+ __isl_take isl_access_info *acc)
+{
+ if (!acc)
+ return NULL;
+ if (acc->n_must <= 1)
+ return acc;
+
+ if (isl_sort(acc->source, acc->n_must, sizeof(struct isl_labeled_map),
+ access_sort_cmp, acc) < 0)
+ return isl_access_info_free(acc);
+
+ return acc;
+}
+
+/* Align the parameters of the two spaces if needed and then call
+ * isl_space_join.
+ */
+static __isl_give isl_space *space_align_and_join(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ if (isl_space_match(left, isl_dim_param, right, isl_dim_param))
+ return isl_space_join(left, right);
+
+ left = isl_space_align_params(left, isl_space_copy(right));
+ right = isl_space_align_params(right, isl_space_copy(left));
+ return isl_space_join(left, right);
+}
+
+/* Initialize an empty isl_flow structure corresponding to a given
+ * isl_access_info structure.
+ * For each must access, two dependences are created (initialized
+ * to the empty relation), one for the resulting must dependences
+ * and one for the resulting may dependences. May accesses can
+ * only lead to may dependences, so only one dependence is created
+ * for each of them.
+ * This function is private as isl_flow structures are only supposed
+ * to be created by isl_access_info_compute_flow.
+ */
+static __isl_give isl_flow *isl_flow_alloc(__isl_keep isl_access_info *acc)
+{
+ int i, n;
+ struct isl_ctx *ctx;
+ struct isl_flow *dep;
+
+ if (!acc)
+ return NULL;
+
+ ctx = isl_map_get_ctx(acc->sink.map);
+ dep = isl_calloc_type(ctx, struct isl_flow);
+ if (!dep)
+ return NULL;
+
+ n = 2 * acc->n_must + acc->n_may;
+ dep->dep = isl_calloc_array(ctx, struct isl_labeled_map, n);
+ if (n && !dep->dep)
+ goto error;
+
+ dep->n_source = n;
+ for (i = 0; i < acc->n_must; ++i) {
+ isl_space *dim;
+ dim = space_align_and_join(
+ isl_map_get_space(acc->source[i].map),
+ isl_space_reverse(isl_map_get_space(acc->sink.map)));
+ dep->dep[2 * i].map = isl_map_empty(dim);
+ dep->dep[2 * i + 1].map = isl_map_copy(dep->dep[2 * i].map);
+ dep->dep[2 * i].data = acc->source[i].data;
+ dep->dep[2 * i + 1].data = acc->source[i].data;
+ dep->dep[2 * i].must = 1;
+ dep->dep[2 * i + 1].must = 0;
+ if (!dep->dep[2 * i].map || !dep->dep[2 * i + 1].map)
+ goto error;
+ }
+ for (i = acc->n_must; i < acc->n_must + acc->n_may; ++i) {
+ isl_space *dim;
+ dim = space_align_and_join(
+ isl_map_get_space(acc->source[i].map),
+ isl_space_reverse(isl_map_get_space(acc->sink.map)));
+ dep->dep[acc->n_must + i].map = isl_map_empty(dim);
+ dep->dep[acc->n_must + i].data = acc->source[i].data;
+ dep->dep[acc->n_must + i].must = 0;
+ if (!dep->dep[acc->n_must + i].map)
+ goto error;
+ }
+
+ return dep;
+error:
+ isl_flow_free(dep);
+ return NULL;
+}
+
+/* Iterate over all sources and for each resulting flow dependence
+ * that is not empty, call the user specfied function.
+ * The second argument in this function call identifies the source,
+ * while the third argument correspond to the final argument of
+ * the isl_flow_foreach call.
+ */
+int isl_flow_foreach(__isl_keep isl_flow *deps,
+ int (*fn)(__isl_take isl_map *dep, int must, void *dep_user, void *user),
+ void *user)
+{
+ int i;
+
+ if (!deps)
+ return -1;
+
+ for (i = 0; i < deps->n_source; ++i) {
+ if (isl_map_plain_is_empty(deps->dep[i].map))
+ continue;
+ if (fn(isl_map_copy(deps->dep[i].map), deps->dep[i].must,
+ deps->dep[i].data, user) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Return a copy of the subset of the sink for which no source could be found.
+ */
+__isl_give isl_map *isl_flow_get_no_source(__isl_keep isl_flow *deps, int must)
+{
+ if (!deps)
+ return NULL;
+
+ if (must)
+ return isl_set_unwrap(isl_set_copy(deps->must_no_source));
+ else
+ return isl_set_unwrap(isl_set_copy(deps->may_no_source));
+}
+
+void isl_flow_free(__isl_take isl_flow *deps)
+{
+ int i;
+
+ if (!deps)
+ return;
+ isl_set_free(deps->must_no_source);
+ isl_set_free(deps->may_no_source);
+ if (deps->dep) {
+ for (i = 0; i < deps->n_source; ++i)
+ isl_map_free(deps->dep[i].map);
+ free(deps->dep);
+ }
+ free(deps);
+}
+
+isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps)
+{
+ return deps ? isl_set_get_ctx(deps->must_no_source) : NULL;
+}
+
+/* Return a map that enforces that the domain iteration occurs after
+ * the range iteration at the given level.
+ * If level is odd, then the domain iteration should occur after
+ * the target iteration in their shared level/2 outermost loops.
+ * In this case we simply need to enforce that these outermost
+ * loop iterations are the same.
+ * If level is even, then the loop iterator of the domain should
+ * be greater than the loop iterator of the range at the last
+ * of the level/2 shared loops, i.e., loop level/2 - 1.
+ */
+static __isl_give isl_map *after_at_level(__isl_take isl_space *dim, int level)
+{
+ struct isl_basic_map *bmap;
+
+ if (level % 2)
+ bmap = isl_basic_map_equal(dim, level/2);
+ else
+ bmap = isl_basic_map_more_at(dim, level/2 - 1);
+
+ return isl_map_from_basic_map(bmap);
+}
+
+/* Compute the partial lexicographic maximum of "dep" on domain "sink",
+ * but first check if the user has set acc->restrict_fn and if so
+ * update either the input or the output of the maximization problem
+ * with respect to the resulting restriction.
+ *
+ * Since the user expects a mapping from sink iterations to source iterations,
+ * whereas the domain of "dep" is a wrapped map, mapping sink iterations
+ * to accessed array elements, we first need to project out the accessed
+ * sink array elements by applying acc->domain_map.
+ * Similarly, the sink restriction specified by the user needs to be
+ * converted back to the wrapped map.
+ */
+static __isl_give isl_map *restricted_partial_lexmax(
+ __isl_keep isl_access_info *acc, __isl_take isl_map *dep,
+ int source, __isl_take isl_set *sink, __isl_give isl_set **empty)
+{
+ isl_map *source_map;
+ isl_restriction *restr;
+ isl_set *sink_domain;
+ isl_set *sink_restr;
+ isl_map *res;
+
+ if (!acc->restrict_fn)
+ return isl_map_partial_lexmax(dep, sink, empty);
+
+ source_map = isl_map_copy(dep);
+ source_map = isl_map_apply_domain(source_map,
+ isl_map_copy(acc->domain_map));
+ sink_domain = isl_set_copy(sink);
+ sink_domain = isl_set_apply(sink_domain, isl_map_copy(acc->domain_map));
+ restr = acc->restrict_fn(source_map, sink_domain,
+ acc->source[source].data, acc->restrict_user);
+ isl_set_free(sink_domain);
+ isl_map_free(source_map);
+
+ if (!restr)
+ goto error;
+ if (restr->type == isl_restriction_type_input) {
+ dep = isl_map_intersect_range(dep, isl_set_copy(restr->source));
+ sink_restr = isl_set_copy(restr->sink);
+ sink_restr = isl_set_apply(sink_restr,
+ isl_map_reverse(isl_map_copy(acc->domain_map)));
+ sink = isl_set_intersect(sink, sink_restr);
+ } else if (restr->type == isl_restriction_type_empty) {
+ isl_space *space = isl_map_get_space(dep);
+ isl_map_free(dep);
+ dep = isl_map_empty(space);
+ }
+
+ res = isl_map_partial_lexmax(dep, sink, empty);
+
+ if (restr->type == isl_restriction_type_output)
+ res = isl_map_intersect_range(res, isl_set_copy(restr->source));
+
+ isl_restriction_free(restr);
+ return res;
+error:
+ isl_map_free(dep);
+ isl_set_free(sink);
+ *empty = NULL;
+ return NULL;
+}
+
+/* Compute the last iteration of must source j that precedes the sink
+ * at the given level for sink iterations in set_C.
+ * The subset of set_C for which no such iteration can be found is returned
+ * in *empty.
+ */
+static struct isl_map *last_source(struct isl_access_info *acc,
+ struct isl_set *set_C,
+ int j, int level, struct isl_set **empty)
+{
+ struct isl_map *read_map;
+ struct isl_map *write_map;
+ struct isl_map *dep_map;
+ struct isl_map *after;
+ struct isl_map *result;
+
+ read_map = isl_map_copy(acc->sink.map);
+ write_map = isl_map_copy(acc->source[j].map);
+ write_map = isl_map_reverse(write_map);
+ dep_map = isl_map_apply_range(read_map, write_map);
+ after = after_at_level(isl_map_get_space(dep_map), level);
+ dep_map = isl_map_intersect(dep_map, after);
+ result = restricted_partial_lexmax(acc, dep_map, j, set_C, empty);
+ result = isl_map_reverse(result);
+
+ return result;
+}
+
+/* For a given mapping between iterations of must source j and iterations
+ * of the sink, compute the last iteration of must source k preceding
+ * the sink at level before_level for any of the sink iterations,
+ * but following the corresponding iteration of must source j at level
+ * after_level.
+ */
+static struct isl_map *last_later_source(struct isl_access_info *acc,
+ struct isl_map *old_map,
+ int j, int before_level,
+ int k, int after_level,
+ struct isl_set **empty)
+{
+ isl_space *dim;
+ struct isl_set *set_C;
+ struct isl_map *read_map;
+ struct isl_map *write_map;
+ struct isl_map *dep_map;
+ struct isl_map *after_write;
+ struct isl_map *before_read;
+ struct isl_map *result;
+
+ set_C = isl_map_range(isl_map_copy(old_map));
+ read_map = isl_map_copy(acc->sink.map);
+ write_map = isl_map_copy(acc->source[k].map);
+
+ write_map = isl_map_reverse(write_map);
+ dep_map = isl_map_apply_range(read_map, write_map);
+ dim = space_align_and_join(isl_map_get_space(acc->source[k].map),
+ isl_space_reverse(isl_map_get_space(acc->source[j].map)));
+ after_write = after_at_level(dim, after_level);
+ after_write = isl_map_apply_range(after_write, old_map);
+ after_write = isl_map_reverse(after_write);
+ dep_map = isl_map_intersect(dep_map, after_write);
+ before_read = after_at_level(isl_map_get_space(dep_map), before_level);
+ dep_map = isl_map_intersect(dep_map, before_read);
+ result = restricted_partial_lexmax(acc, dep_map, k, set_C, empty);
+ result = isl_map_reverse(result);
+
+ return result;
+}
+
+/* Given a shared_level between two accesses, return 1 if the
+ * the first can precede the second at the requested target_level.
+ * If the target level is odd, i.e., refers to a statement level
+ * dimension, then first needs to precede second at the requested
+ * level, i.e., shared_level must be equal to target_level.
+ * If the target level is odd, then the two loops should share
+ * at least the requested number of outer loops.
+ */
+static int can_precede_at_level(int shared_level, int target_level)
+{
+ if (shared_level < target_level)
+ return 0;
+ if ((target_level % 2) && shared_level > target_level)
+ return 0;
+ return 1;
+}
+
+/* Given a possible flow dependence temp_rel[j] between source j and the sink
+ * at level sink_level, remove those elements for which
+ * there is an iteration of another source k < j that is closer to the sink.
+ * The flow dependences temp_rel[k] are updated with the improved sources.
+ * Any improved source needs to precede the sink at the same level
+ * and needs to follow source j at the same or a deeper level.
+ * The lower this level, the later the execution date of source k.
+ * We therefore consider lower levels first.
+ *
+ * If temp_rel[j] is empty, then there can be no improvement and
+ * we return immediately.
+ */
+static int intermediate_sources(__isl_keep isl_access_info *acc,
+ struct isl_map **temp_rel, int j, int sink_level)
+{
+ int k, level;
+ int depth = 2 * isl_map_dim(acc->source[j].map, isl_dim_in) + 1;
+
+ if (isl_map_plain_is_empty(temp_rel[j]))
+ return 0;
+
+ for (k = j - 1; k >= 0; --k) {
+ int plevel, plevel2;
+ plevel = acc->level_before(acc->source[k].data, acc->sink.data);
+ if (!can_precede_at_level(plevel, sink_level))
+ continue;
+
+ plevel2 = acc->level_before(acc->source[j].data,
+ acc->source[k].data);
+
+ for (level = sink_level; level <= depth; ++level) {
+ struct isl_map *T;
+ struct isl_set *trest;
+ struct isl_map *copy;
+
+ if (!can_precede_at_level(plevel2, level))
+ continue;
+
+ copy = isl_map_copy(temp_rel[j]);
+ T = last_later_source(acc, copy, j, sink_level, k,
+ level, &trest);
+ if (isl_map_plain_is_empty(T)) {
+ isl_set_free(trest);
+ isl_map_free(T);
+ continue;
+ }
+ temp_rel[j] = isl_map_intersect_range(temp_rel[j], trest);
+ temp_rel[k] = isl_map_union_disjoint(temp_rel[k], T);
+ }
+ }
+
+ return 0;
+}
+
+/* Compute all iterations of may source j that precedes the sink at the given
+ * level for sink iterations in set_C.
+ */
+static __isl_give isl_map *all_sources(__isl_keep isl_access_info *acc,
+ __isl_take isl_set *set_C, int j, int level)
+{
+ isl_map *read_map;
+ isl_map *write_map;
+ isl_map *dep_map;
+ isl_map *after;
+
+ read_map = isl_map_copy(acc->sink.map);
+ read_map = isl_map_intersect_domain(read_map, set_C);
+ write_map = isl_map_copy(acc->source[acc->n_must + j].map);
+ write_map = isl_map_reverse(write_map);
+ dep_map = isl_map_apply_range(read_map, write_map);
+ after = after_at_level(isl_map_get_space(dep_map), level);
+ dep_map = isl_map_intersect(dep_map, after);
+
+ return isl_map_reverse(dep_map);
+}
+
+/* For a given mapping between iterations of must source k and iterations
+ * of the sink, compute the all iteration of may source j preceding
+ * the sink at level before_level for any of the sink iterations,
+ * but following the corresponding iteration of must source k at level
+ * after_level.
+ */
+static __isl_give isl_map *all_later_sources(__isl_keep isl_access_info *acc,
+ __isl_take isl_map *old_map,
+ int j, int before_level, int k, int after_level)
+{
+ isl_space *dim;
+ isl_set *set_C;
+ isl_map *read_map;
+ isl_map *write_map;
+ isl_map *dep_map;
+ isl_map *after_write;
+ isl_map *before_read;
+
+ set_C = isl_map_range(isl_map_copy(old_map));
+ read_map = isl_map_copy(acc->sink.map);
+ read_map = isl_map_intersect_domain(read_map, set_C);
+ write_map = isl_map_copy(acc->source[acc->n_must + j].map);
+
+ write_map = isl_map_reverse(write_map);
+ dep_map = isl_map_apply_range(read_map, write_map);
+ dim = isl_space_join(isl_map_get_space(acc->source[acc->n_must + j].map),
+ isl_space_reverse(isl_map_get_space(acc->source[k].map)));
+ after_write = after_at_level(dim, after_level);
+ after_write = isl_map_apply_range(after_write, old_map);
+ after_write = isl_map_reverse(after_write);
+ dep_map = isl_map_intersect(dep_map, after_write);
+ before_read = after_at_level(isl_map_get_space(dep_map), before_level);
+ dep_map = isl_map_intersect(dep_map, before_read);
+ return isl_map_reverse(dep_map);
+}
+
+/* Given the must and may dependence relations for the must accesses
+ * for level sink_level, check if there are any accesses of may access j
+ * that occur in between and return their union.
+ * If some of these accesses are intermediate with respect to
+ * (previously thought to be) must dependences, then these
+ * must dependences are turned into may dependences.
+ */
+static __isl_give isl_map *all_intermediate_sources(
+ __isl_keep isl_access_info *acc, __isl_take isl_map *map,
+ struct isl_map **must_rel, struct isl_map **may_rel,
+ int j, int sink_level)
+{
+ int k, level;
+ int depth = 2 * isl_map_dim(acc->source[acc->n_must + j].map,
+ isl_dim_in) + 1;
+
+ for (k = 0; k < acc->n_must; ++k) {
+ int plevel;
+
+ if (isl_map_plain_is_empty(may_rel[k]) &&
+ isl_map_plain_is_empty(must_rel[k]))
+ continue;
+
+ plevel = acc->level_before(acc->source[k].data,
+ acc->source[acc->n_must + j].data);
+
+ for (level = sink_level; level <= depth; ++level) {
+ isl_map *T;
+ isl_map *copy;
+ isl_set *ran;
+
+ if (!can_precede_at_level(plevel, level))
+ continue;
+
+ copy = isl_map_copy(may_rel[k]);
+ T = all_later_sources(acc, copy, j, sink_level, k, level);
+ map = isl_map_union(map, T);
+
+ copy = isl_map_copy(must_rel[k]);
+ T = all_later_sources(acc, copy, j, sink_level, k, level);
+ ran = isl_map_range(isl_map_copy(T));
+ map = isl_map_union(map, T);
+ may_rel[k] = isl_map_union_disjoint(may_rel[k],
+ isl_map_intersect_range(isl_map_copy(must_rel[k]),
+ isl_set_copy(ran)));
+ T = isl_map_from_domain_and_range(
+ isl_set_universe(
+ isl_space_domain(isl_map_get_space(must_rel[k]))),
+ ran);
+ must_rel[k] = isl_map_subtract(must_rel[k], T);
+ }
+ }
+
+ return map;
+}
+
+/* Compute dependences for the case where all accesses are "may"
+ * accesses, which boils down to computing memory based dependences.
+ * The generic algorithm would also work in this case, but it would
+ * be overkill to use it.
+ */
+static __isl_give isl_flow *compute_mem_based_dependences(
+ __isl_keep isl_access_info *acc)
+{
+ int i;
+ isl_set *mustdo;
+ isl_set *maydo;
+ isl_flow *res;
+
+ res = isl_flow_alloc(acc);
+ if (!res)
+ return NULL;
+
+ mustdo = isl_map_domain(isl_map_copy(acc->sink.map));
+ maydo = isl_set_copy(mustdo);
+
+ for (i = 0; i < acc->n_may; ++i) {
+ int plevel;
+ int is_before;
+ isl_space *dim;
+ isl_map *before;
+ isl_map *dep;
+
+ plevel = acc->level_before(acc->source[i].data, acc->sink.data);
+ is_before = plevel & 1;
+ plevel >>= 1;
+
+ dim = isl_map_get_space(res->dep[i].map);
+ if (is_before)
+ before = isl_map_lex_le_first(dim, plevel);
+ else
+ before = isl_map_lex_lt_first(dim, plevel);
+ dep = isl_map_apply_range(isl_map_copy(acc->source[i].map),
+ isl_map_reverse(isl_map_copy(acc->sink.map)));
+ dep = isl_map_intersect(dep, before);
+ mustdo = isl_set_subtract(mustdo,
+ isl_map_range(isl_map_copy(dep)));
+ res->dep[i].map = isl_map_union(res->dep[i].map, dep);
+ }
+
+ res->may_no_source = isl_set_subtract(maydo, isl_set_copy(mustdo));
+ res->must_no_source = mustdo;
+
+ return res;
+}
+
+/* Compute dependences for the case where there is at least one
+ * "must" access.
+ *
+ * The core algorithm considers all levels in which a source may precede
+ * the sink, where a level may either be a statement level or a loop level.
+ * The outermost statement level is 1, the first loop level is 2, etc...
+ * The algorithm basically does the following:
+ * for all levels l of the read access from innermost to outermost
+ * for all sources w that may precede the sink access at that level
+ * compute the last iteration of the source that precedes the sink access
+ * at that level
+ * add result to possible last accesses at level l of source w
+ * for all sources w2 that we haven't considered yet at this level that may
+ * also precede the sink access
+ * for all levels l2 of w from l to innermost
+ * for all possible last accesses dep of w at l
+ * compute last iteration of w2 between the source and sink
+ * of dep
+ * add result to possible last accesses at level l of write w2
+ * and replace possible last accesses dep by the remainder
+ *
+ *
+ * The above algorithm is applied to the must access. During the course
+ * of the algorithm, we keep track of sink iterations that still
+ * need to be considered. These iterations are split into those that
+ * haven't been matched to any source access (mustdo) and those that have only
+ * been matched to may accesses (maydo).
+ * At the end of each level, we also consider the may accesses.
+ * In particular, we consider may accesses that precede the remaining
+ * sink iterations, moving elements from mustdo to maydo when appropriate,
+ * and may accesses that occur between a must source and a sink of any
+ * dependences found at the current level, turning must dependences into
+ * may dependences when appropriate.
+ *
+ */
+static __isl_give isl_flow *compute_val_based_dependences(
+ __isl_keep isl_access_info *acc)
+{
+ isl_ctx *ctx;
+ isl_flow *res;
+ isl_set *mustdo = NULL;
+ isl_set *maydo = NULL;
+ int level, j;
+ int depth;
+ isl_map **must_rel = NULL;
+ isl_map **may_rel = NULL;
+
+ if (!acc)
+ return NULL;
+
+ res = isl_flow_alloc(acc);
+ if (!res)
+ goto error;
+ ctx = isl_map_get_ctx(acc->sink.map);
+
+ depth = 2 * isl_map_dim(acc->sink.map, isl_dim_in) + 1;
+ mustdo = isl_map_domain(isl_map_copy(acc->sink.map));
+ maydo = isl_set_empty_like(mustdo);
+ if (!mustdo || !maydo)
+ goto error;
+ if (isl_set_plain_is_empty(mustdo))
+ goto done;
+
+ must_rel = isl_alloc_array(ctx, struct isl_map *, acc->n_must);
+ may_rel = isl_alloc_array(ctx, struct isl_map *, acc->n_must);
+ if (!must_rel || !may_rel)
+ goto error;
+
+ for (level = depth; level >= 1; --level) {
+ for (j = acc->n_must-1; j >=0; --j) {
+ must_rel[j] = isl_map_empty_like(res->dep[2 * j].map);
+ may_rel[j] = isl_map_copy(must_rel[j]);
+ }
+
+ for (j = acc->n_must - 1; j >= 0; --j) {
+ struct isl_map *T;
+ struct isl_set *rest;
+ int plevel;
+
+ plevel = acc->level_before(acc->source[j].data,
+ acc->sink.data);
+ if (!can_precede_at_level(plevel, level))
+ continue;
+
+ T = last_source(acc, mustdo, j, level, &rest);
+ must_rel[j] = isl_map_union_disjoint(must_rel[j], T);
+ mustdo = rest;
+
+ intermediate_sources(acc, must_rel, j, level);
+
+ T = last_source(acc, maydo, j, level, &rest);
+ may_rel[j] = isl_map_union_disjoint(may_rel[j], T);
+ maydo = rest;
+
+ intermediate_sources(acc, may_rel, j, level);
+
+ if (isl_set_plain_is_empty(mustdo) &&
+ isl_set_plain_is_empty(maydo))
+ break;
+ }
+ for (j = j - 1; j >= 0; --j) {
+ int plevel;
+
+ plevel = acc->level_before(acc->source[j].data,
+ acc->sink.data);
+ if (!can_precede_at_level(plevel, level))
+ continue;
+
+ intermediate_sources(acc, must_rel, j, level);
+ intermediate_sources(acc, may_rel, j, level);
+ }
+
+ for (j = 0; j < acc->n_may; ++j) {
+ int plevel;
+ isl_map *T;
+ isl_set *ran;
+
+ plevel = acc->level_before(acc->source[acc->n_must + j].data,
+ acc->sink.data);
+ if (!can_precede_at_level(plevel, level))
+ continue;
+
+ T = all_sources(acc, isl_set_copy(maydo), j, level);
+ res->dep[2 * acc->n_must + j].map =
+ isl_map_union(res->dep[2 * acc->n_must + j].map, T);
+ T = all_sources(acc, isl_set_copy(mustdo), j, level);
+ ran = isl_map_range(isl_map_copy(T));
+ res->dep[2 * acc->n_must + j].map =
+ isl_map_union(res->dep[2 * acc->n_must + j].map, T);
+ mustdo = isl_set_subtract(mustdo, isl_set_copy(ran));
+ maydo = isl_set_union_disjoint(maydo, ran);
+
+ T = res->dep[2 * acc->n_must + j].map;
+ T = all_intermediate_sources(acc, T, must_rel, may_rel,
+ j, level);
+ res->dep[2 * acc->n_must + j].map = T;
+ }
+
+ for (j = acc->n_must - 1; j >= 0; --j) {
+ res->dep[2 * j].map =
+ isl_map_union_disjoint(res->dep[2 * j].map,
+ must_rel[j]);
+ res->dep[2 * j + 1].map =
+ isl_map_union_disjoint(res->dep[2 * j + 1].map,
+ may_rel[j]);
+ }
+
+ if (isl_set_plain_is_empty(mustdo) &&
+ isl_set_plain_is_empty(maydo))
+ break;
+ }
+
+ free(must_rel);
+ free(may_rel);
+done:
+ res->must_no_source = mustdo;
+ res->may_no_source = maydo;
+ return res;
+error:
+ isl_flow_free(res);
+ isl_set_free(mustdo);
+ isl_set_free(maydo);
+ free(must_rel);
+ free(may_rel);
+ 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, 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.
+ */
+__isl_give isl_flow *isl_access_info_compute_flow(__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;
+
+ if (acc->n_must == 0)
+ res = compute_mem_based_dependences(acc);
+ else {
+ acc = isl_access_info_sort_sources(acc);
+ res = compute_val_based_dependences(acc);
+ }
+ if (!res)
+ goto error;
+
+ 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));
+ 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;
+}
+
+
+/* Keep track of some information about a schedule for a given
+ * access. In particular, keep track of which dimensions
+ * have a constant value and of the actual constant values.
+ */
+struct isl_sched_info {
+ int *is_cst;
+ isl_vec *cst;
+};
+
+static void sched_info_free(__isl_take struct isl_sched_info *info)
+{
+ if (!info)
+ return;
+ isl_vec_free(info->cst);
+ free(info->is_cst);
+ free(info);
+}
+
+/* Extract information on the constant dimensions of the schedule
+ * for a given access. The "map" is of the form
+ *
+ * [S -> D] -> A
+ *
+ * with S the schedule domain, D the iteration domain and A the data domain.
+ */
+static __isl_give struct isl_sched_info *sched_info_alloc(
+ __isl_keep isl_map *map)
+{
+ isl_ctx *ctx;
+ isl_space *dim;
+ struct isl_sched_info *info;
+ int i, n;
+
+ if (!map)
+ return NULL;
+
+ dim = isl_space_unwrap(isl_space_domain(isl_map_get_space(map)));
+ if (!dim)
+ return NULL;
+ n = isl_space_dim(dim, isl_dim_in);
+ isl_space_free(dim);
+
+ ctx = isl_map_get_ctx(map);
+ info = isl_alloc_type(ctx, struct isl_sched_info);
+ if (!info)
+ return NULL;
+ info->is_cst = isl_alloc_array(ctx, int, n);
+ info->cst = isl_vec_alloc(ctx, n);
+ if (n && (!info->is_cst || !info->cst))
+ goto error;
+
+ for (i = 0; i < n; ++i) {
+ isl_val *v;
+
+ v = isl_map_plain_get_val_if_fixed(map, isl_dim_in, i);
+ if (!v)
+ goto error;
+ info->is_cst[i] = !isl_val_is_nan(v);
+ if (info->is_cst[i])
+ info->cst = isl_vec_set_element_val(info->cst, i, v);
+ else
+ isl_val_free(v);
+ }
+
+ return info;
+error:
+ sched_info_free(info);
+ return NULL;
+}
+
+struct isl_compute_flow_data {
+ isl_union_map *must_source;
+ isl_union_map *may_source;
+ isl_union_map *must_dep;
+ isl_union_map *may_dep;
+ isl_union_map *must_no_source;
+ isl_union_map *may_no_source;
+
+ int count;
+ int must;
+ isl_space *dim;
+ struct isl_sched_info *sink_info;
+ struct isl_sched_info **source_info;
+ isl_access_info *accesses;
+};
+
+static int count_matching_array(__isl_take isl_map *map, void *user)
+{
+ int eq;
+ isl_space *dim;
+ struct isl_compute_flow_data *data;
+
+ data = (struct isl_compute_flow_data *)user;
+
+ dim = isl_space_range(isl_map_get_space(map));
+
+ eq = isl_space_is_equal(dim, data->dim);
+
+ isl_space_free(dim);
+ isl_map_free(map);
+
+ if (eq < 0)
+ return -1;
+ if (eq)
+ data->count++;
+
+ return 0;
+}
+
+static int collect_matching_array(__isl_take isl_map *map, void *user)
+{
+ int eq;
+ isl_space *dim;
+ struct isl_sched_info *info;
+ struct isl_compute_flow_data *data;
+
+ data = (struct isl_compute_flow_data *)user;
+
+ dim = isl_space_range(isl_map_get_space(map));
+
+ eq = isl_space_is_equal(dim, data->dim);
+
+ isl_space_free(dim);
+
+ if (eq < 0)
+ goto error;
+ if (!eq) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ info = sched_info_alloc(map);
+ data->source_info[data->count] = info;
+
+ data->accesses = isl_access_info_add_source(data->accesses,
+ map, data->must, info);
+
+ data->count++;
+
+ return 0;
+error:
+ isl_map_free(map);
+ return -1;
+}
+
+/* Determine the shared nesting level and the "textual order" of
+ * the given accesses.
+ *
+ * We first determine the minimal schedule dimension for both accesses.
+ *
+ * If among those dimensions, we can find one where both have a fixed
+ * value and if moreover those values are different, then the previous
+ * dimension is the last shared nesting level and the textual order
+ * is determined based on the order of the fixed values.
+ * If no such fixed values can be found, then we set the shared
+ * nesting level to the minimal schedule dimension, with no textual ordering.
+ */
+static int before(void *first, void *second)
+{
+ struct isl_sched_info *info1 = first;
+ struct isl_sched_info *info2 = second;
+ int n1, n2;
+ int i;
+
+ n1 = isl_vec_size(info1->cst);
+ n2 = isl_vec_size(info2->cst);
+
+ if (n2 < n1)
+ n1 = n2;
+
+ for (i = 0; i < n1; ++i) {
+ int r;
+ int cmp;
+
+ if (!info1->is_cst[i])
+ continue;
+ if (!info2->is_cst[i])
+ continue;
+ cmp = isl_vec_cmp_element(info1->cst, info2->cst, i);
+ if (cmp == 0)
+ continue;
+
+ r = 2 * i + (cmp < 0);
+
+ return r;
+ }
+
+ return 2 * n1;
+}
+
+/* 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.
+ */
+static int compute_flow(__isl_take isl_map *map, void *user)
+{
+ int i;
+ isl_ctx *ctx;
+ struct isl_compute_flow_data *data;
+ isl_flow *flow;
+
+ data = (struct isl_compute_flow_data *)user;
+
+ ctx = isl_map_get_ctx(map);
+
+ data->accesses = NULL;
+ data->sink_info = NULL;
+ data->source_info = NULL;
+ data->count = 0;
+ data->dim = isl_space_range(isl_map_get_space(map));
+
+ if (isl_union_map_foreach_map(data->must_source,
+ &count_matching_array, data) < 0)
+ goto error;
+ if (isl_union_map_foreach_map(data->may_source,
+ &count_matching_array, data) < 0)
+ goto error;
+
+ data->sink_info = sched_info_alloc(map);
+ data->source_info = isl_calloc_array(ctx, struct isl_sched_info *,
+ data->count);
+
+ data->accesses = isl_access_info_alloc(isl_map_copy(map),
+ data->sink_info, &before, data->count);
+ if (!data->sink_info || (data->count && !data->source_info) ||
+ !data->accesses)
+ goto error;
+ data->count = 0;
+ data->must = 1;
+ if (isl_union_map_foreach_map(data->must_source,
+ &collect_matching_array, data) < 0)
+ goto error;
+ data->must = 0;
+ if (isl_union_map_foreach_map(data->may_source,
+ &collect_matching_array, data) < 0)
+ goto error;
+
+ flow = isl_access_info_compute_flow(data->accesses);
+ data->accesses = NULL;
+
+ if (!flow)
+ goto error;
+
+ data->must_no_source = isl_union_map_union(data->must_no_source,
+ isl_union_map_from_map(isl_flow_get_no_source(flow, 1)));
+ data->may_no_source = isl_union_map_union(data->may_no_source,
+ isl_union_map_from_map(isl_flow_get_no_source(flow, 0)));
+
+ for (i = 0; i < flow->n_source; ++i) {
+ isl_union_map *dep;
+ dep = isl_union_map_from_map(isl_map_copy(flow->dep[i].map));
+ if (flow->dep[i].must)
+ data->must_dep = isl_union_map_union(data->must_dep, dep);
+ else
+ data->may_dep = isl_union_map_union(data->may_dep, dep);
+ }
+
+ isl_flow_free(flow);
+
+ sched_info_free(data->sink_info);
+ if (data->source_info) {
+ for (i = 0; i < data->count; ++i)
+ sched_info_free(data->source_info[i]);
+ free(data->source_info);
+ }
+ isl_space_free(data->dim);
+ isl_map_free(map);
+
+ return 0;
+error:
+ isl_access_info_free(data->accesses);
+ sched_info_free(data->sink_info);
+ if (data->source_info) {
+ for (i = 0; i < data->count; ++i)
+ sched_info_free(data->source_info[i]);
+ free(data->source_info);
+ }
+ isl_space_free(data->dim);
+ isl_map_free(map);
+
+ return -1;
+}
+
+/* Given a collection of "sink" and "source" accesses,
+ * compute for each iteration of a 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 relations between source and sink
+ * iterations and a subset of the domain of the sink accesses,
+ * corresponding to those iterations that access an element
+ * not previously accessed.
+ *
+ * We first prepend the schedule dimensions to the domain
+ * of the accesses so that we can easily compare their relative order.
+ * Then we consider each sink access individually in compute_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,
+ __isl_take isl_union_map *schedule,
+ __isl_give isl_union_map **must_dep, __isl_give isl_union_map **may_dep,
+ __isl_give isl_union_map **must_no_source,
+ __isl_give isl_union_map **may_no_source)
+{
+ isl_space *dim;
+ isl_union_map *range_map = NULL;
+ struct isl_compute_flow_data data;
+
+ sink = isl_union_map_align_params(sink,
+ isl_union_map_get_space(must_source));
+ sink = isl_union_map_align_params(sink,
+ isl_union_map_get_space(may_source));
+ sink = isl_union_map_align_params(sink,
+ isl_union_map_get_space(schedule));
+ dim = isl_union_map_get_space(sink);
+ must_source = isl_union_map_align_params(must_source, isl_space_copy(dim));
+ may_source = isl_union_map_align_params(may_source, isl_space_copy(dim));
+ schedule = isl_union_map_align_params(schedule, isl_space_copy(dim));
+
+ schedule = isl_union_map_reverse(schedule);
+ range_map = isl_union_map_range_map(schedule);
+ schedule = isl_union_map_reverse(isl_union_map_copy(range_map));
+ sink = isl_union_map_apply_domain(sink, isl_union_map_copy(schedule));
+ must_source = isl_union_map_apply_domain(must_source,
+ isl_union_map_copy(schedule));
+ may_source = isl_union_map_apply_domain(may_source, schedule);
+
+ data.must_source = must_source;
+ data.may_source = may_source;
+ data.must_dep = must_dep ?
+ isl_union_map_empty(isl_space_copy(dim)) : NULL;
+ data.may_dep = may_dep ? isl_union_map_empty(isl_space_copy(dim)) : NULL;
+ data.must_no_source = must_no_source ?
+ isl_union_map_empty(isl_space_copy(dim)) : NULL;
+ data.may_no_source = may_no_source ?
+ isl_union_map_empty(isl_space_copy(dim)) : NULL;
+
+ isl_space_free(dim);
+
+ if (isl_union_map_foreach_map(sink, &compute_flow, &data) < 0)
+ goto error;
+
+ isl_union_map_free(sink);
+ isl_union_map_free(must_source);
+ isl_union_map_free(may_source);
+
+ if (must_dep) {
+ data.must_dep = isl_union_map_apply_domain(data.must_dep,
+ isl_union_map_copy(range_map));
+ data.must_dep = isl_union_map_apply_range(data.must_dep,
+ isl_union_map_copy(range_map));
+ *must_dep = data.must_dep;
+ }
+ if (may_dep) {
+ data.may_dep = isl_union_map_apply_domain(data.may_dep,
+ isl_union_map_copy(range_map));
+ data.may_dep = isl_union_map_apply_range(data.may_dep,
+ isl_union_map_copy(range_map));
+ *may_dep = data.may_dep;
+ }
+ if (must_no_source) {
+ data.must_no_source = isl_union_map_apply_domain(
+ data.must_no_source, isl_union_map_copy(range_map));
+ *must_no_source = data.must_no_source;
+ }
+ if (may_no_source) {
+ data.may_no_source = isl_union_map_apply_domain(
+ data.may_no_source, isl_union_map_copy(range_map));
+ *may_no_source = data.may_no_source;
+ }
+
+ isl_union_map_free(range_map);
+
+ return 0;
+error:
+ isl_union_map_free(range_map);
+ isl_union_map_free(sink);
+ isl_union_map_free(must_source);
+ isl_union_map_free(may_source);
+ isl_union_map_free(data.must_dep);
+ isl_union_map_free(data.may_dep);
+ isl_union_map_free(data.must_no_source);
+ isl_union_map_free(data.may_no_source);
+
+ if (must_dep)
+ *must_dep = NULL;
+ if (may_dep)
+ *may_dep = NULL;
+ if (must_no_source)
+ *must_no_source = NULL;
+ if (may_no_source)
+ *may_no_source = NULL;
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_fold.c b/polly/lib/External/isl/isl_fold.c
new file mode 100644
index 00000000000..dee86c31f47
--- /dev/null
+++ b/polly/lib/External/isl/isl_fold.c
@@ -0,0 +1,1711 @@
+/*
+ * 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
+ */
+
+#define ISL_DIM_H
+#include <isl_map_private.h>
+#include <isl_union_map_private.h>
+#include <isl_polynomial_private.h>
+#include <isl_point_private.h>
+#include <isl_space_private.h>
+#include <isl_lp_private.h>
+#include <isl_seq.h>
+#include <isl_mat_private.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+#include <isl_config.h>
+#include <isl/deprecated/polynomial_int.h>
+
+enum isl_fold isl_fold_type_negate(enum isl_fold type)
+{
+ switch (type) {
+ case isl_fold_min:
+ return isl_fold_max;
+ case isl_fold_max:
+ return isl_fold_min;
+ case isl_fold_list:
+ return isl_fold_list;
+ }
+
+ isl_die(NULL, isl_error_internal, "unhandled isl_fold type", abort());
+}
+
+static __isl_give isl_qpolynomial_fold *qpolynomial_fold_alloc(
+ enum isl_fold type, __isl_take isl_space *dim, int n)
+{
+ isl_qpolynomial_fold *fold;
+
+ if (!dim)
+ goto error;
+
+ isl_assert(dim->ctx, n >= 0, goto error);
+ fold = isl_calloc(dim->ctx, struct isl_qpolynomial_fold,
+ sizeof(struct isl_qpolynomial_fold) +
+ (n - 1) * sizeof(struct isl_qpolynomial *));
+ if (!fold)
+ goto error;
+
+ fold->ref = 1;
+ fold->size = n;
+ fold->n = 0;
+ fold->type = type;
+ fold->dim = dim;
+
+ return fold;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+isl_ctx *isl_qpolynomial_fold_get_ctx(__isl_keep isl_qpolynomial_fold *fold)
+{
+ return fold ? fold->dim->ctx : NULL;
+}
+
+__isl_give isl_space *isl_qpolynomial_fold_get_domain_space(
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ return fold ? isl_space_copy(fold->dim) : NULL;
+}
+
+__isl_give isl_space *isl_qpolynomial_fold_get_space(
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ isl_space *space;
+ if (!fold)
+ return NULL;
+ space = isl_space_copy(fold->dim);
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ return space;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_domain_space(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim)
+{
+ int i;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold || !dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_reset_domain_space(fold->qp[i],
+ isl_space_copy(dim));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_space_free(fold->dim);
+ fold->dim = dim;
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Reset the space of "fold". This function is called from isl_pw_templ.c
+ * and doesn't know if the space of an element object is represented
+ * directly or through its domain. It therefore passes along both.
+ */
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_space_and_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *space,
+ __isl_take isl_space *domain)
+{
+ isl_space_free(space);
+ return isl_qpolynomial_fold_reset_domain_space(fold, domain);
+}
+
+int isl_qpolynomial_fold_involves_dims(__isl_keep isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!fold)
+ return -1;
+ if (fold->n == 0 || n == 0)
+ return 0;
+
+ for (i = 0; i < fold->n; ++i) {
+ int involves = isl_qpolynomial_involves_dims(fold->qp[i],
+ type, first, n);
+ if (involves < 0 || involves)
+ return involves;
+ }
+ return 0;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_set_dim_name(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ int i;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+ fold->dim = isl_space_set_dim_name(fold->dim, type, pos, s);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_set_dim_name(fold->qp[i],
+ type, pos, s);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_drop_dims(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ if (!fold)
+ return NULL;
+ if (n == 0)
+ return fold;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+ fold->dim = isl_space_drop_dims(fold->dim, set_type, first, n);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_drop_dims(fold->qp[i],
+ type, first, n);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_insert_dims(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!fold)
+ return NULL;
+ if (n == 0 && !isl_space_is_named_or_nested(fold->dim, type))
+ return fold;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+ fold->dim = isl_space_insert_dims(fold->dim, type, first, n);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_insert_dims(fold->qp[i],
+ type, first, n);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+static int isl_qpolynomial_cst_sign(__isl_keep isl_qpolynomial *qp)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_as_cst(qp->upoly);
+ if (!cst)
+ return 0;
+
+ return isl_int_sgn(cst->n) < 0 ? -1 : 1;
+}
+
+static int isl_qpolynomial_aff_sign(__isl_keep isl_set *set,
+ __isl_keep isl_qpolynomial *qp)
+{
+ enum isl_lp_result res;
+ isl_vec *aff;
+ isl_int opt;
+ int sgn = 0;
+
+ aff = isl_qpolynomial_extract_affine(qp);
+ if (!aff)
+ return 0;
+
+ isl_int_init(opt);
+
+ res = isl_set_solve_lp(set, 0, aff->el + 1, aff->el[0],
+ &opt, NULL, NULL);
+ if (res == isl_lp_error)
+ goto done;
+ if (res == isl_lp_empty ||
+ (res == isl_lp_ok && !isl_int_is_neg(opt))) {
+ sgn = 1;
+ goto done;
+ }
+
+ res = isl_set_solve_lp(set, 1, aff->el + 1, aff->el[0],
+ &opt, NULL, NULL);
+ if (res == isl_lp_ok && !isl_int_is_pos(opt))
+ sgn = -1;
+
+done:
+ isl_int_clear(opt);
+ isl_vec_free(aff);
+ return sgn;
+}
+
+/* Determine, if possible, the sign of the quasipolynomial "qp" on
+ * the domain "set".
+ *
+ * If qp is a constant, then the problem is trivial.
+ * If qp is linear, then we check if the minimum of the corresponding
+ * affine constraint is non-negative or if the maximum is non-positive.
+ *
+ * Otherwise, we check if the outermost variable "v" has a lower bound "l"
+ * in "set". If so, we write qp(v,v') as
+ *
+ * q(v,v') * (v - l) + r(v')
+ *
+ * if q(v,v') and r(v') have the same known sign, then the original
+ * quasipolynomial has the same sign as well.
+ *
+ * Return
+ * -1 if qp <= 0
+ * 1 if qp >= 0
+ * 0 if unknown
+ */
+static int isl_qpolynomial_sign(__isl_keep isl_set *set,
+ __isl_keep isl_qpolynomial *qp)
+{
+ int d;
+ int i;
+ int is;
+ struct isl_upoly_rec *rec;
+ isl_vec *v;
+ isl_int l;
+ enum isl_lp_result res;
+ int sgn = 0;
+
+ is = isl_qpolynomial_is_cst(qp, NULL, NULL);
+ if (is < 0)
+ return 0;
+ if (is)
+ return isl_qpolynomial_cst_sign(qp);
+
+ is = isl_qpolynomial_is_affine(qp);
+ if (is < 0)
+ return 0;
+ if (is)
+ return isl_qpolynomial_aff_sign(set, qp);
+
+ if (qp->div->n_row > 0)
+ return 0;
+
+ rec = isl_upoly_as_rec(qp->upoly);
+ if (!rec)
+ return 0;
+
+ d = isl_space_dim(qp->dim, isl_dim_all);
+ v = isl_vec_alloc(set->ctx, 2 + d);
+ if (!v)
+ return 0;
+
+ isl_seq_clr(v->el + 1, 1 + d);
+ isl_int_set_si(v->el[0], 1);
+ isl_int_set_si(v->el[2 + qp->upoly->var], 1);
+
+ isl_int_init(l);
+
+ res = isl_set_solve_lp(set, 0, v->el + 1, v->el[0], &l, NULL, NULL);
+ if (res == isl_lp_ok) {
+ isl_qpolynomial *min;
+ isl_qpolynomial *base;
+ isl_qpolynomial *r, *q;
+ isl_qpolynomial *t;
+
+ min = isl_qpolynomial_cst_on_domain(isl_space_copy(qp->dim), l);
+ base = isl_qpolynomial_var_pow_on_domain(isl_space_copy(qp->dim),
+ qp->upoly->var, 1);
+
+ r = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
+ isl_upoly_copy(rec->p[rec->n - 1]));
+ q = isl_qpolynomial_copy(r);
+
+ for (i = rec->n - 2; i >= 0; --i) {
+ r = isl_qpolynomial_mul(r, isl_qpolynomial_copy(min));
+ t = isl_qpolynomial_alloc(isl_space_copy(qp->dim), 0,
+ isl_upoly_copy(rec->p[i]));
+ r = isl_qpolynomial_add(r, t);
+ if (i == 0)
+ break;
+ q = isl_qpolynomial_mul(q, isl_qpolynomial_copy(base));
+ q = isl_qpolynomial_add(q, isl_qpolynomial_copy(r));
+ }
+
+ if (isl_qpolynomial_is_zero(q))
+ sgn = isl_qpolynomial_sign(set, r);
+ else if (isl_qpolynomial_is_zero(r))
+ sgn = isl_qpolynomial_sign(set, q);
+ else {
+ int sgn_q, sgn_r;
+ sgn_r = isl_qpolynomial_sign(set, r);
+ sgn_q = isl_qpolynomial_sign(set, q);
+ if (sgn_r == sgn_q)
+ sgn = sgn_r;
+ }
+
+ isl_qpolynomial_free(min);
+ isl_qpolynomial_free(base);
+ isl_qpolynomial_free(q);
+ isl_qpolynomial_free(r);
+ }
+
+ isl_int_clear(l);
+
+ isl_vec_free(v);
+
+ return sgn;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
+ __isl_keep isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2)
+{
+ int i, j;
+ int n1;
+ struct isl_qpolynomial_fold *res = NULL;
+ int better;
+
+ if (!fold1 || !fold2)
+ goto error;
+
+ isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
+ isl_assert(fold1->dim->ctx, isl_space_is_equal(fold1->dim, fold2->dim),
+ goto error);
+
+ better = fold1->type == isl_fold_max ? -1 : 1;
+
+ if (isl_qpolynomial_fold_is_empty(fold1)) {
+ isl_qpolynomial_fold_free(fold1);
+ return fold2;
+ }
+
+ if (isl_qpolynomial_fold_is_empty(fold2)) {
+ isl_qpolynomial_fold_free(fold2);
+ return fold1;
+ }
+
+ res = qpolynomial_fold_alloc(fold1->type, isl_space_copy(fold1->dim),
+ fold1->n + fold2->n);
+ if (!res)
+ goto error;
+
+ for (i = 0; i < fold1->n; ++i) {
+ res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
+ if (!res->qp[res->n])
+ goto error;
+ res->n++;
+ }
+ n1 = res->n;
+
+ for (i = 0; i < fold2->n; ++i) {
+ for (j = n1 - 1; j >= 0; --j) {
+ isl_qpolynomial *d;
+ int sgn;
+ d = isl_qpolynomial_sub(
+ isl_qpolynomial_copy(res->qp[j]),
+ isl_qpolynomial_copy(fold2->qp[i]));
+ sgn = isl_qpolynomial_sign(set, d);
+ isl_qpolynomial_free(d);
+ if (sgn == 0)
+ continue;
+ if (sgn != better)
+ break;
+ isl_qpolynomial_free(res->qp[j]);
+ if (j != n1 - 1)
+ res->qp[j] = res->qp[n1 - 1];
+ n1--;
+ if (n1 != res->n - 1)
+ res->qp[n1] = res->qp[res->n - 1];
+ res->n--;
+ }
+ if (j >= 0)
+ continue;
+ res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
+ if (!res->qp[res->n])
+ goto error;
+ res->n++;
+ }
+
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+
+ return res;
+error:
+ isl_qpolynomial_fold_free(res);
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_add_qpolynomial(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_qpolynomial *qp)
+{
+ int i;
+
+ if (!fold || !qp)
+ goto error;
+
+ if (isl_qpolynomial_is_zero(qp)) {
+ isl_qpolynomial_free(qp);
+ return fold;
+ }
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_add(fold->qp[i],
+ isl_qpolynomial_copy(qp));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_qpolynomial_free(qp);
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_add_on_domain(
+ __isl_keep isl_set *dom,
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2)
+{
+ int i;
+ isl_qpolynomial_fold *res = NULL;
+
+ if (!fold1 || !fold2)
+ goto error;
+
+ if (isl_qpolynomial_fold_is_empty(fold1)) {
+ isl_qpolynomial_fold_free(fold1);
+ return fold2;
+ }
+
+ if (isl_qpolynomial_fold_is_empty(fold2)) {
+ isl_qpolynomial_fold_free(fold2);
+ return fold1;
+ }
+
+ if (fold1->n == 1 && fold2->n != 1)
+ return isl_qpolynomial_fold_add_on_domain(dom, fold2, fold1);
+
+ if (fold2->n == 1) {
+ res = isl_qpolynomial_fold_add_qpolynomial(fold1,
+ isl_qpolynomial_copy(fold2->qp[0]));
+ isl_qpolynomial_fold_free(fold2);
+ return res;
+ }
+
+ res = isl_qpolynomial_fold_add_qpolynomial(
+ isl_qpolynomial_fold_copy(fold1),
+ isl_qpolynomial_copy(fold2->qp[0]));
+
+ for (i = 1; i < fold2->n; ++i) {
+ isl_qpolynomial_fold *res_i;
+ res_i = isl_qpolynomial_fold_add_qpolynomial(
+ isl_qpolynomial_fold_copy(fold1),
+ isl_qpolynomial_copy(fold2->qp[i]));
+ res = isl_qpolynomial_fold_fold_on_domain(dom, res, res_i);
+ }
+
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+ return res;
+error:
+ isl_qpolynomial_fold_free(res);
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute_equalities(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_basic_set *eq)
+{
+ int i;
+
+ if (!fold || !eq)
+ goto error;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_substitute_equalities(fold->qp[i],
+ isl_basic_set_copy(eq));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_basic_set_free(eq);
+ return fold;
+error:
+ isl_basic_set_free(eq);
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context)
+{
+ int i;
+
+ if (!fold || !context)
+ goto error;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_gist(fold->qp[i],
+ isl_set_copy(context));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_set_free(context);
+ return fold;
+error:
+ isl_set_free(context);
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context)
+{
+ isl_space *space = isl_qpolynomial_fold_get_domain_space(fold);
+ isl_set *dom_context = isl_set_universe(space);
+ dom_context = isl_set_intersect_params(dom_context, context);
+ return isl_qpolynomial_fold_gist(fold, dom_context);
+}
+
+#define HAS_TYPE
+
+#undef PW
+#define PW isl_pw_qpolynomial_fold
+#undef EL
+#define EL isl_qpolynomial_fold
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_empty
+#undef ZERO
+#define ZERO zero
+#undef IS_ZERO
+#define IS_ZERO is_zero
+#undef FIELD
+#define FIELD fold
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 1
+
+#define NO_NEG
+#define NO_PULLBACK
+
+#include <isl_pw_templ.c>
+
+#undef UNION
+#define UNION isl_union_pw_qpolynomial_fold
+#undef PART
+#define PART isl_pw_qpolynomial_fold
+#undef PARTS
+#define PARTS pw_qpolynomial_fold
+#define ALIGN_DOMAIN
+
+#define NO_SUB
+
+#include <isl_union_templ.c>
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
+ __isl_take isl_space *dim)
+{
+ return qpolynomial_fold_alloc(type, dim, 0);
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
+ enum isl_fold type, __isl_take isl_qpolynomial *qp)
+{
+ isl_qpolynomial_fold *fold;
+
+ if (!qp)
+ return NULL;
+
+ fold = qpolynomial_fold_alloc(type, isl_space_copy(qp->dim), 1);
+ if (!fold)
+ goto error;
+
+ fold->qp[0] = qp;
+ fold->n++;
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ if (!fold)
+ return NULL;
+
+ fold->ref++;
+ return fold;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ int i;
+ isl_qpolynomial_fold *dup;
+
+ if (!fold)
+ return NULL;
+ dup = qpolynomial_fold_alloc(fold->type,
+ isl_space_copy(fold->dim), fold->n);
+ if (!dup)
+ return NULL;
+
+ dup->n = fold->n;
+ for (i = 0; i < fold->n; ++i) {
+ dup->qp[i] = isl_qpolynomial_copy(fold->qp[i]);
+ if (!dup->qp[i])
+ goto error;
+ }
+
+ return dup;
+error:
+ isl_qpolynomial_fold_free(dup);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
+ __isl_take isl_qpolynomial_fold *fold)
+{
+ if (!fold)
+ return NULL;
+
+ if (fold->ref == 1)
+ return fold;
+ fold->ref--;
+ return isl_qpolynomial_fold_dup(fold);
+}
+
+void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold)
+{
+ int i;
+
+ if (!fold)
+ return;
+ if (--fold->ref > 0)
+ return;
+
+ for (i = 0; i < fold->n; ++i)
+ isl_qpolynomial_free(fold->qp[i]);
+ isl_space_free(fold->dim);
+ free(fold);
+}
+
+int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold)
+{
+ if (!fold)
+ return -1;
+
+ return fold->n == 0;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2)
+{
+ int i;
+ struct isl_qpolynomial_fold *res = NULL;
+
+ if (!fold1 || !fold2)
+ goto error;
+
+ isl_assert(fold1->dim->ctx, fold1->type == fold2->type, goto error);
+ isl_assert(fold1->dim->ctx, isl_space_is_equal(fold1->dim, fold2->dim),
+ goto error);
+
+ if (isl_qpolynomial_fold_is_empty(fold1)) {
+ isl_qpolynomial_fold_free(fold1);
+ return fold2;
+ }
+
+ if (isl_qpolynomial_fold_is_empty(fold2)) {
+ isl_qpolynomial_fold_free(fold2);
+ return fold1;
+ }
+
+ res = qpolynomial_fold_alloc(fold1->type, isl_space_copy(fold1->dim),
+ fold1->n + fold2->n);
+ if (!res)
+ goto error;
+
+ for (i = 0; i < fold1->n; ++i) {
+ res->qp[res->n] = isl_qpolynomial_copy(fold1->qp[i]);
+ if (!res->qp[res->n])
+ goto error;
+ res->n++;
+ }
+
+ for (i = 0; i < fold2->n; ++i) {
+ res->qp[res->n] = isl_qpolynomial_copy(fold2->qp[i]);
+ if (!res->qp[res->n])
+ goto error;
+ res->n++;
+ }
+
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+
+ return res;
+error:
+ isl_qpolynomial_fold_free(res);
+ isl_qpolynomial_fold_free(fold1);
+ isl_qpolynomial_fold_free(fold2);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fold(
+ __isl_take isl_pw_qpolynomial_fold *pw1,
+ __isl_take isl_pw_qpolynomial_fold *pw2)
+{
+ int i, j, n;
+ struct isl_pw_qpolynomial_fold *res;
+ isl_set *set;
+
+ if (!pw1 || !pw2)
+ goto error;
+
+ isl_assert(pw1->dim->ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
+
+ if (isl_pw_qpolynomial_fold_is_zero(pw1)) {
+ isl_pw_qpolynomial_fold_free(pw1);
+ return pw2;
+ }
+
+ if (isl_pw_qpolynomial_fold_is_zero(pw2)) {
+ isl_pw_qpolynomial_fold_free(pw2);
+ return pw1;
+ }
+
+ if (pw1->type != pw2->type)
+ isl_die(pw1->dim->ctx, isl_error_invalid,
+ "fold types don't match", goto error);
+
+ n = (pw1->n + 1) * (pw2->n + 1);
+ res = isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pw1->dim),
+ pw1->type, n);
+
+ for (i = 0; i < pw1->n; ++i) {
+ set = isl_set_copy(pw1->p[i].set);
+ for (j = 0; j < pw2->n; ++j) {
+ struct isl_set *common;
+ isl_qpolynomial_fold *sum;
+ set = isl_set_subtract(set,
+ isl_set_copy(pw2->p[j].set));
+ common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
+ isl_set_copy(pw2->p[j].set));
+ if (isl_set_plain_is_empty(common)) {
+ isl_set_free(common);
+ continue;
+ }
+
+ sum = isl_qpolynomial_fold_fold_on_domain(common,
+ isl_qpolynomial_fold_copy(pw1->p[i].fold),
+ isl_qpolynomial_fold_copy(pw2->p[j].fold));
+
+ res = isl_pw_qpolynomial_fold_add_piece(res, common, sum);
+ }
+ res = isl_pw_qpolynomial_fold_add_piece(res, set,
+ isl_qpolynomial_fold_copy(pw1->p[i].fold));
+ }
+
+ for (j = 0; j < pw2->n; ++j) {
+ set = isl_set_copy(pw2->p[j].set);
+ for (i = 0; i < pw1->n; ++i)
+ set = isl_set_subtract(set, isl_set_copy(pw1->p[i].set));
+ res = isl_pw_qpolynomial_fold_add_piece(res, set,
+ isl_qpolynomial_fold_copy(pw2->p[j].fold));
+ }
+
+ isl_pw_qpolynomial_fold_free(pw1);
+ isl_pw_qpolynomial_fold_free(pw2);
+
+ return res;
+error:
+ isl_pw_qpolynomial_fold_free(pw1);
+ isl_pw_qpolynomial_fold_free(pw2);
+ return NULL;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+ __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);
+
+ if (!part || !u)
+ goto error;
+
+ isl_assert(u->space->ctx,
+ 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,
+ &has_same_domain_space, part->dim, 1);
+ if (!entry)
+ goto error;
+
+ if (!entry->data)
+ entry->data = part;
+ else {
+ entry->data = isl_pw_qpolynomial_fold_fold(entry->data,
+ isl_pw_qpolynomial_fold_copy(part));
+ if (!entry->data)
+ goto error;
+ isl_pw_qpolynomial_fold_free(part);
+ }
+
+ return u;
+error:
+ isl_pw_qpolynomial_fold_free(part);
+ isl_union_pw_qpolynomial_fold_free(u);
+ return NULL;
+}
+
+static int fold_part(__isl_take isl_pw_qpolynomial_fold *part, void *user)
+{
+ isl_union_pw_qpolynomial_fold **u;
+ u = (isl_union_pw_qpolynomial_fold **)user;
+
+ *u = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(*u, part);
+
+ return 0;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold(
+ __isl_take isl_union_pw_qpolynomial_fold *u1,
+ __isl_take isl_union_pw_qpolynomial_fold *u2)
+{
+ u1 = isl_union_pw_qpolynomial_fold_cow(u1);
+
+ if (!u1 || !u2)
+ goto error;
+
+ if (isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(u2,
+ &fold_part, &u1) < 0)
+ goto error;
+
+ isl_union_pw_qpolynomial_fold_free(u2);
+
+ return u1;
+error:
+ isl_union_pw_qpolynomial_fold_free(u1);
+ isl_union_pw_qpolynomial_fold_free(u2);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
+ enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp)
+{
+ int i;
+ isl_pw_qpolynomial_fold *pwf;
+
+ if (!pwqp)
+ return NULL;
+
+ pwf = isl_pw_qpolynomial_fold_alloc_size(isl_space_copy(pwqp->dim),
+ type, pwqp->n);
+
+ for (i = 0; i < pwqp->n; ++i)
+ pwf = isl_pw_qpolynomial_fold_add_piece(pwf,
+ isl_set_copy(pwqp->p[i].set),
+ isl_qpolynomial_fold_alloc(type,
+ isl_qpolynomial_copy(pwqp->p[i].qp)));
+
+ isl_pw_qpolynomial_free(pwqp);
+
+ return pwf;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
+ __isl_take isl_pw_qpolynomial_fold *pwf1,
+ __isl_take isl_pw_qpolynomial_fold *pwf2)
+{
+ return isl_pw_qpolynomial_fold_union_add_(pwf1, pwf2);
+}
+
+int isl_qpolynomial_fold_plain_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
+ __isl_keep isl_qpolynomial_fold *fold2)
+{
+ int i;
+
+ if (!fold1 || !fold2)
+ return -1;
+
+ if (fold1->n != fold2->n)
+ return 0;
+
+ /* We probably want to sort the qps first... */
+ for (i = 0; i < fold1->n; ++i) {
+ int eq = isl_qpolynomial_plain_is_equal(fold1->qp[i], fold2->qp[i]);
+ if (eq < 0 || !eq)
+ return eq;
+ }
+
+ return 1;
+}
+
+__isl_give isl_val *isl_qpolynomial_fold_eval(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+
+ if (!fold || !pnt)
+ goto error;
+ ctx = isl_point_get_ctx(pnt);
+ isl_assert(pnt->dim->ctx, isl_space_is_equal(pnt->dim, fold->dim), goto error);
+ isl_assert(pnt->dim->ctx,
+ fold->type == isl_fold_max || fold->type == isl_fold_min,
+ goto error);
+
+ if (fold->n == 0)
+ v = isl_val_zero(ctx);
+ else {
+ int i;
+ v = isl_qpolynomial_eval(isl_qpolynomial_copy(fold->qp[0]),
+ isl_point_copy(pnt));
+ for (i = 1; i < fold->n; ++i) {
+ isl_val *v_i;
+ v_i = isl_qpolynomial_eval(
+ isl_qpolynomial_copy(fold->qp[i]),
+ isl_point_copy(pnt));
+ if (fold->type == isl_fold_max)
+ v = isl_val_max(v, v_i);
+ else
+ v = isl_val_min(v, v_i);
+ }
+ }
+ isl_qpolynomial_fold_free(fold);
+ isl_point_free(pnt);
+
+ return v;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_point_free(pnt);
+ return NULL;
+}
+
+size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ int i;
+ size_t n = 0;
+
+ for (i = 0; i < pwf->n; ++i)
+ n += pwf->p[i].fold->n;
+
+ return n;
+}
+
+__isl_give isl_val *isl_qpolynomial_fold_opt_on_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max)
+{
+ int i;
+ isl_val *opt;
+
+ if (!set || !fold)
+ goto error;
+
+ if (fold->n == 0) {
+ opt = isl_val_zero(isl_set_get_ctx(set));
+ isl_set_free(set);
+ isl_qpolynomial_fold_free(fold);
+ return opt;
+ }
+
+ opt = isl_qpolynomial_opt_on_domain(isl_qpolynomial_copy(fold->qp[0]),
+ isl_set_copy(set), max);
+ for (i = 1; i < fold->n; ++i) {
+ isl_val *opt_i;
+ opt_i = isl_qpolynomial_opt_on_domain(
+ isl_qpolynomial_copy(fold->qp[i]),
+ isl_set_copy(set), max);
+ if (max)
+ opt = isl_val_max(opt, opt_i);
+ else
+ opt = isl_val_min(opt, opt_i);
+ }
+
+ isl_set_free(set);
+ isl_qpolynomial_fold_free(fold);
+
+ return opt;
+error:
+ isl_set_free(set);
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+/* Check whether for each quasi-polynomial in "fold2" there is
+ * a quasi-polynomial in "fold1" that dominates it on "set".
+ */
+static int qpolynomial_fold_covers_on_domain(__isl_keep isl_set *set,
+ __isl_keep isl_qpolynomial_fold *fold1,
+ __isl_keep isl_qpolynomial_fold *fold2)
+{
+ int i, j;
+ int covers;
+
+ if (!set || !fold1 || !fold2)
+ return -1;
+
+ covers = fold1->type == isl_fold_max ? 1 : -1;
+
+ for (i = 0; i < fold2->n; ++i) {
+ for (j = 0; j < fold1->n; ++j) {
+ isl_qpolynomial *d;
+ int sgn;
+
+ d = isl_qpolynomial_sub(
+ isl_qpolynomial_copy(fold1->qp[j]),
+ isl_qpolynomial_copy(fold2->qp[i]));
+ sgn = isl_qpolynomial_sign(set, d);
+ isl_qpolynomial_free(d);
+ if (sgn == covers)
+ break;
+ }
+ if (j >= fold1->n)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Check whether "pwf1" dominated "pwf2", i.e., the domain of "pwf1" contains
+ * that of "pwf2" and on each cell, the corresponding fold from pwf1 dominates
+ * that of pwf2.
+ */
+int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
+ __isl_keep isl_pw_qpolynomial_fold *pwf2)
+{
+ int i, j;
+ isl_set *dom1, *dom2;
+ int is_subset;
+
+ if (!pwf1 || !pwf2)
+ return -1;
+
+ if (pwf2->n == 0)
+ return 1;
+ if (pwf1->n == 0)
+ return 0;
+
+ dom1 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf1));
+ dom2 = isl_pw_qpolynomial_fold_domain(isl_pw_qpolynomial_fold_copy(pwf2));
+ is_subset = isl_set_is_subset(dom2, dom1);
+ isl_set_free(dom1);
+ isl_set_free(dom2);
+
+ if (is_subset < 0 || !is_subset)
+ return is_subset;
+
+ for (i = 0; i < pwf2->n; ++i) {
+ for (j = 0; j < pwf1->n; ++j) {
+ int is_empty;
+ isl_set *common;
+ int covers;
+
+ common = isl_set_intersect(isl_set_copy(pwf1->p[j].set),
+ isl_set_copy(pwf2->p[i].set));
+ is_empty = isl_set_is_empty(common);
+ if (is_empty < 0 || is_empty) {
+ isl_set_free(common);
+ if (is_empty < 0)
+ return -1;
+ continue;
+ }
+ covers = qpolynomial_fold_covers_on_domain(common,
+ pwf1->p[j].fold, pwf2->p[i].fold);
+ isl_set_free(common);
+ if (covers < 0 || !covers)
+ return covers;
+ }
+ }
+
+ return 1;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_morph *morph)
+{
+ int i;
+ isl_ctx *ctx;
+
+ if (!fold || !morph)
+ goto error;
+
+ ctx = fold->dim->ctx;
+ isl_assert(ctx, isl_space_is_equal(fold->dim, morph->dom->dim), goto error);
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ goto error;
+
+ isl_space_free(fold->dim);
+ fold->dim = isl_space_copy(morph->ran->dim);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_morph_domain(fold->qp[i],
+ isl_morph_copy(morph));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_morph_free(morph);
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_morph_free(morph);
+ return NULL;
+}
+
+enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold)
+{
+ if (!fold)
+ return isl_fold_list;
+ return fold->type;
+}
+
+enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf)
+{
+ if (!upwf)
+ return isl_fold_list;
+ return upwf->type;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim)
+{
+ int i;
+
+ if (!fold || !dim)
+ goto error;
+
+ if (isl_space_is_equal(fold->dim, dim)) {
+ isl_space_free(dim);
+ return fold;
+ }
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ goto error;
+
+ isl_space_free(fold->dim);
+ fold->dim = isl_space_copy(dim);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_lift(fold->qp[i],
+ isl_space_copy(dim));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_space_free(dim);
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_space_free(dim);
+ return NULL;
+}
+
+int isl_qpolynomial_fold_foreach_qpolynomial(
+ __isl_keep isl_qpolynomial_fold *fold,
+ int (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user)
+{
+ int i;
+
+ if (!fold)
+ return -1;
+
+ for (i = 0; i < fold->n; ++i)
+ if (fn(isl_qpolynomial_copy(fold->qp[i]), user) < 0)
+ return -1;
+
+ return 0;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ int i;
+
+ if (n == 0)
+ return fold;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+
+ fold->dim = isl_space_move_dims(fold->dim, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!fold->dim)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_move_dims(fold->qp[i],
+ dst_type, dst_pos, src_type, src_pos, n);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+/* For each 0 <= i < "n", replace variable "first" + i of type "type"
+ * in fold->qp[k] by subs[i].
+ */
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute(
+ __isl_take isl_qpolynomial_fold *fold,
+ enum isl_dim_type type, unsigned first, unsigned n,
+ __isl_keep isl_qpolynomial **subs)
+{
+ int i;
+
+ if (n == 0)
+ return fold;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_substitute(fold->qp[i],
+ type, first, n, subs);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+static int 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,
+ &has_same_domain_space, pwqp->dim, 1);
+ if (!entry)
+ goto error;
+
+ pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial((*upwf)->type, pwqp);
+ if (!entry->data)
+ entry->data = pwf;
+ else {
+ entry->data = isl_pw_qpolynomial_fold_add(entry->data, pwf);
+ if (!entry->data)
+ return -1;
+ if (isl_pw_qpolynomial_fold_is_zero(entry->data)) {
+ isl_pw_qpolynomial_fold_free(entry->data);
+ isl_hash_table_remove(ctx, &(*upwf)->table, entry);
+ }
+ }
+
+ return 0;
+error:
+ isl_pw_qpolynomial_free(pwqp);
+ return -1;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_pw_qpolynomial *upwqp)
+{
+ upwf = isl_union_pw_qpolynomial_fold_align_params(upwf,
+ isl_union_pw_qpolynomial_get_space(upwqp));
+ upwqp = isl_union_pw_qpolynomial_align_params(upwqp,
+ isl_union_pw_qpolynomial_fold_get_space(upwf));
+
+ upwf = isl_union_pw_qpolynomial_fold_cow(upwf);
+ if (!upwf || !upwqp)
+ goto error;
+
+ if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &add_pwqp,
+ &upwf) < 0)
+ goto error;
+
+ isl_union_pw_qpolynomial_free(upwqp);
+
+ return upwf;
+error:
+ isl_union_pw_qpolynomial_fold_free(upwf);
+ isl_union_pw_qpolynomial_free(upwqp);
+ return NULL;
+}
+
+static int join_compatible(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2)
+{
+ int m;
+ m = isl_space_match(dim1, isl_dim_param, dim2, isl_dim_param);
+ if (m < 0 || !m)
+ return m;
+ return isl_space_tuple_is_equal(dim1, isl_dim_out, dim2, isl_dim_in);
+}
+
+/* Compute the intersection of the range of the map and the domain
+ * of the piecewise quasipolynomial reduction and then compute a bound
+ * on the associated quasipolynomial reduction over all elements
+ * in this intersection.
+ *
+ * We first introduce some unconstrained dimensions in the
+ * piecewise quasipolynomial, intersect the resulting domain
+ * with the wrapped map and the compute the sum.
+ */
+__isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
+ __isl_take isl_map *map, __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight)
+{
+ isl_ctx *ctx;
+ isl_set *dom;
+ isl_space *map_dim;
+ isl_space *pwf_dim;
+ unsigned n_in;
+ int ok;
+
+ ctx = isl_map_get_ctx(map);
+ if (!ctx)
+ goto error;
+
+ map_dim = isl_map_get_space(map);
+ pwf_dim = isl_pw_qpolynomial_fold_get_space(pwf);
+ ok = join_compatible(map_dim, pwf_dim);
+ isl_space_free(map_dim);
+ isl_space_free(pwf_dim);
+ if (!ok)
+ isl_die(ctx, isl_error_invalid, "incompatible dimensions",
+ goto error);
+
+ n_in = isl_map_dim(map, isl_dim_in);
+ pwf = isl_pw_qpolynomial_fold_insert_dims(pwf, isl_dim_in, 0, n_in);
+
+ dom = isl_map_wrap(map);
+ pwf = isl_pw_qpolynomial_fold_reset_domain_space(pwf,
+ isl_set_get_space(dom));
+
+ pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, dom);
+ pwf = isl_pw_qpolynomial_fold_bound(pwf, tight);
+
+ return pwf;
+error:
+ isl_map_free(map);
+ isl_pw_qpolynomial_fold_free(pwf);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_set_apply_pw_qpolynomial_fold(
+ __isl_take isl_set *set, __isl_take isl_pw_qpolynomial_fold *pwf,
+ int *tight)
+{
+ return isl_map_apply_pw_qpolynomial_fold(set, pwf, tight);
+}
+
+struct isl_apply_fold_data {
+ isl_union_pw_qpolynomial_fold *upwf;
+ isl_union_pw_qpolynomial_fold *res;
+ isl_map *map;
+ int tight;
+};
+
+static int pw_qpolynomial_fold_apply(__isl_take isl_pw_qpolynomial_fold *pwf,
+ void *user)
+{
+ isl_space *map_dim;
+ isl_space *pwf_dim;
+ struct isl_apply_fold_data *data = user;
+ int ok;
+
+ map_dim = isl_map_get_space(data->map);
+ pwf_dim = isl_pw_qpolynomial_fold_get_space(pwf);
+ ok = join_compatible(map_dim, pwf_dim);
+ isl_space_free(map_dim);
+ isl_space_free(pwf_dim);
+
+ if (ok) {
+ pwf = isl_map_apply_pw_qpolynomial_fold(isl_map_copy(data->map),
+ pwf, data->tight ? &data->tight : NULL);
+ data->res = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+ data->res, pwf);
+ } else
+ isl_pw_qpolynomial_fold_free(pwf);
+
+ return 0;
+}
+
+static int map_apply(__isl_take isl_map *map, void *user)
+{
+ struct isl_apply_fold_data *data = user;
+ int r;
+
+ data->map = map;
+ r = isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
+ data->upwf, &pw_qpolynomial_fold_apply, data);
+
+ isl_map_free(map);
+ return r;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight)
+{
+ isl_space *dim;
+ enum isl_fold type;
+ struct isl_apply_fold_data data;
+
+ upwf = isl_union_pw_qpolynomial_fold_align_params(upwf,
+ isl_union_map_get_space(umap));
+ umap = isl_union_map_align_params(umap,
+ isl_union_pw_qpolynomial_fold_get_space(upwf));
+
+ data.upwf = upwf;
+ data.tight = tight ? 1 : 0;
+ dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
+ type = isl_union_pw_qpolynomial_fold_get_type(upwf);
+ data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);
+ if (isl_union_map_foreach_map(umap, &map_apply, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap);
+ isl_union_pw_qpolynomial_fold_free(upwf);
+
+ if (tight)
+ *tight = data.tight;
+
+ return data.res;
+error:
+ isl_union_map_free(umap);
+ isl_union_pw_qpolynomial_fold_free(upwf);
+ isl_union_pw_qpolynomial_fold_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_set_apply_union_pw_qpolynomial_fold(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight)
+{
+ return isl_union_map_apply_union_pw_qpolynomial_fold(uset, upwf, tight);
+}
+
+/* Reorder the dimension of "fold" according to the given reordering.
+ */
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_realign_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_reordering *r)
+{
+ int i;
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold || !r)
+ goto error;
+
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_realign_domain(fold->qp[i],
+ isl_reordering_copy(r));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ fold = isl_qpolynomial_fold_reset_domain_space(fold,
+ isl_space_copy(r->dim));
+
+ isl_reordering_free(r);
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_mul_isl_int(
+ __isl_take isl_qpolynomial_fold *fold, isl_int v)
+{
+ int i;
+
+ if (isl_int_is_one(v))
+ return fold;
+ if (fold && isl_int_is_zero(v)) {
+ isl_qpolynomial_fold *zero;
+ isl_space *dim = isl_space_copy(fold->dim);
+ zero = isl_qpolynomial_fold_empty(fold->type, dim);
+ isl_qpolynomial_fold_free(fold);
+ return zero;
+ }
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ return NULL;
+
+ if (isl_int_is_neg(v))
+ fold->type = isl_fold_type_negate(fold->type);
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_mul_isl_int(fold->qp[i], v);
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ return fold;
+error:
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale(
+ __isl_take isl_qpolynomial_fold *fold, isl_int v)
+{
+ return isl_qpolynomial_fold_mul_isl_int(fold, v);
+}
+
+/* Multiply "fold" by "v".
+ */
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_val(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v)
+{
+ int i;
+
+ if (!fold || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return fold;
+ }
+ if (isl_val_is_zero(v)) {
+ isl_qpolynomial_fold *zero;
+ isl_space *space = isl_qpolynomial_fold_get_domain_space(fold);
+ zero = isl_qpolynomial_fold_empty(fold->type, space);
+ isl_qpolynomial_fold_free(fold);
+ isl_val_free(v);
+ return zero;
+ }
+ if (!isl_val_is_rat(v))
+ isl_die(isl_qpolynomial_fold_get_ctx(fold), isl_error_invalid,
+ "expecting rational factor", goto error);
+
+ fold = isl_qpolynomial_fold_cow(fold);
+ if (!fold)
+ goto error;
+
+ if (isl_val_is_neg(v))
+ fold->type = isl_fold_type_negate(fold->type);
+ for (i = 0; i < fold->n; ++i) {
+ fold->qp[i] = isl_qpolynomial_scale_val(fold->qp[i],
+ isl_val_copy(v));
+ if (!fold->qp[i])
+ goto error;
+ }
+
+ isl_val_free(v);
+ return fold;
+error:
+ isl_val_free(v);
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
+
+/* Divide "fold" by "v".
+ */
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_down_val(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v)
+{
+ if (!fold || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return fold;
+ }
+ if (!isl_val_is_rat(v))
+ isl_die(isl_qpolynomial_fold_get_ctx(fold), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (isl_val_is_zero(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "cannot scale down by zero", goto error);
+
+ return isl_qpolynomial_fold_scale_val(fold, isl_val_inv(v));
+error:
+ isl_val_free(v);
+ isl_qpolynomial_fold_free(fold);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_gmp.c b/polly/lib/External/isl/isl_gmp.c
new file mode 100644
index 00000000000..d488fd2eb30
--- /dev/null
+++ b/polly/lib/External/isl/isl_gmp.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_int.h>
+
+uint32_t isl_gmp_hash(mpz_t v, uint32_t hash)
+{
+ int sa = v[0]._mp_size;
+ int abs_sa = sa < 0 ? -sa : sa;
+ unsigned char *data = (unsigned char *)v[0]._mp_d;
+ unsigned char *end = data + abs_sa * sizeof(v[0]._mp_d[0]);
+
+ if (sa < 0)
+ isl_hash_byte(hash, 0xFF);
+ for (; data < end; ++data)
+ isl_hash_byte(hash, *data);
+ return hash;
+}
diff --git a/polly/lib/External/isl/isl_hash.c b/polly/lib/External/isl/isl_hash.c
new file mode 100644
index 00000000000..36817d7fb42
--- /dev/null
+++ b/polly/lib/External/isl/isl_hash.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <stdlib.h>
+#include <strings.h>
+#include <isl/hash.h>
+#include <isl/ctx.h>
+#include "isl_config.h"
+
+uint32_t isl_hash_string(uint32_t hash, const char *s)
+{
+ for (; *s; s++)
+ isl_hash_byte(hash, *s);
+ return hash;
+}
+
+uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len)
+{
+ int i;
+ const char *s = p;
+ for (i = 0; i < len; ++i)
+ isl_hash_byte(hash, s[i]);
+ return hash;
+}
+
+static unsigned int round_up(unsigned int v)
+{
+ int old_v = v;
+
+ while (v) {
+ old_v = v;
+ v ^= v & -v;
+ }
+ return old_v << 1;
+}
+
+int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
+ int min_size)
+{
+ size_t size;
+
+ if (!table)
+ return -1;
+
+ if (min_size < 2)
+ min_size = 2;
+ table->bits = ffs(round_up(4 * (min_size + 1) / 3 - 1)) - 1;
+ table->n = 0;
+
+ size = 1 << table->bits;
+ table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
+ size);
+ if (!table->entries)
+ return -1;
+
+ return 0;
+}
+
+/* Dummy comparison function that always returns false.
+ */
+static int no(const void *entry, const void *val)
+{
+ return 0;
+}
+
+/* Extend "table" to twice its size.
+ * Return 0 on success and -1 on error.
+ *
+ * We reuse isl_hash_table_find to create entries in the extended table.
+ * Since all entries in the original table are assumed to be different,
+ * there is no need to compare them against each other.
+ */
+static int grow_table(struct isl_ctx *ctx, struct isl_hash_table *table)
+{
+ int n;
+ size_t old_size, size;
+ struct isl_hash_table_entry *entries;
+ uint32_t h;
+
+ entries = table->entries;
+ old_size = 1 << table->bits;
+ size = 2 * old_size;
+ table->entries = isl_calloc_array(ctx, struct isl_hash_table_entry,
+ size);
+ if (!table->entries) {
+ table->entries = entries;
+ return -1;
+ }
+
+ n = table->n;
+ table->n = 0;
+ table->bits++;
+
+ for (h = 0; h < old_size; ++h) {
+ struct isl_hash_table_entry *entry;
+
+ if (!entries[h].data)
+ continue;
+
+ entry = isl_hash_table_find(ctx, table, entries[h].hash,
+ &no, NULL, 1);
+ if (!entry) {
+ table->bits--;
+ free(table->entries);
+ table->entries = entries;
+ table->n = n;
+ return -1;
+ }
+
+ *entry = entries[h];
+ }
+
+ free(entries);
+
+ return 0;
+}
+
+struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size)
+{
+ struct isl_hash_table *table = NULL;
+
+ table = isl_alloc_type(ctx, struct isl_hash_table);
+ if (isl_hash_table_init(ctx, table, min_size))
+ goto error;
+ return table;
+error:
+ isl_hash_table_free(ctx, table);
+ return NULL;
+}
+
+void isl_hash_table_clear(struct isl_hash_table *table)
+{
+ if (!table)
+ return;
+ free(table->entries);
+}
+
+void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table)
+{
+ if (!table)
+ return;
+ isl_hash_table_clear(table);
+ free(table);
+}
+
+struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ uint32_t key_hash,
+ int (*eq)(const void *entry, const void *val),
+ const void *val, int reserve)
+{
+ size_t size;
+ uint32_t h, key_bits;
+
+ key_bits = isl_hash_bits(key_hash, table->bits);
+ size = 1 << table->bits;
+ for (h = key_bits; table->entries[h].data; h = (h+1) % size)
+ if (table->entries[h].hash == key_hash &&
+ eq(table->entries[h].data, val))
+ return &table->entries[h];
+
+ if (!reserve)
+ return NULL;
+
+ if (4 * table->n >= 3 * size) {
+ if (grow_table(ctx, table) < 0)
+ return NULL;
+ return isl_hash_table_find(ctx, table, key_hash, eq, val, 1);
+ }
+
+ table->n++;
+ table->entries[h].hash = key_hash;
+
+ return &table->entries[h];
+}
+
+int isl_hash_table_foreach(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ int (*fn)(void **entry, void *user), void *user)
+{
+ size_t size;
+ uint32_t h;
+
+ if (!table->entries)
+ return -1;
+
+ size = 1 << table->bits;
+ for (h = 0; h < size; ++ h)
+ if (table->entries[h].data &&
+ fn(&table->entries[h].data, user) < 0)
+ return -1;
+
+ return 0;
+}
+
+void isl_hash_table_remove(struct isl_ctx *ctx,
+ struct isl_hash_table *table,
+ struct isl_hash_table_entry *entry)
+{
+ int h, h2;
+ size_t size;
+
+ if (!table || !entry)
+ return;
+
+ size = 1 << table->bits;
+ h = entry - table->entries;
+ isl_assert(ctx, h >= 0 && h < size, return);
+
+ for (h2 = h+1; table->entries[h2 % size].data; h2++) {
+ uint32_t bits = isl_hash_bits(table->entries[h2 % size].hash,
+ table->bits);
+ uint32_t offset = (size + bits - (h+1)) % size;
+ if (offset <= h2 - (h+1))
+ continue;
+ *entry = table->entries[h2 % size];
+ h = h2;
+ entry = &table->entries[h % size];
+ }
+
+ entry->hash = 0;
+ entry->data = NULL;
+ table->n--;
+}
diff --git a/polly/lib/External/isl/isl_hide_deprecated.h b/polly/lib/External/isl/isl_hide_deprecated.h
new file mode 100644
index 00000000000..006e796f88f
--- /dev/null
+++ b/polly/lib/External/isl/isl_hide_deprecated.h
@@ -0,0 +1,53 @@
+#define isl_aff_get_constant isl_gmp_aff_get_constant
+#define isl_aff_get_coefficient isl_gmp_aff_get_coefficient
+#define isl_aff_get_denominator isl_gmp_aff_get_denominator
+#define isl_aff_set_constant isl_gmp_aff_set_constant
+#define isl_aff_set_coefficient isl_gmp_aff_set_coefficient
+#define isl_aff_set_denominator isl_gmp_aff_set_denominator
+#define isl_aff_add_constant isl_gmp_aff_add_constant
+#define isl_aff_add_constant_num isl_gmp_aff_add_constant_num
+#define isl_aff_add_coefficient isl_gmp_aff_add_coefficient
+#define isl_aff_mod isl_gmp_aff_mod
+#define isl_aff_scale isl_gmp_aff_scale
+#define isl_aff_scale_down isl_gmp_aff_scale_down
+#define isl_pw_aff_mod isl_gmp_pw_aff_mod
+#define isl_pw_aff_scale isl_gmp_pw_aff_scale
+#define isl_pw_aff_scale_down isl_gmp_pw_aff_scale_down
+#define isl_multi_aff_scale isl_gmp_multi_aff_scale
+#define isl_ast_expr_get_int isl_gmp_ast_expr_get_int
+#define isl_constraint_get_constant isl_gmp_constraint_get_constant
+#define isl_constraint_get_coefficient isl_gmp_constraint_get_coefficient
+#define isl_constraint_set_constant isl_gmp_constraint_set_constant
+#define isl_constraint_set_coefficient isl_gmp_constraint_set_coefficient
+#define isl_basic_set_max isl_gmp_basic_set_max
+#define isl_set_min isl_gmp_set_min
+#define isl_set_max isl_gmp_set_max
+#define isl_gmp_hash isl_gmp_gmp_hash
+#define isl_basic_map_plain_is_fixed isl_gmp_basic_map_plain_is_fixed
+#define isl_map_fix isl_gmp_map_fix
+#define isl_map_plain_is_fixed isl_gmp_map_plain_is_fixed
+#define isl_map_fast_is_fixed isl_gmp_map_fast_is_fixed
+#define isl_map_fixed_power isl_gmp_map_fixed_power
+#define isl_mat_get_element isl_gmp_mat_get_element
+#define isl_mat_set_element isl_gmp_mat_set_element
+#define isl_point_get_coordinate isl_gmp_point_get_coordinate
+#define isl_point_set_coordinate isl_gmp_point_set_coordinate
+#define isl_qpolynomial_rat_cst_on_domain isl_gmp_qpolynomial_rat_cst_on_domain
+#define isl_qpolynomial_is_cst isl_gmp_qpolynomial_is_cst
+#define isl_qpolynomial_scale isl_gmp_qpolynomial_scale
+#define isl_term_get_num isl_gmp_term_get_num
+#define isl_term_get_den isl_gmp_term_get_den
+#define isl_qpolynomial_fold_scale isl_gmp_qpolynomial_fold_scale
+#define isl_pw_qpolynomial_fold_fix_dim isl_gmp_pw_qpolynomial_fold_fix_dim
+#define isl_basic_set_fix isl_gmp_basic_set_fix
+#define isl_set_lower_bound isl_gmp_set_lower_bound
+#define isl_set_upper_bound isl_gmp_set_upper_bound
+#define isl_set_fix isl_gmp_set_fix
+#define isl_set_plain_is_fixed isl_gmp_set_plain_is_fixed
+#define isl_union_map_fixed_power isl_gmp_union_map_fixed_power
+#define isl_val_int_from_isl_int isl_gmp_val_int_from_isl_int
+#define isl_val_get_num_isl_int isl_gmp_val_get_num_isl_int
+#define isl_vec_get_element isl_gmp_vec_get_element
+#define isl_vec_set_element isl_gmp_vec_set_element
+#define isl_vec_set isl_gmp_vec_set
+#define isl_vec_fdiv_r isl_gmp_vec_fdiv_r
diff --git a/polly/lib/External/isl/isl_hmap_templ.c b/polly/lib/External/isl/isl_hmap_templ.c
new file mode 100644
index 00000000000..983dfbddcad
--- /dev/null
+++ b/polly/lib/External/isl/isl_hmap_templ.c
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2011 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/ctx.h>
+#include <isl/hash.h>
+
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#define KEY CAT(isl_,KEY_BASE)
+#define VAL CAT(isl_,VAL_BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xHMAP(KEY,VAL_BASE) KEY ## _to_ ## VAL_BASE
+#define yHMAP(KEY,VAL_BASE) xHMAP(KEY,VAL_BASE)
+#define HMAP yHMAP(KEY,VAL_BASE)
+#define HMAP_BASE yHMAP(KEY_BASE,VAL_BASE)
+#define xS(TYPE1,TYPE2,NAME) struct isl_ ## TYPE1 ## _ ## TYPE2 ## _ ## NAME
+#define yS(TYPE1,TYPE2,NAME) xS(TYPE1,TYPE2,NAME)
+#define S(NAME) yS(KEY_BASE,VAL_BASE,NAME)
+
+struct HMAP {
+ int ref;
+ isl_ctx *ctx;
+ struct isl_hash_table table;
+};
+
+S(pair) {
+ KEY *key;
+ VAL *val;
+};
+
+__isl_give HMAP *FN(HMAP,alloc)(isl_ctx *ctx, int min_size)
+{
+ HMAP *hmap;
+
+ hmap = isl_calloc_type(ctx, HMAP);
+ if (!hmap)
+ return NULL;
+
+ hmap->ctx = ctx;
+ isl_ctx_ref(ctx);
+ hmap->ref = 1;
+
+ if (isl_hash_table_init(ctx, &hmap->table, min_size) < 0)
+ return FN(HMAP,free)(hmap);
+
+ return hmap;
+}
+
+static int free_pair(void **entry, void *user)
+{
+ S(pair) *pair = *entry;
+ FN(KEY,free)(pair->key);
+ FN(VAL,free)(pair->val);
+ free(pair);
+ *entry = NULL;
+ return 0;
+}
+
+__isl_null HMAP *FN(HMAP,free)(__isl_take HMAP *hmap)
+{
+ if (!hmap)
+ return NULL;
+ if (--hmap->ref > 0)
+ return NULL;
+ isl_hash_table_foreach(hmap->ctx, &hmap->table, &free_pair, NULL);
+ isl_hash_table_clear(&hmap->table);
+ isl_ctx_deref(hmap->ctx);
+ free(hmap);
+ return NULL;
+}
+
+isl_ctx *FN(HMAP,get_ctx)(__isl_keep HMAP *hmap)
+{
+ return hmap ? hmap->ctx : NULL;
+}
+
+/* Add a mapping from "key" to "val" to the associative array
+ * pointed to by user.
+ */
+static int add_key_val(__isl_take KEY *key, __isl_take VAL *val, void *user)
+{
+ HMAP **hmap = (HMAP **) user;
+
+ *hmap = FN(HMAP,set)(*hmap, key, val);
+
+ if (!*hmap)
+ return -1;
+
+ return 0;
+}
+
+__isl_give HMAP *FN(HMAP,dup)(__isl_keep HMAP *hmap)
+{
+ HMAP *dup;
+
+ if (!hmap)
+ return NULL;
+
+ dup = FN(HMAP,alloc)(hmap->ctx, hmap->table.n);
+ if (FN(HMAP,foreach)(hmap, &add_key_val, &dup) < 0)
+ return FN(HMAP,free)(dup);
+
+ return dup;
+}
+
+__isl_give HMAP *FN(HMAP,cow)(__isl_take HMAP *hmap)
+{
+ if (!hmap)
+ return NULL;
+
+ if (hmap->ref == 1)
+ return hmap;
+ hmap->ref--;
+ return FN(HMAP,dup)(hmap);
+}
+
+__isl_give HMAP *FN(HMAP,copy)(__isl_keep HMAP *hmap)
+{
+ if (!hmap)
+ return NULL;
+
+ hmap->ref++;
+ return hmap;
+}
+
+static int has_key(const void *entry, const void *c_key)
+{
+ const S(pair) *pair = entry;
+ KEY *key = (KEY *) c_key;
+
+ return KEY_EQUAL(pair->key, key);
+}
+
+int FN(HMAP,has)(__isl_keep HMAP *hmap, __isl_keep KEY *key)
+{
+ uint32_t hash;
+
+ if (!hmap)
+ return -1;
+
+ hash = FN(KEY,get_hash)(key);
+ return !!isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 0);
+}
+
+__isl_give VAL *FN(HMAP,get)(__isl_keep HMAP *hmap, __isl_take KEY *key)
+{
+ struct isl_hash_table_entry *entry;
+ S(pair) *pair;
+ uint32_t hash;
+
+ if (!hmap || !key)
+ goto error;
+
+ hash = FN(KEY,get_hash)(key);
+ entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 0);
+ FN(KEY,free)(key);
+
+ if (!entry)
+ return NULL;
+
+ pair = entry->data;
+
+ return FN(VAL,copy)(pair->val);
+error:
+ FN(KEY,free)(key);
+ return NULL;
+}
+
+/* Remove the mapping between "key" and its associated value (if any)
+ * from "hmap".
+ *
+ * If "key" is not mapped to anything, then we leave "hmap" untouched"
+ */
+__isl_give HMAP *FN(HMAP,drop)(__isl_take HMAP *hmap, __isl_take KEY *key)
+{
+ struct isl_hash_table_entry *entry;
+ S(pair) *pair;
+ uint32_t hash;
+
+ if (!hmap || !key)
+ goto error;
+
+ hash = FN(KEY,get_hash)(key);
+ entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 0);
+ if (!entry) {
+ FN(KEY,free)(key);
+ return hmap;
+ }
+
+ hmap = FN(HMAP,cow)(hmap);
+ if (!hmap)
+ goto error;
+ entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 0);
+ FN(KEY,free)(key);
+
+ if (!entry)
+ isl_die(hmap->ctx, isl_error_internal,
+ "missing entry" , goto error);
+
+ pair = entry->data;
+ isl_hash_table_remove(hmap->ctx, &hmap->table, entry);
+ FN(KEY,free)(pair->key);
+ FN(VAL,free)(pair->val);
+ free(pair);
+
+ return hmap;
+error:
+ FN(KEY,free)(key);
+ FN(HMAP,free)(hmap);
+ return NULL;
+}
+
+/* Add a mapping from "key" to "val" to "hmap".
+ * If "key" was already mapped to something else, then that mapping
+ * is replaced.
+ * If key happened to be mapped to "val" already, then we leave
+ * "hmap" untouched.
+ */
+__isl_give HMAP *FN(HMAP,set)(__isl_take HMAP *hmap,
+ __isl_take KEY *key, __isl_take VAL *val)
+{
+ struct isl_hash_table_entry *entry;
+ S(pair) *pair;
+ uint32_t hash;
+
+ if (!hmap || !key || !val)
+ goto error;
+
+ hash = FN(KEY,get_hash)(key);
+ entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 0);
+ if (entry) {
+ int equal;
+ pair = entry->data;
+ equal = VAL_EQUAL(pair->val, val);
+ if (equal < 0)
+ goto error;
+ if (equal) {
+ FN(KEY,free)(key);
+ FN(VAL,free)(val);
+ return hmap;
+ }
+ }
+
+ hmap = FN(HMAP,cow)(hmap);
+ if (!hmap)
+ goto error;
+
+ entry = isl_hash_table_find(hmap->ctx, &hmap->table, hash,
+ &has_key, key, 1);
+
+ if (!entry)
+ goto error;
+
+ if (entry->data) {
+ pair = entry->data;
+ FN(VAL,free)(pair->val);
+ pair->val = val;
+ FN(KEY,free)(key);
+ return hmap;
+ }
+
+ pair = isl_alloc_type(hmap->ctx, S(pair));
+ if (!pair)
+ goto error;
+
+ entry->data = pair;
+ pair->key = key;
+ pair->val = val;
+ return hmap;
+error:
+ FN(KEY,free)(key);
+ FN(VAL,free)(val);
+ return FN(HMAP,free)(hmap);
+}
+
+/* Internal data structure for isl_map_to_basic_set_foreach.
+ *
+ * fn is the function that should be called on each entry.
+ * user is the user-specified final argument to fn.
+ */
+S(foreach_data) {
+ int (*fn)(__isl_take KEY *key, __isl_take VAL *val, void *user);
+ void *user;
+};
+
+/* Call data->fn on a copy of the key and value in *entry.
+ */
+static int call_on_copy(void **entry, void *user)
+{
+ S(pair) *pair = *entry;
+ S(foreach_data) *data = (S(foreach_data) *) user;
+
+ return data->fn(FN(KEY,copy)(pair->key), FN(VAL,copy)(pair->val),
+ data->user);
+}
+
+/* Call "fn" on each pair of key and value in "hmap".
+ */
+int FN(HMAP,foreach)(__isl_keep HMAP *hmap,
+ int (*fn)(__isl_take KEY *key, __isl_take VAL *val, void *user),
+ void *user)
+{
+ S(foreach_data) data = { fn, user };
+
+ if (!hmap)
+ return -1;
+
+ return isl_hash_table_foreach(hmap->ctx, &hmap->table,
+ &call_on_copy, &data);
+}
+
+/* Internal data structure for print_pair.
+ *
+ * p is the printer on which the associative array is being printed.
+ * first is set if the current key-value pair is the first to be printed.
+ */
+S(print_data) {
+ isl_printer *p;
+ int first;
+};
+
+/* Print the given key-value pair to data->p.
+ */
+static int print_pair(__isl_take KEY *key, __isl_take VAL *val, void *user)
+{
+ S(print_data) *data = user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, ", ");
+ data->p = FN(isl_printer_print,KEY_BASE)(data->p, key);
+ data->p = isl_printer_print_str(data->p, ": ");
+ data->p = FN(isl_printer_print,VAL_BASE)(data->p, val);
+ data->first = 0;
+
+ FN(KEY,free)(key);
+ FN(VAL,free)(val);
+ return 0;
+}
+
+/* Print the associative array to "p".
+ */
+__isl_give isl_printer *FN(isl_printer_print,HMAP_BASE)(
+ __isl_take isl_printer *p, __isl_keep HMAP *hmap)
+{
+ S(print_data) data;
+
+ if (!p || !hmap)
+ return isl_printer_free(p);
+
+ p = isl_printer_print_str(p, "{");
+ data.p = p;
+ data.first = 1;
+ if (FN(HMAP,foreach)(hmap, &print_pair, &data) < 0)
+ data.p = isl_printer_free(data.p);
+ p = data.p;
+ p = isl_printer_print_str(p, "}");
+
+ return p;
+}
+
+void FN(HMAP,dump)(__isl_keep HMAP *hmap)
+{
+ isl_printer *printer;
+
+ if (!hmap)
+ return;
+
+ printer = isl_printer_to_file(FN(HMAP,get_ctx)(hmap), stderr);
+ printer = FN(isl_printer_print,HMAP_BASE)(printer, hmap);
+ printer = isl_printer_end_line(printer);
+
+ isl_printer_free(printer);
+}
diff --git a/polly/lib/External/isl/isl_id.c b/polly/lib/External/isl/isl_id.c
new file mode 100644
index 00000000000..6895570e113
--- /dev/null
+++ b/polly/lib/External/isl/isl_id.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <string.h>
+#include <isl_ctx_private.h>
+#include <isl_id_private.h>
+
+#undef BASE
+#define BASE id
+
+#include <isl_list_templ.c>
+
+/* A special, static isl_id to use as domains (and ranges)
+ * of sets and parameters domains.
+ * The user should never get a hold on this isl_id.
+ */
+isl_id isl_id_none = {
+ .ref = -1,
+ .ctx = NULL,
+ .name = "#none",
+ .user = NULL
+};
+
+isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id)
+{
+ return id ? id->ctx : NULL;
+}
+
+void *isl_id_get_user(__isl_keep isl_id *id)
+{
+ return id ? id->user : NULL;
+}
+
+const char *isl_id_get_name(__isl_keep isl_id *id)
+{
+ return id ? id->name : NULL;
+}
+
+static __isl_give isl_id *id_alloc(isl_ctx *ctx, const char *name, void *user)
+{
+ const char *copy = name ? strdup(name) : NULL;
+ isl_id *id;
+
+ if (name && !copy)
+ return NULL;
+ id = isl_calloc_type(ctx, struct isl_id);
+ if (!id)
+ goto error;
+
+ id->ctx = ctx;
+ isl_ctx_ref(id->ctx);
+ id->ref = 1;
+ id->name = copy;
+ id->user = user;
+
+ id->hash = isl_hash_init();
+ if (name)
+ id->hash = isl_hash_string(id->hash, name);
+ else
+ id->hash = isl_hash_builtin(id->hash, user);
+
+ return id;
+error:
+ free((char *)copy);
+ return NULL;
+}
+
+uint32_t isl_id_get_hash(__isl_keep isl_id *id)
+{
+ return id ? id->hash : 0;
+}
+
+struct isl_name_and_user {
+ const char *name;
+ void *user;
+};
+
+static int isl_id_has_name_and_user(const void *entry, const void *val)
+{
+ isl_id *id = (isl_id *)entry;
+ struct isl_name_and_user *nu = (struct isl_name_and_user *) val;
+
+ if (id->user != nu->user)
+ return 0;
+ if (!id->name && !nu->name)
+ return 1;
+
+ return !strcmp(id->name, nu->name);
+}
+
+__isl_give isl_id *isl_id_alloc(isl_ctx *ctx, const char *name, void *user)
+{
+ struct isl_hash_table_entry *entry;
+ uint32_t id_hash;
+ struct isl_name_and_user nu = { name, user };
+
+ if (!ctx)
+ return NULL;
+
+ id_hash = isl_hash_init();
+ if (name)
+ id_hash = isl_hash_string(id_hash, name);
+ else
+ id_hash = isl_hash_builtin(id_hash, user);
+ entry = isl_hash_table_find(ctx, &ctx->id_table, id_hash,
+ isl_id_has_name_and_user, &nu, 1);
+ if (!entry)
+ return NULL;
+ if (entry->data)
+ return isl_id_copy(entry->data);
+ entry->data = id_alloc(ctx, name, user);
+ if (!entry->data)
+ ctx->id_table.n--;
+ return entry->data;
+}
+
+/* If the id has a negative refcount, then it is a static isl_id
+ * which should not be changed.
+ */
+__isl_give isl_id *isl_id_copy(isl_id *id)
+{
+ if (!id)
+ return NULL;
+
+ if (id->ref < 0)
+ return id;
+
+ id->ref++;
+ return id;
+}
+
+/* Compare two isl_ids.
+ *
+ * The order is fairly arbitrary. We do keep the comparison of
+ * the user pointers as a last resort since these pointer values
+ * may not be stable across different systems or even different runs.
+ */
+int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2)
+{
+ if (id1 == id2)
+ return 0;
+ if (!id1)
+ return -1;
+ if (!id2)
+ return 1;
+ if (!id1->name != !id2->name)
+ return !id1->name - !id2->name;
+ if (id1->name) {
+ int cmp = strcmp(id1->name, id2->name);
+ if (cmp != 0)
+ return cmp;
+ }
+ if (id1->user < id2->user)
+ return -1;
+ else
+ return 1;
+}
+
+static int isl_id_eq(const void *entry, const void *name)
+{
+ return entry == name;
+}
+
+uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id)
+{
+ if (id)
+ isl_hash_hash(hash, id->hash);
+
+ return hash;
+}
+
+/* Replace the free_user callback by "free_user".
+ */
+__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,
+ __isl_give void (*free_user)(void *user))
+{
+ if (!id)
+ return NULL;
+
+ id->free_user = free_user;
+
+ return id;
+}
+
+/* If the id has a negative refcount, then it is a static isl_id
+ * and should not be freed.
+ */
+__isl_null isl_id *isl_id_free(__isl_take isl_id *id)
+{
+ struct isl_hash_table_entry *entry;
+
+ if (!id)
+ return NULL;
+
+ if (id->ref < 0)
+ return NULL;
+
+ if (--id->ref > 0)
+ return NULL;
+
+ entry = isl_hash_table_find(id->ctx, &id->ctx->id_table, id->hash,
+ isl_id_eq, id, 0);
+ if (!entry)
+ isl_die(id->ctx, isl_error_unknown,
+ "unable to find id", (void)0);
+ else
+ isl_hash_table_remove(id->ctx, &id->ctx->id_table, entry);
+
+ if (id->free_user)
+ id->free_user(id->user);
+
+ free((char *)id->name);
+ isl_ctx_deref(id->ctx);
+ free(id);
+
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,
+ __isl_keep isl_id *id)
+{
+ if (!id)
+ goto error;
+
+ if (id->name)
+ p = isl_printer_print_str(p, id->name);
+ if (id->user) {
+ char buffer[50];
+ snprintf(buffer, sizeof(buffer), "@%p", id->user);
+ p = isl_printer_print_str(p, buffer);
+ }
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_id_private.h b/polly/lib/External/isl/isl_id_private.h
new file mode 100644
index 00000000000..1d903c8e59e
--- /dev/null
+++ b/polly/lib/External/isl/isl_id_private.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_ID_PRIVATE_H
+#define ISL_ID_PRIVATE_H
+
+#include <isl/id.h>
+
+/* Represent a name and/or user pointer.
+ *
+ * If "free_user" is set, then it will be called on "user" when
+ * the last instance of the isl_id is freed.
+ */
+struct isl_id {
+ int ref;
+ isl_ctx *ctx;
+
+ const char *name;
+ void *user;
+ uint32_t hash;
+
+ __isl_give void (*free_user)(void *user);
+};
+
+#undef EL
+#define EL isl_id
+
+#include <isl_list_templ.h>
+
+uint32_t isl_hash_id(uint32_t hash, __isl_keep isl_id *id);
+int isl_id_cmp(__isl_keep isl_id *id1, __isl_keep isl_id *id2);
+
+extern isl_id isl_id_none;
+
+#endif
diff --git a/polly/lib/External/isl/isl_id_to_ast_expr.c b/polly/lib/External/isl/isl_id_to_ast_expr.c
new file mode 100644
index 00000000000..f8ac7f7c68e
--- /dev/null
+++ b/polly/lib/External/isl/isl_id_to_ast_expr.c
@@ -0,0 +1,11 @@
+#include <isl/id_to_ast_expr.h>
+#include <isl/ast.h>
+
+#define isl_id_is_equal(id1,id2) id1 == id2
+
+#define KEY_BASE id
+#define KEY_EQUAL isl_id_is_equal
+#define VAL_BASE ast_expr
+#define VAL_EQUAL isl_ast_expr_is_equal
+
+#include <isl_hmap_templ.c>
diff --git a/polly/lib/External/isl/isl_id_to_pw_aff.c b/polly/lib/External/isl/isl_id_to_pw_aff.c
new file mode 100644
index 00000000000..2fce240dd30
--- /dev/null
+++ b/polly/lib/External/isl/isl_id_to_pw_aff.c
@@ -0,0 +1,11 @@
+#include <isl/id_to_pw_aff.h>
+#include <isl/aff.h>
+
+#define isl_id_is_equal(id1,id2) id1 == id2
+
+#define KEY_BASE id
+#define KEY_EQUAL isl_id_is_equal
+#define VAL_BASE pw_aff
+#define VAL_EQUAL isl_pw_aff_plain_is_equal
+
+#include <isl_hmap_templ.c>
diff --git a/polly/lib/External/isl/isl_ilp.c b/polly/lib/External/isl/isl_ilp.c
new file mode 100644
index 00000000000..5aec90639fd
--- /dev/null
+++ b/polly/lib/External/isl/isl_ilp.c
@@ -0,0 +1,642 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/ilp.h>
+#include "isl_sample.h"
+#include <isl_seq.h>
+#include "isl_equalities.h"
+#include <isl_aff_private.h>
+#include <isl_local_space_private.h>
+#include <isl_mat_private.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+#include <isl_lp_private.h>
+#include <isl_ilp_private.h>
+#include <isl/deprecated/ilp_int.h>
+
+/* Given a basic set "bset", construct a basic set U such that for
+ * each element x in U, the whole unit box positioned at x is inside
+ * the given basic set.
+ * Note that U may not contain all points that satisfy this property.
+ *
+ * We simply add the sum of all negative coefficients to the constant
+ * term. This ensures that if x satisfies the resulting constraints,
+ * then x plus any sum of unit vectors satisfies the original constraints.
+ */
+static struct isl_basic_set *unit_box_base_points(struct isl_basic_set *bset)
+{
+ int i, j, k;
+ struct isl_basic_set *unit_box = NULL;
+ unsigned total;
+
+ if (!bset)
+ goto error;
+
+ if (bset->n_eq != 0) {
+ unit_box = isl_basic_set_empty_like(bset);
+ isl_basic_set_free(bset);
+ return unit_box;
+ }
+
+ total = isl_basic_set_total_dim(bset);
+ unit_box = isl_basic_set_alloc_space(isl_basic_set_get_space(bset),
+ 0, 0, bset->n_ineq);
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(unit_box);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(unit_box->ineq[k], bset->ineq[i], 1 + total);
+ for (j = 0; j < total; ++j) {
+ if (isl_int_is_nonneg(unit_box->ineq[k][1 + j]))
+ continue;
+ isl_int_add(unit_box->ineq[k][0],
+ unit_box->ineq[k][0], unit_box->ineq[k][1 + j]);
+ }
+ }
+
+ isl_basic_set_free(bset);
+ return unit_box;
+error:
+ isl_basic_set_free(bset);
+ isl_basic_set_free(unit_box);
+ return NULL;
+}
+
+/* Find an integer point in "bset", preferably one that is
+ * close to minimizing "f".
+ *
+ * We first check if we can easily put unit boxes inside bset.
+ * If so, we take the best base point of any of the unit boxes we can find
+ * and round it up to the nearest integer.
+ * If not, we simply pick any integer point in "bset".
+ */
+static struct isl_vec *initial_solution(struct isl_basic_set *bset, isl_int *f)
+{
+ enum isl_lp_result res;
+ struct isl_basic_set *unit_box;
+ struct isl_vec *sol;
+
+ unit_box = unit_box_base_points(isl_basic_set_copy(bset));
+
+ res = isl_basic_set_solve_lp(unit_box, 0, f, bset->ctx->one,
+ NULL, NULL, &sol);
+ if (res == isl_lp_ok) {
+ isl_basic_set_free(unit_box);
+ return isl_vec_ceil(sol);
+ }
+
+ isl_basic_set_free(unit_box);
+
+ return isl_basic_set_sample_vec(isl_basic_set_copy(bset));
+}
+
+/* Restrict "bset" to those points with values for f in the interval [l, u].
+ */
+static struct isl_basic_set *add_bounds(struct isl_basic_set *bset,
+ isl_int *f, isl_int l, isl_int u)
+{
+ int k;
+ unsigned total;
+
+ total = isl_basic_set_total_dim(bset);
+ bset = isl_basic_set_extend_constraints(bset, 0, 2);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->ineq[k], f, 1 + total);
+ isl_int_sub(bset->ineq[k][0], bset->ineq[k][0], l);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_neg(bset->ineq[k], f, 1 + total);
+ isl_int_add(bset->ineq[k][0], bset->ineq[k][0], u);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Find an integer point in "bset" that minimizes f (in any) such that
+ * the value of f lies inside the interval [l, u].
+ * Return this integer point if it can be found.
+ * Otherwise, return sol.
+ *
+ * We perform a number of steps until l > u.
+ * In each step, we look for an integer point with value in either
+ * the whole interval [l, u] or half of the interval [l, l+floor(u-l-1/2)].
+ * The choice depends on whether we have found an integer point in the
+ * previous step. If so, we look for the next point in half of the remaining
+ * interval.
+ * If we find a point, the current solution is updated and u is set
+ * to its value minus 1.
+ * If no point can be found, we update l to the upper bound of the interval
+ * we checked (u or l+floor(u-l-1/2)) plus 1.
+ */
+static struct isl_vec *solve_ilp_search(struct isl_basic_set *bset,
+ isl_int *f, isl_int *opt, struct isl_vec *sol, isl_int l, isl_int u)
+{
+ isl_int tmp;
+ int divide = 1;
+
+ isl_int_init(tmp);
+
+ while (isl_int_le(l, u)) {
+ struct isl_basic_set *slice;
+ struct isl_vec *sample;
+
+ if (!divide)
+ isl_int_set(tmp, u);
+ else {
+ isl_int_sub(tmp, u, l);
+ isl_int_fdiv_q_ui(tmp, tmp, 2);
+ isl_int_add(tmp, tmp, l);
+ }
+ slice = add_bounds(isl_basic_set_copy(bset), f, l, tmp);
+ sample = isl_basic_set_sample_vec(slice);
+ if (!sample) {
+ isl_vec_free(sol);
+ sol = NULL;
+ break;
+ }
+ if (sample->size > 0) {
+ isl_vec_free(sol);
+ sol = sample;
+ isl_seq_inner_product(f, sol->el, sol->size, opt);
+ isl_int_sub_ui(u, *opt, 1);
+ divide = 1;
+ } else {
+ isl_vec_free(sample);
+ if (!divide)
+ break;
+ isl_int_add_ui(l, tmp, 1);
+ divide = 0;
+ }
+ }
+
+ isl_int_clear(tmp);
+
+ return sol;
+}
+
+/* Find an integer point in "bset" that minimizes f (if any).
+ * If sol_p is not NULL then the integer point is returned in *sol_p.
+ * The optimal value of f is returned in *opt.
+ *
+ * The algorithm maintains a currently best solution and an interval [l, u]
+ * of values of f for which integer solutions could potentially still be found.
+ * The initial value of the best solution so far is any solution.
+ * The initial value of l is minimal value of f over the rationals
+ * (rounded up to the nearest integer).
+ * The initial value of u is the value of f at the initial solution minus 1.
+ *
+ * We then call solve_ilp_search to perform a binary search on the interval.
+ */
+static enum isl_lp_result solve_ilp(struct isl_basic_set *bset,
+ isl_int *f, isl_int *opt,
+ struct isl_vec **sol_p)
+{
+ enum isl_lp_result res;
+ isl_int l, u;
+ struct isl_vec *sol;
+
+ res = isl_basic_set_solve_lp(bset, 0, f, bset->ctx->one,
+ opt, NULL, &sol);
+ if (res == isl_lp_ok && isl_int_is_one(sol->el[0])) {
+ if (sol_p)
+ *sol_p = sol;
+ else
+ isl_vec_free(sol);
+ return isl_lp_ok;
+ }
+ isl_vec_free(sol);
+ if (res == isl_lp_error || res == isl_lp_empty)
+ return res;
+
+ sol = initial_solution(bset, f);
+ if (!sol)
+ return isl_lp_error;
+ if (sol->size == 0) {
+ isl_vec_free(sol);
+ return isl_lp_empty;
+ }
+ if (res == isl_lp_unbounded) {
+ isl_vec_free(sol);
+ return isl_lp_unbounded;
+ }
+
+ isl_int_init(l);
+ isl_int_init(u);
+
+ isl_int_set(l, *opt);
+
+ isl_seq_inner_product(f, sol->el, sol->size, opt);
+ isl_int_sub_ui(u, *opt, 1);
+
+ sol = solve_ilp_search(bset, f, opt, sol, l, u);
+ if (!sol)
+ res = isl_lp_error;
+
+ isl_int_clear(l);
+ isl_int_clear(u);
+
+ if (sol_p)
+ *sol_p = sol;
+ else
+ isl_vec_free(sol);
+
+ return res;
+}
+
+static enum isl_lp_result solve_ilp_with_eq(struct isl_basic_set *bset, int max,
+ isl_int *f, isl_int *opt,
+ struct isl_vec **sol_p)
+{
+ unsigned dim;
+ enum isl_lp_result res;
+ struct isl_mat *T = NULL;
+ struct isl_vec *v;
+
+ bset = isl_basic_set_copy(bset);
+ dim = isl_basic_set_total_dim(bset);
+ v = isl_vec_alloc(bset->ctx, 1 + dim);
+ if (!v)
+ goto error;
+ isl_seq_cpy(v->el, f, 1 + dim);
+ bset = isl_basic_set_remove_equalities(bset, &T, NULL);
+ v = isl_vec_mat_product(v, isl_mat_copy(T));
+ if (!v)
+ goto error;
+ res = isl_basic_set_solve_ilp(bset, max, v->el, opt, sol_p);
+ isl_vec_free(v);
+ if (res == isl_lp_ok && sol_p) {
+ *sol_p = isl_mat_vec_product(T, *sol_p);
+ if (!*sol_p)
+ res = isl_lp_error;
+ } else
+ isl_mat_free(T);
+ isl_basic_set_free(bset);
+ return res;
+error:
+ isl_mat_free(T);
+ isl_basic_set_free(bset);
+ return isl_lp_error;
+}
+
+/* Find an integer point in "bset" that minimizes (or maximizes if max is set)
+ * f (if any).
+ * If sol_p is not NULL then the integer point is returned in *sol_p.
+ * The optimal value of f is returned in *opt.
+ *
+ * If there is any equality among the points in "bset", then we first
+ * project it out. Otherwise, we continue with solve_ilp above.
+ */
+enum isl_lp_result isl_basic_set_solve_ilp(struct isl_basic_set *bset, int max,
+ isl_int *f, isl_int *opt,
+ struct isl_vec **sol_p)
+{
+ unsigned dim;
+ enum isl_lp_result res;
+
+ if (!bset)
+ return isl_lp_error;
+ if (sol_p)
+ *sol_p = NULL;
+
+ isl_assert(bset->ctx, isl_basic_set_n_param(bset) == 0, goto error);
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return isl_lp_empty;
+
+ if (bset->n_eq)
+ return solve_ilp_with_eq(bset, max, f, opt, sol_p);
+
+ dim = isl_basic_set_total_dim(bset);
+
+ if (max)
+ isl_seq_neg(f, f, 1 + dim);
+
+ res = solve_ilp(bset, f, opt, sol_p);
+
+ if (max) {
+ isl_seq_neg(f, f, 1 + dim);
+ isl_int_neg(*opt, *opt);
+ }
+
+ return res;
+error:
+ isl_basic_set_free(bset);
+ return isl_lp_error;
+}
+
+static enum isl_lp_result basic_set_opt(__isl_keep isl_basic_set *bset, int max,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ enum isl_lp_result res;
+
+ if (!obj)
+ return isl_lp_error;
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_underlying_set(bset);
+ res = isl_basic_set_solve_ilp(bset, max, obj->v->el + 1, opt, NULL);
+ isl_basic_set_free(bset);
+ return res;
+}
+
+static __isl_give isl_mat *extract_divs(__isl_keep isl_basic_set *bset)
+{
+ int i;
+ isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+ isl_mat *div;
+
+ div = isl_mat_alloc(ctx, bset->n_div,
+ 1 + 1 + isl_basic_set_total_dim(bset));
+ if (!div)
+ return NULL;
+
+ for (i = 0; i < bset->n_div; ++i)
+ isl_seq_cpy(div->row[i], bset->div[i], div->n_col);
+
+ return div;
+}
+
+enum isl_lp_result isl_basic_set_opt(__isl_keep isl_basic_set *bset, int max,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_ctx *ctx;
+ isl_mat *bset_div = NULL;
+ isl_mat *div = NULL;
+ enum isl_lp_result res;
+ int bset_n_div, obj_n_div;
+
+ if (!bset || !obj)
+ return isl_lp_error;
+
+ ctx = isl_aff_get_ctx(obj);
+ if (!isl_space_is_equal(bset->dim, obj->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", return isl_lp_error);
+ if (!isl_int_is_one(obj->v->el[0]))
+ isl_die(ctx, isl_error_unsupported,
+ "expecting integer affine expression",
+ return isl_lp_error);
+
+ bset_n_div = isl_basic_set_dim(bset, isl_dim_div);
+ obj_n_div = isl_aff_dim(obj, isl_dim_div);
+ if (bset_n_div == 0 && obj_n_div == 0)
+ return basic_set_opt(bset, max, obj, opt);
+
+ bset = isl_basic_set_copy(bset);
+ obj = isl_aff_copy(obj);
+
+ bset_div = extract_divs(bset);
+ exp1 = isl_alloc_array(ctx, int, bset_n_div);
+ exp2 = isl_alloc_array(ctx, int, obj_n_div);
+ if (!bset_div || (bset_n_div && !exp1) || (obj_n_div && !exp2))
+ goto error;
+
+ div = isl_merge_divs(bset_div, obj->ls->div, exp1, exp2);
+
+ bset = isl_basic_set_expand_divs(bset, isl_mat_copy(div), exp1);
+ obj = isl_aff_expand_divs(obj, isl_mat_copy(div), exp2);
+
+ res = basic_set_opt(bset, max, obj, opt);
+
+ isl_mat_free(bset_div);
+ isl_mat_free(div);
+ free(exp1);
+ free(exp2);
+ isl_basic_set_free(bset);
+ isl_aff_free(obj);
+
+ return res;
+error:
+ isl_mat_free(div);
+ isl_mat_free(bset_div);
+ free(exp1);
+ free(exp2);
+ isl_basic_set_free(bset);
+ isl_aff_free(obj);
+ return isl_lp_error;
+}
+
+/* Compute the minimum (maximum if max is set) of the integer affine
+ * expression obj over the points in set and put the result in *opt.
+ *
+ * The parameters are assumed to have been aligned.
+ */
+static enum isl_lp_result isl_set_opt_aligned(__isl_keep isl_set *set, int max,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ int i;
+ enum isl_lp_result res;
+ int empty = 1;
+ isl_int opt_i;
+
+ if (!set || !obj)
+ return isl_lp_error;
+ if (set->n == 0)
+ return isl_lp_empty;
+
+ res = isl_basic_set_opt(set->p[0], max, obj, opt);
+ if (res == isl_lp_error || res == isl_lp_unbounded)
+ return res;
+ if (set->n == 1)
+ return res;
+ if (res == isl_lp_ok)
+ empty = 0;
+
+ isl_int_init(opt_i);
+ for (i = 1; i < set->n; ++i) {
+ res = isl_basic_set_opt(set->p[i], max, obj, &opt_i);
+ if (res == isl_lp_error || res == isl_lp_unbounded) {
+ isl_int_clear(opt_i);
+ return res;
+ }
+ if (res == isl_lp_ok)
+ empty = 0;
+ if (max ? isl_int_gt(opt_i, *opt) : isl_int_lt(opt_i, *opt))
+ isl_int_set(*opt, opt_i);
+ }
+ isl_int_clear(opt_i);
+
+ return empty ? isl_lp_empty : isl_lp_ok;
+}
+
+/* Compute the minimum (maximum if max is set) of the integer affine
+ * expression obj over the points in set and put the result in *opt.
+ */
+enum isl_lp_result isl_set_opt(__isl_keep isl_set *set, int max,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ enum isl_lp_result res;
+
+ if (!set || !obj)
+ return isl_lp_error;
+
+ if (isl_space_match(set->dim, isl_dim_param,
+ obj->ls->dim, isl_dim_param))
+ return isl_set_opt_aligned(set, max, obj, opt);
+
+ set = isl_set_copy(set);
+ obj = isl_aff_copy(obj);
+ set = isl_set_align_params(set, isl_aff_get_domain_space(obj));
+ obj = isl_aff_align_params(obj, isl_set_get_space(set));
+
+ res = isl_set_opt_aligned(set, max, obj, opt);
+
+ isl_set_free(set);
+ isl_aff_free(obj);
+
+ return res;
+}
+
+enum isl_lp_result isl_basic_set_max(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ return isl_basic_set_opt(bset, 1, obj, opt);
+}
+
+enum isl_lp_result isl_set_max(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ return isl_set_opt(set, 1, obj, opt);
+}
+
+enum isl_lp_result isl_set_min(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj, isl_int *opt)
+{
+ return isl_set_opt(set, 0, obj, opt);
+}
+
+/* Convert the result of a function that returns an isl_lp_result
+ * to an isl_val. The numerator of "v" is set to the optimal value
+ * if lp_res is isl_lp_ok. "max" is set if a maximum was computed.
+ *
+ * Return "v" with denominator set to 1 if lp_res is isl_lp_ok.
+ * Return NULL on error.
+ * Return a NaN if lp_res is isl_lp_empty.
+ * Return infinity or negative infinity if lp_res is isl_lp_unbounded,
+ * depending on "max".
+ */
+static __isl_give isl_val *convert_lp_result(enum isl_lp_result lp_res,
+ __isl_take isl_val *v, int max)
+{
+ isl_ctx *ctx;
+
+ if (lp_res == isl_lp_ok) {
+ isl_int_set_si(v->d, 1);
+ return isl_val_normalize(v);
+ }
+ ctx = isl_val_get_ctx(v);
+ isl_val_free(v);
+ if (lp_res == isl_lp_error)
+ return NULL;
+ if (lp_res == isl_lp_empty)
+ return isl_val_nan(ctx);
+ if (max)
+ return isl_val_infty(ctx);
+ else
+ return isl_val_neginfty(ctx);
+}
+
+/* Return the minimum (maximum if max is set) of the integer affine
+ * expression "obj" over the points in "bset".
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ *
+ * Call isl_basic_set_opt and translate the results.
+ */
+__isl_give isl_val *isl_basic_set_opt_val(__isl_keep isl_basic_set *bset,
+ int max, __isl_keep isl_aff *obj)
+{
+ isl_ctx *ctx;
+ isl_val *res;
+ enum isl_lp_result lp_res;
+
+ if (!bset || !obj)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(obj);
+ res = isl_val_alloc(ctx);
+ if (!res)
+ return NULL;
+ lp_res = isl_basic_set_opt(bset, max, obj, &res->n);
+ return convert_lp_result(lp_res, res, max);
+}
+
+/* Return the maximum of the integer affine
+ * expression "obj" over the points in "bset".
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+__isl_give isl_val *isl_basic_set_max_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj)
+{
+ return isl_basic_set_opt_val(bset, 1, obj);
+}
+
+/* Return the minimum (maximum if max is set) of the integer affine
+ * expression "obj" over the points in "set".
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ *
+ * Call isl_set_opt and translate the results.
+ */
+__isl_give isl_val *isl_set_opt_val(__isl_keep isl_set *set, int max,
+ __isl_keep isl_aff *obj)
+{
+ isl_ctx *ctx;
+ isl_val *res;
+ enum isl_lp_result lp_res;
+
+ if (!set || !obj)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(obj);
+ res = isl_val_alloc(ctx);
+ if (!res)
+ return NULL;
+ lp_res = isl_set_opt(set, max, obj, &res->n);
+ return convert_lp_result(lp_res, res, max);
+}
+
+/* Return the minimum of the integer affine
+ * expression "obj" over the points in "set".
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+__isl_give isl_val *isl_set_min_val(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj)
+{
+ return isl_set_opt_val(set, 0, obj);
+}
+
+/* Return the maximum of the integer affine
+ * expression "obj" over the points in "set".
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+__isl_give isl_val *isl_set_max_val(__isl_keep isl_set *set,
+ __isl_keep isl_aff *obj)
+{
+ return isl_set_opt_val(set, 1, obj);
+}
diff --git a/polly/lib/External/isl/isl_ilp_private.h b/polly/lib/External/isl/isl_ilp_private.h
new file mode 100644
index 00000000000..932b2c3d4f2
--- /dev/null
+++ b/polly/lib/External/isl/isl_ilp_private.h
@@ -0,0 +1,11 @@
+#ifndef ISL_ILP_PRIVATE_H
+#define ISL_ILP_PRIVATE_H
+
+#include <isl_int.h>
+#include <isl/lp.h>
+#include <isl/set.h>
+
+enum isl_lp_result isl_basic_set_solve_ilp(__isl_keep isl_basic_set *bset,
+ int max, isl_int *f, isl_int *opt, __isl_give isl_vec **sol_p);
+
+#endif
diff --git a/polly/lib/External/isl/isl_imath.c b/polly/lib/External/isl/isl_imath.c
new file mode 100644
index 00000000000..959b5e78272
--- /dev/null
+++ b/polly/lib/External/isl/isl_imath.c
@@ -0,0 +1,53 @@
+#include <isl_int.h>
+
+uint32_t isl_imath_hash(mp_int v, uint32_t hash)
+{
+ unsigned const char *data = (unsigned char *)v->digits;
+ unsigned const char *end = data + v->used * sizeof(v->digits[0]);
+
+ if (v->sign == 1)
+ isl_hash_byte(hash, 0xFF);
+ for (; data < end; ++data)
+ isl_hash_byte(hash, *data);
+ return hash;
+}
+
+/* Try a standard conversion that fits into a long.
+ */
+int isl_imath_fits_slong_p(mp_int op)
+{
+ unsigned long out;
+ mp_result res = mp_int_to_int(op, &out);
+ return res == MP_OK;
+}
+
+/* Try a standard conversion that fits into an unsigned long.
+ */
+int isl_imath_fits_ulong_p(mp_int op)
+{
+ unsigned long out;
+ mp_result res = mp_int_to_uint(op, &out);
+ return res == MP_OK;
+}
+
+void isl_imath_addmul_ui(mp_int rop, mp_int op1, unsigned long op2)
+{
+ isl_int temp;
+ isl_int_init(temp);
+
+ isl_int_set_ui(temp, op2);
+ isl_int_addmul(rop, op1, temp);
+
+ isl_int_clear(temp);
+}
+
+void isl_imath_submul_ui(mp_int rop, mp_int op1, unsigned long op2)
+{
+ isl_int temp;
+ isl_int_init(temp);
+
+ isl_int_set_ui(temp, op2);
+ isl_int_submul(rop, op1, temp);
+
+ isl_int_clear(temp);
+}
diff --git a/polly/lib/External/isl/isl_imath.h b/polly/lib/External/isl/isl_imath.h
new file mode 100644
index 00000000000..d51e03cb1fd
--- /dev/null
+++ b/polly/lib/External/isl/isl_imath.h
@@ -0,0 +1,8 @@
+#include <imath.h>
+#include <gmp_compat.h>
+
+uint32_t isl_imath_hash(mp_int v, uint32_t hash);
+int isl_imath_fits_ulong_p(mp_int op);
+int isl_imath_fits_slong_p(mp_int op);
+void isl_imath_addmul_ui(mp_int rop, mp_int op1, unsigned long op2);
+void isl_imath_submul_ui(mp_int rop, mp_int op1, unsigned long op2);
diff --git a/polly/lib/External/isl/isl_input.c b/polly/lib/External/isl/isl_input.c
new file mode 100644
index 00000000000..520e7f45c19
--- /dev/null
+++ b/polly/lib/External/isl/isl_input.c
@@ -0,0 +1,3370 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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 <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_stream_private.h>
+#include <isl/obj.h>
+#include "isl_polynomial_private.h"
+#include <isl/union_map.h>
+#include <isl_mat_private.h>
+#include <isl_aff_private.h>
+#include <isl_vec_private.h>
+#include <isl/list.h>
+#include <isl_val_private.h>
+
+struct variable {
+ char *name;
+ int pos;
+ struct variable *next;
+};
+
+struct vars {
+ struct isl_ctx *ctx;
+ int n;
+ struct variable *v;
+};
+
+static struct vars *vars_new(struct isl_ctx *ctx)
+{
+ struct vars *v;
+ v = isl_alloc_type(ctx, struct vars);
+ if (!v)
+ return NULL;
+ v->ctx = ctx;
+ v->n = 0;
+ v->v = NULL;
+ return v;
+}
+
+static void variable_free(struct variable *var)
+{
+ while (var) {
+ struct variable *next = var->next;
+ free(var->name);
+ free(var);
+ var = next;
+ }
+}
+
+static void vars_free(struct vars *v)
+{
+ if (!v)
+ return;
+ variable_free(v->v);
+ free(v);
+}
+
+static void vars_drop(struct vars *v, int n)
+{
+ struct variable *var;
+
+ if (!v || !v->v)
+ return;
+
+ v->n -= n;
+
+ var = v->v;
+ while (--n >= 0) {
+ struct variable *next = var->next;
+ free(var->name);
+ free(var);
+ var = next;
+ }
+ v->v = var;
+}
+
+static struct variable *variable_new(struct vars *v, const char *name, int len,
+ int pos)
+{
+ struct variable *var;
+ var = isl_calloc_type(v->ctx, struct variable);
+ if (!var)
+ goto error;
+ var->name = strdup(name);
+ var->name[len] = '\0';
+ var->pos = pos;
+ var->next = v->v;
+ return var;
+error:
+ variable_free(v->v);
+ return NULL;
+}
+
+static int vars_pos(struct vars *v, const char *s, int len)
+{
+ int pos;
+ struct variable *q;
+
+ if (len == -1)
+ len = strlen(s);
+ for (q = v->v; q; q = q->next) {
+ if (strncmp(q->name, s, len) == 0 && q->name[len] == '\0')
+ break;
+ }
+ if (q)
+ pos = q->pos;
+ else {
+ pos = v->n;
+ v->v = variable_new(v, s, len, v->n);
+ if (!v->v)
+ return -1;
+ v->n++;
+ }
+ return pos;
+}
+
+static int vars_add_anon(struct vars *v)
+{
+ v->v = variable_new(v, "", 0, v->n);
+
+ if (!v->v)
+ return -1;
+ v->n++;
+
+ return 0;
+}
+
+/* Obtain next token, with some preprocessing.
+ * In particular, evaluate expressions of the form x^y,
+ * with x and y values.
+ */
+static struct isl_token *next_token(struct isl_stream *s)
+{
+ struct isl_token *tok, *tok2;
+
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE)
+ return tok;
+ if (!isl_stream_eat_if_available(s, '^'))
+ return tok;
+ tok2 = isl_stream_next_token(s);
+ if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok2, "expecting constant value");
+ goto error;
+ }
+
+ isl_int_pow_ui(tok->u.v, tok->u.v, isl_int_get_ui(tok2->u.v));
+
+ isl_token_free(tok2);
+ return tok;
+error:
+ isl_token_free(tok);
+ isl_token_free(tok2);
+ return NULL;
+}
+
+/* Read an isl_val from "s".
+ *
+ * The following token sequences are recognized
+ *
+ * "infty" -> infty
+ * "-" "infty" -> -infty
+ * "NaN" -> NaN
+ * n "/" d -> n/d
+ * v -> v
+ *
+ * where n, d and v are integer constants.
+ */
+__isl_give isl_val *isl_stream_read_val(struct isl_stream *s)
+{
+ struct isl_token *tok = NULL;
+ struct isl_token *tok2 = NULL;
+ isl_val *val;
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok->type == ISL_TOKEN_INFTY) {
+ isl_token_free(tok);
+ return isl_val_infty(s->ctx);
+ }
+ if (tok->type == '-' &&
+ isl_stream_eat_if_available(s, ISL_TOKEN_INFTY)) {
+ isl_token_free(tok);
+ return isl_val_neginfty(s->ctx);
+ }
+ if (tok->type == ISL_TOKEN_NAN) {
+ isl_token_free(tok);
+ return isl_val_nan(s->ctx);
+ }
+ if (tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting value");
+ goto error;
+ }
+
+ if (isl_stream_eat_if_available(s, '/')) {
+ tok2 = next_token(s);
+ if (!tok2) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok2->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok2, "expecting value");
+ goto error;
+ }
+ val = isl_val_rat_from_isl_int(s->ctx, tok->u.v, tok2->u.v);
+ val = isl_val_normalize(val);
+ } else {
+ val = isl_val_int_from_isl_int(s->ctx, tok->u.v);
+ }
+
+ isl_token_free(tok);
+ isl_token_free(tok2);
+ return val;
+error:
+ isl_token_free(tok);
+ isl_token_free(tok2);
+ return NULL;
+}
+
+/* Read an isl_val from "str".
+ */
+struct isl_val *isl_val_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ isl_val *val;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ val = isl_stream_read_val(s);
+ isl_stream_free(s);
+ return val;
+}
+
+static int accept_cst_factor(struct isl_stream *s, isl_int *f)
+{
+ struct isl_token *tok;
+
+ tok = next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting constant value");
+ goto error;
+ }
+
+ isl_int_mul(*f, *f, tok->u.v);
+
+ isl_token_free(tok);
+
+ if (isl_stream_eat_if_available(s, '*'))
+ return accept_cst_factor(s, f);
+
+ return 0;
+error:
+ isl_token_free(tok);
+ return -1;
+}
+
+/* Given an affine expression aff, return an affine expression
+ * for aff % d, with d the next token on the stream, which is
+ * assumed to be a constant.
+ *
+ * We introduce an integer division q = [aff/d] and the result
+ * is set to aff - d q.
+ */
+static __isl_give isl_pw_aff *affine_mod(struct isl_stream *s,
+ struct vars *v, __isl_take isl_pw_aff *aff)
+{
+ struct isl_token *tok;
+ isl_pw_aff *q;
+
+ tok = next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting constant value");
+ goto error;
+ }
+
+ q = isl_pw_aff_copy(aff);
+ q = isl_pw_aff_scale_down(q, tok->u.v);
+ q = isl_pw_aff_floor(q);
+ q = isl_pw_aff_scale(q, tok->u.v);
+
+ aff = isl_pw_aff_sub(aff, q);
+
+ isl_token_free(tok);
+ return aff;
+error:
+ isl_pw_aff_free(aff);
+ isl_token_free(tok);
+ return NULL;
+}
+
+static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s,
+ __isl_take isl_space *space, struct vars *v);
+static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v);
+
+static __isl_give isl_pw_aff *accept_minmax(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v)
+{
+ struct isl_token *tok;
+ isl_pw_aff_list *list = NULL;
+ int min;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ min = tok->type == ISL_TOKEN_MIN;
+ isl_token_free(tok);
+
+ if (isl_stream_eat(s, '('))
+ goto error;
+
+ list = accept_affine_list(s, isl_space_copy(dim), v);
+ if (!list)
+ goto error;
+
+ if (isl_stream_eat(s, ')'))
+ goto error;
+
+ isl_space_free(dim);
+ return min ? isl_pw_aff_list_min(list) : isl_pw_aff_list_max(list);
+error:
+ isl_space_free(dim);
+ isl_pw_aff_list_free(list);
+ return NULL;
+}
+
+/* Is "tok" the start of an integer division?
+ */
+static int is_start_of_div(struct isl_token *tok)
+{
+ if (!tok)
+ return 0;
+ if (tok->type == '[')
+ return 1;
+ if (tok->type == ISL_TOKEN_FLOOR)
+ return 1;
+ if (tok->type == ISL_TOKEN_CEIL)
+ return 1;
+ if (tok->type == ISL_TOKEN_FLOORD)
+ return 1;
+ if (tok->type == ISL_TOKEN_CEILD)
+ return 1;
+ return 0;
+}
+
+/* Read an integer division from "s" and return it as an isl_pw_aff.
+ *
+ * The integer division can be of the form
+ *
+ * [<affine expression>]
+ * floor(<affine expression>)
+ * ceil(<affine expression>)
+ * floord(<affine expression>,<denominator>)
+ * ceild(<affine expression>,<denominator>)
+ */
+static __isl_give isl_pw_aff *accept_div(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v)
+{
+ struct isl_token *tok;
+ int f = 0;
+ int c = 0;
+ int extra = 0;
+ isl_pw_aff *pwaff = NULL;
+
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOORD))
+ extra = f = 1;
+ else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEILD))
+ extra = c = 1;
+ else if (isl_stream_eat_if_available(s, ISL_TOKEN_FLOOR))
+ f = 1;
+ else if (isl_stream_eat_if_available(s, ISL_TOKEN_CEIL))
+ c = 1;
+ if (f || c) {
+ if (isl_stream_eat(s, '('))
+ goto error;
+ } else {
+ if (isl_stream_eat(s, '['))
+ goto error;
+ }
+
+ pwaff = accept_affine(s, isl_space_copy(dim), v);
+
+ if (extra) {
+ if (isl_stream_eat(s, ','))
+ goto error;
+
+ tok = next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expected denominator");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ isl_pw_aff_scale_down(pwaff, tok->u.v);
+ isl_token_free(tok);
+ }
+
+ if (c)
+ pwaff = isl_pw_aff_ceil(pwaff);
+ else
+ pwaff = isl_pw_aff_floor(pwaff);
+
+ if (f || c) {
+ if (isl_stream_eat(s, ')'))
+ goto error;
+ } else {
+ if (isl_stream_eat(s, ']'))
+ goto error;
+ }
+
+ isl_space_free(dim);
+ return pwaff;
+error:
+ isl_space_free(dim);
+ isl_pw_aff_free(pwaff);
+ return NULL;
+}
+
+static __isl_give isl_pw_aff *accept_affine_factor(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v)
+{
+ struct isl_token *tok = NULL;
+ isl_pw_aff *res = NULL;
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+
+ if (tok->type == ISL_TOKEN_AFF) {
+ res = isl_pw_aff_copy(tok->u.pwaff);
+ isl_token_free(tok);
+ } else if (tok->type == ISL_TOKEN_IDENT) {
+ int n = v->n;
+ int pos = vars_pos(v, tok->u.s, -1);
+ isl_aff *aff;
+
+ if (pos < 0)
+ goto error;
+ if (pos >= n) {
+ vars_drop(v, v->n - n);
+ isl_stream_error(s, tok, "unknown identifier");
+ goto error;
+ }
+
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(isl_space_copy(dim)));
+ if (!aff)
+ goto error;
+ isl_int_set_si(aff->v->el[2 + pos], 1);
+ res = isl_pw_aff_from_aff(aff);
+ isl_token_free(tok);
+ } else if (tok->type == ISL_TOKEN_VALUE) {
+ if (isl_stream_eat_if_available(s, '*')) {
+ res = accept_affine_factor(s, isl_space_copy(dim), v);
+ res = isl_pw_aff_scale(res, tok->u.v);
+ } else {
+ isl_local_space *ls;
+ isl_aff *aff;
+ ls = isl_local_space_from_space(isl_space_copy(dim));
+ aff = isl_aff_zero_on_domain(ls);
+ aff = isl_aff_add_constant(aff, tok->u.v);
+ res = isl_pw_aff_from_aff(aff);
+ }
+ isl_token_free(tok);
+ } else if (tok->type == '(') {
+ isl_token_free(tok);
+ tok = NULL;
+ res = accept_affine(s, isl_space_copy(dim), v);
+ if (!res)
+ goto error;
+ if (isl_stream_eat(s, ')'))
+ goto error;
+ } else if (is_start_of_div(tok)) {
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ res = accept_div(s, isl_space_copy(dim), v);
+ } else if (tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX) {
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ res = accept_minmax(s, isl_space_copy(dim), v);
+ } else {
+ isl_stream_error(s, tok, "expecting factor");
+ goto error;
+ }
+ if (isl_stream_eat_if_available(s, '%') ||
+ isl_stream_eat_if_available(s, ISL_TOKEN_MOD)) {
+ isl_space_free(dim);
+ return affine_mod(s, v, res);
+ }
+ if (isl_stream_eat_if_available(s, '*')) {
+ isl_int f;
+ isl_int_init(f);
+ isl_int_set_si(f, 1);
+ if (accept_cst_factor(s, &f) < 0) {
+ isl_int_clear(f);
+ goto error2;
+ }
+ res = isl_pw_aff_scale(res, f);
+ isl_int_clear(f);
+ }
+ if (isl_stream_eat_if_available(s, '/')) {
+ isl_int f;
+ isl_int_init(f);
+ isl_int_set_si(f, 1);
+ if (accept_cst_factor(s, &f) < 0) {
+ isl_int_clear(f);
+ goto error2;
+ }
+ res = isl_pw_aff_scale_down(res, f);
+ isl_int_clear(f);
+ }
+
+ isl_space_free(dim);
+ return res;
+error:
+ isl_token_free(tok);
+error2:
+ isl_pw_aff_free(res);
+ isl_space_free(dim);
+ return NULL;
+}
+
+static __isl_give isl_pw_aff *add_cst(__isl_take isl_pw_aff *pwaff, isl_int v)
+{
+ isl_aff *aff;
+ isl_space *space;
+
+ space = isl_pw_aff_get_domain_space(pwaff);
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+ aff = isl_aff_add_constant(aff, v);
+
+ return isl_pw_aff_add(pwaff, isl_pw_aff_from_aff(aff));
+}
+
+/* Return a piecewise affine expression defined on the specified domain
+ * that represents NaN.
+ */
+static __isl_give isl_pw_aff *nan_on_domain(__isl_keep isl_space *space)
+{
+ isl_local_space *ls;
+
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ return isl_pw_aff_nan_on_domain(ls);
+}
+
+static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s,
+ __isl_take isl_space *space, struct vars *v)
+{
+ struct isl_token *tok = NULL;
+ isl_local_space *ls;
+ isl_pw_aff *res;
+ int sign = 1;
+
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ res = isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
+ if (!res)
+ goto error;
+
+ for (;;) {
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok->type == '-') {
+ sign = -sign;
+ isl_token_free(tok);
+ continue;
+ }
+ if (tok->type == '(' || is_start_of_div(tok) ||
+ tok->type == ISL_TOKEN_MIN || tok->type == ISL_TOKEN_MAX ||
+ tok->type == ISL_TOKEN_IDENT ||
+ tok->type == ISL_TOKEN_AFF) {
+ isl_pw_aff *term;
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ term = accept_affine_factor(s,
+ isl_space_copy(space), v);
+ if (sign < 0)
+ res = isl_pw_aff_sub(res, term);
+ else
+ res = isl_pw_aff_add(res, term);
+ if (!res)
+ goto error;
+ sign = 1;
+ } else if (tok->type == ISL_TOKEN_VALUE) {
+ if (sign < 0)
+ isl_int_neg(tok->u.v, tok->u.v);
+ if (isl_stream_eat_if_available(s, '*') ||
+ isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
+ isl_pw_aff *term;
+ term = accept_affine_factor(s,
+ isl_space_copy(space), v);
+ term = isl_pw_aff_scale(term, tok->u.v);
+ res = isl_pw_aff_add(res, term);
+ if (!res)
+ goto error;
+ } else {
+ res = add_cst(res, tok->u.v);
+ }
+ sign = 1;
+ } else if (tok->type == ISL_TOKEN_NAN) {
+ res = isl_pw_aff_add(res, nan_on_domain(space));
+ } else {
+ isl_stream_error(s, tok, "unexpected isl_token");
+ isl_stream_push_token(s, tok);
+ isl_pw_aff_free(res);
+ isl_space_free(space);
+ return NULL;
+ }
+ isl_token_free(tok);
+
+ tok = next_token(s);
+ if (tok && tok->type == '-') {
+ sign = -sign;
+ isl_token_free(tok);
+ } else if (tok && tok->type == '+') {
+ /* nothing */
+ isl_token_free(tok);
+ } else if (tok && tok->type == ISL_TOKEN_VALUE &&
+ isl_int_is_neg(tok->u.v)) {
+ isl_stream_push_token(s, tok);
+ } else {
+ if (tok)
+ isl_stream_push_token(s, tok);
+ break;
+ }
+ }
+
+ isl_space_free(space);
+ return res;
+error:
+ isl_space_free(space);
+ isl_token_free(tok);
+ isl_pw_aff_free(res);
+ return NULL;
+}
+
+static int is_comparator(struct isl_token *tok)
+{
+ if (!tok)
+ return 0;
+
+ switch (tok->type) {
+ case ISL_TOKEN_LT:
+ case ISL_TOKEN_GT:
+ case ISL_TOKEN_LE:
+ case ISL_TOKEN_GE:
+ case ISL_TOKEN_NE:
+ case '=':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static __isl_give isl_map *read_formula(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational);
+static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v, int rational);
+
+/* Accept a ternary operator, given the first argument.
+ */
+static __isl_give isl_pw_aff *accept_ternary(struct isl_stream *s,
+ __isl_take isl_map *cond, struct vars *v, int rational)
+{
+ isl_space *dim;
+ isl_pw_aff *pwaff1 = NULL, *pwaff2 = NULL, *pa_cond;
+
+ if (!cond)
+ return NULL;
+
+ if (isl_stream_eat(s, '?'))
+ goto error;
+
+ dim = isl_space_wrap(isl_map_get_space(cond));
+ pwaff1 = accept_extended_affine(s, dim, v, rational);
+ if (!pwaff1)
+ goto error;
+
+ if (isl_stream_eat(s, ':'))
+ goto error;
+
+ dim = isl_pw_aff_get_domain_space(pwaff1);
+ pwaff2 = accept_extended_affine(s, dim, v, rational);
+ if (!pwaff1)
+ goto error;
+
+ pa_cond = isl_set_indicator_function(isl_map_wrap(cond));
+ return isl_pw_aff_cond(pa_cond, pwaff1, pwaff2);
+error:
+ isl_map_free(cond);
+ isl_pw_aff_free(pwaff1);
+ isl_pw_aff_free(pwaff2);
+ return NULL;
+}
+
+/* Set *line and *col to those of the next token, if any.
+ */
+static void set_current_line_col(struct isl_stream *s, int *line, int *col)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return;
+
+ *line = tok->line;
+ *col = tok->col;
+ isl_stream_push_token(s, tok);
+}
+
+/* Push a token encapsulating "pa" onto "s", with the given
+ * line and column.
+ */
+static int push_aff(struct isl_stream *s, int line, int col,
+ __isl_take isl_pw_aff *pa)
+{
+ struct isl_token *tok;
+
+ tok = isl_token_new(s->ctx, line, col, 0);
+ if (!tok)
+ goto error;
+ tok->type = ISL_TOKEN_AFF;
+ tok->u.pwaff = pa;
+ isl_stream_push_token(s, tok);
+
+ return 0;
+error:
+ isl_pw_aff_free(pa);
+ return -1;
+}
+
+/* Accept an affine expression that may involve ternary operators.
+ * We first read an affine expression.
+ * If it is not followed by a comparison operator, we simply return it.
+ * Otherwise, we assume the affine expression is part of the first
+ * argument of a ternary operator and try to parse that.
+ */
+static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v, int rational)
+{
+ isl_space *space;
+ isl_map *cond;
+ isl_pw_aff *pwaff;
+ struct isl_token *tok;
+ int line = -1, col = -1;
+ int is_comp;
+
+ set_current_line_col(s, &line, &col);
+
+ pwaff = accept_affine(s, dim, v);
+ if (rational)
+ pwaff = isl_pw_aff_set_rational(pwaff);
+ if (!pwaff)
+ return NULL;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return isl_pw_aff_free(pwaff);
+
+ is_comp = is_comparator(tok);
+ isl_stream_push_token(s, tok);
+ if (!is_comp)
+ return pwaff;
+
+ space = isl_pw_aff_get_domain_space(pwaff);
+ cond = isl_map_universe(isl_space_unwrap(space));
+
+ if (push_aff(s, line, col, pwaff) < 0)
+ cond = isl_map_free(cond);
+ if (!cond)
+ return NULL;
+
+ cond = read_formula(s, v, cond, rational);
+
+ return accept_ternary(s, cond, v, rational);
+}
+
+static __isl_give isl_map *read_var_def(struct isl_stream *s,
+ __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
+ int rational)
+{
+ isl_pw_aff *def;
+ int pos;
+ isl_map *def_map;
+
+ if (type == isl_dim_param)
+ pos = isl_map_dim(map, isl_dim_param);
+ else {
+ pos = isl_map_dim(map, isl_dim_in);
+ if (type == isl_dim_out)
+ pos += isl_map_dim(map, isl_dim_out);
+ type = isl_dim_in;
+ }
+ --pos;
+
+ def = accept_extended_affine(s, isl_space_wrap(isl_map_get_space(map)),
+ v, rational);
+ def_map = isl_map_from_pw_aff(def);
+ def_map = isl_map_equate(def_map, type, pos, isl_dim_out, 0);
+ def_map = isl_set_unwrap(isl_map_domain(def_map));
+
+ map = isl_map_intersect(map, def_map);
+
+ return map;
+}
+
+static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s,
+ __isl_take isl_space *dim, struct vars *v)
+{
+ isl_pw_aff *pwaff;
+ isl_pw_aff_list *list;
+ struct isl_token *tok = NULL;
+
+ pwaff = accept_affine(s, isl_space_copy(dim), v);
+ list = isl_pw_aff_list_from_pw_aff(pwaff);
+ if (!list)
+ goto error;
+
+ for (;;) {
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok->type != ',') {
+ isl_stream_push_token(s, tok);
+ break;
+ }
+ isl_token_free(tok);
+
+ pwaff = accept_affine(s, isl_space_copy(dim), v);
+ list = isl_pw_aff_list_concat(list,
+ isl_pw_aff_list_from_pw_aff(pwaff));
+ if (!list)
+ goto error;
+ }
+
+ isl_space_free(dim);
+ return list;
+error:
+ isl_space_free(dim);
+ isl_pw_aff_list_free(list);
+ return NULL;
+}
+
+static __isl_give isl_map *read_defined_var_list(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ struct isl_token *tok;
+
+ while ((tok = isl_stream_next_token(s)) != NULL) {
+ int p;
+ int n = v->n;
+
+ if (tok->type != ISL_TOKEN_IDENT)
+ break;
+
+ p = vars_pos(v, tok->u.s, -1);
+ if (p < 0)
+ goto error;
+ if (p < n) {
+ isl_stream_error(s, tok, "expecting unique identifier");
+ goto error;
+ }
+
+ map = isl_map_add_dims(map, isl_dim_out, 1);
+
+ isl_token_free(tok);
+ tok = isl_stream_next_token(s);
+ if (tok && tok->type == '=') {
+ isl_token_free(tok);
+ map = read_var_def(s, map, isl_dim_out, v, rational);
+ tok = isl_stream_next_token(s);
+ }
+
+ if (!tok || tok->type != ',')
+ break;
+
+ isl_token_free(tok);
+ }
+ if (tok)
+ isl_stream_push_token(s, tok);
+
+ return map;
+error:
+ isl_token_free(tok);
+ isl_map_free(map);
+ return NULL;
+}
+
+static int next_is_tuple(struct isl_stream *s)
+{
+ struct isl_token *tok;
+ int is_tuple;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type == '[') {
+ isl_stream_push_token(s, tok);
+ return 1;
+ }
+ if (tok->type != ISL_TOKEN_IDENT && !tok->is_keyword) {
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+
+ is_tuple = isl_stream_next_token_is(s, '[');
+
+ isl_stream_push_token(s, tok);
+
+ return is_tuple;
+}
+
+/* Allocate an initial tuple with zero dimensions and an anonymous,
+ * unstructured space.
+ * A tuple is represented as an isl_multi_pw_aff.
+ * The range space is the space of the tuple.
+ * The domain space is an anonymous space
+ * with a dimension for each variable in the set of variables in "v".
+ * If a given dimension is not defined in terms of earlier dimensions in
+ * the input, then the corresponding isl_pw_aff is set equal to one time
+ * the variable corresponding to the dimension being defined.
+ */
+static __isl_give isl_multi_pw_aff *tuple_alloc(struct vars *v)
+{
+ return isl_multi_pw_aff_alloc(isl_space_alloc(v->ctx, 0, v->n, 0));
+}
+
+/* Is "pa" an expression in term of earlier dimensions?
+ * The alternative is that the dimension is defined to be equal to itself,
+ * meaning that it has a universe domain and an expression that depends
+ * on itself. "i" is the position of the expression in a sequence
+ * of "n" expressions. The final dimensions of "pa" correspond to
+ * these "n" expressions.
+ */
+static int pw_aff_is_expr(__isl_keep isl_pw_aff *pa, int i, int n)
+{
+ isl_aff *aff;
+
+ if (!pa)
+ return -1;
+ if (pa->n != 1)
+ return 1;
+ if (!isl_set_plain_is_universe(pa->p[0].set))
+ return 1;
+
+ aff = pa->p[0].aff;
+ if (isl_int_is_zero(aff->v->el[aff->v->size - n + i]))
+ return 1;
+ return 0;
+}
+
+/* Does the tuple contain any dimensions that are defined
+ * in terms of earlier dimensions?
+ */
+static int tuple_has_expr(__isl_keep isl_multi_pw_aff *tuple)
+{
+ int i, n;
+ int has_expr = 0;
+ isl_pw_aff *pa;
+
+ if (!tuple)
+ return -1;
+ n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+ for (i = 0; i < n; ++i) {
+ pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
+ has_expr = pw_aff_is_expr(pa, i, n);
+ isl_pw_aff_free(pa);
+ if (has_expr < 0 || has_expr)
+ break;
+ }
+
+ return has_expr;
+}
+
+/* Add a dimension to the given tuple.
+ * The dimension is initially undefined, so it is encoded
+ * as one times itself.
+ */
+static __isl_give isl_multi_pw_aff *tuple_add_dim(
+ __isl_take isl_multi_pw_aff *tuple, struct vars *v)
+{
+ isl_space *space;
+ isl_aff *aff;
+ isl_pw_aff *pa;
+
+ tuple = isl_multi_pw_aff_add_dims(tuple, isl_dim_in, 1);
+ space = isl_multi_pw_aff_get_domain_space(tuple);
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n, 1);
+ pa = isl_pw_aff_from_aff(aff);
+ tuple = isl_multi_pw_aff_flat_range_product(tuple,
+ isl_multi_pw_aff_from_pw_aff(pa));
+
+ return tuple;
+}
+
+/* Set the name of dimension "pos" in "tuple" to "name".
+ * During printing, we add primes if the same name appears more than once
+ * to distinguish the occurrences. Here, we remove those primes from "name"
+ * before setting the name of the dimension.
+ */
+static __isl_give isl_multi_pw_aff *tuple_set_dim_name(
+ __isl_take isl_multi_pw_aff *tuple, int pos, char *name)
+{
+ char *prime;
+
+ if (!name)
+ return tuple;
+
+ prime = strchr(name, '\'');
+ if (prime)
+ *prime = '\0';
+ tuple = isl_multi_pw_aff_set_dim_name(tuple, isl_dim_set, pos, name);
+ if (prime)
+ *prime = '\'';
+
+ return tuple;
+}
+
+/* Accept a piecewise affine expression.
+ *
+ * At the outer level, the piecewise affine expression may be of the form
+ *
+ * aff1 : condition1; aff2 : conditions2; ...
+ *
+ * or simply
+ *
+ * aff
+ *
+ * each of the affine expressions may in turn include ternary operators.
+ *
+ * There may be parentheses around some subexpression of "aff1"
+ * around "aff1" itself, around "aff1 : condition1" and/or
+ * around the entire piecewise affine expression.
+ * We therefore remove the opening parenthesis (if any) from the stream
+ * in case the closing parenthesis follows the colon, but if the closing
+ * parenthesis is the first thing in the stream after the parsed affine
+ * expression, we push the parsed expression onto the stream and parse
+ * again in case the parentheses enclose some subexpression of "aff1".
+ */
+static __isl_give isl_pw_aff *accept_piecewise_affine(struct isl_stream *s,
+ __isl_take isl_space *space, struct vars *v, int rational)
+{
+ isl_pw_aff *res;
+ isl_space *res_space;
+
+ res_space = isl_space_from_domain(isl_space_copy(space));
+ res_space = isl_space_add_dims(res_space, isl_dim_out, 1);
+ res = isl_pw_aff_empty(res_space);
+ do {
+ isl_pw_aff *pa;
+ int seen_paren;
+ int line = -1, col = -1;
+
+ set_current_line_col(s, &line, &col);
+ seen_paren = isl_stream_eat_if_available(s, '(');
+ if (seen_paren)
+ pa = accept_piecewise_affine(s, isl_space_copy(space),
+ v, rational);
+ else
+ pa = accept_extended_affine(s, isl_space_copy(space),
+ v, rational);
+ if (seen_paren && isl_stream_eat_if_available(s, ')')) {
+ seen_paren = 0;
+ if (push_aff(s, line, col, pa) < 0)
+ goto error;
+ pa = accept_extended_affine(s, isl_space_copy(space),
+ v, rational);
+ }
+ if (isl_stream_eat_if_available(s, ':')) {
+ isl_space *dom_space;
+ isl_set *dom;
+
+ dom_space = isl_pw_aff_get_domain_space(pa);
+ dom = isl_set_universe(dom_space);
+ dom = read_formula(s, v, dom, rational);
+ pa = isl_pw_aff_intersect_domain(pa, dom);
+ }
+
+ res = isl_pw_aff_union_add(res, pa);
+
+ if (seen_paren && isl_stream_eat(s, ')'))
+ goto error;
+ } while (isl_stream_eat_if_available(s, ';'));
+
+ isl_space_free(space);
+
+ return res;
+error:
+ isl_space_free(space);
+ return isl_pw_aff_free(res);
+}
+
+/* Read an affine expression from "s" and replace the definition
+ * of dimension "pos" in "tuple" by this expression.
+ *
+ * accept_extended_affine requires a wrapped space as input.
+ * The domain space of "tuple", on the other hand is an anonymous space,
+ * so we have to adjust the space of the isl_pw_aff before adding it
+ * to "tuple".
+ */
+static __isl_give isl_multi_pw_aff *read_tuple_var_def(struct isl_stream *s,
+ __isl_take isl_multi_pw_aff *tuple, int pos, struct vars *v,
+ int rational)
+{
+ isl_space *space;
+ isl_pw_aff *def;
+
+ space = isl_space_wrap(isl_space_alloc(s->ctx, 0, v->n, 0));
+
+ def = accept_piecewise_affine(s, space, v, rational);
+
+ space = isl_space_set_alloc(s->ctx, 0, v->n);
+ def = isl_pw_aff_reset_domain_space(def, space);
+ tuple = isl_multi_pw_aff_set_pw_aff(tuple, pos, def);
+
+ return tuple;
+}
+
+/* Read a list of variables and/or affine expressions and return the list
+ * as an isl_multi_pw_aff.
+ * The elements in the list are separated by either "," or "][".
+ * If "comma" is set then only "," is allowed.
+ */
+static __isl_give isl_multi_pw_aff *read_tuple_var_list(struct isl_stream *s,
+ struct vars *v, int rational, int comma)
+{
+ int i = 0;
+ struct isl_token *tok;
+ isl_multi_pw_aff *res;
+
+ res = tuple_alloc(v);
+
+ if (isl_stream_next_token_is(s, ']'))
+ return res;
+
+ while ((tok = next_token(s)) != NULL) {
+ int new_name = 0;
+
+ res = tuple_add_dim(res, v);
+
+ if (tok->type == ISL_TOKEN_IDENT) {
+ int n = v->n;
+ int p = vars_pos(v, tok->u.s, -1);
+ if (p < 0)
+ goto error;
+ new_name = p >= n;
+ }
+
+ if (tok->type == '*') {
+ if (vars_add_anon(v) < 0)
+ goto error;
+ isl_token_free(tok);
+ } else if (new_name) {
+ res = tuple_set_dim_name(res, i, v->v->name);
+ isl_token_free(tok);
+ if (isl_stream_eat_if_available(s, '='))
+ res = read_tuple_var_def(s, res, i, v,
+ rational);
+ } else {
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ if (vars_add_anon(v) < 0)
+ goto error;
+ res = read_tuple_var_def(s, res, i, v, rational);
+ }
+
+ tok = isl_stream_next_token(s);
+ if (!comma && tok && tok->type == ']' &&
+ isl_stream_next_token_is(s, '[')) {
+ isl_token_free(tok);
+ tok = isl_stream_next_token(s);
+ } else if (!tok || tok->type != ',')
+ break;
+
+ isl_token_free(tok);
+ i++;
+ }
+ if (tok)
+ isl_stream_push_token(s, tok);
+
+ return res;
+error:
+ isl_token_free(tok);
+ return isl_multi_pw_aff_free(res);
+}
+
+/* Read a tuple and represent it as an isl_multi_pw_aff. See tuple_alloc.
+ */
+static __isl_give isl_multi_pw_aff *read_tuple(struct isl_stream *s,
+ struct vars *v, int rational, int comma)
+{
+ struct isl_token *tok;
+ char *name = NULL;
+ isl_multi_pw_aff *res = NULL;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type == ISL_TOKEN_IDENT || tok->is_keyword) {
+ name = strdup(tok->u.s);
+ isl_token_free(tok);
+ if (!name)
+ goto error;
+ } else
+ isl_stream_push_token(s, tok);
+ if (isl_stream_eat(s, '['))
+ goto error;
+ if (next_is_tuple(s)) {
+ isl_multi_pw_aff *out;
+ int n;
+ res = read_tuple(s, v, rational, comma);
+ if (isl_stream_eat(s, ISL_TOKEN_TO))
+ goto error;
+ out = read_tuple(s, v, rational, comma);
+ n = isl_multi_pw_aff_dim(out, isl_dim_out);
+ res = isl_multi_pw_aff_add_dims(res, isl_dim_in, n);
+ res = isl_multi_pw_aff_range_product(res, out);
+ } else
+ res = read_tuple_var_list(s, v, rational, comma);
+ if (isl_stream_eat(s, ']'))
+ goto error;
+
+ if (name) {
+ res = isl_multi_pw_aff_set_tuple_name(res, isl_dim_out, name);
+ free(name);
+ }
+
+ return res;
+error:
+ free(name);
+ return isl_multi_pw_aff_free(res);
+}
+
+/* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
+ * We first create the appropriate space in "map" based on the range
+ * space of this isl_multi_pw_aff. Then, we add equalities based
+ * on the affine expressions. These live in an anonymous space,
+ * however, so we first need to reset the space to that of "map".
+ */
+static __isl_give isl_map *map_from_tuple(__isl_take isl_multi_pw_aff *tuple,
+ __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
+ int rational)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_space *space = NULL;
+
+ if (!map || !tuple)
+ goto error;
+ ctx = isl_multi_pw_aff_get_ctx(tuple);
+ n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+ space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
+ if (!space)
+ goto error;
+
+ if (type == isl_dim_param) {
+ if (isl_space_has_tuple_name(space, isl_dim_set) ||
+ isl_space_is_wrapping(space)) {
+ isl_die(ctx, isl_error_invalid,
+ "parameter tuples cannot be named or nested",
+ goto error);
+ }
+ map = isl_map_add_dims(map, type, n);
+ for (i = 0; i < n; ++i) {
+ isl_id *id;
+ if (!isl_space_has_dim_name(space, isl_dim_set, i))
+ isl_die(ctx, isl_error_invalid,
+ "parameters must be named",
+ goto error);
+ id = isl_space_get_dim_id(space, isl_dim_set, i);
+ map = isl_map_set_dim_id(map, isl_dim_param, i, id);
+ }
+ } else if (type == isl_dim_in) {
+ isl_set *set;
+
+ set = isl_set_universe(isl_space_copy(space));
+ if (rational)
+ set = isl_set_set_rational(set);
+ set = isl_set_intersect_params(set, isl_map_params(map));
+ map = isl_map_from_domain(set);
+ } else {
+ isl_set *set;
+
+ set = isl_set_universe(isl_space_copy(space));
+ if (rational)
+ set = isl_set_set_rational(set);
+ map = isl_map_from_domain_and_range(isl_map_domain(map), set);
+ }
+
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ isl_space *space;
+ isl_aff *aff;
+ isl_set *set;
+ isl_map *map_i;
+
+ pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
+ space = isl_pw_aff_get_domain_space(pa);
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+ aff = isl_aff_add_coefficient_si(aff,
+ isl_dim_in, v->n - n + i, -1);
+ pa = isl_pw_aff_add(pa, isl_pw_aff_from_aff(aff));
+ if (rational)
+ pa = isl_pw_aff_set_rational(pa);
+ set = isl_pw_aff_zero_set(pa);
+ map_i = isl_map_from_range(set);
+ map_i = isl_map_reset_space(map_i, isl_map_get_space(map));
+ map = isl_map_intersect(map, map_i);
+ }
+
+ isl_space_free(space);
+ isl_multi_pw_aff_free(tuple);
+ return map;
+error:
+ isl_space_free(space);
+ isl_multi_pw_aff_free(tuple);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Read a tuple from "s" and add it to "map".
+ * The tuple is initially represented as an isl_multi_pw_aff and
+ * then added to "map".
+ */
+static __isl_give isl_map *read_map_tuple(struct isl_stream *s,
+ __isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
+ int rational, int comma)
+{
+ isl_multi_pw_aff *tuple;
+
+ tuple = read_tuple(s, v, rational, comma);
+ if (!tuple)
+ return isl_map_free(map);
+
+ return map_from_tuple(tuple, map, type, v, rational);
+}
+
+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,
+ int rational)
+{
+ isl_set *cond;
+
+ left = isl_pw_aff_list_copy(left);
+ right = isl_pw_aff_list_copy(right);
+ if (rational) {
+ left = isl_pw_aff_list_set_rational(left);
+ right = isl_pw_aff_list_set_rational(right);
+ }
+ 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);
+ else if (type == ISL_TOKEN_LT)
+ cond = isl_pw_aff_list_lt_set(left, right);
+ else if (type == ISL_TOKEN_GT)
+ cond = isl_pw_aff_list_gt_set(left, right);
+ else if (type == ISL_TOKEN_NE)
+ cond = isl_pw_aff_list_ne_set(left, right);
+ else
+ cond = isl_pw_aff_list_eq_set(left, right);
+
+ return isl_set_intersect(set, cond);
+}
+
+static __isl_give isl_map *add_constraint(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ struct isl_token *tok = NULL;
+ isl_pw_aff_list *list1 = NULL, *list2 = NULL;
+ isl_set *set;
+
+ set = isl_map_wrap(map);
+ list1 = accept_affine_list(s, isl_set_get_space(set), v);
+ if (!list1)
+ goto error;
+ tok = isl_stream_next_token(s);
+ if (!is_comparator(tok)) {
+ isl_stream_error(s, tok, "missing operator");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ goto error;
+ }
+ for (;;) {
+ list2 = accept_affine_list(s, isl_set_get_space(set), v);
+ if (!list2)
+ goto error;
+
+ set = construct_constraints(set, tok->type, list1, list2,
+ rational);
+ isl_token_free(tok);
+ isl_pw_aff_list_free(list1);
+ list1 = list2;
+
+ tok = isl_stream_next_token(s);
+ if (!is_comparator(tok)) {
+ if (tok)
+ isl_stream_push_token(s, tok);
+ break;
+ }
+ }
+ 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);
+ return NULL;
+}
+
+static __isl_give isl_map *read_exists(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ int n = v->n;
+ int seen_paren = isl_stream_eat_if_available(s, '(');
+
+ map = isl_map_from_domain(isl_map_wrap(map));
+ map = read_defined_var_list(s, v, map, rational);
+
+ if (isl_stream_eat(s, ':'))
+ goto error;
+
+ map = read_formula(s, v, map, rational);
+ map = isl_set_unwrap(isl_map_domain(map));
+
+ vars_drop(v, v->n - n);
+ if (seen_paren && isl_stream_eat(s, ')'))
+ goto error;
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Parse an expression between parentheses and push the result
+ * back on the stream.
+ *
+ * The parsed expression may be either an affine expression
+ * or a condition. The first type is pushed onto the stream
+ * as an isl_pw_aff, while the second is pushed as an isl_map.
+ *
+ * If the initial token indicates the start of a condition,
+ * we parse it as such.
+ * Otherwise, we first parse an affine expression and push
+ * that onto the stream. If the affine expression covers the
+ * entire expression between parentheses, we return.
+ * Otherwise, we assume that the affine expression is the
+ * start of a condition and continue parsing.
+ */
+static int resolve_paren_expr(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ struct isl_token *tok, *tok2;
+ int line, col;
+ isl_pw_aff *pwaff;
+
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != '(')
+ goto error;
+
+ if (isl_stream_next_token_is(s, '('))
+ if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
+ goto error;
+
+ if (isl_stream_next_token_is(s, ISL_TOKEN_EXISTS) ||
+ isl_stream_next_token_is(s, ISL_TOKEN_NOT) ||
+ isl_stream_next_token_is(s, ISL_TOKEN_TRUE) ||
+ isl_stream_next_token_is(s, ISL_TOKEN_FALSE) ||
+ isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
+ map = read_formula(s, v, map, rational);
+ if (isl_stream_eat(s, ')'))
+ goto error;
+ tok->type = ISL_TOKEN_MAP;
+ tok->u.map = map;
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+
+ tok2 = isl_stream_next_token(s);
+ if (!tok2)
+ goto error;
+ line = tok2->line;
+ col = tok2->col;
+ isl_stream_push_token(s, tok2);
+
+ pwaff = accept_affine(s, isl_space_wrap(isl_map_get_space(map)), v);
+ if (!pwaff)
+ goto error;
+
+ tok2 = isl_token_new(s->ctx, line, col, 0);
+ if (!tok2)
+ goto error2;
+ tok2->type = ISL_TOKEN_AFF;
+ tok2->u.pwaff = pwaff;
+
+ if (isl_stream_eat_if_available(s, ')')) {
+ isl_stream_push_token(s, tok2);
+ isl_token_free(tok);
+ isl_map_free(map);
+ return 0;
+ }
+
+ isl_stream_push_token(s, tok2);
+
+ map = read_formula(s, v, map, rational);
+ if (isl_stream_eat(s, ')'))
+ goto error;
+
+ tok->type = ISL_TOKEN_MAP;
+ tok->u.map = map;
+ isl_stream_push_token(s, tok);
+
+ return 0;
+error2:
+ isl_pw_aff_free(pwaff);
+error:
+ isl_token_free(tok);
+ isl_map_free(map);
+ return -1;
+}
+
+static __isl_give isl_map *read_conjunct(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ if (isl_stream_next_token_is(s, '('))
+ if (resolve_paren_expr(s, v, isl_map_copy(map), rational))
+ goto error;
+
+ if (isl_stream_next_token_is(s, ISL_TOKEN_MAP)) {
+ struct isl_token *tok;
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ isl_map_free(map);
+ map = isl_map_copy(tok->u.map);
+ isl_token_free(tok);
+ return map;
+ }
+
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_EXISTS))
+ return read_exists(s, v, map, rational);
+
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_TRUE))
+ return map;
+
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_FALSE)) {
+ isl_space *dim = isl_map_get_space(map);
+ isl_map_free(map);
+ return isl_map_empty(dim);
+ }
+
+ return add_constraint(s, v, map, rational);
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+static __isl_give isl_map *read_conjuncts(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ isl_map *res;
+ int negate;
+
+ negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
+ res = read_conjunct(s, v, isl_map_copy(map), rational);
+ if (negate)
+ res = isl_map_subtract(isl_map_copy(map), res);
+
+ while (res && isl_stream_eat_if_available(s, ISL_TOKEN_AND)) {
+ isl_map *res_i;
+
+ negate = isl_stream_eat_if_available(s, ISL_TOKEN_NOT);
+ res_i = read_conjunct(s, v, isl_map_copy(map), rational);
+ if (negate)
+ res = isl_map_subtract(res, res_i);
+ else
+ res = isl_map_intersect(res, res_i);
+ }
+
+ isl_map_free(map);
+ return res;
+}
+
+static struct isl_map *read_disjuncts(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ isl_map *res;
+
+ if (isl_stream_next_token_is(s, '}')) {
+ isl_space *dim = isl_map_get_space(map);
+ isl_map_free(map);
+ return isl_map_universe(dim);
+ }
+
+ res = read_conjuncts(s, v, isl_map_copy(map), rational);
+ while (isl_stream_eat_if_available(s, ISL_TOKEN_OR)) {
+ isl_map *res_i;
+
+ res_i = read_conjuncts(s, v, isl_map_copy(map), rational);
+ res = isl_map_union(res, res_i);
+ }
+
+ isl_map_free(map);
+ return res;
+}
+
+/* Read a first order formula from "s", add the corresponding
+ * constraints to "map" and return the result.
+ *
+ * In particular, read a formula of the form
+ *
+ * a
+ *
+ * or
+ *
+ * a implies b
+ *
+ * where a and b are disjunctions.
+ *
+ * In the first case, map is replaced by
+ *
+ * map \cap { [..] : a }
+ *
+ * In the second case, it is replaced by
+ *
+ * (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
+ */
+static __isl_give isl_map *read_formula(struct isl_stream *s,
+ struct vars *v, __isl_take isl_map *map, int rational)
+{
+ isl_map *res;
+
+ res = read_disjuncts(s, v, isl_map_copy(map), rational);
+
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_IMPLIES)) {
+ isl_map *res2;
+
+ res = isl_map_subtract(isl_map_copy(map), res);
+ res2 = read_disjuncts(s, v, map, rational);
+ res = isl_map_union(res, res2);
+ } else
+ isl_map_free(map);
+
+ return res;
+}
+
+static int polylib_pos_to_isl_pos(__isl_keep isl_basic_map *bmap, int pos)
+{
+ if (pos < isl_basic_map_dim(bmap, isl_dim_out))
+ return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
+ isl_basic_map_dim(bmap, isl_dim_in) + pos;
+ pos -= isl_basic_map_dim(bmap, isl_dim_out);
+
+ if (pos < isl_basic_map_dim(bmap, isl_dim_in))
+ return 1 + isl_basic_map_dim(bmap, isl_dim_param) + pos;
+ pos -= isl_basic_map_dim(bmap, isl_dim_in);
+
+ if (pos < isl_basic_map_dim(bmap, isl_dim_div))
+ return 1 + isl_basic_map_dim(bmap, isl_dim_param) +
+ isl_basic_map_dim(bmap, isl_dim_in) +
+ isl_basic_map_dim(bmap, isl_dim_out) + pos;
+ pos -= isl_basic_map_dim(bmap, isl_dim_div);
+
+ if (pos < isl_basic_map_dim(bmap, isl_dim_param))
+ return 1 + pos;
+
+ return 0;
+}
+
+static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
+ struct isl_stream *s, __isl_take isl_basic_map *bmap)
+{
+ int j;
+ struct isl_token *tok;
+ int type;
+ int k;
+ isl_int *c;
+ unsigned nparam;
+ unsigned dim;
+
+ if (!bmap)
+ return NULL;
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ dim = isl_basic_map_dim(bmap, isl_dim_out);
+
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting coefficient");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ if (!tok->on_new_line) {
+ isl_stream_error(s, tok, "coefficient should appear on new line");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+
+ type = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ isl_assert(s->ctx, type == 0 || type == 1, goto error);
+ if (type == 0) {
+ k = isl_basic_map_alloc_equality(bmap);
+ c = bmap->eq[k];
+ } else {
+ k = isl_basic_map_alloc_inequality(bmap);
+ c = bmap->ineq[k];
+ }
+ if (k < 0)
+ goto error;
+
+ for (j = 0; j < 1 + isl_basic_map_total_dim(bmap); ++j) {
+ int pos;
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting coefficient");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ if (tok->on_new_line) {
+ isl_stream_error(s, tok,
+ "coefficient should not appear on new line");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ pos = polylib_pos_to_isl_pos(bmap, j);
+ isl_int_set(c[pos], tok->u.v);
+ isl_token_free(tok);
+ }
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s)
+{
+ int i;
+ struct isl_token *tok;
+ struct isl_token *tok2;
+ int n_row, n_col;
+ int on_new_line;
+ unsigned in = 0, out, local = 0;
+ struct isl_basic_map *bmap = NULL;
+ int nparam = 0;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ tok2 = isl_stream_next_token(s);
+ if (!tok2) {
+ isl_token_free(tok);
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ if (tok->type != ISL_TOKEN_VALUE || tok2->type != ISL_TOKEN_VALUE) {
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ isl_stream_error(s, NULL,
+ "expecting constraint matrix dimensions");
+ return NULL;
+ }
+ n_row = isl_int_get_si(tok->u.v);
+ n_col = isl_int_get_si(tok2->u.v);
+ on_new_line = tok2->on_new_line;
+ isl_token_free(tok2);
+ isl_token_free(tok);
+ isl_assert(s->ctx, !on_new_line, return NULL);
+ isl_assert(s->ctx, n_row >= 0, return NULL);
+ isl_assert(s->ctx, n_col >= 2 + nparam, return NULL);
+ tok = isl_stream_next_token_on_same_line(s);
+ if (tok) {
+ if (tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok,
+ "expecting number of output dimensions");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ out = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ tok = isl_stream_next_token_on_same_line(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok,
+ "expecting number of input dimensions");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ in = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ tok = isl_stream_next_token_on_same_line(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok,
+ "expecting number of existentials");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ local = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ tok = isl_stream_next_token_on_same_line(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok,
+ "expecting number of parameters");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ nparam = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+ if (n_col != 1 + out + in + local + nparam + 1) {
+ isl_stream_error(s, NULL,
+ "dimensions don't match");
+ goto error;
+ }
+ } else
+ out = n_col - 2 - nparam;
+ bmap = isl_basic_map_alloc(s->ctx, nparam, in, out, local, n_row, n_row);
+ if (!bmap)
+ return NULL;
+
+ for (i = 0; i < local; ++i) {
+ int k = isl_basic_map_alloc_div(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->div[k], 1 + 1 + nparam + in + out + local);
+ }
+
+ for (i = 0; i < n_row; ++i)
+ bmap = basic_map_read_polylib_constraint(s, bmap);
+
+ tok = isl_stream_next_token_on_same_line(s);
+ if (tok) {
+ isl_stream_error(s, tok, "unexpected extra token on line");
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static struct isl_map *map_read_polylib(struct isl_stream *s)
+{
+ struct isl_token *tok;
+ struct isl_token *tok2;
+ int i, n;
+ struct isl_map *map;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ tok2 = isl_stream_next_token_on_same_line(s);
+ if (tok2 && tok2->type == ISL_TOKEN_VALUE) {
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ return isl_map_from_basic_map(basic_map_read_polylib(s));
+ }
+ if (tok2) {
+ isl_stream_error(s, tok2, "unexpected token");
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ return NULL;
+ }
+ n = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ isl_assert(s->ctx, n >= 1, return NULL);
+
+ map = isl_map_from_basic_map(basic_map_read_polylib(s));
+
+ for (i = 1; map && i < n; ++i)
+ map = isl_map_union(map,
+ isl_map_from_basic_map(basic_map_read_polylib(s)));
+
+ return map;
+}
+
+static int optional_power(struct isl_stream *s)
+{
+ int pow;
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 1;
+ if (tok->type != '^') {
+ isl_stream_push_token(s, tok);
+ return 1;
+ }
+ isl_token_free(tok);
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting exponent");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ return 1;
+ }
+ pow = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+ return pow;
+}
+
+static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s,
+ __isl_keep isl_map *map, struct vars *v);
+
+static __isl_give isl_pw_qpolynomial *read_factor(struct isl_stream *s,
+ __isl_keep isl_map *map, struct vars *v)
+{
+ isl_pw_qpolynomial *pwqp;
+ struct isl_token *tok;
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ if (tok->type == '(') {
+ int pow;
+
+ isl_token_free(tok);
+ pwqp = read_term(s, map, v);
+ if (!pwqp)
+ return NULL;
+ if (isl_stream_eat(s, ')'))
+ goto error;
+ pow = optional_power(s);
+ pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
+ } else if (tok->type == ISL_TOKEN_VALUE) {
+ struct isl_token *tok2;
+ isl_qpolynomial *qp;
+
+ tok2 = isl_stream_next_token(s);
+ if (tok2 && tok2->type == '/') {
+ isl_token_free(tok2);
+ tok2 = next_token(s);
+ if (!tok2 || tok2->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok2, "expected denominator");
+ isl_token_free(tok);
+ isl_token_free(tok2);
+ return NULL;
+ }
+ qp = isl_qpolynomial_rat_cst_on_domain(isl_map_get_space(map),
+ tok->u.v, tok2->u.v);
+ isl_token_free(tok2);
+ } else {
+ isl_stream_push_token(s, tok2);
+ qp = isl_qpolynomial_cst_on_domain(isl_map_get_space(map),
+ tok->u.v);
+ }
+ isl_token_free(tok);
+ pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
+ } else if (tok->type == ISL_TOKEN_INFTY) {
+ isl_qpolynomial *qp;
+ isl_token_free(tok);
+ qp = isl_qpolynomial_infty_on_domain(isl_map_get_space(map));
+ pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
+ } else if (tok->type == ISL_TOKEN_NAN) {
+ isl_qpolynomial *qp;
+ isl_token_free(tok);
+ qp = isl_qpolynomial_nan_on_domain(isl_map_get_space(map));
+ pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
+ } else if (tok->type == ISL_TOKEN_IDENT) {
+ int n = v->n;
+ int pos = vars_pos(v, tok->u.s, -1);
+ int pow;
+ isl_qpolynomial *qp;
+ if (pos < 0) {
+ isl_token_free(tok);
+ return NULL;
+ }
+ if (pos >= n) {
+ vars_drop(v, v->n - n);
+ isl_stream_error(s, tok, "unknown identifier");
+ isl_token_free(tok);
+ return NULL;
+ }
+ isl_token_free(tok);
+ pow = optional_power(s);
+ qp = isl_qpolynomial_var_pow_on_domain(isl_map_get_space(map), pos, pow);
+ pwqp = isl_pw_qpolynomial_from_qpolynomial(qp);
+ } else if (is_start_of_div(tok)) {
+ isl_pw_aff *pwaff;
+ int pow;
+
+ isl_stream_push_token(s, tok);
+ pwaff = accept_div(s, isl_map_get_space(map), v);
+ pow = optional_power(s);
+ pwqp = isl_pw_qpolynomial_from_pw_aff(pwaff);
+ pwqp = isl_pw_qpolynomial_pow(pwqp, pow);
+ } else if (tok->type == '-') {
+ isl_token_free(tok);
+ pwqp = read_factor(s, map, v);
+ pwqp = isl_pw_qpolynomial_neg(pwqp);
+ } else {
+ isl_stream_error(s, tok, "unexpected isl_token");
+ isl_stream_push_token(s, tok);
+ return NULL;
+ }
+
+ if (isl_stream_eat_if_available(s, '*') ||
+ isl_stream_next_token_is(s, ISL_TOKEN_IDENT)) {
+ isl_pw_qpolynomial *pwqp2;
+
+ pwqp2 = read_factor(s, map, v);
+ pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp2);
+ }
+
+ return pwqp;
+error:
+ isl_pw_qpolynomial_free(pwqp);
+ return NULL;
+}
+
+static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s,
+ __isl_keep isl_map *map, struct vars *v)
+{
+ struct isl_token *tok;
+ isl_pw_qpolynomial *pwqp;
+
+ pwqp = read_factor(s, map, v);
+
+ for (;;) {
+ tok = next_token(s);
+ if (!tok)
+ return pwqp;
+
+ if (tok->type == '+') {
+ isl_pw_qpolynomial *pwqp2;
+
+ isl_token_free(tok);
+ pwqp2 = read_factor(s, map, v);
+ pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
+ } else if (tok->type == '-') {
+ isl_pw_qpolynomial *pwqp2;
+
+ isl_token_free(tok);
+ pwqp2 = read_factor(s, map, v);
+ pwqp = isl_pw_qpolynomial_sub(pwqp, pwqp2);
+ } else if (tok->type == ISL_TOKEN_VALUE &&
+ isl_int_is_neg(tok->u.v)) {
+ isl_pw_qpolynomial *pwqp2;
+
+ isl_stream_push_token(s, tok);
+ pwqp2 = read_factor(s, map, v);
+ pwqp = isl_pw_qpolynomial_add(pwqp, pwqp2);
+ } else {
+ isl_stream_push_token(s, tok);
+ break;
+ }
+ }
+
+ return pwqp;
+}
+
+static __isl_give isl_map *read_optional_formula(struct isl_stream *s,
+ __isl_take isl_map *map, struct vars *v, int rational)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok->type == ':' ||
+ (tok->type == ISL_TOKEN_OR && !strcmp(tok->u.s, "|"))) {
+ isl_token_free(tok);
+ map = read_formula(s, v, map, rational);
+ } else
+ isl_stream_push_token(s, tok);
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+static struct isl_obj obj_read_poly(struct isl_stream *s,
+ __isl_take isl_map *map, struct vars *v, int n)
+{
+ struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
+ isl_pw_qpolynomial *pwqp;
+ struct isl_set *set;
+
+ pwqp = read_term(s, map, v);
+ map = read_optional_formula(s, map, v, 0);
+ set = isl_map_range(map);
+
+ pwqp = isl_pw_qpolynomial_intersect_domain(pwqp, set);
+
+ vars_drop(v, v->n - n);
+
+ obj.v = pwqp;
+ return obj;
+}
+
+static struct isl_obj obj_read_poly_or_fold(struct isl_stream *s,
+ __isl_take isl_set *set, struct vars *v, int n)
+{
+ struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
+ isl_pw_qpolynomial *pwqp;
+ isl_pw_qpolynomial_fold *pwf = NULL;
+
+ if (!isl_stream_eat_if_available(s, ISL_TOKEN_MAX))
+ return obj_read_poly(s, set, v, n);
+
+ if (isl_stream_eat(s, '('))
+ goto error;
+
+ pwqp = read_term(s, set, v);
+ pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max, pwqp);
+
+ while (isl_stream_eat_if_available(s, ',')) {
+ isl_pw_qpolynomial_fold *pwf_i;
+ pwqp = read_term(s, set, v);
+ pwf_i = isl_pw_qpolynomial_fold_from_pw_qpolynomial(isl_fold_max,
+ pwqp);
+ pwf = isl_pw_qpolynomial_fold_fold(pwf, pwf_i);
+ }
+
+ if (isl_stream_eat(s, ')'))
+ goto error;
+
+ set = read_optional_formula(s, set, v, 0);
+ pwf = isl_pw_qpolynomial_fold_intersect_domain(pwf, set);
+
+ vars_drop(v, v->n - n);
+
+ obj.v = pwf;
+ return obj;
+error:
+ isl_set_free(set);
+ isl_pw_qpolynomial_fold_free(pwf);
+ obj.type = isl_obj_none;
+ return obj;
+}
+
+static int is_rational(struct isl_stream *s)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type == ISL_TOKEN_RAT && isl_stream_next_token_is(s, ':')) {
+ isl_token_free(tok);
+ isl_stream_eat(s, ':');
+ return 1;
+ }
+
+ isl_stream_push_token(s, tok);
+
+ return 0;
+}
+
+static struct isl_obj obj_read_body(struct isl_stream *s,
+ __isl_take isl_map *map, struct vars *v)
+{
+ struct isl_token *tok;
+ struct isl_obj obj = { isl_obj_set, NULL };
+ int n = v->n;
+ int rational;
+
+ rational = is_rational(s);
+ if (rational)
+ map = isl_map_set_rational(map);
+
+ if (isl_stream_next_token_is(s, ':')) {
+ obj.type = isl_obj_set;
+ obj.v = read_optional_formula(s, map, v, rational);
+ return obj;
+ }
+
+ if (!next_is_tuple(s))
+ return obj_read_poly_or_fold(s, map, v, n);
+
+ map = read_map_tuple(s, map, isl_dim_in, v, rational, 0);
+ if (!map)
+ goto error;
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ goto error;
+ if (tok->type == ISL_TOKEN_TO) {
+ obj.type = isl_obj_map;
+ isl_token_free(tok);
+ if (!next_is_tuple(s)) {
+ isl_set *set = isl_map_domain(map);
+ return obj_read_poly_or_fold(s, set, v, n);
+ }
+ map = read_map_tuple(s, map, isl_dim_out, v, rational, 0);
+ if (!map)
+ goto error;
+ } else {
+ map = isl_map_domain(map);
+ isl_stream_push_token(s, tok);
+ }
+
+ map = read_optional_formula(s, map, v, rational);
+
+ vars_drop(v, v->n - n);
+
+ obj.v = map;
+ return obj;
+error:
+ isl_map_free(map);
+ obj.type = isl_obj_none;
+ return obj;
+}
+
+static struct isl_obj to_union(isl_ctx *ctx, struct isl_obj obj)
+{
+ if (obj.type == isl_obj_map) {
+ obj.v = isl_union_map_from_map(obj.v);
+ obj.type = isl_obj_union_map;
+ } else if (obj.type == isl_obj_set) {
+ obj.v = isl_union_set_from_set(obj.v);
+ obj.type = isl_obj_union_set;
+ } else if (obj.type == isl_obj_pw_qpolynomial) {
+ obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
+ obj.type = isl_obj_union_pw_qpolynomial;
+ } else if (obj.type == isl_obj_pw_qpolynomial_fold) {
+ obj.v = isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(obj.v);
+ obj.type = isl_obj_union_pw_qpolynomial_fold;
+ } else
+ isl_assert(ctx, 0, goto error);
+ return obj;
+error:
+ obj.type->free(obj.v);
+ obj.type = isl_obj_none;
+ return obj;
+}
+
+static struct isl_obj obj_add(struct isl_ctx *ctx,
+ struct isl_obj obj1, struct isl_obj obj2)
+{
+ if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
+ obj1 = to_union(ctx, obj1);
+ if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
+ obj2 = to_union(ctx, obj2);
+ if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
+ obj1 = to_union(ctx, obj1);
+ if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
+ obj2 = to_union(ctx, obj2);
+ if (obj1.type == isl_obj_pw_qpolynomial &&
+ obj2.type == isl_obj_union_pw_qpolynomial)
+ obj1 = to_union(ctx, obj1);
+ if (obj1.type == isl_obj_union_pw_qpolynomial &&
+ obj2.type == isl_obj_pw_qpolynomial)
+ obj2 = to_union(ctx, obj2);
+ if (obj1.type == isl_obj_pw_qpolynomial_fold &&
+ obj2.type == isl_obj_union_pw_qpolynomial_fold)
+ obj1 = to_union(ctx, obj1);
+ if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
+ obj2.type == isl_obj_pw_qpolynomial_fold)
+ obj2 = to_union(ctx, obj2);
+ isl_assert(ctx, obj1.type == obj2.type, goto error);
+ if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) {
+ obj1 = to_union(ctx, obj1);
+ obj2 = to_union(ctx, obj2);
+ }
+ if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) {
+ obj1 = to_union(ctx, obj1);
+ obj2 = to_union(ctx, obj2);
+ }
+ if (obj1.type == isl_obj_pw_qpolynomial &&
+ !isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) {
+ obj1 = to_union(ctx, obj1);
+ obj2 = to_union(ctx, obj2);
+ }
+ if (obj1.type == isl_obj_pw_qpolynomial_fold &&
+ !isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) {
+ obj1 = to_union(ctx, obj1);
+ obj2 = to_union(ctx, obj2);
+ }
+ obj1.v = obj1.type->add(obj1.v, obj2.v);
+ return obj1;
+error:
+ obj1.type->free(obj1.v);
+ obj2.type->free(obj2.v);
+ obj1.type = isl_obj_none;
+ obj1.v = NULL;
+ return obj1;
+}
+
+static struct isl_obj obj_read(struct isl_stream *s)
+{
+ isl_map *map = NULL;
+ struct isl_token *tok;
+ struct vars *v = NULL;
+ struct isl_obj obj = { isl_obj_set, NULL };
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ if (tok->type == ISL_TOKEN_VALUE) {
+ struct isl_token *tok2;
+ struct isl_map *map;
+
+ tok2 = isl_stream_next_token(s);
+ if (!tok2 || tok2->type != ISL_TOKEN_VALUE ||
+ isl_int_is_neg(tok2->u.v)) {
+ if (tok2)
+ isl_stream_push_token(s, tok2);
+ obj.type = isl_obj_val;
+ obj.v = isl_val_int_from_isl_int(s->ctx, tok->u.v);
+ isl_token_free(tok);
+ return obj;
+ }
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+ map = map_read_polylib(s);
+ if (!map)
+ goto error;
+ if (isl_map_may_be_set(map))
+ obj.v = isl_map_range(map);
+ else {
+ obj.type = isl_obj_map;
+ obj.v = map;
+ }
+ return obj;
+ }
+ v = vars_new(s->ctx);
+ if (!v) {
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ map = isl_map_universe(isl_space_params_alloc(s->ctx, 0));
+ if (tok->type == '[') {
+ isl_stream_push_token(s, tok);
+ map = read_map_tuple(s, map, isl_dim_param, v, 0, 0);
+ if (!map)
+ goto error;
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_TO) {
+ isl_stream_error(s, tok, "expecting '->'");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ isl_token_free(tok);
+ tok = isl_stream_next_token(s);
+ }
+ if (!tok || tok->type != '{') {
+ isl_stream_error(s, tok, "expecting '{'");
+ if (tok)
+ isl_stream_push_token(s, tok);
+ goto error;
+ }
+ isl_token_free(tok);
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ ;
+ else if (tok->type == ISL_TOKEN_IDENT && !strcmp(tok->u.s, "Sym")) {
+ isl_token_free(tok);
+ if (isl_stream_eat(s, '='))
+ goto error;
+ map = read_map_tuple(s, map, isl_dim_param, v, 0, 1);
+ if (!map)
+ goto error;
+ } else if (tok->type == '}') {
+ obj.type = isl_obj_union_set;
+ obj.v = isl_union_set_empty(isl_map_get_space(map));
+ isl_token_free(tok);
+ goto done;
+ } else
+ isl_stream_push_token(s, tok);
+
+ for (;;) {
+ struct isl_obj o;
+ tok = NULL;
+ o = obj_read_body(s, isl_map_copy(map), v);
+ if (o.type == isl_obj_none || !o.v)
+ goto error;
+ if (!obj.v)
+ obj = o;
+ else {
+ obj = obj_add(s->ctx, obj, o);
+ if (obj.type == isl_obj_none || !obj.v)
+ goto error;
+ }
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ';')
+ break;
+ isl_token_free(tok);
+ if (isl_stream_next_token_is(s, '}')) {
+ tok = isl_stream_next_token(s);
+ break;
+ }
+ }
+
+ if (tok && tok->type == '}') {
+ isl_token_free(tok);
+ } else {
+ isl_stream_error(s, tok, "unexpected isl_token");
+ if (tok)
+ isl_token_free(tok);
+ goto error;
+ }
+done:
+ vars_free(v);
+ isl_map_free(map);
+
+ return obj;
+error:
+ isl_map_free(map);
+ obj.type->free(obj.v);
+ if (v)
+ vars_free(v);
+ obj.v = NULL;
+ return obj;
+}
+
+struct isl_obj isl_stream_read_obj(struct isl_stream *s)
+{
+ return obj_read(s);
+}
+
+__isl_give isl_map *isl_stream_read_map(struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.v)
+ isl_assert(s->ctx, obj.type == isl_obj_map ||
+ obj.type == isl_obj_set, goto error);
+
+ if (obj.type == isl_obj_set)
+ obj.v = isl_map_from_range(obj.v);
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+__isl_give isl_set *isl_stream_read_set(struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.v) {
+ if (obj.type == isl_obj_map && isl_map_may_be_set(obj.v)) {
+ obj.v = isl_map_range(obj.v);
+ obj.type = isl_obj_set;
+ }
+ isl_assert(s->ctx, obj.type == isl_obj_set, goto error);
+ }
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_stream_read_union_map(struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.type == isl_obj_map) {
+ obj.type = isl_obj_union_map;
+ obj.v = isl_union_map_from_map(obj.v);
+ }
+ if (obj.type == isl_obj_set) {
+ obj.type = isl_obj_union_set;
+ obj.v = isl_union_set_from_set(obj.v);
+ }
+ if (obj.v && obj.type == isl_obj_union_set &&
+ isl_union_set_is_empty(obj.v))
+ obj.type = isl_obj_union_map;
+ if (obj.v && obj.type != isl_obj_union_map)
+ isl_die(s->ctx, isl_error_invalid, "invalid input", goto error);
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+__isl_give isl_union_set *isl_stream_read_union_set(struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.type == isl_obj_set) {
+ obj.type = isl_obj_union_set;
+ obj.v = isl_union_set_from_set(obj.v);
+ }
+ if (obj.v)
+ isl_assert(s->ctx, obj.type == isl_obj_union_set, goto error);
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *basic_map_read(struct isl_stream *s)
+{
+ struct isl_obj obj;
+ struct isl_map *map;
+ struct isl_basic_map *bmap;
+
+ obj = obj_read(s);
+ if (obj.v && (obj.type != isl_obj_map && obj.type != isl_obj_set))
+ isl_die(s->ctx, isl_error_invalid, "not a (basic) set or map",
+ goto error);
+ map = obj.v;
+ if (!map)
+ return NULL;
+
+ if (map->n > 1)
+ isl_die(s->ctx, isl_error_invalid,
+ "set or map description involves "
+ "more than one disjunct", goto error);
+
+ if (map->n == 0)
+ bmap = isl_basic_map_empty_like_map(map);
+ else
+ bmap = isl_basic_map_copy(map->p[0]);
+
+ isl_map_free(map);
+
+ return bmap;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+static __isl_give isl_basic_set *basic_set_read(struct isl_stream *s)
+{
+ isl_basic_map *bmap;
+ bmap = basic_map_read(s);
+ if (!bmap)
+ return NULL;
+ if (!isl_basic_map_may_be_set(bmap))
+ isl_die(s->ctx, isl_error_invalid,
+ "input is not a set", goto error);
+ return isl_basic_map_range(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
+ FILE *input)
+{
+ struct isl_basic_map *bmap;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ bmap = basic_map_read(s);
+ isl_stream_free(s);
+ return bmap;
+}
+
+__isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
+ FILE *input)
+{
+ isl_basic_set *bset;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ bset = basic_set_read(s);
+ isl_stream_free(s);
+ return bset;
+}
+
+struct isl_basic_map *isl_basic_map_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ struct isl_basic_map *bmap;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ bmap = basic_map_read(s);
+ isl_stream_free(s);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ isl_basic_set *bset;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ bset = basic_set_read(s);
+ isl_stream_free(s);
+ return bset;
+}
+
+__isl_give isl_map *isl_map_read_from_file(struct isl_ctx *ctx,
+ FILE *input)
+{
+ struct isl_map *map;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ map = isl_stream_read_map(s);
+ isl_stream_free(s);
+ return map;
+}
+
+__isl_give isl_map *isl_map_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ struct isl_map *map;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ map = isl_stream_read_map(s);
+ isl_stream_free(s);
+ return map;
+}
+
+__isl_give isl_set *isl_set_read_from_file(struct isl_ctx *ctx,
+ FILE *input)
+{
+ isl_set *set;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ set = isl_stream_read_set(s);
+ isl_stream_free(s);
+ return set;
+}
+
+struct isl_set *isl_set_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ isl_set *set;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ set = isl_stream_read_set(s);
+ isl_stream_free(s);
+ return set;
+}
+
+__isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
+ FILE *input)
+{
+ isl_union_map *umap;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ umap = isl_stream_read_union_map(s);
+ isl_stream_free(s);
+ return umap;
+}
+
+__isl_give isl_union_map *isl_union_map_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ isl_union_map *umap;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ umap = isl_stream_read_union_map(s);
+ isl_stream_free(s);
+ return umap;
+}
+
+__isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
+ FILE *input)
+{
+ isl_union_set *uset;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ uset = isl_stream_read_union_set(s);
+ isl_stream_free(s);
+ return uset;
+}
+
+__isl_give isl_union_set *isl_union_set_read_from_str(struct isl_ctx *ctx,
+ const char *str)
+{
+ isl_union_set *uset;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ uset = isl_stream_read_union_set(s);
+ isl_stream_free(s);
+ return uset;
+}
+
+static __isl_give isl_vec *isl_vec_read_polylib(struct isl_stream *s)
+{
+ struct isl_vec *vec = NULL;
+ struct isl_token *tok;
+ unsigned size;
+ int j;
+
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting vector length");
+ goto error;
+ }
+
+ size = isl_int_get_si(tok->u.v);
+ isl_token_free(tok);
+
+ vec = isl_vec_alloc(s->ctx, size);
+
+ for (j = 0; j < size; ++j) {
+ tok = isl_stream_next_token(s);
+ if (!tok || tok->type != ISL_TOKEN_VALUE) {
+ isl_stream_error(s, tok, "expecting constant value");
+ goto error;
+ }
+ isl_int_set(vec->el[j], tok->u.v);
+ isl_token_free(tok);
+ }
+
+ return vec;
+error:
+ isl_token_free(tok);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+static __isl_give isl_vec *vec_read(struct isl_stream *s)
+{
+ return isl_vec_read_polylib(s);
+}
+
+__isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
+{
+ isl_vec *v;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ v = vec_read(s);
+ isl_stream_free(s);
+ return v;
+}
+
+__isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
+ struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.v)
+ isl_assert(s->ctx, obj.type == isl_obj_pw_qpolynomial,
+ goto error);
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_pw_qpolynomial *pwqp;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ pwqp = isl_stream_read_pw_qpolynomial(s);
+ isl_stream_free(s);
+ return pwqp;
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
+ FILE *input)
+{
+ isl_pw_qpolynomial *pwqp;
+ struct isl_stream *s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ pwqp = isl_stream_read_pw_qpolynomial(s);
+ isl_stream_free(s);
+ return pwqp;
+}
+
+/* Is the next token an identifer not in "v"?
+ */
+static int next_is_fresh_ident(struct isl_stream *s, struct vars *v)
+{
+ int n = v->n;
+ int fresh;
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ fresh = tok->type == ISL_TOKEN_IDENT && vars_pos(v, tok->u.s, -1) >= n;
+ isl_stream_push_token(s, tok);
+
+ vars_drop(v, v->n - n);
+
+ return fresh;
+}
+
+/* First read the domain of the affine expression, which may be
+ * a parameter space or a set.
+ * The tricky part is that we don't know if the domain is a set or not,
+ * so when we are trying to read the domain, we may actually be reading
+ * the affine expression itself (defined on a parameter domains)
+ * If the tuple we are reading is named, we assume it's the domain.
+ * Also, if inside the tuple, the first thing we find is a nested tuple
+ * or a new identifier, we again assume it's the domain.
+ * Otherwise, we assume we are reading an affine expression.
+ */
+static __isl_give isl_set *read_aff_domain(struct isl_stream *s,
+ __isl_take isl_set *dom, struct vars *v)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (tok && (tok->type == ISL_TOKEN_IDENT || tok->is_keyword)) {
+ isl_stream_push_token(s, tok);
+ return read_map_tuple(s, dom, isl_dim_set, v, 1, 0);
+ }
+ if (!tok || tok->type != '[') {
+ isl_stream_error(s, tok, "expecting '['");
+ goto error;
+ }
+ if (next_is_tuple(s) || next_is_fresh_ident(s, v)) {
+ isl_stream_push_token(s, tok);
+ dom = read_map_tuple(s, dom, isl_dim_set, v, 1, 0);
+ } else
+ isl_stream_push_token(s, tok);
+
+ return dom;
+error:
+ if (tok)
+ isl_stream_push_token(s, tok);
+ isl_set_free(dom);
+ return NULL;
+}
+
+/* Read an affine expression from "s".
+ */
+__isl_give isl_aff *isl_stream_read_aff(struct isl_stream *s)
+{
+ isl_aff *aff;
+ isl_multi_aff *ma;
+
+ ma = isl_stream_read_multi_aff(s);
+ if (!ma)
+ return NULL;
+ if (isl_multi_aff_dim(ma, isl_dim_out) != 1)
+ isl_die(s->ctx, isl_error_invalid,
+ "expecting single affine expression",
+ goto error);
+
+ aff = isl_multi_aff_get_aff(ma, 0);
+ isl_multi_aff_free(ma);
+ return aff;
+error:
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Read a piecewise affine expression from "s" with domain (space) "dom".
+ */
+static __isl_give isl_pw_aff *read_pw_aff_with_dom(struct isl_stream *s,
+ __isl_take isl_set *dom, struct vars *v)
+{
+ isl_pw_aff *pwaff = NULL;
+
+ if (!isl_set_is_params(dom) && isl_stream_eat(s, ISL_TOKEN_TO))
+ goto error;
+
+ if (isl_stream_eat(s, '['))
+ goto error;
+
+ pwaff = accept_affine(s, isl_set_get_space(dom), v);
+
+ if (isl_stream_eat(s, ']'))
+ goto error;
+
+ dom = read_optional_formula(s, dom, v, 0);
+ pwaff = isl_pw_aff_intersect_domain(pwaff, dom);
+
+ return pwaff;
+error:
+ isl_set_free(dom);
+ isl_pw_aff_free(pwaff);
+ return NULL;
+}
+
+__isl_give isl_pw_aff *isl_stream_read_pw_aff(struct isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom = NULL;
+ isl_set *aff_dom;
+ isl_pw_aff *pa = NULL;
+ int n;
+
+ 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;
+
+ n = v->n;
+ aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+ pa = read_pw_aff_with_dom(s, aff_dom, v);
+ vars_drop(v, v->n - n);
+
+ while (isl_stream_eat_if_available(s, ';')) {
+ isl_pw_aff *pa_i;
+
+ n = v->n;
+ aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+ pa_i = read_pw_aff_with_dom(s, aff_dom, v);
+ vars_drop(v, v->n - n);
+
+ pa = isl_pw_aff_union_add(pa, pa_i);
+ }
+
+ if (isl_stream_eat(s, '}'))
+ goto error;
+
+ vars_free(v);
+ isl_set_free(dom);
+ return pa;
+error:
+ vars_free(v);
+ isl_set_free(dom);
+ isl_pw_aff_free(pa);
+ return NULL;
+}
+
+__isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
+{
+ isl_aff *aff;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ aff = isl_stream_read_aff(s);
+ isl_stream_free(s);
+ return aff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
+{
+ isl_pw_aff *pa;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ pa = isl_stream_read_pw_aff(s);
+ isl_stream_free(s);
+ return pa;
+}
+
+/* Read an isl_pw_multi_aff from "s".
+ * We currently read a generic object and if it turns out to be a set or
+ * a map, we convert that to an isl_pw_multi_aff.
+ * It would be more efficient if we were to construct the isl_pw_multi_aff
+ * directly.
+ */
+__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (!obj.v)
+ return NULL;
+
+ if (obj.type == isl_obj_map)
+ return isl_pw_multi_aff_from_map(obj.v);
+ if (obj.type == isl_obj_set)
+ return isl_pw_multi_aff_from_set(obj.v);
+
+ obj.type->free(obj.v);
+ isl_die(s->ctx, isl_error_invalid, "unexpected object type",
+ return NULL);
+}
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_pw_multi_aff *pma;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ pma = isl_stream_read_pw_multi_aff(s);
+ isl_stream_free(s);
+ return pma;
+}
+
+/* Read an isl_union_pw_multi_aff from "s".
+ * We currently read a generic object and if it turns out to be a set or
+ * a map, we convert that to an isl_union_pw_multi_aff.
+ * It would be more efficient if we were to construct
+ * the isl_union_pw_multi_aff directly.
+ */
+__isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
+ struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (!obj.v)
+ return NULL;
+
+ if (obj.type == isl_obj_map || obj.type == isl_obj_set)
+ obj = to_union(s->ctx, obj);
+ if (obj.type == isl_obj_union_map)
+ return isl_union_pw_multi_aff_from_union_map(obj.v);
+ if (obj.type == isl_obj_union_set)
+ return isl_union_pw_multi_aff_from_union_set(obj.v);
+
+ obj.type->free(obj.v);
+ isl_die(s->ctx, isl_error_invalid, "unexpected object type",
+ return NULL);
+}
+
+/* Read an isl_union_pw_multi_aff from "str".
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
+ isl_ctx *ctx, const char *str)
+{
+ isl_union_pw_multi_aff *upma;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ upma = isl_stream_read_union_pw_multi_aff(s);
+ isl_stream_free(s);
+ return upma;
+}
+
+/* Assuming "pa" represents a single affine expression defined on a universe
+ * domain, extract this affine expression.
+ */
+static __isl_give isl_aff *aff_from_pw_aff(__isl_take isl_pw_aff *pa)
+{
+ isl_aff *aff;
+
+ if (!pa)
+ return NULL;
+ if (pa->n != 1)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "expecting single affine expression",
+ goto error);
+ if (!isl_set_plain_is_universe(pa->p[0].set))
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "expecting universe domain",
+ goto error);
+
+ aff = isl_aff_copy(pa->p[0].aff);
+ isl_pw_aff_free(pa);
+ return aff;
+error:
+ isl_pw_aff_free(pa);
+ return NULL;
+}
+
+/* Read a multi-affine expression from "s".
+ * If the multi-affine expression has a domain, then the tuple
+ * representing this domain cannot involve any affine expressions.
+ * The tuple representing the actual expressions needs to consist
+ * of only affine expressions. Moreover, these expressions can
+ * only depend on parameters and input dimensions and not on other
+ * output dimensions.
+ */
+__isl_give isl_multi_aff *isl_stream_read_multi_aff(struct isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom = NULL;
+ isl_multi_pw_aff *tuple = NULL;
+ int dim, i, n;
+ isl_space *space, *dom_space;
+ isl_multi_aff *ma = 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_set_plain_is_universe(dom))
+ isl_die(s->ctx, isl_error_invalid,
+ "expecting universe parameter domain", goto error);
+ if (isl_stream_eat(s, '{'))
+ goto error;
+
+ tuple = read_tuple(s, v, 0, 0);
+ if (!tuple)
+ goto error;
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
+ isl_set *set;
+ isl_space *space;
+ int has_expr;
+
+ has_expr = tuple_has_expr(tuple);
+ if (has_expr < 0)
+ goto error;
+ if (has_expr)
+ isl_die(s->ctx, isl_error_invalid,
+ "expecting universe domain", goto error);
+ space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
+ set = isl_set_universe(space);
+ dom = isl_set_intersect_params(set, dom);
+ isl_multi_pw_aff_free(tuple);
+ tuple = read_tuple(s, v, 0, 0);
+ if (!tuple)
+ goto error;
+ }
+
+ if (isl_stream_eat(s, '}'))
+ goto error;
+
+ n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+ dim = isl_set_dim(dom, isl_dim_all);
+ dom_space = isl_set_get_space(dom);
+ space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
+ space = isl_space_align_params(space, isl_space_copy(dom_space));
+ if (!isl_space_is_params(dom_space))
+ space = isl_space_map_from_domain_and_range(
+ isl_space_copy(dom_space), space);
+ isl_space_free(dom_space);
+ ma = isl_multi_aff_alloc(space);
+
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ isl_aff *aff;
+ pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
+ aff = aff_from_pw_aff(pa);
+ if (!aff)
+ goto error;
+ if (isl_aff_involves_dims(aff, isl_dim_in, dim, i + 1)) {
+ isl_aff_free(aff);
+ isl_die(s->ctx, isl_error_invalid,
+ "not an affine expression", goto error);
+ }
+ aff = isl_aff_drop_dims(aff, isl_dim_in, dim, n);
+ space = isl_multi_aff_get_domain_space(ma);
+ aff = isl_aff_reset_domain_space(aff, space);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ isl_multi_pw_aff_free(tuple);
+ vars_free(v);
+ isl_set_free(dom);
+ return ma;
+error:
+ isl_multi_pw_aff_free(tuple);
+ vars_free(v);
+ isl_set_free(dom);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+__isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_multi_aff *maff;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ maff = isl_stream_read_multi_aff(s);
+ isl_stream_free(s);
+ return maff;
+}
+
+/* Read an isl_multi_pw_aff from "s".
+ *
+ * The input format is similar to that of map, except that any conditions
+ * on the domains should be specified inside the tuple since each
+ * piecewise affine expression may have a different domain.
+ *
+ * Since we do not know in advance if the isl_multi_pw_aff lives
+ * in a set or a map space, we first read the first tuple and check
+ * if it is followed by a "->". If so, we convert the tuple into
+ * the domain of the isl_multi_pw_aff and read in the next tuple.
+ * This tuple (or the first tuple if it was not followed by a "->")
+ * is then converted into the isl_multi_pw_aff.
+ *
+ * Note that the function read_tuple accepts tuples where some output or
+ * set dimensions are defined in terms of other output or set dimensions
+ * since this function is also used to read maps. As a special case,
+ * read_tuple also accept dimensions that are defined in terms of themselves
+ * (i.e., that are not defined).
+ * These cases are not allowed when reading am isl_multi_pw_aff so we check
+ * that the definition of the output/set dimensions does not involve any
+ * output/set dimensions.
+ * We then drop the output dimensions from the domain of the result
+ * of read_tuple (which is of the form [input, output] -> [output],
+ * with anonymous domain) and reset the space.
+ */
+__isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(struct isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom = NULL;
+ isl_multi_pw_aff *tuple = NULL;
+ int dim, i, n;
+ isl_space *space, *dom_space;
+ isl_multi_pw_aff *mpa = 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;
+
+ tuple = read_tuple(s, v, 0, 0);
+ if (!tuple)
+ goto error;
+ if (isl_stream_eat_if_available(s, ISL_TOKEN_TO)) {
+ isl_map *map = map_from_tuple(tuple, dom, isl_dim_in, v, 0);
+ dom = isl_map_domain(map);
+ tuple = read_tuple(s, v, 0, 0);
+ if (!tuple)
+ goto error;
+ }
+
+ if (isl_stream_eat(s, '}'))
+ goto error;
+
+ n = isl_multi_pw_aff_dim(tuple, isl_dim_out);
+ dim = isl_set_dim(dom, isl_dim_all);
+ dom_space = isl_set_get_space(dom);
+ space = isl_space_range(isl_multi_pw_aff_get_space(tuple));
+ space = isl_space_align_params(space, isl_space_copy(dom_space));
+ if (!isl_space_is_params(dom_space))
+ space = isl_space_map_from_domain_and_range(
+ isl_space_copy(dom_space), space);
+ isl_space_free(dom_space);
+ mpa = isl_multi_pw_aff_alloc(space);
+
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ pa = isl_multi_pw_aff_get_pw_aff(tuple, i);
+ if (!pa)
+ goto error;
+ if (isl_pw_aff_involves_dims(pa, isl_dim_in, dim, i + 1)) {
+ isl_pw_aff_free(pa);
+ isl_die(s->ctx, isl_error_invalid,
+ "not an affine expression", goto error);
+ }
+ pa = isl_pw_aff_drop_dims(pa, isl_dim_in, dim, n);
+ space = isl_multi_pw_aff_get_domain_space(mpa);
+ pa = isl_pw_aff_reset_domain_space(pa, space);
+ mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+ }
+
+ isl_multi_pw_aff_free(tuple);
+ vars_free(v);
+ mpa = isl_multi_pw_aff_intersect_domain(mpa, dom);
+ return mpa;
+error:
+ isl_multi_pw_aff_free(tuple);
+ vars_free(v);
+ isl_set_free(dom);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Read an isl_multi_pw_aff from "str".
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_multi_pw_aff *mpa;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ mpa = isl_stream_read_multi_pw_aff(s);
+ isl_stream_free(s);
+ return mpa;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
+ struct isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj = obj_read(s);
+ if (obj.type == isl_obj_pw_qpolynomial) {
+ obj.type = isl_obj_union_pw_qpolynomial;
+ obj.v = isl_union_pw_qpolynomial_from_pw_qpolynomial(obj.v);
+ }
+ if (obj.v)
+ isl_assert(s->ctx, obj.type == isl_obj_union_pw_qpolynomial,
+ goto error);
+
+ return obj.v;
+error:
+ obj.type->free(obj.v);
+ return NULL;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
+ isl_ctx *ctx, const char *str)
+{
+ isl_union_pw_qpolynomial *upwqp;
+ struct isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ upwqp = isl_stream_read_union_pw_qpolynomial(s);
+ isl_stream_free(s);
+ return upwqp;
+}
diff --git a/polly/lib/External/isl/isl_int.h b/polly/lib/External/isl/isl_int.h
new file mode 100644
index 00000000000..3be0661ee2c
--- /dev/null
+++ b/polly/lib/External/isl/isl_int.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_INT_H
+#define ISL_INT_H
+#define ISL_DEPRECATED_INT_H
+
+#include <isl/hash.h>
+#include <isl/printer.h>
+#include <string.h>
+#include <isl_config.h>
+
+#ifdef USE_GMP_FOR_MP
+#include <isl_int_gmp.h>
+#endif
+
+#ifdef USE_IMATH_FOR_MP
+#include <isl_int_imath.h>
+#endif
+
+#define isl_int_is_zero(i) (isl_int_sgn(i) == 0)
+#define isl_int_is_one(i) (isl_int_cmp_si(i,1) == 0)
+#define isl_int_is_negone(i) (isl_int_cmp_si(i,-1) == 0)
+#define isl_int_is_pos(i) (isl_int_sgn(i) > 0)
+#define isl_int_is_neg(i) (isl_int_sgn(i) < 0)
+#define isl_int_is_nonpos(i) (isl_int_sgn(i) <= 0)
+#define isl_int_is_nonneg(i) (isl_int_sgn(i) >= 0)
+
+#define isl_int_print(out,i,width) \
+ do { \
+ char *s; \
+ s = isl_int_get_str(i); \
+ fprintf(out, "%*s", width, s); \
+ isl_int_free_str(s); \
+ } while (0)
+
+__isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
+ isl_int i);
+
+#endif /* ISL_INT_H */
diff --git a/polly/lib/External/isl/isl_int_gmp.h b/polly/lib/External/isl/isl_int_gmp.h
new file mode 100644
index 00000000000..08f2857b1e6
--- /dev/null
+++ b/polly/lib/External/isl/isl_int_gmp.h
@@ -0,0 +1,88 @@
+#ifndef ISL_INT_GMP_H
+#define ISL_INT_GMP_H
+
+#include <gmp.h>
+
+/* isl_int is the basic integer type, implemented with GMP's mpz_t. In the
+ * future, different types such as long long or cln::cl_I will be supported.
+ */
+typedef mpz_t isl_int;
+
+#define isl_int_init(i) mpz_init(i)
+#define isl_int_clear(i) mpz_clear(i)
+
+#define isl_int_set(r,i) mpz_set(r,i)
+#define isl_int_set_si(r,i) mpz_set_si(r,i)
+#define isl_int_set_ui(r,i) mpz_set_ui(r,i)
+#define isl_int_fits_slong(r) mpz_fits_slong_p(r)
+#define isl_int_get_si(r) mpz_get_si(r)
+#define isl_int_fits_ulong(r) mpz_fits_ulong_p(r)
+#define isl_int_get_ui(r) mpz_get_ui(r)
+#define isl_int_get_d(r) mpz_get_d(r)
+#define isl_int_get_str(r) mpz_get_str(0, 10, r)
+#define isl_int_abs(r,i) mpz_abs(r,i)
+#define isl_int_neg(r,i) mpz_neg(r,i)
+#define isl_int_swap(i,j) mpz_swap(i,j)
+#define isl_int_swap_or_set(i,j) mpz_swap(i,j)
+#define isl_int_add_ui(r,i,j) mpz_add_ui(r,i,j)
+#define isl_int_sub_ui(r,i,j) mpz_sub_ui(r,i,j)
+
+#define isl_int_add(r,i,j) mpz_add(r,i,j)
+#define isl_int_sub(r,i,j) mpz_sub(r,i,j)
+#define isl_int_mul(r,i,j) mpz_mul(r,i,j)
+#define isl_int_mul_2exp(r,i,j) mpz_mul_2exp(r,i,j)
+#define isl_int_mul_si(r,i,j) mpz_mul_si(r,i,j)
+#define isl_int_mul_ui(r,i,j) mpz_mul_ui(r,i,j)
+#define isl_int_pow_ui(r,i,j) mpz_pow_ui(r,i,j)
+#define isl_int_addmul(r,i,j) mpz_addmul(r,i,j)
+#define isl_int_addmul_ui(r,i,j) mpz_addmul_ui(r,i,j)
+#define isl_int_submul(r,i,j) mpz_submul(r,i,j)
+#define isl_int_submul_ui(r,i,j) mpz_submul_ui(r,i,j)
+
+#define isl_int_gcd(r,i,j) mpz_gcd(r,i,j)
+#define isl_int_lcm(r,i,j) mpz_lcm(r,i,j)
+#define isl_int_divexact(r,i,j) mpz_divexact(r,i,j)
+#define isl_int_divexact_ui(r,i,j) mpz_divexact_ui(r,i,j)
+#define isl_int_tdiv_q(r,i,j) mpz_tdiv_q(r,i,j)
+#define isl_int_cdiv_q(r,i,j) mpz_cdiv_q(r,i,j)
+#define isl_int_fdiv_q(r,i,j) mpz_fdiv_q(r,i,j)
+#define isl_int_fdiv_r(r,i,j) mpz_fdiv_r(r,i,j)
+#define isl_int_fdiv_q_ui(r,i,j) mpz_fdiv_q_ui(r,i,j)
+
+#define isl_int_read(r,s) mpz_set_str(r,s,10)
+#define isl_int_sgn(i) mpz_sgn(i)
+#define isl_int_cmp(i,j) mpz_cmp(i,j)
+#define isl_int_cmp_si(i,si) mpz_cmp_si(i,si)
+#define isl_int_eq(i,j) (mpz_cmp(i,j) == 0)
+#define isl_int_ne(i,j) (mpz_cmp(i,j) != 0)
+#define isl_int_lt(i,j) (mpz_cmp(i,j) < 0)
+#define isl_int_le(i,j) (mpz_cmp(i,j) <= 0)
+#define isl_int_gt(i,j) (mpz_cmp(i,j) > 0)
+#define isl_int_ge(i,j) (mpz_cmp(i,j) >= 0)
+#define isl_int_abs_cmp(i,j) mpz_cmpabs(i,j)
+#define isl_int_abs_eq(i,j) (mpz_cmpabs(i,j) == 0)
+#define isl_int_abs_ne(i,j) (mpz_cmpabs(i,j) != 0)
+#define isl_int_abs_lt(i,j) (mpz_cmpabs(i,j) < 0)
+#define isl_int_abs_gt(i,j) (mpz_cmpabs(i,j) > 0)
+#define isl_int_abs_ge(i,j) (mpz_cmpabs(i,j) >= 0)
+#define isl_int_is_divisible_by(i,j) mpz_divisible_p(i,j)
+
+uint32_t isl_gmp_hash(mpz_t v, uint32_t hash);
+#define isl_int_hash(v,h) isl_gmp_hash(v,h)
+
+#ifndef mp_get_memory_functions
+void mp_get_memory_functions(
+ void *(**alloc_func_ptr) (size_t),
+ void *(**realloc_func_ptr) (void *, size_t, size_t),
+ void (**free_func_ptr) (void *, size_t));
+#endif
+
+typedef void (*isl_int_print_mp_free_t)(void *, size_t);
+#define isl_int_free_str(s) \
+ do { \
+ isl_int_print_mp_free_t mp_free; \
+ mp_get_memory_functions(NULL, NULL, &mp_free); \
+ (*mp_free)(s, strlen(s) + 1); \
+ } while (0)
+
+#endif /* ISL_INT_GMP_H */
diff --git a/polly/lib/External/isl/isl_int_imath.h b/polly/lib/External/isl/isl_int_imath.h
new file mode 100644
index 00000000000..e5b7186bf16
--- /dev/null
+++ b/polly/lib/External/isl/isl_int_imath.h
@@ -0,0 +1,76 @@
+#ifndef ISL_INT_IMATH_H
+#define ISL_INT_IMATH_H
+
+#include "isl_hide_deprecated.h"
+
+#include <isl_imath.h>
+
+/* isl_int is the basic integer type, implemented with imath's mp_int. */
+typedef mp_int isl_int;
+
+#define isl_int_init(i) i = mp_int_alloc()
+#define isl_int_clear(i) mp_int_free(i)
+
+#define isl_int_set(r,i) impz_set(r,i)
+#define isl_int_set_si(r,i) impz_set_si(r,i)
+#define isl_int_set_ui(r,i) impz_set_ui(r,i)
+#define isl_int_fits_slong(r) isl_imath_fits_slong_p(r)
+#define isl_int_get_si(r) impz_get_si(r)
+#define isl_int_fits_ulong(r) isl_imath_fits_ulong_p(r)
+#define isl_int_get_ui(r) impz_get_ui(r)
+#define isl_int_get_d(r) impz_get_si(r)
+#define isl_int_get_str(r) impz_get_str(0, 10, r)
+#define isl_int_abs(r,i) impz_abs(r,i)
+#define isl_int_neg(r,i) impz_neg(r,i)
+#define isl_int_swap(i,j) impz_swap(i,j)
+#define isl_int_swap_or_set(i,j) impz_swap(i,j)
+#define isl_int_add_ui(r,i,j) impz_add_ui(r,i,j)
+#define isl_int_sub_ui(r,i,j) impz_sub_ui(r,i,j)
+
+#define isl_int_add(r,i,j) impz_add(r,i,j)
+#define isl_int_sub(r,i,j) impz_sub(r,i,j)
+#define isl_int_mul(r,i,j) impz_mul(r,i,j)
+#define isl_int_mul_2exp(r,i,j) impz_mul_2exp(r,i,j)
+#define isl_int_mul_si(r,i,j) mp_int_mul_value(i,j,r)
+#define isl_int_mul_ui(r,i,j) impz_mul_ui(r,i,j)
+#define isl_int_pow_ui(r,i,j) impz_pow_ui(r,i,j)
+#define isl_int_addmul(r,i,j) impz_addmul(r,i,j)
+#define isl_int_addmul_ui(r,i,j) isl_imath_addmul_ui(r,i,j)
+#define isl_int_submul(r,i,j) impz_submul(r,i,j)
+#define isl_int_submul_ui(r,i,j) isl_imath_submul_ui(r,i,j)
+
+#define isl_int_gcd(r,i,j) impz_gcd(r,i,j)
+#define isl_int_lcm(r,i,j) impz_lcm(r,i,j)
+#define isl_int_divexact(r,i,j) impz_divexact(r,i,j)
+#define isl_int_divexact_ui(r,i,j) impz_divexact_ui(r,i,j)
+#define isl_int_tdiv_q(r,i,j) impz_tdiv_q(r,i,j)
+#define isl_int_cdiv_q(r,i,j) impz_cdiv_q(r,i,j)
+#define isl_int_fdiv_q(r,i,j) impz_fdiv_q(r,i,j)
+#define isl_int_fdiv_r(r,i,j) impz_fdiv_r(r,i,j)
+#define isl_int_fdiv_q_ui(r,i,j) impz_fdiv_q_ui(r,i,j)
+
+#define isl_int_read(r,s) impz_set_str(r,s,10)
+#define isl_int_sgn(i) impz_sgn(i)
+#define isl_int_cmp(i,j) impz_cmp(i,j)
+#define isl_int_cmp_si(i,si) impz_cmp_si(i,si)
+#define isl_int_eq(i,j) (impz_cmp(i,j) == 0)
+#define isl_int_ne(i,j) (impz_cmp(i,j) != 0)
+#define isl_int_lt(i,j) (impz_cmp(i,j) < 0)
+#define isl_int_le(i,j) (impz_cmp(i,j) <= 0)
+#define isl_int_gt(i,j) (impz_cmp(i,j) > 0)
+#define isl_int_ge(i,j) (impz_cmp(i,j) >= 0)
+#define isl_int_abs_cmp(i,j) impz_cmpabs(i,j)
+#define isl_int_abs_eq(i,j) (impz_cmpabs(i,j) == 0)
+#define isl_int_abs_ne(i,j) (impz_cmpabs(i,j) != 0)
+#define isl_int_abs_lt(i,j) (impz_cmpabs(i,j) < 0)
+#define isl_int_abs_gt(i,j) (impz_cmpabs(i,j) > 0)
+#define isl_int_abs_ge(i,j) (impz_cmpabs(i,j) >= 0)
+#define isl_int_is_divisible_by(i,j) impz_divisible_p(i,j)
+
+uint32_t isl_imath_hash(mp_int v, uint32_t hash);
+#define isl_int_hash(v,h) isl_imath_hash(v,h)
+
+typedef void (*isl_int_print_mp_free_t)(void *, size_t);
+#define isl_int_free_str(s) free(s)
+
+#endif /* ISL_INT_IMATH_H */
diff --git a/polly/lib/External/isl/isl_list_templ.c b/polly/lib/External/isl/isl_list_templ.c
new file mode 100644
index 00000000000..bee624835a2
--- /dev/null
+++ b/polly/lib/External/isl/isl_list_templ.c
@@ -0,0 +1,522 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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_sort.h>
+#include <isl_tarjan.h>
+
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xLIST(EL) EL ## _list
+#define LIST(EL) xLIST(EL)
+#define xS(TYPE,NAME) struct TYPE ## _ ## NAME
+#define S(TYPE,NAME) xS(TYPE,NAME)
+
+isl_ctx *FN(LIST(EL),get_ctx)(__isl_keep LIST(EL) *list)
+{
+ return list ? list->ctx : NULL;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),alloc)(isl_ctx *ctx, int n)
+{
+ LIST(EL) *list;
+
+ if (n < 0)
+ isl_die(ctx, isl_error_invalid,
+ "cannot create list of negative length",
+ return NULL);
+ list = isl_alloc(ctx, LIST(EL),
+ sizeof(LIST(EL)) + (n - 1) * sizeof(struct EL *));
+ if (!list)
+ return NULL;
+
+ list->ctx = ctx;
+ isl_ctx_ref(ctx);
+ list->ref = 1;
+ list->size = n;
+ list->n = 0;
+ return list;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),copy)(__isl_keep LIST(EL) *list)
+{
+ if (!list)
+ return NULL;
+
+ list->ref++;
+ return list;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),dup)(__isl_keep LIST(EL) *list)
+{
+ int i;
+ LIST(EL) *dup;
+
+ if (!list)
+ return NULL;
+
+ dup = FN(LIST(EL),alloc)(FN(LIST(EL),get_ctx)(list), list->n);
+ if (!dup)
+ return NULL;
+ for (i = 0; i < list->n; ++i)
+ dup = FN(LIST(EL),add)(dup, FN(EL,copy)(list->p[i]));
+ return dup;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),cow)(__isl_take LIST(EL) *list)
+{
+ if (!list)
+ return NULL;
+
+ if (list->ref == 1)
+ return list;
+ list->ref--;
+ return FN(LIST(EL),dup)(list);
+}
+
+/* Make sure "list" has room for at least "n" more pieces.
+ * Always return a list with a single reference.
+ *
+ * If there is only one reference to list, we extend it in place.
+ * Otherwise, we create a new LIST(EL) and copy the elements.
+ */
+static __isl_give LIST(EL) *FN(LIST(EL),grow)(__isl_take LIST(EL) *list, int n)
+{
+ isl_ctx *ctx;
+ int i, new_size;
+ LIST(EL) *res;
+
+ if (!list)
+ return NULL;
+ if (list->ref == 1 && list->n + n <= list->size)
+ return list;
+
+ ctx = FN(LIST(EL),get_ctx)(list);
+ new_size = ((list->n + n + 1) * 3) / 2;
+ if (list->ref == 1) {
+ res = isl_realloc(ctx, list, LIST(EL),
+ sizeof(LIST(EL)) + (new_size - 1) * sizeof(EL *));
+ if (!res)
+ return FN(LIST(EL),free)(list);
+ res->size = new_size;
+ return res;
+ }
+
+ if (list->n + n <= list->size && list->size < new_size)
+ new_size = list->size;
+
+ res = FN(LIST(EL),alloc)(ctx, new_size);
+ if (!res)
+ return FN(LIST(EL),free)(list);
+
+ for (i = 0; i < list->n; ++i)
+ res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
+
+ FN(LIST(EL),free)(list);
+ return res;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),add)(__isl_take LIST(EL) *list,
+ __isl_take struct EL *el)
+{
+ list = FN(LIST(EL),grow)(list, 1);
+ if (!list || !el)
+ goto error;
+ list->p[list->n] = el;
+ list->n++;
+ return list;
+error:
+ FN(EL,free)(el);
+ FN(LIST(EL),free)(list);
+ return NULL;
+}
+
+/* Remove the "n" elements starting at "first" from "list".
+ */
+__isl_give LIST(EL) *FN(LIST(EL),drop)(__isl_take LIST(EL) *list,
+ unsigned first, unsigned n)
+{
+ int i;
+
+ if (!list)
+ return NULL;
+ if (first + n > list->n || first + n < first)
+ isl_die(list->ctx, isl_error_invalid,
+ "index out of bounds", return FN(LIST(EL),free)(list));
+ if (n == 0)
+ return list;
+ list = FN(LIST(EL),cow)(list);
+ if (!list)
+ return NULL;
+ for (i = 0; i < n; ++i)
+ FN(EL,free)(list->p[first + i]);
+ for (i = first; i + n < list->n; ++i)
+ list->p[i] = list->p[i + n];
+ list->n -= n;
+ return list;
+}
+
+/* Insert "el" at position "pos" in "list".
+ *
+ * If there is only one reference to "list" and if it already has space
+ * for one extra element, we insert it directly into "list".
+ * Otherwise, we create a new list consisting of "el" and copied
+ * elements from "list".
+ */
+__isl_give LIST(EL) *FN(LIST(EL),insert)(__isl_take LIST(EL) *list,
+ unsigned pos, __isl_take struct EL *el)
+{
+ int i;
+ isl_ctx *ctx;
+ LIST(EL) *res;
+
+ if (!list || !el)
+ goto error;
+ ctx = FN(LIST(EL),get_ctx)(list);
+ if (pos > list->n)
+ isl_die(ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+
+ if (list->ref == 1 && list->size > list->n) {
+ for (i = list->n - 1; i >= pos; --i)
+ list->p[i + 1] = list->p[i];
+ list->n++;
+ list->p[pos] = el;
+ return list;
+ }
+
+ res = FN(LIST(EL),alloc)(ctx, list->n + 1);
+ for (i = 0; i < pos; ++i)
+ res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
+ res = FN(LIST(EL),add)(res, el);
+ for (i = pos; i < list->n; ++i)
+ res = FN(LIST(EL),add)(res, FN(EL,copy)(list->p[i]));
+ FN(LIST(EL),free)(list);
+
+ return res;
+error:
+ FN(EL,free)(el);
+ FN(LIST(EL),free)(list);
+ return NULL;
+}
+
+__isl_null LIST(EL) *FN(LIST(EL),free)(__isl_take LIST(EL) *list)
+{
+ int i;
+
+ if (!list)
+ return NULL;
+
+ if (--list->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(list->ctx);
+ for (i = 0; i < list->n; ++i)
+ FN(EL,free)(list->p[i]);
+ free(list);
+
+ return NULL;
+}
+
+int FN(FN(LIST(EL),n),BASE)(__isl_keep LIST(EL) *list)
+{
+ return list ? list->n : 0;
+}
+
+__isl_give EL *FN(FN(LIST(EL),get),BASE)(__isl_keep LIST(EL) *list, int index)
+{
+ if (!list)
+ return NULL;
+ if (index < 0 || index >= list->n)
+ isl_die(list->ctx, isl_error_invalid,
+ "index out of bounds", return NULL);
+ return FN(EL,copy)(list->p[index]);
+}
+
+/* Replace the element at position "index" in "list" by "el".
+ */
+__isl_give LIST(EL) *FN(FN(LIST(EL),set),BASE)(__isl_take LIST(EL) *list,
+ int index, __isl_take EL *el)
+{
+ if (!list || !el)
+ goto error;
+ if (index < 0 || index >= list->n)
+ isl_die(list->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+ if (list->p[index] == el) {
+ FN(EL,free)(el);
+ return list;
+ }
+ list = FN(LIST(EL),cow)(list);
+ if (!list)
+ goto error;
+ FN(EL,free)(list->p[index]);
+ list->p[index] = el;
+ return list;
+error:
+ FN(EL,free)(el);
+ FN(LIST(EL),free)(list);
+ return NULL;
+}
+
+int FN(LIST(EL),foreach)(__isl_keep LIST(EL) *list,
+ int (*fn)(__isl_take EL *el, void *user), void *user)
+{
+ int i;
+
+ if (!list)
+ return -1;
+
+ for (i = 0; i < list->n; ++i) {
+ EL *el = FN(EL,copy(list->p[i]));
+ if (!el)
+ return -1;
+ if (fn(el, user) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Internal data structure for isl_*_list_sort.
+ *
+ * "cmp" is the original comparison function.
+ * "user" is a user provided pointer that should be passed to "cmp".
+ */
+S(LIST(EL),sort_data) {
+ int (*cmp)(__isl_keep EL *a, __isl_keep EL *b, void *user);
+ void *user;
+};
+
+/* Compare two entries of an isl_*_list based on the user provided
+ * comparison function on pairs of isl_* objects.
+ */
+static int FN(LIST(EL),cmp)(const void *a, const void *b, void *user)
+{
+ S(LIST(EL),sort_data) *data = user;
+ EL * const *el1 = a;
+ EL * const *el2 = b;
+
+ return data->cmp(*el1, *el2, data->user);
+}
+
+/* Sort the elements of "list" in ascending order according to
+ * comparison function "cmp".
+ */
+__isl_give LIST(EL) *FN(LIST(EL),sort)(__isl_take LIST(EL) *list,
+ int (*cmp)(__isl_keep EL *a, __isl_keep EL *b, void *user), void *user)
+{
+ S(LIST(EL),sort_data) data = { cmp, user };
+
+ if (!list)
+ return NULL;
+ if (list->n <= 1)
+ return list;
+ list = FN(LIST(EL),cow)(list);
+ if (!list)
+ return NULL;
+
+ if (isl_sort(list->p, list->n, sizeof(list->p[0]),
+ &FN(LIST(EL),cmp), &data) < 0)
+ return FN(LIST(EL),free)(list);
+
+ return list;
+}
+
+/* Internal data structure for isl_*_list_foreach_scc.
+ *
+ * "list" is the original list.
+ * "follows" is the user provided callback that defines the edges of the graph.
+ */
+S(LIST(EL),foreach_scc_data) {
+ LIST(EL) *list;
+ int (*follows)(__isl_keep EL *a, __isl_keep EL *b, void *user);
+ void *follows_user;
+};
+
+/* Does element i of data->list follow element j?
+ *
+ * Use the user provided callback to find out.
+ */
+static int FN(LIST(EL),follows)(int i, int j, void *user)
+{
+ S(LIST(EL),foreach_scc_data) *data = user;
+
+ return data->follows(data->list->p[i], data->list->p[j],
+ data->follows_user);
+}
+
+/* Call "fn" on the sublist of "list" that consists of the elements
+ * with indices specified by the "n" elements of "pos".
+ */
+static int FN(LIST(EL),call_on_scc)(__isl_keep LIST(EL) *list, int *pos, int n,
+ int (*fn)(__isl_take LIST(EL) *scc, void *user), void *user)
+{
+ int i;
+ isl_ctx *ctx;
+ LIST(EL) *slice;
+
+ ctx = FN(LIST(EL),get_ctx)(list);
+ slice = FN(LIST(EL),alloc)(ctx, n);
+ for (i = 0; i < n; ++i) {
+ EL *el;
+
+ el = FN(EL,copy)(list->p[pos[i]]);
+ slice = FN(LIST(EL),add)(slice, el);
+ }
+
+ return fn(slice, user);
+}
+
+/* Call "fn" on each of the strongly connected components (SCCs) of
+ * the graph with as vertices the elements of "list" and
+ * a directed edge from node b to node a iff follows(a, b)
+ * returns 1. follows should return -1 on error.
+ *
+ * If SCC a contains a node i that follows a node j in another SCC b
+ * (i.e., follows(i, j, user) returns 1), then fn will be called on SCC a
+ * after being called on SCC b.
+ *
+ * We simply call isl_tarjan_graph_init, extract the SCCs from the result and
+ * call fn on each of them.
+ */
+int FN(LIST(EL),foreach_scc)(__isl_keep LIST(EL) *list,
+ int (*follows)(__isl_keep EL *a, __isl_keep EL *b, void *user),
+ void *follows_user,
+ int (*fn)(__isl_take LIST(EL) *scc, void *user), void *fn_user)
+{
+ S(LIST(EL),foreach_scc_data) data = { list, follows, follows_user };
+ int i, n;
+ isl_ctx *ctx;
+ struct isl_tarjan_graph *g;
+
+ if (!list)
+ return -1;
+ if (list->n == 0)
+ return 0;
+ if (list->n == 1)
+ return fn(FN(LIST(EL),copy)(list), fn_user);
+
+ ctx = FN(LIST(EL),get_ctx)(list);
+ n = list->n;
+ g = isl_tarjan_graph_init(ctx, n, &FN(LIST(EL),follows), &data);
+ if (!g)
+ return -1;
+
+ i = 0;
+ do {
+ int first;
+
+ if (g->order[i] == -1)
+ isl_die(ctx, isl_error_internal, "cannot happen",
+ break);
+ first = i;
+ while (g->order[i] != -1) {
+ ++i; --n;
+ }
+ if (first == 0 && n == 0) {
+ isl_tarjan_graph_free(g);
+ return fn(FN(LIST(EL),copy)(list), fn_user);
+ }
+ if (FN(LIST(EL),call_on_scc)(list, g->order + first, i - first,
+ fn, fn_user) < 0)
+ break;
+ ++i;
+ } while (n);
+
+ isl_tarjan_graph_free(g);
+
+ return n > 0 ? -1 : 0;
+}
+
+__isl_give LIST(EL) *FN(FN(LIST(EL),from),BASE)(__isl_take EL *el)
+{
+ isl_ctx *ctx;
+ LIST(EL) *list;
+
+ if (!el)
+ return NULL;
+ ctx = FN(EL,get_ctx)(el);
+ list = FN(LIST(EL),alloc)(ctx, 1);
+ if (!list)
+ goto error;
+ list = FN(LIST(EL),add)(list, el);
+ return list;
+error:
+ FN(EL,free)(el);
+ return NULL;
+}
+
+__isl_give LIST(EL) *FN(LIST(EL),concat)(__isl_take LIST(EL) *list1,
+ __isl_take LIST(EL) *list2)
+{
+ int i;
+ isl_ctx *ctx;
+ LIST(EL) *res;
+
+ if (!list1 || !list2)
+ goto error;
+
+ ctx = FN(LIST(EL),get_ctx)(list1);
+ res = FN(LIST(EL),alloc)(ctx, list1->n + list2->n);
+ for (i = 0; i < list1->n; ++i)
+ res = FN(LIST(EL),add)(res, FN(EL,copy)(list1->p[i]));
+ for (i = 0; i < list2->n; ++i)
+ res = FN(LIST(EL),add)(res, FN(EL,copy)(list2->p[i]));
+
+ FN(LIST(EL),free)(list1);
+ FN(LIST(EL),free)(list2);
+ return res;
+error:
+ FN(LIST(EL),free)(list1);
+ FN(LIST(EL),free)(list2);
+ return NULL;
+}
+
+__isl_give isl_printer *CAT(isl_printer_print_,LIST(BASE))(
+ __isl_take isl_printer *p, __isl_keep LIST(EL) *list)
+{
+ int i;
+
+ if (!p || !list)
+ goto error;
+ p = isl_printer_print_str(p, "(");
+ for (i = 0; i < list->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, ",");
+ p = CAT(isl_printer_print_,BASE)(p, list->p[i]);
+ }
+ p = isl_printer_print_str(p, ")");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void FN(LIST(EL),dump)(__isl_keep LIST(EL) *list)
+{
+ isl_printer *printer;
+
+ if (!list)
+ return;
+
+ printer = isl_printer_to_file(FN(LIST(EL),get_ctx)(list), stderr);
+ printer = CAT(isl_printer_print_,LIST(BASE))(printer, list);
+ printer = isl_printer_end_line(printer);
+
+ isl_printer_free(printer);
+}
diff --git a/polly/lib/External/isl/isl_list_templ.h b/polly/lib/External/isl/isl_list_templ.h
new file mode 100644
index 00000000000..893f9d91d4c
--- /dev/null
+++ b/polly/lib/External/isl/isl_list_templ.h
@@ -0,0 +1,16 @@
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xLIST(EL) EL ## _list
+#define LIST(EL) xLIST(EL)
+
+struct LIST(EL) {
+ int ref;
+ isl_ctx *ctx;
+
+ int n;
+
+ size_t size;
+ struct EL *p[1];
+};
+
+__isl_give LIST(EL) *FN(LIST(EL),dup)(__isl_keep LIST(EL) *list);
diff --git a/polly/lib/External/isl/isl_local_space.c b/polly/lib/External/isl/isl_local_space.c
new file mode 100644
index 00000000000..4de3b357de1
--- /dev/null
+++ b/polly/lib/External/isl/isl_local_space.c
@@ -0,0 +1,1363 @@
+/*
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2012-2014 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_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_local_space_private.h>
+#include <isl_space_private.h>
+#include <isl_mat_private.h>
+#include <isl_aff_private.h>
+#include <isl_vec_private.h>
+#include <isl_seq.h>
+
+isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls)
+{
+ return ls ? ls->dim->ctx : NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim,
+ __isl_take isl_mat *div)
+{
+ isl_ctx *ctx;
+ isl_local_space *ls = NULL;
+
+ if (!dim || !div)
+ goto error;
+
+ ctx = isl_space_get_ctx(dim);
+ ls = isl_calloc_type(ctx, struct isl_local_space);
+ if (!ls)
+ goto error;
+
+ ls->ref = 1;
+ ls->dim = dim;
+ ls->div = div;
+
+ return ls;
+error:
+ isl_mat_free(div);
+ isl_space_free(dim);
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim,
+ unsigned n_div)
+{
+ isl_ctx *ctx;
+ isl_mat *div;
+ unsigned total;
+
+ if (!dim)
+ return NULL;
+
+ total = isl_space_dim(dim, isl_dim_all);
+
+ ctx = isl_space_get_ctx(dim);
+ div = isl_mat_alloc(ctx, n_div, 1 + 1 + total + n_div);
+ return isl_local_space_alloc_div(dim, div);
+}
+
+__isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim)
+{
+ return isl_local_space_alloc(dim, 0);
+}
+
+__isl_give isl_local_space *isl_local_space_copy(__isl_keep isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ ls->ref++;
+ return ls;
+}
+
+__isl_give isl_local_space *isl_local_space_dup(__isl_keep isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ return isl_local_space_alloc_div(isl_space_copy(ls->dim),
+ isl_mat_copy(ls->div));
+
+}
+
+__isl_give isl_local_space *isl_local_space_cow(__isl_take isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ if (ls->ref == 1)
+ return ls;
+ ls->ref--;
+ return isl_local_space_dup(ls);
+}
+
+__isl_null isl_local_space *isl_local_space_free(
+ __isl_take isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ if (--ls->ref > 0)
+ return NULL;
+
+ isl_space_free(ls->dim);
+ isl_mat_free(ls->div);
+
+ free(ls);
+
+ return NULL;
+}
+
+/* Is the local space that of a parameter domain?
+ */
+int isl_local_space_is_params(__isl_keep isl_local_space *ls)
+{
+ if (!ls)
+ return -1;
+ return isl_space_is_params(ls->dim);
+}
+
+/* Is the local space that of a set?
+ */
+int isl_local_space_is_set(__isl_keep isl_local_space *ls)
+{
+ return ls ? isl_space_is_set(ls->dim) : -1;
+}
+
+/* Return true if the two local spaces are identical, with identical
+ * expressions for the integer divisions.
+ */
+int isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
+ __isl_keep isl_local_space *ls2)
+{
+ int equal;
+
+ if (!ls1 || !ls2)
+ return -1;
+
+ equal = isl_space_is_equal(ls1->dim, ls2->dim);
+ if (equal < 0 || !equal)
+ return equal;
+
+ if (!isl_local_space_divs_known(ls1))
+ return 0;
+ if (!isl_local_space_divs_known(ls2))
+ return 0;
+
+ return isl_mat_is_equal(ls1->div, ls2->div);
+}
+
+/* Compare two isl_local_spaces.
+ *
+ * Return -1 if "ls1" is "smaller" than "ls2", 1 if "ls1" is "greater"
+ * than "ls2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary. We do "prefer" divs that only involve
+ * earlier dimensions in the sense that we consider local spaces where
+ * the first differing div involves earlier dimensions to be smaller.
+ */
+int isl_local_space_cmp(__isl_keep isl_local_space *ls1,
+ __isl_keep isl_local_space *ls2)
+{
+ int i;
+ int cmp;
+ int known1, known2;
+ int last1, last2;
+ int n_col;
+
+ if (ls1 == ls2)
+ return 0;
+ if (!ls1)
+ return -1;
+ if (!ls2)
+ return 1;
+
+ cmp = isl_space_cmp(ls1->dim, ls2->dim);
+ if (cmp != 0)
+ return cmp;
+
+ if (ls1->div->n_row != ls2->div->n_row)
+ return ls1->div->n_row - ls2->div->n_row;
+
+ n_col = isl_mat_cols(ls1->div);
+ for (i = 0; i < ls1->div->n_row; ++i) {
+ known1 = isl_local_space_div_is_known(ls1, i);
+ known2 = isl_local_space_div_is_known(ls2, i);
+ if (!known1 && !known2)
+ continue;
+ if (!known1)
+ return 1;
+ if (!known2)
+ return -1;
+ last1 = isl_seq_last_non_zero(ls1->div->row[i] + 1, n_col - 1);
+ last2 = isl_seq_last_non_zero(ls2->div->row[i] + 1, n_col - 1);
+ if (last1 != last2)
+ return last1 - last2;
+ cmp = isl_seq_cmp(ls1->div->row[i], ls2->div->row[i], n_col);
+ if (cmp != 0)
+ return cmp;
+ }
+
+ return 0;
+}
+
+int isl_local_space_dim(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type)
+{
+ if (!ls)
+ return 0;
+ if (type == isl_dim_div)
+ return ls->div->n_row;
+ if (type == isl_dim_all)
+ return isl_space_dim(ls->dim, isl_dim_all) + ls->div->n_row;
+ return isl_space_dim(ls->dim, type);
+}
+
+unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type)
+{
+ isl_space *dim;
+
+ if (!ls)
+ return 0;
+
+ dim = ls->dim;
+ switch (type) {
+ case isl_dim_cst: return 0;
+ case isl_dim_param: return 1;
+ case isl_dim_in: return 1 + dim->nparam;
+ case isl_dim_out: return 1 + dim->nparam + dim->n_in;
+ case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out;
+ default: return 0;
+ }
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "ls".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_local_space_find_dim_by_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, const char *name)
+{
+ if (!ls)
+ return -1;
+ if (type == isl_dim_div)
+ return -1;
+ return isl_space_find_dim_by_name(ls->dim, type, name);
+}
+
+/* Does the given dimension have a name?
+ */
+int isl_local_space_has_dim_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ return ls ? isl_space_has_dim_name(ls->dim, type, pos) : -1;
+}
+
+const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ return ls ? isl_space_get_dim_name(ls->dim, type, pos) : NULL;
+}
+
+int isl_local_space_has_dim_id(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ return ls ? isl_space_has_dim_id(ls->dim, type, pos) : -1;
+}
+
+__isl_give isl_id *isl_local_space_get_dim_id(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos)
+{
+ return ls ? isl_space_get_dim_id(ls->dim, type, pos) : NULL;
+}
+
+__isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls,
+ int pos)
+{
+ isl_aff *aff;
+
+ if (!ls)
+ return NULL;
+
+ if (pos < 0 || pos >= ls->div->n_row)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "index out of bounds", return NULL);
+
+ if (isl_int_is_zero(ls->div->row[pos][0]))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "expression of div unknown", return NULL);
+ if (!isl_local_space_is_set(ls))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "cannot represent divs of map spaces", return NULL);
+
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ if (!aff)
+ return NULL;
+ isl_seq_cpy(aff->v->el, ls->div->row[pos], aff->v->size);
+ return aff;
+}
+
+__isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ return isl_space_copy(ls->dim);
+}
+
+/* Replace the identifier of the tuple of type "type" by "id".
+ */
+__isl_give isl_local_space *isl_local_space_set_tuple_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ goto error;
+ ls->dim = isl_space_set_tuple_id(ls->dim, type, id);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ return ls;
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_set_dim_name(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+ ls->dim = isl_space_set_dim_name(ls->dim, type, pos, s);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+__isl_give isl_local_space *isl_local_space_set_dim_id(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ goto error;
+ ls->dim = isl_space_set_dim_id(ls->dim, type, pos, id);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_reset_space(
+ __isl_take isl_local_space *ls, __isl_take isl_space *dim)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls || !dim)
+ goto error;
+
+ isl_space_free(ls->dim);
+ ls->dim = dim;
+
+ return ls;
+error:
+ isl_local_space_free(ls);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Reorder the columns of the given div definitions according to the
+ * given reordering.
+ * The order of the divs themselves is assumed not to change.
+ */
+static __isl_give isl_mat *reorder_divs(__isl_take isl_mat *div,
+ __isl_take isl_reordering *r)
+{
+ int i, j;
+ isl_mat *mat;
+ int extra;
+
+ if (!div || !r)
+ goto error;
+
+ extra = isl_space_dim(r->dim, isl_dim_all) + div->n_row - r->len;
+ mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra);
+ if (!mat)
+ goto error;
+
+ for (i = 0; i < div->n_row; ++i) {
+ isl_seq_cpy(mat->row[i], div->row[i], 2);
+ isl_seq_clr(mat->row[i] + 2, mat->n_col - 2);
+ for (j = 0; j < r->len; ++j)
+ isl_int_set(mat->row[i][2 + r->pos[j]],
+ div->row[i][2 + j]);
+ }
+
+ isl_reordering_free(r);
+ isl_mat_free(div);
+ return mat;
+error:
+ isl_reordering_free(r);
+ isl_mat_free(div);
+ return NULL;
+}
+
+/* Reorder the dimensions of "ls" according to the given reordering.
+ * The reordering r is assumed to have been extended with the local
+ * variables, leaving them in the same order.
+ */
+__isl_give isl_local_space *isl_local_space_realign(
+ __isl_take isl_local_space *ls, __isl_take isl_reordering *r)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls || !r)
+ goto error;
+
+ ls->div = reorder_divs(ls->div, isl_reordering_copy(r));
+ if (!ls->div)
+ goto error;
+
+ ls = isl_local_space_reset_space(ls, isl_space_copy(r->dim));
+
+ isl_reordering_free(r);
+ return ls;
+error:
+ isl_local_space_free(ls);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_add_div(
+ __isl_take isl_local_space *ls, __isl_take isl_vec *div)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls || !div)
+ goto error;
+
+ if (ls->div->n_col != div->size)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "incompatible dimensions", goto error);
+
+ ls->div = isl_mat_add_zero_cols(ls->div, 1);
+ ls->div = isl_mat_add_rows(ls->div, 1);
+ if (!ls->div)
+ goto error;
+
+ isl_seq_cpy(ls->div->row[ls->div->n_row - 1], div->el, div->size);
+ isl_int_set_si(ls->div->row[ls->div->n_row - 1][div->size], 0);
+
+ isl_vec_free(div);
+ return ls;
+error:
+ isl_local_space_free(ls);
+ isl_vec_free(div);
+ return NULL;
+}
+
+__isl_give isl_local_space *isl_local_space_replace_divs(
+ __isl_take isl_local_space *ls, __isl_take isl_mat *div)
+{
+ ls = isl_local_space_cow(ls);
+
+ if (!ls || !div)
+ goto error;
+
+ isl_mat_free(ls->div);
+ ls->div = div;
+ return ls;
+error:
+ isl_mat_free(div);
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+/* Copy row "s" of "src" to row "d" of "dst", applying the expansion
+ * defined by "exp".
+ */
+static void expand_row(__isl_keep isl_mat *dst, int d,
+ __isl_keep isl_mat *src, int s, int *exp)
+{
+ int i;
+ unsigned c = src->n_col - src->n_row;
+
+ isl_seq_cpy(dst->row[d], src->row[s], c);
+ isl_seq_clr(dst->row[d] + c, dst->n_col - c);
+
+ for (i = 0; i < s; ++i)
+ isl_int_set(dst->row[d][c + exp[i]], src->row[s][c + i]);
+}
+
+/* Compare (known) divs.
+ * Return non-zero if at least one of the two divs is unknown.
+ * In particular, if both divs are unknown, we respect their
+ * current order. Otherwise, we sort the known div after the unknown
+ * div only if the known div depends on the unknown div.
+ */
+static int cmp_row(isl_int *row_i, isl_int *row_j, int i, int j,
+ unsigned n_row, unsigned n_col)
+{
+ int li, lj;
+ int unknown_i, unknown_j;
+
+ unknown_i = isl_int_is_zero(row_i[0]);
+ unknown_j = isl_int_is_zero(row_j[0]);
+
+ if (unknown_i && unknown_j)
+ return i - j;
+
+ if (unknown_i)
+ li = n_col - n_row + i;
+ else
+ li = isl_seq_last_non_zero(row_i, n_col);
+ if (unknown_j)
+ lj = n_col - n_row + j;
+ else
+ lj = isl_seq_last_non_zero(row_j, n_col);
+
+ if (li != lj)
+ return li - lj;
+
+ return isl_seq_cmp(row_i, row_j, n_col);
+}
+
+/* Call cmp_row for divs in a matrix.
+ */
+int isl_mat_cmp_div(__isl_keep isl_mat *div, int i, int j)
+{
+ return cmp_row(div->row[i], div->row[j], i, j, div->n_row, div->n_col);
+}
+
+/* Call cmp_row for divs in a basic map.
+ */
+static int bmap_cmp_row(__isl_keep isl_basic_map *bmap, int i, int j,
+ unsigned total)
+{
+ return cmp_row(bmap->div[i], bmap->div[j], i, j, bmap->n_div, total);
+}
+
+/* Sort the divs in "bmap".
+ *
+ * We first make sure divs are placed after divs on which they depend.
+ * Then we perform a simple insertion sort based on the same ordering
+ * that is used in isl_merge_divs.
+ */
+__isl_give isl_basic_map *isl_basic_map_sort_divs(
+ __isl_take isl_basic_map *bmap)
+{
+ int i, j;
+ unsigned total;
+
+ bmap = isl_basic_map_order_divs(bmap);
+ if (!bmap)
+ return NULL;
+ if (bmap->n_div <= 1)
+ return bmap;
+
+ total = 2 + isl_basic_map_total_dim(bmap);
+ for (i = 1; i < bmap->n_div; ++i) {
+ for (j = i - 1; j >= 0; --j) {
+ if (bmap_cmp_row(bmap, j, j + 1, total) <= 0)
+ break;
+ isl_basic_map_swap_div(bmap, j, j + 1);
+ }
+ }
+
+ return bmap;
+}
+
+/* Sort the divs in the basic maps of "map".
+ */
+__isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map)
+{
+ return isl_map_inline_foreach_basic_map(map, &isl_basic_map_sort_divs);
+}
+
+/* Combine the two lists of divs into a single list.
+ * For each row i in div1, exp1[i] is set to the position of the corresponding
+ * row in the result. Similarly for div2 and exp2.
+ * This function guarantees
+ * exp1[i] >= i
+ * exp1[i+1] > exp1[i]
+ * For optimal merging, the two input list should have been sorted.
+ */
+__isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1,
+ __isl_keep isl_mat *div2, int *exp1, int *exp2)
+{
+ int i, j, k;
+ isl_mat *div = NULL;
+ unsigned d;
+
+ if (!div1 || !div2)
+ return NULL;
+
+ d = div1->n_col - div1->n_row;
+ div = isl_mat_alloc(div1->ctx, 1 + div1->n_row + div2->n_row,
+ d + div1->n_row + div2->n_row);
+ if (!div)
+ return NULL;
+
+ for (i = 0, j = 0, k = 0; i < div1->n_row && j < div2->n_row; ++k) {
+ int cmp;
+
+ expand_row(div, k, div1, i, exp1);
+ expand_row(div, k + 1, div2, j, exp2);
+
+ cmp = isl_mat_cmp_div(div, k, k + 1);
+ if (cmp == 0) {
+ exp1[i++] = k;
+ exp2[j++] = k;
+ } else if (cmp < 0) {
+ exp1[i++] = k;
+ } else {
+ exp2[j++] = k;
+ isl_seq_cpy(div->row[k], div->row[k + 1], div->n_col);
+ }
+ }
+ for (; i < div1->n_row; ++i, ++k) {
+ expand_row(div, k, div1, i, exp1);
+ exp1[i] = k;
+ }
+ for (; j < div2->n_row; ++j, ++k) {
+ expand_row(div, k, div2, j, exp2);
+ exp2[j] = k;
+ }
+
+ div->n_row = k;
+ div->n_col = d + k;
+
+ return div;
+}
+
+/* Swap divs "a" and "b" in "ls".
+ */
+__isl_give isl_local_space *isl_local_space_swap_div(
+ __isl_take isl_local_space *ls, int a, int b)
+{
+ int offset;
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+ if (a < 0 || a >= ls->div->n_row || b < 0 || b >= ls->div->n_row)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "index out of bounds", return isl_local_space_free(ls));
+ offset = ls->div->n_col - ls->div->n_row;
+ ls->div = isl_mat_swap_cols(ls->div, offset + a, offset + b);
+ ls->div = isl_mat_swap_rows(ls->div, a, b);
+ if (!ls->div)
+ return isl_local_space_free(ls);
+ return ls;
+}
+
+/* Construct a local space that contains all the divs in either
+ * "ls1" or "ls2".
+ */
+__isl_give isl_local_space *isl_local_space_intersect(
+ __isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2)
+{
+ isl_ctx *ctx;
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_mat *div;
+ int equal;
+
+ if (!ls1 || !ls2)
+ goto error;
+
+ ctx = isl_local_space_get_ctx(ls1);
+ if (!isl_space_is_equal(ls1->dim, ls2->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces should be identical", goto error);
+
+ if (ls2->div->n_row == 0) {
+ isl_local_space_free(ls2);
+ return ls1;
+ }
+
+ if (ls1->div->n_row == 0) {
+ isl_local_space_free(ls1);
+ return ls2;
+ }
+
+ exp1 = isl_alloc_array(ctx, int, ls1->div->n_row);
+ exp2 = isl_alloc_array(ctx, int, ls2->div->n_row);
+ if (!exp1 || !exp2)
+ goto error;
+
+ div = isl_merge_divs(ls1->div, ls2->div, exp1, exp2);
+ if (!div)
+ goto error;
+
+ equal = isl_mat_is_equal(ls1->div, div);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ ls1 = isl_local_space_cow(ls1);
+ if (!ls1)
+ goto error;
+
+ free(exp1);
+ free(exp2);
+ isl_local_space_free(ls2);
+ isl_mat_free(ls1->div);
+ ls1->div = div;
+
+ return ls1;
+error:
+ free(exp1);
+ free(exp2);
+ isl_local_space_free(ls1);
+ isl_local_space_free(ls2);
+ return NULL;
+}
+
+/* Does "ls" have an explicit representation for div "div"?
+ */
+int isl_local_space_div_is_known(__isl_keep isl_local_space *ls, int div)
+{
+ if (!ls)
+ return -1;
+ if (div < 0 || div >= ls->div->n_row)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "position out of bounds", return -1);
+ return !isl_int_is_zero(ls->div->row[div][0]);
+}
+
+int isl_local_space_divs_known(__isl_keep isl_local_space *ls)
+{
+ int i;
+
+ if (!ls)
+ return -1;
+
+ for (i = 0; i < ls->div->n_row; ++i)
+ if (isl_int_is_zero(ls->div->row[i][0]))
+ return 0;
+
+ return 1;
+}
+
+__isl_give isl_local_space *isl_local_space_domain(
+ __isl_take isl_local_space *ls)
+{
+ ls = isl_local_space_drop_dims(ls, isl_dim_out,
+ 0, isl_local_space_dim(ls, isl_dim_out));
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+ ls->dim = isl_space_domain(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ return ls;
+}
+
+__isl_give isl_local_space *isl_local_space_range(
+ __isl_take isl_local_space *ls)
+{
+ ls = isl_local_space_drop_dims(ls, isl_dim_in,
+ 0, isl_local_space_dim(ls, isl_dim_in));
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ ls->dim = isl_space_range(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ return ls;
+}
+
+/* Construct a local space for a map that has the given local
+ * space as domain and that has a zero-dimensional range.
+ */
+__isl_give isl_local_space *isl_local_space_from_domain(
+ __isl_take isl_local_space *ls)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+ ls->dim = isl_space_from_domain(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ return ls;
+}
+
+__isl_give isl_local_space *isl_local_space_add_dims(
+ __isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n)
+{
+ int pos;
+
+ if (!ls)
+ return NULL;
+ pos = isl_local_space_dim(ls, type);
+ return isl_local_space_insert_dims(ls, type, pos, n);
+}
+
+/* Remove common factor of non-constant terms and denominator.
+ */
+static void normalize_div(__isl_keep isl_local_space *ls, int div)
+{
+ isl_ctx *ctx = ls->div->ctx;
+ unsigned total = ls->div->n_col - 2;
+
+ isl_seq_gcd(ls->div->row[div] + 2, total, &ctx->normalize_gcd);
+ isl_int_gcd(ctx->normalize_gcd,
+ ctx->normalize_gcd, ls->div->row[div][0]);
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return;
+
+ isl_seq_scale_down(ls->div->row[div] + 2, ls->div->row[div] + 2,
+ ctx->normalize_gcd, total);
+ isl_int_divexact(ls->div->row[div][0], ls->div->row[div][0],
+ ctx->normalize_gcd);
+ isl_int_fdiv_q(ls->div->row[div][1], ls->div->row[div][1],
+ ctx->normalize_gcd);
+}
+
+/* Exploit the equalities in "eq" to simplify the expressions of
+ * the integer divisions in "ls".
+ * The integer divisions in "ls" are assumed to appear as regular
+ * dimensions in "eq".
+ */
+__isl_give isl_local_space *isl_local_space_substitute_equalities(
+ __isl_take isl_local_space *ls, __isl_take isl_basic_set *eq)
+{
+ int i, j, k;
+ unsigned total;
+ unsigned n_div;
+
+ if (!ls || !eq)
+ goto error;
+
+ total = isl_space_dim(eq->dim, isl_dim_all);
+ if (isl_local_space_dim(ls, isl_dim_all) != total)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "spaces don't match", goto error);
+ total++;
+ n_div = eq->n_div;
+ for (i = 0; i < eq->n_eq; ++i) {
+ j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
+ if (j < 0 || j == 0 || j >= total)
+ continue;
+
+ for (k = 0; k < ls->div->n_row; ++k) {
+ if (isl_int_is_zero(ls->div->row[k][1 + j]))
+ continue;
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ goto error;
+ ls->div = isl_mat_cow(ls->div);
+ if (!ls->div)
+ goto error;
+ isl_seq_elim(ls->div->row[k] + 1, eq->eq[i], j, total,
+ &ls->div->row[k][0]);
+ normalize_div(ls, k);
+ }
+ }
+
+ isl_basic_set_free(eq);
+ return ls;
+error:
+ isl_basic_set_free(eq);
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+/* Plug in the affine expressions "subs" of length "subs_len" (including
+ * the denominator and the constant term) into the variable at position "pos"
+ * of the "n" div expressions starting at "first".
+ *
+ * Let i be the dimension to replace and let "subs" be of the form
+ *
+ * f/d
+ *
+ * Any integer division starting at "first" with a non-zero coefficient for i,
+ *
+ * floor((a i + g)/m)
+ *
+ * is replaced by
+ *
+ * floor((a f + d g)/(m d))
+ */
+__isl_give isl_local_space *isl_local_space_substitute_seq(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, isl_int *subs, int subs_len,
+ int first, int n)
+{
+ int i;
+ isl_int v;
+
+ if (n == 0)
+ return ls;
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+ ls->div = isl_mat_cow(ls->div);
+ if (!ls->div)
+ return isl_local_space_free(ls);
+
+ if (first + n > ls->div->n_row)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "index out of bounds", return isl_local_space_free(ls));
+
+ pos += isl_local_space_offset(ls, type);
+
+ isl_int_init(v);
+ for (i = first; i < ls->div->n_row; ++i) {
+ if (isl_int_is_zero(ls->div->row[i][1 + pos]))
+ continue;
+ isl_seq_substitute(ls->div->row[i], pos, subs,
+ ls->div->n_col, subs_len, v);
+ normalize_div(ls, i);
+ }
+ isl_int_clear(v);
+
+ return ls;
+}
+
+/* Plug in "subs" for dimension "type", "pos" in the integer divisions
+ * of "ls".
+ *
+ * Let i be the dimension to replace and let "subs" be of the form
+ *
+ * f/d
+ *
+ * Any integer division with a non-zero coefficient for i,
+ *
+ * floor((a i + g)/m)
+ *
+ * is replaced by
+ *
+ * floor((a f + d g)/(m d))
+ */
+__isl_give isl_local_space *isl_local_space_substitute(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls || !subs)
+ return isl_local_space_free(ls);
+
+ if (!isl_space_is_equal(ls->dim, subs->ls->dim))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "spaces don't match", return isl_local_space_free(ls));
+ if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
+ "cannot handle divs yet",
+ return isl_local_space_free(ls));
+
+ return isl_local_space_substitute_seq(ls, type, pos, subs->v->el,
+ subs->v->size, 0, ls->div->n_row);
+}
+
+int isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type)
+{
+ if (!ls)
+ return -1;
+ return isl_space_is_named_or_nested(ls->dim, type);
+}
+
+__isl_give isl_local_space *isl_local_space_drop_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_ctx *ctx;
+
+ if (!ls)
+ return NULL;
+ if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
+ return ls;
+
+ ctx = isl_local_space_get_ctx(ls);
+ if (first + n > isl_local_space_dim(ls, type))
+ isl_die(ctx, isl_error_invalid, "range out of bounds",
+ return isl_local_space_free(ls));
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ if (type == isl_dim_div) {
+ ls->div = isl_mat_drop_rows(ls->div, first, n);
+ } else {
+ ls->dim = isl_space_drop_dims(ls->dim, type, first, n);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ }
+
+ first += 1 + isl_local_space_offset(ls, type);
+ ls->div = isl_mat_drop_cols(ls->div, first, n);
+ if (!ls->div)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+__isl_give isl_local_space *isl_local_space_insert_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_ctx *ctx;
+
+ if (!ls)
+ return NULL;
+ if (n == 0 && !isl_local_space_is_named_or_nested(ls, type))
+ return ls;
+
+ ctx = isl_local_space_get_ctx(ls);
+ if (first > isl_local_space_dim(ls, type))
+ isl_die(ctx, isl_error_invalid, "position out of bounds",
+ return isl_local_space_free(ls));
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ if (type == isl_dim_div) {
+ ls->div = isl_mat_insert_zero_rows(ls->div, first, n);
+ } else {
+ ls->dim = isl_space_insert_dims(ls->dim, type, first, n);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+ }
+
+ first += 1 + isl_local_space_offset(ls, type);
+ ls->div = isl_mat_insert_zero_cols(ls->div, first, n);
+ if (!ls->div)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+/* Check if the constraints pointed to by "constraint" is a div
+ * constraint corresponding to div "div" in "ls".
+ *
+ * That is, if div = floor(f/m), then check if the constraint is
+ *
+ * f - m d >= 0
+ * or
+ * -(f-(m-1)) + m d >= 0
+ */
+int isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls,
+ isl_int *constraint, unsigned div)
+{
+ unsigned pos;
+
+ if (!ls)
+ return -1;
+
+ if (isl_int_is_zero(ls->div->row[div][0]))
+ return 0;
+
+ pos = isl_local_space_offset(ls, isl_dim_div) + div;
+
+ if (isl_int_eq(constraint[pos], ls->div->row[div][0])) {
+ int neg;
+ isl_int_sub(ls->div->row[div][1],
+ ls->div->row[div][1], ls->div->row[div][0]);
+ isl_int_add_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
+ neg = isl_seq_is_neg(constraint, ls->div->row[div]+1, pos);
+ isl_int_sub_ui(ls->div->row[div][1], ls->div->row[div][1], 1);
+ isl_int_add(ls->div->row[div][1],
+ ls->div->row[div][1], ls->div->row[div][0]);
+ if (!neg)
+ return 0;
+ if (isl_seq_first_non_zero(constraint+pos+1,
+ ls->div->n_row-div-1) != -1)
+ return 0;
+ } else if (isl_int_abs_eq(constraint[pos], ls->div->row[div][0])) {
+ if (!isl_seq_eq(constraint, ls->div->row[div]+1, pos))
+ return 0;
+ if (isl_seq_first_non_zero(constraint+pos+1,
+ ls->div->n_row-div-1) != -1)
+ return 0;
+ } else
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Set active[i] to 1 if the dimension at position i is involved
+ * in the linear expression l.
+ */
+int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l)
+{
+ int i, j;
+ isl_ctx *ctx;
+ int *active = NULL;
+ unsigned total;
+ unsigned offset;
+
+ ctx = isl_local_space_get_ctx(ls);
+ total = isl_local_space_dim(ls, isl_dim_all);
+ active = isl_calloc_array(ctx, int, total);
+ if (total && !active)
+ return NULL;
+
+ for (i = 0; i < total; ++i)
+ active[i] = !isl_int_is_zero(l[i]);
+
+ offset = isl_local_space_offset(ls, isl_dim_div) - 1;
+ for (i = ls->div->n_row - 1; i >= 0; --i) {
+ if (!active[offset + i])
+ continue;
+ for (j = 0; j < total; ++j)
+ active[j] |= !isl_int_is_zero(ls->div->row[i][2 + j]);
+ }
+
+ return active;
+}
+
+/* Given a local space "ls" of a set, create a local space
+ * for the lift of the set. In particular, the result
+ * is of the form [dim -> local[..]], with ls->div->n_row variables in the
+ * range of the wrapped map.
+ */
+__isl_give isl_local_space *isl_local_space_lift(
+ __isl_take isl_local_space *ls)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ ls->dim = isl_space_lift(ls->dim, ls->div->n_row);
+ ls->div = isl_mat_drop_rows(ls->div, 0, ls->div->n_row);
+ if (!ls->dim || !ls->div)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+/* Construct a basic map that maps a set living in local space "ls"
+ * to the corresponding lifted local space.
+ */
+__isl_give isl_basic_map *isl_local_space_lifting(
+ __isl_take isl_local_space *ls)
+{
+ isl_basic_map *lifting;
+ isl_basic_set *bset;
+
+ if (!ls)
+ return NULL;
+ if (!isl_local_space_is_set(ls))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "lifting only defined on set spaces", goto error);
+
+ bset = isl_basic_set_from_local_space(ls);
+ lifting = isl_basic_set_unwrap(isl_basic_set_lift(bset));
+ lifting = isl_basic_map_domain_map(lifting);
+ lifting = isl_basic_map_reverse(lifting);
+
+ return lifting;
+error:
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+/* Compute the preimage of "ls" under the function represented by "ma".
+ * In other words, plug in "ma" in "ls". The result is a local space
+ * that is part of the domain space of "ma".
+ *
+ * If the divs in "ls" are represented as
+ *
+ * floor((a_i(p) + b_i x + c_i(divs))/n_i)
+ *
+ * and ma is represented by
+ *
+ * x = D(p) + F(y) + G(divs')
+ *
+ * then the resulting divs are
+ *
+ * floor((a_i(p) + b_i D(p) + b_i F(y) + B_i G(divs') + c_i(divs))/n_i)
+ *
+ * We first copy over the divs from "ma" and then
+ * we add the modified divs from "ls".
+ */
+__isl_give isl_local_space *isl_local_space_preimage_multi_aff(
+ __isl_take isl_local_space *ls, __isl_take isl_multi_aff *ma)
+{
+ int i;
+ isl_space *space;
+ isl_local_space *res = NULL;
+ int n_div_ls, n_div_ma;
+ isl_int f, c1, c2, g;
+
+ ma = isl_multi_aff_align_divs(ma);
+ if (!ls || !ma)
+ goto error;
+ if (!isl_space_is_range_internal(ls->dim, ma->space))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ n_div_ls = isl_local_space_dim(ls, isl_dim_div);
+ n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
+
+ space = isl_space_domain(isl_multi_aff_get_space(ma));
+ res = isl_local_space_alloc(space, n_div_ma + n_div_ls);
+ if (!res)
+ goto error;
+
+ if (n_div_ma) {
+ isl_mat_free(res->div);
+ res->div = isl_mat_copy(ma->p[0]->ls->div);
+ res->div = isl_mat_add_zero_cols(res->div, n_div_ls);
+ res->div = isl_mat_add_rows(res->div, n_div_ls);
+ if (!res->div)
+ goto error;
+ }
+
+ isl_int_init(f);
+ isl_int_init(c1);
+ isl_int_init(c2);
+ isl_int_init(g);
+
+ for (i = 0; i < ls->div->n_row; ++i) {
+ if (isl_int_is_zero(ls->div->row[i][0])) {
+ isl_int_set_si(res->div->row[n_div_ma + i][0], 0);
+ continue;
+ }
+ isl_seq_preimage(res->div->row[n_div_ma + i], ls->div->row[i],
+ ma, 0, 0, n_div_ma, n_div_ls, f, c1, c2, g, 1);
+ normalize_div(res, n_div_ma + i);
+ }
+
+ isl_int_clear(f);
+ isl_int_clear(c1);
+ isl_int_clear(c2);
+ isl_int_clear(g);
+
+ isl_local_space_free(ls);
+ isl_multi_aff_free(ma);
+ return res;
+error:
+ isl_local_space_free(ls);
+ isl_multi_aff_free(ma);
+ isl_local_space_free(res);
+ return NULL;
+}
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of "ls"
+ * to dimensions of "dst_type" at "dst_pos".
+ *
+ * Moving to/from local dimensions is not allowed.
+ * We currently assume that the dimension type changes.
+ */
+__isl_give isl_local_space *isl_local_space_move_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ unsigned g_dst_pos;
+ unsigned g_src_pos;
+
+ if (!ls)
+ return NULL;
+ if (n == 0 &&
+ !isl_local_space_is_named_or_nested(ls, src_type) &&
+ !isl_local_space_is_named_or_nested(ls, dst_type))
+ return ls;
+
+ if (src_pos + n > isl_local_space_dim(ls, src_type))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "range out of bounds", return isl_local_space_free(ls));
+ if (dst_pos > isl_local_space_dim(ls, dst_type))
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "position out of bounds",
+ return isl_local_space_free(ls));
+ if (src_type == isl_dim_div)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "cannot move divs", return isl_local_space_free(ls));
+ if (dst_type == isl_dim_div)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_invalid,
+ "cannot move to divs", return isl_local_space_free(ls));
+ if (dst_type == src_type && dst_pos == src_pos)
+ return ls;
+ if (dst_type == src_type)
+ isl_die(isl_local_space_get_ctx(ls), isl_error_unsupported,
+ "moving dims within the same type not supported",
+ return isl_local_space_free(ls));
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ g_src_pos = 1 + isl_local_space_offset(ls, src_type) + src_pos;
+ g_dst_pos = 1 + isl_local_space_offset(ls, dst_type) + dst_pos;
+ if (dst_type > src_type)
+ g_dst_pos -= n;
+ ls->div = isl_mat_move_cols(ls->div, g_dst_pos, g_src_pos, n);
+ if (!ls->div)
+ return isl_local_space_free(ls);
+ ls->dim = isl_space_move_dims(ls->dim, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+/* Remove any internal structure of the domain of "ls".
+ * If there is any such internal structure in the input,
+ * then the name of the corresponding space is also removed.
+ */
+__isl_give isl_local_space *isl_local_space_flatten_domain(
+ __isl_take isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ if (!ls->dim->nested[0])
+ return ls;
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ ls->dim = isl_space_flatten_domain(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
+
+/* Remove any internal structure of the range of "ls".
+ * If there is any such internal structure in the input,
+ * then the name of the corresponding space is also removed.
+ */
+__isl_give isl_local_space *isl_local_space_flatten_range(
+ __isl_take isl_local_space *ls)
+{
+ if (!ls)
+ return NULL;
+
+ if (!ls->dim->nested[1])
+ return ls;
+
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ ls->dim = isl_space_flatten_range(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
diff --git a/polly/lib/External/isl/isl_local_space_private.h b/polly/lib/External/isl/isl_local_space_private.h
new file mode 100644
index 00000000000..4d7e69ff2b5
--- /dev/null
+++ b/polly/lib/External/isl/isl_local_space_private.h
@@ -0,0 +1,75 @@
+#ifndef ISL_LOCAL_SPACE_PRIVATE_H
+#define ISL_LOCAL_SPACE_PRIVATE_H
+
+#include <isl/mat.h>
+#include <isl/set.h>
+#include <isl/local_space.h>
+
+struct isl_local_space {
+ int ref;
+
+ isl_space *dim;
+ isl_mat *div;
+};
+
+__isl_give isl_local_space *isl_local_space_alloc(__isl_take isl_space *dim,
+ unsigned n_div);
+__isl_give isl_local_space *isl_local_space_alloc_div(__isl_take isl_space *dim,
+ __isl_take isl_mat *div);
+
+__isl_give isl_local_space *isl_local_space_swap_div(
+ __isl_take isl_local_space *ls, int a, int b);
+__isl_give isl_local_space *isl_local_space_add_div(
+ __isl_take isl_local_space *ls, __isl_take isl_vec *div);
+
+int isl_mat_cmp_div(__isl_keep isl_mat *div, int i, int j);
+__isl_give isl_mat *isl_merge_divs(__isl_keep isl_mat *div1,
+ __isl_keep isl_mat *div2, int *exp1, int *exp2);
+
+unsigned isl_local_space_offset(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type);
+
+__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_give isl_local_space *isl_local_space_substitute_equalities(
+ __isl_take isl_local_space *ls, __isl_take isl_basic_set *eq);
+
+int isl_local_space_is_named_or_nested(__isl_keep isl_local_space *ls,
+ enum isl_dim_type type);
+
+__isl_give isl_local_space *isl_local_space_reset_space(
+ __isl_take isl_local_space *ls, __isl_take isl_space *dim);
+__isl_give isl_local_space *isl_local_space_realign(
+ __isl_take isl_local_space *ls, __isl_take isl_reordering *r);
+
+int isl_local_space_is_div_constraint(__isl_keep isl_local_space *ls,
+ isl_int *constraint, unsigned div);
+
+int *isl_local_space_get_active(__isl_keep isl_local_space *ls, isl_int *l);
+
+__isl_give isl_local_space *isl_local_space_substitute_seq(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, isl_int *subs, int subs_len,
+ int first, int n);
+__isl_give isl_local_space *isl_local_space_substitute(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs);
+
+__isl_give isl_local_space *isl_local_space_lift(
+ __isl_take isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_preimage_multi_aff(
+ __isl_take isl_local_space *ls, __isl_take isl_multi_aff *ma);
+
+__isl_give isl_local_space *isl_local_space_move_dims(
+ __isl_take isl_local_space *ls,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+int isl_local_space_cmp(__isl_keep isl_local_space *ls1,
+ __isl_keep isl_local_space *ls2);
+
+#endif
diff --git a/polly/lib/External/isl/isl_lp.c b/polly/lib/External/isl/isl_lp.c
new file mode 100644
index 00000000000..1d5ae6ef862
--- /dev/null
+++ b/polly/lib/External/isl/isl_lp.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/lp.h>
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include <isl_options_private.h>
+#include <isl_local_space_private.h>
+#include <isl_aff_private.h>
+#include <isl_mat_private.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+
+enum isl_lp_result isl_tab_solve_lp(struct isl_basic_map *bmap, int maximize,
+ isl_int *f, isl_int denom, isl_int *opt,
+ isl_int *opt_denom,
+ struct isl_vec **sol)
+{
+ struct isl_tab *tab;
+ enum isl_lp_result res;
+ unsigned dim = isl_basic_map_total_dim(bmap);
+
+ if (maximize)
+ isl_seq_neg(f, f, 1 + dim);
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ tab = isl_tab_from_basic_map(bmap, 0);
+ res = isl_tab_min(tab, f, denom, opt, opt_denom, 0);
+ if (res == isl_lp_ok && sol) {
+ *sol = isl_tab_get_sample_value(tab);
+ if (!*sol)
+ res = isl_lp_error;
+ }
+ isl_tab_free(tab);
+
+ if (maximize)
+ isl_seq_neg(f, f, 1 + dim);
+ if (maximize && opt)
+ isl_int_neg(*opt, *opt);
+
+ return res;
+}
+
+/* Given a basic map "bmap" and an affine combination of the variables "f"
+ * with denominator "denom", set *opt / *opt_denom to the minimal
+ * (or maximal if "maximize" is true) value attained by f/d over "bmap",
+ * assuming the basic map is not empty and the expression cannot attain
+ * arbitrarily small (or large) values.
+ * If opt_denom is NULL, then *opt is rounded up (or down)
+ * to the nearest integer.
+ * The return value reflects the nature of the result (empty, unbounded,
+ * minmimal or maximal value returned in *opt).
+ */
+enum isl_lp_result isl_basic_map_solve_lp(struct isl_basic_map *bmap, int max,
+ isl_int *f, isl_int d, isl_int *opt,
+ isl_int *opt_denom,
+ struct isl_vec **sol)
+{
+ if (sol)
+ *sol = NULL;
+
+ if (!bmap)
+ return isl_lp_error;
+
+ return isl_tab_solve_lp(bmap, max, f, d, opt, opt_denom, sol);
+}
+
+enum isl_lp_result isl_basic_set_solve_lp(struct isl_basic_set *bset, int max,
+ isl_int *f, isl_int d, isl_int *opt,
+ isl_int *opt_denom,
+ struct isl_vec **sol)
+{
+ return isl_basic_map_solve_lp((struct isl_basic_map *)bset, max,
+ f, d, opt, opt_denom, sol);
+}
+
+enum isl_lp_result isl_map_solve_lp(__isl_keep isl_map *map, int max,
+ isl_int *f, isl_int d, isl_int *opt,
+ isl_int *opt_denom,
+ struct isl_vec **sol)
+{
+ int i;
+ isl_int o;
+ isl_int t;
+ isl_int opt_i;
+ isl_int opt_denom_i;
+ enum isl_lp_result res;
+ int max_div;
+ isl_vec *v = NULL;
+
+ if (!map)
+ return isl_lp_error;
+ if (map->n == 0)
+ return isl_lp_empty;
+
+ max_div = 0;
+ for (i = 0; i < map->n; ++i)
+ if (map->p[i]->n_div > max_div)
+ max_div = map->p[i]->n_div;
+ if (max_div > 0) {
+ unsigned total = isl_space_dim(map->dim, isl_dim_all);
+ v = isl_vec_alloc(map->ctx, 1 + total + max_div);
+ if (!v)
+ return isl_lp_error;
+ isl_seq_cpy(v->el, f, 1 + total);
+ isl_seq_clr(v->el + 1 + total, max_div);
+ f = v->el;
+ }
+
+ if (!opt && map->n > 1 && sol) {
+ isl_int_init(o);
+ opt = &o;
+ }
+ if (map->n > 0)
+ isl_int_init(opt_i);
+ if (map->n > 0 && opt_denom) {
+ isl_int_init(opt_denom_i);
+ isl_int_init(t);
+ }
+
+ res = isl_basic_map_solve_lp(map->p[0], max, f, d,
+ opt, opt_denom, sol);
+ if (res == isl_lp_error || res == isl_lp_unbounded)
+ goto done;
+
+ if (sol)
+ *sol = NULL;
+
+ for (i = 1; i < map->n; ++i) {
+ isl_vec *sol_i = NULL;
+ enum isl_lp_result res_i;
+ int better;
+
+ res_i = isl_basic_map_solve_lp(map->p[i], max, f, d,
+ &opt_i,
+ opt_denom ? &opt_denom_i : NULL,
+ sol ? &sol_i : NULL);
+ if (res_i == isl_lp_error || res_i == isl_lp_unbounded) {
+ res = res_i;
+ goto done;
+ }
+ if (res_i == isl_lp_empty)
+ continue;
+ if (res == isl_lp_empty) {
+ better = 1;
+ } else if (!opt_denom) {
+ if (max)
+ better = isl_int_gt(opt_i, *opt);
+ else
+ better = isl_int_lt(opt_i, *opt);
+ } else {
+ isl_int_mul(t, opt_i, *opt_denom);
+ isl_int_submul(t, *opt, opt_denom_i);
+ if (max)
+ better = isl_int_is_pos(t);
+ else
+ better = isl_int_is_neg(t);
+ }
+ if (better) {
+ res = res_i;
+ if (opt)
+ isl_int_set(*opt, opt_i);
+ if (opt_denom)
+ isl_int_set(*opt_denom, opt_denom_i);
+ if (sol) {
+ isl_vec_free(*sol);
+ *sol = sol_i;
+ }
+ } else
+ isl_vec_free(sol_i);
+ }
+
+done:
+ isl_vec_free(v);
+ if (map->n > 0 && opt_denom) {
+ isl_int_clear(opt_denom_i);
+ isl_int_clear(t);
+ }
+ if (map->n > 0)
+ isl_int_clear(opt_i);
+ if (opt == &o)
+ isl_int_clear(o);
+ return res;
+}
+
+enum isl_lp_result isl_set_solve_lp(__isl_keep isl_set *set, int max,
+ isl_int *f, isl_int d, isl_int *opt,
+ isl_int *opt_denom,
+ struct isl_vec **sol)
+{
+ return isl_map_solve_lp((struct isl_map *)set, max,
+ f, d, opt, opt_denom, sol);
+}
+
+/* Return the optimal (rational) value of "obj" over "bset", assuming
+ * that "obj" and "bset" have aligned parameters and divs.
+ * If "max" is set, then the maximal value is computed.
+ * Otherwise, the minimal value is computed.
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ *
+ * Call isl_basic_set_solve_lp and translate the results.
+ */
+static __isl_give isl_val *basic_set_opt_lp(
+ __isl_keep isl_basic_set *bset, int max, __isl_keep isl_aff *obj)
+{
+ isl_ctx *ctx;
+ isl_val *res;
+ enum isl_lp_result lp_res;
+
+ if (!bset || !obj)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(obj);
+ res = isl_val_alloc(ctx);
+ if (!res)
+ return NULL;
+ lp_res = isl_basic_set_solve_lp(bset, max, obj->v->el + 1,
+ obj->v->el[0], &res->n, &res->d, NULL);
+ if (lp_res == isl_lp_ok)
+ return isl_val_normalize(res);
+ isl_val_free(res);
+ if (lp_res == isl_lp_error)
+ return NULL;
+ if (lp_res == isl_lp_empty)
+ return isl_val_nan(ctx);
+ if (max)
+ return isl_val_infty(ctx);
+ else
+ return isl_val_neginfty(ctx);
+}
+
+/* Return the optimal (rational) value of "obj" over "bset", assuming
+ * that "obj" and "bset" have aligned parameters.
+ * If "max" is set, then the maximal value is computed.
+ * Otherwise, the minimal value is computed.
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ *
+ * Align the divs of "bset" and "obj" and call basic_set_opt_lp.
+ */
+static __isl_give isl_val *isl_basic_set_opt_lp_val_aligned(
+ __isl_keep isl_basic_set *bset, int max, __isl_keep isl_aff *obj)
+{
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_ctx *ctx;
+ isl_mat *bset_div = NULL;
+ isl_mat *div = NULL;
+ isl_val *res;
+ int bset_n_div, obj_n_div;
+
+ if (!bset || !obj)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(obj);
+ if (!isl_space_is_equal(bset->dim, obj->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", return NULL);
+
+ bset_n_div = isl_basic_set_dim(bset, isl_dim_div);
+ obj_n_div = isl_aff_dim(obj, isl_dim_div);
+ if (bset_n_div == 0 && obj_n_div == 0)
+ return basic_set_opt_lp(bset, max, obj);
+
+ bset = isl_basic_set_copy(bset);
+ obj = isl_aff_copy(obj);
+
+ bset_div = isl_basic_set_get_divs(bset);
+ exp1 = isl_alloc_array(ctx, int, bset_n_div);
+ exp2 = isl_alloc_array(ctx, int, obj_n_div);
+ if (!bset_div || (bset_n_div && !exp1) || (obj_n_div && !exp2))
+ goto error;
+
+ div = isl_merge_divs(bset_div, obj->ls->div, exp1, exp2);
+
+ bset = isl_basic_set_expand_divs(bset, isl_mat_copy(div), exp1);
+ obj = isl_aff_expand_divs(obj, isl_mat_copy(div), exp2);
+
+ res = basic_set_opt_lp(bset, max, obj);
+
+ isl_mat_free(bset_div);
+ isl_mat_free(div);
+ free(exp1);
+ free(exp2);
+ isl_basic_set_free(bset);
+ isl_aff_free(obj);
+
+ return res;
+error:
+ isl_mat_free(div);
+ isl_mat_free(bset_div);
+ free(exp1);
+ free(exp2);
+ isl_basic_set_free(bset);
+ isl_aff_free(obj);
+ return NULL;
+}
+
+/* Return the optimal (rational) value of "obj" over "bset".
+ * If "max" is set, then the maximal value is computed.
+ * Otherwise, the minimal value is computed.
+ *
+ * Return infinity or negative infinity if the optimal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+static __isl_give isl_val *isl_basic_set_opt_lp_val(
+ __isl_keep isl_basic_set *bset, int max, __isl_keep isl_aff *obj)
+{
+ isl_val *res;
+
+ if (!bset || !obj)
+ return NULL;
+
+ if (isl_space_match(bset->dim, isl_dim_param,
+ obj->ls->dim, isl_dim_param))
+ return isl_basic_set_opt_lp_val_aligned(bset, max, obj);
+
+ bset = isl_basic_set_copy(bset);
+ obj = isl_aff_copy(obj);
+ bset = isl_basic_set_align_params(bset, isl_aff_get_domain_space(obj));
+ obj = isl_aff_align_params(obj, isl_basic_set_get_space(bset));
+
+ res = isl_basic_set_opt_lp_val_aligned(bset, max, obj);
+
+ isl_basic_set_free(bset);
+ isl_aff_free(obj);
+
+ return res;
+}
+
+/* Return the minimal (rational) value of "obj" over "bset".
+ *
+ * Return negative infinity if the minimal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+__isl_give isl_val *isl_basic_set_min_lp_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj)
+{
+ return isl_basic_set_opt_lp_val(bset, 0, obj);
+}
+
+/* Return the maximal (rational) value of "obj" over "bset".
+ *
+ * Return infinity if the maximal value is unbounded and
+ * NaN if "bset" is empty.
+ */
+__isl_give isl_val *isl_basic_set_max_lp_val(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_aff *obj)
+{
+ return isl_basic_set_opt_lp_val(bset, 1, obj);
+}
diff --git a/polly/lib/External/isl/isl_lp_private.h b/polly/lib/External/isl/isl_lp_private.h
new file mode 100644
index 00000000000..ddc44c1eeda
--- /dev/null
+++ b/polly/lib/External/isl/isl_lp_private.h
@@ -0,0 +1,21 @@
+#ifndef ISL_LP_PRIVATE_H
+#define ISL_LP_PRIVATE_H
+
+#include <isl_int.h>
+#include <isl/lp.h>
+#include <isl/vec.h>
+
+enum isl_lp_result isl_basic_map_solve_lp(__isl_keep isl_basic_map *bmap,
+ int max, isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ __isl_give isl_vec **sol);
+enum isl_lp_result isl_basic_set_solve_lp(__isl_keep isl_basic_set *bset,
+ int max, isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ __isl_give isl_vec **sol);
+enum isl_lp_result isl_map_solve_lp(__isl_keep isl_map *map, int max,
+ isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ __isl_give isl_vec **sol);
+enum isl_lp_result isl_set_solve_lp(__isl_keep isl_set *set, int max,
+ isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ __isl_give isl_vec **sol);
+
+#endif
diff --git a/polly/lib/External/isl/isl_map.c b/polly/lib/External/isl/isl_map.c
new file mode 100644
index 00000000000..8f021c09e66
--- /dev/null
+++ b/polly/lib/External/isl/isl_map.c
@@ -0,0 +1,12888 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012-2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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 - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <string.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_blk.h>
+#include "isl_space_private.h"
+#include "isl_equalities.h"
+#include <isl_lp_private.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl_reordering.h>
+#include "isl_sample.h"
+#include <isl_sort.h>
+#include "isl_tab.h"
+#include <isl/vec.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_dim_map.h>
+#include <isl_local_space_private.h>
+#include <isl_aff_private.h>
+#include <isl_options_private.h>
+#include <isl_morph.h>
+#include <isl_val_private.h>
+#include <isl/deprecated/map_int.h>
+#include <isl/deprecated/set_int.h>
+
+static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param: return dim->nparam;
+ case isl_dim_in: return dim->n_in;
+ case isl_dim_out: return dim->n_out;
+ case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
+ default: return 0;
+ }
+}
+
+static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param: return 1;
+ case isl_dim_in: return 1 + dim->nparam;
+ case isl_dim_out: return 1 + dim->nparam + dim->n_in;
+ default: return 0;
+ }
+}
+
+unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type)
+{
+ if (!bmap)
+ return 0;
+ switch (type) {
+ case isl_dim_cst: return 1;
+ case isl_dim_param:
+ case isl_dim_in:
+ case isl_dim_out: return isl_space_dim(bmap->dim, type);
+ case isl_dim_div: return bmap->n_div;
+ case isl_dim_all: return isl_basic_map_total_dim(bmap);
+ default: return 0;
+ }
+}
+
+unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type)
+{
+ return map ? n(map->dim, type) : 0;
+}
+
+unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type)
+{
+ return set ? n(set->dim, type) : 0;
+}
+
+unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
+ enum isl_dim_type type)
+{
+ isl_space *dim = bmap->dim;
+ switch (type) {
+ case isl_dim_cst: return 0;
+ case isl_dim_param: return 1;
+ case isl_dim_in: return 1 + dim->nparam;
+ case isl_dim_out: return 1 + dim->nparam + dim->n_in;
+ case isl_dim_div: return 1 + dim->nparam + dim->n_in + dim->n_out;
+ default: return 0;
+ }
+}
+
+unsigned isl_basic_set_offset(struct isl_basic_set *bset,
+ enum isl_dim_type type)
+{
+ return isl_basic_map_offset(bset, type);
+}
+
+static unsigned map_offset(struct isl_map *map, enum isl_dim_type type)
+{
+ return pos(map->dim, type);
+}
+
+unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type)
+{
+ return isl_basic_map_dim(bset, type);
+}
+
+unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_set_dim(bset, isl_dim_set);
+}
+
+unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_set_dim(bset, isl_dim_param);
+}
+
+unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset)
+{
+ if (!bset)
+ return 0;
+ return isl_space_dim(bset->dim, isl_dim_all) + bset->n_div;
+}
+
+unsigned isl_set_n_dim(__isl_keep isl_set *set)
+{
+ return isl_set_dim(set, isl_dim_set);
+}
+
+unsigned isl_set_n_param(__isl_keep isl_set *set)
+{
+ return isl_set_dim(set, isl_dim_param);
+}
+
+unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap)
+{
+ return bmap ? bmap->dim->n_in : 0;
+}
+
+unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap)
+{
+ return bmap ? bmap->dim->n_out : 0;
+}
+
+unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap)
+{
+ return bmap ? bmap->dim->nparam : 0;
+}
+
+unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap)
+{
+ return bmap ? bmap->n_div : 0;
+}
+
+unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap)
+{
+ return bmap ? isl_space_dim(bmap->dim, isl_dim_all) + bmap->n_div : 0;
+}
+
+unsigned isl_map_n_in(const struct isl_map *map)
+{
+ return map ? map->dim->n_in : 0;
+}
+
+unsigned isl_map_n_out(const struct isl_map *map)
+{
+ return map ? map->dim->n_out : 0;
+}
+
+unsigned isl_map_n_param(const struct isl_map *map)
+{
+ return map ? map->dim->nparam : 0;
+}
+
+int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set)
+{
+ int m;
+ if (!map || !set)
+ return -1;
+ m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
+ if (m < 0 || !m)
+ return m;
+ return isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ set->dim, isl_dim_set);
+}
+
+int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
+ struct isl_basic_set *bset)
+{
+ int m;
+ if (!bmap || !bset)
+ return -1;
+ m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
+ if (m < 0 || !m)
+ return m;
+ return isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
+ bset->dim, isl_dim_set);
+}
+
+int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set)
+{
+ int m;
+ if (!map || !set)
+ return -1;
+ m = isl_space_match(map->dim, isl_dim_param, set->dim, isl_dim_param);
+ if (m < 0 || !m)
+ return m;
+ return isl_space_tuple_is_equal(map->dim, isl_dim_out,
+ set->dim, isl_dim_set);
+}
+
+int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
+ struct isl_basic_set *bset)
+{
+ int m;
+ if (!bmap || !bset)
+ return -1;
+ m = isl_space_match(bmap->dim, isl_dim_param, bset->dim, isl_dim_param);
+ if (m < 0 || !m)
+ return m;
+ return isl_space_tuple_is_equal(bmap->dim, isl_dim_out,
+ bset->dim, isl_dim_set);
+}
+
+isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap)
+{
+ return bmap ? bmap->ctx : NULL;
+}
+
+isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset)
+{
+ return bset ? bset->ctx : NULL;
+}
+
+isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map)
+{
+ return map ? map->ctx : NULL;
+}
+
+isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set)
+{
+ return set ? set->ctx : NULL;
+}
+
+__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+ return isl_space_copy(bmap->dim);
+}
+
+__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset)
+{
+ if (!bset)
+ return NULL;
+ return isl_space_copy(bset->dim);
+}
+
+/* Extract the divs in "bmap" as a matrix.
+ */
+__isl_give isl_mat *isl_basic_map_get_divs(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_mat *div;
+ unsigned total;
+ unsigned cols;
+
+ if (!bmap)
+ return NULL;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ cols = 1 + 1 + total + bmap->n_div;
+ div = isl_mat_alloc(ctx, bmap->n_div, cols);
+ if (!div)
+ return NULL;
+
+ for (i = 0; i < bmap->n_div; ++i)
+ isl_seq_cpy(div->row[i], bmap->div[i], cols);
+
+ return div;
+}
+
+/* Extract the divs in "bset" as a matrix.
+ */
+__isl_give isl_mat *isl_basic_set_get_divs(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_get_divs(bset);
+}
+
+__isl_give isl_local_space *isl_basic_map_get_local_space(
+ __isl_keep isl_basic_map *bmap)
+{
+ isl_mat *div;
+
+ if (!bmap)
+ return NULL;
+
+ div = isl_basic_map_get_divs(bmap);
+ return isl_local_space_alloc_div(isl_space_copy(bmap->dim), div);
+}
+
+__isl_give isl_local_space *isl_basic_set_get_local_space(
+ __isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_get_local_space(bset);
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_local_space(
+ __isl_take isl_local_space *ls)
+{
+ int i;
+ int n_div;
+ isl_basic_map *bmap;
+
+ if (!ls)
+ return NULL;
+
+ n_div = isl_local_space_dim(ls, isl_dim_div);
+ bmap = isl_basic_map_alloc_space(isl_local_space_get_space(ls),
+ n_div, 0, 2 * n_div);
+
+ for (i = 0; i < n_div; ++i)
+ if (isl_basic_map_alloc_div(bmap) < 0)
+ goto error;
+
+ 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;
+ }
+
+ isl_local_space_free(ls);
+ return bmap;
+error:
+ isl_local_space_free(ls);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_from_local_space(
+ __isl_take isl_local_space *ls)
+{
+ return isl_basic_map_from_local_space(ls);
+}
+
+__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map)
+{
+ if (!map)
+ return NULL;
+ return isl_space_copy(map->dim);
+}
+
+__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set)
+{
+ if (!set)
+ return NULL;
+ return isl_space_copy(set->dim);
+}
+
+__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ bmap->dim = isl_space_set_tuple_name(bmap->dim, type, s);
+ if (!bmap->dim)
+ goto error;
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
+ __isl_take isl_basic_set *bset, const char *s)
+{
+ return isl_basic_map_set_tuple_name(bset, isl_dim_set, s);
+}
+
+const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type)
+{
+ return bmap ? isl_space_get_tuple_name(bmap->dim, type) : NULL;
+}
+
+__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
+ enum isl_dim_type type, const char *s)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_set_tuple_name(map->dim, type, s);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_set_tuple_name(map->p[i], type, s);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Replace the identifier of the tuple of type "type" by "id".
+ */
+__isl_give isl_basic_map *isl_basic_map_set_tuple_id(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ bmap->dim = isl_space_set_tuple_id(bmap->dim, type, id);
+ if (!bmap->dim)
+ return isl_basic_map_free(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+/* Replace the identifier of the tuple by "id".
+ */
+__isl_give isl_basic_set *isl_basic_set_set_tuple_id(
+ __isl_take isl_basic_set *bset, __isl_take isl_id *id)
+{
+ return isl_basic_map_set_tuple_id(bset, isl_dim_set, id);
+}
+
+/* Does the input or output tuple have a name?
+ */
+int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type)
+{
+ return map ? isl_space_has_tuple_name(map->dim, type) : -1;
+}
+
+const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
+ enum isl_dim_type type)
+{
+ return map ? isl_space_get_tuple_name(map->dim, type) : NULL;
+}
+
+__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
+ const char *s)
+{
+ return (isl_set *)isl_map_set_tuple_name((isl_map *)set, isl_dim_set, s);
+}
+
+__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+
+ map->dim = isl_space_set_tuple_id(map->dim, type, id);
+
+ return isl_map_reset_space(map, isl_space_copy(map->dim));
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
+ __isl_take isl_id *id)
+{
+ return isl_map_set_tuple_id(set, isl_dim_set, id);
+}
+
+__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
+ enum isl_dim_type type)
+{
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_reset_tuple_id(map->dim, type);
+
+ return isl_map_reset_space(map, isl_space_copy(map->dim));
+}
+
+__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set)
+{
+ return isl_map_reset_tuple_id(set, isl_dim_set);
+}
+
+int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type)
+{
+ return map ? isl_space_has_tuple_id(map->dim, type) : -1;
+}
+
+__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
+ enum isl_dim_type type)
+{
+ return map ? isl_space_get_tuple_id(map->dim, type) : NULL;
+}
+
+int isl_set_has_tuple_id(__isl_keep isl_set *set)
+{
+ return isl_map_has_tuple_id(set, isl_dim_set);
+}
+
+__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set)
+{
+ return isl_map_get_tuple_id(set, isl_dim_set);
+}
+
+/* Does the set tuple have a name?
+ */
+int isl_set_has_tuple_name(__isl_keep isl_set *set)
+{
+ return set ? isl_space_has_tuple_name(set->dim, isl_dim_set) : -1;
+}
+
+
+const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset)
+{
+ return bset ? isl_space_get_tuple_name(bset->dim, isl_dim_set) : NULL;
+}
+
+const char *isl_set_get_tuple_name(__isl_keep isl_set *set)
+{
+ return set ? isl_space_get_tuple_name(set->dim, isl_dim_set) : NULL;
+}
+
+const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ return bmap ? isl_space_get_dim_name(bmap->dim, type, pos) : NULL;
+}
+
+const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos)
+{
+ return bset ? isl_space_get_dim_name(bset->dim, type, pos) : NULL;
+}
+
+/* Does the given dimension have a name?
+ */
+int isl_map_has_dim_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ return map ? isl_space_has_dim_name(map->dim, type, pos) : -1;
+}
+
+const char *isl_map_get_dim_name(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ return map ? isl_space_get_dim_name(map->dim, type, pos) : NULL;
+}
+
+const char *isl_set_get_dim_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return set ? isl_space_get_dim_name(set->dim, type, pos) : NULL;
+}
+
+/* Does the given dimension have a name?
+ */
+int isl_set_has_dim_name(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return set ? isl_space_has_dim_name(set->dim, type, pos) : -1;
+}
+
+__isl_give isl_basic_map *isl_basic_map_set_dim_name(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ bmap->dim = isl_space_set_dim_name(bmap->dim, type, pos, s);
+ if (!bmap->dim)
+ goto error;
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_set_dim_name(map->dim, type, pos, s);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_set_dim_name(map->p[i], type, pos, s);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_set_dim_name(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ return (isl_basic_set *)isl_basic_map_set_dim_name(
+ (isl_basic_map *)bset, type, pos, s);
+}
+
+__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ return (isl_set *)isl_map_set_dim_name((isl_map *)set, type, pos, s);
+}
+
+int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ return bmap ? isl_space_has_dim_id(bmap->dim, type, pos) : -1;
+}
+
+__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos)
+{
+ return bset ? isl_space_get_dim_id(bset->dim, type, pos) : NULL;
+}
+
+int isl_map_has_dim_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ return map ? isl_space_has_dim_id(map->dim, type, pos) : -1;
+}
+
+__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ return map ? isl_space_get_dim_id(map->dim, type, pos) : NULL;
+}
+
+int isl_set_has_dim_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_map_has_dim_id(set, type, pos);
+}
+
+__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_map_get_dim_id(set, type, pos);
+}
+
+__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+
+ map->dim = isl_space_set_dim_id(map->dim, type, pos, id);
+
+ return isl_map_reset_space(map, isl_space_copy(map->dim));
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ return isl_map_set_dim_id(set, type, pos, id);
+}
+
+int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
+ __isl_keep isl_id *id)
+{
+ if (!map)
+ return -1;
+ return isl_space_find_dim_by_id(map->dim, type, id);
+}
+
+int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
+ __isl_keep isl_id *id)
+{
+ return isl_map_find_dim_by_id(set, type, id);
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "bmap".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, const char *name)
+{
+ if (!bmap)
+ return -1;
+ return isl_space_find_dim_by_name(bmap->dim, type, name);
+}
+
+int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
+ const char *name)
+{
+ if (!map)
+ return -1;
+ return isl_space_find_dim_by_name(map->dim, type, name);
+}
+
+int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
+ const char *name)
+{
+ return isl_map_find_dim_by_name(set, type, name);
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of "map".
+ */
+__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map)
+{
+ isl_space *space;
+
+ space = isl_map_get_space(map);
+ space = isl_space_reset_user(space);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of "set".
+ */
+__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set)
+{
+ return isl_map_reset_user(set);
+}
+
+int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ return ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+}
+
+int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_is_rational(bset);
+}
+
+/* Does "bmap" contain any rational points?
+ *
+ * If "bmap" has an equality for each dimension, equating the dimension
+ * to an integer constant, then it has no rational points, even if it
+ * is marked as rational.
+ */
+int isl_basic_map_has_rational(__isl_keep isl_basic_map *bmap)
+{
+ int has_rational = 1;
+ unsigned total;
+
+ if (!bmap)
+ return -1;
+ if (isl_basic_map_plain_is_empty(bmap))
+ return 0;
+ if (!isl_basic_map_is_rational(bmap))
+ return 0;
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_implicit_equalities(bmap);
+ if (!bmap)
+ return -1;
+ total = isl_basic_map_total_dim(bmap);
+ if (bmap->n_eq == total) {
+ int i, j;
+ for (i = 0; i < bmap->n_eq; ++i) {
+ j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
+ if (j < 0)
+ break;
+ if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
+ !isl_int_is_negone(bmap->eq[i][1 + j]))
+ break;
+ j = isl_seq_first_non_zero(bmap->eq[i] + 1 + j + 1,
+ total - j - 1);
+ if (j >= 0)
+ break;
+ }
+ if (i == bmap->n_eq)
+ has_rational = 0;
+ }
+ isl_basic_map_free(bmap);
+
+ return has_rational;
+}
+
+/* Does "map" contain any rational points?
+ */
+int isl_map_has_rational(__isl_keep isl_map *map)
+{
+ int i;
+ int has_rational;
+
+ if (!map)
+ return -1;
+ for (i = 0; i < map->n; ++i) {
+ has_rational = isl_basic_map_has_rational(map->p[i]);
+ if (has_rational < 0)
+ return -1;
+ if (has_rational)
+ return 1;
+ }
+ return 0;
+}
+
+/* Does "set" contain any rational points?
+ */
+int isl_set_has_rational(__isl_keep isl_set *set)
+{
+ return isl_map_has_rational(set);
+}
+
+/* Is this basic set a parameter domain?
+ */
+int isl_basic_set_is_params(__isl_keep isl_basic_set *bset)
+{
+ if (!bset)
+ return -1;
+ return isl_space_is_params(bset->dim);
+}
+
+/* Is this set a parameter domain?
+ */
+int isl_set_is_params(__isl_keep isl_set *set)
+{
+ if (!set)
+ return -1;
+ return isl_space_is_params(set->dim);
+}
+
+/* Is this map actually a parameter domain?
+ * Users should never call this function. Outside of isl,
+ * a map can never be a parameter domain.
+ */
+int isl_map_is_params(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+ return isl_space_is_params(map->dim);
+}
+
+static struct isl_basic_map *basic_map_init(struct isl_ctx *ctx,
+ struct isl_basic_map *bmap, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ int i;
+ size_t row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + extra;
+
+ bmap->ctx = ctx;
+ isl_ctx_ref(ctx);
+
+ bmap->block = isl_blk_alloc(ctx, (n_ineq + n_eq) * row_size);
+ if (isl_blk_is_error(bmap->block))
+ goto error;
+
+ bmap->ineq = isl_alloc_array(ctx, isl_int *, n_ineq + n_eq);
+ if ((n_ineq + n_eq) && !bmap->ineq)
+ goto error;
+
+ if (extra == 0) {
+ bmap->block2 = isl_blk_empty();
+ bmap->div = NULL;
+ } else {
+ bmap->block2 = isl_blk_alloc(ctx, extra * (1 + row_size));
+ if (isl_blk_is_error(bmap->block2))
+ goto error;
+
+ bmap->div = isl_alloc_array(ctx, isl_int *, extra);
+ if (!bmap->div)
+ goto error;
+ }
+
+ for (i = 0; i < n_ineq + n_eq; ++i)
+ bmap->ineq[i] = bmap->block.data + i * row_size;
+
+ for (i = 0; i < extra; ++i)
+ bmap->div[i] = bmap->block2.data + i * (1 + row_size);
+
+ bmap->ref = 1;
+ bmap->flags = 0;
+ bmap->c_size = n_eq + n_ineq;
+ bmap->eq = bmap->ineq + n_ineq;
+ bmap->extra = extra;
+ bmap->n_eq = 0;
+ bmap->n_ineq = 0;
+ bmap->n_div = 0;
+ bmap->sample = NULL;
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *bmap;
+ isl_space *space;
+
+ space = isl_space_set_alloc(ctx, nparam, dim);
+ if (!space)
+ return NULL;
+
+ bmap = isl_basic_map_alloc_space(space, extra, n_eq, n_ineq);
+ return (struct isl_basic_set *)bmap;
+}
+
+struct isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
+ unsigned extra, unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *bmap;
+ if (!dim)
+ return NULL;
+ isl_assert(dim->ctx, dim->n_in == 0, goto error);
+ bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
+ return (struct isl_basic_set *)bmap;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
+ unsigned extra, unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *bmap;
+
+ if (!dim)
+ return NULL;
+ bmap = isl_calloc_type(dim->ctx, struct isl_basic_map);
+ if (!bmap)
+ goto error;
+ bmap->dim = dim;
+
+ return basic_map_init(dim->ctx, bmap, extra, n_eq, n_ineq);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned in, unsigned out, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *bmap;
+ isl_space *dim;
+
+ dim = isl_space_alloc(ctx, nparam, in, out);
+ if (!dim)
+ return NULL;
+
+ bmap = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
+ return bmap;
+}
+
+static void dup_constraints(
+ struct isl_basic_map *dst, struct isl_basic_map *src)
+{
+ int i;
+ unsigned total = isl_basic_map_total_dim(src);
+
+ for (i = 0; i < src->n_eq; ++i) {
+ int j = isl_basic_map_alloc_equality(dst);
+ isl_seq_cpy(dst->eq[j], src->eq[i], 1+total);
+ }
+
+ for (i = 0; i < src->n_ineq; ++i) {
+ int j = isl_basic_map_alloc_inequality(dst);
+ isl_seq_cpy(dst->ineq[j], src->ineq[i], 1+total);
+ }
+
+ for (i = 0; i < src->n_div; ++i) {
+ int j = isl_basic_map_alloc_div(dst);
+ isl_seq_cpy(dst->div[j], src->div[i], 1+1+total);
+ }
+ ISL_F_SET(dst, ISL_BASIC_SET_FINAL);
+}
+
+struct isl_basic_map *isl_basic_map_dup(struct isl_basic_map *bmap)
+{
+ struct isl_basic_map *dup;
+
+ if (!bmap)
+ return NULL;
+ dup = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
+ bmap->n_div, bmap->n_eq, bmap->n_ineq);
+ if (!dup)
+ return NULL;
+ dup_constraints(dup, bmap);
+ dup->flags = bmap->flags;
+ dup->sample = isl_vec_copy(bmap->sample);
+ return dup;
+}
+
+struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset)
+{
+ struct isl_basic_map *dup;
+
+ dup = isl_basic_map_dup((struct isl_basic_map *)bset);
+ return (struct isl_basic_set *)dup;
+}
+
+struct isl_basic_set *isl_basic_set_copy(struct isl_basic_set *bset)
+{
+ if (!bset)
+ return NULL;
+
+ if (ISL_F_ISSET(bset, ISL_BASIC_SET_FINAL)) {
+ bset->ref++;
+ return bset;
+ }
+ return isl_basic_set_dup(bset);
+}
+
+struct isl_set *isl_set_copy(struct isl_set *set)
+{
+ if (!set)
+ return NULL;
+
+ set->ref++;
+ return set;
+}
+
+struct isl_basic_map *isl_basic_map_copy(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL)) {
+ bmap->ref++;
+ return bmap;
+ }
+ bmap = isl_basic_map_dup(bmap);
+ if (bmap)
+ ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
+ return bmap;
+}
+
+struct isl_map *isl_map_copy(struct isl_map *map)
+{
+ if (!map)
+ return NULL;
+
+ map->ref++;
+ return map;
+}
+
+__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (--bmap->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(bmap->ctx);
+ free(bmap->div);
+ isl_blk_free(bmap->ctx, bmap->block2);
+ free(bmap->ineq);
+ isl_blk_free(bmap->ctx, bmap->block);
+ isl_vec_free(bmap->sample);
+ isl_space_free(bmap->dim);
+ free(bmap);
+
+ return NULL;
+}
+
+__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_free((struct isl_basic_map *)bset);
+}
+
+static int room_for_con(struct isl_basic_map *bmap, unsigned n)
+{
+ return bmap->n_eq + bmap->n_ineq + n <= bmap->c_size;
+}
+
+__isl_give isl_map *isl_map_align_params_map_map_and(
+ __isl_take isl_map *map1, __isl_take isl_map *map2,
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
+ __isl_take isl_map *map2))
+{
+ if (!map1 || !map2)
+ goto error;
+ if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
+ return fn(map1, map2);
+ if (!isl_space_has_named_params(map1->dim) ||
+ !isl_space_has_named_params(map2->dim))
+ isl_die(map1->ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ map1 = isl_map_align_params(map1, isl_map_get_space(map2));
+ map2 = isl_map_align_params(map2, isl_map_get_space(map1));
+ return fn(map1, map2);
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2,
+ int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2))
+{
+ int r;
+
+ if (!map1 || !map2)
+ return -1;
+ if (isl_space_match(map1->dim, isl_dim_param, map2->dim, isl_dim_param))
+ return fn(map1, map2);
+ if (!isl_space_has_named_params(map1->dim) ||
+ !isl_space_has_named_params(map2->dim))
+ isl_die(map1->ctx, isl_error_invalid,
+ "unaligned unnamed parameters", return -1);
+ map1 = isl_map_copy(map1);
+ map2 = isl_map_copy(map2);
+ map1 = isl_map_align_params(map1, isl_map_get_space(map2));
+ map2 = isl_map_align_params(map2, isl_map_get_space(map1));
+ r = fn(map1, map2);
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return r;
+}
+
+int isl_basic_map_alloc_equality(struct isl_basic_map *bmap)
+{
+ struct isl_ctx *ctx;
+ if (!bmap)
+ return -1;
+ ctx = bmap->ctx;
+ isl_assert(ctx, room_for_con(bmap, 1), return -1);
+ isl_assert(ctx, (bmap->eq - bmap->ineq) + bmap->n_eq <= bmap->c_size,
+ return -1);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
+ if ((bmap->eq - bmap->ineq) + bmap->n_eq == bmap->c_size) {
+ isl_int *t;
+ int j = isl_basic_map_alloc_inequality(bmap);
+ if (j < 0)
+ return -1;
+ t = bmap->ineq[j];
+ bmap->ineq[j] = bmap->ineq[bmap->n_ineq - 1];
+ bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
+ bmap->eq[-1] = t;
+ bmap->n_eq++;
+ bmap->n_ineq--;
+ bmap->eq--;
+ return 0;
+ }
+ isl_seq_clr(bmap->eq[bmap->n_eq] + 1 + isl_basic_map_total_dim(bmap),
+ bmap->extra - bmap->n_div);
+ return bmap->n_eq++;
+}
+
+int isl_basic_set_alloc_equality(struct isl_basic_set *bset)
+{
+ return isl_basic_map_alloc_equality((struct isl_basic_map *)bset);
+}
+
+int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n)
+{
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, n <= bmap->n_eq, return -1);
+ bmap->n_eq -= n;
+ return 0;
+}
+
+int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n)
+{
+ return isl_basic_map_free_equality((struct isl_basic_map *)bset, n);
+}
+
+int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos)
+{
+ isl_int *t;
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, pos < bmap->n_eq, return -1);
+
+ if (pos != bmap->n_eq - 1) {
+ t = bmap->eq[pos];
+ bmap->eq[pos] = bmap->eq[bmap->n_eq - 1];
+ bmap->eq[bmap->n_eq - 1] = t;
+ }
+ bmap->n_eq--;
+ return 0;
+}
+
+int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos)
+{
+ return isl_basic_map_drop_equality((struct isl_basic_map *)bset, pos);
+}
+
+/* Turn inequality "pos" of "bmap" into an equality.
+ *
+ * In particular, we move the inequality in front of the equalities
+ * and move the last inequality in the position of the moved inequality.
+ * Note that isl_tab_make_equalities_explicit depends on this particular
+ * change in the ordering of the constraints.
+ */
+void isl_basic_map_inequality_to_equality(
+ struct isl_basic_map *bmap, unsigned pos)
+{
+ isl_int *t;
+
+ t = bmap->ineq[pos];
+ bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
+ bmap->ineq[bmap->n_ineq - 1] = bmap->eq[-1];
+ bmap->eq[-1] = t;
+ bmap->n_eq++;
+ bmap->n_ineq--;
+ bmap->eq--;
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
+}
+
+static int room_for_ineq(struct isl_basic_map *bmap, unsigned n)
+{
+ return bmap->n_ineq + n <= bmap->eq - bmap->ineq;
+}
+
+int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap)
+{
+ struct isl_ctx *ctx;
+ if (!bmap)
+ return -1;
+ ctx = bmap->ctx;
+ isl_assert(ctx, room_for_ineq(bmap, 1), return -1);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_ALL_EQUALITIES);
+ isl_seq_clr(bmap->ineq[bmap->n_ineq] +
+ 1 + isl_basic_map_total_dim(bmap),
+ bmap->extra - bmap->n_div);
+ return bmap->n_ineq++;
+}
+
+int isl_basic_set_alloc_inequality(struct isl_basic_set *bset)
+{
+ return isl_basic_map_alloc_inequality((struct isl_basic_map *)bset);
+}
+
+int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n)
+{
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, n <= bmap->n_ineq, return -1);
+ bmap->n_ineq -= n;
+ return 0;
+}
+
+int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n)
+{
+ return isl_basic_map_free_inequality((struct isl_basic_map *)bset, n);
+}
+
+int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos)
+{
+ isl_int *t;
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
+
+ if (pos != bmap->n_ineq - 1) {
+ t = bmap->ineq[pos];
+ bmap->ineq[pos] = bmap->ineq[bmap->n_ineq - 1];
+ bmap->ineq[bmap->n_ineq - 1] = t;
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ }
+ bmap->n_ineq--;
+ return 0;
+}
+
+int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos)
+{
+ return isl_basic_map_drop_inequality((struct isl_basic_map *)bset, pos);
+}
+
+__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
+ isl_int *eq)
+{
+ int k;
+
+ bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
+ if (!bmap)
+ return NULL;
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->eq[k], eq, 1 + isl_basic_map_total_dim(bmap));
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
+ isl_int *eq)
+{
+ return (isl_basic_set *)
+ isl_basic_map_add_eq((isl_basic_map *)bset, eq);
+}
+
+__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
+ isl_int *ineq)
+{
+ int k;
+
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+ if (!bmap)
+ return NULL;
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->ineq[k], ineq, 1 + isl_basic_map_total_dim(bmap));
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
+ isl_int *ineq)
+{
+ return (isl_basic_set *)
+ isl_basic_map_add_ineq((isl_basic_map *)bset, ineq);
+}
+
+int isl_basic_map_alloc_div(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, bmap->n_div < bmap->extra, return -1);
+ isl_seq_clr(bmap->div[bmap->n_div] +
+ 1 + 1 + isl_basic_map_total_dim(bmap),
+ bmap->extra - bmap->n_div);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
+ return bmap->n_div++;
+}
+
+int isl_basic_set_alloc_div(struct isl_basic_set *bset)
+{
+ return isl_basic_map_alloc_div((struct isl_basic_map *)bset);
+}
+
+int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n)
+{
+ if (!bmap)
+ return -1;
+ isl_assert(bmap->ctx, n <= bmap->n_div, return -1);
+ bmap->n_div -= n;
+ return 0;
+}
+
+int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n)
+{
+ return isl_basic_map_free_div((struct isl_basic_map *)bset, n);
+}
+
+/* Copy constraint from src to dst, putting the vars of src at offset
+ * dim_off in dst and the divs of src at offset div_off in dst.
+ * If both sets are actually map, then dim_off applies to the input
+ * variables.
+ */
+static void copy_constraint(struct isl_basic_map *dst_map, isl_int *dst,
+ struct isl_basic_map *src_map, isl_int *src,
+ unsigned in_off, unsigned out_off, unsigned div_off)
+{
+ unsigned src_nparam = isl_basic_map_n_param(src_map);
+ unsigned dst_nparam = isl_basic_map_n_param(dst_map);
+ unsigned src_in = isl_basic_map_n_in(src_map);
+ unsigned dst_in = isl_basic_map_n_in(dst_map);
+ unsigned src_out = isl_basic_map_n_out(src_map);
+ unsigned dst_out = isl_basic_map_n_out(dst_map);
+ isl_int_set(dst[0], src[0]);
+ isl_seq_cpy(dst+1, src+1, isl_min(dst_nparam, src_nparam));
+ if (dst_nparam > src_nparam)
+ isl_seq_clr(dst+1+src_nparam,
+ dst_nparam - src_nparam);
+ isl_seq_clr(dst+1+dst_nparam, in_off);
+ isl_seq_cpy(dst+1+dst_nparam+in_off,
+ src+1+src_nparam,
+ isl_min(dst_in-in_off, src_in));
+ if (dst_in-in_off > src_in)
+ isl_seq_clr(dst+1+dst_nparam+in_off+src_in,
+ dst_in - in_off - src_in);
+ isl_seq_clr(dst+1+dst_nparam+dst_in, out_off);
+ isl_seq_cpy(dst+1+dst_nparam+dst_in+out_off,
+ src+1+src_nparam+src_in,
+ isl_min(dst_out-out_off, src_out));
+ if (dst_out-out_off > src_out)
+ isl_seq_clr(dst+1+dst_nparam+dst_in+out_off+src_out,
+ dst_out - out_off - src_out);
+ isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out, div_off);
+ isl_seq_cpy(dst+1+dst_nparam+dst_in+dst_out+div_off,
+ src+1+src_nparam+src_in+src_out,
+ isl_min(dst_map->extra-div_off, src_map->n_div));
+ if (dst_map->n_div-div_off > src_map->n_div)
+ isl_seq_clr(dst+1+dst_nparam+dst_in+dst_out+
+ div_off+src_map->n_div,
+ dst_map->n_div - div_off - src_map->n_div);
+}
+
+static void copy_div(struct isl_basic_map *dst_map, isl_int *dst,
+ struct isl_basic_map *src_map, isl_int *src,
+ unsigned in_off, unsigned out_off, unsigned div_off)
+{
+ isl_int_set(dst[0], src[0]);
+ copy_constraint(dst_map, dst+1, src_map, src+1, in_off, out_off, div_off);
+}
+
+static struct isl_basic_map *add_constraints(struct isl_basic_map *bmap1,
+ struct isl_basic_map *bmap2, unsigned i_pos, unsigned o_pos)
+{
+ int i;
+ unsigned div_off;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ div_off = bmap1->n_div;
+
+ for (i = 0; i < bmap2->n_eq; ++i) {
+ int i1 = isl_basic_map_alloc_equality(bmap1);
+ if (i1 < 0)
+ goto error;
+ copy_constraint(bmap1, bmap1->eq[i1], bmap2, bmap2->eq[i],
+ i_pos, o_pos, div_off);
+ }
+
+ for (i = 0; i < bmap2->n_ineq; ++i) {
+ int i1 = isl_basic_map_alloc_inequality(bmap1);
+ if (i1 < 0)
+ goto error;
+ copy_constraint(bmap1, bmap1->ineq[i1], bmap2, bmap2->ineq[i],
+ i_pos, o_pos, div_off);
+ }
+
+ for (i = 0; i < bmap2->n_div; ++i) {
+ int i1 = isl_basic_map_alloc_div(bmap1);
+ if (i1 < 0)
+ goto error;
+ copy_div(bmap1, bmap1->div[i1], bmap2, bmap2->div[i],
+ i_pos, o_pos, div_off);
+ }
+
+ isl_basic_map_free(bmap2);
+
+ return bmap1;
+
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2, unsigned pos)
+{
+ return (struct isl_basic_set *)
+ add_constraints((struct isl_basic_map *)bset1,
+ (struct isl_basic_map *)bset2, 0, pos);
+}
+
+struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
+ __isl_take isl_space *dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *ext;
+ unsigned flags;
+ int dims_ok;
+
+ if (!dim)
+ goto error;
+
+ if (!base)
+ goto error;
+
+ dims_ok = isl_space_is_equal(base->dim, dim) &&
+ base->extra >= base->n_div + extra;
+
+ if (dims_ok && room_for_con(base, n_eq + n_ineq) &&
+ room_for_ineq(base, n_ineq)) {
+ isl_space_free(dim);
+ return base;
+ }
+
+ isl_assert(base->ctx, base->dim->nparam <= dim->nparam, goto error);
+ isl_assert(base->ctx, base->dim->n_in <= dim->n_in, goto error);
+ isl_assert(base->ctx, base->dim->n_out <= dim->n_out, goto error);
+ extra += base->extra;
+ n_eq += base->n_eq;
+ n_ineq += base->n_ineq;
+
+ ext = isl_basic_map_alloc_space(dim, extra, n_eq, n_ineq);
+ dim = NULL;
+ if (!ext)
+ goto error;
+
+ if (dims_ok)
+ ext->sample = isl_vec_copy(base->sample);
+ flags = base->flags;
+ ext = add_constraints(ext, base, 0, 0);
+ if (ext) {
+ ext->flags = flags;
+ ISL_F_CLR(ext, ISL_BASIC_SET_FINAL);
+ }
+
+ return ext;
+
+error:
+ isl_space_free(dim);
+ isl_basic_map_free(base);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
+ __isl_take isl_space *dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_extend_space((struct isl_basic_map *)base, dim,
+ extra, n_eq, n_ineq);
+}
+
+struct isl_basic_map *isl_basic_map_extend_constraints(
+ struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq)
+{
+ if (!base)
+ return NULL;
+ return isl_basic_map_extend_space(base, isl_space_copy(base->dim),
+ 0, n_eq, n_ineq);
+}
+
+struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
+ unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ struct isl_basic_map *bmap;
+ isl_space *dim;
+
+ if (!base)
+ return NULL;
+ dim = isl_space_alloc(base->ctx, nparam, n_in, n_out);
+ if (!dim)
+ goto error;
+
+ bmap = isl_basic_map_extend_space(base, dim, extra, n_eq, n_ineq);
+ return bmap;
+error:
+ isl_basic_map_free(base);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
+ unsigned nparam, unsigned dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_extend((struct isl_basic_map *)base,
+ nparam, 0, dim, extra, n_eq, n_ineq);
+}
+
+struct isl_basic_set *isl_basic_set_extend_constraints(
+ struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_extend_constraints((struct isl_basic_map *)base,
+ n_eq, n_ineq);
+}
+
+struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_cow((struct isl_basic_map *)bset);
+}
+
+struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (bmap->ref > 1) {
+ bmap->ref--;
+ bmap = isl_basic_map_dup(bmap);
+ }
+ if (bmap)
+ ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
+ return bmap;
+}
+
+struct isl_set *isl_set_cow(struct isl_set *set)
+{
+ if (!set)
+ return NULL;
+
+ if (set->ref == 1)
+ return set;
+ set->ref--;
+ return isl_set_dup(set);
+}
+
+struct isl_map *isl_map_cow(struct isl_map *map)
+{
+ if (!map)
+ return NULL;
+
+ if (map->ref == 1)
+ return map;
+ map->ref--;
+ return isl_map_dup(map);
+}
+
+static void swap_vars(struct isl_blk blk, isl_int *a,
+ unsigned a_len, unsigned b_len)
+{
+ isl_seq_cpy(blk.data, a+a_len, b_len);
+ isl_seq_cpy(blk.data+b_len, a, a_len);
+ isl_seq_cpy(a, blk.data, b_len+a_len);
+}
+
+static __isl_give isl_basic_map *isl_basic_map_swap_vars(
+ __isl_take isl_basic_map *bmap, unsigned pos, unsigned n1, unsigned n2)
+{
+ int i;
+ struct isl_blk blk;
+
+ if (!bmap)
+ goto error;
+
+ isl_assert(bmap->ctx,
+ pos + n1 + n2 <= 1 + isl_basic_map_total_dim(bmap), goto error);
+
+ if (n1 == 0 || n2 == 0)
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ blk = isl_blk_alloc(bmap->ctx, n1 + n2);
+ if (isl_blk_is_error(blk))
+ goto error;
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ swap_vars(blk,
+ bmap->eq[i] + pos, n1, n2);
+
+ for (i = 0; i < bmap->n_ineq; ++i)
+ swap_vars(blk,
+ bmap->ineq[i] + pos, n1, n2);
+
+ for (i = 0; i < bmap->n_div; ++i)
+ swap_vars(blk,
+ bmap->div[i]+1 + pos, n1, n2);
+
+ isl_blk_free(bmap->ctx, blk);
+
+ ISL_F_CLR(bmap, ISL_BASIC_SET_NORMALIZED);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_basic_set *isl_basic_set_swap_vars(
+ __isl_take isl_basic_set *bset, unsigned n)
+{
+ unsigned dim;
+ unsigned nparam;
+
+ if (!bset)
+ return NULL;
+
+ nparam = isl_basic_set_n_param(bset);
+ dim = isl_basic_set_n_dim(bset);
+ isl_assert(bset->ctx, n <= dim, goto error);
+
+ return isl_basic_map_swap_vars(bset, 1 + nparam, n, dim - n);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap)
+{
+ int i = 0;
+ unsigned total;
+ if (!bmap)
+ goto error;
+ total = isl_basic_map_total_dim(bmap);
+ isl_basic_map_free_div(bmap, bmap->n_div);
+ isl_basic_map_free_inequality(bmap, bmap->n_ineq);
+ if (bmap->n_eq > 0)
+ isl_basic_map_free_equality(bmap, bmap->n_eq-1);
+ else {
+ i = isl_basic_map_alloc_equality(bmap);
+ if (i < 0)
+ goto error;
+ }
+ isl_int_set_si(bmap->eq[i][0], 1);
+ isl_seq_clr(bmap->eq[i]+1, total);
+ ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
+ isl_vec_free(bmap->sample);
+ bmap->sample = NULL;
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_set_to_empty((struct isl_basic_map *)bset);
+}
+
+/* Swap divs "a" and "b" in "bmap" (without modifying any of the constraints
+ * of "bmap").
+ */
+static void swap_div(__isl_keep isl_basic_map *bmap, int a, int b)
+{
+ isl_int *t = bmap->div[a];
+ bmap->div[a] = bmap->div[b];
+ bmap->div[b] = t;
+}
+
+/* Swap divs "a" and "b" in "bmap" and adjust the constraints and
+ * div definitions accordingly.
+ */
+void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b)
+{
+ int i;
+ unsigned off = isl_space_dim(bmap->dim, isl_dim_all);
+
+ swap_div(bmap, a, b);
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ isl_int_swap(bmap->eq[i][1+off+a], bmap->eq[i][1+off+b]);
+
+ for (i = 0; i < bmap->n_ineq; ++i)
+ isl_int_swap(bmap->ineq[i][1+off+a], bmap->ineq[i][1+off+b]);
+
+ for (i = 0; i < bmap->n_div; ++i)
+ isl_int_swap(bmap->div[i][1+1+off+a], bmap->div[i][1+1+off+b]);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+}
+
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints, without removing the dimensions from the space.
+ * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
+ */
+__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (n == 0)
+ return map;
+
+ if (first + n > isl_map_dim(map, type) || first + n < first)
+ isl_die(map->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_eliminate(map->p[i], type, first, n);
+ if (!map->p[i])
+ goto error;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints, without removing the dimensions from the space.
+ * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
+ */
+__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_set *)isl_map_eliminate((isl_map *)set, type, first, n);
+}
+
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints, without removing the dimensions from the space.
+ * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
+ */
+__isl_give isl_set *isl_set_eliminate_dims(__isl_take isl_set *set,
+ unsigned first, unsigned n)
+{
+ return isl_set_eliminate(set, isl_dim_set, first, n);
+}
+
+__isl_give isl_basic_map *isl_basic_map_remove_divs(
+ __isl_take isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+ bmap = isl_basic_map_eliminate_vars(bmap,
+ isl_space_dim(bmap->dim, isl_dim_all), bmap->n_div);
+ if (!bmap)
+ return NULL;
+ bmap->n_div = 0;
+ return isl_basic_map_finalize(bmap);
+}
+
+__isl_give isl_basic_set *isl_basic_set_remove_divs(
+ __isl_take isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)isl_basic_map_remove_divs(
+ (struct isl_basic_map *)bset);
+}
+
+__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (map->n == 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_remove_divs(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set)
+{
+ return isl_map_remove_divs(set);
+}
+
+struct isl_basic_map *isl_basic_map_remove_dims(struct isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ if (!bmap)
+ return NULL;
+ isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
+ goto error);
+ if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
+ return bmap;
+ bmap = isl_basic_map_eliminate_vars(bmap,
+ isl_basic_map_offset(bmap, type) - 1 + first, n);
+ if (!bmap)
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY) && type == isl_dim_div)
+ return bmap;
+ bmap = isl_basic_map_drop(bmap, type, first, n);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Return true if the definition of the given div (recursively) involves
+ * any of the given variables.
+ */
+static int div_involves_vars(__isl_keep isl_basic_map *bmap, int div,
+ unsigned first, unsigned n)
+{
+ int i;
+ unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return 0;
+ if (isl_seq_first_non_zero(bmap->div[div] + 1 + first, n) >= 0)
+ return 1;
+
+ for (i = bmap->n_div - 1; i >= 0; --i) {
+ if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
+ continue;
+ if (div_involves_vars(bmap, i, first, n))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Try and add a lower and/or upper bound on "div" to "bmap"
+ * based on inequality "i".
+ * "total" is the total number of variables (excluding the divs).
+ * "v" is a temporary object that can be used during the calculations.
+ * If "lb" is set, then a lower bound should be constructed.
+ * If "ub" is set, then an upper bound should be constructed.
+ *
+ * The calling function has already checked that the inequality does not
+ * reference "div", but we still need to check that the inequality is
+ * of the right form. We'll consider the case where we want to construct
+ * a lower bound. The construction of upper bounds is similar.
+ *
+ * Let "div" be of the form
+ *
+ * q = floor((a + f(x))/d)
+ *
+ * We essentially check if constraint "i" is of the form
+ *
+ * b + f(x) >= 0
+ *
+ * so that we can use it to derive a lower bound on "div".
+ * However, we allow a slightly more general form
+ *
+ * b + g(x) >= 0
+ *
+ * with the condition that the coefficients of g(x) - f(x) are all
+ * divisible by d.
+ * Rewriting this constraint as
+ *
+ * 0 >= -b - g(x)
+ *
+ * adding a + f(x) to both sides and dividing by d, we obtain
+ *
+ * (a + f(x))/d >= (a-b)/d + (f(x)-g(x))/d
+ *
+ * Taking the floor on both sides, we obtain
+ *
+ * q >= floor((a-b)/d) + (f(x)-g(x))/d
+ *
+ * or
+ *
+ * (g(x)-f(x))/d + ceil((b-a)/d) + q >= 0
+ *
+ * In the case of an upper bound, we construct the constraint
+ *
+ * (g(x)+f(x))/d + floor((b+a)/d) - q >= 0
+ *
+ */
+static __isl_give isl_basic_map *insert_bounds_on_div_from_ineq(
+ __isl_take isl_basic_map *bmap, int div, int i,
+ unsigned total, isl_int v, int lb, int ub)
+{
+ int j;
+
+ for (j = 0; (lb || ub) && j < total + bmap->n_div; ++j) {
+ if (lb) {
+ isl_int_sub(v, bmap->ineq[i][1 + j],
+ bmap->div[div][1 + 1 + j]);
+ lb = isl_int_is_divisible_by(v, bmap->div[div][0]);
+ }
+ if (ub) {
+ isl_int_add(v, bmap->ineq[i][1 + j],
+ bmap->div[div][1 + 1 + j]);
+ ub = isl_int_is_divisible_by(v, bmap->div[div][0]);
+ }
+ }
+ if (!lb && !ub)
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 0, lb + ub);
+ if (lb) {
+ int k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ for (j = 0; j < 1 + total + bmap->n_div; ++j) {
+ isl_int_sub(bmap->ineq[k][j], bmap->ineq[i][j],
+ bmap->div[div][1 + j]);
+ isl_int_cdiv_q(bmap->ineq[k][j],
+ bmap->ineq[k][j], bmap->div[div][0]);
+ }
+ isl_int_set_si(bmap->ineq[k][1 + total + div], 1);
+ }
+ if (ub) {
+ int k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ for (j = 0; j < 1 + total + bmap->n_div; ++j) {
+ isl_int_add(bmap->ineq[k][j], bmap->ineq[i][j],
+ bmap->div[div][1 + j]);
+ isl_int_fdiv_q(bmap->ineq[k][j],
+ bmap->ineq[k][j], bmap->div[div][0]);
+ }
+ isl_int_set_si(bmap->ineq[k][1 + total + div], -1);
+ }
+
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* This function is called right before "div" is eliminated from "bmap"
+ * using Fourier-Motzkin.
+ * Look through the constraints of "bmap" for constraints on the argument
+ * of the integer division and use them to construct constraints on the
+ * integer division itself. These constraints can then be combined
+ * during the Fourier-Motzkin elimination.
+ * Note that it is only useful to introduce lower bounds on "div"
+ * if "bmap" already contains upper bounds on "div" as the newly
+ * introduce lower bounds can then be combined with the pre-existing
+ * upper bounds. Similarly for upper bounds.
+ * We therefore first check if "bmap" contains any lower and/or upper bounds
+ * on "div".
+ *
+ * It is interesting to note that the introduction of these constraints
+ * can indeed lead to more accurate results, even when compared to
+ * deriving constraints on the argument of "div" from constraints on "div".
+ * Consider, for example, the set
+ *
+ * { [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }
+ *
+ * The second constraint can be rewritten as
+ *
+ * 2 * [(-i-2j+3)/4] + k >= 0
+ *
+ * from which we can derive
+ *
+ * -i - 2j + 3 >= -2k
+ *
+ * or
+ *
+ * i + 2j <= 3 + 2k
+ *
+ * Combined with the first constraint, we obtain
+ *
+ * -3 <= 3 + 2k or k >= -3
+ *
+ * If, on the other hand we derive a constraint on [(i+2j)/4] from
+ * the first constraint, we obtain
+ *
+ * [(i + 2j)/4] >= [-3/4] = -1
+ *
+ * Combining this constraint with the second constraint, we obtain
+ *
+ * k >= -2
+ */
+static __isl_give isl_basic_map *insert_bounds_on_div(
+ __isl_take isl_basic_map *bmap, int div)
+{
+ int i;
+ int check_lb, check_ub;
+ isl_int v;
+ unsigned total;
+
+ if (!bmap)
+ return NULL;
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return bmap;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+
+ check_lb = 0;
+ check_ub = 0;
+ for (i = 0; (!check_lb || !check_ub) && i < bmap->n_ineq; ++i) {
+ int s = isl_int_sgn(bmap->ineq[i][1 + total + div]);
+ if (s > 0)
+ check_ub = 1;
+ if (s < 0)
+ check_lb = 1;
+ }
+
+ if (!check_lb && !check_ub)
+ return bmap;
+
+ isl_int_init(v);
+
+ for (i = 0; bmap && i < bmap->n_ineq; ++i) {
+ if (!isl_int_is_zero(bmap->ineq[i][1 + total + div]))
+ continue;
+
+ bmap = insert_bounds_on_div_from_ineq(bmap, div, i, total, v,
+ check_lb, check_ub);
+ }
+
+ isl_int_clear(v);
+
+ return bmap;
+}
+
+/* Remove all divs (recursively) involving any of the given dimensions
+ * in their definitions.
+ */
+__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!bmap)
+ return NULL;
+ isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
+ goto error);
+ first += isl_basic_map_offset(bmap, type);
+
+ for (i = bmap->n_div - 1; i >= 0; --i) {
+ if (!div_involves_vars(bmap, i, first, n))
+ continue;
+ bmap = insert_bounds_on_div(bmap, i);
+ bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
+ if (!bmap)
+ return NULL;
+ i = bmap->n_div;
+ }
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_basic_map_remove_divs_involving_dims(bset, type, first, n);
+}
+
+__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (map->n == 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_remove_divs_involving_dims(map->p[i],
+ type, first, n);
+ if (!map->p[i])
+ goto error;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_set *)isl_map_remove_divs_involving_dims((isl_map *)set,
+ type, first, n);
+}
+
+/* Does the desciption of "bmap" depend on the specified dimensions?
+ * We also check whether the dimensions appear in any of the div definitions.
+ * In principle there is no need for this check. If the dimensions appear
+ * in a div definition, they also appear in the defining constraints of that
+ * div.
+ */
+int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!bmap)
+ return -1;
+
+ if (first + n > isl_basic_map_dim(bmap, type))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "index out of bounds", return -1);
+
+ first += isl_basic_map_offset(bmap, type);
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (isl_seq_first_non_zero(bmap->eq[i] + first, n) >= 0)
+ return 1;
+ for (i = 0; i < bmap->n_ineq; ++i)
+ if (isl_seq_first_non_zero(bmap->ineq[i] + first, n) >= 0)
+ return 1;
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (isl_seq_first_non_zero(bmap->div[i] + 1 + first, n) >= 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+int isl_map_involves_dims(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ if (first + n > isl_map_dim(map, type))
+ isl_die(map->ctx, isl_error_invalid,
+ "index out of bounds", return -1);
+
+ for (i = 0; i < map->n; ++i) {
+ int involves = isl_basic_map_involves_dims(map->p[i],
+ type, first, n);
+ if (involves < 0 || involves)
+ return involves;
+ }
+
+ return 0;
+}
+
+int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_basic_map_involves_dims(bset, type, first, n);
+}
+
+int isl_set_involves_dims(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_map_involves_dims(set, type, first, n);
+}
+
+/* Return true if the definition of the given div is unknown or depends
+ * on unknown divs.
+ */
+static int div_is_unknown(__isl_keep isl_basic_map *bmap, int div)
+{
+ int i;
+ unsigned div_offset = isl_basic_map_offset(bmap, isl_dim_div);
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return 1;
+
+ for (i = bmap->n_div - 1; i >= 0; --i) {
+ if (isl_int_is_zero(bmap->div[div][1 + div_offset + i]))
+ continue;
+ if (div_is_unknown(bmap, i))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Remove all divs that are unknown or defined in terms of unknown divs.
+ */
+__isl_give isl_basic_map *isl_basic_map_remove_unknown_divs(
+ __isl_take isl_basic_map *bmap)
+{
+ int i;
+
+ if (!bmap)
+ return NULL;
+
+ for (i = bmap->n_div - 1; i >= 0; --i) {
+ if (!div_is_unknown(bmap, i))
+ continue;
+ bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, i, 1);
+ if (!bmap)
+ return NULL;
+ i = bmap->n_div;
+ }
+
+ return bmap;
+}
+
+/* Remove all divs that are unknown or defined in terms of unknown divs.
+ */
+__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_remove_unknown_divs(bset);
+}
+
+__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (map->n == 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_remove_unknown_divs(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set)
+{
+ return (isl_set *)isl_map_remove_unknown_divs((isl_map *)set);
+}
+
+__isl_give isl_basic_set *isl_basic_set_remove_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_basic_set *)
+ isl_basic_map_remove_dims((isl_basic_map *)bset, type, first, n);
+}
+
+struct isl_map *isl_map_remove_dims(struct isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (n == 0)
+ return map;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+ isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_eliminate_vars(map->p[i],
+ isl_basic_map_offset(map->p[i], type) - 1 + first, n);
+ if (!map->p[i])
+ goto error;
+ }
+ map = isl_map_drop(map, type, first, n);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_set *)isl_map_remove_dims((isl_map *)bset, type, first, n);
+}
+
+/* Project out n inputs starting at first using Fourier-Motzkin */
+struct isl_map *isl_map_remove_inputs(struct isl_map *map,
+ unsigned first, unsigned n)
+{
+ return isl_map_remove_dims(map, isl_dim_in, first, n);
+}
+
+static void dump_term(struct isl_basic_map *bmap,
+ isl_int c, int pos, FILE *out)
+{
+ const char *name;
+ unsigned in = isl_basic_map_n_in(bmap);
+ unsigned dim = in + isl_basic_map_n_out(bmap);
+ unsigned nparam = isl_basic_map_n_param(bmap);
+ if (!pos)
+ isl_int_print(out, c, 0);
+ else {
+ if (!isl_int_is_one(c))
+ isl_int_print(out, c, 0);
+ if (pos < 1 + nparam) {
+ name = isl_space_get_dim_name(bmap->dim,
+ isl_dim_param, pos - 1);
+ if (name)
+ fprintf(out, "%s", name);
+ else
+ fprintf(out, "p%d", pos - 1);
+ } else if (pos < 1 + nparam + in)
+ fprintf(out, "i%d", pos - 1 - nparam);
+ else if (pos < 1 + nparam + dim)
+ fprintf(out, "o%d", pos - 1 - nparam - in);
+ else
+ fprintf(out, "e%d", pos - 1 - nparam - dim);
+ }
+}
+
+static void dump_constraint_sign(struct isl_basic_map *bmap, isl_int *c,
+ int sign, FILE *out)
+{
+ int i;
+ int first;
+ unsigned len = 1 + isl_basic_map_total_dim(bmap);
+ isl_int v;
+
+ isl_int_init(v);
+ for (i = 0, first = 1; i < len; ++i) {
+ if (isl_int_sgn(c[i]) * sign <= 0)
+ continue;
+ if (!first)
+ fprintf(out, " + ");
+ first = 0;
+ isl_int_abs(v, c[i]);
+ dump_term(bmap, v, i, out);
+ }
+ isl_int_clear(v);
+ if (first)
+ fprintf(out, "0");
+}
+
+static void dump_constraint(struct isl_basic_map *bmap, isl_int *c,
+ const char *op, FILE *out, int indent)
+{
+ int i;
+
+ fprintf(out, "%*s", indent, "");
+
+ dump_constraint_sign(bmap, c, 1, out);
+ fprintf(out, " %s ", op);
+ dump_constraint_sign(bmap, c, -1, out);
+
+ fprintf(out, "\n");
+
+ for (i = bmap->n_div; i < bmap->extra; ++i) {
+ if (isl_int_is_zero(c[1+isl_space_dim(bmap->dim, isl_dim_all)+i]))
+ continue;
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "ERROR: unused div coefficient not zero\n");
+ abort();
+ }
+}
+
+static void dump_constraints(struct isl_basic_map *bmap,
+ isl_int **c, unsigned n,
+ const char *op, FILE *out, int indent)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ dump_constraint(bmap, c[i], op, out, indent);
+}
+
+static void dump_affine(struct isl_basic_map *bmap, isl_int *exp, FILE *out)
+{
+ int j;
+ int first = 1;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ for (j = 0; j < 1 + total; ++j) {
+ if (isl_int_is_zero(exp[j]))
+ continue;
+ if (!first && isl_int_is_pos(exp[j]))
+ fprintf(out, "+");
+ dump_term(bmap, exp[j], j, out);
+ first = 0;
+ }
+}
+
+static void dump(struct isl_basic_map *bmap, FILE *out, int indent)
+{
+ int i;
+
+ dump_constraints(bmap, bmap->eq, bmap->n_eq, "=", out, indent);
+ dump_constraints(bmap, bmap->ineq, bmap->n_ineq, ">=", out, indent);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "e%d = [(", i);
+ dump_affine(bmap, bmap->div[i]+1, out);
+ fprintf(out, ")/");
+ isl_int_print(out, bmap->div[i][0], 0);
+ fprintf(out, "]\n");
+ }
+}
+
+void isl_basic_set_print_internal(struct isl_basic_set *bset,
+ FILE *out, int indent)
+{
+ if (!bset) {
+ fprintf(out, "null basic set\n");
+ return;
+ }
+
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "ref: %d, nparam: %d, dim: %d, extra: %d, flags: %x\n",
+ bset->ref, bset->dim->nparam, bset->dim->n_out,
+ bset->extra, bset->flags);
+ dump((struct isl_basic_map *)bset, out, indent);
+}
+
+void isl_basic_map_print_internal(struct isl_basic_map *bmap,
+ FILE *out, int indent)
+{
+ if (!bmap) {
+ fprintf(out, "null basic map\n");
+ return;
+ }
+
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "ref: %d, nparam: %d, in: %d, out: %d, extra: %d, "
+ "flags: %x, n_name: %d\n",
+ bmap->ref,
+ bmap->dim->nparam, bmap->dim->n_in, bmap->dim->n_out,
+ bmap->extra, bmap->flags, bmap->dim->n_id);
+ dump(bmap, out, indent);
+}
+
+int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos)
+{
+ unsigned total;
+ if (!bmap)
+ return -1;
+ total = isl_basic_map_total_dim(bmap);
+ isl_assert(bmap->ctx, pos < bmap->n_ineq, return -1);
+ isl_seq_neg(bmap->ineq[pos], bmap->ineq[pos], 1 + total);
+ isl_int_sub_ui(bmap->ineq[pos][0], bmap->ineq[pos][0], 1);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ return 0;
+}
+
+__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
+ unsigned flags)
+{
+ struct isl_set *set;
+
+ if (!dim)
+ return NULL;
+ isl_assert(dim->ctx, dim->n_in == 0, goto error);
+ isl_assert(dim->ctx, n >= 0, goto error);
+ set = isl_alloc(dim->ctx, struct isl_set,
+ sizeof(struct isl_set) +
+ (n - 1) * sizeof(struct isl_basic_set *));
+ if (!set)
+ goto error;
+
+ set->ctx = dim->ctx;
+ isl_ctx_ref(set->ctx);
+ set->ref = 1;
+ set->size = n;
+ set->n = 0;
+ set->dim = dim;
+ set->flags = flags;
+ return set;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned dim, int n, unsigned flags)
+{
+ struct isl_set *set;
+ isl_space *dims;
+
+ dims = isl_space_alloc(ctx, nparam, 0, dim);
+ if (!dims)
+ return NULL;
+
+ set = isl_set_alloc_space(dims, n, flags);
+ return set;
+}
+
+/* Make sure "map" has room for at least "n" more basic maps.
+ */
+struct isl_map *isl_map_grow(struct isl_map *map, int n)
+{
+ int i;
+ struct isl_map *grown = NULL;
+
+ if (!map)
+ return NULL;
+ isl_assert(map->ctx, n >= 0, goto error);
+ if (map->n + n <= map->size)
+ return map;
+ grown = isl_map_alloc_space(isl_map_get_space(map), map->n + n, map->flags);
+ if (!grown)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ grown->p[i] = isl_basic_map_copy(map->p[i]);
+ if (!grown->p[i])
+ goto error;
+ grown->n++;
+ }
+ isl_map_free(map);
+ return grown;
+error:
+ isl_map_free(grown);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Make sure "set" has room for at least "n" more basic sets.
+ */
+struct isl_set *isl_set_grow(struct isl_set *set, int n)
+{
+ return (struct isl_set *)isl_map_grow((struct isl_map *)set, n);
+}
+
+struct isl_set *isl_set_dup(struct isl_set *set)
+{
+ int i;
+ struct isl_set *dup;
+
+ if (!set)
+ return NULL;
+
+ dup = isl_set_alloc_space(isl_space_copy(set->dim), set->n, set->flags);
+ if (!dup)
+ return NULL;
+ for (i = 0; i < set->n; ++i)
+ dup = isl_set_add_basic_set(dup, isl_basic_set_copy(set->p[i]));
+ return dup;
+}
+
+struct isl_set *isl_set_from_basic_set(struct isl_basic_set *bset)
+{
+ return isl_map_from_basic_map(bset);
+}
+
+struct isl_map *isl_map_from_basic_map(struct isl_basic_map *bmap)
+{
+ struct isl_map *map;
+
+ if (!bmap)
+ return NULL;
+
+ map = isl_map_alloc_space(isl_space_copy(bmap->dim), 1, ISL_MAP_DISJOINT);
+ return isl_map_add_basic_map(map, bmap);
+}
+
+__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *bset)
+{
+ return (struct isl_set *)isl_map_add_basic_map((struct isl_map *)set,
+ (struct isl_basic_map *)bset);
+}
+
+__isl_null isl_set *isl_set_free(__isl_take isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return NULL;
+
+ if (--set->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(set->ctx);
+ for (i = 0; i < set->n; ++i)
+ isl_basic_set_free(set->p[i]);
+ isl_space_free(set->dim);
+ free(set);
+
+ return NULL;
+}
+
+void isl_set_print_internal(struct isl_set *set, FILE *out, int indent)
+{
+ int i;
+
+ if (!set) {
+ fprintf(out, "null set\n");
+ return;
+ }
+
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "ref: %d, n: %d, nparam: %d, dim: %d, flags: %x\n",
+ set->ref, set->n, set->dim->nparam, set->dim->n_out,
+ set->flags);
+ for (i = 0; i < set->n; ++i) {
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "basic set %d:\n", i);
+ isl_basic_set_print_internal(set->p[i], out, indent+4);
+ }
+}
+
+void isl_map_print_internal(struct isl_map *map, FILE *out, int indent)
+{
+ int i;
+
+ if (!map) {
+ fprintf(out, "null map\n");
+ return;
+ }
+
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "ref: %d, n: %d, nparam: %d, in: %d, out: %d, "
+ "flags: %x, n_name: %d\n",
+ map->ref, map->n, map->dim->nparam, map->dim->n_in,
+ map->dim->n_out, map->flags, map->dim->n_id);
+ for (i = 0; i < map->n; ++i) {
+ fprintf(out, "%*s", indent, "");
+ fprintf(out, "basic map %d:\n", i);
+ isl_basic_map_print_internal(map->p[i], out, indent+4);
+ }
+}
+
+struct isl_basic_map *isl_basic_map_intersect_domain(
+ struct isl_basic_map *bmap, struct isl_basic_set *bset)
+{
+ struct isl_basic_map *bmap_domain;
+
+ if (!bmap || !bset)
+ goto error;
+
+ isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
+ bset->dim, isl_dim_param), goto error);
+
+ if (isl_space_dim(bset->dim, isl_dim_set) != 0)
+ isl_assert(bset->ctx,
+ isl_basic_map_compatible_domain(bmap, bset), goto error);
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+ bset->n_div, bset->n_eq, bset->n_ineq);
+ bmap_domain = isl_basic_map_from_domain(bset);
+ bmap = add_constraints(bmap, bmap_domain, 0, 0);
+
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_intersect_range(
+ struct isl_basic_map *bmap, struct isl_basic_set *bset)
+{
+ struct isl_basic_map *bmap_range;
+
+ if (!bmap || !bset)
+ goto error;
+
+ isl_assert(bset->ctx, isl_space_match(bmap->dim, isl_dim_param,
+ bset->dim, isl_dim_param), goto error);
+
+ if (isl_space_dim(bset->dim, isl_dim_set) != 0)
+ isl_assert(bset->ctx,
+ isl_basic_map_compatible_range(bmap, bset), goto error);
+
+ if (isl_basic_set_is_universe(bset)) {
+ isl_basic_set_free(bset);
+ return bmap;
+ }
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+ bset->n_div, bset->n_eq, bset->n_ineq);
+ bmap_range = isl_basic_map_from_basic_set(bset, isl_space_copy(bset->dim));
+ bmap = add_constraints(bmap, bmap_range, 0, 0);
+
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec)
+{
+ int i;
+ unsigned total;
+ isl_int s;
+
+ if (!bmap || !vec)
+ return -1;
+
+ total = 1 + isl_basic_map_total_dim(bmap);
+ if (total != vec->size)
+ return -1;
+
+ isl_int_init(s);
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ isl_seq_inner_product(vec->el, bmap->eq[i], total, &s);
+ if (!isl_int_is_zero(s)) {
+ isl_int_clear(s);
+ return 0;
+ }
+ }
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ isl_seq_inner_product(vec->el, bmap->ineq[i], total, &s);
+ if (isl_int_is_neg(s)) {
+ isl_int_clear(s);
+ return 0;
+ }
+ }
+
+ isl_int_clear(s);
+
+ return 1;
+}
+
+int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec)
+{
+ return isl_basic_map_contains((struct isl_basic_map *)bset, vec);
+}
+
+struct isl_basic_map *isl_basic_map_intersect(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ struct isl_vec *sample = NULL;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
+ bmap2->dim, isl_dim_param), goto error);
+ if (isl_space_dim(bmap1->dim, isl_dim_all) ==
+ isl_space_dim(bmap1->dim, isl_dim_param) &&
+ isl_space_dim(bmap2->dim, isl_dim_all) !=
+ isl_space_dim(bmap2->dim, isl_dim_param))
+ return isl_basic_map_intersect(bmap2, bmap1);
+
+ if (isl_space_dim(bmap2->dim, isl_dim_all) !=
+ isl_space_dim(bmap2->dim, isl_dim_param))
+ isl_assert(bmap1->ctx,
+ isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
+
+ if (bmap1->sample &&
+ isl_basic_map_contains(bmap1, bmap1->sample) > 0 &&
+ isl_basic_map_contains(bmap2, bmap1->sample) > 0)
+ sample = isl_vec_copy(bmap1->sample);
+ else if (bmap2->sample &&
+ isl_basic_map_contains(bmap1, bmap2->sample) > 0 &&
+ isl_basic_map_contains(bmap2, bmap2->sample) > 0)
+ sample = isl_vec_copy(bmap2->sample);
+
+ bmap1 = isl_basic_map_cow(bmap1);
+ if (!bmap1)
+ goto error;
+ bmap1 = isl_basic_map_extend_space(bmap1, isl_space_copy(bmap1->dim),
+ bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
+ bmap1 = add_constraints(bmap1, bmap2, 0, 0);
+
+ if (!bmap1)
+ isl_vec_free(sample);
+ else if (sample) {
+ isl_vec_free(bmap1->sample);
+ bmap1->sample = sample;
+ }
+
+ bmap1 = isl_basic_map_simplify(bmap1);
+ return isl_basic_map_finalize(bmap1);
+error:
+ if (sample)
+ isl_vec_free(sample);
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_intersect(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_intersect(
+ (struct isl_basic_map *)bset1,
+ (struct isl_basic_map *)bset2);
+}
+
+__isl_give isl_basic_set *isl_basic_set_intersect_params(
+ __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
+{
+ return isl_basic_set_intersect(bset1, bset2);
+}
+
+/* Special case of isl_map_intersect, where both map1 and map2
+ * are convex, without any divs and such that either map1 or map2
+ * contains a single constraint. This constraint is then simply
+ * added to the other map.
+ */
+static __isl_give isl_map *map_intersect_add_constraint(
+ __isl_take isl_map *map1, __isl_take isl_map *map2)
+{
+ isl_assert(map1->ctx, map1->n == 1, goto error);
+ isl_assert(map2->ctx, map1->n == 1, goto error);
+ isl_assert(map1->ctx, map1->p[0]->n_div == 0, goto error);
+ isl_assert(map2->ctx, map1->p[0]->n_div == 0, goto error);
+
+ if (map2->p[0]->n_eq + map2->p[0]->n_ineq != 1)
+ return isl_map_intersect(map2, map1);
+
+ isl_assert(map2->ctx,
+ map2->p[0]->n_eq + map2->p[0]->n_ineq == 1, goto error);
+
+ map1 = isl_map_cow(map1);
+ if (!map1)
+ goto error;
+ if (isl_map_plain_is_empty(map1)) {
+ isl_map_free(map2);
+ return map1;
+ }
+ map1->p[0] = isl_basic_map_cow(map1->p[0]);
+ if (map2->p[0]->n_eq == 1)
+ map1->p[0] = isl_basic_map_add_eq(map1->p[0], map2->p[0]->eq[0]);
+ else
+ map1->p[0] = isl_basic_map_add_ineq(map1->p[0],
+ map2->p[0]->ineq[0]);
+
+ map1->p[0] = isl_basic_map_simplify(map1->p[0]);
+ map1->p[0] = isl_basic_map_finalize(map1->p[0]);
+ if (!map1->p[0])
+ goto error;
+
+ if (isl_basic_map_plain_is_empty(map1->p[0])) {
+ isl_basic_map_free(map1->p[0]);
+ map1->n = 0;
+ }
+
+ isl_map_free(map2);
+
+ return map1;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+/* map2 may be either a parameter domain or a map living in the same
+ * space as map1.
+ */
+static __isl_give isl_map *map_intersect_internal(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ unsigned flags = 0;
+ isl_map *result;
+ int i, j;
+
+ if (!map1 || !map2)
+ goto error;
+
+ if ((isl_map_plain_is_empty(map1) ||
+ isl_map_plain_is_universe(map2)) &&
+ isl_space_is_equal(map1->dim, map2->dim)) {
+ isl_map_free(map2);
+ return map1;
+ }
+ if ((isl_map_plain_is_empty(map2) ||
+ isl_map_plain_is_universe(map1)) &&
+ isl_space_is_equal(map1->dim, map2->dim)) {
+ isl_map_free(map1);
+ return map2;
+ }
+
+ if (map1->n == 1 && map2->n == 1 &&
+ map1->p[0]->n_div == 0 && map2->p[0]->n_div == 0 &&
+ isl_space_is_equal(map1->dim, map2->dim) &&
+ (map1->p[0]->n_eq + map1->p[0]->n_ineq == 1 ||
+ map2->p[0]->n_eq + map2->p[0]->n_ineq == 1))
+ return map_intersect_add_constraint(map1, map2);
+
+ if (isl_space_dim(map2->dim, isl_dim_all) !=
+ isl_space_dim(map2->dim, isl_dim_param))
+ isl_assert(map1->ctx,
+ isl_space_is_equal(map1->dim, map2->dim), goto error);
+
+ if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
+ ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
+ ISL_FL_SET(flags, ISL_MAP_DISJOINT);
+
+ result = isl_map_alloc_space(isl_space_copy(map1->dim),
+ map1->n * map2->n, flags);
+ if (!result)
+ goto error;
+ for (i = 0; i < map1->n; ++i)
+ for (j = 0; j < map2->n; ++j) {
+ struct isl_basic_map *part;
+ part = isl_basic_map_intersect(
+ isl_basic_map_copy(map1->p[i]),
+ isl_basic_map_copy(map2->p[j]));
+ if (isl_basic_map_is_empty(part) < 0)
+ part = isl_basic_map_free(part);
+ result = isl_map_add_basic_map(result, part);
+ if (!result)
+ goto error;
+ }
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return result;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+static __isl_give isl_map *map_intersect(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ if (!map1 || !map2)
+ goto error;
+ if (!isl_space_is_equal(map1->dim, map2->dim))
+ isl_die(isl_map_get_ctx(map1), isl_error_invalid,
+ "spaces don't match", goto error);
+ return map_intersect_internal(map1, map2);
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_intersect);
+}
+
+struct isl_set *isl_set_intersect(struct isl_set *set1, struct isl_set *set2)
+{
+ return (struct isl_set *)
+ isl_map_intersect((struct isl_map *)set1,
+ (struct isl_map *)set2);
+}
+
+/* map_intersect_internal accepts intersections
+ * with parameter domains, so we can just call that function.
+ */
+static __isl_give isl_map *map_intersect_params(__isl_take isl_map *map,
+ __isl_take isl_set *params)
+{
+ return map_intersect_internal(map, params);
+}
+
+__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_intersect_params);
+}
+
+__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
+ __isl_take isl_set *params)
+{
+ return isl_map_intersect_params(set, params);
+}
+
+struct isl_basic_map *isl_basic_map_reverse(struct isl_basic_map *bmap)
+{
+ isl_space *dim;
+ struct isl_basic_set *bset;
+ unsigned in;
+
+ if (!bmap)
+ return NULL;
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ dim = isl_space_reverse(isl_space_copy(bmap->dim));
+ in = isl_basic_map_n_in(bmap);
+ bset = isl_basic_set_from_basic_map(bmap);
+ bset = isl_basic_set_swap_vars(bset, in);
+ return isl_basic_map_from_basic_set(bset, dim);
+}
+
+static __isl_give isl_basic_map *basic_map_space_reset(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type)
+{
+ isl_space *space;
+
+ if (!bmap)
+ return NULL;
+ if (!isl_space_is_named_or_nested(bmap->dim, type))
+ return bmap;
+
+ space = isl_basic_map_get_space(bmap);
+ space = isl_space_reset(space, type);
+ bmap = isl_basic_map_reset_space(bmap, space);
+ return bmap;
+}
+
+__isl_give isl_basic_map *isl_basic_map_insert_dims(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type,
+ unsigned pos, unsigned n)
+{
+ isl_space *res_dim;
+ struct isl_basic_map *res;
+ struct isl_dim_map *dim_map;
+ unsigned total, off;
+ enum isl_dim_type t;
+
+ if (n == 0)
+ return basic_map_space_reset(bmap, type);
+
+ if (!bmap)
+ return NULL;
+
+ res_dim = isl_space_insert_dims(isl_basic_map_get_space(bmap), type, pos, n);
+
+ total = isl_basic_map_total_dim(bmap) + n;
+ dim_map = isl_dim_map_alloc(bmap->ctx, total);
+ off = 0;
+ for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+ if (t != type) {
+ isl_dim_map_dim(dim_map, bmap->dim, t, off);
+ } else {
+ unsigned size = isl_basic_map_dim(bmap, t);
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ 0, pos, off);
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ pos, size - pos, off + pos + n);
+ }
+ off += isl_space_dim(res_dim, t);
+ }
+ isl_dim_map_div(dim_map, bmap, off);
+
+ res = isl_basic_map_alloc_space(res_dim,
+ bmap->n_div, bmap->n_eq, bmap->n_ineq);
+ if (isl_basic_map_is_rational(bmap))
+ res = isl_basic_map_set_rational(res);
+ if (isl_basic_map_plain_is_empty(bmap)) {
+ isl_basic_map_free(bmap);
+ free(dim_map);
+ return isl_basic_map_set_to_empty(res);
+ }
+ res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
+ return isl_basic_map_finalize(res);
+}
+
+__isl_give isl_basic_set *isl_basic_set_insert_dims(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return isl_basic_map_insert_dims(bset, type, pos, n);
+}
+
+__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned n)
+{
+ if (!bmap)
+ return NULL;
+ return isl_basic_map_insert_dims(bmap, type,
+ isl_basic_map_dim(bmap, type), n);
+}
+
+__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned n)
+{
+ if (!bset)
+ return NULL;
+ isl_assert(bset->ctx, type != isl_dim_in, goto error);
+ return (isl_basic_set *)isl_basic_map_add((isl_basic_map *)bset, type, n);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static __isl_give isl_map *map_space_reset(__isl_take isl_map *map,
+ enum isl_dim_type type)
+{
+ isl_space *space;
+
+ if (!map || !isl_space_is_named_or_nested(map->dim, type))
+ return map;
+
+ space = isl_map_get_space(map);
+ space = isl_space_reset(space, type);
+ map = isl_map_reset_space(map, space);
+ return map;
+}
+
+__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ int i;
+
+ if (n == 0)
+ return map_space_reset(map, type);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_insert_dims(map->dim, type, pos, n);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_insert_dims(map->p[i], type, pos, n);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ return isl_map_insert_dims(set, type, pos, n);
+}
+
+__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned n)
+{
+ if (!map)
+ return NULL;
+ return isl_map_insert_dims(map, type, isl_map_dim(map, type), n);
+}
+
+__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned n)
+{
+ if (!set)
+ return NULL;
+ isl_assert(set->ctx, type != isl_dim_in, goto error);
+ return (isl_set *)isl_map_add_dims((isl_map *)set, type, n);
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_move_dims(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ struct isl_dim_map *dim_map;
+ struct isl_basic_map *res;
+ enum isl_dim_type t;
+ unsigned total, off;
+
+ if (!bmap)
+ return NULL;
+ if (n == 0)
+ return bmap;
+
+ isl_assert(bmap->ctx, src_pos + n <= isl_basic_map_dim(bmap, src_type),
+ goto error);
+
+ if (dst_type == src_type && dst_pos == src_pos)
+ return bmap;
+
+ isl_assert(bmap->ctx, dst_type != src_type, goto error);
+
+ if (pos(bmap->dim, dst_type) + dst_pos ==
+ pos(bmap->dim, src_type) + src_pos +
+ ((src_type < dst_type) ? n : 0)) {
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+ }
+
+ total = isl_basic_map_total_dim(bmap);
+ dim_map = isl_dim_map_alloc(bmap->ctx, total);
+
+ off = 0;
+ for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+ unsigned size = isl_space_dim(bmap->dim, t);
+ if (t == dst_type) {
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ 0, dst_pos, off);
+ off += dst_pos;
+ isl_dim_map_dim_range(dim_map, bmap->dim, src_type,
+ src_pos, n, off);
+ off += n;
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ dst_pos, size - dst_pos, off);
+ off += size - dst_pos;
+ } else if (t == src_type) {
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ 0, src_pos, off);
+ off += src_pos;
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ src_pos + n, size - src_pos - n, off);
+ off += size - src_pos - n;
+ } else {
+ isl_dim_map_dim(dim_map, bmap->dim, t, off);
+ off += size;
+ }
+ }
+ isl_dim_map_div(dim_map, bmap, off);
+
+ res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
+ bmap->n_div, bmap->n_eq, bmap->n_ineq);
+ bmap = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
+ if (!bmap)
+ goto error;
+
+ bmap->dim = isl_space_move_dims(bmap->dim, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!bmap->dim)
+ goto error;
+
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ return (isl_basic_set *)isl_basic_map_move_dims(
+ (isl_basic_map *)bset, dst_type, dst_pos, src_type, src_pos, n);
+}
+
+__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ if (!set)
+ return NULL;
+ isl_assert(set->ctx, dst_type != isl_dim_in, goto error);
+ return (isl_set *)isl_map_move_dims((isl_map *)set, dst_type, dst_pos,
+ src_type, src_pos, n);
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (n == 0)
+ return map;
+
+ isl_assert(map->ctx, src_pos + n <= isl_map_dim(map, src_type),
+ goto error);
+
+ if (dst_type == src_type && dst_pos == src_pos)
+ return map;
+
+ isl_assert(map->ctx, dst_type != src_type, goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_move_dims(map->dim, dst_type, dst_pos, src_type, src_pos, n);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_move_dims(map->p[i],
+ dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Move the specified dimensions to the last columns right before
+ * the divs. Don't change the dimension specification of bmap.
+ * That's the responsibility of the caller.
+ */
+static __isl_give isl_basic_map *move_last(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ struct isl_dim_map *dim_map;
+ struct isl_basic_map *res;
+ enum isl_dim_type t;
+ unsigned total, off;
+
+ if (!bmap)
+ return NULL;
+ if (pos(bmap->dim, type) + first + n ==
+ 1 + isl_space_dim(bmap->dim, isl_dim_all))
+ return bmap;
+
+ total = isl_basic_map_total_dim(bmap);
+ dim_map = isl_dim_map_alloc(bmap->ctx, total);
+
+ off = 0;
+ for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+ unsigned size = isl_space_dim(bmap->dim, t);
+ if (t == type) {
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ 0, first, off);
+ off += first;
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ first, n, total - bmap->n_div - n);
+ isl_dim_map_dim_range(dim_map, bmap->dim, t,
+ first + n, size - (first + n), off);
+ off += size - (first + n);
+ } else {
+ isl_dim_map_dim(dim_map, bmap->dim, t, off);
+ off += size;
+ }
+ }
+ isl_dim_map_div(dim_map, bmap, off + n);
+
+ res = isl_basic_map_alloc_space(isl_basic_map_get_space(bmap),
+ bmap->n_div, bmap->n_eq, bmap->n_ineq);
+ res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
+ return res;
+}
+
+/* Insert "n" rows in the divs of "bmap".
+ *
+ * The number of columns is not changed, which means that the last
+ * dimensions of "bmap" are being reintepreted as the new divs.
+ * The space of "bmap" is not adjusted, however, which means
+ * that "bmap" is left in an inconsistent state. Removing "n" dimensions
+ * from the space of "bmap" is the responsibility of the caller.
+ */
+static __isl_give isl_basic_map *insert_div_rows(__isl_take isl_basic_map *bmap,
+ int n)
+{
+ int i;
+ size_t row_size;
+ isl_int **new_div;
+ isl_int *old;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ row_size = 1 + isl_space_dim(bmap->dim, isl_dim_all) + bmap->extra;
+ old = bmap->block2.data;
+ bmap->block2 = isl_blk_extend(bmap->ctx, bmap->block2,
+ (bmap->extra + n) * (1 + row_size));
+ if (!bmap->block2.data)
+ return isl_basic_map_free(bmap);
+ new_div = isl_alloc_array(bmap->ctx, isl_int *, bmap->extra + n);
+ if (!new_div)
+ return isl_basic_map_free(bmap);
+ for (i = 0; i < n; ++i) {
+ new_div[i] = bmap->block2.data +
+ (bmap->extra + i) * (1 + row_size);
+ isl_seq_clr(new_div[i], 1 + row_size);
+ }
+ for (i = 0; i < bmap->extra; ++i)
+ new_div[n + i] = bmap->block2.data + (bmap->div[i] - old);
+ free(bmap->div);
+ bmap->div = new_div;
+ bmap->n_div += n;
+ bmap->extra += n;
+
+ return bmap;
+}
+
+/* Turn the n dimensions of type type, starting at first
+ * into existentially quantified variables.
+ */
+__isl_give isl_basic_map *isl_basic_map_project_out(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ if (n == 0)
+ return basic_map_space_reset(bmap, type);
+
+ if (!bmap)
+ return NULL;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+ return isl_basic_map_remove_dims(bmap, type, first, n);
+
+ isl_assert(bmap->ctx, first + n <= isl_basic_map_dim(bmap, type),
+ goto error);
+
+ bmap = move_last(bmap, type, first, n);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = insert_div_rows(bmap, n);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
+ if (!bmap->dim)
+ goto error;
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_drop_redundant_divs(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Turn the n dimensions of type type, starting at first
+ * into existentially quantified variables.
+ */
+struct isl_basic_set *isl_basic_set_project_out(struct isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_basic_set *)isl_basic_map_project_out(
+ (isl_basic_map *)bset, type, first, n);
+}
+
+/* Turn the n dimensions of type type, starting at first
+ * into existentially quantified variables.
+ */
+__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ if (n == 0)
+ return map_space_reset(map, type);
+
+ isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_drop_dims(map->dim, type, first, n);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_project_out(map->p[i], type, first, n);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Turn the n dimensions of type type, starting at first
+ * into existentially quantified variables.
+ */
+__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_set *)isl_map_project_out((isl_map *)set, type, first, n);
+}
+
+static struct isl_basic_map *add_divs(struct isl_basic_map *bmap, unsigned n)
+{
+ int i, j;
+
+ for (i = 0; i < n; ++i) {
+ j = isl_basic_map_alloc_div(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->div[j], 1+1+isl_basic_map_total_dim(bmap));
+ }
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_apply_range(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ isl_space *dim_result = NULL;
+ struct isl_basic_map *bmap;
+ unsigned n_in, n_out, n, nparam, total, pos;
+ struct isl_dim_map *dim_map1, *dim_map2;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+ if (!isl_space_match(bmap1->dim, isl_dim_param,
+ bmap2->dim, isl_dim_param))
+ isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
+ "parameters don't match", goto error);
+ if (!isl_space_tuple_is_equal(bmap1->dim, isl_dim_out,
+ bmap2->dim, isl_dim_in))
+ isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ dim_result = isl_space_join(isl_space_copy(bmap1->dim),
+ isl_space_copy(bmap2->dim));
+
+ n_in = isl_basic_map_n_in(bmap1);
+ n_out = isl_basic_map_n_out(bmap2);
+ n = isl_basic_map_n_out(bmap1);
+ nparam = isl_basic_map_n_param(bmap1);
+
+ total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + n;
+ dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
+ dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_in);
+ isl_dim_map_div(dim_map1, bmap1, pos += n_out);
+ isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
+
+ bmap = isl_basic_map_alloc_space(dim_result,
+ bmap1->n_div + bmap2->n_div + n,
+ bmap1->n_eq + bmap2->n_eq,
+ bmap1->n_ineq + bmap2->n_ineq);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
+ bmap = add_divs(bmap, n);
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_drop_redundant_divs(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_apply(
+ struct isl_basic_set *bset, struct isl_basic_map *bmap)
+{
+ if (!bset || !bmap)
+ goto error;
+
+ isl_assert(bset->ctx, isl_basic_map_compatible_domain(bmap, bset),
+ goto error);
+
+ return (struct isl_basic_set *)
+ isl_basic_map_apply_range((struct isl_basic_map *)bset, bmap);
+error:
+ isl_basic_set_free(bset);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_apply_domain(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ isl_assert(bmap1->ctx,
+ isl_basic_map_n_in(bmap1) == isl_basic_map_n_in(bmap2), goto error);
+ isl_assert(bmap1->ctx,
+ isl_basic_map_n_param(bmap1) == isl_basic_map_n_param(bmap2),
+ goto error);
+
+ bmap1 = isl_basic_map_reverse(bmap1);
+ bmap1 = isl_basic_map_apply_range(bmap1, bmap2);
+ return isl_basic_map_reverse(bmap1);
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+/* Given two basic maps A -> f(A) and B -> g(B), construct a basic map
+ * A \cap B -> f(A) + f(B)
+ */
+struct isl_basic_map *isl_basic_map_sum(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ unsigned n_in, n_out, nparam, total, pos;
+ struct isl_basic_map *bmap = NULL;
+ struct isl_dim_map *dim_map1, *dim_map2;
+ int i;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
+ goto error);
+
+ nparam = isl_basic_map_n_param(bmap1);
+ n_in = isl_basic_map_n_in(bmap1);
+ n_out = isl_basic_map_n_out(bmap1);
+
+ total = nparam + n_in + n_out + bmap1->n_div + bmap2->n_div + 2 * n_out;
+ dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
+ dim_map2 = isl_dim_map_alloc(bmap2->ctx, total);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
+ isl_dim_map_div(dim_map1, bmap1, pos += n_in + n_out);
+ isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += bmap2->n_div);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += n_out);
+
+ bmap = isl_basic_map_alloc_space(isl_space_copy(bmap1->dim),
+ bmap1->n_div + bmap2->n_div + 2 * n_out,
+ bmap1->n_eq + bmap2->n_eq + n_out,
+ bmap1->n_ineq + bmap2->n_ineq);
+ for (i = 0; i < n_out; ++i) {
+ int j = isl_basic_map_alloc_equality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[j], 1+total);
+ isl_int_set_si(bmap->eq[j][1+nparam+n_in+i], -1);
+ isl_int_set_si(bmap->eq[j][1+pos+i], 1);
+ isl_int_set_si(bmap->eq[j][1+pos-n_out+i], 1);
+ }
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
+ bmap = add_divs(bmap, 2 * n_out);
+
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+/* Given two maps A -> f(A) and B -> g(B), construct a map
+ * A \cap B -> f(A) + f(B)
+ */
+struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2)
+{
+ struct isl_map *result;
+ int i, j;
+
+ if (!map1 || !map2)
+ goto error;
+
+ isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
+
+ result = isl_map_alloc_space(isl_space_copy(map1->dim),
+ map1->n * map2->n, 0);
+ if (!result)
+ goto error;
+ for (i = 0; i < map1->n; ++i)
+ for (j = 0; j < map2->n; ++j) {
+ struct isl_basic_map *part;
+ part = isl_basic_map_sum(
+ isl_basic_map_copy(map1->p[i]),
+ isl_basic_map_copy(map2->p[j]));
+ if (isl_basic_map_is_empty(part))
+ isl_basic_map_free(part);
+ else
+ result = isl_map_add_basic_map(result, part);
+ if (!result)
+ goto error;
+ }
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return result;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ return (isl_set *)isl_map_sum((isl_map *)set1, (isl_map *)set2);
+}
+
+/* Given a basic map A -> f(A), construct A -> -f(A).
+ */
+struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap)
+{
+ int i, j;
+ unsigned off, n;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ n = isl_basic_map_dim(bmap, isl_dim_out);
+ off = isl_basic_map_offset(bmap, isl_dim_out);
+ for (i = 0; i < bmap->n_eq; ++i)
+ for (j = 0; j < n; ++j)
+ isl_int_neg(bmap->eq[i][off+j], bmap->eq[i][off+j]);
+ for (i = 0; i < bmap->n_ineq; ++i)
+ for (j = 0; j < n; ++j)
+ isl_int_neg(bmap->ineq[i][off+j], bmap->ineq[i][off+j]);
+ for (i = 0; i < bmap->n_div; ++i)
+ for (j = 0; j < n; ++j)
+ isl_int_neg(bmap->div[i][1+off+j], bmap->div[i][1+off+j]);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return isl_basic_map_finalize(bmap);
+}
+
+__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_neg(bset);
+}
+
+/* Given a map A -> f(A), construct A -> -f(A).
+ */
+struct isl_map *isl_map_neg(struct 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_neg(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_neg(__isl_take isl_set *set)
+{
+ return (isl_set *)isl_map_neg((isl_map *)set);
+}
+
+/* Given a basic map A -> f(A) and an integer d, construct a basic map
+ * A -> floor(f(A)/d).
+ */
+struct isl_basic_map *isl_basic_map_floordiv(struct isl_basic_map *bmap,
+ isl_int d)
+{
+ unsigned n_in, n_out, nparam, total, pos;
+ struct isl_basic_map *result = NULL;
+ struct isl_dim_map *dim_map;
+ int i;
+
+ if (!bmap)
+ return NULL;
+
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ n_out = isl_basic_map_n_out(bmap);
+
+ total = nparam + n_in + n_out + bmap->n_div + n_out;
+ dim_map = isl_dim_map_alloc(bmap->ctx, total);
+ isl_dim_map_dim(dim_map, bmap->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map, bmap->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_div(dim_map, bmap, pos += n_in + n_out);
+ isl_dim_map_dim(dim_map, bmap->dim, isl_dim_out, pos += bmap->n_div);
+
+ result = isl_basic_map_alloc_space(isl_space_copy(bmap->dim),
+ bmap->n_div + n_out,
+ bmap->n_eq, bmap->n_ineq + 2 * n_out);
+ result = isl_basic_map_add_constraints_dim_map(result, bmap, dim_map);
+ result = add_divs(result, n_out);
+ for (i = 0; i < n_out; ++i) {
+ int j;
+ j = isl_basic_map_alloc_inequality(result);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(result->ineq[j], 1+total);
+ isl_int_neg(result->ineq[j][1+nparam+n_in+i], d);
+ isl_int_set_si(result->ineq[j][1+pos+i], 1);
+ j = isl_basic_map_alloc_inequality(result);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(result->ineq[j], 1+total);
+ isl_int_set(result->ineq[j][1+nparam+n_in+i], d);
+ isl_int_set_si(result->ineq[j][1+pos+i], -1);
+ isl_int_sub_ui(result->ineq[j][0], d, 1);
+ }
+
+ result = isl_basic_map_simplify(result);
+ return isl_basic_map_finalize(result);
+error:
+ isl_basic_map_free(result);
+ return NULL;
+}
+
+/* Given a map A -> f(A) and an integer d, construct a map
+ * A -> floor(f(A)/d).
+ */
+struct isl_map *isl_map_floordiv(struct isl_map *map, isl_int d)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_floordiv(map->p[i], d);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Given a map A -> f(A) and an integer d, construct a map
+ * A -> floor(f(A)/d).
+ */
+__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
+ __isl_take isl_val *d)
+{
+ if (!map || !d)
+ goto error;
+ if (!isl_val_is_int(d))
+ isl_die(isl_val_get_ctx(d), isl_error_invalid,
+ "expecting integer denominator", goto error);
+ map = isl_map_floordiv(map, d->n);
+ isl_val_free(d);
+ return map;
+error:
+ isl_map_free(map);
+ isl_val_free(d);
+ return NULL;
+}
+
+static struct isl_basic_map *var_equal(struct isl_basic_map *bmap, unsigned pos)
+{
+ int i;
+ unsigned nparam;
+ unsigned n_in;
+
+ i = isl_basic_map_alloc_equality(bmap);
+ if (i < 0)
+ goto error;
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[i][1+nparam+pos], -1);
+ isl_int_set_si(bmap->eq[i][1+nparam+n_in+pos], 1);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraints to "bmap" expressing i_pos < o_pos
+ */
+static struct isl_basic_map *var_less(struct isl_basic_map *bmap, unsigned pos)
+{
+ int i;
+ unsigned nparam;
+ unsigned n_in;
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ goto error;
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->ineq[i][0], -1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraint to "bmap" expressing i_pos <= o_pos
+ */
+static __isl_give isl_basic_map *var_less_or_equal(
+ __isl_take isl_basic_map *bmap, unsigned pos)
+{
+ int i;
+ unsigned nparam;
+ unsigned n_in;
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ goto error;
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->ineq[i][1+nparam+pos], -1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], 1);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraints to "bmap" expressing i_pos > o_pos
+ */
+static struct isl_basic_map *var_more(struct isl_basic_map *bmap, unsigned pos)
+{
+ int i;
+ unsigned nparam;
+ unsigned n_in;
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ goto error;
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->ineq[i][0], -1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraint to "bmap" expressing i_pos >= o_pos
+ */
+static __isl_give isl_basic_map *var_more_or_equal(
+ __isl_take isl_basic_map *bmap, unsigned pos)
+{
+ int i;
+ unsigned nparam;
+ unsigned n_in;
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ goto error;
+ nparam = isl_basic_map_n_param(bmap);
+ n_in = isl_basic_map_n_in(bmap);
+ isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->ineq[i][1+nparam+pos], 1);
+ isl_int_set_si(bmap->ineq[i][1+nparam+n_in+pos], -1);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_equal(
+ __isl_take isl_space *dim, unsigned n_equal)
+{
+ int i;
+ struct isl_basic_map *bmap;
+ bmap = isl_basic_map_alloc_space(dim, 0, n_equal, 0);
+ if (!bmap)
+ return NULL;
+ for (i = 0; i < n_equal && bmap; ++i)
+ bmap = var_equal(bmap, i);
+ return isl_basic_map_finalize(bmap);
+}
+
+/* Return a relation on of dimension "dim" expressing i_[0..pos] << o_[0..pos]
+ */
+__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
+ unsigned pos)
+{
+ int i;
+ struct isl_basic_map *bmap;
+ bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+ if (!bmap)
+ return NULL;
+ for (i = 0; i < pos && bmap; ++i)
+ bmap = var_equal(bmap, i);
+ if (bmap)
+ bmap = var_less(bmap, pos);
+ return isl_basic_map_finalize(bmap);
+}
+
+/* Return a relation on of dimension "dim" expressing i_[0..pos] <<= o_[0..pos]
+ */
+__isl_give isl_basic_map *isl_basic_map_less_or_equal_at(
+ __isl_take isl_space *dim, unsigned pos)
+{
+ int i;
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+ for (i = 0; i < pos; ++i)
+ bmap = var_equal(bmap, i);
+ bmap = var_less_or_equal(bmap, pos);
+ return isl_basic_map_finalize(bmap);
+}
+
+/* Return a relation on pairs of sets of dimension "dim" expressing i_pos > o_pos
+ */
+__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
+ unsigned pos)
+{
+ int i;
+ struct isl_basic_map *bmap;
+ bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+ if (!bmap)
+ return NULL;
+ for (i = 0; i < pos && bmap; ++i)
+ bmap = var_equal(bmap, i);
+ if (bmap)
+ bmap = var_more(bmap, pos);
+ return isl_basic_map_finalize(bmap);
+}
+
+/* Return a relation on of dimension "dim" expressing i_[0..pos] >>= o_[0..pos]
+ */
+__isl_give isl_basic_map *isl_basic_map_more_or_equal_at(
+ __isl_take isl_space *dim, unsigned pos)
+{
+ int i;
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_alloc_space(dim, 0, pos, 1);
+ for (i = 0; i < pos; ++i)
+ bmap = var_equal(bmap, i);
+ bmap = var_more_or_equal(bmap, pos);
+ return isl_basic_map_finalize(bmap);
+}
+
+static __isl_give isl_map *map_lex_lte_first(__isl_take isl_space *dims,
+ unsigned n, int equal)
+{
+ struct isl_map *map;
+ int i;
+
+ if (n == 0 && equal)
+ return isl_map_universe(dims);
+
+ map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
+
+ for (i = 0; i + 1 < n; ++i)
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_less_at(isl_space_copy(dims), i));
+ if (n > 0) {
+ if (equal)
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_less_or_equal_at(dims, n - 1));
+ else
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_less_at(dims, n - 1));
+ } else
+ isl_space_free(dims);
+
+ return map;
+}
+
+static __isl_give isl_map *map_lex_lte(__isl_take isl_space *dims, int equal)
+{
+ if (!dims)
+ return NULL;
+ return map_lex_lte_first(dims, dims->n_out, equal);
+}
+
+__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n)
+{
+ return map_lex_lte_first(dim, n, 0);
+}
+
+__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n)
+{
+ return map_lex_lte_first(dim, n, 1);
+}
+
+__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim)
+{
+ return map_lex_lte(isl_space_map_from_set(set_dim), 0);
+}
+
+__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim)
+{
+ return map_lex_lte(isl_space_map_from_set(set_dim), 1);
+}
+
+static __isl_give isl_map *map_lex_gte_first(__isl_take isl_space *dims,
+ unsigned n, int equal)
+{
+ struct isl_map *map;
+ int i;
+
+ if (n == 0 && equal)
+ return isl_map_universe(dims);
+
+ map = isl_map_alloc_space(isl_space_copy(dims), n, ISL_MAP_DISJOINT);
+
+ for (i = 0; i + 1 < n; ++i)
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_more_at(isl_space_copy(dims), i));
+ if (n > 0) {
+ if (equal)
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_more_or_equal_at(dims, n - 1));
+ else
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_more_at(dims, n - 1));
+ } else
+ isl_space_free(dims);
+
+ return map;
+}
+
+static __isl_give isl_map *map_lex_gte(__isl_take isl_space *dims, int equal)
+{
+ if (!dims)
+ return NULL;
+ return map_lex_gte_first(dims, dims->n_out, equal);
+}
+
+__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n)
+{
+ return map_lex_gte_first(dim, n, 0);
+}
+
+__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n)
+{
+ return map_lex_gte_first(dim, n, 1);
+}
+
+__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim)
+{
+ return map_lex_gte(isl_space_map_from_set(set_dim), 0);
+}
+
+__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim)
+{
+ return map_lex_gte(isl_space_map_from_set(set_dim), 1);
+}
+
+__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ isl_map *map;
+ map = isl_map_lex_le(isl_set_get_space(set1));
+ map = isl_map_intersect_domain(map, set1);
+ map = isl_map_intersect_range(map, set2);
+ return map;
+}
+
+__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ isl_map *map;
+ map = isl_map_lex_lt(isl_set_get_space(set1));
+ map = isl_map_intersect_domain(map, set1);
+ map = isl_map_intersect_range(map, set2);
+ return map;
+}
+
+__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ isl_map *map;
+ map = isl_map_lex_ge(isl_set_get_space(set1));
+ map = isl_map_intersect_domain(map, set1);
+ map = isl_map_intersect_range(map, set2);
+ return map;
+}
+
+__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ isl_map *map;
+ map = isl_map_lex_gt(isl_set_get_space(set1));
+ map = isl_map_intersect_domain(map, set1);
+ map = isl_map_intersect_range(map, set2);
+ return map;
+}
+
+__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *map;
+ map = isl_map_lex_le(isl_space_range(isl_map_get_space(map1)));
+ map = isl_map_apply_domain(map, isl_map_reverse(map1));
+ map = isl_map_apply_range(map, isl_map_reverse(map2));
+ return map;
+}
+
+__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *map;
+ map = isl_map_lex_lt(isl_space_range(isl_map_get_space(map1)));
+ map = isl_map_apply_domain(map, isl_map_reverse(map1));
+ map = isl_map_apply_range(map, isl_map_reverse(map2));
+ return map;
+}
+
+__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *map;
+ map = isl_map_lex_ge(isl_space_range(isl_map_get_space(map1)));
+ map = isl_map_apply_domain(map, isl_map_reverse(map1));
+ map = isl_map_apply_range(map, isl_map_reverse(map2));
+ return map;
+}
+
+__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *map;
+ map = isl_map_lex_gt(isl_space_range(isl_map_get_space(map1)));
+ map = isl_map_apply_domain(map, isl_map_reverse(map1));
+ map = isl_map_apply_range(map, isl_map_reverse(map2));
+ return map;
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_basic_set(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
+{
+ struct isl_basic_map *bmap;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset || !dim)
+ goto error;
+
+ isl_assert(bset->ctx, isl_space_compatible(bset->dim, dim), goto error);
+ isl_space_free(bset->dim);
+ bmap = (struct isl_basic_map *) bset;
+ bmap->dim = dim;
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_set_free(bset);
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ goto error;
+ if (bmap->dim->n_in == 0)
+ return (struct isl_basic_set *)bmap;
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ bmap->dim = isl_space_as_set_space(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+ bmap = isl_basic_map_finalize(bmap);
+ return (struct isl_basic_set *)bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* For a div d = floor(f/m), add the constraint
+ *
+ * f - m d >= 0
+ */
+static int add_upper_div_constraint(__isl_keep isl_basic_map *bmap,
+ unsigned pos, isl_int *div)
+{
+ int i;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ return -1;
+ isl_seq_cpy(bmap->ineq[i], div + 1, 1 + total);
+ isl_int_neg(bmap->ineq[i][1 + pos], div[0]);
+
+ return 0;
+}
+
+/* For a div d = floor(f/m), add the constraint
+ *
+ * -(f-(n-1)) + m d >= 0
+ */
+static int add_lower_div_constraint(__isl_keep isl_basic_map *bmap,
+ unsigned pos, isl_int *div)
+{
+ int i;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ return -1;
+ isl_seq_neg(bmap->ineq[i], div + 1, 1 + total);
+ isl_int_set(bmap->ineq[i][1 + pos], div[0]);
+ isl_int_add(bmap->ineq[i][0], bmap->ineq[i][0], bmap->ineq[i][1 + pos]);
+ isl_int_sub_ui(bmap->ineq[i][0], bmap->ineq[i][0], 1);
+
+ return 0;
+}
+
+/* For a div d = floor(f/m), add the constraints
+ *
+ * f - m d >= 0
+ * -(f-(n-1)) + m d >= 0
+ *
+ * Note that the second constraint is the negation of
+ *
+ * f - m d >= n
+ */
+int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
+ unsigned pos, isl_int *div)
+{
+ if (add_upper_div_constraint(bmap, pos, div) < 0)
+ return -1;
+ if (add_lower_div_constraint(bmap, pos, div) < 0)
+ return -1;
+ return 0;
+}
+
+int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
+ unsigned pos, isl_int *div)
+{
+ return isl_basic_map_add_div_constraints_var((isl_basic_map *)bset,
+ pos, div);
+}
+
+int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div)
+{
+ unsigned total = isl_basic_map_total_dim(bmap);
+ unsigned div_pos = total - bmap->n_div + div;
+
+ return isl_basic_map_add_div_constraints_var(bmap, div_pos,
+ bmap->div[div]);
+}
+
+/* For each known div d = floor(f/m), add the constraints
+ *
+ * f - m d >= 0
+ * -(f-(n-1)) + m d >= 0
+ */
+__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)
+ 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);
+ }
+
+ bmap = isl_basic_map_remove_duplicate_constraints(bmap, NULL, 0);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+}
+
+/* Add the div constraint of sign "sign" for div "div" of "bmap".
+ *
+ * In particular, if this div is of the form d = floor(f/m),
+ * then add the constraint
+ *
+ * f - m d >= 0
+ *
+ * if sign < 0 or the constraint
+ *
+ * -(f-(n-1)) + m d >= 0
+ *
+ * if sign > 0.
+ */
+int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
+ unsigned div, int sign)
+{
+ unsigned total;
+ unsigned div_pos;
+
+ if (!bmap)
+ return -1;
+
+ total = isl_basic_map_total_dim(bmap);
+ div_pos = total - bmap->n_div + div;
+
+ if (sign < 0)
+ return add_upper_div_constraint(bmap, div_pos, bmap->div[div]);
+ else
+ return add_lower_div_constraint(bmap, div_pos, bmap->div[div]);
+}
+
+int isl_basic_set_add_div_constraints(struct isl_basic_set *bset, unsigned div)
+{
+ return isl_basic_map_add_div_constraints(bset, div);
+}
+
+struct isl_basic_set *isl_basic_map_underlying_set(
+ struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ goto error;
+ if (bmap->dim->nparam == 0 && bmap->dim->n_in == 0 &&
+ bmap->n_div == 0 &&
+ !isl_space_is_named_or_nested(bmap->dim, isl_dim_in) &&
+ !isl_space_is_named_or_nested(bmap->dim, isl_dim_out))
+ return (struct isl_basic_set *)bmap;
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ bmap->dim = isl_space_underlying(bmap->dim, bmap->n_div);
+ if (!bmap->dim)
+ goto error;
+ bmap->extra -= bmap->n_div;
+ bmap->n_div = 0;
+ bmap = isl_basic_map_finalize(bmap);
+ return (struct isl_basic_set *)bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_underlying_set(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_underlying_set((isl_basic_map *)bset);
+}
+
+/* Replace each element in "list" by the result of applying
+ * isl_basic_set_underlying_set to the element.
+ */
+__isl_give isl_basic_set_list *isl_basic_set_list_underlying_set(
+ __isl_take isl_basic_set_list *list)
+{
+ int i, n;
+
+ if (!list)
+ return NULL;
+
+ n = isl_basic_set_list_n_basic_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset;
+
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ bset = isl_basic_set_underlying_set(bset);
+ list = isl_basic_set_list_set_basic_set(list, i, bset);
+ }
+
+ return list;
+}
+
+struct isl_basic_map *isl_basic_map_overlying_set(
+ struct isl_basic_set *bset, struct isl_basic_map *like)
+{
+ struct isl_basic_map *bmap;
+ struct isl_ctx *ctx;
+ unsigned total;
+ int i;
+
+ if (!bset || !like)
+ goto error;
+ ctx = bset->ctx;
+ isl_assert(ctx, bset->n_div == 0, goto error);
+ 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) {
+ isl_basic_map_free(like);
+ return (struct isl_basic_map *)bset;
+ }
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ goto error;
+ total = bset->dim->n_out + bset->extra;
+ bmap = (struct isl_basic_map *)bset;
+ isl_space_free(bmap->dim);
+ bmap->dim = isl_space_copy(like->dim);
+ if (!bmap->dim)
+ goto error;
+ bmap->n_div = like->n_div;
+ bmap->extra += like->n_div;
+ if (bmap->extra) {
+ unsigned ltotal;
+ isl_int **div;
+ ltotal = total - bmap->extra + like->extra;
+ if (ltotal > total)
+ ltotal = total;
+ bmap->block2 = isl_blk_extend(ctx, bmap->block2,
+ bmap->extra * (1 + 1 + total));
+ if (isl_blk_is_error(bmap->block2))
+ goto error;
+ div = isl_realloc_array(ctx, bmap->div, isl_int *, bmap->extra);
+ if (!div)
+ goto error;
+ bmap->div = div;
+ for (i = 0; i < bmap->extra; ++i)
+ bmap->div[i] = bmap->block2.data + i * (1 + 1 + total);
+ for (i = 0; i < like->n_div; ++i) {
+ isl_seq_cpy(bmap->div[i], like->div[i], 1 + 1 + ltotal);
+ isl_seq_clr(bmap->div[i]+1+1+ltotal, total - ltotal);
+ }
+ bmap = isl_basic_map_add_known_div_constraints(bmap);
+ }
+ isl_basic_map_free(like);
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(like);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_from_underlying_set(
+ struct isl_basic_set *bset, struct isl_basic_set *like)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_overlying_set(bset, (struct isl_basic_map *)like);
+}
+
+struct isl_set *isl_set_from_underlying_set(
+ struct isl_set *set, struct isl_basic_set *like)
+{
+ int i;
+
+ if (!set || !like)
+ goto error;
+ isl_assert(set->ctx, set->dim->n_out == isl_basic_set_total_dim(like),
+ goto error);
+ if (isl_space_is_equal(set->dim, like->dim) && like->n_div == 0) {
+ isl_basic_set_free(like);
+ return set;
+ }
+ set = isl_set_cow(set);
+ if (!set)
+ goto error;
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_from_underlying_set(set->p[i],
+ isl_basic_set_copy(like));
+ if (!set->p[i])
+ goto error;
+ }
+ isl_space_free(set->dim);
+ set->dim = isl_space_copy(like->dim);
+ if (!set->dim)
+ goto error;
+ isl_basic_set_free(like);
+ return set;
+error:
+ isl_basic_set_free(like);
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_set *isl_map_underlying_set(struct isl_map *map)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+ map->dim = isl_space_cow(map->dim);
+ if (!map->dim)
+ goto error;
+
+ for (i = 1; i < map->n; ++i)
+ isl_assert(map->ctx, map->p[0]->n_div == map->p[i]->n_div,
+ goto error);
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = (struct isl_basic_map *)
+ isl_basic_map_underlying_set(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ if (map->n == 0)
+ map->dim = isl_space_underlying(map->dim, 0);
+ else {
+ isl_space_free(map->dim);
+ map->dim = isl_space_copy(map->p[0]->dim);
+ }
+ if (!map->dim)
+ goto error;
+ return (struct isl_set *)map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_set *isl_set_to_underlying_set(struct isl_set *set)
+{
+ return (struct isl_set *)isl_map_underlying_set((struct isl_map *)set);
+}
+
+__isl_give isl_basic_map *isl_basic_map_reset_space(
+ __isl_take isl_basic_map *bmap, __isl_take isl_space *dim)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap || !dim)
+ goto error;
+
+ isl_space_free(bmap->dim);
+ bmap->dim = dim;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_reset_space(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *dim)
+{
+ return (isl_basic_set *)isl_basic_map_reset_space((isl_basic_map *)bset,
+ dim);
+}
+
+__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
+ __isl_take isl_space *dim)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map || !dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_reset_space(map->p[i],
+ isl_space_copy(dim));
+ if (!map->p[i])
+ goto error;
+ }
+ isl_space_free(map->dim);
+ map->dim = dim;
+
+ return map;
+error:
+ isl_map_free(map);
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
+ __isl_take isl_space *dim)
+{
+ return (struct isl_set *) isl_map_reset_space((struct isl_map *)set, dim);
+}
+
+/* Compute the parameter domain of the given basic set.
+ */
+__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset)
+{
+ isl_space *space;
+ unsigned n;
+
+ if (isl_basic_set_is_params(bset))
+ return bset;
+
+ n = isl_basic_set_dim(bset, isl_dim_set);
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
+ space = isl_basic_set_get_space(bset);
+ space = isl_space_params(space);
+ bset = isl_basic_set_reset_space(bset, space);
+ return bset;
+}
+
+/* Construct a zero-dimensional basic set with the given parameter domain.
+ */
+__isl_give isl_basic_set *isl_basic_set_from_params(
+ __isl_take isl_basic_set *bset)
+{
+ isl_space *space;
+ space = isl_basic_set_get_space(bset);
+ space = isl_space_set_from_params(space);
+ bset = isl_basic_set_reset_space(bset, space);
+ return bset;
+}
+
+/* Compute the parameter domain of the given set.
+ */
+__isl_give isl_set *isl_set_params(__isl_take isl_set *set)
+{
+ isl_space *space;
+ unsigned n;
+
+ if (isl_set_is_params(set))
+ return set;
+
+ n = isl_set_dim(set, isl_dim_set);
+ set = isl_set_project_out(set, isl_dim_set, 0, n);
+ space = isl_set_get_space(set);
+ space = isl_space_params(space);
+ set = isl_set_reset_space(set, space);
+ return set;
+}
+
+/* Construct a zero-dimensional set with the given parameter domain.
+ */
+__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set)
+{
+ isl_space *space;
+ space = isl_set_get_space(set);
+ space = isl_space_set_from_params(space);
+ set = isl_set_reset_space(set, space);
+ return set;
+}
+
+/* Compute the parameter domain of the given map.
+ */
+__isl_give isl_set *isl_map_params(__isl_take isl_map *map)
+{
+ isl_space *space;
+ unsigned n;
+
+ n = isl_map_dim(map, isl_dim_in);
+ map = isl_map_project_out(map, isl_dim_in, 0, n);
+ n = isl_map_dim(map, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_out, 0, n);
+ space = isl_map_get_space(map);
+ space = isl_space_params(space);
+ map = isl_map_reset_space(map, space);
+ return map;
+}
+
+struct isl_basic_set *isl_basic_map_domain(struct isl_basic_map *bmap)
+{
+ isl_space *dim;
+ struct isl_basic_set *domain;
+ unsigned n_in;
+ unsigned n_out;
+
+ if (!bmap)
+ return NULL;
+ dim = isl_space_domain(isl_basic_map_get_space(bmap));
+
+ n_in = isl_basic_map_n_in(bmap);
+ n_out = isl_basic_map_n_out(bmap);
+ domain = isl_basic_set_from_basic_map(bmap);
+ domain = isl_basic_set_project_out(domain, isl_dim_set, n_in, n_out);
+
+ domain = isl_basic_set_reset_space(domain, dim);
+
+ return domain;
+}
+
+int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ return isl_space_may_be_set(bmap->dim);
+}
+
+/* Is this basic map actually a set?
+ * Users should never call this function. Outside of isl,
+ * the type should indicate whether something is a set or a map.
+ */
+int isl_basic_map_is_set(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ return isl_space_is_set(bmap->dim);
+}
+
+struct isl_basic_set *isl_basic_map_range(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+ if (isl_basic_map_is_set(bmap))
+ return bmap;
+ return isl_basic_map_domain(isl_basic_map_reverse(bmap));
+}
+
+__isl_give isl_basic_map *isl_basic_map_domain_map(
+ __isl_take isl_basic_map *bmap)
+{
+ int i, k;
+ isl_space *dim;
+ isl_basic_map *domain;
+ int nparam, n_in, n_out;
+ unsigned total;
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+
+ dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
+ domain = isl_basic_map_universe(dim);
+
+ bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
+ bmap = isl_basic_map_apply_range(bmap, domain);
+ bmap = isl_basic_map_extend_constraints(bmap, n_in, 0);
+
+ total = isl_basic_map_total_dim(bmap);
+
+ for (i = 0; i < n_in; ++i) {
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], 1 + total);
+ isl_int_set_si(bmap->eq[k][1 + nparam + i], -1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
+ }
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_range_map(
+ __isl_take isl_basic_map *bmap)
+{
+ int i, k;
+ isl_space *dim;
+ isl_basic_map *range;
+ int nparam, n_in, n_out;
+ unsigned total;
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+
+ dim = isl_space_from_range(isl_space_range(isl_basic_map_get_space(bmap)));
+ range = isl_basic_map_universe(dim);
+
+ bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
+ bmap = isl_basic_map_apply_range(bmap, range);
+ bmap = isl_basic_map_extend_constraints(bmap, n_out, 0);
+
+ total = isl_basic_map_total_dim(bmap);
+
+ for (i = 0; i < n_out; ++i) {
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], 1 + total);
+ isl_int_set_si(bmap->eq[k][1 + nparam + n_in + i], -1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + n_in + n_out + i], 1);
+ }
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+int isl_map_may_be_set(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+ return isl_space_may_be_set(map->dim);
+}
+
+/* Is this map actually a set?
+ * Users should never call this function. Outside of isl,
+ * the type should indicate whether something is a set or a map.
+ */
+int isl_map_is_set(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+ return isl_space_is_set(map->dim);
+}
+
+struct isl_set *isl_map_range(struct isl_map *map)
+{
+ int i;
+ struct isl_set *set;
+
+ if (!map)
+ goto error;
+ if (isl_map_is_set(map))
+ return (isl_set *)map;
+
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+
+ set = (struct isl_set *) map;
+ set->dim = isl_space_range(set->dim);
+ if (!set->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ set->p[i] = isl_basic_map_range(map->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+ ISL_F_CLR(set, ISL_MAP_DISJOINT);
+ ISL_F_CLR(set, ISL_SET_NORMALIZED);
+ return set;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_domain_map(map->dim);
+ if (!map->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_domain_map(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map)
+{
+ int i;
+ isl_space *range_dim;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ range_dim = isl_space_range(isl_map_get_space(map));
+ range_dim = isl_space_from_range(range_dim);
+ map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
+ map->dim = isl_space_join(map->dim, range_dim);
+ if (!map->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_range_map(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Given a wrapped map of the form A[B -> C],
+ * return the map A[B -> C] -> B.
+ */
+__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set)
+{
+ isl_id *id;
+ isl_map *map;
+
+ if (!set)
+ return NULL;
+ if (!isl_set_has_tuple_id(set))
+ return isl_map_domain_map(isl_set_unwrap(set));
+
+ id = isl_set_get_tuple_id(set);
+ map = isl_map_domain_map(isl_set_unwrap(set));
+ map = isl_map_set_tuple_id(map, isl_dim_in, id);
+
+ return map;
+}
+
+__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
+ __isl_take isl_space *dim)
+{
+ int i;
+ struct isl_map *map = NULL;
+
+ set = isl_set_cow(set);
+ if (!set || !dim)
+ goto error;
+ isl_assert(set->ctx, isl_space_compatible(set->dim, dim), goto error);
+ map = (struct isl_map *)set;
+ for (i = 0; i < set->n; ++i) {
+ map->p[i] = isl_basic_map_from_basic_set(
+ set->p[i], isl_space_copy(dim));
+ if (!map->p[i])
+ goto error;
+ }
+ isl_space_free(map->dim);
+ map->dim = dim;
+ return map;
+error:
+ isl_space_free(dim);
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_domain(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_reverse(isl_basic_map_from_range(bset));
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_range(
+ __isl_take isl_basic_set *bset)
+{
+ isl_space *space;
+ space = isl_basic_set_get_space(bset);
+ space = isl_space_from_range(space);
+ bset = isl_basic_set_reset_space(bset, space);
+ return (isl_basic_map *)bset;
+}
+
+/* Create a relation with the given set as range.
+ * The domain of the created relation is a zero-dimensional
+ * flat anonymous space.
+ */
+__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set)
+{
+ isl_space *space;
+ space = isl_set_get_space(set);
+ space = isl_space_from_range(space);
+ set = isl_set_reset_space(set, space);
+ return (struct isl_map *)set;
+}
+
+/* Create a relation with the given set as domain.
+ * The range of the created relation is a zero-dimensional
+ * flat anonymous space.
+ */
+__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set)
+{
+ return isl_map_reverse(isl_map_from_range(set));
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
+ __isl_take isl_basic_set *domain, __isl_take isl_basic_set *range)
+{
+ return isl_basic_map_apply_range(isl_basic_map_reverse(domain), range);
+}
+
+__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
+ __isl_take isl_set *range)
+{
+ return isl_map_apply_range(isl_map_reverse(domain), range);
+}
+
+struct isl_set *isl_set_from_map(struct isl_map *map)
+{
+ int i;
+ struct isl_set *set = NULL;
+
+ if (!map)
+ return NULL;
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+ map->dim = isl_space_as_set_space(map->dim);
+ if (!map->dim)
+ goto error;
+ set = (struct isl_set *)map;
+ for (i = 0; i < map->n; ++i) {
+ set->p[i] = isl_basic_set_from_basic_map(map->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+ return set;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
+ unsigned flags)
+{
+ struct isl_map *map;
+
+ if (!dim)
+ return NULL;
+ if (n < 0)
+ isl_die(dim->ctx, isl_error_internal,
+ "negative number of basic maps", goto error);
+ map = isl_alloc(dim->ctx, struct isl_map,
+ sizeof(struct isl_map) +
+ (n - 1) * sizeof(struct isl_basic_map *));
+ if (!map)
+ goto error;
+
+ map->ctx = dim->ctx;
+ isl_ctx_ref(map->ctx);
+ map->ref = 1;
+ map->size = n;
+ map->n = 0;
+ map->dim = dim;
+ map->flags = flags;
+ return map;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
+ unsigned nparam, unsigned in, unsigned out, int n,
+ unsigned flags)
+{
+ struct isl_map *map;
+ isl_space *dims;
+
+ dims = isl_space_alloc(ctx, nparam, in, out);
+ if (!dims)
+ return NULL;
+
+ map = isl_map_alloc_space(dims, n, flags);
+ return map;
+}
+
+__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim)
+{
+ struct isl_basic_map *bmap;
+ bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
+ bmap = isl_basic_map_set_to_empty(bmap);
+ return bmap;
+}
+
+__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim)
+{
+ struct isl_basic_set *bset;
+ bset = isl_basic_set_alloc_space(dim, 0, 1, 0);
+ bset = isl_basic_set_set_to_empty(bset);
+ return bset;
+}
+
+struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model)
+{
+ struct isl_basic_map *bmap;
+ if (!model)
+ return NULL;
+ bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
+ bmap = isl_basic_map_set_to_empty(bmap);
+ return bmap;
+}
+
+struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model)
+{
+ struct isl_basic_map *bmap;
+ if (!model)
+ return NULL;
+ bmap = isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
+ bmap = isl_basic_map_set_to_empty(bmap);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *model)
+{
+ struct isl_basic_set *bset;
+ if (!model)
+ return NULL;
+ bset = isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 1, 0);
+ bset = isl_basic_set_set_to_empty(bset);
+ return bset;
+}
+
+__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim)
+{
+ struct isl_basic_map *bmap;
+ bmap = isl_basic_map_alloc_space(dim, 0, 0, 0);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+}
+
+__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim)
+{
+ struct isl_basic_set *bset;
+ bset = isl_basic_set_alloc_space(dim, 0, 0, 0);
+ bset = isl_basic_set_finalize(bset);
+ return bset;
+}
+
+__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim)
+{
+ int i;
+ unsigned total = isl_space_dim(dim, isl_dim_all);
+ isl_basic_map *bmap;
+
+ bmap= isl_basic_map_alloc_space(dim, 0, 0, total);
+ for (i = 0; i < total; ++i) {
+ int k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k], 1 + total);
+ isl_int_set_si(bmap->ineq[k][1 + i], 1);
+ }
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim)
+{
+ return isl_basic_map_nat_universe(dim);
+}
+
+__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim)
+{
+ return isl_map_from_basic_map(isl_basic_map_nat_universe(dim));
+}
+
+__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim)
+{
+ return isl_map_nat_universe(dim);
+}
+
+__isl_give isl_basic_map *isl_basic_map_universe_like(
+ __isl_keep isl_basic_map *model)
+{
+ if (!model)
+ return NULL;
+ return isl_basic_map_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
+}
+
+struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *model)
+{
+ if (!model)
+ return NULL;
+ return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
+}
+
+__isl_give isl_basic_set *isl_basic_set_universe_like_set(
+ __isl_keep isl_set *model)
+{
+ if (!model)
+ return NULL;
+ return isl_basic_set_alloc_space(isl_space_copy(model->dim), 0, 0, 0);
+}
+
+__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim)
+{
+ return isl_map_alloc_space(dim, 0, ISL_MAP_DISJOINT);
+}
+
+struct isl_map *isl_map_empty_like(struct isl_map *model)
+{
+ if (!model)
+ return NULL;
+ return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
+}
+
+struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model)
+{
+ if (!model)
+ return NULL;
+ return isl_map_alloc_space(isl_space_copy(model->dim), 0, ISL_MAP_DISJOINT);
+}
+
+__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim)
+{
+ return isl_set_alloc_space(dim, 0, ISL_MAP_DISJOINT);
+}
+
+struct isl_set *isl_set_empty_like(struct isl_set *model)
+{
+ if (!model)
+ return NULL;
+ return isl_set_empty(isl_space_copy(model->dim));
+}
+
+__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim)
+{
+ struct isl_map *map;
+ if (!dim)
+ return NULL;
+ map = isl_map_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
+ map = isl_map_add_basic_map(map, isl_basic_map_universe(dim));
+ return map;
+}
+
+__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim)
+{
+ struct isl_set *set;
+ if (!dim)
+ return NULL;
+ set = isl_set_alloc_space(isl_space_copy(dim), 1, ISL_MAP_DISJOINT);
+ set = isl_set_add_basic_set(set, isl_basic_set_universe(dim));
+ return set;
+}
+
+__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model)
+{
+ if (!model)
+ return NULL;
+ return isl_set_universe(isl_space_copy(model->dim));
+}
+
+struct isl_map *isl_map_dup(struct isl_map *map)
+{
+ int i;
+ struct isl_map *dup;
+
+ if (!map)
+ return NULL;
+ dup = isl_map_alloc_space(isl_space_copy(map->dim), map->n, map->flags);
+ for (i = 0; i < map->n; ++i)
+ dup = isl_map_add_basic_map(dup, isl_basic_map_copy(map->p[i]));
+ return dup;
+}
+
+__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *bmap)
+{
+ if (!bmap || !map)
+ goto error;
+ if (isl_basic_map_plain_is_empty(bmap)) {
+ isl_basic_map_free(bmap);
+ return map;
+ }
+ isl_assert(map->ctx, isl_space_is_equal(map->dim, bmap->dim), goto error);
+ isl_assert(map->ctx, map->n < map->size, goto error);
+ map->p[map->n] = bmap;
+ map->n++;
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ if (map)
+ isl_map_free(map);
+ if (bmap)
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_null isl_map *isl_map_free(__isl_take isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ if (--map->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(map->ctx);
+ for (i = 0; i < map->n; ++i)
+ isl_basic_map_free(map->p[i]);
+ isl_space_free(map->dim);
+ free(map);
+
+ return NULL;
+}
+
+struct isl_map *isl_map_extend(struct isl_map *base,
+ unsigned nparam, unsigned n_in, unsigned n_out)
+{
+ int i;
+
+ base = isl_map_cow(base);
+ if (!base)
+ return NULL;
+
+ base->dim = isl_space_extend(base->dim, nparam, n_in, n_out);
+ if (!base->dim)
+ goto error;
+ for (i = 0; i < base->n; ++i) {
+ base->p[i] = isl_basic_map_extend_space(base->p[i],
+ isl_space_copy(base->dim), 0, 0, 0);
+ if (!base->p[i])
+ goto error;
+ }
+ return base;
+error:
+ isl_map_free(base);
+ return NULL;
+}
+
+struct isl_set *isl_set_extend(struct isl_set *base,
+ unsigned nparam, unsigned dim)
+{
+ return (struct isl_set *)isl_map_extend((struct isl_map *)base,
+ nparam, 0, dim);
+}
+
+static struct isl_basic_map *isl_basic_map_fix_pos_si(
+ struct isl_basic_map *bmap, unsigned pos, int value)
+{
+ int j;
+
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
+ j = isl_basic_map_alloc_equality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[j][pos], -1);
+ isl_int_set_si(bmap->eq[j][0], value);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *isl_basic_map_fix_pos(
+ __isl_take isl_basic_map *bmap, unsigned pos, isl_int value)
+{
+ int j;
+
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
+ j = isl_basic_map_alloc_equality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[j] + 1, isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[j][pos], -1);
+ isl_int_set(bmap->eq[j][0], value);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_fix_si(struct isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ if (!bmap)
+ return NULL;
+ isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
+ return isl_basic_map_fix_pos_si(bmap,
+ isl_basic_map_offset(bmap, type) + pos, value);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_fix(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ if (!bmap)
+ return NULL;
+ isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
+ return isl_basic_map_fix_pos(bmap,
+ isl_basic_map_offset(bmap, type) + pos, value);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Fix the value of the variable at position "pos" of type "type" of "bmap"
+ * to be equal to "v".
+ */
+__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
+{
+ if (!bmap || !v)
+ goto error;
+ if (!isl_val_is_int(v))
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "expecting integer value", goto error);
+ if (pos >= isl_basic_map_dim(bmap, type))
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "index out of bounds", goto error);
+ pos += isl_basic_map_offset(bmap, type);
+ bmap = isl_basic_map_fix_pos(bmap, pos, v->n);
+ isl_val_free(v);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Fix the value of the variable at position "pos" of type "type" of "bset"
+ * to be equal to "v".
+ */
+__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
+{
+ return isl_basic_map_fix_val(bset, type, pos, v);
+}
+
+struct isl_basic_set *isl_basic_set_fix_si(struct isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_fix_si((struct isl_basic_map *)bset,
+ type, pos, value);
+}
+
+__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_fix((struct isl_basic_map *)bset,
+ type, pos, value);
+}
+
+struct isl_basic_map *isl_basic_map_fix_input_si(struct isl_basic_map *bmap,
+ unsigned input, int value)
+{
+ return isl_basic_map_fix_si(bmap, isl_dim_in, input, value);
+}
+
+struct isl_basic_set *isl_basic_set_fix_dim_si(struct isl_basic_set *bset,
+ unsigned dim, int value)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_fix_si((struct isl_basic_map *)bset,
+ isl_dim_set, dim, value);
+}
+
+static int remove_if_empty(__isl_keep isl_map *map, int i)
+{
+ int empty = isl_basic_map_plain_is_empty(map->p[i]);
+
+ if (empty < 0)
+ return -1;
+ if (!empty)
+ return 0;
+
+ isl_basic_map_free(map->p[i]);
+ if (i != map->n - 1) {
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ map->p[i] = map->p[map->n - 1];
+ }
+ map->n--;
+
+ return 0;
+}
+
+/* Perform "fn" on each basic map of "map", where we may not be holding
+ * the only reference to "map".
+ * In particular, "fn" should be a semantics preserving operation
+ * that we want to apply to all copies of "map". We therefore need
+ * to be careful not to modify "map" in a way that breaks "map"
+ * in case anything goes wrong.
+ */
+__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
+ __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap))
+{
+ struct isl_basic_map *bmap;
+ int i;
+
+ if (!map)
+ return NULL;
+
+ for (i = map->n - 1; i >= 0; --i) {
+ bmap = isl_basic_map_copy(map->p[i]);
+ bmap = fn(bmap);
+ if (!bmap)
+ goto error;
+ isl_basic_map_free(map->p[i]);
+ map->p[i] = bmap;
+ if (remove_if_empty(map, i) < 0)
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_map *isl_map_fix_si(struct isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+ for (i = map->n - 1; i >= 0; --i) {
+ map->p[i] = isl_basic_map_fix_si(map->p[i], type, pos, value);
+ if (remove_if_empty(map, i) < 0)
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return (struct isl_set *)
+ isl_map_fix_si((struct isl_map *)set, type, pos, value);
+}
+
+__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_fix(map->p[i], type, pos, value);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return (struct isl_set *)isl_map_fix((isl_map *)set, type, pos, value);
+}
+
+/* Fix the value of the variable at position "pos" of type "type" of "map"
+ * to be equal to "v".
+ */
+__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map || !v)
+ goto error;
+
+ if (!isl_val_is_int(v))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "expecting integer value", goto error);
+ if (pos >= isl_map_dim(map, type))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "index out of bounds", goto error);
+ for (i = map->n - 1; i >= 0; --i) {
+ map->p[i] = isl_basic_map_fix_val(map->p[i], type, pos,
+ isl_val_copy(v));
+ if (remove_if_empty(map, i) < 0)
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ isl_val_free(v);
+ return map;
+error:
+ isl_map_free(map);
+ isl_val_free(v);
+ return NULL;
+}
+
+/* Fix the value of the variable at position "pos" of type "type" of "set"
+ * to be equal to "v".
+ */
+__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
+{
+ return isl_map_fix_val(set, type, pos, v);
+}
+
+struct isl_map *isl_map_fix_input_si(struct isl_map *map,
+ unsigned input, int value)
+{
+ return isl_map_fix_si(map, isl_dim_in, input, value);
+}
+
+struct isl_set *isl_set_fix_dim_si(struct isl_set *set, unsigned dim, int value)
+{
+ return (struct isl_set *)
+ isl_map_fix_si((struct isl_map *)set, isl_dim_set, dim, value);
+}
+
+static __isl_give isl_basic_map *basic_map_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value, int upper)
+{
+ int j;
+
+ if (!bmap)
+ return NULL;
+ isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), goto error);
+ pos += isl_basic_map_offset(bmap, type);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+ j = isl_basic_map_alloc_inequality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
+ if (upper) {
+ isl_int_set_si(bmap->ineq[j][pos], -1);
+ isl_int_set_si(bmap->ineq[j][0], value);
+ } else {
+ isl_int_set_si(bmap->ineq[j][pos], 1);
+ isl_int_set_si(bmap->ineq[j][0], -value);
+ }
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return basic_map_bound_si(bmap, type, pos, value, 0);
+}
+
+/* Constrain the values of the given dimension to be no greater than "value".
+ */
+__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return basic_map_bound_si(bmap, type, pos, value, 1);
+}
+
+struct isl_basic_set *isl_basic_set_lower_bound_dim(struct isl_basic_set *bset,
+ unsigned dim, isl_int value)
+{
+ int j;
+
+ bset = isl_basic_set_cow(bset);
+ bset = isl_basic_set_extend_constraints(bset, 0, 1);
+ j = isl_basic_set_alloc_inequality(bset);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[j], 1 + isl_basic_set_total_dim(bset));
+ isl_int_set_si(bset->ineq[j][1 + isl_basic_set_n_param(bset) + dim], 1);
+ isl_int_neg(bset->ineq[j][0], value);
+ bset = isl_basic_set_simplify(bset);
+ return isl_basic_set_finalize(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static __isl_give isl_map *map_bound_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value, int upper)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ isl_assert(map->ctx, pos < isl_map_dim(map, type), goto error);
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = basic_map_bound_si(map->p[i],
+ type, pos, value, upper);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return map_bound_si(map, type, pos, value, 0);
+}
+
+__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return map_bound_si(map, type, pos, value, 1);
+}
+
+__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return (struct isl_set *)
+ isl_map_lower_bound_si((struct isl_map *)set, type, pos, value);
+}
+
+__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, int value)
+{
+ return isl_map_upper_bound_si(set, type, pos, value);
+}
+
+/* Bound the given variable of "bmap" from below (or above is "upper"
+ * is set) to "value".
+ */
+static __isl_give isl_basic_map *basic_map_bound(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, isl_int value, int upper)
+{
+ int j;
+
+ if (!bmap)
+ return NULL;
+ if (pos >= isl_basic_map_dim(bmap, type))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+ pos += isl_basic_map_offset(bmap, type);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+ j = isl_basic_map_alloc_inequality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[j], 1 + isl_basic_map_total_dim(bmap));
+ if (upper) {
+ isl_int_set_si(bmap->ineq[j][pos], -1);
+ isl_int_set(bmap->ineq[j][0], value);
+ } else {
+ isl_int_set_si(bmap->ineq[j][pos], 1);
+ isl_int_neg(bmap->ineq[j][0], value);
+ }
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Bound the given variable of "map" from below (or above is "upper"
+ * is set) to "value".
+ */
+static __isl_give isl_map *map_bound(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int value, int upper)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ if (pos >= isl_map_dim(map, type))
+ isl_die(map->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+ for (i = map->n - 1; i >= 0; --i) {
+ map->p[i] = basic_map_bound(map->p[i], type, pos, value, upper);
+ if (remove_if_empty(map, i) < 0)
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_lower_bound(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return map_bound(map, type, pos, value, 0);
+}
+
+__isl_give isl_map *isl_map_upper_bound(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return map_bound(map, type, pos, value, 1);
+}
+
+__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return isl_map_lower_bound(set, type, pos, value);
+}
+
+__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value)
+{
+ return isl_map_upper_bound(set, type, pos, value);
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "set"
+ * to be no smaller than "value".
+ */
+__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
+{
+ if (!value)
+ goto error;
+ if (!isl_val_is_int(value))
+ isl_die(isl_set_get_ctx(set), isl_error_invalid,
+ "expecting integer value", goto error);
+ set = isl_set_lower_bound(set, type, pos, value->n);
+ isl_val_free(value);
+ return set;
+error:
+ isl_val_free(value);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Force the values of the variable at position "pos" of type "type" of "set"
+ * to be no greater than "value".
+ */
+__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *value)
+{
+ if (!value)
+ goto error;
+ if (!isl_val_is_int(value))
+ isl_die(isl_set_get_ctx(set), isl_error_invalid,
+ "expecting integer value", goto error);
+ set = isl_set_upper_bound(set, type, pos, value->n);
+ isl_val_free(value);
+ return set;
+error:
+ isl_val_free(value);
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_set *isl_set_lower_bound_dim(struct isl_set *set, unsigned dim,
+ isl_int value)
+{
+ int i;
+
+ set = isl_set_cow(set);
+ if (!set)
+ return NULL;
+
+ isl_assert(set->ctx, dim < isl_set_n_dim(set), goto error);
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_lower_bound_dim(set->p[i], dim, value);
+ if (!set->p[i])
+ goto error;
+ }
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_map *isl_map_reverse(struct isl_map *map)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ map->dim = isl_space_reverse(map->dim);
+ if (!map->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_reverse(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+static struct isl_map *isl_basic_map_partial_lexopt(
+ struct isl_basic_map *bmap, struct isl_basic_set *dom,
+ struct isl_set **empty, int max)
+{
+ return isl_tab_basic_map_partial_lexopt(bmap, dom, empty, max);
+}
+
+struct isl_map *isl_basic_map_partial_lexmax(
+ struct isl_basic_map *bmap, struct isl_basic_set *dom,
+ struct isl_set **empty)
+{
+ return isl_basic_map_partial_lexopt(bmap, dom, empty, 1);
+}
+
+struct isl_map *isl_basic_map_partial_lexmin(
+ struct isl_basic_map *bmap, struct isl_basic_set *dom,
+ struct isl_set **empty)
+{
+ return isl_basic_map_partial_lexopt(bmap, dom, empty, 0);
+}
+
+struct isl_set *isl_basic_set_partial_lexmin(
+ struct isl_basic_set *bset, struct isl_basic_set *dom,
+ struct isl_set **empty)
+{
+ return (struct isl_set *)
+ isl_basic_map_partial_lexmin((struct isl_basic_map *)bset,
+ dom, empty);
+}
+
+struct isl_set *isl_basic_set_partial_lexmax(
+ struct isl_basic_set *bset, struct isl_basic_set *dom,
+ struct isl_set **empty)
+{
+ return (struct isl_set *)
+ isl_basic_map_partial_lexmax((struct isl_basic_map *)bset,
+ dom, empty);
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 0);
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, empty, 1);
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_basic_map_partial_lexmin_pw_multi_aff(bset, dom, empty);
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_basic_map_partial_lexmax_pw_multi_aff(bset, dom, empty);
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_map_lexopt_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, int max)
+{
+ isl_basic_set *dom = NULL;
+ isl_space *dom_space;
+
+ if (!bmap)
+ goto error;
+ dom_space = isl_space_domain(isl_space_copy(bmap->dim));
+ dom = isl_basic_set_universe(dom_space);
+ return isl_basic_map_partial_lexopt_pw_multi_aff(bmap, dom, NULL, max);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
+ __isl_take isl_basic_map *bmap)
+{
+ return isl_basic_map_lexopt_pw_multi_aff(bmap, 0);
+}
+
+#undef TYPE
+#define TYPE isl_pw_multi_aff
+#undef SUFFIX
+#define SUFFIX _pw_multi_aff
+#undef EMPTY
+#define EMPTY isl_pw_multi_aff_empty
+#undef ADD
+#define ADD isl_pw_multi_aff_union_add
+#include "isl_map_lexopt_templ.c"
+
+/* Given a map "map", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom,
+ * in the form of an isl_pw_multi_aff.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * We first compute the lexicographically minimal or maximal element
+ * in the first basic map. This results in a partial solution "res"
+ * and a subset "todo" of dom that still need to be handled.
+ * We then consider each of the remaining maps in "map" and successively
+ * update both "res" and "todo".
+ */
+static __isl_give isl_pw_multi_aff *isl_map_partial_lexopt_aligned_pw_multi_aff(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ int i;
+ isl_pw_multi_aff *res;
+ isl_set *todo;
+
+ if (!map || !dom)
+ goto error;
+
+ if (isl_map_plain_is_empty(map)) {
+ if (empty)
+ *empty = dom;
+ else
+ isl_set_free(dom);
+ return isl_pw_multi_aff_from_map(map);
+ }
+
+ res = basic_map_partial_lexopt_pw_multi_aff(
+ isl_basic_map_copy(map->p[0]),
+ isl_set_copy(dom), &todo, max);
+
+ for (i = 1; i < map->n; ++i) {
+ isl_pw_multi_aff *res_i;
+ isl_set *todo_i;
+
+ res_i = basic_map_partial_lexopt_pw_multi_aff(
+ isl_basic_map_copy(map->p[i]),
+ isl_set_copy(dom), &todo_i, max);
+
+ if (max)
+ res = isl_pw_multi_aff_union_lexmax(res, res_i);
+ else
+ res = isl_pw_multi_aff_union_lexmin(res, res_i);
+
+ todo = isl_set_intersect(todo, todo_i);
+ }
+
+ isl_set_free(dom);
+ isl_map_free(map);
+
+ if (empty)
+ *empty = todo;
+ else
+ isl_set_free(todo);
+
+ return res;
+error:
+ if (empty)
+ *empty = NULL;
+ isl_set_free(dom);
+ isl_map_free(map);
+ return NULL;
+}
+
+#undef TYPE
+#define TYPE isl_map
+#undef SUFFIX
+#define SUFFIX
+#undef EMPTY
+#define EMPTY isl_map_empty
+#undef ADD
+#define ADD isl_map_union_disjoint
+#include "isl_map_lexopt_templ.c"
+
+/* Given a map "map", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * We first compute the lexicographically minimal or maximal element
+ * in the first basic map. This results in a partial solution "res"
+ * and a subset "todo" of dom that still need to be handled.
+ * We then consider each of the remaining maps in "map" and successively
+ * update both "res" and "todo".
+ *
+ * Let res^k and todo^k be the results after k steps and let i = k + 1.
+ * Assume we are computing the lexicographical maximum.
+ * We first compute the lexicographically maximal element in basic map i.
+ * This results in a partial solution res_i and a subset todo_i.
+ * Then we combine these results with those obtain for the first k basic maps
+ * to obtain a result that is valid for the first k+1 basic maps.
+ * In particular, the set where there is no solution is the set where
+ * there is no solution for the first k basic maps and also no solution
+ * for the ith basic map, i.e.,
+ *
+ * todo^i = todo^k * todo_i
+ *
+ * On dom(res^k) * dom(res_i), we need to pick the larger of the two
+ * solutions, arbitrarily breaking ties in favor of res^k.
+ * That is, when res^k(a) >= res_i(a), we pick res^k and
+ * when res^k(a) < res_i(a), we pick res_i. (Here, ">=" and "<" denote
+ * the lexicographic order.)
+ * In practice, we compute
+ *
+ * res^k * (res_i . "<=")
+ *
+ * and
+ *
+ * res_i * (res^k . "<")
+ *
+ * Finally, we consider the symmetric difference of dom(res^k) and dom(res_i),
+ * where only one of res^k and res_i provides a solution and we simply pick
+ * that one, i.e.,
+ *
+ * res^k * todo_i
+ * and
+ * res_i * todo^k
+ *
+ * Note that we only compute these intersections when dom(res^k) intersects
+ * dom(res_i). Otherwise, the only effect of these intersections is to
+ * potentially break up res^k and res_i into smaller pieces.
+ * We want to avoid such splintering as much as possible.
+ * In fact, an earlier implementation of this function would look for
+ * better results in the domain of res^k and for extra results in todo^k,
+ * but this would always result in a splintering according to todo^k,
+ * even when the domain of basic map i is disjoint from the domains of
+ * the previous basic maps.
+ */
+static __isl_give isl_map *isl_map_partial_lexopt_aligned(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ int i;
+ struct isl_map *res;
+ struct isl_set *todo;
+
+ if (!map || !dom)
+ goto error;
+
+ if (isl_map_plain_is_empty(map)) {
+ if (empty)
+ *empty = dom;
+ else
+ isl_set_free(dom);
+ return map;
+ }
+
+ res = basic_map_partial_lexopt(isl_basic_map_copy(map->p[0]),
+ isl_set_copy(dom), &todo, max);
+
+ for (i = 1; i < map->n; ++i) {
+ isl_map *lt, *le;
+ isl_map *res_i;
+ isl_set *todo_i;
+ isl_space *dim = isl_space_range(isl_map_get_space(res));
+
+ res_i = basic_map_partial_lexopt(isl_basic_map_copy(map->p[i]),
+ isl_set_copy(dom), &todo_i, max);
+
+ if (max) {
+ lt = isl_map_lex_lt(isl_space_copy(dim));
+ le = isl_map_lex_le(dim);
+ } else {
+ lt = isl_map_lex_gt(isl_space_copy(dim));
+ le = isl_map_lex_ge(dim);
+ }
+ lt = isl_map_apply_range(isl_map_copy(res), lt);
+ lt = isl_map_intersect(lt, isl_map_copy(res_i));
+ le = isl_map_apply_range(isl_map_copy(res_i), le);
+ le = isl_map_intersect(le, isl_map_copy(res));
+
+ if (!isl_map_is_empty(lt) || !isl_map_is_empty(le)) {
+ res = isl_map_intersect_domain(res,
+ isl_set_copy(todo_i));
+ res_i = isl_map_intersect_domain(res_i,
+ isl_set_copy(todo));
+ }
+
+ res = isl_map_union_disjoint(res, res_i);
+ res = isl_map_union_disjoint(res, lt);
+ res = isl_map_union_disjoint(res, le);
+
+ todo = isl_set_intersect(todo, todo_i);
+ }
+
+ isl_set_free(dom);
+ isl_map_free(map);
+
+ if (empty)
+ *empty = todo;
+ else
+ isl_set_free(todo);
+
+ return res;
+error:
+ if (empty)
+ *empty = NULL;
+ isl_set_free(dom);
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_partial_lexmax(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_map_partial_lexopt(map, dom, empty, 1);
+}
+
+__isl_give isl_map *isl_map_partial_lexmin(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty)
+{
+ return isl_map_partial_lexopt(map, dom, empty, 0);
+}
+
+__isl_give isl_set *isl_set_partial_lexmin(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty)
+{
+ return (struct isl_set *)
+ isl_map_partial_lexmin((struct isl_map *)set,
+ dom, empty);
+}
+
+__isl_give isl_set *isl_set_partial_lexmax(
+ __isl_take isl_set *set, __isl_take isl_set *dom,
+ __isl_give isl_set **empty)
+{
+ return (struct isl_set *)
+ isl_map_partial_lexmax((struct isl_map *)set,
+ dom, empty);
+}
+
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over its domain.
+ *
+ * Since we are not interested in the part of the domain space where
+ * there is no solution, we initialize the domain to those constraints
+ * of "bmap" that only involve the parameters and the input dimensions.
+ * This relieves the parametric programming engine from detecting those
+ * inequalities and transferring them to the context. More importantly,
+ * it ensures that those inequalities are transferred first and not
+ * intermixed with inequalities that actually split the domain.
+ */
+__isl_give isl_map *isl_basic_map_lexopt(__isl_take isl_basic_map *bmap, int max)
+{
+ int n_div;
+ int n_out;
+ isl_basic_map *copy;
+ isl_basic_set *dom;
+
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ copy = isl_basic_map_copy(bmap);
+ copy = isl_basic_map_drop_constraints_involving_dims(copy,
+ isl_dim_div, 0, n_div);
+ copy = isl_basic_map_drop_constraints_involving_dims(copy,
+ isl_dim_out, 0, n_out);
+ dom = isl_basic_map_domain(copy);
+ return isl_basic_map_partial_lexopt(bmap, dom, NULL, max);
+}
+
+__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap)
+{
+ return isl_basic_map_lexopt(bmap, 0);
+}
+
+__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap)
+{
+ return isl_basic_map_lexopt(bmap, 1);
+}
+
+__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset)
+{
+ return (isl_set *)isl_basic_map_lexmin((isl_basic_map *)bset);
+}
+
+__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset)
+{
+ return (isl_set *)isl_basic_map_lexmax((isl_basic_map *)bset);
+}
+
+/* Extract the first and only affine expression from list
+ * and then add it to *pwaff with the given dom.
+ * This domain is known to be disjoint from other domains
+ * because of the way isl_basic_map_foreach_lexmax works.
+ */
+static int update_dim_opt(__isl_take isl_basic_set *dom,
+ __isl_take isl_aff_list *list, void *user)
+{
+ isl_ctx *ctx = isl_basic_set_get_ctx(dom);
+ isl_aff *aff;
+ isl_pw_aff **pwaff = user;
+ isl_pw_aff *pwaff_i;
+
+ if (!list)
+ goto error;
+ if (isl_aff_list_n_aff(list) != 1)
+ isl_die(ctx, isl_error_internal,
+ "expecting single element list", goto error);
+
+ aff = isl_aff_list_get_aff(list, 0);
+ pwaff_i = isl_pw_aff_alloc(isl_set_from_basic_set(dom), aff);
+
+ *pwaff = isl_pw_aff_add_disjoint(*pwaff, pwaff_i);
+
+ isl_aff_list_free(list);
+
+ return 0;
+error:
+ isl_basic_set_free(dom);
+ isl_aff_list_free(list);
+ return -1;
+}
+
+/* Given a basic map with one output dimension, compute the minimum or
+ * maximum of that dimension as an isl_pw_aff.
+ *
+ * The isl_pw_aff is constructed by having isl_basic_map_foreach_lexopt
+ * call update_dim_opt on each leaf of the result.
+ */
+static __isl_give isl_pw_aff *basic_map_dim_opt(__isl_keep isl_basic_map *bmap,
+ int max)
+{
+ isl_space *dim = isl_basic_map_get_space(bmap);
+ isl_pw_aff *pwaff;
+ int r;
+
+ dim = isl_space_from_domain(isl_space_domain(dim));
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ pwaff = isl_pw_aff_empty(dim);
+
+ r = isl_basic_map_foreach_lexopt(bmap, max, &update_dim_opt, &pwaff);
+ if (r < 0)
+ return isl_pw_aff_free(pwaff);
+
+ return pwaff;
+}
+
+/* Compute the minimum or maximum of the given output dimension
+ * as a function of the parameters and the input dimensions,
+ * but independently of the other output dimensions.
+ *
+ * We first project out the other output dimension and then compute
+ * the "lexicographic" maximum in each basic map, combining the results
+ * using isl_pw_aff_union_max.
+ */
+static __isl_give isl_pw_aff *map_dim_opt(__isl_take isl_map *map, int pos,
+ int max)
+{
+ int i;
+ isl_pw_aff *pwaff;
+ unsigned n_out;
+
+ n_out = isl_map_dim(map, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_out, pos + 1, n_out - (pos + 1));
+ map = isl_map_project_out(map, isl_dim_out, 0, pos);
+ if (!map)
+ return NULL;
+
+ if (map->n == 0) {
+ isl_space *dim = isl_map_get_space(map);
+ isl_map_free(map);
+ return isl_pw_aff_empty(dim);
+ }
+
+ pwaff = basic_map_dim_opt(map->p[0], max);
+ for (i = 1; i < map->n; ++i) {
+ isl_pw_aff *pwaff_i;
+
+ pwaff_i = basic_map_dim_opt(map->p[i], max);
+ pwaff = isl_pw_aff_union_opt(pwaff, pwaff_i, max);
+ }
+
+ isl_map_free(map);
+
+ return pwaff;
+}
+
+/* Compute the maximum of the given output dimension as a function of the
+ * parameters and input dimensions, but independently of
+ * the other output dimensions.
+ */
+__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos)
+{
+ return map_dim_opt(map, pos, 1);
+}
+
+/* Compute the minimum or maximum of the given set dimension
+ * as a function of the parameters,
+ * but independently of the other set dimensions.
+ */
+static __isl_give isl_pw_aff *set_dim_opt(__isl_take isl_set *set, int pos,
+ int max)
+{
+ return map_dim_opt(set, pos, max);
+}
+
+/* Compute the maximum of the given set dimension as a function of the
+ * parameters, but independently of the other set dimensions.
+ */
+__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos)
+{
+ return set_dim_opt(set, pos, 1);
+}
+
+/* Compute the minimum of the given set dimension as a function of the
+ * parameters, but independently of the other set dimensions.
+ */
+__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos)
+{
+ return set_dim_opt(set, pos, 0);
+}
+
+/* Apply a preimage specified by "mat" on the parameters of "bset".
+ * bset is assumed to have only parameters and divs.
+ */
+static struct isl_basic_set *basic_set_parameter_preimage(
+ struct isl_basic_set *bset, struct isl_mat *mat)
+{
+ unsigned nparam;
+
+ if (!bset || !mat)
+ goto error;
+
+ bset->dim = isl_space_cow(bset->dim);
+ if (!bset->dim)
+ goto error;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ isl_assert(bset->ctx, mat->n_row == 1 + nparam, goto error);
+
+ bset->dim->nparam = 0;
+ bset->dim->n_out = nparam;
+ bset = isl_basic_set_preimage(bset, mat);
+ if (bset) {
+ bset->dim->nparam = bset->dim->n_out;
+ bset->dim->n_out = 0;
+ }
+ return bset;
+error:
+ isl_mat_free(mat);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Apply a preimage specified by "mat" on the parameters of "set".
+ * set is assumed to have only parameters and divs.
+ */
+static struct isl_set *set_parameter_preimage(
+ struct isl_set *set, struct isl_mat *mat)
+{
+ isl_space *dim = NULL;
+ unsigned nparam;
+
+ if (!set || !mat)
+ goto error;
+
+ dim = isl_space_copy(set->dim);
+ dim = isl_space_cow(dim);
+ if (!dim)
+ goto error;
+
+ nparam = isl_set_dim(set, isl_dim_param);
+
+ isl_assert(set->ctx, mat->n_row == 1 + nparam, goto error);
+
+ dim->nparam = 0;
+ dim->n_out = nparam;
+ isl_set_reset_space(set, dim);
+ set = isl_set_preimage(set, mat);
+ if (!set)
+ goto error2;
+ dim = isl_space_copy(set->dim);
+ dim = isl_space_cow(dim);
+ if (!dim)
+ goto error2;
+ dim->nparam = dim->n_out;
+ dim->n_out = 0;
+ isl_set_reset_space(set, dim);
+ return set;
+error:
+ isl_space_free(dim);
+ isl_mat_free(mat);
+error2:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Intersect the basic set "bset" with the affine space specified by the
+ * equalities in "eq".
+ */
+static struct isl_basic_set *basic_set_append_equalities(
+ struct isl_basic_set *bset, struct isl_mat *eq)
+{
+ int i, k;
+ unsigned len;
+
+ if (!bset || !eq)
+ goto error;
+
+ bset = isl_basic_set_extend_space(bset, isl_space_copy(bset->dim), 0,
+ eq->n_row, 0);
+ if (!bset)
+ goto error;
+
+ len = 1 + isl_space_dim(bset->dim, isl_dim_all) + bset->extra;
+ for (i = 0; i < eq->n_row; ++i) {
+ k = isl_basic_set_alloc_equality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->eq[k], eq->row[i], eq->n_col);
+ isl_seq_clr(bset->eq[k] + eq->n_col, len - eq->n_col);
+ }
+ isl_mat_free(eq);
+
+ bset = isl_basic_set_gauss(bset, NULL);
+ bset = isl_basic_set_finalize(bset);
+
+ return bset;
+error:
+ isl_mat_free(eq);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Intersect the set "set" with the affine space specified by the
+ * equalities in "eq".
+ */
+static struct isl_set *set_append_equalities(struct isl_set *set,
+ struct isl_mat *eq)
+{
+ int i;
+
+ if (!set || !eq)
+ goto error;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = basic_set_append_equalities(set->p[i],
+ isl_mat_copy(eq));
+ if (!set->p[i])
+ goto error;
+ }
+ isl_mat_free(eq);
+ return set;
+error:
+ isl_mat_free(eq);
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Given a basic set "bset" that only involves parameters and existentially
+ * quantified variables, return the index of the first equality
+ * that only involves parameters. If there is no such equality then
+ * return bset->n_eq.
+ *
+ * This function assumes that isl_basic_set_gauss has been called on "bset".
+ */
+static int first_parameter_equality(__isl_keep isl_basic_set *bset)
+{
+ int i, j;
+ unsigned nparam, n_div;
+
+ if (!bset)
+ return -1;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+
+ for (i = 0, j = n_div - 1; i < bset->n_eq && j >= 0; --j) {
+ if (!isl_int_is_zero(bset->eq[i][1 + nparam + j]))
+ ++i;
+ }
+
+ return i;
+}
+
+/* Compute an explicit representation for the existentially quantified
+ * variables in "bset" by computing the "minimal value" of the set
+ * variables. Since there are no set variables, the computation of
+ * the minimal value essentially computes an explicit representation
+ * of the non-empty part(s) of "bset".
+ *
+ * The input only involves parameters and existentially quantified variables.
+ * All equalities among parameters have been removed.
+ *
+ * Since the existentially quantified variables in the result are in general
+ * going to be different from those in the input, we first replace
+ * them by the minimal number of variables based on their equalities.
+ * This should simplify the parametric integer programming.
+ */
+static __isl_give isl_set *base_compute_divs(__isl_take isl_basic_set *bset)
+{
+ isl_morph *morph1, *morph2;
+ isl_set *set;
+ unsigned n;
+
+ if (!bset)
+ return NULL;
+ if (bset->n_eq == 0)
+ return isl_basic_set_lexmin(bset);
+
+ morph1 = isl_basic_set_parameter_compression(bset);
+ bset = isl_morph_basic_set(isl_morph_copy(morph1), bset);
+ bset = isl_basic_set_lift(bset);
+ morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
+ bset = isl_morph_basic_set(morph2, bset);
+ n = isl_basic_set_dim(bset, isl_dim_set);
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 0, n);
+
+ set = isl_basic_set_lexmin(bset);
+
+ set = isl_morph_set(isl_morph_inverse(morph1), set);
+
+ return set;
+}
+
+/* Project the given basic set onto its parameter domain, possibly introducing
+ * new, explicit, existential variables in the constraints.
+ * The input has parameters and (possibly implicit) existential variables.
+ * The output has the same parameters, but only
+ * explicit existentially quantified variables.
+ *
+ * The actual projection is performed by pip, but pip doesn't seem
+ * to like equalities very much, so we first remove the equalities
+ * among the parameters by performing a variable compression on
+ * the parameters. Afterward, an inverse transformation is performed
+ * and the equalities among the parameters are inserted back in.
+ *
+ * The variable compression on the parameters may uncover additional
+ * equalities that were only implicit before. We therefore check
+ * if there are any new parameter equalities in the result and
+ * if so recurse. The removal of parameter equalities is required
+ * for the parameter compression performed by base_compute_divs.
+ */
+static struct isl_set *parameter_compute_divs(struct isl_basic_set *bset)
+{
+ int i;
+ struct isl_mat *eq;
+ struct isl_mat *T, *T2;
+ struct isl_set *set;
+ unsigned nparam;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+
+ if (bset->n_eq == 0)
+ return base_compute_divs(bset);
+
+ bset = isl_basic_set_gauss(bset, NULL);
+ if (!bset)
+ return NULL;
+ if (isl_basic_set_plain_is_empty(bset))
+ return isl_set_from_basic_set(bset);
+
+ i = first_parameter_equality(bset);
+ if (i == bset->n_eq)
+ return base_compute_divs(bset);
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ eq = isl_mat_sub_alloc6(bset->ctx, bset->eq, i, bset->n_eq - i,
+ 0, 1 + nparam);
+ eq = isl_mat_cow(eq);
+ T = isl_mat_variable_compression(isl_mat_copy(eq), &T2);
+ if (T && T->n_col == 0) {
+ isl_mat_free(T);
+ isl_mat_free(T2);
+ isl_mat_free(eq);
+ bset = isl_basic_set_set_to_empty(bset);
+ return isl_set_from_basic_set(bset);
+ }
+ bset = basic_set_parameter_preimage(bset, T);
+
+ i = first_parameter_equality(bset);
+ if (!bset)
+ set = NULL;
+ else if (i == bset->n_eq)
+ set = base_compute_divs(bset);
+ else
+ set = parameter_compute_divs(bset);
+ set = set_parameter_preimage(set, T2);
+ set = set_append_equalities(set, eq);
+ return set;
+}
+
+/* Insert the divs from "ls" before those of "bmap".
+ *
+ * The number of columns is not changed, which means that the last
+ * dimensions of "bmap" are being reintepreted as the divs from "ls".
+ * The caller is responsible for removing the same number of dimensions
+ * from the space of "bmap".
+ */
+static __isl_give isl_basic_map *insert_divs_from_local_space(
+ __isl_take isl_basic_map *bmap, __isl_keep isl_local_space *ls)
+{
+ int i;
+ int n_div;
+ int old_n_div;
+
+ n_div = isl_local_space_dim(ls, isl_dim_div);
+ if (n_div == 0)
+ return bmap;
+
+ old_n_div = bmap->n_div;
+ bmap = insert_div_rows(bmap, n_div);
+ if (!bmap)
+ return NULL;
+
+ for (i = 0; i < n_div; ++i) {
+ isl_seq_cpy(bmap->div[i], ls->div->row[i], ls->div->n_col);
+ isl_seq_clr(bmap->div[i] + ls->div->n_col, old_n_div);
+ }
+
+ return bmap;
+}
+
+/* Replace the space of "bmap" by the space and divs of "ls".
+ *
+ * If "ls" has any divs, then we simplify the result since we may
+ * have discovered some additional equalities that could simplify
+ * the div expressions.
+ */
+static __isl_give isl_basic_map *basic_replace_space_by_local_space(
+ __isl_take isl_basic_map *bmap, __isl_take isl_local_space *ls)
+{
+ int n_div;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap || !ls)
+ goto error;
+
+ n_div = isl_local_space_dim(ls, isl_dim_div);
+ bmap = insert_divs_from_local_space(bmap, ls);
+ if (!bmap)
+ goto error;
+
+ isl_space_free(bmap->dim);
+ bmap->dim = isl_local_space_get_space(ls);
+ if (!bmap->dim)
+ goto error;
+
+ isl_local_space_free(ls);
+ if (n_div > 0)
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_local_space_free(ls);
+ return NULL;
+}
+
+/* Replace the space of "map" by the space and divs of "ls".
+ */
+static __isl_give isl_map *replace_space_by_local_space(__isl_take isl_map *map,
+ __isl_take isl_local_space *ls)
+{
+ int i;
+
+ map = isl_map_cow(map);
+ if (!map || !ls)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = basic_replace_space_by_local_space(map->p[i],
+ isl_local_space_copy(ls));
+ if (!map->p[i])
+ goto error;
+ }
+ isl_space_free(map->dim);
+ map->dim = isl_local_space_get_space(ls);
+ if (!map->dim)
+ goto error;
+
+ isl_local_space_free(ls);
+ return map;
+error:
+ isl_local_space_free(ls);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Compute an explicit representation for the existentially
+ * quantified variables for which do not know any explicit representation yet.
+ *
+ * We first sort the existentially quantified variables so that the
+ * existentially quantified variables for which we already have an explicit
+ * representation are placed before those for which we do not.
+ * The input dimensions, the output dimensions and the existentially
+ * quantified variables for which we already have an explicit
+ * representation are then turned into parameters.
+ * compute_divs returns a map with the same parameters and
+ * no input or output dimensions and the dimension specification
+ * is reset to that of the input, including the existentially quantified
+ * variables for which we already had an explicit representation.
+ */
+static struct isl_map *compute_divs(struct isl_basic_map *bmap)
+{
+ struct isl_basic_set *bset;
+ struct isl_set *set;
+ struct isl_map *map;
+ isl_space *dim;
+ isl_local_space *ls;
+ unsigned nparam;
+ unsigned n_in;
+ unsigned n_out;
+ unsigned n_known;
+ int i;
+
+ bmap = isl_basic_map_sort_divs(bmap);
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ for (n_known = 0; n_known < bmap->n_div; ++n_known)
+ if (isl_int_is_zero(bmap->div[n_known][0]))
+ break;
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ dim = isl_space_set_alloc(bmap->ctx,
+ nparam + n_in + n_out + n_known, 0);
+ if (!dim)
+ goto error;
+
+ ls = isl_basic_map_get_local_space(bmap);
+ ls = isl_local_space_drop_dims(ls, isl_dim_div,
+ n_known, bmap->n_div - n_known);
+ if (n_known > 0) {
+ for (i = n_known; i < bmap->n_div; ++i)
+ swap_div(bmap, i - n_known, i);
+ bmap->n_div -= n_known;
+ bmap->extra -= n_known;
+ }
+ bmap = isl_basic_map_reset_space(bmap, dim);
+ bset = (struct isl_basic_set *)bmap;
+
+ set = parameter_compute_divs(bset);
+ map = (struct isl_map *)set;
+ map = replace_space_by_local_space(map, ls);
+
+ return map;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+int isl_basic_map_divs_known(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ unsigned off;
+
+ if (!bmap)
+ return -1;
+
+ 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;
+ isl_assert(bmap->ctx, isl_int_is_zero(bmap->div[i][1+1+off+i]),
+ return -1);
+ }
+ return 1;
+}
+
+static int map_divs_known(__isl_keep isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ int known = isl_basic_map_divs_known(map->p[i]);
+ if (known <= 0)
+ return known;
+ }
+
+ return 1;
+}
+
+/* If bmap contains any unknown divs, then compute explicit
+ * expressions for them. However, this computation may be
+ * quite expensive, so first try to remove divs that aren't
+ * strictly needed.
+ */
+struct isl_map *isl_basic_map_compute_divs(struct isl_basic_map *bmap)
+{
+ int known;
+ struct isl_map *map;
+
+ known = isl_basic_map_divs_known(bmap);
+ if (known < 0)
+ goto error;
+ if (known)
+ return isl_map_from_basic_map(bmap);
+
+ bmap = isl_basic_map_drop_redundant_divs(bmap);
+
+ known = isl_basic_map_divs_known(bmap);
+ if (known < 0)
+ goto error;
+ if (known)
+ return isl_map_from_basic_map(bmap);
+
+ map = compute_divs(bmap);
+ return map;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_map *isl_map_compute_divs(struct isl_map *map)
+{
+ int i;
+ int known;
+ struct isl_map *res;
+
+ if (!map)
+ return NULL;
+ if (map->n == 0)
+ return map;
+
+ known = map_divs_known(map);
+ if (known < 0) {
+ isl_map_free(map);
+ return NULL;
+ }
+ if (known)
+ return map;
+
+ res = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[0]));
+ for (i = 1 ; i < map->n; ++i) {
+ struct isl_map *r2;
+ r2 = isl_basic_map_compute_divs(isl_basic_map_copy(map->p[i]));
+ if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
+ res = isl_map_union_disjoint(res, r2);
+ else
+ res = isl_map_union(res, r2);
+ }
+ isl_map_free(map);
+
+ return res;
+}
+
+struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset)
+{
+ return (struct isl_set *)
+ isl_basic_map_compute_divs((struct isl_basic_map *)bset);
+}
+
+struct isl_set *isl_set_compute_divs(struct isl_set *set)
+{
+ return (struct isl_set *)
+ isl_map_compute_divs((struct isl_map *)set);
+}
+
+struct isl_set *isl_map_domain(struct isl_map *map)
+{
+ int i;
+ struct isl_set *set;
+
+ if (!map)
+ goto error;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ set = (struct isl_set *)map;
+ set->dim = isl_space_domain(set->dim);
+ if (!set->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ set->p[i] = isl_basic_map_domain(map->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+ ISL_F_CLR(set, ISL_MAP_DISJOINT);
+ ISL_F_CLR(set, ISL_SET_NORMALIZED);
+ return set;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Return the union of "map1" and "map2", where we assume for now that
+ * "map1" and "map2" are disjoint. Note that the basic maps inside
+ * "map1" or "map2" may not be disjoint from each other.
+ * Also note that this function is also called from isl_map_union,
+ * which takes care of handling the situation where "map1" and "map2"
+ * may not be disjoint.
+ *
+ * If one of the inputs is empty, we can simply return the other input.
+ * Similarly, if one of the inputs is universal, then it is equal to the union.
+ */
+static __isl_give isl_map *map_union_disjoint(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ int i;
+ unsigned flags = 0;
+ struct isl_map *map = NULL;
+ int is_universe;
+
+ if (!map1 || !map2)
+ goto error;
+
+ if (!isl_space_is_equal(map1->dim, map2->dim))
+ isl_die(isl_map_get_ctx(map1), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ if (map1->n == 0) {
+ isl_map_free(map1);
+ return map2;
+ }
+ if (map2->n == 0) {
+ isl_map_free(map2);
+ return map1;
+ }
+
+ is_universe = isl_map_plain_is_universe(map1);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_map_free(map2);
+ return map1;
+ }
+
+ is_universe = isl_map_plain_is_universe(map2);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_map_free(map1);
+ return map2;
+ }
+
+ if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
+ ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
+ ISL_FL_SET(flags, ISL_MAP_DISJOINT);
+
+ map = isl_map_alloc_space(isl_space_copy(map1->dim),
+ map1->n + map2->n, flags);
+ if (!map)
+ goto error;
+ for (i = 0; i < map1->n; ++i) {
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_copy(map1->p[i]));
+ if (!map)
+ goto error;
+ }
+ for (i = 0; i < map2->n; ++i) {
+ map = isl_map_add_basic_map(map,
+ isl_basic_map_copy(map2->p[i]));
+ if (!map)
+ goto error;
+ }
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return map;
+error:
+ isl_map_free(map);
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+/* Return the union of "map1" and "map2", where "map1" and "map2" are
+ * guaranteed to be disjoint by the caller.
+ *
+ * Note that this functions is called from within isl_map_make_disjoint,
+ * so we have to be careful not to touch the constraints of the inputs
+ * in any way.
+ */
+__isl_give isl_map *isl_map_union_disjoint(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_union_disjoint);
+}
+
+/* Return the union of "map1" and "map2", where "map1" and "map2" may
+ * not be disjoint. The parameters are assumed to have been aligned.
+ *
+ * We currently simply call map_union_disjoint, the internal operation
+ * of which does not really depend on the inputs being disjoint.
+ * If the result contains more than one basic map, then we clear
+ * the disjoint flag since the result may contain basic maps from
+ * both inputs and these are not guaranteed to be disjoint.
+ *
+ * As a special case, if "map1" and "map2" are obviously equal,
+ * then we simply return "map1".
+ */
+static __isl_give isl_map *map_union_aligned(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ int equal;
+
+ if (!map1 || !map2)
+ goto error;
+
+ equal = isl_map_plain_is_equal(map1, map2);
+ if (equal < 0)
+ goto error;
+ if (equal) {
+ isl_map_free(map2);
+ return map1;
+ }
+
+ map1 = map_union_disjoint(map1, map2);
+ if (!map1)
+ return NULL;
+ if (map1->n > 1)
+ ISL_F_CLR(map1, ISL_MAP_DISJOINT);
+ return map1;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+/* Return the union of "map1" and "map2", where "map1" and "map2" may
+ * not be disjoint.
+ */
+__isl_give isl_map *isl_map_union(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_union_aligned);
+}
+
+struct isl_set *isl_set_union_disjoint(
+ struct isl_set *set1, struct isl_set *set2)
+{
+ return (struct isl_set *)
+ isl_map_union_disjoint(
+ (struct isl_map *)set1, (struct isl_map *)set2);
+}
+
+struct isl_set *isl_set_union(struct isl_set *set1, struct isl_set *set2)
+{
+ return (struct isl_set *)
+ isl_map_union((struct isl_map *)set1, (struct isl_map *)set2);
+}
+
+/* Apply "fn" to pairs of elements from "map" and "set" and collect
+ * the results.
+ *
+ * "map" and "set" are assumed to be compatible and non-NULL.
+ */
+static __isl_give isl_map *map_intersect_set(__isl_take isl_map *map,
+ __isl_take isl_set *set,
+ __isl_give isl_basic_map *fn(__isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *bset))
+{
+ unsigned flags = 0;
+ struct isl_map *result;
+ int i, j;
+
+ if (isl_set_plain_is_universe(set)) {
+ isl_set_free(set);
+ return map;
+ }
+
+ if (ISL_F_ISSET(map, ISL_MAP_DISJOINT) &&
+ ISL_F_ISSET(set, ISL_MAP_DISJOINT))
+ ISL_FL_SET(flags, ISL_MAP_DISJOINT);
+
+ result = isl_map_alloc_space(isl_space_copy(map->dim),
+ map->n * set->n, flags);
+ for (i = 0; result && i < map->n; ++i)
+ for (j = 0; j < set->n; ++j) {
+ result = isl_map_add_basic_map(result,
+ fn(isl_basic_map_copy(map->p[i]),
+ isl_basic_set_copy(set->p[j])));
+ if (!result)
+ break;
+ }
+
+ isl_map_free(map);
+ isl_set_free(set);
+ return result;
+}
+
+static __isl_give isl_map *map_intersect_range(__isl_take isl_map *map,
+ __isl_take isl_set *set)
+{
+ if (!map || !set)
+ goto error;
+
+ if (!isl_map_compatible_range(map, set))
+ isl_die(set->ctx, isl_error_invalid,
+ "incompatible spaces", goto error);
+
+ return map_intersect_set(map, set, &isl_basic_map_intersect_range);
+error:
+ isl_map_free(map);
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_intersect_range(__isl_take isl_map *map,
+ __isl_take isl_set *set)
+{
+ return isl_map_align_params_map_map_and(map, set, &map_intersect_range);
+}
+
+static __isl_give isl_map *map_intersect_domain(__isl_take isl_map *map,
+ __isl_take isl_set *set)
+{
+ if (!map || !set)
+ goto error;
+
+ if (!isl_map_compatible_domain(map, set))
+ isl_die(set->ctx, isl_error_invalid,
+ "incompatible spaces", goto error);
+
+ return map_intersect_set(map, set, &isl_basic_map_intersect_domain);
+error:
+ isl_map_free(map);
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_intersect_domain(__isl_take isl_map *map,
+ __isl_take isl_set *set)
+{
+ return isl_map_align_params_map_map_and(map, set,
+ &map_intersect_domain);
+}
+
+static __isl_give isl_map *map_apply_domain(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ if (!map1 || !map2)
+ goto error;
+ map1 = isl_map_reverse(map1);
+ map1 = isl_map_apply_range(map1, map2);
+ return isl_map_reverse(map1);
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_apply_domain(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_apply_domain);
+}
+
+static __isl_give isl_map *map_apply_range(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_space *dim_result;
+ struct isl_map *result;
+ int i, j;
+
+ if (!map1 || !map2)
+ goto error;
+
+ dim_result = isl_space_join(isl_space_copy(map1->dim),
+ isl_space_copy(map2->dim));
+
+ result = isl_map_alloc_space(dim_result, map1->n * map2->n, 0);
+ if (!result)
+ goto error;
+ for (i = 0; i < map1->n; ++i)
+ for (j = 0; j < map2->n; ++j) {
+ result = isl_map_add_basic_map(result,
+ isl_basic_map_apply_range(
+ isl_basic_map_copy(map1->p[i]),
+ isl_basic_map_copy(map2->p[j])));
+ if (!result)
+ goto error;
+ }
+ isl_map_free(map1);
+ isl_map_free(map2);
+ if (result && result->n <= 1)
+ ISL_F_SET(result, ISL_MAP_DISJOINT);
+ return result;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_apply_range(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_apply_range);
+}
+
+/*
+ * returns range - domain
+ */
+struct isl_basic_set *isl_basic_map_deltas(struct isl_basic_map *bmap)
+{
+ isl_space *dims, *target_dim;
+ struct isl_basic_set *bset;
+ unsigned dim;
+ unsigned nparam;
+ int i;
+
+ if (!bmap)
+ goto error;
+ isl_assert(bmap->ctx, isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
+ bmap->dim, isl_dim_out),
+ goto error);
+ target_dim = isl_space_domain(isl_basic_map_get_space(bmap));
+ dim = isl_basic_map_n_in(bmap);
+ nparam = isl_basic_map_n_param(bmap);
+ bset = isl_basic_set_from_basic_map(bmap);
+ bset = isl_basic_set_cow(bset);
+ dims = isl_basic_set_get_space(bset);
+ dims = isl_space_add_dims(dims, isl_dim_set, dim);
+ bset = isl_basic_set_extend_space(bset, dims, 0, dim, 0);
+ bset = isl_basic_set_swap_vars(bset, 2*dim);
+ for (i = 0; i < dim; ++i) {
+ int j = isl_basic_map_alloc_equality(
+ (struct isl_basic_map *)bset);
+ if (j < 0) {
+ bset = isl_basic_set_free(bset);
+ break;
+ }
+ isl_seq_clr(bset->eq[j], 1 + isl_basic_set_total_dim(bset));
+ isl_int_set_si(bset->eq[j][1+nparam+i], 1);
+ isl_int_set_si(bset->eq[j][1+nparam+dim+i], 1);
+ isl_int_set_si(bset->eq[j][1+nparam+2*dim+i], -1);
+ }
+ bset = isl_basic_set_project_out(bset, isl_dim_set, dim, 2*dim);
+ bset = isl_basic_set_reset_space(bset, target_dim);
+ return bset;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/*
+ * returns range - domain
+ */
+__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map)
+{
+ int i;
+ isl_space *dim;
+ struct isl_set *result;
+
+ if (!map)
+ return NULL;
+
+ isl_assert(map->ctx, isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ map->dim, isl_dim_out),
+ goto error);
+ dim = isl_map_get_space(map);
+ dim = isl_space_domain(dim);
+ result = isl_set_alloc_space(dim, map->n, 0);
+ if (!result)
+ goto error;
+ for (i = 0; i < map->n; ++i)
+ result = isl_set_add_basic_set(result,
+ isl_basic_map_deltas(isl_basic_map_copy(map->p[i])));
+ isl_map_free(map);
+ return result;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/*
+ * returns [domain -> range] -> range - domain
+ */
+__isl_give isl_basic_map *isl_basic_map_deltas_map(
+ __isl_take isl_basic_map *bmap)
+{
+ int i, k;
+ isl_space *dim;
+ isl_basic_map *domain;
+ int nparam, n;
+ unsigned total;
+
+ if (!isl_space_tuple_is_equal(bmap->dim, isl_dim_in,
+ bmap->dim, isl_dim_out))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "domain and range don't match", goto error);
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ n = isl_basic_map_dim(bmap, isl_dim_in);
+
+ dim = isl_space_from_range(isl_space_domain(isl_basic_map_get_space(bmap)));
+ domain = isl_basic_map_universe(dim);
+
+ bmap = isl_basic_map_from_domain(isl_basic_map_wrap(bmap));
+ bmap = isl_basic_map_apply_range(bmap, domain);
+ bmap = isl_basic_map_extend_constraints(bmap, n, 0);
+
+ total = isl_basic_map_total_dim(bmap);
+
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], 1 + total);
+ isl_int_set_si(bmap->eq[k][1 + nparam + i], 1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + n + i], -1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + n + n + i], 1);
+ }
+
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/*
+ * returns [domain -> range] -> range - domain
+ */
+__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map)
+{
+ int i;
+ isl_space *domain_dim;
+
+ if (!map)
+ return NULL;
+
+ if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ map->dim, isl_dim_out))
+ isl_die(map->ctx, isl_error_invalid,
+ "domain and range don't match", goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ domain_dim = isl_space_from_range(isl_space_domain(isl_map_get_space(map)));
+ map->dim = isl_space_from_domain(isl_space_wrap(map->dim));
+ map->dim = isl_space_join(map->dim, domain_dim);
+ if (!map->dim)
+ goto error;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_deltas_map(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+static __isl_give isl_basic_map *basic_map_identity(__isl_take isl_space *dims)
+{
+ struct isl_basic_map *bmap;
+ unsigned nparam;
+ unsigned dim;
+ int i;
+
+ if (!dims)
+ return NULL;
+
+ nparam = dims->nparam;
+ dim = dims->n_out;
+ bmap = isl_basic_map_alloc_space(dims, 0, dim, 0);
+ if (!bmap)
+ goto error;
+
+ for (i = 0; i < dim; ++i) {
+ int j = isl_basic_map_alloc_equality(bmap);
+ if (j < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[j], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[j][1+nparam+i], 1);
+ isl_int_set_si(bmap->eq[j][1+nparam+dim+i], -1);
+ }
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (dim->n_in != dim->n_out)
+ isl_die(dim->ctx, isl_error_invalid,
+ "number of input and output dimensions needs to be "
+ "the same", goto error);
+ return basic_map_identity(dim);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model)
+{
+ if (!model || !model->dim)
+ return NULL;
+ return isl_basic_map_identity(isl_space_copy(model->dim));
+}
+
+__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim)
+{
+ return isl_map_from_basic_map(isl_basic_map_identity(dim));
+}
+
+struct isl_map *isl_map_identity_like(struct isl_map *model)
+{
+ if (!model || !model->dim)
+ return NULL;
+ return isl_map_identity(isl_space_copy(model->dim));
+}
+
+struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model)
+{
+ if (!model || !model->dim)
+ return NULL;
+ return isl_map_identity(isl_space_copy(model->dim));
+}
+
+__isl_give isl_map *isl_set_identity(__isl_take isl_set *set)
+{
+ isl_space *dim = isl_set_get_space(set);
+ isl_map *id;
+ id = isl_map_identity(isl_space_map_from_set(dim));
+ return isl_map_intersect_range(id, set);
+}
+
+/* Construct a basic set with all set dimensions having only non-negative
+ * values.
+ */
+__isl_give isl_basic_set *isl_basic_set_positive_orthant(
+ __isl_take isl_space *space)
+{
+ int i;
+ unsigned nparam;
+ unsigned dim;
+ struct isl_basic_set *bset;
+
+ if (!space)
+ return NULL;
+ nparam = space->nparam;
+ dim = space->n_out;
+ bset = isl_basic_set_alloc_space(space, 0, 0, dim);
+ if (!bset)
+ return NULL;
+ for (i = 0; i < dim; ++i) {
+ int k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
+ isl_int_set_si(bset->ineq[k][1 + nparam + i], 1);
+ }
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Construct the half-space x_pos >= 0.
+ */
+static __isl_give isl_basic_set *nonneg_halfspace(__isl_take isl_space *dim,
+ int pos)
+{
+ int k;
+ isl_basic_set *nonneg;
+
+ nonneg = isl_basic_set_alloc_space(dim, 0, 0, 1);
+ k = isl_basic_set_alloc_inequality(nonneg);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(nonneg->ineq[k], 1 + isl_basic_set_total_dim(nonneg));
+ isl_int_set_si(nonneg->ineq[k][pos], 1);
+
+ return isl_basic_set_finalize(nonneg);
+error:
+ isl_basic_set_free(nonneg);
+ return NULL;
+}
+
+/* Construct the half-space x_pos <= -1.
+ */
+static __isl_give isl_basic_set *neg_halfspace(__isl_take isl_space *dim, int pos)
+{
+ int k;
+ isl_basic_set *neg;
+
+ neg = isl_basic_set_alloc_space(dim, 0, 0, 1);
+ k = isl_basic_set_alloc_inequality(neg);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(neg->ineq[k], 1 + isl_basic_set_total_dim(neg));
+ isl_int_set_si(neg->ineq[k][0], -1);
+ isl_int_set_si(neg->ineq[k][pos], -1);
+
+ return isl_basic_set_finalize(neg);
+error:
+ isl_basic_set_free(neg);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ isl_basic_set *nonneg;
+ isl_basic_set *neg;
+
+ if (!set)
+ return NULL;
+ if (n == 0)
+ return set;
+
+ isl_assert(set->ctx, first + n <= isl_set_dim(set, type), goto error);
+
+ for (i = 0; i < n; ++i) {
+ nonneg = nonneg_halfspace(isl_set_get_space(set),
+ pos(set->dim, type) + first + i);
+ neg = neg_halfspace(isl_set_get_space(set),
+ pos(set->dim, type) + first + i);
+
+ set = isl_set_intersect(set, isl_basic_set_union(nonneg, neg));
+ }
+
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+static int foreach_orthant(__isl_take isl_set *set, int *signs, int first,
+ int len, int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
+ void *user)
+{
+ isl_set *half;
+
+ if (!set)
+ return -1;
+ if (isl_set_plain_is_empty(set)) {
+ isl_set_free(set);
+ return 0;
+ }
+ if (first == len)
+ return fn(set, signs, user);
+
+ signs[first] = 1;
+ half = isl_set_from_basic_set(nonneg_halfspace(isl_set_get_space(set),
+ 1 + first));
+ half = isl_set_intersect(half, isl_set_copy(set));
+ if (foreach_orthant(half, signs, first + 1, len, fn, user) < 0)
+ goto error;
+
+ signs[first] = -1;
+ half = isl_set_from_basic_set(neg_halfspace(isl_set_get_space(set),
+ 1 + first));
+ half = isl_set_intersect(half, set);
+ return foreach_orthant(half, signs, first + 1, len, fn, user);
+error:
+ isl_set_free(set);
+ return -1;
+}
+
+/* Call "fn" on the intersections of "set" with each of the orthants
+ * (except for obviously empty intersections). The orthant is identified
+ * by the signs array, with each entry having value 1 or -1 according
+ * to the sign of the corresponding variable.
+ */
+int isl_set_foreach_orthant(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
+ void *user)
+{
+ unsigned nparam;
+ unsigned nvar;
+ int *signs;
+ int r;
+
+ if (!set)
+ return -1;
+ if (isl_set_plain_is_empty(set))
+ return 0;
+
+ nparam = isl_set_dim(set, isl_dim_param);
+ nvar = isl_set_dim(set, isl_dim_set);
+
+ signs = isl_alloc_array(set->ctx, int, nparam + nvar);
+
+ r = foreach_orthant(isl_set_copy(set), signs, 0, nparam + nvar,
+ fn, user);
+
+ free(signs);
+
+ return r;
+}
+
+int isl_set_is_equal(struct isl_set *set1, struct isl_set *set2)
+{
+ return isl_map_is_equal((struct isl_map *)set1, (struct isl_map *)set2);
+}
+
+int isl_basic_map_is_subset(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ int is_subset;
+ struct isl_map *map1;
+ struct isl_map *map2;
+
+ if (!bmap1 || !bmap2)
+ return -1;
+
+ map1 = isl_map_from_basic_map(isl_basic_map_copy(bmap1));
+ map2 = isl_map_from_basic_map(isl_basic_map_copy(bmap2));
+
+ is_subset = isl_map_is_subset(map1, map2);
+
+ isl_map_free(map1);
+ isl_map_free(map2);
+
+ return is_subset;
+}
+
+int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2)
+{
+ return isl_basic_map_is_subset(bset1, bset2);
+}
+
+int isl_basic_map_is_equal(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ int is_subset;
+
+ if (!bmap1 || !bmap2)
+ return -1;
+ is_subset = isl_basic_map_is_subset(bmap1, bmap2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_basic_map_is_subset(bmap2, bmap1);
+ return is_subset;
+}
+
+int isl_basic_set_is_equal(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ return isl_basic_map_is_equal(
+ (struct isl_basic_map *)bset1, (struct isl_basic_map *)bset2);
+}
+
+int isl_map_is_empty(struct isl_map *map)
+{
+ int i;
+ int is_empty;
+
+ if (!map)
+ return -1;
+ for (i = 0; i < map->n; ++i) {
+ is_empty = isl_basic_map_is_empty(map->p[i]);
+ if (is_empty < 0)
+ return -1;
+ if (!is_empty)
+ return 0;
+ }
+ return 1;
+}
+
+int isl_map_plain_is_empty(__isl_keep isl_map *map)
+{
+ return map ? map->n == 0 : -1;
+}
+
+int isl_map_fast_is_empty(__isl_keep isl_map *map)
+{
+ return isl_map_plain_is_empty(map);
+}
+
+int isl_set_plain_is_empty(struct isl_set *set)
+{
+ return set ? set->n == 0 : -1;
+}
+
+int isl_set_fast_is_empty(__isl_keep isl_set *set)
+{
+ return isl_set_plain_is_empty(set);
+}
+
+int isl_set_is_empty(struct isl_set *set)
+{
+ return isl_map_is_empty((struct isl_map *)set);
+}
+
+int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ if (!map1 || !map2)
+ return -1;
+
+ return isl_space_is_equal(map1->dim, map2->dim);
+}
+
+int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ if (!set1 || !set2)
+ return -1;
+
+ return isl_space_is_equal(set1->dim, set2->dim);
+}
+
+static int map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ int is_subset;
+
+ if (!map1 || !map2)
+ return -1;
+ is_subset = isl_map_is_subset(map1, map2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_map_is_subset(map2, map1);
+ return is_subset;
+}
+
+int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ return isl_map_align_params_map_map_and_test(map1, map2, &map_is_equal);
+}
+
+int isl_basic_map_is_strict_subset(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ int is_subset;
+
+ if (!bmap1 || !bmap2)
+ return -1;
+ is_subset = isl_basic_map_is_subset(bmap1, bmap2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_basic_map_is_subset(bmap2, bmap1);
+ if (is_subset == -1)
+ return is_subset;
+ return !is_subset;
+}
+
+int isl_map_is_strict_subset(struct isl_map *map1, struct isl_map *map2)
+{
+ int is_subset;
+
+ if (!map1 || !map2)
+ return -1;
+ is_subset = isl_map_is_subset(map1, map2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_map_is_subset(map2, map1);
+ if (is_subset == -1)
+ return is_subset;
+ return !is_subset;
+}
+
+int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ return isl_map_is_strict_subset((isl_map *)set1, (isl_map *)set2);
+}
+
+int isl_basic_map_is_universe(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ return bmap->n_eq == 0 && bmap->n_ineq == 0;
+}
+
+int isl_basic_set_is_universe(struct isl_basic_set *bset)
+{
+ if (!bset)
+ return -1;
+ return bset->n_eq == 0 && bset->n_ineq == 0;
+}
+
+int isl_map_plain_is_universe(__isl_keep isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ int r = isl_basic_map_is_universe(map->p[i]);
+ if (r < 0 || r)
+ return r;
+ }
+
+ return 0;
+}
+
+int isl_set_plain_is_universe(__isl_keep isl_set *set)
+{
+ return isl_map_plain_is_universe((isl_map *) set);
+}
+
+int isl_set_fast_is_universe(__isl_keep isl_set *set)
+{
+ return isl_set_plain_is_universe(set);
+}
+
+int isl_basic_map_is_empty(struct isl_basic_map *bmap)
+{
+ struct isl_basic_set *bset = NULL;
+ struct isl_vec *sample = NULL;
+ int empty;
+ unsigned total;
+
+ if (!bmap)
+ return -1;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ return 1;
+
+ if (isl_basic_map_is_universe(bmap))
+ return 0;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
+ struct isl_basic_map *copy = isl_basic_map_copy(bmap);
+ copy = isl_basic_map_remove_redundancies(copy);
+ empty = isl_basic_map_plain_is_empty(copy);
+ isl_basic_map_free(copy);
+ return empty;
+ }
+
+ total = 1 + isl_basic_map_total_dim(bmap);
+ if (bmap->sample && bmap->sample->size == total) {
+ int contains = isl_basic_map_contains(bmap, bmap->sample);
+ if (contains < 0)
+ return -1;
+ if (contains)
+ return 0;
+ }
+ isl_vec_free(bmap->sample);
+ bmap->sample = NULL;
+ bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
+ if (!bset)
+ return -1;
+ sample = isl_basic_set_sample_vec(bset);
+ if (!sample)
+ return -1;
+ empty = sample->size == 0;
+ isl_vec_free(bmap->sample);
+ bmap->sample = sample;
+ if (empty)
+ ISL_F_SET(bmap, ISL_BASIC_MAP_EMPTY);
+
+ return empty;
+}
+
+int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ return ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY);
+}
+
+int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap)
+{
+ return isl_basic_map_plain_is_empty(bmap);
+}
+
+int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset)
+{
+ if (!bset)
+ return -1;
+ return ISL_F_ISSET(bset, ISL_BASIC_SET_EMPTY);
+}
+
+int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_set_plain_is_empty(bset);
+}
+
+int isl_basic_set_is_empty(struct isl_basic_set *bset)
+{
+ return isl_basic_map_is_empty((struct isl_basic_map *)bset);
+}
+
+struct isl_map *isl_basic_map_union(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ struct isl_map *map;
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim), goto error);
+
+ map = isl_map_alloc_space(isl_space_copy(bmap1->dim), 2, 0);
+ if (!map)
+ goto error;
+ map = isl_map_add_basic_map(map, bmap1);
+ map = isl_map_add_basic_map(map, bmap2);
+ return map;
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+struct isl_set *isl_basic_set_union(
+ struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+ return (struct isl_set *)isl_basic_map_union(
+ (struct isl_basic_map *)bset1,
+ (struct isl_basic_map *)bset2);
+}
+
+/* Order divs such that any div only depends on previous divs */
+struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap)
+{
+ int i;
+ unsigned off;
+
+ if (!bmap)
+ return NULL;
+
+ off = isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ int pos;
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ pos = isl_seq_first_non_zero(bmap->div[i]+1+1+off+i,
+ bmap->n_div-i);
+ if (pos == -1)
+ continue;
+ isl_basic_map_swap_div(bmap, i, i + pos);
+ --i;
+ }
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_order_divs((struct isl_basic_map *)bset);
+}
+
+__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return 0;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_order_divs(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Apply the expansion computed by isl_merge_divs.
+ * The expansion itself is given by "exp" while the resulting
+ * list of divs is given by "div".
+ */
+__isl_give isl_basic_set *isl_basic_set_expand_divs(
+ __isl_take isl_basic_set *bset, __isl_take isl_mat *div, int *exp)
+{
+ int i, j;
+ int n_div;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset || !div)
+ goto error;
+
+ if (div->n_row < bset->n_div)
+ isl_die(isl_mat_get_ctx(div), isl_error_invalid,
+ "not an expansion", goto error);
+
+ n_div = bset->n_div;
+ bset = isl_basic_map_extend_space(bset, isl_space_copy(bset->dim),
+ div->n_row - n_div, 0,
+ 2 * (div->n_row - n_div));
+
+ for (i = n_div; i < div->n_row; ++i)
+ if (isl_basic_set_alloc_div(bset) < 0)
+ goto error;
+
+ j = n_div - 1;
+ for (i = div->n_row - 1; i >= 0; --i) {
+ if (j >= 0 && exp[j] == i) {
+ if (i != j)
+ isl_basic_map_swap_div(bset, i, j);
+ j--;
+ } else {
+ isl_seq_cpy(bset->div[i], div->row[i], div->n_col);
+ if (isl_basic_map_add_div_constraints(bset, i) < 0)
+ goto error;
+ }
+ }
+
+ isl_mat_free(div);
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_mat_free(div);
+ return NULL;
+}
+
+/* Look for a div in dst that corresponds to the div "div" in src.
+ * The divs before "div" in src and dst are assumed to be the same.
+ *
+ * Returns -1 if no corresponding div was found and the position
+ * of the corresponding div in dst otherwise.
+ */
+static int find_div(struct isl_basic_map *dst,
+ struct isl_basic_map *src, unsigned div)
+{
+ int i;
+
+ unsigned total = isl_space_dim(src->dim, isl_dim_all);
+
+ isl_assert(dst->ctx, div <= dst->n_div, return -1);
+ for (i = div; i < dst->n_div; ++i)
+ if (isl_seq_eq(dst->div[i], src->div[div], 1+1+total+div) &&
+ isl_seq_first_non_zero(dst->div[i]+1+1+total+div,
+ dst->n_div - div) == -1)
+ return i;
+ return -1;
+}
+
+/* Align the divs of "dst" to those of "src", adding divs from "src"
+ * if needed. That is, make sure that the first src->n_div divs
+ * of the result are equal to those of src.
+ *
+ * The result is not finalized as by design it will have redundant
+ * divs if any divs from "src" were copied.
+ */
+__isl_give isl_basic_map *isl_basic_map_align_divs(
+ __isl_take isl_basic_map *dst, __isl_keep isl_basic_map *src)
+{
+ int i;
+ int known, extended;
+ unsigned total;
+
+ if (!dst || !src)
+ return isl_basic_map_free(dst);
+
+ if (src->n_div == 0)
+ return dst;
+
+ known = isl_basic_map_divs_known(src);
+ if (known < 0)
+ return isl_basic_map_free(dst);
+ if (!known)
+ isl_die(isl_basic_map_get_ctx(src), isl_error_invalid,
+ "some src divs are unknown",
+ return isl_basic_map_free(dst));
+
+ src = isl_basic_map_order_divs(src);
+
+ extended = 0;
+ total = isl_space_dim(src->dim, isl_dim_all);
+ for (i = 0; i < src->n_div; ++i) {
+ int j = find_div(dst, src, i);
+ if (j < 0) {
+ if (!extended) {
+ int extra = src->n_div - i;
+ dst = isl_basic_map_cow(dst);
+ if (!dst)
+ return NULL;
+ dst = isl_basic_map_extend_space(dst,
+ isl_space_copy(dst->dim),
+ extra, 0, 2 * extra);
+ extended = 1;
+ }
+ j = isl_basic_map_alloc_div(dst);
+ if (j < 0)
+ return isl_basic_map_free(dst);
+ isl_seq_cpy(dst->div[j], src->div[i], 1+1+total+i);
+ isl_seq_clr(dst->div[j]+1+1+total+i, dst->n_div - i);
+ if (isl_basic_map_add_div_constraints(dst, j) < 0)
+ return isl_basic_map_free(dst);
+ }
+ if (j != i)
+ isl_basic_map_swap_div(dst, i, j);
+ }
+ return dst;
+}
+
+struct isl_basic_set *isl_basic_set_align_divs(
+ struct isl_basic_set *dst, struct isl_basic_set *src)
+{
+ return (struct isl_basic_set *)isl_basic_map_align_divs(
+ (struct isl_basic_map *)dst, (struct isl_basic_map *)src);
+}
+
+struct isl_map *isl_map_align_divs(struct isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ if (map->n == 0)
+ return map;
+ map = isl_map_compute_divs(map);
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ for (i = 1; i < map->n; ++i)
+ map->p[0] = isl_basic_map_align_divs(map->p[0], map->p[i]);
+ for (i = 1; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_align_divs(map->p[i], map->p[0]);
+ if (!map->p[i])
+ return isl_map_free(map);
+ }
+
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+}
+
+struct isl_set *isl_set_align_divs(struct isl_set *set)
+{
+ return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
+}
+
+/* Align the divs of the basic sets in "set" to those
+ * of the basic sets in "list", as well as to the other basic sets in "set".
+ * The elements in "list" are assumed to have known divs.
+ */
+__isl_give isl_set *isl_set_align_divs_to_basic_set_list(
+ __isl_take isl_set *set, __isl_keep isl_basic_set_list *list)
+{
+ int i, n;
+
+ set = isl_set_compute_divs(set);
+ set = isl_set_cow(set);
+ if (!set || !list)
+ return isl_set_free(set);
+ if (set->n == 0)
+ return set;
+
+ n = isl_basic_set_list_n_basic_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset;
+
+ bset = isl_basic_set_list_get_basic_set(list, i);
+ set->p[0] = isl_basic_set_align_divs(set->p[0], bset);
+ isl_basic_set_free(bset);
+ }
+ if (!set->p[0])
+ return isl_set_free(set);
+
+ return isl_set_align_divs(set);
+}
+
+/* Align the divs of each element of "list" to those of "bset".
+ * Both "bset" and the elements of "list" are assumed to have known divs.
+ */
+__isl_give isl_basic_set_list *isl_basic_set_list_align_divs_to_basic_set(
+ __isl_take isl_basic_set_list *list, __isl_keep isl_basic_set *bset)
+{
+ int i, n;
+
+ if (!list || !bset)
+ return isl_basic_set_list_free(list);
+
+ n = isl_basic_set_list_n_basic_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_basic_set *bset_i;
+
+ bset_i = isl_basic_set_list_get_basic_set(list, i);
+ bset_i = isl_basic_set_align_divs(bset_i, bset);
+ list = isl_basic_set_list_set_basic_set(list, i, bset_i);
+ }
+
+ return list;
+}
+
+static __isl_give isl_set *set_apply( __isl_take isl_set *set,
+ __isl_take isl_map *map)
+{
+ if (!set || !map)
+ goto error;
+ isl_assert(set->ctx, isl_map_compatible_domain(map, set), goto error);
+ map = isl_map_intersect_domain(map, set);
+ set = isl_map_range(map);
+ return set;
+error:
+ isl_set_free(set);
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_apply( __isl_take isl_set *set,
+ __isl_take isl_map *map)
+{
+ return isl_map_align_params_map_map_and(set, map, &set_apply);
+}
+
+/* There is no need to cow as removing empty parts doesn't change
+ * the meaning of the set.
+ */
+struct isl_map *isl_map_remove_empty_parts(struct isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ for (i = map->n - 1; i >= 0; --i)
+ remove_if_empty(map, i);
+
+ return map;
+}
+
+struct isl_set *isl_set_remove_empty_parts(struct isl_set *set)
+{
+ return (struct isl_set *)
+ isl_map_remove_empty_parts((struct isl_map *)set);
+}
+
+struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map)
+{
+ struct isl_basic_map *bmap;
+ if (!map || map->n == 0)
+ return NULL;
+ bmap = map->p[map->n-1];
+ isl_assert(map->ctx, ISL_F_ISSET(bmap, ISL_BASIC_SET_FINAL), return NULL);
+ return isl_basic_map_copy(bmap);
+}
+
+struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set)
+{
+ return (struct isl_basic_set *)
+ isl_map_copy_basic_map((struct isl_map *)set);
+}
+
+__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
+ __isl_keep isl_basic_map *bmap)
+{
+ int i;
+
+ if (!map || !bmap)
+ goto error;
+ for (i = map->n-1; i >= 0; --i) {
+ if (map->p[i] != bmap)
+ continue;
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+ isl_basic_map_free(map->p[i]);
+ if (i != map->n-1) {
+ ISL_F_CLR(map, ISL_SET_NORMALIZED);
+ map->p[i] = map->p[map->n-1];
+ }
+ map->n--;
+ return map;
+ }
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
+ struct isl_basic_set *bset)
+{
+ return (struct isl_set *)isl_map_drop_basic_map((struct isl_map *)set,
+ (struct isl_basic_map *)bset);
+}
+
+/* Given two basic sets bset1 and bset2, compute the maximal difference
+ * between the values of dimension pos in bset1 and those in bset2
+ * for any common value of the parameters and dimensions preceding pos.
+ */
+static enum isl_lp_result basic_set_maximal_difference_at(
+ __isl_keep isl_basic_set *bset1, __isl_keep isl_basic_set *bset2,
+ int pos, isl_int *opt)
+{
+ isl_space *dims;
+ struct isl_basic_map *bmap1 = NULL;
+ struct isl_basic_map *bmap2 = NULL;
+ struct isl_ctx *ctx;
+ struct isl_vec *obj;
+ unsigned total;
+ unsigned nparam;
+ unsigned dim1, dim2;
+ enum isl_lp_result res;
+
+ if (!bset1 || !bset2)
+ return isl_lp_error;
+
+ nparam = isl_basic_set_n_param(bset1);
+ dim1 = isl_basic_set_n_dim(bset1);
+ dim2 = isl_basic_set_n_dim(bset2);
+ dims = isl_space_alloc(bset1->ctx, nparam, pos, dim1 - pos);
+ bmap1 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset1), dims);
+ dims = isl_space_alloc(bset2->ctx, nparam, pos, dim2 - pos);
+ bmap2 = isl_basic_map_from_basic_set(isl_basic_set_copy(bset2), dims);
+ if (!bmap1 || !bmap2)
+ goto error;
+ bmap1 = isl_basic_map_cow(bmap1);
+ bmap1 = isl_basic_map_extend(bmap1, nparam,
+ pos, (dim1 - pos) + (dim2 - pos),
+ bmap2->n_div, bmap2->n_eq, bmap2->n_ineq);
+ bmap1 = add_constraints(bmap1, bmap2, 0, dim1 - pos);
+ if (!bmap1)
+ goto error2;
+ total = isl_basic_map_total_dim(bmap1);
+ ctx = bmap1->ctx;
+ obj = isl_vec_alloc(ctx, 1 + total);
+ if (!obj)
+ goto error2;
+ isl_seq_clr(obj->block.data, 1 + total);
+ isl_int_set_si(obj->block.data[1+nparam+pos], 1);
+ isl_int_set_si(obj->block.data[1+nparam+pos+(dim1-pos)], -1);
+ res = isl_basic_map_solve_lp(bmap1, 1, obj->block.data, ctx->one,
+ opt, NULL, NULL);
+ isl_basic_map_free(bmap1);
+ isl_vec_free(obj);
+ return res;
+error:
+ isl_basic_map_free(bmap2);
+error2:
+ isl_basic_map_free(bmap1);
+ return isl_lp_error;
+}
+
+/* Given two _disjoint_ basic sets bset1 and bset2, check whether
+ * for any common value of the parameters and dimensions preceding pos
+ * in both basic sets, the values of dimension pos in bset1 are
+ * smaller or larger than those in bset2.
+ *
+ * Returns
+ * 1 if bset1 follows bset2
+ * -1 if bset1 precedes bset2
+ * 0 if bset1 and bset2 are incomparable
+ * -2 if some error occurred.
+ */
+int isl_basic_set_compare_at(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2, int pos)
+{
+ isl_int opt;
+ enum isl_lp_result res;
+ int cmp;
+
+ isl_int_init(opt);
+
+ res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
+
+ if (res == isl_lp_empty)
+ cmp = 0;
+ else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
+ res == isl_lp_unbounded)
+ cmp = 1;
+ else if (res == isl_lp_ok && isl_int_is_neg(opt))
+ cmp = -1;
+ else
+ cmp = -2;
+
+ isl_int_clear(opt);
+ return cmp;
+}
+
+/* Given two basic sets bset1 and bset2, check whether
+ * for any common value of the parameters and dimensions preceding pos
+ * there is a value of dimension pos in bset1 that is larger
+ * than a value of the same dimension in bset2.
+ *
+ * Return
+ * 1 if there exists such a pair
+ * 0 if there is no such pair, but there is a pair of equal values
+ * -1 otherwise
+ * -2 if some error occurred.
+ */
+int isl_basic_set_follows_at(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2, int pos)
+{
+ isl_int opt;
+ enum isl_lp_result res;
+ int cmp;
+
+ isl_int_init(opt);
+
+ res = basic_set_maximal_difference_at(bset1, bset2, pos, &opt);
+
+ if (res == isl_lp_empty)
+ cmp = -1;
+ else if ((res == isl_lp_ok && isl_int_is_pos(opt)) ||
+ res == isl_lp_unbounded)
+ cmp = 1;
+ else if (res == isl_lp_ok && isl_int_is_neg(opt))
+ cmp = -1;
+ else if (res == isl_lp_ok)
+ cmp = 0;
+ else
+ cmp = -2;
+
+ isl_int_clear(opt);
+ return cmp;
+}
+
+/* Given two sets set1 and set2, check whether
+ * for any common value of the parameters and dimensions preceding pos
+ * there is a value of dimension pos in set1 that is larger
+ * than a value of the same dimension in set2.
+ *
+ * Return
+ * 1 if there exists such a pair
+ * 0 if there is no such pair, but there is a pair of equal values
+ * -1 otherwise
+ * -2 if some error occurred.
+ */
+int isl_set_follows_at(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2, int pos)
+{
+ int i, j;
+ int follows = -1;
+
+ if (!set1 || !set2)
+ return -2;
+
+ for (i = 0; i < set1->n; ++i)
+ for (j = 0; j < set2->n; ++j) {
+ int f;
+ f = isl_basic_set_follows_at(set1->p[i], set2->p[j], pos);
+ if (f == 1 || f == -2)
+ return f;
+ if (f > follows)
+ follows = f;
+ }
+
+ return follows;
+}
+
+static int isl_basic_map_plain_has_fixed_var(__isl_keep isl_basic_map *bmap,
+ unsigned pos, isl_int *val)
+{
+ int i;
+ int d;
+ unsigned total;
+
+ if (!bmap)
+ return -1;
+ total = isl_basic_map_total_dim(bmap);
+ for (i = 0, d = total-1; i < bmap->n_eq && d+1 > pos; ++i) {
+ for (; d+1 > pos; --d)
+ if (!isl_int_is_zero(bmap->eq[i][1+d]))
+ break;
+ if (d != pos)
+ continue;
+ if (isl_seq_first_non_zero(bmap->eq[i]+1, d) != -1)
+ return 0;
+ if (isl_seq_first_non_zero(bmap->eq[i]+1+d+1, total-d-1) != -1)
+ return 0;
+ if (!isl_int_is_one(bmap->eq[i][1+d]))
+ return 0;
+ if (val)
+ isl_int_neg(*val, bmap->eq[i][0]);
+ return 1;
+ }
+ return 0;
+}
+
+static int isl_map_plain_has_fixed_var(__isl_keep isl_map *map,
+ unsigned pos, isl_int *val)
+{
+ int i;
+ isl_int v;
+ isl_int tmp;
+ int fixed;
+
+ if (!map)
+ return -1;
+ if (map->n == 0)
+ return 0;
+ if (map->n == 1)
+ return isl_basic_map_plain_has_fixed_var(map->p[0], pos, val);
+ isl_int_init(v);
+ isl_int_init(tmp);
+ fixed = isl_basic_map_plain_has_fixed_var(map->p[0], pos, &v);
+ for (i = 1; fixed == 1 && i < map->n; ++i) {
+ fixed = isl_basic_map_plain_has_fixed_var(map->p[i], pos, &tmp);
+ if (fixed == 1 && isl_int_ne(tmp, v))
+ fixed = 0;
+ }
+ if (val)
+ isl_int_set(*val, v);
+ isl_int_clear(tmp);
+ isl_int_clear(v);
+ return fixed;
+}
+
+static int isl_basic_set_plain_has_fixed_var(__isl_keep isl_basic_set *bset,
+ unsigned pos, isl_int *val)
+{
+ return isl_basic_map_plain_has_fixed_var((struct isl_basic_map *)bset,
+ pos, val);
+}
+
+static int isl_set_plain_has_fixed_var(__isl_keep isl_set *set, unsigned pos,
+ isl_int *val)
+{
+ return isl_map_plain_has_fixed_var((struct isl_map *)set, pos, val);
+}
+
+int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, isl_int *val)
+{
+ if (pos >= isl_basic_map_dim(bmap, type))
+ return -1;
+ return isl_basic_map_plain_has_fixed_var(bmap,
+ isl_basic_map_offset(bmap, type) - 1 + pos, val);
+}
+
+/* If "bmap" obviously lies on a hyperplane where the given dimension
+ * has a fixed value, then return that value.
+ * Otherwise return NaN.
+ */
+__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
+ __isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+ int fixed;
+
+ if (!bmap)
+ return NULL;
+ ctx = isl_basic_map_get_ctx(bmap);
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+ fixed = isl_basic_map_plain_is_fixed(bmap, type, pos, &v->n);
+ if (fixed < 0)
+ return isl_val_free(v);
+ if (fixed) {
+ isl_int_set_si(v->d, 1);
+ return v;
+ }
+ isl_val_free(v);
+ return isl_val_nan(ctx);
+}
+
+int isl_map_plain_is_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int *val)
+{
+ if (pos >= isl_map_dim(map, type))
+ return -1;
+ return isl_map_plain_has_fixed_var(map,
+ map_offset(map, type) - 1 + pos, val);
+}
+
+/* If "map" obviously lies on a hyperplane where the given dimension
+ * has a fixed value, then return that value.
+ * Otherwise return NaN.
+ */
+__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+ int fixed;
+
+ if (!map)
+ return NULL;
+ ctx = isl_map_get_ctx(map);
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+ fixed = isl_map_plain_is_fixed(map, type, pos, &v->n);
+ if (fixed < 0)
+ return isl_val_free(v);
+ if (fixed) {
+ isl_int_set_si(v->d, 1);
+ return v;
+ }
+ isl_val_free(v);
+ return isl_val_nan(ctx);
+}
+
+/* If "set" obviously lies on a hyperplane where the given dimension
+ * has a fixed value, then return that value.
+ * Otherwise return NaN.
+ */
+__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_map_plain_get_val_if_fixed(set, type, pos);
+}
+
+int isl_set_plain_is_fixed(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int *val)
+{
+ return isl_map_plain_is_fixed(set, type, pos, val);
+}
+
+int isl_map_fast_is_fixed(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos, isl_int *val)
+{
+ return isl_map_plain_is_fixed(map, type, pos, val);
+}
+
+/* Check if dimension dim has fixed value and if so and if val is not NULL,
+ * then return this fixed value in *val.
+ */
+int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
+ unsigned dim, isl_int *val)
+{
+ return isl_basic_set_plain_has_fixed_var(bset,
+ isl_basic_set_n_param(bset) + dim, val);
+}
+
+/* Check if dimension dim has fixed value and if so and if val is not NULL,
+ * then return this fixed value in *val.
+ */
+int isl_set_plain_dim_is_fixed(__isl_keep isl_set *set,
+ unsigned dim, isl_int *val)
+{
+ return isl_set_plain_has_fixed_var(set, isl_set_n_param(set) + dim, val);
+}
+
+int isl_set_fast_dim_is_fixed(__isl_keep isl_set *set,
+ unsigned dim, isl_int *val)
+{
+ return isl_set_plain_dim_is_fixed(set, dim, val);
+}
+
+/* Check if input variable in has fixed value and if so and if val is not NULL,
+ * then return this fixed value in *val.
+ */
+int isl_map_plain_input_is_fixed(__isl_keep isl_map *map,
+ unsigned in, isl_int *val)
+{
+ return isl_map_plain_has_fixed_var(map, isl_map_n_param(map) + in, val);
+}
+
+/* Check if dimension dim has an (obvious) fixed lower bound and if so
+ * and if val is not NULL, then return this lower bound in *val.
+ */
+int isl_basic_set_plain_dim_has_fixed_lower_bound(
+ __isl_keep isl_basic_set *bset, unsigned dim, isl_int *val)
+{
+ int i, i_eq = -1, i_ineq = -1;
+ isl_int *c;
+ unsigned total;
+ unsigned nparam;
+
+ if (!bset)
+ return -1;
+ total = isl_basic_set_total_dim(bset);
+ nparam = isl_basic_set_n_param(bset);
+ for (i = 0; i < bset->n_eq; ++i) {
+ if (isl_int_is_zero(bset->eq[i][1+nparam+dim]))
+ continue;
+ if (i_eq != -1)
+ return 0;
+ i_eq = i;
+ }
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (!isl_int_is_pos(bset->ineq[i][1+nparam+dim]))
+ continue;
+ if (i_eq != -1 || i_ineq != -1)
+ return 0;
+ i_ineq = i;
+ }
+ if (i_eq == -1 && i_ineq == -1)
+ return 0;
+ c = i_eq != -1 ? bset->eq[i_eq] : bset->ineq[i_ineq];
+ /* The coefficient should always be one due to normalization. */
+ if (!isl_int_is_one(c[1+nparam+dim]))
+ return 0;
+ if (isl_seq_first_non_zero(c+1, nparam+dim) != -1)
+ return 0;
+ if (isl_seq_first_non_zero(c+1+nparam+dim+1,
+ total - nparam - dim - 1) != -1)
+ return 0;
+ if (val)
+ isl_int_neg(*val, c[0]);
+ return 1;
+}
+
+int isl_set_plain_dim_has_fixed_lower_bound(__isl_keep isl_set *set,
+ unsigned dim, isl_int *val)
+{
+ int i;
+ isl_int v;
+ isl_int tmp;
+ int fixed;
+
+ if (!set)
+ return -1;
+ if (set->n == 0)
+ return 0;
+ if (set->n == 1)
+ return isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
+ dim, val);
+ isl_int_init(v);
+ isl_int_init(tmp);
+ fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[0],
+ dim, &v);
+ for (i = 1; fixed == 1 && i < set->n; ++i) {
+ fixed = isl_basic_set_plain_dim_has_fixed_lower_bound(set->p[i],
+ dim, &tmp);
+ if (fixed == 1 && isl_int_ne(tmp, v))
+ fixed = 0;
+ }
+ if (val)
+ isl_int_set(*val, v);
+ isl_int_clear(tmp);
+ isl_int_clear(v);
+ return fixed;
+}
+
+/* uset_gist depends on constraints without existentially quantified
+ * variables sorting first.
+ */
+static int sort_constraint_cmp(const void *p1, const void *p2, void *arg)
+{
+ isl_int **c1 = (isl_int **) p1;
+ isl_int **c2 = (isl_int **) p2;
+ int l1, l2;
+ unsigned size = *(unsigned *) arg;
+
+ l1 = isl_seq_last_non_zero(*c1 + 1, size);
+ l2 = isl_seq_last_non_zero(*c2 + 1, size);
+
+ if (l1 != l2)
+ return l1 - l2;
+
+ return isl_seq_cmp(*c1 + 1, *c2 + 1, size);
+}
+
+static struct isl_basic_map *isl_basic_map_sort_constraints(
+ struct isl_basic_map *bmap)
+{
+ unsigned total;
+
+ if (!bmap)
+ return NULL;
+ if (bmap->n_ineq == 0)
+ return bmap;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
+ return bmap;
+ total = isl_basic_map_total_dim(bmap);
+ if (isl_sort(bmap->ineq, bmap->n_ineq, sizeof(isl_int *),
+ &sort_constraint_cmp, &total) < 0)
+ return isl_basic_map_free(bmap);
+ return bmap;
+}
+
+__isl_give isl_basic_set *isl_basic_set_sort_constraints(
+ __isl_take isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)isl_basic_map_sort_constraints(
+ (struct isl_basic_map *)bset);
+}
+
+struct isl_basic_map *isl_basic_map_normalize(struct isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED))
+ return bmap;
+ bmap = isl_basic_map_remove_redundancies(bmap);
+ bmap = isl_basic_map_sort_constraints(bmap);
+ if (bmap)
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_normalize(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)isl_basic_map_normalize(
+ (struct isl_basic_map *)bset);
+}
+
+int isl_basic_map_plain_cmp(const __isl_keep isl_basic_map *bmap1,
+ const __isl_keep isl_basic_map *bmap2)
+{
+ int i, cmp;
+ unsigned total;
+
+ if (bmap1 == bmap2)
+ return 0;
+ if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) !=
+ ISL_F_ISSET(bmap2, ISL_BASIC_MAP_RATIONAL))
+ return ISL_F_ISSET(bmap1, ISL_BASIC_MAP_RATIONAL) ? -1 : 1;
+ if (isl_basic_map_n_param(bmap1) != isl_basic_map_n_param(bmap2))
+ return isl_basic_map_n_param(bmap1) - isl_basic_map_n_param(bmap2);
+ if (isl_basic_map_n_in(bmap1) != isl_basic_map_n_in(bmap2))
+ return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
+ if (isl_basic_map_n_out(bmap1) != isl_basic_map_n_out(bmap2))
+ return isl_basic_map_n_out(bmap1) - isl_basic_map_n_out(bmap2);
+ if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY) &&
+ ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
+ return 0;
+ if (ISL_F_ISSET(bmap1, ISL_BASIC_MAP_EMPTY))
+ return 1;
+ if (ISL_F_ISSET(bmap2, ISL_BASIC_MAP_EMPTY))
+ return -1;
+ if (bmap1->n_eq != bmap2->n_eq)
+ return bmap1->n_eq - bmap2->n_eq;
+ if (bmap1->n_ineq != bmap2->n_ineq)
+ return bmap1->n_ineq - bmap2->n_ineq;
+ if (bmap1->n_div != bmap2->n_div)
+ return bmap1->n_div - bmap2->n_div;
+ total = isl_basic_map_total_dim(bmap1);
+ for (i = 0; i < bmap1->n_eq; ++i) {
+ cmp = isl_seq_cmp(bmap1->eq[i], bmap2->eq[i], 1+total);
+ if (cmp)
+ return cmp;
+ }
+ for (i = 0; i < bmap1->n_ineq; ++i) {
+ cmp = isl_seq_cmp(bmap1->ineq[i], bmap2->ineq[i], 1+total);
+ if (cmp)
+ return cmp;
+ }
+ for (i = 0; i < bmap1->n_div; ++i) {
+ cmp = isl_seq_cmp(bmap1->div[i], bmap2->div[i], 1+1+total);
+ if (cmp)
+ return cmp;
+ }
+ return 0;
+}
+
+int isl_basic_set_plain_cmp(const __isl_keep isl_basic_set *bset1,
+ const __isl_keep isl_basic_set *bset2)
+{
+ return isl_basic_map_plain_cmp(bset1, bset2);
+}
+
+int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ int i, cmp;
+
+ if (set1 == set2)
+ return 0;
+ if (set1->n != set2->n)
+ return set1->n - set2->n;
+
+ for (i = 0; i < set1->n; ++i) {
+ cmp = isl_basic_set_plain_cmp(set1->p[i], set2->p[i]);
+ if (cmp)
+ return cmp;
+ }
+
+ return 0;
+}
+
+int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2)
+{
+ return isl_basic_map_plain_cmp(bmap1, bmap2) == 0;
+}
+
+int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2)
+{
+ return isl_basic_map_plain_is_equal((isl_basic_map *)bset1,
+ (isl_basic_map *)bset2);
+}
+
+static int qsort_bmap_cmp(const void *p1, const void *p2)
+{
+ const struct isl_basic_map *bmap1 = *(const struct isl_basic_map **)p1;
+ const struct isl_basic_map *bmap2 = *(const struct isl_basic_map **)p2;
+
+ return isl_basic_map_plain_cmp(bmap1, bmap2);
+}
+
+/* Sort the basic maps of "map" and remove duplicate basic maps.
+ *
+ * While removing basic maps, we make sure that the basic maps remain
+ * sorted because isl_map_normalize expects the basic maps of the result
+ * to be sorted.
+ */
+static __isl_give isl_map *sort_and_remove_duplicates(__isl_take isl_map *map)
+{
+ int i, j;
+
+ map = isl_map_remove_empty_parts(map);
+ if (!map)
+ return NULL;
+ qsort(map->p, map->n, sizeof(struct isl_basic_map *), qsort_bmap_cmp);
+ for (i = map->n - 1; i >= 1; --i) {
+ if (!isl_basic_map_plain_is_equal(map->p[i - 1], map->p[i]))
+ continue;
+ isl_basic_map_free(map->p[i-1]);
+ for (j = i; j < map->n; ++j)
+ map->p[j - 1] = map->p[j];
+ map->n--;
+ }
+
+ return map;
+}
+
+/* Remove obvious duplicates among the basic maps of "map".
+ *
+ * Unlike isl_map_normalize, this function does not remove redundant
+ * constraints and only removes duplicates that have exactly the same
+ * constraints in the input. It does sort the constraints and
+ * the basic maps to ease the detection of duplicates.
+ *
+ * If "map" has already been normalized or if the basic maps are
+ * disjoint, then there can be no duplicates.
+ */
+__isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map)
+{
+ int i;
+ isl_basic_map *bmap;
+
+ if (!map)
+ return NULL;
+ if (map->n <= 1)
+ return map;
+ if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED | ISL_MAP_DISJOINT))
+ return map;
+ for (i = 0; i < map->n; ++i) {
+ bmap = isl_basic_map_copy(map->p[i]);
+ bmap = isl_basic_map_sort_constraints(bmap);
+ if (!bmap)
+ return isl_map_free(map);
+ isl_basic_map_free(map->p[i]);
+ map->p[i] = bmap;
+ }
+
+ map = sort_and_remove_duplicates(map);
+ return map;
+}
+
+/* We normalize in place, but if anything goes wrong we need
+ * to return NULL, so we need to make sure we don't change the
+ * meaning of any possible other copies of map.
+ */
+__isl_give isl_map *isl_map_normalize(__isl_take isl_map *map)
+{
+ int i;
+ struct isl_basic_map *bmap;
+
+ if (!map)
+ return NULL;
+ if (ISL_F_ISSET(map, ISL_MAP_NORMALIZED))
+ return map;
+ for (i = 0; i < map->n; ++i) {
+ bmap = isl_basic_map_normalize(isl_basic_map_copy(map->p[i]));
+ if (!bmap)
+ goto error;
+ isl_basic_map_free(map->p[i]);
+ map->p[i] = bmap;
+ }
+
+ map = sort_and_remove_duplicates(map);
+ if (map)
+ ISL_F_SET(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_set *isl_set_normalize(struct isl_set *set)
+{
+ return (struct isl_set *)isl_map_normalize((struct isl_map *)set);
+}
+
+int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ int i;
+ int equal;
+
+ if (!map1 || !map2)
+ return -1;
+
+ if (map1 == map2)
+ return 1;
+ if (!isl_space_is_equal(map1->dim, map2->dim))
+ return 0;
+
+ map1 = isl_map_copy(map1);
+ map2 = isl_map_copy(map2);
+ map1 = isl_map_normalize(map1);
+ map2 = isl_map_normalize(map2);
+ if (!map1 || !map2)
+ goto error;
+ equal = map1->n == map2->n;
+ for (i = 0; equal && i < map1->n; ++i) {
+ equal = isl_basic_map_plain_is_equal(map1->p[i], map2->p[i]);
+ if (equal < 0)
+ goto error;
+ }
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return equal;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return -1;
+}
+
+int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ return isl_map_plain_is_equal(map1, map2);
+}
+
+int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ return isl_map_plain_is_equal((struct isl_map *)set1,
+ (struct isl_map *)set2);
+}
+
+int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ return isl_set_plain_is_equal(set1, set2);
+}
+
+/* Return an interval that ranges from min to max (inclusive)
+ */
+struct isl_basic_set *isl_basic_set_interval(struct isl_ctx *ctx,
+ isl_int min, isl_int max)
+{
+ int k;
+ struct isl_basic_set *bset = NULL;
+
+ bset = isl_basic_set_alloc(ctx, 0, 1, 0, 0, 2);
+ if (!bset)
+ goto error;
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(bset->ineq[k][1], 1);
+ isl_int_neg(bset->ineq[k][0], min);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(bset->ineq[k][1], -1);
+ isl_int_set(bset->ineq[k][0], max);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Return the basic sets in "set" as a list.
+ */
+__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
+ __isl_keep isl_set *set)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_basic_set_list *list;
+
+ if (!set)
+ return NULL;
+ ctx = isl_set_get_ctx(set);
+ list = isl_basic_set_list_alloc(ctx, 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;
+}
+
+/* Return the intersection of the elements in the non-empty list "list".
+ * All elements are assumed to live in the same space.
+ */
+__isl_give isl_basic_set *isl_basic_set_list_intersect(
+ __isl_take struct isl_basic_set_list *list)
+{
+ int i, n;
+ isl_basic_set *bset;
+
+ if (!list)
+ return NULL;
+ n = isl_basic_set_list_n_basic_set(list);
+ if (n < 1)
+ isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
+ "expecting non-empty list", goto error);
+
+ bset = isl_basic_set_list_get_basic_set(list, 0);
+ for (i = 1; i < n; ++i) {
+ isl_basic_set *bset_i;
+
+ bset_i = isl_basic_set_list_get_basic_set(list, i);
+ bset = isl_basic_set_intersect(bset, bset_i);
+ }
+
+ isl_basic_set_list_free(list);
+ return bset;
+error:
+ isl_basic_set_list_free(list);
+ return NULL;
+}
+
+/* Return the Cartesian product of the basic sets in list (in the given order).
+ */
+__isl_give isl_basic_set *isl_basic_set_list_product(
+ __isl_take struct isl_basic_set_list *list)
+{
+ int i;
+ unsigned dim;
+ unsigned nparam;
+ unsigned extra;
+ unsigned n_eq;
+ unsigned n_ineq;
+ struct isl_basic_set *product = NULL;
+
+ if (!list)
+ goto error;
+ isl_assert(list->ctx, list->n > 0, goto error);
+ isl_assert(list->ctx, list->p[0], goto error);
+ nparam = isl_basic_set_n_param(list->p[0]);
+ dim = isl_basic_set_n_dim(list->p[0]);
+ extra = list->p[0]->n_div;
+ n_eq = list->p[0]->n_eq;
+ n_ineq = list->p[0]->n_ineq;
+ for (i = 1; i < list->n; ++i) {
+ isl_assert(list->ctx, list->p[i], goto error);
+ isl_assert(list->ctx,
+ nparam == isl_basic_set_n_param(list->p[i]), goto error);
+ dim += isl_basic_set_n_dim(list->p[i]);
+ extra += list->p[i]->n_div;
+ n_eq += list->p[i]->n_eq;
+ n_ineq += list->p[i]->n_ineq;
+ }
+ product = isl_basic_set_alloc(list->ctx, nparam, dim, extra,
+ n_eq, n_ineq);
+ if (!product)
+ goto error;
+ dim = 0;
+ for (i = 0; i < list->n; ++i) {
+ isl_basic_set_add_constraints(product,
+ isl_basic_set_copy(list->p[i]), dim);
+ dim += isl_basic_set_n_dim(list->p[i]);
+ }
+ isl_basic_set_list_free(list);
+ return product;
+error:
+ isl_basic_set_free(product);
+ isl_basic_set_list_free(list);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_product(
+ struct isl_basic_map *bmap1, struct isl_basic_map *bmap2)
+{
+ isl_space *dim_result = NULL;
+ struct isl_basic_map *bmap;
+ unsigned in1, in2, out1, out2, nparam, total, pos;
+ struct isl_dim_map *dim_map1, *dim_map2;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ isl_assert(bmap1->ctx, isl_space_match(bmap1->dim, isl_dim_param,
+ bmap2->dim, isl_dim_param), goto error);
+ dim_result = isl_space_product(isl_space_copy(bmap1->dim),
+ isl_space_copy(bmap2->dim));
+
+ in1 = isl_basic_map_n_in(bmap1);
+ in2 = isl_basic_map_n_in(bmap2);
+ out1 = isl_basic_map_n_out(bmap1);
+ out2 = isl_basic_map_n_out(bmap2);
+ nparam = isl_basic_map_n_param(bmap1);
+
+ total = nparam + in1 + in2 + out1 + out2 + bmap1->n_div + bmap2->n_div;
+ dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
+ dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
+ isl_dim_map_div(dim_map1, bmap1, pos += out2);
+ isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
+
+ bmap = isl_basic_map_alloc_space(dim_result,
+ bmap1->n_div + bmap2->n_div,
+ bmap1->n_eq + bmap2->n_eq,
+ bmap1->n_ineq + bmap2->n_ineq);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_flat_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
+{
+ isl_basic_map *prod;
+
+ prod = isl_basic_map_product(bmap1, bmap2);
+ prod = isl_basic_map_flatten(prod);
+ return prod;
+}
+
+__isl_give isl_basic_set *isl_basic_set_flat_product(
+ __isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2)
+{
+ return isl_basic_map_flat_range_product(bset1, bset2);
+}
+
+__isl_give isl_basic_map *isl_basic_map_domain_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
+{
+ isl_space *space_result = NULL;
+ isl_basic_map *bmap;
+ unsigned in1, in2, out, nparam, total, pos;
+ struct isl_dim_map *dim_map1, *dim_map2;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ space_result = isl_space_domain_product(isl_space_copy(bmap1->dim),
+ isl_space_copy(bmap2->dim));
+
+ in1 = isl_basic_map_dim(bmap1, isl_dim_in);
+ in2 = isl_basic_map_dim(bmap2, isl_dim_in);
+ out = isl_basic_map_dim(bmap1, isl_dim_out);
+ nparam = isl_basic_map_dim(bmap1, isl_dim_param);
+
+ total = nparam + in1 + in2 + out + bmap1->n_div + bmap2->n_div;
+ dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
+ dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos += in1);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in2);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos);
+ isl_dim_map_div(dim_map1, bmap1, pos += out);
+ isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
+
+ bmap = isl_basic_map_alloc_space(space_result,
+ bmap1->n_div + bmap2->n_div,
+ bmap1->n_eq + bmap2->n_eq,
+ bmap1->n_ineq + bmap2->n_ineq);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_range_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
+{
+ isl_space *dim_result = NULL;
+ isl_basic_map *bmap;
+ unsigned in, out1, out2, nparam, total, pos;
+ struct isl_dim_map *dim_map1, *dim_map2;
+
+ if (!bmap1 || !bmap2)
+ goto error;
+
+ if (!isl_space_match(bmap1->dim, isl_dim_param,
+ bmap2->dim, isl_dim_param))
+ isl_die(isl_basic_map_get_ctx(bmap1), isl_error_invalid,
+ "parameters don't match", goto error);
+
+ dim_result = isl_space_range_product(isl_space_copy(bmap1->dim),
+ isl_space_copy(bmap2->dim));
+
+ in = isl_basic_map_dim(bmap1, isl_dim_in);
+ out1 = isl_basic_map_n_out(bmap1);
+ out2 = isl_basic_map_n_out(bmap2);
+ nparam = isl_basic_map_n_param(bmap1);
+
+ total = nparam + in + out1 + out2 + bmap1->n_div + bmap2->n_div;
+ dim_map1 = isl_dim_map_alloc(bmap1->ctx, total);
+ dim_map2 = isl_dim_map_alloc(bmap1->ctx, total);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_param, pos = 0);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_in, pos += nparam);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_in, pos);
+ isl_dim_map_dim(dim_map1, bmap1->dim, isl_dim_out, pos += in);
+ isl_dim_map_dim(dim_map2, bmap2->dim, isl_dim_out, pos += out1);
+ isl_dim_map_div(dim_map1, bmap1, pos += out2);
+ isl_dim_map_div(dim_map2, bmap2, pos += bmap1->n_div);
+
+ bmap = isl_basic_map_alloc_space(dim_result,
+ bmap1->n_div + bmap2->n_div,
+ bmap1->n_eq + bmap2->n_eq,
+ bmap1->n_ineq + bmap2->n_ineq);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap1, dim_map1);
+ bmap = isl_basic_map_add_constraints_dim_map(bmap, bmap2, dim_map2);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_flat_range_product(
+ __isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2)
+{
+ isl_basic_map *prod;
+
+ prod = isl_basic_map_range_product(bmap1, bmap2);
+ prod = isl_basic_map_flatten_range(prod);
+ return prod;
+}
+
+/* Apply "basic_map_product" to each pair of basic maps in "map1" and "map2"
+ * and collect the results.
+ * The result live in the space obtained by calling "space_product"
+ * on the spaces of "map1" and "map2".
+ * If "remove_duplicates" is set then the result may contain duplicates
+ * (even if the inputs do not) and so we try and remove the obvious
+ * duplicates.
+ */
+static __isl_give isl_map *map_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2,
+ __isl_give isl_space *(*space_product)(__isl_take isl_space *left,
+ __isl_take isl_space *right),
+ __isl_give isl_basic_map *(*basic_map_product)(
+ __isl_take isl_basic_map *left,
+ __isl_take isl_basic_map *right),
+ int remove_duplicates)
+{
+ unsigned flags = 0;
+ struct isl_map *result;
+ int i, j;
+
+ if (!map1 || !map2)
+ goto error;
+
+ isl_assert(map1->ctx, isl_space_match(map1->dim, isl_dim_param,
+ map2->dim, isl_dim_param), goto error);
+
+ if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT) &&
+ ISL_F_ISSET(map2, ISL_MAP_DISJOINT))
+ ISL_FL_SET(flags, ISL_MAP_DISJOINT);
+
+ result = isl_map_alloc_space(space_product(isl_space_copy(map1->dim),
+ isl_space_copy(map2->dim)),
+ map1->n * map2->n, flags);
+ if (!result)
+ goto error;
+ for (i = 0; i < map1->n; ++i)
+ for (j = 0; j < map2->n; ++j) {
+ struct isl_basic_map *part;
+ part = basic_map_product(isl_basic_map_copy(map1->p[i]),
+ isl_basic_map_copy(map2->p[j]));
+ if (isl_basic_map_is_empty(part))
+ isl_basic_map_free(part);
+ else
+ result = isl_map_add_basic_map(result, part);
+ if (!result)
+ goto error;
+ }
+ if (remove_duplicates)
+ result = isl_map_remove_obvious_duplicates(result);
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return result;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+/* Given two maps A -> B and C -> D, construct a map [A -> C] -> [B -> D]
+ */
+static __isl_give isl_map *map_product_aligned(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return map_product(map1, map2, &isl_space_product,
+ &isl_basic_map_product, 0);
+}
+
+__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_product_aligned);
+}
+
+/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B, D)
+ */
+__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *prod;
+
+ prod = isl_map_product(map1, map2);
+ prod = isl_map_flatten(prod);
+ return prod;
+}
+
+/* Given two set A and B, construct its Cartesian product A x B.
+ */
+struct isl_set *isl_set_product(struct isl_set *set1, struct isl_set *set2)
+{
+ return isl_map_range_product(set1, set2);
+}
+
+__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
+ __isl_take isl_set *set2)
+{
+ return isl_map_flat_range_product(set1, set2);
+}
+
+/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
+ */
+static __isl_give isl_map *map_domain_product_aligned(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return map_product(map1, map2, &isl_space_domain_product,
+ &isl_basic_map_domain_product, 1);
+}
+
+/* Given two maps A -> B and C -> D, construct a map (A * C) -> [B -> D]
+ */
+static __isl_give isl_map *map_range_product_aligned(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return map_product(map1, map2, &isl_space_range_product,
+ &isl_basic_map_range_product, 1);
+}
+
+__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2,
+ &map_domain_product_aligned);
+}
+
+__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2,
+ &map_range_product_aligned);
+}
+
+/* Given a map of the form [A -> B] -> [C -> D], return the map A -> C.
+ */
+__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total1, keep1, total2, keep2;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(map->dim) ||
+ !isl_space_range_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total1 = isl_space_dim(space, isl_dim_in);
+ total2 = isl_space_dim(space, isl_dim_out);
+ space = isl_space_factor_domain(space);
+ keep1 = isl_space_dim(space, isl_dim_in);
+ keep2 = isl_space_dim(space, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_in, keep1, total1 - keep1);
+ map = isl_map_project_out(map, isl_dim_out, keep2, total2 - keep2);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given a map of the form [A -> B] -> [C -> D], return the map B -> D.
+ */
+__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total1, keep1, total2, keep2;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(map->dim) ||
+ !isl_space_range_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total1 = isl_space_dim(space, isl_dim_in);
+ total2 = isl_space_dim(space, isl_dim_out);
+ space = isl_space_factor_range(space);
+ keep1 = isl_space_dim(space, isl_dim_in);
+ keep2 = isl_space_dim(space, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_in, 0, total1 - keep1);
+ map = isl_map_project_out(map, isl_dim_out, 0, total2 - keep2);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given a map of the form [A -> B] -> C, return the map A -> C.
+ */
+__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "domain is not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total = isl_space_dim(space, isl_dim_in);
+ space = isl_space_domain_factor_domain(space);
+ keep = isl_space_dim(space, isl_dim_in);
+ map = isl_map_project_out(map, isl_dim_in, keep, total - keep);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given a map of the form [A -> B] -> C, return the map B -> C.
+ */
+__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "domain is not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total = isl_space_dim(space, isl_dim_in);
+ space = isl_space_domain_factor_range(space);
+ keep = isl_space_dim(space, isl_dim_in);
+ map = isl_map_project_out(map, isl_dim_in, 0, total - keep);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given a map A -> [B -> C], extract the map A -> B.
+ */
+__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_range_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "range is not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total = isl_space_dim(space, isl_dim_out);
+ space = isl_space_range_factor_domain(space);
+ keep = isl_space_dim(space, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_out, keep, total - keep);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given a map A -> [B -> C], extract the map A -> C.
+ */
+__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!map)
+ return NULL;
+ if (!isl_space_range_is_wrapping(map->dim))
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "range is not a product", return isl_map_free(map));
+
+ space = isl_map_get_space(map);
+ total = isl_space_dim(space, isl_dim_out);
+ space = isl_space_range_factor_range(space);
+ keep = isl_space_dim(space, isl_dim_out);
+ map = isl_map_project_out(map, isl_dim_out, 0, total - keep);
+ map = isl_map_reset_space(map, space);
+
+ return map;
+}
+
+/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D)
+ */
+__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *prod;
+
+ prod = isl_map_domain_product(map1, map2);
+ prod = isl_map_flatten_domain(prod);
+ return prod;
+}
+
+/* Given two maps A -> B and C -> D, construct a map (A * C) -> (B, D)
+ */
+__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ isl_map *prod;
+
+ prod = isl_map_range_product(map1, map2);
+ prod = isl_map_flatten_range(prod);
+ return prod;
+}
+
+uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ uint32_t hash = isl_hash_init();
+ unsigned total;
+
+ if (!bmap)
+ return 0;
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_normalize(bmap);
+ if (!bmap)
+ return 0;
+ total = isl_basic_map_total_dim(bmap);
+ isl_hash_byte(hash, bmap->n_eq & 0xFF);
+ for (i = 0; i < bmap->n_eq; ++i) {
+ uint32_t c_hash;
+ c_hash = isl_seq_get_hash(bmap->eq[i], 1 + total);
+ isl_hash_hash(hash, c_hash);
+ }
+ isl_hash_byte(hash, bmap->n_ineq & 0xFF);
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ uint32_t c_hash;
+ c_hash = isl_seq_get_hash(bmap->ineq[i], 1 + total);
+ isl_hash_hash(hash, c_hash);
+ }
+ isl_hash_byte(hash, bmap->n_div & 0xFF);
+ for (i = 0; i < bmap->n_div; ++i) {
+ uint32_t c_hash;
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ isl_hash_byte(hash, i & 0xFF);
+ c_hash = isl_seq_get_hash(bmap->div[i], 1 + 1 + total);
+ isl_hash_hash(hash, c_hash);
+ }
+ isl_basic_map_free(bmap);
+ return hash;
+}
+
+uint32_t isl_basic_set_get_hash(__isl_keep isl_basic_set *bset)
+{
+ return isl_basic_map_get_hash((isl_basic_map *)bset);
+}
+
+uint32_t isl_map_get_hash(__isl_keep isl_map *map)
+{
+ int i;
+ uint32_t hash;
+
+ if (!map)
+ return 0;
+ map = isl_map_copy(map);
+ map = isl_map_normalize(map);
+ if (!map)
+ return 0;
+
+ hash = isl_hash_init();
+ for (i = 0; i < map->n; ++i) {
+ uint32_t bmap_hash;
+ bmap_hash = isl_basic_map_get_hash(map->p[i]);
+ isl_hash_hash(hash, bmap_hash);
+ }
+
+ isl_map_free(map);
+
+ return hash;
+}
+
+uint32_t isl_set_get_hash(__isl_keep isl_set *set)
+{
+ return isl_map_get_hash((isl_map *)set);
+}
+
+/* Check if the value for dimension dim is completely determined
+ * by the values of the other parameters and variables.
+ * That is, check if dimension dim is involved in an equality.
+ */
+int isl_basic_set_dim_is_unique(struct isl_basic_set *bset, unsigned dim)
+{
+ int i;
+ unsigned nparam;
+
+ if (!bset)
+ return -1;
+ nparam = isl_basic_set_n_param(bset);
+ for (i = 0; i < bset->n_eq; ++i)
+ if (!isl_int_is_zero(bset->eq[i][1 + nparam + dim]))
+ return 1;
+ return 0;
+}
+
+/* Check if the value for dimension dim is completely determined
+ * by the values of the other parameters and variables.
+ * That is, check if dimension dim is involved in an equality
+ * for each of the subsets.
+ */
+int isl_set_dim_is_unique(struct isl_set *set, unsigned dim)
+{
+ int i;
+
+ if (!set)
+ return -1;
+ for (i = 0; i < set->n; ++i) {
+ int unique;
+ unique = isl_basic_set_dim_is_unique(set->p[i], dim);
+ if (unique != 1)
+ return unique;
+ }
+ return 1;
+}
+
+/* Return the number of basic maps in the (current) representation of "map".
+ */
+int isl_map_n_basic_map(__isl_keep isl_map *map)
+{
+ return map ? map->n : 0;
+}
+
+int isl_set_n_basic_set(__isl_keep isl_set *set)
+{
+ return set ? set->n : 0;
+}
+
+int isl_map_foreach_basic_map(__isl_keep isl_map *map,
+ int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user)
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i)
+ if (fn(isl_basic_map_copy(map->p[i]), user) < 0)
+ return -1;
+
+ return 0;
+}
+
+int isl_set_foreach_basic_set(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user)
+{
+ int i;
+
+ if (!set)
+ return -1;
+
+ for (i = 0; i < set->n; ++i)
+ if (fn(isl_basic_set_copy(set->p[i]), user) < 0)
+ return -1;
+
+ return 0;
+}
+
+__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset)
+{
+ isl_space *dim;
+
+ if (!bset)
+ return NULL;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_lift(dim, bset->n_div);
+ if (!dim)
+ goto error;
+ isl_space_free(bset->dim);
+ bset->dim = dim;
+ bset->extra -= bset->n_div;
+ bset->n_div = 0;
+
+ bset = isl_basic_set_finalize(bset);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_lift(__isl_take isl_set *set)
+{
+ int i;
+ isl_space *dim;
+ unsigned n_div;
+
+ set = isl_set_align_divs(set);
+
+ if (!set)
+ return NULL;
+
+ set = isl_set_cow(set);
+ if (!set)
+ return NULL;
+
+ n_div = set->p[0]->n_div;
+ dim = isl_set_get_space(set);
+ dim = isl_space_lift(dim, n_div);
+ if (!dim)
+ goto error;
+ isl_space_free(set->dim);
+ set->dim = dim;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_lift(set->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set)
+{
+ isl_space *dim;
+ struct isl_basic_map *bmap;
+ unsigned n_set;
+ unsigned n_div;
+ unsigned n_param;
+ unsigned total;
+ int i, k, l;
+
+ set = isl_set_align_divs(set);
+
+ if (!set)
+ return NULL;
+
+ dim = isl_set_get_space(set);
+ if (set->n == 0 || set->p[0]->n_div == 0) {
+ isl_set_free(set);
+ return isl_map_identity(isl_space_map_from_set(dim));
+ }
+
+ n_div = set->p[0]->n_div;
+ dim = isl_space_map_from_set(dim);
+ n_param = isl_space_dim(dim, isl_dim_param);
+ n_set = isl_space_dim(dim, isl_dim_in);
+ dim = isl_space_extend(dim, n_param, n_set, n_set + n_div);
+ bmap = isl_basic_map_alloc_space(dim, 0, n_set, 2 * n_div);
+ for (i = 0; i < n_set; ++i)
+ bmap = var_equal(bmap, i);
+
+ total = n_param + n_set + n_set + n_div;
+ for (i = 0; i < n_div; ++i) {
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->ineq[k], set->p[0]->div[i]+1, 1+n_param);
+ isl_seq_clr(bmap->ineq[k]+1+n_param, n_set);
+ isl_seq_cpy(bmap->ineq[k]+1+n_param+n_set,
+ set->p[0]->div[i]+1+1+n_param, n_set + n_div);
+ isl_int_neg(bmap->ineq[k][1+n_param+n_set+n_set+i],
+ set->p[0]->div[i][0]);
+
+ l = isl_basic_map_alloc_inequality(bmap);
+ if (l < 0)
+ goto error;
+ isl_seq_neg(bmap->ineq[l], bmap->ineq[k], 1 + total);
+ isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0],
+ set->p[0]->div[i][0]);
+ isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
+ }
+
+ isl_set_free(set);
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ return isl_map_from_basic_map(bmap);
+error:
+ isl_set_free(set);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+int isl_basic_set_size(__isl_keep isl_basic_set *bset)
+{
+ unsigned dim;
+ int size = 0;
+
+ if (!bset)
+ return -1;
+
+ dim = isl_basic_set_total_dim(bset);
+ size += bset->n_eq * (1 + dim);
+ size += bset->n_ineq * (1 + dim);
+ size += bset->n_div * (2 + dim);
+
+ return size;
+}
+
+int isl_set_size(__isl_keep isl_set *set)
+{
+ int i;
+ int size = 0;
+
+ if (!set)
+ return -1;
+
+ for (i = 0; i < set->n; ++i)
+ size += isl_basic_set_size(set->p[i]);
+
+ return size;
+}
+
+/* Check if there is any lower bound (if lower == 0) and/or upper
+ * bound (if upper == 0) on the specified dim.
+ */
+static int basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos, int lower, int upper)
+{
+ int i;
+
+ if (!bmap)
+ return -1;
+
+ isl_assert(bmap->ctx, pos < isl_basic_map_dim(bmap, type), return -1);
+
+ pos += isl_basic_map_offset(bmap, type);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (!isl_int_is_zero(bmap->div[i][1 + pos]))
+ return 1;
+ }
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (!isl_int_is_zero(bmap->eq[i][pos]))
+ return 1;
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ int sgn = isl_int_sgn(bmap->ineq[i][pos]);
+ if (sgn > 0)
+ lower = 1;
+ if (sgn < 0)
+ upper = 1;
+ }
+
+ return lower && upper;
+}
+
+int isl_basic_map_dim_is_bounded(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ return basic_map_dim_is_bounded(bmap, type, pos, 0, 0);
+}
+
+int isl_basic_map_dim_has_lower_bound(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ return basic_map_dim_is_bounded(bmap, type, pos, 0, 1);
+}
+
+int isl_basic_map_dim_has_upper_bound(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos)
+{
+ return basic_map_dim_is_bounded(bmap, type, pos, 1, 0);
+}
+
+int isl_map_dim_is_bounded(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos)
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ int bounded;
+ bounded = isl_basic_map_dim_is_bounded(map->p[i], type, pos);
+ if (bounded < 0 || !bounded)
+ return bounded;
+ }
+
+ return 1;
+}
+
+/* Return 1 if the specified dim is involved in both an upper bound
+ * and a lower bound.
+ */
+int isl_set_dim_is_bounded(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return isl_map_dim_is_bounded((isl_map *)set, type, pos);
+}
+
+/* Does "map" have a bound (according to "fn") for any of its basic maps?
+ */
+static int has_any_bound(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos,
+ int (*fn)(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos))
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ int bounded;
+ bounded = fn(map->p[i], type, pos);
+ if (bounded < 0 || bounded)
+ return bounded;
+ }
+
+ return 0;
+}
+
+/* Return 1 if the specified dim is involved in any lower bound.
+ */
+int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return has_any_bound(set, type, pos,
+ &isl_basic_map_dim_has_lower_bound);
+}
+
+/* Return 1 if the specified dim is involved in any upper bound.
+ */
+int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return has_any_bound(set, type, pos,
+ &isl_basic_map_dim_has_upper_bound);
+}
+
+/* Does "map" have a bound (according to "fn") for all of its basic maps?
+ */
+static int has_bound(__isl_keep isl_map *map,
+ enum isl_dim_type type, unsigned pos,
+ int (*fn)(__isl_keep isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned pos))
+{
+ int i;
+
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ int bounded;
+ bounded = fn(map->p[i], type, pos);
+ if (bounded < 0 || !bounded)
+ return bounded;
+ }
+
+ return 1;
+}
+
+/* Return 1 if the specified dim has a lower bound (in each of its basic sets).
+ */
+int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return has_bound(set, type, pos, &isl_basic_map_dim_has_lower_bound);
+}
+
+/* Return 1 if the specified dim has an upper bound (in each of its basic sets).
+ */
+int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
+ enum isl_dim_type type, unsigned pos)
+{
+ return has_bound(set, type, pos, &isl_basic_map_dim_has_upper_bound);
+}
+
+/* For each of the "n" variables starting at "first", determine
+ * the sign of the variable and put the results in the first "n"
+ * elements of the array "signs".
+ * Sign
+ * 1 means that the variable is non-negative
+ * -1 means that the variable is non-positive
+ * 0 means the variable attains both positive and negative values.
+ */
+int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
+ unsigned first, unsigned n, int *signs)
+{
+ isl_vec *bound = NULL;
+ struct isl_tab *tab = NULL;
+ struct isl_tab_undo *snap;
+ int i;
+
+ if (!bset || !signs)
+ return -1;
+
+ bound = isl_vec_alloc(bset->ctx, 1 + isl_basic_set_total_dim(bset));
+ tab = isl_tab_from_basic_set(bset, 0);
+ if (!bound || !tab)
+ goto error;
+
+ isl_seq_clr(bound->el, bound->size);
+ isl_int_set_si(bound->el[0], -1);
+
+ snap = isl_tab_snap(tab);
+ for (i = 0; i < n; ++i) {
+ int empty;
+
+ isl_int_set_si(bound->el[1 + first + i], -1);
+ if (isl_tab_add_ineq(tab, bound->el) < 0)
+ goto error;
+ empty = tab->empty;
+ isl_int_set_si(bound->el[1 + first + i], 0);
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ if (empty) {
+ signs[i] = 1;
+ continue;
+ }
+
+ isl_int_set_si(bound->el[1 + first + i], 1);
+ if (isl_tab_add_ineq(tab, bound->el) < 0)
+ goto error;
+ empty = tab->empty;
+ isl_int_set_si(bound->el[1 + first + i], 0);
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ signs[i] = empty ? -1 : 0;
+ }
+
+ isl_tab_free(tab);
+ isl_vec_free(bound);
+ return 0;
+error:
+ isl_tab_free(tab);
+ isl_vec_free(bound);
+ return -1;
+}
+
+int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n, int *signs)
+{
+ if (!bset || !signs)
+ return -1;
+ isl_assert(bset->ctx, first + n <= isl_basic_set_dim(bset, type),
+ return -1);
+
+ first += pos(bset->dim, type) - 1;
+ return isl_basic_set_vars_get_sign(bset, first, n, signs);
+}
+
+/* Is it possible for the integer division "div" to depend (possibly
+ * indirectly) on any output dimensions?
+ *
+ * If the div is undefined, then we conservatively assume that it
+ * may depend on them.
+ * Otherwise, we check if it actually depends on them or on any integer
+ * divisions that may depend on them.
+ */
+static int div_may_involve_output(__isl_keep isl_basic_map *bmap, int div)
+{
+ int i;
+ unsigned n_out, o_out;
+ unsigned n_div, o_div;
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return 1;
+
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ o_out = isl_basic_map_offset(bmap, isl_dim_out);
+
+ if (isl_seq_first_non_zero(bmap->div[div] + 1 + o_out, n_out) != -1)
+ return 1;
+
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ o_div = isl_basic_map_offset(bmap, isl_dim_div);
+
+ for (i = 0; i < n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[div][1 + o_div + i]))
+ continue;
+ if (div_may_involve_output(bmap, i))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* 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.
+ * 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 j, k;
+ unsigned n_out, o_out;
+ unsigned n_div, o_div;
+
+ if (!bmap)
+ return -1;
+
+ 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 (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;
+ }
+ if (k >= n_div)
+ return j;
+ }
+
+ return bmap->n_eq;
+}
+
+/* Check if the given basic map is obviously single-valued.
+ * In particular, for each output dimension, check that there is
+ * an equality that defines the output dimension in terms of
+ * earlier dimensions.
+ */
+int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ unsigned n_out;
+
+ if (!bmap)
+ return -1;
+
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+
+ for (i = 0; i < n_out; ++i) {
+ int eq;
+
+ eq = isl_basic_map_output_defining_equality(bmap, i);
+ if (eq < 0)
+ return -1;
+ if (eq >= bmap->n_eq)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Check if the given basic map is single-valued.
+ * We simply compute
+ *
+ * M \circ M^-1
+ *
+ * and check if the result is a subset of the identity mapping.
+ */
+int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap)
+{
+ isl_space *space;
+ isl_basic_map *test;
+ isl_basic_map *id;
+ int sv;
+
+ sv = isl_basic_map_plain_is_single_valued(bmap);
+ if (sv < 0 || sv)
+ return sv;
+
+ test = isl_basic_map_reverse(isl_basic_map_copy(bmap));
+ test = isl_basic_map_apply_range(test, isl_basic_map_copy(bmap));
+
+ space = isl_basic_map_get_space(bmap);
+ space = isl_space_map_from_set(isl_space_range(space));
+ id = isl_basic_map_identity(space);
+
+ sv = isl_basic_map_is_subset(test, id);
+
+ isl_basic_map_free(test);
+ isl_basic_map_free(id);
+
+ return sv;
+}
+
+/* Check if the given map is obviously single-valued.
+ */
+int isl_map_plain_is_single_valued(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+ if (map->n == 0)
+ return 1;
+ if (map->n >= 2)
+ return 0;
+
+ return isl_basic_map_plain_is_single_valued(map->p[0]);
+}
+
+/* Check if the given map is single-valued.
+ * We simply compute
+ *
+ * M \circ M^-1
+ *
+ * and check if the result is a subset of the identity mapping.
+ */
+int isl_map_is_single_valued(__isl_keep isl_map *map)
+{
+ isl_space *dim;
+ isl_map *test;
+ isl_map *id;
+ int sv;
+
+ sv = isl_map_plain_is_single_valued(map);
+ if (sv < 0 || sv)
+ return sv;
+
+ test = isl_map_reverse(isl_map_copy(map));
+ test = isl_map_apply_range(test, isl_map_copy(map));
+
+ dim = isl_space_map_from_set(isl_space_range(isl_map_get_space(map)));
+ id = isl_map_identity(dim);
+
+ sv = isl_map_is_subset(test, id);
+
+ isl_map_free(test);
+ isl_map_free(id);
+
+ return sv;
+}
+
+int isl_map_is_injective(__isl_keep isl_map *map)
+{
+ int in;
+
+ map = isl_map_copy(map);
+ map = isl_map_reverse(map);
+ in = isl_map_is_single_valued(map);
+ isl_map_free(map);
+
+ return in;
+}
+
+/* Check if the given map is obviously injective.
+ */
+int isl_map_plain_is_injective(__isl_keep isl_map *map)
+{
+ int in;
+
+ map = isl_map_copy(map);
+ map = isl_map_reverse(map);
+ in = isl_map_plain_is_single_valued(map);
+ isl_map_free(map);
+
+ return in;
+}
+
+int isl_map_is_bijective(__isl_keep isl_map *map)
+{
+ int sv;
+
+ sv = isl_map_is_single_valued(map);
+ if (sv < 0 || !sv)
+ return sv;
+
+ return isl_map_is_injective(map);
+}
+
+int isl_set_is_singleton(__isl_keep isl_set *set)
+{
+ return isl_map_is_single_valued((isl_map *)set);
+}
+
+int isl_map_is_translation(__isl_keep isl_map *map)
+{
+ int ok;
+ isl_set *delta;
+
+ delta = isl_map_deltas(isl_map_copy(map));
+ ok = isl_set_is_singleton(delta);
+ isl_set_free(delta);
+
+ return ok;
+}
+
+static int unique(isl_int *p, unsigned pos, unsigned len)
+{
+ if (isl_seq_first_non_zero(p, pos) != -1)
+ return 0;
+ if (isl_seq_first_non_zero(p + pos + 1, len - pos - 1) != -1)
+ return 0;
+ return 1;
+}
+
+int isl_basic_set_is_box(__isl_keep isl_basic_set *bset)
+{
+ int i, j;
+ unsigned nvar;
+ unsigned ovar;
+
+ if (!bset)
+ return -1;
+
+ if (isl_basic_set_dim(bset, isl_dim_div) != 0)
+ return 0;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ ovar = isl_space_offset(bset->dim, isl_dim_set);
+ for (j = 0; j < nvar; ++j) {
+ int lower = 0, upper = 0;
+ for (i = 0; i < bset->n_eq; ++i) {
+ if (isl_int_is_zero(bset->eq[i][1 + ovar + j]))
+ continue;
+ if (!unique(bset->eq[i] + 1 + ovar, j, nvar))
+ return 0;
+ break;
+ }
+ if (i < bset->n_eq)
+ continue;
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_zero(bset->ineq[i][1 + ovar + j]))
+ continue;
+ if (!unique(bset->ineq[i] + 1 + ovar, j, nvar))
+ return 0;
+ if (isl_int_is_pos(bset->ineq[i][1 + ovar + j]))
+ lower = 1;
+ else
+ upper = 1;
+ }
+ if (!lower || !upper)
+ return 0;
+ }
+
+ return 1;
+}
+
+int isl_set_is_box(__isl_keep isl_set *set)
+{
+ if (!set)
+ return -1;
+ if (set->n != 1)
+ return 0;
+
+ return isl_basic_set_is_box(set->p[0]);
+}
+
+int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset)
+{
+ if (!bset)
+ return -1;
+
+ return isl_space_is_wrapping(bset->dim);
+}
+
+int isl_set_is_wrapping(__isl_keep isl_set *set)
+{
+ if (!set)
+ return -1;
+
+ return isl_space_is_wrapping(set->dim);
+}
+
+/* Is the domain of "map" a wrapped relation?
+ */
+int isl_map_domain_is_wrapping(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+
+ return isl_space_domain_is_wrapping(map->dim);
+}
+
+/* Is the range of "map" a wrapped relation?
+ */
+int isl_map_range_is_wrapping(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+
+ return isl_space_range_is_wrapping(map->dim);
+}
+
+__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_wrap(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return (isl_basic_set *)bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__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;
+}
+
+__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset)
+{
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+
+ bset->dim = isl_space_unwrap(bset->dim);
+ if (!bset->dim)
+ goto error;
+
+ bset = isl_basic_set_finalize(bset);
+
+ return (isl_basic_map *)bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+__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;
+}
+
+__isl_give isl_basic_map *isl_basic_map_reset(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type)
+{
+ if (!bmap)
+ return NULL;
+
+ if (!isl_space_is_named_or_nested(bmap->dim, type))
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_reset(bmap->dim, type);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
+ enum isl_dim_type type)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ if (!isl_space_is_named_or_nested(map->dim, type))
+ return map;
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_reset(map->p[i], type);
+ if (!map->p[i])
+ goto error;
+ }
+ map->dim = isl_space_reset(map->dim, type);
+ if (!map->dim)
+ goto error;
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (!bmap->dim->nested[0] && !bmap->dim->nested[1])
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_flatten(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset)
+{
+ return (isl_basic_set *)isl_basic_map_flatten((isl_basic_map *)bset);
+}
+
+__isl_give isl_basic_map *isl_basic_map_flatten_domain(
+ __isl_take isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (!bmap->dim->nested[0])
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_flatten_domain(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_flatten_range(
+ __isl_take isl_basic_map *bmap)
+{
+ if (!bmap)
+ return NULL;
+
+ if (!bmap->dim->nested[1])
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ bmap->dim = isl_space_flatten_range(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__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;
+}
+
+__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set)
+{
+ return (isl_set *)isl_map_flatten((isl_map *)set);
+}
+
+__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set)
+{
+ isl_space *dim, *flat_dim;
+ isl_map *map;
+
+ dim = isl_set_get_space(set);
+ flat_dim = isl_space_flatten(isl_space_copy(dim));
+ map = isl_map_identity(isl_space_join(isl_space_reverse(dim), flat_dim));
+ map = isl_map_intersect_domain(map, set);
+
+ return 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;
+}
+
+__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;
+}
+
+/* Reorder the dimensions of "bmap" according to the given dim_map
+ * and set the dimension specification to "dim".
+ */
+__isl_give isl_basic_map *isl_basic_map_realign(__isl_take isl_basic_map *bmap,
+ __isl_take isl_space *dim, __isl_take struct isl_dim_map *dim_map)
+{
+ isl_basic_map *res;
+ unsigned flags;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap || !dim || !dim_map)
+ goto error;
+
+ flags = bmap->flags;
+ ISL_FL_CLR(flags, ISL_BASIC_MAP_FINAL);
+ ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED);
+ ISL_FL_CLR(flags, ISL_BASIC_MAP_NORMALIZED_DIVS);
+ res = isl_basic_map_alloc_space(dim,
+ bmap->n_div, bmap->n_eq, bmap->n_ineq);
+ res = isl_basic_map_add_constraints_dim_map(res, bmap, dim_map);
+ if (res)
+ res->flags = flags;
+ res = isl_basic_map_finalize(res);
+ return res;
+error:
+ free(dim_map);
+ isl_basic_map_free(bmap);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Reorder the dimensions of "map" according to given reordering.
+ */
+__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
+ __isl_take isl_reordering *r)
+{
+ int i;
+ struct isl_dim_map *dim_map;
+
+ map = isl_map_cow(map);
+ dim_map = isl_dim_map_from_reordering(r);
+ if (!map || !r || !dim_map)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ struct isl_dim_map *dim_map_i;
+
+ dim_map_i = isl_dim_map_extend(dim_map, map->p[i]);
+
+ map->p[i] = isl_basic_map_realign(map->p[i],
+ isl_space_copy(r->dim), dim_map_i);
+
+ if (!map->p[i])
+ goto error;
+ }
+
+ map = isl_map_reset_space(map, isl_space_copy(r->dim));
+
+ isl_reordering_free(r);
+ free(dim_map);
+ return map;
+error:
+ free(dim_map);
+ isl_map_free(map);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
+ __isl_take isl_reordering *r)
+{
+ return (isl_set *)isl_map_realign((isl_map *)set, r);
+}
+
+__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
+ __isl_take isl_space *model)
+{
+ isl_ctx *ctx;
+
+ if (!map || !model)
+ goto error;
+
+ ctx = isl_space_get_ctx(model);
+ if (!isl_space_has_named_params(model))
+ isl_die(ctx, isl_error_invalid,
+ "model has unnamed parameters", goto error);
+ if (!isl_space_has_named_params(map->dim))
+ isl_die(ctx, isl_error_invalid,
+ "relation has unnamed parameters", goto error);
+ if (!isl_space_match(map->dim, isl_dim_param, model, isl_dim_param)) {
+ isl_reordering *exp;
+
+ model = isl_space_drop_dims(model, isl_dim_in,
+ 0, isl_space_dim(model, isl_dim_in));
+ model = isl_space_drop_dims(model, isl_dim_out,
+ 0, isl_space_dim(model, isl_dim_out));
+ exp = isl_parameter_alignment_reordering(map->dim, model);
+ exp = isl_reordering_extend_space(exp, isl_map_get_space(map));
+ map = isl_map_realign(map, exp);
+ }
+
+ isl_space_free(model);
+ return map;
+error:
+ isl_space_free(model);
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
+ __isl_take isl_space *model)
+{
+ return isl_map_align_params(set, model);
+}
+
+/* Align the parameters of "bmap" to those of "model", introducing
+ * additional parameters if needed.
+ */
+__isl_give isl_basic_map *isl_basic_map_align_params(
+ __isl_take isl_basic_map *bmap, __isl_take isl_space *model)
+{
+ isl_ctx *ctx;
+
+ if (!bmap || !model)
+ goto error;
+
+ ctx = isl_space_get_ctx(model);
+ if (!isl_space_has_named_params(model))
+ isl_die(ctx, isl_error_invalid,
+ "model has unnamed parameters", goto error);
+ if (!isl_space_has_named_params(bmap->dim))
+ isl_die(ctx, isl_error_invalid,
+ "relation has unnamed parameters", goto error);
+ if (!isl_space_match(bmap->dim, isl_dim_param, model, isl_dim_param)) {
+ isl_reordering *exp;
+ struct isl_dim_map *dim_map;
+
+ model = isl_space_drop_dims(model, isl_dim_in,
+ 0, isl_space_dim(model, isl_dim_in));
+ model = isl_space_drop_dims(model, isl_dim_out,
+ 0, isl_space_dim(model, isl_dim_out));
+ exp = isl_parameter_alignment_reordering(bmap->dim, model);
+ exp = isl_reordering_extend_space(exp,
+ isl_basic_map_get_space(bmap));
+ dim_map = isl_dim_map_from_reordering(exp);
+ bmap = isl_basic_map_realign(bmap,
+ exp ? isl_space_copy(exp->dim) : NULL,
+ isl_dim_map_extend(dim_map, bmap));
+ isl_reordering_free(exp);
+ free(dim_map);
+ }
+
+ isl_space_free(model);
+ return bmap;
+error:
+ isl_space_free(model);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Align the parameters of "bset" to those of "model", introducing
+ * additional parameters if needed.
+ */
+__isl_give isl_basic_set *isl_basic_set_align_params(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *model)
+{
+ return isl_basic_map_align_params(bset, model);
+}
+
+__isl_give isl_mat *isl_basic_map_equalities_matrix(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5)
+{
+ enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
+ struct isl_mat *mat;
+ int i, j, k;
+ int pos;
+
+ if (!bmap)
+ return NULL;
+ mat = isl_mat_alloc(bmap->ctx, bmap->n_eq,
+ isl_basic_map_total_dim(bmap) + 1);
+ if (!mat)
+ return NULL;
+ for (i = 0; i < bmap->n_eq; ++i)
+ for (j = 0, pos = 0; j < 5; ++j) {
+ int off = isl_basic_map_offset(bmap, c[j]);
+ for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+ isl_int_set(mat->row[i][pos],
+ bmap->eq[i][off + k]);
+ ++pos;
+ }
+ }
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_basic_map_inequalities_matrix(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5)
+{
+ enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
+ struct isl_mat *mat;
+ int i, j, k;
+ int pos;
+
+ if (!bmap)
+ return NULL;
+ mat = isl_mat_alloc(bmap->ctx, bmap->n_ineq,
+ isl_basic_map_total_dim(bmap) + 1);
+ if (!mat)
+ return NULL;
+ for (i = 0; i < bmap->n_ineq; ++i)
+ for (j = 0, pos = 0; j < 5; ++j) {
+ int off = isl_basic_map_offset(bmap, c[j]);
+ for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+ isl_int_set(mat->row[i][pos],
+ bmap->ineq[i][off + k]);
+ ++pos;
+ }
+ }
+
+ return mat;
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
+ __isl_take isl_space *dim,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3,
+ enum isl_dim_type c4, enum isl_dim_type c5)
+{
+ enum isl_dim_type c[5] = { c1, c2, c3, c4, c5 };
+ isl_basic_map *bmap;
+ unsigned total;
+ unsigned extra;
+ int i, j, k, l;
+ int pos;
+
+ if (!dim || !eq || !ineq)
+ goto error;
+
+ if (eq->n_col != ineq->n_col)
+ isl_die(dim->ctx, isl_error_invalid,
+ "equalities and inequalities matrices should have "
+ "same number of columns", goto error);
+
+ total = 1 + isl_space_dim(dim, isl_dim_all);
+
+ if (eq->n_col < total)
+ isl_die(dim->ctx, isl_error_invalid,
+ "number of columns too small", goto error);
+
+ extra = eq->n_col - total;
+
+ bmap = isl_basic_map_alloc_space(isl_space_copy(dim), extra,
+ eq->n_row, ineq->n_row);
+ if (!bmap)
+ goto error;
+ for (i = 0; i < extra; ++i) {
+ k = isl_basic_map_alloc_div(bmap);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(bmap->div[k][0], 0);
+ }
+ for (i = 0; i < eq->n_row; ++i) {
+ l = isl_basic_map_alloc_equality(bmap);
+ if (l < 0)
+ goto error;
+ for (j = 0, pos = 0; j < 5; ++j) {
+ int off = isl_basic_map_offset(bmap, c[j]);
+ for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+ isl_int_set(bmap->eq[l][off + k],
+ eq->row[i][pos]);
+ ++pos;
+ }
+ }
+ }
+ for (i = 0; i < ineq->n_row; ++i) {
+ l = isl_basic_map_alloc_inequality(bmap);
+ if (l < 0)
+ goto error;
+ for (j = 0, pos = 0; j < 5; ++j) {
+ int off = isl_basic_map_offset(bmap, c[j]);
+ for (k = 0; k < isl_basic_map_dim(bmap, c[j]); ++k) {
+ isl_int_set(bmap->ineq[l][off + k],
+ ineq->row[i][pos]);
+ ++pos;
+ }
+ }
+ }
+
+ isl_space_free(dim);
+ isl_mat_free(eq);
+ isl_mat_free(ineq);
+
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_space_free(dim);
+ isl_mat_free(eq);
+ isl_mat_free(ineq);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_basic_set_equalities_matrix(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
+{
+ return isl_basic_map_equalities_matrix((isl_basic_map *)bset,
+ c1, c2, c3, c4, isl_dim_in);
+}
+
+__isl_give isl_mat *isl_basic_set_inequalities_matrix(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
+{
+ return isl_basic_map_inequalities_matrix((isl_basic_map *)bset,
+ c1, c2, c3, c4, isl_dim_in);
+}
+
+__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
+ __isl_take isl_space *dim,
+ __isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+ enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4)
+{
+ return (isl_basic_set*)
+ isl_basic_map_from_constraint_matrices(dim, eq, ineq,
+ c1, c2, c3, c4, isl_dim_in);
+}
+
+int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+
+ return isl_space_can_zip(bmap->dim);
+}
+
+int isl_map_can_zip(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+
+ return isl_space_can_zip(map->dim);
+}
+
+/* Given a basic map (A -> B) -> (C -> D), return the corresponding basic map
+ * (A -> C) -> (B -> D).
+ */
+__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap)
+{
+ unsigned pos;
+ unsigned n1;
+ unsigned n2;
+
+ if (!bmap)
+ return NULL;
+
+ if (!isl_basic_map_can_zip(bmap))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "basic map cannot be zipped", goto error);
+ pos = isl_basic_map_offset(bmap, isl_dim_in) +
+ isl_space_dim(bmap->dim->nested[0], isl_dim_in);
+ n1 = isl_space_dim(bmap->dim->nested[0], isl_dim_out);
+ n2 = isl_space_dim(bmap->dim->nested[1], isl_dim_in);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = isl_basic_map_swap_vars(bmap, pos, n1, n2);
+ if (!bmap)
+ return NULL;
+ bmap->dim = isl_space_zip(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Given a map (A -> B) -> (C -> D), return the corresponding map
+ * (A -> C) -> (B -> D).
+ */
+__isl_give isl_map *isl_map_zip(__isl_take isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ if (!isl_map_can_zip(map))
+ isl_die(map->ctx, isl_error_invalid, "map cannot be zipped",
+ goto error);
+
+ map = isl_map_cow(map);
+ if (!map)
+ return NULL;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_zip(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+
+ map->dim = isl_space_zip(map->dim);
+ if (!map->dim)
+ goto error;
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Can we apply isl_basic_map_curry to "bmap"?
+ * That is, does it have a nested relation in its domain?
+ */
+int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+
+ return isl_space_can_curry(bmap->dim);
+}
+
+/* Can we apply isl_map_curry to "map"?
+ * That is, does it have a nested relation in its domain?
+ */
+int isl_map_can_curry(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+
+ return isl_space_can_curry(map->dim);
+}
+
+/* Given a basic map (A -> B) -> C, return the corresponding basic map
+ * A -> (B -> C).
+ */
+__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap)
+{
+
+ if (!bmap)
+ return NULL;
+
+ if (!isl_basic_map_can_curry(bmap))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "basic map cannot be curried", goto error);
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ bmap->dim = isl_space_curry(bmap->dim);
+ if (!bmap->dim)
+ goto error;
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Given a map (A -> B) -> C, return the corresponding map
+ * A -> (B -> C).
+ */
+__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);
+
+ map = isl_map_cow(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;
+ }
+
+ map->dim = isl_space_curry(map->dim);
+ if (!map->dim)
+ goto error;
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Can we apply isl_basic_map_uncurry to "bmap"?
+ * That is, does it have a nested relation in its domain?
+ */
+int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+
+ return isl_space_can_uncurry(bmap->dim);
+}
+
+/* Can we apply isl_map_uncurry to "map"?
+ * That is, does it have a nested relation in its domain?
+ */
+int isl_map_can_uncurry(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+
+ return isl_space_can_uncurry(map->dim);
+}
+
+/* Given a basic map A -> (B -> C), return the corresponding basic map
+ * (A -> B) -> C.
+ */
+__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap)
+{
+
+ if (!bmap)
+ return NULL;
+
+ if (!isl_basic_map_can_uncurry(bmap))
+ isl_die(bmap->ctx, isl_error_invalid,
+ "basic map cannot be uncurried",
+ return isl_basic_map_free(bmap));
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ bmap->dim = isl_space_uncurry(bmap->dim);
+ if (!bmap->dim)
+ return isl_basic_map_free(bmap);
+ return bmap;
+}
+
+/* Given a map A -> (B -> C), return the corresponding map
+ * (A -> B) -> C.
+ */
+__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;
+}
+
+/* Construct a basic map mapping the domain of the affine expression
+ * to a one-dimensional range prescribed by the affine expression.
+ */
+__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff)
+{
+ int k;
+ int pos;
+ isl_local_space *ls;
+ isl_basic_map *bmap;
+
+ if (!aff)
+ return NULL;
+
+ ls = isl_aff_get_local_space(aff);
+ bmap = isl_basic_map_from_local_space(ls);
+ bmap = isl_basic_map_extend_constraints(bmap, 1, 0);
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+
+ pos = isl_basic_map_offset(bmap, isl_dim_out);
+ isl_seq_cpy(bmap->eq[k], aff->v->el + 1, pos);
+ isl_int_neg(bmap->eq[k][pos], aff->v->el[0]);
+ isl_seq_cpy(bmap->eq[k] + pos + 1, aff->v->el + 1 + pos,
+ aff->v->size - (pos + 1));
+
+ isl_aff_free(aff);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_aff_free(aff);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Construct a map mapping the domain of the affine expression
+ * to a one-dimensional range prescribed by the affine expression.
+ */
+__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff)
+{
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_from_aff(aff);
+ return isl_map_from_basic_map(bmap);
+}
+
+/* Construct a basic map mapping the domain the multi-affine expression
+ * to its range, with each dimension in the range equated to the
+ * corresponding affine expression.
+ */
+__isl_give isl_basic_map *isl_basic_map_from_multi_aff(
+ __isl_take isl_multi_aff *maff)
+{
+ int i;
+ isl_space *space;
+ isl_basic_map *bmap;
+
+ if (!maff)
+ return NULL;
+
+ if (isl_space_dim(maff->space, isl_dim_out) != maff->n)
+ isl_die(isl_multi_aff_get_ctx(maff), isl_error_internal,
+ "invalid space", goto error);
+
+ space = isl_space_domain(isl_multi_aff_get_space(maff));
+ bmap = isl_basic_map_universe(isl_space_from_domain(space));
+
+ for (i = 0; i < maff->n; ++i) {
+ isl_aff *aff;
+ isl_basic_map *bmap_i;
+
+ aff = isl_aff_copy(maff->p[i]);
+ bmap_i = isl_basic_map_from_aff(aff);
+
+ bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
+ }
+
+ bmap = isl_basic_map_reset_space(bmap, isl_multi_aff_get_space(maff));
+
+ isl_multi_aff_free(maff);
+ return bmap;
+error:
+ isl_multi_aff_free(maff);
+ return NULL;
+}
+
+/* Construct a map mapping the domain the multi-affine expression
+ * to its range, with each dimension in the range equated to the
+ * corresponding affine expression.
+ */
+__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff)
+{
+ isl_basic_map *bmap;
+
+ bmap = isl_basic_map_from_multi_aff(maff);
+ return isl_map_from_basic_map(bmap);
+}
+
+/* Construct a basic map mapping a domain in the given space to
+ * to an n-dimensional range, with n the number of elements in the list,
+ * where each coordinate in the range is prescribed by the
+ * corresponding affine expression.
+ * The domains of all affine expressions in the list are assumed to match
+ * domain_dim.
+ */
+__isl_give isl_basic_map *isl_basic_map_from_aff_list(
+ __isl_take isl_space *domain_dim, __isl_take isl_aff_list *list)
+{
+ int i;
+ isl_space *dim;
+ isl_basic_map *bmap;
+
+ if (!list)
+ return NULL;
+
+ dim = isl_space_from_domain(domain_dim);
+ bmap = isl_basic_map_universe(dim);
+
+ for (i = 0; i < list->n; ++i) {
+ isl_aff *aff;
+ isl_basic_map *bmap_i;
+
+ aff = isl_aff_copy(list->p[i]);
+ bmap_i = isl_basic_map_from_aff(aff);
+
+ bmap = isl_basic_map_flat_range_product(bmap, bmap_i);
+ }
+
+ isl_aff_list_free(list);
+ return bmap;
+}
+
+__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ return isl_map_equate(set, type1, pos1, type2, pos2);
+}
+
+/* Construct a basic map where the given dimensions are equal to each other.
+ */
+static __isl_give isl_basic_map *equator(__isl_take isl_space *space,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *bmap = NULL;
+ int i;
+
+ if (!space)
+ return NULL;
+
+ if (pos1 >= isl_space_dim(space, type1))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "index out of bounds", goto error);
+ if (pos2 >= isl_space_dim(space, type2))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ if (type1 == type2 && pos1 == pos2)
+ return isl_basic_map_universe(space);
+
+ bmap = isl_basic_map_alloc_space(isl_space_copy(space), 0, 1, 0);
+ i = isl_basic_map_alloc_equality(bmap);
+ if (i < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+ pos1 += isl_basic_map_offset(bmap, type1);
+ pos2 += isl_basic_map_offset(bmap, type2);
+ isl_int_set_si(bmap->eq[i][pos1], -1);
+ isl_int_set_si(bmap->eq[i][pos2], 1);
+ bmap = isl_basic_map_finalize(bmap);
+ isl_space_free(space);
+ return bmap;
+error:
+ isl_space_free(space);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraint imposing that the given two dimensions are equal.
+ */
+__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *eq;
+
+ eq = equator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
+
+ bmap = isl_basic_map_intersect(bmap, eq);
+
+ return bmap;
+}
+
+/* Add a constraint imposing that the given two dimensions are equal.
+ */
+__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *bmap;
+
+ bmap = equator(isl_map_get_space(map), type1, pos1, type2, pos2);
+
+ map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+ return map;
+}
+
+/* Add a constraint imposing that the given two dimensions have opposite values.
+ */
+__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *bmap = NULL;
+ int i;
+
+ if (!map)
+ return NULL;
+
+ if (pos1 >= isl_map_dim(map, type1))
+ isl_die(map->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+ if (pos2 >= isl_map_dim(map, type2))
+ isl_die(map->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+
+ bmap = isl_basic_map_alloc_space(isl_map_get_space(map), 0, 1, 0);
+ i = isl_basic_map_alloc_equality(bmap);
+ if (i < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[i], 1 + isl_basic_map_total_dim(bmap));
+ pos1 += isl_basic_map_offset(bmap, type1);
+ pos2 += isl_basic_map_offset(bmap, type2);
+ isl_int_set_si(bmap->eq[i][pos1], 1);
+ isl_int_set_si(bmap->eq[i][pos2], 1);
+ bmap = isl_basic_map_finalize(bmap);
+
+ map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+ return map;
+error:
+ isl_basic_map_free(bmap);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Construct a constraint imposing that the value of the first dimension is
+ * greater than or equal to that of the second.
+ */
+static __isl_give isl_constraint *constraint_order_ge(
+ __isl_take isl_space *space, enum isl_dim_type type1, int pos1,
+ enum isl_dim_type type2, int pos2)
+{
+ isl_constraint *c;
+
+ if (!space)
+ return NULL;
+
+ c = isl_inequality_alloc(isl_local_space_from_space(space));
+
+ if (pos1 >= isl_constraint_dim(c, type1))
+ isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
+ "index out of bounds", return isl_constraint_free(c));
+ if (pos2 >= isl_constraint_dim(c, type2))
+ isl_die(isl_constraint_get_ctx(c), isl_error_invalid,
+ "index out of bounds", return isl_constraint_free(c));
+
+ if (type1 == type2 && pos1 == pos2)
+ return c;
+
+ c = isl_constraint_set_coefficient_si(c, type1, pos1, 1);
+ c = isl_constraint_set_coefficient_si(c, type2, pos2, -1);
+
+ return c;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * greater than or equal to that of the second.
+ */
+__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_constraint *c;
+ isl_space *space;
+
+ if (type1 == type2 && pos1 == pos2)
+ return bmap;
+ space = isl_basic_map_get_space(bmap);
+ c = constraint_order_ge(space, type1, pos1, type2, pos2);
+ bmap = isl_basic_map_add_constraint(bmap, c);
+
+ return bmap;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * greater than or equal to that of the second.
+ */
+__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_constraint *c;
+ isl_space *space;
+
+ if (type1 == type2 && pos1 == pos2)
+ return map;
+ space = isl_map_get_space(map);
+ c = constraint_order_ge(space, type1, pos1, type2, pos2);
+ map = isl_map_add_constraint(map, c);
+
+ return map;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * less than or equal to that of the second.
+ */
+__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ return isl_map_order_ge(map, type2, pos2, type1, pos1);
+}
+
+/* Construct a basic map where the value of the first dimension is
+ * greater than that of the second.
+ */
+static __isl_give isl_basic_map *greator(__isl_take isl_space *space,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *bmap = NULL;
+ int i;
+
+ if (!space)
+ return NULL;
+
+ if (pos1 >= isl_space_dim(space, type1))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "index out of bounds", goto error);
+ if (pos2 >= isl_space_dim(space, type2))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ if (type1 == type2 && pos1 == pos2)
+ return isl_basic_map_empty(space);
+
+ bmap = isl_basic_map_alloc_space(space, 0, 0, 1);
+ i = isl_basic_map_alloc_inequality(bmap);
+ if (i < 0)
+ return isl_basic_map_free(bmap);
+ isl_seq_clr(bmap->ineq[i], 1 + isl_basic_map_total_dim(bmap));
+ pos1 += isl_basic_map_offset(bmap, type1);
+ pos2 += isl_basic_map_offset(bmap, type2);
+ isl_int_set_si(bmap->ineq[i][pos1], 1);
+ isl_int_set_si(bmap->ineq[i][pos2], -1);
+ isl_int_set_si(bmap->ineq[i][0], -1);
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_space_free(space);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * greater than that of the second.
+ */
+__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *gt;
+
+ gt = greator(isl_basic_map_get_space(bmap), type1, pos1, type2, pos2);
+
+ bmap = isl_basic_map_intersect(bmap, gt);
+
+ return bmap;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * greater than that of the second.
+ */
+__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ isl_basic_map *bmap;
+
+ bmap = greator(isl_map_get_space(map), type1, pos1, type2, pos2);
+
+ map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+ return map;
+}
+
+/* Add a constraint imposing that the value of the first dimension is
+ * smaller than that of the second.
+ */
+__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
+ enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2)
+{
+ return isl_map_order_gt(map, type2, pos2, type1, pos1);
+}
+
+__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
+ int pos)
+{
+ isl_aff *div;
+ isl_local_space *ls;
+
+ if (!bmap)
+ return NULL;
+
+ if (!isl_basic_map_divs_known(bmap))
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "some divs are unknown", return NULL);
+
+ ls = isl_basic_map_get_local_space(bmap);
+ div = isl_local_space_get_div(ls, pos);
+ isl_local_space_free(ls);
+
+ return div;
+}
+
+__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
+ int pos)
+{
+ return isl_basic_map_get_div(bset, pos);
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "bset".
+ *
+ * Let i be the dimension to replace and let "subs" be of the form
+ *
+ * f/d
+ *
+ * Any integer division with a non-zero coefficient for i,
+ *
+ * floor((a i + g)/m)
+ *
+ * is replaced by
+ *
+ * floor((a f + d g)/(m d))
+ *
+ * Constraints of the form
+ *
+ * a i + g
+ *
+ * are replaced by
+ *
+ * a f + d g
+ *
+ * We currently require that "subs" is an integral expression.
+ * Handling rational expressions may require us to add stride constraints
+ * as we do in isl_basic_set_preimage_multi_aff.
+ */
+__isl_give isl_basic_set *isl_basic_set_substitute(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
+{
+ int i;
+ isl_int v;
+ isl_ctx *ctx;
+
+ if (bset && isl_basic_set_plain_is_empty(bset))
+ return bset;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset || !subs)
+ goto error;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ if (!isl_space_is_equal(bset->dim, subs->ls->dim))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", goto error);
+ if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+ isl_die(ctx, isl_error_unsupported,
+ "cannot handle divs yet", goto error);
+ if (!isl_int_is_one(subs->v->el[0]))
+ isl_die(ctx, isl_error_invalid,
+ "can only substitute integer expressions", goto error);
+
+ pos += isl_basic_set_offset(bset, type);
+
+ isl_int_init(v);
+
+ for (i = 0; i < bset->n_eq; ++i) {
+ if (isl_int_is_zero(bset->eq[i][pos]))
+ continue;
+ isl_int_set(v, bset->eq[i][pos]);
+ isl_int_set_si(bset->eq[i][pos], 0);
+ isl_seq_combine(bset->eq[i], subs->v->el[0], bset->eq[i],
+ v, subs->v->el + 1, subs->v->size - 1);
+ }
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_int_is_zero(bset->ineq[i][pos]))
+ continue;
+ isl_int_set(v, bset->ineq[i][pos]);
+ isl_int_set_si(bset->ineq[i][pos], 0);
+ isl_seq_combine(bset->ineq[i], subs->v->el[0], bset->ineq[i],
+ v, subs->v->el + 1, subs->v->size - 1);
+ }
+
+ for (i = 0; i < bset->n_div; ++i) {
+ if (isl_int_is_zero(bset->div[i][1 + pos]))
+ continue;
+ isl_int_set(v, bset->div[i][1 + pos]);
+ isl_int_set_si(bset->div[i][1 + pos], 0);
+ isl_seq_combine(bset->div[i] + 1,
+ subs->v->el[0], bset->div[i] + 1,
+ v, subs->v->el + 1, subs->v->size - 1);
+ isl_int_mul(bset->div[i][0], bset->div[i][0], subs->v->el[0]);
+ }
+
+ isl_int_clear(v);
+
+ bset = isl_basic_set_simplify(bset);
+ return isl_basic_set_finalize(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "set".
+ */
+__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
+{
+ int i;
+
+ if (set && isl_set_plain_is_empty(set))
+ return set;
+
+ set = isl_set_cow(set);
+ if (!set || !subs)
+ goto error;
+
+ for (i = set->n - 1; i >= 0; --i) {
+ set->p[i] = isl_basic_set_substitute(set->p[i], type, pos, subs);
+ if (remove_if_empty(set, i) < 0)
+ goto error;
+ }
+
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Check if the range of "ma" is compatible with the domain or range
+ * (depending on "type") of "bmap".
+ * Return -1 if anything is wrong.
+ */
+static int check_basic_map_compatible_range_multi_aff(
+ __isl_keep isl_basic_map *bmap, enum isl_dim_type type,
+ __isl_keep isl_multi_aff *ma)
+{
+ int m;
+ isl_space *ma_space;
+
+ ma_space = isl_multi_aff_get_space(ma);
+
+ m = isl_space_match(bmap->dim, isl_dim_param, ma_space, isl_dim_param);
+ if (m < 0)
+ goto error;
+ if (!m)
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "parameters don't match", goto error);
+ m = isl_space_tuple_is_equal(bmap->dim, type, ma_space, isl_dim_out);
+ if (m < 0)
+ goto error;
+ if (!m)
+ isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ isl_space_free(ma_space);
+ return m;
+error:
+ isl_space_free(ma_space);
+ return -1;
+}
+
+/* Copy the divs from "ma" to "bmap", adding zeros for the "n_before"
+ * coefficients before the transformed range of dimensions,
+ * the "n_after" coefficients after the transformed range of dimensions
+ * and the coefficients of the other divs in "bmap".
+ */
+static int set_ma_divs(__isl_keep isl_basic_map *bmap,
+ __isl_keep isl_multi_aff *ma, int n_before, int n_after, int n_div)
+{
+ int i;
+ int n_param;
+ int n_set;
+ isl_local_space *ls;
+
+ if (n_div == 0)
+ return 0;
+
+ ls = isl_aff_get_domain_local_space(ma->p[0]);
+ if (!ls)
+ return -1;
+
+ n_param = isl_local_space_dim(ls, isl_dim_param);
+ n_set = isl_local_space_dim(ls, isl_dim_set);
+ for (i = 0; i < n_div; ++i) {
+ int o_bmap = 0, o_ls = 0;
+
+ isl_seq_cpy(bmap->div[i], ls->div->row[i], 1 + 1 + n_param);
+ o_bmap += 1 + 1 + n_param;
+ o_ls += 1 + 1 + n_param;
+ isl_seq_clr(bmap->div[i] + o_bmap, n_before);
+ o_bmap += n_before;
+ isl_seq_cpy(bmap->div[i] + o_bmap,
+ ls->div->row[i] + o_ls, n_set);
+ o_bmap += n_set;
+ o_ls += n_set;
+ isl_seq_clr(bmap->div[i] + o_bmap, n_after);
+ o_bmap += n_after;
+ isl_seq_cpy(bmap->div[i] + o_bmap,
+ ls->div->row[i] + o_ls, n_div);
+ o_bmap += n_div;
+ o_ls += n_div;
+ isl_seq_clr(bmap->div[i] + o_bmap, bmap->n_div - n_div);
+ if (isl_basic_set_add_div_constraints(bmap, i) < 0)
+ goto error;
+ }
+
+ isl_local_space_free(ls);
+ return 0;
+error:
+ isl_local_space_free(ls);
+ return -1;
+}
+
+/* How many stride constraints does "ma" enforce?
+ * That is, how many of the affine expressions have a denominator
+ * different from one?
+ */
+static int multi_aff_strides(__isl_keep isl_multi_aff *ma)
+{
+ int i;
+ int strides = 0;
+
+ for (i = 0; i < ma->n; ++i)
+ if (!isl_int_is_one(ma->p[i]->v->el[0]))
+ strides++;
+
+ return strides;
+}
+
+/* For each affine expression in ma of the form
+ *
+ * x_i = (f_i y + h_i)/m_i
+ *
+ * with m_i different from one, add a constraint to "bmap"
+ * of the form
+ *
+ * f_i y + h_i = m_i alpha_i
+ *
+ * with alpha_i an additional existentially quantified variable.
+ */
+static __isl_give isl_basic_map *add_ma_strides(
+ __isl_take isl_basic_map *bmap, __isl_keep isl_multi_aff *ma,
+ int n_before, int n_after)
+{
+ int i, k;
+ int div;
+ int total;
+ int n_param;
+ int n_in;
+ int n_div;
+
+ total = isl_basic_map_total_dim(bmap);
+ n_param = isl_multi_aff_dim(ma, isl_dim_param);
+ n_in = isl_multi_aff_dim(ma, isl_dim_in);
+ n_div = isl_multi_aff_dim(ma, isl_dim_div);
+ for (i = 0; i < ma->n; ++i) {
+ int o_bmap = 0, o_ma = 1;
+
+ if (isl_int_is_one(ma->p[i]->v->el[0]))
+ continue;
+ div = isl_basic_map_alloc_div(bmap);
+ k = isl_basic_map_alloc_equality(bmap);
+ if (div < 0 || k < 0)
+ goto error;
+ isl_int_set_si(bmap->div[div][0], 0);
+ isl_seq_cpy(bmap->eq[k] + o_bmap,
+ ma->p[i]->v->el + o_ma, 1 + n_param);
+ o_bmap += 1 + n_param;
+ o_ma += 1 + n_param;
+ isl_seq_clr(bmap->eq[k] + o_bmap, n_before);
+ o_bmap += n_before;
+ isl_seq_cpy(bmap->eq[k] + o_bmap,
+ ma->p[i]->v->el + o_ma, n_in);
+ o_bmap += n_in;
+ o_ma += n_in;
+ isl_seq_clr(bmap->eq[k] + o_bmap, n_after);
+ o_bmap += n_after;
+ isl_seq_cpy(bmap->eq[k] + o_bmap,
+ ma->p[i]->v->el + o_ma, n_div);
+ o_bmap += n_div;
+ o_ma += n_div;
+ isl_seq_clr(bmap->eq[k] + o_bmap, 1 + total - o_bmap);
+ isl_int_neg(bmap->eq[k][1 + total], ma->p[i]->v->el[0]);
+ total++;
+ }
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Replace the domain or range space (depending on "type) of "space" by "set".
+ */
+static __isl_give isl_space *isl_space_set(__isl_take isl_space *space,
+ enum isl_dim_type type, __isl_take isl_space *set)
+{
+ if (type == isl_dim_in) {
+ space = isl_space_range(space);
+ space = isl_space_map_from_domain_and_range(set, space);
+ } else {
+ space = isl_space_domain(space);
+ space = isl_space_map_from_domain_and_range(space, set);
+ }
+
+ return space;
+}
+
+/* Compute the preimage of the domain or range (depending on "type")
+ * of "bmap" under the function represented by "ma".
+ * In other words, plug in "ma" in the domain or range of "bmap".
+ * The result is a basic map that lives in the same space as "bmap"
+ * except that the domain or range has been replaced by
+ * the domain space of "ma".
+ *
+ * If bmap is represented by
+ *
+ * A(p) + S u + B x + T v + C(divs) >= 0,
+ *
+ * where u and x are input and output dimensions if type == isl_dim_out
+ * while x and v are input and output dimensions if type == isl_dim_in,
+ * and ma is represented by
+ *
+ * x = D(p) + F(y) + G(divs')
+ *
+ * then the result is
+ *
+ * A(p) + B D(p) + S u + B F(y) + T v + B G(divs') + C(divs) >= 0
+ *
+ * The divs in the input set are similarly adjusted.
+ * In particular
+ *
+ * floor((a_i(p) + s u + b_i x + t v + c_i(divs))/n_i)
+ *
+ * becomes
+ *
+ * floor((a_i(p) + b_i D(p) + s u + b_i F(y) + t v +
+ * B_i G(divs') + c_i(divs))/n_i)
+ *
+ * If bmap is not a rational map and if F(y) involves any denominators
+ *
+ * x_i = (f_i y + h_i)/m_i
+ *
+ * then additional constraints are added to ensure that we only
+ * map back integer points. That is we enforce
+ *
+ * f_i y + h_i = m_i alpha_i
+ *
+ * with alpha_i an additional existentially quantified variable.
+ *
+ * We first copy over the divs from "ma".
+ * Then we add the modified constraints and divs from "bmap".
+ * Finally, we add the stride constraints, if needed.
+ */
+__isl_give isl_basic_map *isl_basic_map_preimage_multi_aff(
+ __isl_take isl_basic_map *bmap, enum isl_dim_type type,
+ __isl_take isl_multi_aff *ma)
+{
+ int i, k;
+ isl_space *space;
+ isl_basic_map *res = NULL;
+ int n_before, n_after, n_div_bmap, n_div_ma;
+ isl_int f, c1, c2, g;
+ int rational, strides;
+
+ isl_int_init(f);
+ isl_int_init(c1);
+ isl_int_init(c2);
+ isl_int_init(g);
+
+ ma = isl_multi_aff_align_divs(ma);
+ if (!bmap || !ma)
+ goto error;
+ if (check_basic_map_compatible_range_multi_aff(bmap, type, ma) < 0)
+ goto error;
+
+ if (type == isl_dim_in) {
+ n_before = 0;
+ n_after = isl_basic_map_dim(bmap, isl_dim_out);
+ } else {
+ n_before = isl_basic_map_dim(bmap, isl_dim_in);
+ n_after = 0;
+ }
+ n_div_bmap = isl_basic_map_dim(bmap, isl_dim_div);
+ n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
+
+ space = isl_multi_aff_get_domain_space(ma);
+ space = isl_space_set(isl_basic_map_get_space(bmap), type, space);
+ rational = isl_basic_map_is_rational(bmap);
+ strides = rational ? 0 : multi_aff_strides(ma);
+ res = isl_basic_map_alloc_space(space, n_div_ma + n_div_bmap + strides,
+ bmap->n_eq + strides, bmap->n_ineq + 2 * n_div_ma);
+ if (rational)
+ res = isl_basic_map_set_rational(res);
+
+ for (i = 0; i < n_div_ma + n_div_bmap; ++i)
+ if (isl_basic_map_alloc_div(res) < 0)
+ goto error;
+
+ if (set_ma_divs(res, ma, n_before, n_after, n_div_ma) < 0)
+ goto error;
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ k = isl_basic_map_alloc_equality(res);
+ if (k < 0)
+ goto error;
+ isl_seq_preimage(res->eq[k], bmap->eq[i], ma, n_before,
+ n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
+ }
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ k = isl_basic_map_alloc_inequality(res);
+ if (k < 0)
+ goto error;
+ isl_seq_preimage(res->ineq[k], bmap->ineq[i], ma, n_before,
+ n_after, n_div_ma, n_div_bmap, f, c1, c2, g, 0);
+ }
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0])) {
+ isl_int_set_si(res->div[n_div_ma + i][0], 0);
+ continue;
+ }
+ isl_seq_preimage(res->div[n_div_ma + i], bmap->div[i], ma,
+ n_before, n_after, n_div_ma, n_div_bmap,
+ f, c1, c2, g, 1);
+ }
+
+ if (strides)
+ res = add_ma_strides(res, ma, n_before, n_after);
+
+ isl_int_clear(f);
+ isl_int_clear(c1);
+ isl_int_clear(c2);
+ isl_int_clear(g);
+ isl_basic_map_free(bmap);
+ isl_multi_aff_free(ma);
+ res = isl_basic_set_simplify(res);
+ return isl_basic_map_finalize(res);
+error:
+ isl_int_clear(f);
+ isl_int_clear(c1);
+ isl_int_clear(c2);
+ isl_int_clear(g);
+ isl_basic_map_free(bmap);
+ isl_multi_aff_free(ma);
+ isl_basic_map_free(res);
+ return NULL;
+}
+
+/* Compute the preimage of "bset" under the function represented by "ma".
+ * In other words, plug in "ma" in "bset". The result is a basic set
+ * that lives in the domain space of "ma".
+ */
+__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
+ __isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma)
+{
+ return isl_basic_map_preimage_multi_aff(bset, isl_dim_set, ma);
+}
+
+/* Compute the preimage of the domain of "bmap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the domain of "bmap".
+ * The result is a basic map that lives in the same space as "bmap"
+ * except that the domain has been replaced by the domain space of "ma".
+ */
+__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
+{
+ return isl_basic_map_preimage_multi_aff(bmap, isl_dim_in, ma);
+}
+
+/* Compute the preimage of the range of "bmap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the range of "bmap".
+ * The result is a basic map that lives in the same space as "bmap"
+ * except that the range has been replaced by the domain space of "ma".
+ */
+__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma)
+{
+ return isl_basic_map_preimage_multi_aff(bmap, isl_dim_out, ma);
+}
+
+/* Check if the range of "ma" is compatible with the domain or range
+ * (depending on "type") of "map".
+ * Return -1 if anything is wrong.
+ */
+static int check_map_compatible_range_multi_aff(
+ __isl_keep isl_map *map, enum isl_dim_type type,
+ __isl_keep isl_multi_aff *ma)
+{
+ int m;
+ isl_space *ma_space;
+
+ ma_space = isl_multi_aff_get_space(ma);
+ m = isl_space_tuple_is_equal(map->dim, type, ma_space, isl_dim_out);
+ isl_space_free(ma_space);
+ if (m >= 0 && !m)
+ isl_die(isl_map_get_ctx(map), isl_error_invalid,
+ "spaces don't match", return -1);
+ return m;
+}
+
+/* Compute the preimage of the domain or range (depending on "type")
+ * of "map" under the function represented by "ma".
+ * In other words, plug in "ma" in the domain or range of "map".
+ * The result is a map that lives in the same space as "map"
+ * except that the domain or range has been replaced by
+ * the domain space of "ma".
+ *
+ * The parameters are assumed to have been aligned.
+ */
+static __isl_give isl_map *map_preimage_multi_aff(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_multi_aff *ma)
+{
+ int i;
+ isl_space *space;
+
+ map = isl_map_cow(map);
+ ma = isl_multi_aff_align_divs(ma);
+ if (!map || !ma)
+ goto error;
+ if (check_map_compatible_range_multi_aff(map, type, ma) < 0)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_preimage_multi_aff(map->p[i], type,
+ isl_multi_aff_copy(ma));
+ if (!map->p[i])
+ goto error;
+ }
+
+ space = isl_multi_aff_get_domain_space(ma);
+ space = isl_space_set(isl_map_get_space(map), type, space);
+
+ isl_space_free(map->dim);
+ map->dim = space;
+ if (!map->dim)
+ goto error;
+
+ isl_multi_aff_free(ma);
+ if (map->n > 1)
+ ISL_F_CLR(map, ISL_MAP_DISJOINT);
+ ISL_F_CLR(map, ISL_SET_NORMALIZED);
+ return map;
+error:
+ isl_multi_aff_free(ma);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Compute the preimage of the domain or range (depending on "type")
+ * of "map" under the function represented by "ma".
+ * In other words, plug in "ma" in the domain or range of "map".
+ * The result is a map that lives in the same space as "map"
+ * except that the domain or range has been replaced by
+ * the domain space of "ma".
+ */
+__isl_give isl_map *isl_map_preimage_multi_aff(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_multi_aff *ma)
+{
+ if (!map || !ma)
+ goto error;
+
+ if (isl_space_match(map->dim, isl_dim_param, ma->space, isl_dim_param))
+ return map_preimage_multi_aff(map, type, ma);
+
+ if (!isl_space_has_named_params(map->dim) ||
+ !isl_space_has_named_params(ma->space))
+ isl_die(map->ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ map = isl_map_align_params(map, isl_multi_aff_get_space(ma));
+ ma = isl_multi_aff_align_params(ma, isl_map_get_space(map));
+
+ return map_preimage_multi_aff(map, type, ma);
+error:
+ isl_multi_aff_free(ma);
+ return isl_map_free(map);
+}
+
+/* Compute the preimage of "set" under the function represented by "ma".
+ * In other words, plug in "ma" in "set". The result is a set
+ * that lives in the domain space of "ma".
+ */
+__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
+ __isl_take isl_multi_aff *ma)
+{
+ return isl_map_preimage_multi_aff(set, isl_dim_set, ma);
+}
+
+/* Compute the preimage of the domain of "map" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the domain of "map".
+ * The result is a map that lives in the same space as "map"
+ * except that the domain has been replaced by the domain space of "ma".
+ */
+__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma)
+{
+ return isl_map_preimage_multi_aff(map, isl_dim_in, ma);
+}
+
+/* Compute the preimage of the range of "map" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the range of "map".
+ * The result is a map that lives in the same space as "map"
+ * except that the range has been replaced by the domain space of "ma".
+ */
+__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
+ __isl_take isl_multi_aff *ma)
+{
+ return isl_map_preimage_multi_aff(map, isl_dim_out, ma);
+}
+
+/* Compute the preimage of "map" under the function represented by "pma".
+ * In other words, plug in "pma" in the domain or range of "map".
+ * The result is a map that lives in the same space as "map",
+ * except that the space of type "type" has been replaced by
+ * the domain space of "pma".
+ *
+ * The parameters of "map" and "pma" are assumed to have been aligned.
+ */
+static __isl_give isl_map *isl_map_preimage_pw_multi_aff_aligned(
+ __isl_take isl_map *map, enum isl_dim_type type,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ int i;
+ isl_map *res;
+
+ if (!pma)
+ goto error;
+
+ if (pma->n == 0) {
+ isl_pw_multi_aff_free(pma);
+ res = isl_map_empty(isl_map_get_space(map));
+ isl_map_free(map);
+ return res;
+ }
+
+ res = isl_map_preimage_multi_aff(isl_map_copy(map), type,
+ isl_multi_aff_copy(pma->p[0].maff));
+ if (type == isl_dim_in)
+ res = isl_map_intersect_domain(res,
+ isl_map_copy(pma->p[0].set));
+ else
+ res = isl_map_intersect_range(res,
+ isl_map_copy(pma->p[0].set));
+
+ for (i = 1; i < pma->n; ++i) {
+ isl_map *res_i;
+
+ res_i = isl_map_preimage_multi_aff(isl_map_copy(map), type,
+ isl_multi_aff_copy(pma->p[i].maff));
+ if (type == isl_dim_in)
+ res_i = isl_map_intersect_domain(res_i,
+ isl_map_copy(pma->p[i].set));
+ else
+ res_i = isl_map_intersect_range(res_i,
+ isl_map_copy(pma->p[i].set));
+ res = isl_map_union(res, res_i);
+ }
+
+ isl_pw_multi_aff_free(pma);
+ isl_map_free(map);
+ return res;
+error:
+ isl_pw_multi_aff_free(pma);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Compute the preimage of "map" under the function represented by "pma".
+ * In other words, plug in "pma" in the domain or range of "map".
+ * The result is a map that lives in the same space as "map",
+ * except that the space of type "type" has been replaced by
+ * the domain space of "pma".
+ */
+__isl_give isl_map *isl_map_preimage_pw_multi_aff(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_pw_multi_aff *pma)
+{
+ if (!map || !pma)
+ goto error;
+
+ if (isl_space_match(map->dim, isl_dim_param, pma->dim, isl_dim_param))
+ return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
+
+ if (!isl_space_has_named_params(map->dim) ||
+ !isl_space_has_named_params(pma->dim))
+ isl_die(map->ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ map = isl_map_align_params(map, isl_pw_multi_aff_get_space(pma));
+ pma = isl_pw_multi_aff_align_params(pma, isl_map_get_space(map));
+
+ return isl_map_preimage_pw_multi_aff_aligned(map, type, pma);
+error:
+ isl_pw_multi_aff_free(pma);
+ return isl_map_free(map);
+}
+
+/* Compute the preimage of "set" under the function represented by "pma".
+ * In other words, plug in "pma" in "set". The result is a set
+ * that lives in the domain space of "pma".
+ */
+__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ return isl_map_preimage_pw_multi_aff(set, isl_dim_set, pma);
+}
+
+/* Compute the preimage of the domain of "map" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the domain of "map".
+ * The result is a map that lives in the same space as "map",
+ * except that domain space has been replaced by the domain space of "pma".
+ */
+__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
+{
+ return isl_map_preimage_pw_multi_aff(map, isl_dim_in, pma);
+}
+
+/* Compute the preimage of the range of "map" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the range of "map".
+ * The result is a map that lives in the same space as "map",
+ * except that range space has been replaced by the domain space of "pma".
+ */
+__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
+ __isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma)
+{
+ return isl_map_preimage_pw_multi_aff(map, isl_dim_out, pma);
+}
+
+/* Compute the preimage of "map" under the function represented by "mpa".
+ * In other words, plug in "mpa" in the domain or range of "map".
+ * The result is a map that lives in the same space as "map",
+ * except that the space of type "type" has been replaced by
+ * the domain space of "mpa".
+ *
+ * If the map does not involve any constraints that refer to the
+ * dimensions of the substituted space, then the only possible
+ * effect of "mpa" on the map is to map the space to a different space.
+ * We create a separate isl_multi_aff to effectuate this change
+ * in order to avoid spurious splitting of the map along the pieces
+ * of "mpa".
+ */
+__isl_give isl_map *isl_map_preimage_multi_pw_aff(__isl_take isl_map *map,
+ enum isl_dim_type type, __isl_take isl_multi_pw_aff *mpa)
+{
+ int n;
+ isl_pw_multi_aff *pma;
+
+ if (!map || !mpa)
+ goto error;
+
+ n = isl_map_dim(map, type);
+ if (!isl_map_involves_dims(map, type, 0, n)) {
+ isl_space *space;
+ isl_multi_aff *ma;
+
+ space = isl_multi_pw_aff_get_space(mpa);
+ isl_multi_pw_aff_free(mpa);
+ ma = isl_multi_aff_zero(space);
+ return isl_map_preimage_multi_aff(map, type, ma);
+ }
+
+ pma = isl_pw_multi_aff_from_multi_pw_aff(mpa);
+ return isl_map_preimage_pw_multi_aff(map, type, pma);
+error:
+ isl_map_free(map);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Compute the preimage of "map" under the function represented by "mpa".
+ * In other words, plug in "mpa" in the domain "map".
+ * The result is a map that lives in the same space as "map",
+ * except that domain space has been replaced by the domain space of "mpa".
+ */
+__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
+ __isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa)
+{
+ return isl_map_preimage_multi_pw_aff(map, isl_dim_in, mpa);
+}
+
+/* Compute the preimage of "set" by the function represented by "mpa".
+ * In other words, plug in "mpa" in "set".
+ */
+__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ return isl_map_preimage_multi_pw_aff(set, isl_dim_set, mpa);
+}
diff --git a/polly/lib/External/isl/isl_map_lexopt_templ.c b/polly/lib/External/isl/isl_map_lexopt_templ.c
new file mode 100644
index 00000000000..1196a87f7ea
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_lexopt_templ.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012 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
+ */
+
+/* Function for computing the lexicographic optimum of a map
+ * in the form of either an isl_map or an isl_pw_multi_aff.
+ */
+
+#define xSF(TYPE,SUFFIX) TYPE ## SUFFIX
+#define SF(TYPE,SUFFIX) xSF(TYPE,SUFFIX)
+
+/* Given a basic map "bmap", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * We first make sure the basic sets in dom are disjoint and then
+ * simply collect the results over each of the basic sets separately.
+ * We could probably improve the efficiency a bit by moving the union
+ * domain down into the parametric integer programming.
+ */
+static __isl_give TYPE *SF(basic_map_partial_lexopt,SUFFIX)(
+ __isl_take isl_basic_map *bmap, __isl_take isl_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ int i;
+ TYPE *res;
+
+ dom = isl_set_make_disjoint(dom);
+ if (!dom)
+ goto error;
+
+ if (isl_set_plain_is_empty(dom)) {
+ isl_space *space = isl_basic_map_get_space(bmap);
+ if (empty)
+ *empty = dom;
+ else
+ isl_set_free(dom);
+ isl_basic_map_free(bmap);
+ return EMPTY(space);
+ }
+
+ res = SF(isl_basic_map_partial_lexopt,SUFFIX)(isl_basic_map_copy(bmap),
+ isl_basic_set_copy(dom->p[0]), empty, max);
+
+ for (i = 1; i < dom->n; ++i) {
+ TYPE *res_i;
+ isl_set *empty_i;
+
+ res_i = SF(isl_basic_map_partial_lexopt,SUFFIX)(
+ isl_basic_map_copy(bmap),
+ isl_basic_set_copy(dom->p[i]), &empty_i, max);
+
+ res = ADD(res, res_i);
+ *empty = isl_set_union_disjoint(*empty, empty_i);
+ }
+
+ isl_set_free(dom);
+ isl_basic_map_free(bmap);
+ return res;
+error:
+ *empty = NULL;
+ isl_set_free(dom);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give TYPE *SF(isl_map_partial_lexopt_aligned,SUFFIX)(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty, int max);
+
+/* Given a map "map", compute the lexicographically minimal
+ * (or maximal) image element for each domain element in dom.
+ * Set *empty to those elements in dom that do not have an image element.
+ *
+ * Align parameters if needed and then call isl_map_partial_lexopt_aligned.
+ */
+static __isl_give TYPE *SF(isl_map_partial_lexopt,SUFFIX)(
+ __isl_take isl_map *map, __isl_take isl_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ if (!map || !dom)
+ goto error;
+ if (isl_space_match(map->dim, isl_dim_param, dom->dim, isl_dim_param))
+ return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom,
+ empty, max);
+ if (!isl_space_has_named_params(map->dim) ||
+ !isl_space_has_named_params(dom->dim))
+ isl_die(map->ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ map = isl_map_align_params(map, isl_map_get_space(dom));
+ dom = isl_map_align_params(dom, isl_map_get_space(map));
+ return SF(isl_map_partial_lexopt_aligned,SUFFIX)(map, dom, empty, max);
+error:
+ if (empty)
+ *empty = NULL;
+ isl_set_free(dom);
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give TYPE *SF(isl_map_lexopt,SUFFIX)(__isl_take isl_map *map, int max)
+{
+ isl_set *dom = NULL;
+ isl_space *dom_space;
+
+ if (!map)
+ goto error;
+ dom_space = isl_space_domain(isl_space_copy(map->dim));
+ dom = isl_set_universe(dom_space);
+ return SF(isl_map_partial_lexopt,SUFFIX)(map, dom, NULL, max);
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give TYPE *SF(isl_map_lexmin,SUFFIX)(__isl_take isl_map *map)
+{
+ return SF(isl_map_lexopt,SUFFIX)(map, 0);
+}
+
+__isl_give TYPE *SF(isl_map_lexmax,SUFFIX)(__isl_take isl_map *map)
+{
+ return SF(isl_map_lexopt,SUFFIX)(map, 1);
+}
+
+__isl_give TYPE *SF(isl_set_lexmin,SUFFIX)(__isl_take isl_set *set)
+{
+ return SF(isl_map_lexmin,SUFFIX)(set);
+}
+
+__isl_give TYPE *SF(isl_set_lexmax,SUFFIX)(__isl_take isl_set *set)
+{
+ return SF(isl_map_lexmax,SUFFIX)(set);
+}
diff --git a/polly/lib/External/isl/isl_map_private.h b/polly/lib/External/isl/isl_map_private.h
new file mode 100644
index 00000000000..7f1cd589b56
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_private.h
@@ -0,0 +1,408 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_MAP_PRIVATE_H
+#define ISL_MAP_PRIVATE_H
+
+#define isl_basic_set isl_basic_map
+#define isl_set isl_map
+#define isl_basic_set_list isl_basic_map_list
+#define isl_set_list isl_map_list
+#include <isl/list.h>
+ISL_DECLARE_LIST(basic_map)
+ISL_DECLARE_LIST(map)
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl_reordering.h>
+#include <isl/vec.h>
+#include <isl_blk.h>
+
+/* A "basic map" is a relation between two sets of variables,
+ * called the "in" and "out" variables.
+ * A "basic set" is a basic map with a zero-dimensional
+ * domain.
+ *
+ * It is implemented as a set with two extra fields:
+ * n_in is the number of in variables
+ * n_out is the number of out variables
+ * n_in + n_out should be equal to set.dim
+ */
+struct isl_basic_map {
+ int ref;
+#define ISL_BASIC_MAP_FINAL (1 << 0)
+#define ISL_BASIC_MAP_EMPTY (1 << 1)
+#define ISL_BASIC_MAP_NO_IMPLICIT (1 << 2)
+#define ISL_BASIC_MAP_NO_REDUNDANT (1 << 3)
+#define ISL_BASIC_MAP_RATIONAL (1 << 4)
+#define ISL_BASIC_MAP_NORMALIZED (1 << 5)
+#define ISL_BASIC_MAP_NORMALIZED_DIVS (1 << 6)
+#define ISL_BASIC_MAP_ALL_EQUALITIES (1 << 7)
+#define ISL_BASIC_SET_FINAL (1 << 0)
+#define ISL_BASIC_SET_EMPTY (1 << 1)
+#define ISL_BASIC_SET_NO_IMPLICIT (1 << 2)
+#define ISL_BASIC_SET_NO_REDUNDANT (1 << 3)
+#define ISL_BASIC_SET_RATIONAL (1 << 4)
+#define ISL_BASIC_SET_NORMALIZED (1 << 5)
+#define ISL_BASIC_SET_NORMALIZED_DIVS (1 << 6)
+#define ISL_BASIC_SET_ALL_EQUALITIES (1 << 7)
+ unsigned flags;
+
+ struct isl_ctx *ctx;
+
+ isl_space *dim;
+ unsigned extra;
+
+ unsigned n_eq;
+ unsigned n_ineq;
+
+ size_t c_size;
+ isl_int **eq;
+ isl_int **ineq;
+
+ unsigned n_div;
+
+ isl_int **div;
+
+ struct isl_vec *sample;
+
+ struct isl_blk block;
+ struct isl_blk block2;
+};
+
+#undef EL
+#define EL isl_basic_set
+
+#include <isl_list_templ.h>
+
+/* A "map" is a (possibly disjoint) union of basic maps.
+ * A "set" is a (possibly disjoint) union of basic sets.
+ *
+ * Currently, the isl_set structure is identical to the isl_map structure
+ * and the library depends on this correspondence internally.
+ * However, users should not depend on this correspondence.
+ */
+struct isl_map {
+ int ref;
+#define ISL_MAP_DISJOINT (1 << 0)
+#define ISL_MAP_NORMALIZED (1 << 1)
+#define ISL_SET_DISJOINT (1 << 0)
+#define ISL_SET_NORMALIZED (1 << 1)
+ unsigned flags;
+
+ struct isl_ctx *ctx;
+
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_basic_map *p[1];
+};
+
+#undef EL
+#define EL isl_set
+
+#include <isl_list_templ.h>
+
+__isl_give isl_map *isl_map_realign(__isl_take isl_map *map,
+ __isl_take isl_reordering *r);
+__isl_give isl_set *isl_set_realign(__isl_take isl_set *set,
+ __isl_take isl_reordering *r);
+
+__isl_give isl_map *isl_map_reset(__isl_take isl_map *map,
+ enum isl_dim_type type);
+
+__isl_give isl_basic_set *isl_basic_set_reset_space(
+ __isl_take isl_basic_set *bset, __isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_reset_space(
+ __isl_take isl_basic_map *bmap, __isl_take isl_space *dim);
+__isl_give isl_map *isl_map_reset_space(__isl_take isl_map *map,
+ __isl_take isl_space *dim);
+
+unsigned isl_basic_map_offset(struct isl_basic_map *bmap,
+ enum isl_dim_type type);
+unsigned isl_basic_set_offset(struct isl_basic_set *bset,
+ enum isl_dim_type type);
+
+int isl_basic_map_may_be_set(__isl_keep isl_basic_map *bmap);
+int isl_map_may_be_set(__isl_keep isl_map *map);
+int isl_map_compatible_domain(struct isl_map *map, struct isl_set *set);
+int isl_basic_map_compatible_domain(struct isl_basic_map *bmap,
+ struct isl_basic_set *bset);
+int isl_basic_map_compatible_range(struct isl_basic_map *bmap,
+ struct isl_basic_set *bset);
+
+struct isl_basic_map *isl_basic_map_extend_space(struct isl_basic_map *base,
+ __isl_take isl_space *dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_extend_space(struct isl_basic_set *base,
+ __isl_take isl_space *dim, unsigned extra,
+ unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_add_constraints(struct isl_basic_set *bset1,
+ struct isl_basic_set *bset2, unsigned pos);
+
+struct isl_map *isl_map_grow(struct isl_map *map, int n);
+struct isl_set *isl_set_grow(struct isl_set *set, int n);
+
+int isl_basic_set_contains(struct isl_basic_set *bset, struct isl_vec *vec);
+int isl_basic_map_contains(struct isl_basic_map *bmap, struct isl_vec *vec);
+
+__isl_give isl_basic_set *isl_basic_set_alloc_space(__isl_take isl_space *dim,
+ unsigned extra, unsigned n_eq, unsigned n_ineq);
+__isl_give isl_set *isl_set_alloc_space(__isl_take isl_space *dim, int n,
+ unsigned flags);
+__isl_give isl_basic_map *isl_basic_map_alloc_space(__isl_take isl_space *dim,
+ unsigned extra, unsigned n_eq, unsigned n_ineq);
+__isl_give isl_map *isl_map_alloc_space(__isl_take isl_space *dim, int n,
+ unsigned flags);
+
+unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap);
+
+int isl_basic_map_alloc_equality(struct isl_basic_map *bmap);
+int isl_basic_set_alloc_equality(struct isl_basic_set *bset);
+int isl_basic_set_free_inequality(struct isl_basic_set *bset, unsigned n);
+int isl_basic_map_free_equality(struct isl_basic_map *bmap, unsigned n);
+int isl_basic_set_free_equality(struct isl_basic_set *bset, unsigned n);
+int isl_basic_set_alloc_inequality(struct isl_basic_set *bset);
+int isl_basic_map_alloc_inequality(struct isl_basic_map *bmap);
+int isl_basic_map_free_inequality(struct isl_basic_map *bmap, unsigned n);
+int isl_basic_map_alloc_div(struct isl_basic_map *bmap);
+int isl_basic_set_alloc_div(struct isl_basic_set *bset);
+int isl_basic_map_free_div(struct isl_basic_map *bmap, unsigned n);
+int isl_basic_set_free_div(struct isl_basic_set *bset, unsigned n);
+void isl_basic_map_inequality_to_equality(
+ struct isl_basic_map *bmap, unsigned pos);
+int isl_basic_map_drop_equality(struct isl_basic_map *bmap, unsigned pos);
+int isl_basic_set_drop_equality(struct isl_basic_set *bset, unsigned pos);
+int isl_basic_set_drop_inequality(struct isl_basic_set *bset, unsigned pos);
+int isl_basic_map_drop_inequality(struct isl_basic_map *bmap, unsigned pos);
+__isl_give isl_basic_set *isl_basic_set_add_eq(__isl_take isl_basic_set *bset,
+ isl_int *eq);
+__isl_give isl_basic_map *isl_basic_map_add_eq(__isl_take isl_basic_map *bmap,
+ isl_int *eq);
+__isl_give isl_basic_set *isl_basic_set_add_ineq(__isl_take isl_basic_set *bset,
+ isl_int *ineq);
+__isl_give isl_basic_map *isl_basic_map_add_ineq(__isl_take isl_basic_map *bmap,
+ isl_int *ineq);
+
+int isl_inequality_negate(struct isl_basic_map *bmap, unsigned pos);
+
+struct isl_basic_set *isl_basic_set_cow(struct isl_basic_set *bset);
+struct isl_basic_map *isl_basic_map_cow(struct isl_basic_map *bmap);
+struct isl_set *isl_set_cow(struct isl_set *set);
+struct isl_map *isl_map_cow(struct isl_map *map);
+
+struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap);
+struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset);
+void isl_basic_map_swap_div(struct isl_basic_map *bmap, int a, int b);
+struct isl_basic_map *isl_basic_map_order_divs(struct isl_basic_map *bmap);
+__isl_give isl_map *isl_map_order_divs(__isl_take isl_map *map);
+struct isl_basic_map *isl_basic_map_align_divs(
+ struct isl_basic_map *dst, struct isl_basic_map *src);
+struct isl_basic_set *isl_basic_set_align_divs(
+ struct isl_basic_set *dst, struct isl_basic_set *src);
+__isl_give isl_set *isl_set_align_divs_to_basic_set_list(
+ __isl_take isl_set *set, __isl_keep isl_basic_set_list *list);
+__isl_give isl_basic_set_list *isl_basic_set_list_align_divs_to_basic_set(
+ __isl_take isl_basic_set_list *list, __isl_keep isl_basic_set *bset);
+__isl_give isl_basic_map *isl_basic_map_sort_divs(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map);
+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);
+__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,
+ const __isl_keep isl_basic_map *bmap2);
+int isl_basic_map_plain_is_equal(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2);
+struct isl_basic_map *isl_basic_map_normalize_constraints(
+ struct isl_basic_map *bmap);
+struct isl_basic_set *isl_basic_set_normalize_constraints(
+ struct isl_basic_set *bset);
+struct isl_basic_map *isl_basic_map_implicit_equalities(
+ struct isl_basic_map *bmap);
+struct isl_basic_set *isl_basic_map_underlying_set(struct isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_set_underlying_set(
+ __isl_take isl_basic_set *bset);
+__isl_give isl_basic_set_list *isl_basic_set_list_underlying_set(
+ __isl_take isl_basic_set_list *list);
+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_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,
+ enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_set *isl_set_drop(struct isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_basic_set *isl_basic_set_drop_dims(
+ struct isl_basic_set *bset, unsigned first, unsigned n);
+struct isl_set *isl_set_drop_dims(
+ struct isl_set *set, unsigned first, unsigned n);
+struct isl_map *isl_map_drop_inputs(
+ struct isl_map *map, unsigned first, unsigned n);
+struct isl_map *isl_map_drop(struct isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
+ __isl_take isl_basic_map *bmap, int *progress, int detect_divs);
+
+struct isl_map *isl_map_remove_empty_parts(struct isl_map *map);
+struct isl_set *isl_set_remove_empty_parts(struct isl_set *set);
+__isl_give isl_map *isl_map_remove_obvious_duplicates(__isl_take isl_map *map);
+
+struct isl_set *isl_set_normalize(struct isl_set *set);
+
+struct isl_set *isl_set_drop_vars(
+ struct isl_set *set, unsigned first, unsigned n);
+
+struct isl_basic_map *isl_basic_map_eliminate_vars(
+ struct isl_basic_map *bmap, unsigned pos, unsigned n);
+struct isl_basic_set *isl_basic_set_eliminate_vars(
+ struct isl_basic_set *bset, unsigned pos, unsigned n);
+
+__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_basic_set_constraint_is_redundant(struct isl_basic_set **bset,
+ isl_int *c, isl_int *opt_n, isl_int *opt_d);
+
+int isl_basic_map_add_div_constraint(__isl_keep isl_basic_map *bmap,
+ unsigned div, int sign);
+int isl_basic_map_add_div_constraints(struct isl_basic_map *bmap, unsigned div);
+__isl_give isl_basic_map *isl_basic_map_add_known_div_constraints(
+ __isl_take isl_basic_map *bmap);
+struct isl_basic_map *isl_basic_map_drop_redundant_divs(
+ struct isl_basic_map *bmap);
+struct isl_basic_set *isl_basic_set_drop_redundant_divs(
+ struct isl_basic_set *bset);
+
+struct isl_basic_set *isl_basic_set_recession_cone(struct isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_lineality_space(struct isl_basic_set *bset);
+
+struct isl_basic_set *isl_basic_set_set_rational(struct isl_basic_set *bset);
+__isl_give isl_set *isl_set_set_rational(__isl_take isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_set_rational(
+ __isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_set_rational(__isl_take isl_map *map);
+
+int isl_map_has_rational(__isl_keep isl_map *map);
+int isl_set_has_rational(__isl_keep isl_set *set);
+
+struct isl_mat;
+
+struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
+ struct isl_mat *mat);
+struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat);
+
+__isl_give isl_basic_set *isl_basic_set_transform_dims(
+ __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
+ __isl_take isl_mat *trans);
+
+isl_int *isl_set_wrap_facet(__isl_keep isl_set *set,
+ isl_int *facet, isl_int *ridge);
+
+int isl_basic_map_contains_point(__isl_keep isl_basic_map *bmap,
+ __isl_keep isl_point *point);
+int isl_set_contains_point(__isl_keep isl_set *set, __isl_keep isl_point *point);
+
+int isl_basic_set_vars_get_sign(__isl_keep isl_basic_set *bset,
+ unsigned first, unsigned n, int *signs);
+int isl_set_foreach_orthant(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_set *orthant, int *signs, void *user),
+ void *user);
+
+int isl_basic_map_add_div_constraints_var(__isl_keep isl_basic_map *bmap,
+ unsigned pos, isl_int *div);
+int isl_basic_set_add_div_constraints_var(__isl_keep isl_basic_set *bset,
+ unsigned pos, isl_int *div);
+int isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
+ isl_int *constraint, unsigned div);
+int isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
+ isl_int *constraint, unsigned div);
+
+__isl_give isl_basic_set *isl_basic_set_from_local_space(
+ __isl_take isl_local_space *ls);
+__isl_give isl_basic_map *isl_basic_map_from_local_space(
+ __isl_take isl_local_space *ls);
+__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_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);
+
+__isl_give isl_map *isl_map_inline_foreach_basic_map(__isl_take isl_map *map,
+ __isl_give isl_basic_map *(*fn)(__isl_take isl_basic_map *bmap));
+
+__isl_give isl_map *isl_map_align_params_map_map_and(
+ __isl_take isl_map *map1, __isl_take isl_map *map2,
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map1,
+ __isl_take isl_map *map2));
+int isl_map_align_params_map_map_and_test(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2,
+ int (*fn)(__isl_keep isl_map *map1, __isl_keep isl_map *map2));
+
+int isl_basic_map_foreach_lexopt(__isl_keep isl_basic_map *bmap, int max,
+ int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+ void *user),
+ void *user);
+int isl_basic_set_foreach_lexopt(__isl_keep isl_basic_set *bset, int max,
+ int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+ void *user),
+ void *user);
+
+__isl_give isl_set *isl_set_substitute(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs);
+
+__isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *context);
+
+int isl_map_compatible_range(__isl_keep isl_map *map, __isl_keep isl_set *set);
+
+int isl_basic_map_plain_is_single_valued(__isl_keep isl_basic_map *bmap);
+
+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);
+
+int isl_basic_set_dim_residue_class(struct isl_basic_set *bset,
+ int pos, isl_int *modulo, isl_int *residue);
+int isl_set_dim_residue_class(struct isl_set *set,
+ int pos, isl_int *modulo, isl_int *residue);
+
+__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
+ enum isl_dim_type type, unsigned pos, isl_int value);
+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);
+
+__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
+ __isl_keep isl_set *set);
+
+__isl_give isl_map *isl_map_fixed_power(__isl_take isl_map *map, isl_int exp);
+
+int isl_basic_set_count_upto(__isl_keep isl_basic_set *bset,
+ isl_int max, isl_int *count);
+int isl_set_count_upto(__isl_keep isl_set *set, isl_int max, isl_int *count);
+
+#endif
diff --git a/polly/lib/External/isl/isl_map_simplify.c b/polly/lib/External/isl/isl_map_simplify.c
new file mode 100644
index 00000000000..78815bd98c7
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_simplify.c
@@ -0,0 +1,3257 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2012 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <strings.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include "isl_equalities.h"
+#include <isl/map.h>
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include <isl_space_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+static void swap_equality(struct isl_basic_map *bmap, int a, int b)
+{
+ isl_int *t = bmap->eq[a];
+ bmap->eq[a] = bmap->eq[b];
+ bmap->eq[b] = t;
+}
+
+static void swap_inequality(struct isl_basic_map *bmap, int a, int b)
+{
+ if (a != b) {
+ isl_int *t = bmap->ineq[a];
+ bmap->ineq[a] = bmap->ineq[b];
+ bmap->ineq[b] = t;
+ }
+}
+
+static void constraint_drop_vars(isl_int *c, unsigned n, unsigned rem)
+{
+ isl_seq_cpy(c, c + n, rem);
+ isl_seq_clr(c + rem, n);
+}
+
+/* Drop n dimensions starting at first.
+ *
+ * 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
+ * to be equal to extra.
+ */
+struct isl_basic_set *isl_basic_set_drop_dims(
+ struct isl_basic_set *bset, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!bset)
+ goto error;
+
+ isl_assert(bset->ctx, first + n <= bset->dim->n_out, goto error);
+
+ if (n == 0 && !isl_space_get_tuple_name(bset->dim, isl_dim_set))
+ return bset;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+
+ for (i = 0; i < bset->n_eq; ++i)
+ constraint_drop_vars(bset->eq[i]+1+bset->dim->nparam+first, n,
+ (bset->dim->n_out-first-n)+bset->extra);
+
+ for (i = 0; i < bset->n_ineq; ++i)
+ constraint_drop_vars(bset->ineq[i]+1+bset->dim->nparam+first, n,
+ (bset->dim->n_out-first-n)+bset->extra);
+
+ for (i = 0; i < bset->n_div; ++i)
+ constraint_drop_vars(bset->div[i]+1+1+bset->dim->nparam+first, n,
+ (bset->dim->n_out-first-n)+bset->extra);
+
+ bset->dim = isl_space_drop_outputs(bset->dim, first, n);
+ if (!bset->dim)
+ goto error;
+
+ ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
+ bset = isl_basic_set_simplify(bset);
+ return isl_basic_set_finalize(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_set *isl_set_drop_dims(
+ struct isl_set *set, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!set)
+ goto error;
+
+ isl_assert(set->ctx, first + n <= set->dim->n_out, goto error);
+
+ if (n == 0 && !isl_space_get_tuple_name(set->dim, isl_dim_set))
+ return set;
+ set = isl_set_cow(set);
+ if (!set)
+ goto error;
+ set->dim = isl_space_drop_outputs(set->dim, first, n);
+ if (!set->dim)
+ goto error;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_drop_dims(set->p[i], first, n);
+ if (!set->p[i])
+ goto error;
+ }
+
+ ISL_F_CLR(set, ISL_SET_NORMALIZED);
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+/* Move "n" divs starting at "first" to the end of the list of divs.
+ */
+static struct isl_basic_map *move_divs_last(struct isl_basic_map *bmap,
+ unsigned first, unsigned n)
+{
+ isl_int **div;
+ int i;
+
+ if (first + n == bmap->n_div)
+ return bmap;
+
+ div = isl_alloc_array(bmap->ctx, isl_int *, n);
+ if (!div)
+ goto error;
+ for (i = 0; i < n; ++i)
+ div[i] = bmap->div[first + i];
+ for (i = 0; i < bmap->n_div - first - n; ++i)
+ bmap->div[first + i] = bmap->div[first + n + i];
+ for (i = 0; i < n; ++i)
+ bmap->div[bmap->n_div - n + i] = div[i];
+ free(div);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Drop "n" dimensions of type "type" starting at "first".
+ *
+ * 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
+ * to be equal to extra.
+ */
+struct isl_basic_map *isl_basic_map_drop(struct isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ unsigned dim;
+ unsigned offset;
+ unsigned left;
+
+ if (!bmap)
+ goto error;
+
+ dim = isl_basic_map_dim(bmap, type);
+ isl_assert(bmap->ctx, first + n <= dim, goto error);
+
+ if (n == 0 && !isl_space_is_named_or_nested(bmap->dim, type))
+ return bmap;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+
+ offset = isl_basic_map_offset(bmap, type) + first;
+ left = isl_basic_map_total_dim(bmap) - (offset - 1) - n;
+ for (i = 0; i < bmap->n_eq; ++i)
+ constraint_drop_vars(bmap->eq[i]+offset, n, left);
+
+ for (i = 0; i < bmap->n_ineq; ++i)
+ constraint_drop_vars(bmap->ineq[i]+offset, n, left);
+
+ for (i = 0; i < bmap->n_div; ++i)
+ constraint_drop_vars(bmap->div[i]+1+offset, n, left);
+
+ if (type == isl_dim_div) {
+ bmap = move_divs_last(bmap, first, n);
+ if (!bmap)
+ goto error;
+ isl_basic_map_free_div(bmap, n);
+ } else
+ bmap->dim = isl_space_drop_dims(bmap->dim, type, first, n);
+ if (!bmap->dim)
+ goto error;
+
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ bmap = isl_basic_map_simplify(bmap);
+ return isl_basic_map_finalize(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_drop(__isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_basic_set *)isl_basic_map_drop((isl_basic_map *)bset,
+ type, first, n);
+}
+
+struct isl_basic_map *isl_basic_map_drop_inputs(
+ struct isl_basic_map *bmap, unsigned first, unsigned n)
+{
+ return isl_basic_map_drop(bmap, isl_dim_in, first, n);
+}
+
+struct isl_map *isl_map_drop(struct isl_map *map,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!map)
+ goto error;
+
+ isl_assert(map->ctx, first + n <= isl_map_dim(map, type), goto error);
+
+ if (n == 0 && !isl_space_get_tuple_name(map->dim, type))
+ return map;
+ map = isl_map_cow(map);
+ if (!map)
+ goto error;
+ map->dim = isl_space_drop_dims(map->dim, type, first, n);
+ if (!map->dim)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_drop(map->p[i], type, first, n);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_set *isl_set_drop(struct isl_set *set,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return (isl_set *)isl_map_drop((isl_map *)set, type, first, n);
+}
+
+struct isl_map *isl_map_drop_inputs(
+ struct isl_map *map, unsigned first, unsigned n)
+{
+ return isl_map_drop(map, isl_dim_in, first, n);
+}
+
+/*
+ * We don't cow, as the div is assumed to be redundant.
+ */
+static struct isl_basic_map *isl_basic_map_drop_div(
+ struct isl_basic_map *bmap, unsigned div)
+{
+ int i;
+ unsigned pos;
+
+ if (!bmap)
+ goto error;
+
+ pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
+
+ isl_assert(bmap->ctx, div < bmap->n_div, goto error);
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ constraint_drop_vars(bmap->eq[i]+pos, 1, bmap->extra-div-1);
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (!isl_int_is_zero(bmap->ineq[i][pos])) {
+ isl_basic_map_drop_inequality(bmap, i);
+ --i;
+ continue;
+ }
+ constraint_drop_vars(bmap->ineq[i]+pos, 1, bmap->extra-div-1);
+ }
+
+ for (i = 0; i < bmap->n_div; ++i)
+ constraint_drop_vars(bmap->div[i]+1+pos, 1, bmap->extra-div-1);
+
+ if (div != bmap->n_div - 1) {
+ int j;
+ isl_int *t = bmap->div[div];
+
+ for (j = div; j < bmap->n_div - 1; ++j)
+ bmap->div[j] = bmap->div[j+1];
+
+ bmap->div[bmap->n_div - 1] = t;
+ }
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ isl_basic_map_free_div(bmap, 1);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_map *isl_basic_map_normalize_constraints(
+ struct isl_basic_map *bmap)
+{
+ int i;
+ isl_int gcd;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ if (!bmap)
+ return NULL;
+
+ isl_int_init(gcd);
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ isl_seq_gcd(bmap->eq[i]+1, total, &gcd);
+ if (isl_int_is_zero(gcd)) {
+ if (!isl_int_is_zero(bmap->eq[i][0])) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ break;
+ }
+ isl_basic_map_drop_equality(bmap, i);
+ continue;
+ }
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+ isl_int_gcd(gcd, gcd, bmap->eq[i][0]);
+ if (isl_int_is_one(gcd))
+ continue;
+ if (!isl_int_is_divisible_by(bmap->eq[i][0], gcd)) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ break;
+ }
+ isl_seq_scale_down(bmap->eq[i], bmap->eq[i], gcd, 1+total);
+ }
+
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ isl_seq_gcd(bmap->ineq[i]+1, total, &gcd);
+ if (isl_int_is_zero(gcd)) {
+ if (isl_int_is_neg(bmap->ineq[i][0])) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ break;
+ }
+ isl_basic_map_drop_inequality(bmap, i);
+ continue;
+ }
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+ isl_int_gcd(gcd, gcd, bmap->ineq[i][0]);
+ if (isl_int_is_one(gcd))
+ continue;
+ isl_int_fdiv_q(bmap->ineq[i][0], bmap->ineq[i][0], gcd);
+ isl_seq_scale_down(bmap->ineq[i]+1, bmap->ineq[i]+1, gcd, total);
+ }
+ isl_int_clear(gcd);
+
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_normalize_constraints(
+ struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)isl_basic_map_normalize_constraints(
+ (struct isl_basic_map *)bset);
+}
+
+/* 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
+ *
+ * floor((a + m f(x))/(m d))
+ *
+ * then replace it by
+ *
+ * floor((floor(a/m) + f(x))/d)
+ *
+ * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
+ * and can therefore not influence the result of the floor.
+ */
+static void normalize_div_expression(__isl_keep isl_basic_map *bmap, int div)
+{
+ unsigned total = isl_basic_map_total_dim(bmap);
+ isl_ctx *ctx = bmap->ctx;
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return;
+ isl_seq_gcd(bmap->div[div] + 2, total, &ctx->normalize_gcd);
+ isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, bmap->div[div][0]);
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return;
+ isl_int_fdiv_q(bmap->div[div][1], bmap->div[div][1],
+ ctx->normalize_gcd);
+ isl_int_divexact(bmap->div[div][0], bmap->div[div][0],
+ ctx->normalize_gcd);
+ isl_seq_scale_down(bmap->div[div] + 2, bmap->div[div] + 2,
+ ctx->normalize_gcd, total);
+}
+
+/* Remove any common factor in numerator and denominator of a div expression,
+ * not taking into account the constant term.
+ * That is, look for any div of the form
+ *
+ * floor((a + m f(x))/(m d))
+ *
+ * and replace it by
+ *
+ * floor((floor(a/m) + f(x))/d)
+ *
+ * The difference {a/m}/d in the argument satisfies 0 <= {a/m}/d < 1/d
+ * and can therefore not influence the result of the floor.
+ */
+static __isl_give isl_basic_map *normalize_div_expressions(
+ __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)
+ normalize_div_expression(bmap, i);
+
+ return bmap;
+}
+
+/* Assumes divs have been ordered if keep_divs is set.
+ */
+static void eliminate_var_using_equality(struct isl_basic_map *bmap,
+ unsigned pos, isl_int *eq, int keep_divs, int *progress)
+{
+ unsigned total;
+ unsigned space_total;
+ int k;
+ int last_div;
+
+ total = isl_basic_map_total_dim(bmap);
+ space_total = isl_space_dim(bmap->dim, isl_dim_all);
+ last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
+ for (k = 0; k < bmap->n_eq; ++k) {
+ if (bmap->eq[k] == eq)
+ continue;
+ if (isl_int_is_zero(bmap->eq[k][1+pos]))
+ continue;
+ if (progress)
+ *progress = 1;
+ isl_seq_elim(bmap->eq[k], eq, 1+pos, 1+total, NULL);
+ isl_seq_normalize(bmap->ctx, bmap->eq[k], 1 + total);
+ }
+
+ for (k = 0; k < bmap->n_ineq; ++k) {
+ if (isl_int_is_zero(bmap->ineq[k][1+pos]))
+ continue;
+ if (progress)
+ *progress = 1;
+ isl_seq_elim(bmap->ineq[k], eq, 1+pos, 1+total, NULL);
+ isl_seq_normalize(bmap->ctx, bmap->ineq[k], 1 + total);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ }
+
+ for (k = 0; k < bmap->n_div; ++k) {
+ if (isl_int_is_zero(bmap->div[k][0]))
+ continue;
+ if (isl_int_is_zero(bmap->div[k][1+1+pos]))
+ continue;
+ if (progress)
+ *progress = 1;
+ /* We need to be careful about circular definitions,
+ * so for now we just remove the definition of div k
+ * if the equality contains any divs.
+ * If keep_divs is set, then the divs have been ordered
+ * and we can keep the definition as long as the result
+ * is still ordered.
+ */
+ if (last_div == -1 || (keep_divs && last_div < k)) {
+ isl_seq_elim(bmap->div[k]+1, eq,
+ 1+pos, 1+total, &bmap->div[k][0]);
+ normalize_div_expression(bmap, k);
+ } else
+ isl_seq_clr(bmap->div[k], 1 + total);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ }
+}
+
+/* Assumes divs have been ordered if keep_divs is set.
+ */
+static void eliminate_div(struct isl_basic_map *bmap, isl_int *eq,
+ unsigned div, int keep_divs)
+{
+ unsigned pos = isl_space_dim(bmap->dim, isl_dim_all) + div;
+
+ eliminate_var_using_equality(bmap, pos, eq, keep_divs, NULL);
+
+ isl_basic_map_drop_div(bmap, div);
+}
+
+/* Check if elimination of div "div" using equality "eq" would not
+ * result in a div depending on a later div.
+ */
+static int ok_to_eliminate_div(struct isl_basic_map *bmap, isl_int *eq,
+ unsigned div)
+{
+ int k;
+ int last_div;
+ unsigned space_total = isl_space_dim(bmap->dim, isl_dim_all);
+ unsigned pos = space_total + div;
+
+ last_div = isl_seq_last_non_zero(eq + 1 + space_total, bmap->n_div);
+ if (last_div < 0 || last_div <= div)
+ return 1;
+
+ for (k = 0; k <= last_div; ++k) {
+ if (isl_int_is_zero(bmap->div[k][0]))
+ return 1;
+ if (!isl_int_is_zero(bmap->div[k][1 + 1 + pos]))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Elimininate divs based on equalities
+ */
+static struct isl_basic_map *eliminate_divs_eq(
+ struct isl_basic_map *bmap, int *progress)
+{
+ int d;
+ int i;
+ int modified = 0;
+ unsigned off;
+
+ bmap = isl_basic_map_order_divs(bmap);
+
+ if (!bmap)
+ return NULL;
+
+ off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (d = bmap->n_div - 1; d >= 0 ; --d) {
+ for (i = 0; i < bmap->n_eq; ++i) {
+ if (!isl_int_is_one(bmap->eq[i][off + d]) &&
+ !isl_int_is_negone(bmap->eq[i][off + d]))
+ continue;
+ if (!ok_to_eliminate_div(bmap, bmap->eq[i], d))
+ continue;
+ modified = 1;
+ *progress = 1;
+ eliminate_div(bmap, bmap->eq[i], d, 1);
+ isl_basic_map_drop_equality(bmap, i);
+ break;
+ }
+ }
+ if (modified)
+ return eliminate_divs_eq(bmap, progress);
+ return bmap;
+}
+
+/* Elimininate divs based on inequalities
+ */
+static struct isl_basic_map *eliminate_divs_ineq(
+ struct isl_basic_map *bmap, int *progress)
+{
+ int d;
+ int i;
+ unsigned off;
+ struct isl_ctx *ctx;
+
+ if (!bmap)
+ return NULL;
+
+ ctx = bmap->ctx;
+ off = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (d = bmap->n_div - 1; d >= 0 ; --d) {
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (!isl_int_is_zero(bmap->eq[i][off + d]))
+ break;
+ if (i < bmap->n_eq)
+ continue;
+ for (i = 0; i < bmap->n_ineq; ++i)
+ if (isl_int_abs_gt(bmap->ineq[i][off + d], ctx->one))
+ break;
+ if (i < bmap->n_ineq)
+ continue;
+ *progress = 1;
+ bmap = isl_basic_map_eliminate_vars(bmap, (off-1)+d, 1);
+ if (!bmap || ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ break;
+ bmap = isl_basic_map_drop_div(bmap, d);
+ if (!bmap)
+ break;
+ }
+ return bmap;
+}
+
+struct isl_basic_map *isl_basic_map_gauss(
+ struct isl_basic_map *bmap, int *progress)
+{
+ int k;
+ int done;
+ int last_var;
+ unsigned total_var;
+ unsigned total;
+
+ bmap = isl_basic_map_order_divs(bmap);
+
+ if (!bmap)
+ return NULL;
+
+ total = isl_basic_map_total_dim(bmap);
+ total_var = total - bmap->n_div;
+
+ last_var = total - 1;
+ for (done = 0; done < bmap->n_eq; ++done) {
+ for (; last_var >= 0; --last_var) {
+ for (k = done; k < bmap->n_eq; ++k)
+ if (!isl_int_is_zero(bmap->eq[k][1+last_var]))
+ break;
+ if (k < bmap->n_eq)
+ break;
+ }
+ if (last_var < 0)
+ break;
+ if (k != done)
+ swap_equality(bmap, k, done);
+ if (isl_int_is_neg(bmap->eq[done][1+last_var]))
+ isl_seq_neg(bmap->eq[done], bmap->eq[done], 1+total);
+
+ eliminate_var_using_equality(bmap, last_var, bmap->eq[done], 1,
+ progress);
+
+ if (last_var >= total_var &&
+ isl_int_is_zero(bmap->div[last_var - total_var][0])) {
+ unsigned div = last_var - total_var;
+ isl_seq_neg(bmap->div[div]+1, bmap->eq[done], 1+total);
+ isl_int_set_si(bmap->div[div][1+1+last_var], 0);
+ isl_int_set(bmap->div[div][0],
+ bmap->eq[done][1+last_var]);
+ if (progress)
+ *progress = 1;
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ }
+ }
+ if (done == bmap->n_eq)
+ return bmap;
+ for (k = done; k < bmap->n_eq; ++k) {
+ if (isl_int_is_zero(bmap->eq[k][0]))
+ continue;
+ return isl_basic_map_set_to_empty(bmap);
+ }
+ isl_basic_map_free_equality(bmap, bmap->n_eq-done);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_gauss(
+ struct isl_basic_set *bset, int *progress)
+{
+ return (struct isl_basic_set*)isl_basic_map_gauss(
+ (struct isl_basic_map *)bset, progress);
+}
+
+
+static unsigned int round_up(unsigned int v)
+{
+ int old_v = v;
+
+ while (v) {
+ old_v = v;
+ v ^= v & -v;
+ }
+ return old_v << 1;
+}
+
+static int hash_index(isl_int ***index, unsigned int size, int bits,
+ struct isl_basic_map *bmap, int k)
+{
+ 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))
+ break;
+ return h;
+}
+
+static int set_hash_index(isl_int ***index, unsigned int size, int bits,
+ struct isl_basic_set *bset, int k)
+{
+ return hash_index(index, size, bits, (struct isl_basic_map *)bset, k);
+}
+
+/* If we can eliminate more than one div, then we need to make
+ * sure we do it from last div to first div, in order not to
+ * change the position of the other divs that still need to
+ * be removed.
+ */
+static struct isl_basic_map *remove_duplicate_divs(
+ struct isl_basic_map *bmap, int *progress)
+{
+ unsigned int size;
+ int *index;
+ int *elim_for;
+ int k, l, h;
+ int bits;
+ struct isl_blk eq;
+ unsigned total_var;
+ unsigned total;
+ struct isl_ctx *ctx;
+
+ bmap = isl_basic_map_order_divs(bmap);
+ if (!bmap || bmap->n_div <= 1)
+ return bmap;
+
+ total_var = isl_space_dim(bmap->dim, isl_dim_all);
+ total = total_var + bmap->n_div;
+
+ ctx = bmap->ctx;
+ for (k = bmap->n_div - 1; k >= 0; --k)
+ if (!isl_int_is_zero(bmap->div[k][0]))
+ break;
+ if (k <= 0)
+ return bmap;
+
+ elim_for = isl_calloc_array(ctx, int, bmap->n_div);
+ size = round_up(4 * bmap->n_div / 3 - 1);
+ bits = ffs(size) - 1;
+ index = isl_calloc_array(ctx, int, size);
+ if (!index)
+ return bmap;
+ eq = isl_blk_alloc(ctx, 1+total);
+ if (isl_blk_is_error(eq))
+ goto out;
+
+ isl_seq_clr(eq.data, 1+total);
+ index[isl_seq_get_hash_bits(bmap->div[k], 2+total, bits)] = k + 1;
+ for (--k; k >= 0; --k) {
+ uint32_t hash;
+
+ if (isl_int_is_zero(bmap->div[k][0]))
+ continue;
+
+ hash = isl_seq_get_hash_bits(bmap->div[k], 2+total, bits);
+ for (h = hash; index[h]; h = (h+1) % size)
+ if (isl_seq_eq(bmap->div[k],
+ bmap->div[index[h]-1], 2+total))
+ break;
+ if (index[h]) {
+ *progress = 1;
+ l = index[h] - 1;
+ elim_for[l] = k + 1;
+ }
+ index[h] = k+1;
+ }
+ for (l = bmap->n_div - 1; l >= 0; --l) {
+ if (!elim_for[l])
+ continue;
+ k = elim_for[l] - 1;
+ isl_int_set_si(eq.data[1+total_var+k], -1);
+ isl_int_set_si(eq.data[1+total_var+l], 1);
+ eliminate_div(bmap, eq.data, l, 1);
+ isl_int_set_si(eq.data[1+total_var+k], 0);
+ isl_int_set_si(eq.data[1+total_var+l], 0);
+ }
+
+ isl_blk_free(ctx, eq);
+out:
+ free(index);
+ free(elim_for);
+ return bmap;
+}
+
+static int n_pure_div_eq(struct isl_basic_map *bmap)
+{
+ int i, j;
+ unsigned total;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ for (i = 0, j = bmap->n_div-1; i < bmap->n_eq; ++i) {
+ while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
+ --j;
+ if (j < 0)
+ break;
+ if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total, j) != -1)
+ return 0;
+ }
+ return i;
+}
+
+/* Normalize divs that appear in equalities.
+ *
+ * In particular, we assume that bmap contains some equalities
+ * of the form
+ *
+ * a x = m * e_i
+ *
+ * and we want to replace the set of e_i by a minimal set and
+ * such that the new e_i have a canonical representation in terms
+ * of the vector x.
+ * If any of the equalities involves more than one divs, then
+ * we currently simply bail out.
+ *
+ * Let us first additionally assume that all equalities involve
+ * a div. The equalities then express modulo constraints on the
+ * remaining variables and we can use "parameter compression"
+ * to find a minimal set of constraints. The result is a transformation
+ *
+ * x = T(x') = x_0 + G x'
+ *
+ * with G a lower-triangular matrix with all elements below the diagonal
+ * non-negative and smaller than the diagonal element on the same row.
+ * We first normalize x_0 by making the same property hold in the affine
+ * T matrix.
+ * The rows i of G with a 1 on the diagonal do not impose any modulo
+ * constraint and simply express x_i = x'_i.
+ * For each of the remaining rows i, we introduce a div and a corresponding
+ * equality. In particular
+ *
+ * g_ii e_j = x_i - g_i(x')
+ *
+ * where each x'_k is replaced either by x_k (if g_kk = 1) or the
+ * corresponding div (if g_kk != 1).
+ *
+ * If there are any equalities not involving any div, then we
+ * first apply a variable compression on the variables x:
+ *
+ * x = C x'' x'' = C_2 x
+ *
+ * and perform the above parameter compression on A C instead of on A.
+ * The resulting compression is then of the form
+ *
+ * x'' = T(x') = x_0 + G x'
+ *
+ * and in constructing the new divs and the corresponding equalities,
+ * we have to replace each x'', i.e., the x'_k with (g_kk = 1),
+ * by the corresponding row from C_2.
+ */
+static struct isl_basic_map *normalize_divs(
+ struct isl_basic_map *bmap, int *progress)
+{
+ int i, j, k;
+ int total;
+ int div_eq;
+ struct isl_mat *B;
+ struct isl_vec *d;
+ struct isl_mat *T = NULL;
+ struct isl_mat *C = NULL;
+ struct isl_mat *C2 = NULL;
+ isl_int v;
+ int *pos;
+ int dropped, needed;
+
+ if (!bmap)
+ return NULL;
+
+ if (bmap->n_div == 0)
+ return bmap;
+
+ if (bmap->n_eq == 0)
+ return bmap;
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS))
+ return bmap;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ div_eq = n_pure_div_eq(bmap);
+ if (div_eq == 0)
+ return bmap;
+
+ if (div_eq < bmap->n_eq) {
+ B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, div_eq,
+ bmap->n_eq - div_eq, 0, 1 + total);
+ C = isl_mat_variable_compression(B, &C2);
+ if (!C || !C2)
+ goto error;
+ if (C->n_col == 0) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ isl_mat_free(C);
+ isl_mat_free(C2);
+ goto done;
+ }
+ }
+
+ d = isl_vec_alloc(bmap->ctx, div_eq);
+ if (!d)
+ goto error;
+ for (i = 0, j = bmap->n_div-1; i < div_eq; ++i) {
+ while (j >= 0 && isl_int_is_zero(bmap->eq[i][1 + total + j]))
+ --j;
+ isl_int_set(d->block.data[i], bmap->eq[i][1 + total + j]);
+ }
+ B = isl_mat_sub_alloc6(bmap->ctx, bmap->eq, 0, div_eq, 0, 1 + total);
+
+ if (C) {
+ B = isl_mat_product(B, C);
+ C = NULL;
+ }
+
+ T = isl_mat_parameter_compression(B, d);
+ if (!T)
+ goto error;
+ if (T->n_col == 0) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ isl_mat_free(C2);
+ isl_mat_free(T);
+ goto done;
+ }
+ isl_int_init(v);
+ for (i = 0; i < T->n_row - 1; ++i) {
+ isl_int_fdiv_q(v, T->row[1 + i][0], T->row[1 + i][1 + i]);
+ if (isl_int_is_zero(v))
+ continue;
+ isl_mat_col_submul(T, 0, v, 1 + i);
+ }
+ isl_int_clear(v);
+ pos = isl_alloc_array(bmap->ctx, int, T->n_row);
+ if (!pos)
+ goto error;
+ /* We have to be careful because dropping equalities may reorder them */
+ dropped = 0;
+ for (j = bmap->n_div - 1; j >= 0; --j) {
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (!isl_int_is_zero(bmap->eq[i][1 + total + j]))
+ break;
+ if (i < bmap->n_eq) {
+ bmap = isl_basic_map_drop_div(bmap, j);
+ isl_basic_map_drop_equality(bmap, i);
+ ++dropped;
+ }
+ }
+ pos[0] = 0;
+ needed = 0;
+ for (i = 1; i < T->n_row; ++i) {
+ if (isl_int_is_one(T->row[i][i]))
+ pos[i] = i;
+ else
+ needed++;
+ }
+ if (needed > dropped) {
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+ needed, needed, 0);
+ if (!bmap)
+ goto error;
+ }
+ for (i = 1; i < T->n_row; ++i) {
+ if (isl_int_is_one(T->row[i][i]))
+ continue;
+ k = isl_basic_map_alloc_div(bmap);
+ pos[i] = 1 + total + k;
+ isl_seq_clr(bmap->div[k] + 1, 1 + total + bmap->n_div);
+ isl_int_set(bmap->div[k][0], T->row[i][i]);
+ if (C2)
+ isl_seq_cpy(bmap->div[k] + 1, C2->row[i], 1 + total);
+ else
+ isl_int_set_si(bmap->div[k][1 + i], 1);
+ for (j = 0; j < i; ++j) {
+ if (isl_int_is_zero(T->row[i][j]))
+ continue;
+ if (pos[j] < T->n_row && C2)
+ isl_seq_submul(bmap->div[k] + 1, T->row[i][j],
+ C2->row[pos[j]], 1 + total);
+ else
+ isl_int_neg(bmap->div[k][1 + pos[j]],
+ T->row[i][j]);
+ }
+ j = isl_basic_map_alloc_equality(bmap);
+ isl_seq_neg(bmap->eq[j], bmap->div[k]+1, 1+total+bmap->n_div);
+ isl_int_set(bmap->eq[j][pos[i]], bmap->div[k][0]);
+ }
+ free(pos);
+ isl_mat_free(C2);
+ isl_mat_free(T);
+
+ if (progress)
+ *progress = 1;
+done:
+ ISL_F_SET(bmap, ISL_BASIC_MAP_NORMALIZED_DIVS);
+
+ return bmap;
+error:
+ isl_mat_free(C);
+ isl_mat_free(C2);
+ isl_mat_free(T);
+ return bmap;
+}
+
+static struct isl_basic_map *set_div_from_lower_bound(
+ struct isl_basic_map *bmap, int div, int ineq)
+{
+ unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+
+ isl_seq_neg(bmap->div[div] + 1, bmap->ineq[ineq], total + bmap->n_div);
+ isl_int_set(bmap->div[div][0], bmap->ineq[ineq][total + div]);
+ isl_int_add(bmap->div[div][1], bmap->div[div][1], bmap->div[div][0]);
+ isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
+ isl_int_set_si(bmap->div[div][1 + total + div], 0);
+
+ return bmap;
+}
+
+/* Check whether it is ok to define a div based on an inequality.
+ * To avoid the introduction of circular definitions of divs, we
+ * do not allow such a definition if the resulting expression would refer to
+ * any other undefined divs or if any known div is defined in
+ * terms of the unknown div.
+ */
+static int ok_to_set_div_from_bound(struct isl_basic_map *bmap,
+ int div, int ineq)
+{
+ int j;
+ unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+
+ /* Not defined in terms of unknown divs */
+ for (j = 0; j < bmap->n_div; ++j) {
+ if (div == j)
+ continue;
+ if (isl_int_is_zero(bmap->ineq[ineq][total + j]))
+ continue;
+ if (isl_int_is_zero(bmap->div[j][0]))
+ return 0;
+ }
+
+ /* No other div defined in terms of this one => avoid loops */
+ for (j = 0; j < bmap->n_div; ++j) {
+ if (div == j)
+ continue;
+ if (isl_int_is_zero(bmap->div[j][0]))
+ continue;
+ if (!isl_int_is_zero(bmap->div[j][1 + total + div]))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Would an expression for div "div" based on inequality "ineq" of "bmap"
+ * be a better expression than the current one?
+ *
+ * If we do not have any expression yet, then any expression would be better.
+ * Otherwise we check if the last variable involved in the inequality
+ * (disregarding the div that it would define) is in an earlier position
+ * than the last variable involved in the current div expression.
+ */
+static int better_div_constraint(__isl_keep isl_basic_map *bmap,
+ int div, int ineq)
+{
+ unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+ int last_div;
+ int last_ineq;
+
+ if (isl_int_is_zero(bmap->div[div][0]))
+ return 1;
+
+ if (isl_seq_last_non_zero(bmap->ineq[ineq] + total + div + 1,
+ bmap->n_div - (div + 1)) >= 0)
+ return 0;
+
+ last_ineq = isl_seq_last_non_zero(bmap->ineq[ineq], total + div);
+ last_div = isl_seq_last_non_zero(bmap->div[div] + 1,
+ total + bmap->n_div);
+
+ return last_ineq < last_div;
+}
+
+/* Given two constraints "k" and "l" that are opposite to each other,
+ * except for the constant term, check if we can use them
+ * to obtain an expression for one of the hitherto unknown divs or
+ * a "better" expression for a div for which we already have an expression.
+ * "sum" is the sum of the constant terms of the constraints.
+ * If this sum is strictly smaller than the coefficient of one
+ * of the divs, then this pair can be used define the div.
+ * To avoid the introduction of circular definitions of divs, we
+ * do not use the pair if the resulting expression would refer to
+ * any other undefined divs or if any known div is defined in
+ * terms of the unknown div.
+ */
+static struct isl_basic_map *check_for_div_constraints(
+ struct isl_basic_map *bmap, int k, int l, isl_int sum, int *progress)
+{
+ int i;
+ unsigned total = 1 + isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->ineq[k][total + i]))
+ continue;
+ if (isl_int_abs_ge(sum, bmap->ineq[k][total + i]))
+ continue;
+ if (!better_div_constraint(bmap, i, k))
+ continue;
+ if (!ok_to_set_div_from_bound(bmap, i, k))
+ break;
+ if (isl_int_is_pos(bmap->ineq[k][total + i]))
+ bmap = set_div_from_lower_bound(bmap, i, k);
+ else
+ bmap = set_div_from_lower_bound(bmap, i, l);
+ if (progress)
+ *progress = 1;
+ break;
+ }
+ return bmap;
+}
+
+__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;
+ 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);
+ bits = ffs(size) - 1;
+ ctx = isl_basic_map_get_ctx(bmap);
+ index = isl_calloc_array(ctx, isl_int **, size);
+ if (!index)
+ return bmap;
+
+ index[isl_seq_get_hash_bits(bmap->ineq[0]+1, total, bits)] = &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];
+ continue;
+ }
+ if (progress)
+ *progress = 1;
+ l = 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);
+ --k;
+ }
+ 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);
+ isl_seq_neg(bmap->ineq[k]+1, bmap->ineq[k]+1, total);
+ if (!index[h])
+ continue;
+ l = 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)
+ bmap = check_for_div_constraints(bmap, k, l,
+ sum, progress);
+ continue;
+ }
+ if (isl_int_is_zero(sum)) {
+ /* We need to break out of the loop after these
+ * changes since the contents of the hash
+ * will no longer be valid.
+ * Plus, we probably we want to regauss first.
+ */
+ if (progress)
+ *progress = 1;
+ isl_basic_map_drop_inequality(bmap, l);
+ isl_basic_map_inequality_to_equality(bmap, k);
+ } else
+ bmap = isl_basic_map_set_to_empty(bmap);
+ break;
+ }
+ isl_int_clear(sum);
+
+ free(index);
+ return bmap;
+}
+
+
+/* Eliminate knowns divs from constraints where they appear with
+ * a (positive or negative) unit coefficient.
+ *
+ * That is, replace
+ *
+ * floor(e/m) + f >= 0
+ *
+ * by
+ *
+ * e + m f >= 0
+ *
+ * and
+ *
+ * -floor(e/m) + f >= 0
+ *
+ * by
+ *
+ * -e + m f + m - 1 >= 0
+ *
+ * The first conversion is valid because floor(e/m) >= -f is equivalent
+ * to e/m >= -f because -f is an integral expression.
+ * The second conversion follows from the fact that
+ *
+ * -floor(e/m) = ceil(-e/m) = floor((-e + m - 1)/m)
+ *
+ *
+ * Note that one of the div constraints may have been eliminated
+ * due to being redundant with respect to the constraint that is
+ * being modified by this function. The modified constraint may
+ * no longer imply this div constraint, so we add it back to make
+ * sure we do not lose any information.
+ *
+ * We skip integral divs, i.e., those with denominator 1, as we would
+ * risk eliminating the div from the div constraints. We do not need
+ * to handle those divs here anyway since the div constraints will turn
+ * out to form an equality and this equality can then be use to eliminate
+ * the div from all constraints.
+ */
+static __isl_give isl_basic_map *eliminate_unit_divs(
+ __isl_take isl_basic_map *bmap, int *progress)
+{
+ int i, j;
+ isl_ctx *ctx;
+ unsigned total;
+
+ if (!bmap)
+ return NULL;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ total = 1 + 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]))
+ continue;
+ if (isl_int_is_one(bmap->div[i][0]))
+ continue;
+ for (j = 0; j < bmap->n_ineq; ++j) {
+ int s;
+
+ if (!isl_int_is_one(bmap->ineq[j][total + i]) &&
+ !isl_int_is_negone(bmap->ineq[j][total + i]))
+ continue;
+
+ *progress = 1;
+
+ s = isl_int_sgn(bmap->ineq[j][total + i]);
+ isl_int_set_si(bmap->ineq[j][total + i], 0);
+ if (s < 0)
+ isl_seq_combine(bmap->ineq[j],
+ ctx->negone, bmap->div[i] + 1,
+ bmap->div[i][0], bmap->ineq[j],
+ total + bmap->n_div);
+ else
+ isl_seq_combine(bmap->ineq[j],
+ ctx->one, bmap->div[i] + 1,
+ bmap->div[i][0], bmap->ineq[j],
+ total + bmap->n_div);
+ if (s < 0) {
+ isl_int_add(bmap->ineq[j][0],
+ bmap->ineq[j][0], bmap->div[i][0]);
+ isl_int_sub_ui(bmap->ineq[j][0],
+ bmap->ineq[j][0], 1);
+ }
+
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+ if (isl_basic_map_add_div_constraint(bmap, i, s) < 0)
+ return isl_basic_map_free(bmap);
+ }
+ }
+
+ return bmap;
+}
+
+struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap)
+{
+ int progress = 1;
+ if (!bmap)
+ return NULL;
+ while (progress) {
+ progress = 0;
+ if (!bmap)
+ break;
+ if (isl_basic_map_plain_is_empty(bmap))
+ break;
+ bmap = isl_basic_map_normalize_constraints(bmap);
+ bmap = normalize_div_expressions(bmap);
+ bmap = remove_duplicate_divs(bmap, &progress);
+ bmap = eliminate_unit_divs(bmap, &progress);
+ bmap = eliminate_divs_eq(bmap, &progress);
+ bmap = eliminate_divs_ineq(bmap, &progress);
+ bmap = isl_basic_map_gauss(bmap, &progress);
+ /* requires equalities in normal form */
+ bmap = normalize_divs(bmap, &progress);
+ bmap = isl_basic_map_remove_duplicate_constraints(bmap,
+ &progress, 1);
+ }
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_simplify((struct isl_basic_map *)bset);
+}
+
+
+int isl_basic_map_is_div_constraint(__isl_keep isl_basic_map *bmap,
+ isl_int *constraint, unsigned div)
+{
+ unsigned pos;
+
+ if (!bmap)
+ return -1;
+
+ pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
+
+ if (isl_int_eq(constraint[pos], bmap->div[div][0])) {
+ int neg;
+ isl_int_sub(bmap->div[div][1],
+ bmap->div[div][1], bmap->div[div][0]);
+ isl_int_add_ui(bmap->div[div][1], bmap->div[div][1], 1);
+ neg = isl_seq_is_neg(constraint, bmap->div[div]+1, pos);
+ isl_int_sub_ui(bmap->div[div][1], bmap->div[div][1], 1);
+ isl_int_add(bmap->div[div][1],
+ bmap->div[div][1], bmap->div[div][0]);
+ if (!neg)
+ return 0;
+ if (isl_seq_first_non_zero(constraint+pos+1,
+ bmap->n_div-div-1) != -1)
+ return 0;
+ } else if (isl_int_abs_eq(constraint[pos], bmap->div[div][0])) {
+ if (!isl_seq_eq(constraint, bmap->div[div]+1, pos))
+ return 0;
+ if (isl_seq_first_non_zero(constraint+pos+1,
+ bmap->n_div-div-1) != -1)
+ return 0;
+ } else
+ return 0;
+
+ return 1;
+}
+
+int isl_basic_set_is_div_constraint(__isl_keep isl_basic_set *bset,
+ isl_int *constraint, unsigned div)
+{
+ return isl_basic_map_is_div_constraint(bset, constraint, div);
+}
+
+
+/* If the only constraints a div d=floor(f/m)
+ * appears in are its two defining constraints
+ *
+ * f - m d >=0
+ * -(f - (m - 1)) + m d >= 0
+ *
+ * then it can safely be removed.
+ */
+static int div_is_redundant(struct isl_basic_map *bmap, int div)
+{
+ int i;
+ unsigned pos = 1 + isl_space_dim(bmap->dim, isl_dim_all) + div;
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (!isl_int_is_zero(bmap->eq[i][pos]))
+ return 0;
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (isl_int_is_zero(bmap->ineq[i][pos]))
+ continue;
+ if (!isl_basic_map_is_div_constraint(bmap, bmap->ineq[i], div))
+ return 0;
+ }
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (!isl_int_is_zero(bmap->div[i][1+pos]))
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Remove divs that don't occur in any of the constraints or other divs.
+ * These can arise when dropping constraints from a basic map or
+ * when the divs of a basic map have been temporarily aligned
+ * with the divs of another basic map.
+ */
+static struct isl_basic_map *remove_redundant_divs(struct isl_basic_map *bmap)
+{
+ int i;
+
+ if (!bmap)
+ return NULL;
+
+ for (i = bmap->n_div-1; i >= 0; --i) {
+ if (!div_is_redundant(bmap, i))
+ continue;
+ bmap = isl_basic_map_drop_div(bmap, i);
+ }
+ return bmap;
+}
+
+struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap)
+{
+ bmap = remove_redundant_divs(bmap);
+ if (!bmap)
+ return NULL;
+ ISL_F_SET(bmap, ISL_BASIC_SET_FINAL);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_finalize((struct isl_basic_map *)bset);
+}
+
+struct isl_set *isl_set_finalize(struct isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return NULL;
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_finalize(set->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+ return set;
+error:
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_map *isl_map_finalize(struct isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_finalize(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+
+/* Remove definition of any div that is defined in terms of the given variable.
+ * The div itself is not removed. Functions such as
+ * eliminate_divs_ineq depend on the other divs remaining in place.
+ */
+static struct isl_basic_map *remove_dependent_vars(struct isl_basic_map *bmap,
+ int pos)
+{
+ int i;
+
+ if (!bmap)
+ return NULL;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (isl_int_is_zero(bmap->div[i][1+1+pos]))
+ continue;
+ isl_int_set_si(bmap->div[i][0], 0);
+ }
+ return bmap;
+}
+
+/* Eliminate the specified variables from the constraints using
+ * Fourier-Motzkin. The variables themselves are not removed.
+ */
+struct isl_basic_map *isl_basic_map_eliminate_vars(
+ struct isl_basic_map *bmap, unsigned pos, unsigned n)
+{
+ int d;
+ int i, j, k;
+ unsigned total;
+ int need_gauss = 0;
+
+ if (n == 0)
+ return bmap;
+ if (!bmap)
+ return NULL;
+ total = isl_basic_map_total_dim(bmap);
+
+ bmap = isl_basic_map_cow(bmap);
+ for (d = pos + n - 1; d >= 0 && d >= pos; --d)
+ bmap = remove_dependent_vars(bmap, d);
+ if (!bmap)
+ return NULL;
+
+ for (d = pos + n - 1;
+ d >= 0 && d >= total - bmap->n_div && d >= pos; --d)
+ isl_seq_clr(bmap->div[d-(total-bmap->n_div)], 2+total);
+ for (d = pos + n - 1; d >= 0 && d >= pos; --d) {
+ int n_lower, n_upper;
+ if (!bmap)
+ return NULL;
+ for (i = 0; i < bmap->n_eq; ++i) {
+ if (isl_int_is_zero(bmap->eq[i][1+d]))
+ continue;
+ eliminate_var_using_equality(bmap, d, bmap->eq[i], 0, NULL);
+ isl_basic_map_drop_equality(bmap, i);
+ need_gauss = 1;
+ break;
+ }
+ if (i < bmap->n_eq)
+ continue;
+ n_lower = 0;
+ n_upper = 0;
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (isl_int_is_pos(bmap->ineq[i][1+d]))
+ n_lower++;
+ else if (isl_int_is_neg(bmap->ineq[i][1+d]))
+ n_upper++;
+ }
+ bmap = isl_basic_map_extend_constraints(bmap,
+ 0, n_lower * n_upper);
+ if (!bmap)
+ goto error;
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ int last;
+ if (isl_int_is_zero(bmap->ineq[i][1+d]))
+ continue;
+ last = -1;
+ for (j = 0; j < i; ++j) {
+ if (isl_int_is_zero(bmap->ineq[j][1+d]))
+ continue;
+ last = j;
+ if (isl_int_sgn(bmap->ineq[i][1+d]) ==
+ isl_int_sgn(bmap->ineq[j][1+d]))
+ continue;
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->ineq[k], bmap->ineq[i],
+ 1+total);
+ isl_seq_elim(bmap->ineq[k], bmap->ineq[j],
+ 1+d, 1+total, NULL);
+ }
+ isl_basic_map_drop_inequality(bmap, i);
+ i = last + 1;
+ }
+ if (n_lower > 0 && n_upper > 0) {
+ bmap = isl_basic_map_normalize_constraints(bmap);
+ bmap = isl_basic_map_remove_duplicate_constraints(bmap,
+ NULL, 0);
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ bmap = isl_basic_map_remove_redundancies(bmap);
+ need_gauss = 0;
+ if (!bmap)
+ goto error;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ break;
+ }
+ }
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_NORMALIZED);
+ if (need_gauss)
+ bmap = isl_basic_map_gauss(bmap, NULL);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_eliminate_vars(
+ struct isl_basic_set *bset, unsigned pos, unsigned n)
+{
+ return (struct isl_basic_set *)isl_basic_map_eliminate_vars(
+ (struct isl_basic_map *)bset, pos, n);
+}
+
+/* Eliminate the specified n dimensions starting at first from the
+ * constraints, without removing the dimensions from the space.
+ * If the set is rational, the dimensions are eliminated using Fourier-Motzkin.
+ * Otherwise, they are projected out and the original space is restored.
+ */
+__isl_give isl_basic_map *isl_basic_map_eliminate(
+ __isl_take isl_basic_map *bmap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_space *space;
+
+ if (!bmap)
+ return NULL;
+ if (n == 0)
+ return bmap;
+
+ if (first + n > isl_basic_map_dim(bmap, type) || first + n < first)
+ isl_die(bmap->ctx, isl_error_invalid,
+ "index out of bounds", goto error);
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL)) {
+ first += isl_basic_map_offset(bmap, type) - 1;
+ bmap = isl_basic_map_eliminate_vars(bmap, first, n);
+ return isl_basic_map_finalize(bmap);
+ }
+
+ space = isl_basic_map_get_space(bmap);
+ bmap = isl_basic_map_project_out(bmap, type, first, n);
+ bmap = isl_basic_map_insert_dims(bmap, type, first, n);
+ bmap = isl_basic_map_reset_space(bmap, space);
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_eliminate(
+ __isl_take isl_basic_set *bset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_basic_map_eliminate(bset, type, first, n);
+}
+
+/* Don't assume equalities are in order, because align_divs
+ * may have changed the order of the divs.
+ */
+static void compute_elimination_index(struct isl_basic_map *bmap, int *elim)
+{
+ int d, i;
+ unsigned total;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ for (d = 0; d < total; ++d)
+ elim[d] = -1;
+ for (i = 0; i < bmap->n_eq; ++i) {
+ for (d = total - 1; d >= 0; --d) {
+ if (isl_int_is_zero(bmap->eq[i][1+d]))
+ continue;
+ elim[d] = i;
+ break;
+ }
+ }
+}
+
+static void set_compute_elimination_index(struct isl_basic_set *bset, int *elim)
+{
+ compute_elimination_index((struct isl_basic_map *)bset, elim);
+}
+
+static int reduced_using_equalities(isl_int *dst, isl_int *src,
+ struct isl_basic_map *bmap, int *elim)
+{
+ int d;
+ int copied = 0;
+ unsigned total;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+ for (d = total - 1; d >= 0; --d) {
+ if (isl_int_is_zero(src[1+d]))
+ continue;
+ if (elim[d] == -1)
+ continue;
+ if (!copied) {
+ isl_seq_cpy(dst, src, 1 + total);
+ copied = 1;
+ }
+ isl_seq_elim(dst, bmap->eq[elim[d]], 1 + d, 1 + total, NULL);
+ }
+ return copied;
+}
+
+static int set_reduced_using_equalities(isl_int *dst, isl_int *src,
+ struct isl_basic_set *bset, int *elim)
+{
+ return reduced_using_equalities(dst, src,
+ (struct isl_basic_map *)bset, elim);
+}
+
+static struct isl_basic_set *isl_basic_set_reduce_using_equalities(
+ struct isl_basic_set *bset, struct isl_basic_set *context)
+{
+ int i;
+ int *elim;
+
+ if (!bset || !context)
+ goto error;
+
+ if (context->n_eq == 0) {
+ isl_basic_set_free(context);
+ return bset;
+ }
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ goto error;
+
+ elim = isl_alloc_array(bset->ctx, int, isl_basic_set_n_dim(bset));
+ if (!elim)
+ goto error;
+ set_compute_elimination_index(context, elim);
+ for (i = 0; i < bset->n_eq; ++i)
+ set_reduced_using_equalities(bset->eq[i], bset->eq[i],
+ context, elim);
+ for (i = 0; i < bset->n_ineq; ++i)
+ set_reduced_using_equalities(bset->ineq[i], bset->ineq[i],
+ context, elim);
+ isl_basic_set_free(context);
+ free(elim);
+ bset = isl_basic_set_simplify(bset);
+ bset = isl_basic_set_finalize(bset);
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_basic_set_free(context);
+ return NULL;
+}
+
+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;
+
+ if (!bset)
+ return NULL;
+
+ size = round_up(4 * (context->n_ineq+1) / 3 - 1);
+ bits = ffs(size) - 1;
+ ctx = isl_basic_set_get_ctx(bset);
+ index = isl_calloc_array(ctx, isl_int **, size);
+ if (!index)
+ 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]))
+ continue;
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ goto error;
+ isl_basic_set_drop_inequality(bset, k);
+ --k;
+ }
+ free(index);
+ return bset;
+error:
+ free(index);
+ return bset;
+}
+
+/* Remove constraints from "bmap" that are identical to constraints
+ * in "context" or that are more relaxed (greater constant term).
+ *
+ * We perform the test for shifted copies on the pure constraints
+ * in remove_shifted_constraints.
+ */
+static __isl_give isl_basic_map *isl_basic_map_remove_shifted_constraints(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_map *context)
+{
+ isl_basic_set *bset, *bset_context;
+
+ if (!bmap || !context)
+ goto error;
+
+ if (bmap->n_ineq == 0 || context->n_ineq == 0) {
+ isl_basic_map_free(context);
+ return bmap;
+ }
+
+ context = isl_basic_map_align_divs(context, bmap);
+ bmap = isl_basic_map_align_divs(bmap, context);
+
+ bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
+ bset_context = isl_basic_map_underlying_set(context);
+ bset = remove_shifted_constraints(bset, bset_context);
+ isl_basic_set_free(bset_context);
+
+ bmap = isl_basic_map_overlying_set(bset, bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_map_free(context);
+ return NULL;
+}
+
+/* Does the (linear part of a) constraint "c" involve any of the "len"
+ * "relevant" dimensions?
+ */
+static int is_related(isl_int *c, int len, int *relevant)
+{
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ if (!relevant[i])
+ continue;
+ if (!isl_int_is_zero(c[i]))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Drop constraints from "bset" that do not involve any of
+ * the dimensions marked "relevant".
+ */
+static __isl_give isl_basic_set *drop_unrelated_constraints(
+ __isl_take isl_basic_set *bset, int *relevant)
+{
+ int i, dim;
+
+ dim = isl_basic_set_dim(bset, isl_dim_set);
+ for (i = 0; i < dim; ++i)
+ if (!relevant[i])
+ break;
+ if (i >= dim)
+ return bset;
+
+ for (i = bset->n_eq - 1; i >= 0; --i)
+ if (!is_related(bset->eq[i] + 1, dim, relevant))
+ isl_basic_set_drop_equality(bset, i);
+
+ for (i = bset->n_ineq - 1; i >= 0; --i)
+ if (!is_related(bset->ineq[i] + 1, dim, relevant))
+ isl_basic_set_drop_inequality(bset, i);
+
+ return bset;
+}
+
+/* Update the groups in "group" based on the (linear part of a) constraint "c".
+ *
+ * In particular, for any variable involved in the constraint,
+ * find the actual group id from before and replace the group
+ * of the corresponding variable by the minimal group of all
+ * the variables involved in the constraint considered so far
+ * (if this minimum is smaller) or replace the minimum by this group
+ * (if the minimum is larger).
+ *
+ * At the end, all the variables in "c" will (indirectly) point
+ * to the minimal of the groups that they referred to originally.
+ */
+static void update_groups(int dim, int *group, isl_int *c)
+{
+ int j;
+ int min = dim;
+
+ for (j = 0; j < dim; ++j) {
+ if (isl_int_is_zero(c[j]))
+ continue;
+ while (group[j] >= 0 && group[group[j]] != group[j])
+ group[j] = group[group[j]];
+ if (group[j] == min)
+ continue;
+ if (group[j] < min) {
+ if (min >= 0 && min < dim)
+ group[min] = group[j];
+ min = group[j];
+ } else
+ group[group[j]] = min;
+ }
+}
+
+/* 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 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.
+ * 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.
+ * 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
+ * the variables.
+ *
+ * After computing the groups, we drop constraints that do not involve
+ * any variables in the -1 group.
+ */
+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);
+
+ if (!group)
+ goto error;
+
+ for (i = 0; i < dim; ++i) {
+ for (j = 0; j < bset->n_eq; ++j)
+ if (!isl_int_is_zero(bset->eq[j][1 + i]))
+ break;
+ if (j < bset->n_eq) {
+ group[i] = -1;
+ continue;
+ }
+ for (j = 0; j < bset->n_ineq; ++j)
+ if (!isl_int_is_zero(bset->ineq[j][1 + i]))
+ break;
+ if (j < bset->n_ineq)
+ 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;
+ }
+
+ 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;
+error:
+ free(group);
+ return isl_basic_set_free(context);
+}
+
+/* Remove all information from bset that is redundant in the context
+ * of context. Both bset and context are assumed to be full-dimensional.
+ *
+ * We first remove the inequalities from "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".
+ * Note that this removal of constraints cannot be replaced by
+ * a factorization because factors in "bset" may still be connected
+ * to each other through constraints in "context".
+ *
+ * If there are any inequalities left, we construct a tableau for
+ * the context and then add the inequalities of "bset".
+ * Before adding these inequalities, we freeze all constraints such that
+ * they won't be considered redundant in terms of the constraints of "bset".
+ * Then we detect all redundant constraints (among the
+ * constraints that weren't frozen), first by checking for redundancy in the
+ * the tableau and then by checking if replacing a constraint by its negation
+ * would lead to an empty set. This last step is fairly expensive
+ * and could be optimized by more reuse of the tableau.
+ * 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)
+{
+ int i, k;
+ isl_basic_set *combined = NULL;
+ struct isl_tab *tab = NULL;
+ unsigned context_ineq;
+ unsigned total;
+
+ if (!bset || !context)
+ goto error;
+
+ if (isl_basic_set_is_universe(bset)) {
+ isl_basic_set_free(context);
+ return bset;
+ }
+
+ if (isl_basic_set_is_universe(context)) {
+ isl_basic_set_free(context);
+ return bset;
+ }
+
+ bset = remove_shifted_constraints(bset, context);
+ if (!bset)
+ goto error;
+ if (bset->n_ineq == 0)
+ goto done;
+
+ context = drop_irrelevant_constraints(context, bset);
+ if (!context)
+ goto error;
+ if (isl_basic_set_is_universe(context)) {
+ isl_basic_set_free(context);
+ return bset;
+ }
+
+ 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)
+ 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)
+ goto error;
+ bset = isl_basic_set_add_constraints(combined, bset, 0);
+ combined = NULL;
+ if (!bset)
+ 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) {
+ int is_empty;
+ if (tab->con[i].is_redundant)
+ 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);
+ if (is_empty < 0)
+ goto error;
+ isl_basic_set_free(combined);
+ combined = NULL;
+ if (!is_empty)
+ tab->con[i].is_redundant = 0;
+ }
+ for (i = 0; i < context_ineq; ++i)
+ tab->con[i].is_redundant = 1;
+ bset = isl_basic_set_update_from_tab(bset, 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);
+ return bset;
+error:
+ isl_tab_free(tab);
+ isl_basic_set_free(combined);
+ isl_basic_set_free(context);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* 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
+ * redundant in the context of the equalities and inequalities of
+ * context are removed.
+ *
+ * First of all, we drop those constraints from "context"
+ * 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.
+ *
+ * If two constraints are mutually redundant, then uset_gist_full
+ * will remove the second of those constraints. We therefore first
+ * sort the constraints so that constraints not involving existentially
+ * quantified variables are given precedence over those that do.
+ * We have to perform this sorting before the variable compression,
+ * because that may effect the order of the variables.
+ */
+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_basic_set *aff;
+ isl_basic_set *aff_context;
+ unsigned total;
+
+ if (!bset || !context)
+ goto error;
+
+ context = drop_irrelevant_constraints(context, 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);
+ if (!aff)
+ goto error;
+ if (isl_basic_set_plain_is_empty(aff)) {
+ isl_basic_set_free(bset);
+ isl_basic_set_free(context);
+ return aff;
+ }
+ bset = isl_basic_set_sort_constraints(bset);
+ if (aff->n_eq == 0) {
+ isl_basic_set_free(aff);
+ return uset_gist_full(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);
+ 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));
+
+ 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 = isl_basic_set_reduce_using_equalities(bset, aff_context);
+
+ if (bset) {
+ ISL_F_SET(bset, ISL_BASIC_SET_NO_IMPLICIT);
+ ISL_F_SET(bset, ISL_BASIC_SET_NO_REDUNDANT);
+ }
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_basic_set_free(context);
+ 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.
+ *
+ * The core computation is performed on the pure constraints.
+ * When we add back the meaning of the integer divisions, we need
+ * to (re)introduce the div constraints. If we happen to have
+ * discovered that some of these integer divisions are equal to
+ * some affine combination of other variables, then these div
+ * constraints may end up getting simplified in terms of the equalities,
+ * resulting in extra inequalities on the other variables that
+ * may have been removed already or that may not even have been
+ * part of the input. We try and remove those constraints of
+ * this form that are most obviously redundant with respect to
+ * the context. We also remove those div constraints that are
+ * redundant with respect to the other constraints in the result.
+ */
+struct isl_basic_map *isl_basic_map_gist(struct isl_basic_map *bmap,
+ struct isl_basic_map *context)
+{
+ isl_basic_set *bset, *eq;
+ isl_basic_map *eq_bmap;
+ unsigned n_div, n_eq, n_ineq;
+
+ if (!bmap || !context)
+ goto error;
+
+ if (isl_basic_map_is_universe(bmap)) {
+ isl_basic_map_free(context);
+ return bmap;
+ }
+ if (isl_basic_map_plain_is_empty(context)) {
+ isl_space *space = isl_basic_map_get_space(bmap);
+ isl_basic_map_free(bmap);
+ isl_basic_map_free(context);
+ return isl_basic_map_universe(space);
+ }
+ if (isl_basic_map_plain_is_empty(bmap)) {
+ isl_basic_map_free(context);
+ return bmap;
+ }
+
+ bmap = isl_basic_map_remove_redundancies(bmap);
+ context = isl_basic_map_remove_redundancies(context);
+ 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);
+
+ bset = uset_gist(isl_basic_map_underlying_set(isl_basic_map_copy(bmap)),
+ isl_basic_map_underlying_set(isl_basic_map_copy(context)));
+
+ if (!bset || bset->n_eq == 0 || n_div == 0 ||
+ isl_basic_set_plain_is_empty(bset)) {
+ isl_basic_map_free(context);
+ return isl_basic_map_overlying_set(bset, bmap);
+ }
+
+ n_eq = bset->n_eq;
+ n_ineq = bset->n_ineq;
+ eq = isl_basic_set_copy(bset);
+ eq = isl_basic_set_cow(bset);
+ if (isl_basic_set_free_inequality(eq, n_ineq) < 0)
+ eq = isl_basic_set_free(eq);
+ if (isl_basic_set_free_equality(bset, n_eq) < 0)
+ bset = isl_basic_set_free(bset);
+
+ eq_bmap = isl_basic_map_overlying_set(eq, isl_basic_map_copy(bmap));
+ eq_bmap = isl_basic_map_remove_shifted_constraints(eq_bmap, context);
+ bmap = isl_basic_map_overlying_set(bset, bmap);
+ bmap = isl_basic_map_intersect(bmap, eq_bmap);
+ bmap = isl_basic_map_remove_redundancies(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ isl_basic_map_free(context);
+ return NULL;
+}
+
+/*
+ * Assumes context has no implicit divs.
+ */
+__isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
+ __isl_take isl_basic_map *context)
+{
+ int i;
+
+ if (!map || !context)
+ goto error;
+
+ if (isl_basic_map_plain_is_empty(context)) {
+ isl_space *space = isl_map_get_space(map);
+ isl_map_free(map);
+ isl_basic_map_free(context);
+ return isl_map_universe(space);
+ }
+
+ context = isl_basic_map_remove_redundancies(context);
+ map = isl_map_cow(map);
+ if (!map || !context)
+ goto error;
+ isl_assert(map->ctx, isl_space_is_equal(map->dim, context->dim), goto error);
+ map = isl_map_compute_divs(map);
+ if (!map)
+ goto error;
+ for (i = map->n - 1; i >= 0; --i) {
+ map->p[i] = isl_basic_map_gist(map->p[i],
+ isl_basic_map_copy(context));
+ if (!map->p[i])
+ goto error;
+ if (isl_basic_map_plain_is_empty(map->p[i])) {
+ isl_basic_map_free(map->p[i]);
+ if (i != map->n - 1)
+ map->p[i] = map->p[map->n - 1];
+ map->n--;
+ }
+ }
+ isl_basic_map_free(context);
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ 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.
+ *
+ * If "map" is already the universe, then we cannot make it any simpler.
+ * Similarly, if "context" is the universe, then we cannot exploit it
+ * to simplify "map"
+ * If "map" and "context" are identical to each other, then we can
+ * return the corresponding universe.
+ *
+ * If none of these cases apply, we have to work a bit harder.
+ */
+static __isl_give isl_map *map_gist(__isl_take isl_map *map,
+ __isl_take isl_map *context)
+{
+ int equal;
+ int is_universe;
+
+ is_universe = isl_map_plain_is_universe(map);
+ if (is_universe >= 0 && !is_universe)
+ is_universe = isl_map_plain_is_universe(context);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_map_free(context);
+ return map;
+ }
+
+ equal = isl_map_plain_is_equal(map, context);
+ if (equal < 0)
+ goto error;
+ if (equal) {
+ isl_map *res = isl_map_universe(isl_map_get_space(map));
+ isl_map_free(map);
+ isl_map_free(context);
+ return res;
+ }
+
+ context = isl_map_compute_divs(context);
+ return isl_map_gist_basic_map(map, isl_map_simple_hull(context));
+error:
+ isl_map_free(map);
+ isl_map_free(context);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+ __isl_take isl_map *context)
+{
+ return isl_map_align_params_map_map_and(map, context, &map_gist);
+}
+
+struct isl_basic_set *isl_basic_set_gist(struct isl_basic_set *bset,
+ struct isl_basic_set *context)
+{
+ return (struct isl_basic_set *)isl_basic_map_gist(
+ (struct isl_basic_map *)bset, (struct isl_basic_map *)context);
+}
+
+__isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *context)
+{
+ return (struct isl_set *)isl_map_gist_basic_map((struct isl_map *)set,
+ (struct isl_basic_map *)context);
+}
+
+__isl_give isl_set *isl_set_gist_params_basic_set(__isl_take isl_set *set,
+ __isl_take isl_basic_set *context)
+{
+ isl_space *space = isl_set_get_space(set);
+ isl_basic_set *dom_context = isl_basic_set_universe(space);
+ dom_context = isl_basic_set_intersect_params(dom_context, context);
+ return isl_set_gist_basic_set(set, dom_context);
+}
+
+__isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
+ __isl_take isl_set *context)
+{
+ return (struct isl_set *)isl_map_gist((struct isl_map *)set,
+ (struct isl_map *)context);
+}
+
+__isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
+ __isl_take isl_set *context)
+{
+ isl_map *map_context = isl_map_universe(isl_map_get_space(map));
+ map_context = isl_map_intersect_domain(map_context, context);
+ return isl_map_gist(map, map_context);
+}
+
+__isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
+ __isl_take isl_set *context)
+{
+ isl_map *map_context = isl_map_universe(isl_map_get_space(map));
+ map_context = isl_map_intersect_range(map_context, context);
+ return isl_map_gist(map, map_context);
+}
+
+__isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
+ __isl_take isl_set *context)
+{
+ isl_map *map_context = isl_map_universe(isl_map_get_space(map));
+ map_context = isl_map_intersect_params(map_context, context);
+ return isl_map_gist(map, map_context);
+}
+
+__isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
+ __isl_take isl_set *context)
+{
+ return isl_map_gist_params(set, context);
+}
+
+/* Quick check to see if two basic maps are disjoint.
+ * In particular, we reduce the equalities and inequalities of
+ * one basic map in the context of the equalities of the other
+ * basic map and check if we get a contradiction.
+ */
+int isl_basic_map_plain_is_disjoint(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2)
+{
+ struct isl_vec *v = NULL;
+ int *elim = NULL;
+ unsigned total;
+ int i;
+
+ if (!bmap1 || !bmap2)
+ return -1;
+ isl_assert(bmap1->ctx, isl_space_is_equal(bmap1->dim, bmap2->dim),
+ return -1);
+ if (bmap1->n_div || bmap2->n_div)
+ return 0;
+ if (!bmap1->n_eq && !bmap2->n_eq)
+ return 0;
+
+ total = isl_space_dim(bmap1->dim, isl_dim_all);
+ if (total == 0)
+ return 0;
+ v = isl_vec_alloc(bmap1->ctx, 1 + total);
+ if (!v)
+ goto error;
+ elim = isl_alloc_array(bmap1->ctx, int, total);
+ if (!elim)
+ goto error;
+ compute_elimination_index(bmap1, elim);
+ for (i = 0; i < bmap2->n_eq; ++i) {
+ int reduced;
+ reduced = reduced_using_equalities(v->block.data, bmap2->eq[i],
+ bmap1, elim);
+ if (reduced && !isl_int_is_zero(v->block.data[0]) &&
+ isl_seq_first_non_zero(v->block.data + 1, total) == -1)
+ goto disjoint;
+ }
+ for (i = 0; i < bmap2->n_ineq; ++i) {
+ int reduced;
+ reduced = reduced_using_equalities(v->block.data,
+ bmap2->ineq[i], bmap1, elim);
+ if (reduced && isl_int_is_neg(v->block.data[0]) &&
+ isl_seq_first_non_zero(v->block.data + 1, total) == -1)
+ goto disjoint;
+ }
+ compute_elimination_index(bmap2, elim);
+ for (i = 0; i < bmap1->n_ineq; ++i) {
+ int reduced;
+ reduced = reduced_using_equalities(v->block.data,
+ bmap1->ineq[i], bmap2, elim);
+ if (reduced && isl_int_is_neg(v->block.data[0]) &&
+ isl_seq_first_non_zero(v->block.data + 1, total) == -1)
+ goto disjoint;
+ }
+ isl_vec_free(v);
+ free(elim);
+ return 0;
+disjoint:
+ isl_vec_free(v);
+ free(elim);
+ return 1;
+error:
+ isl_vec_free(v);
+ free(elim);
+ return -1;
+}
+
+int isl_basic_set_plain_is_disjoint(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2)
+{
+ return isl_basic_map_plain_is_disjoint((struct isl_basic_map *)bset1,
+ (struct isl_basic_map *)bset2);
+}
+
+/* Are "map1" and "map2" obviously disjoint?
+ *
+ * If one of them is empty or if they live in different spaces (ignoring
+ * parameters), then they are clearly disjoint.
+ *
+ * If they have different parameters, then we skip any further tests.
+ *
+ * If they are obviously equal, but not obviously empty, then we will
+ * not be able to detect if they are disjoint.
+ *
+ * Otherwise we check if each basic map in "map1" is obviously disjoint
+ * from each basic map in "map2".
+ */
+int isl_map_plain_is_disjoint(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2)
+{
+ int i, j;
+ int disjoint;
+ int intersect;
+ int match;
+
+ if (!map1 || !map2)
+ return -1;
+
+ disjoint = isl_map_plain_is_empty(map1);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ disjoint = isl_map_plain_is_empty(map2);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ match = isl_space_tuple_is_equal(map1->dim, isl_dim_in,
+ map2->dim, isl_dim_in);
+ if (match < 0 || !match)
+ return match < 0 ? -1 : 1;
+
+ match = isl_space_tuple_is_equal(map1->dim, isl_dim_out,
+ map2->dim, isl_dim_out);
+ if (match < 0 || !match)
+ return match < 0 ? -1 : 1;
+
+ match = isl_space_match(map1->dim, isl_dim_param,
+ map2->dim, isl_dim_param);
+ if (match < 0 || !match)
+ return match < 0 ? -1 : 0;
+
+ intersect = isl_map_plain_is_equal(map1, map2);
+ if (intersect < 0 || intersect)
+ return intersect < 0 ? -1 : 0;
+
+ for (i = 0; i < map1->n; ++i) {
+ for (j = 0; j < map2->n; ++j) {
+ int d = isl_basic_map_plain_is_disjoint(map1->p[i],
+ map2->p[j]);
+ if (d != 1)
+ return d;
+ }
+ }
+ return 1;
+}
+
+/* Are "map1" and "map2" disjoint?
+ *
+ * They are disjoint if they are "obviously disjoint" or if one of them
+ * is empty. Otherwise, they are not disjoint if one of them is universal.
+ * If none of these cases apply, we compute the intersection and see if
+ * the result is empty.
+ */
+int isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ int disjoint;
+ int intersect;
+ isl_map *test;
+
+ disjoint = isl_map_plain_is_disjoint(map1, map2);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ disjoint = isl_map_is_empty(map1);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ disjoint = isl_map_is_empty(map2);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ intersect = isl_map_plain_is_universe(map1);
+ if (intersect < 0 || intersect)
+ return intersect < 0 ? -1 : 0;
+
+ intersect = isl_map_plain_is_universe(map2);
+ if (intersect < 0 || intersect)
+ return intersect < 0 ? -1 : 0;
+
+ test = isl_map_intersect(isl_map_copy(map1), isl_map_copy(map2));
+ disjoint = isl_map_is_empty(test);
+ isl_map_free(test);
+
+ return disjoint;
+}
+
+/* Are "bmap1" and "bmap2" disjoint?
+ *
+ * They are disjoint if they are "obviously disjoint" or if one of them
+ * is empty. Otherwise, they are not disjoint if one of them is universal.
+ * If none of these cases apply, we compute the intersection and see if
+ * the result is empty.
+ */
+int isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
+ __isl_keep isl_basic_map *bmap2)
+{
+ int disjoint;
+ int intersect;
+ isl_basic_map *test;
+
+ disjoint = isl_basic_map_plain_is_disjoint(bmap1, bmap2);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ disjoint = isl_basic_map_is_empty(bmap1);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ disjoint = isl_basic_map_is_empty(bmap2);
+ if (disjoint < 0 || disjoint)
+ return disjoint;
+
+ intersect = isl_basic_map_is_universe(bmap1);
+ if (intersect < 0 || intersect)
+ return intersect < 0 ? -1 : 0;
+
+ intersect = isl_basic_map_is_universe(bmap2);
+ if (intersect < 0 || intersect)
+ return intersect < 0 ? -1 : 0;
+
+ test = isl_basic_map_intersect(isl_basic_map_copy(bmap1),
+ isl_basic_map_copy(bmap2));
+ disjoint = isl_basic_map_is_empty(test);
+ isl_basic_map_free(test);
+
+ return disjoint;
+}
+
+/* Are "bset1" and "bset2" disjoint?
+ */
+int isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1,
+ __isl_keep isl_basic_set *bset2)
+{
+ return isl_basic_map_is_disjoint(bset1, bset2);
+}
+
+int isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
+ __isl_keep isl_set *set2)
+{
+ return isl_map_plain_is_disjoint((struct isl_map *)set1,
+ (struct isl_map *)set2);
+}
+
+/* Are "set1" and "set2" disjoint?
+ */
+int isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ return isl_map_is_disjoint(set1, set2);
+}
+
+int isl_set_fast_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ return isl_set_plain_is_disjoint(set1, set2);
+}
+
+/* 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.
+ *
+ * We first check that
+ * - the bounds are opposites of each other (except for the constant
+ * term)
+ * - the bounds do not reference any other div
+ * - no div is defined in terms of this div
+ *
+ * Let m be the size of the range allowed on the div by the bounds.
+ * That is, the bounds are of the form
+ *
+ * e <= a <= e + m - 1
+ *
+ * with e some expression in the other variables.
+ * We look for another div b such that no third div is defined in terms
+ * of this second div b and such that in any constraint that contains
+ * a (except for the given lower and upper bound), also contains b
+ * with a coefficient that is m times that of b.
+ * That is, all constraints (execpt for the lower and upper bound)
+ * are of the form
+ *
+ * e + f (a + m b) >= 0
+ *
+ * If so, we return b so that "a + m b" can be replaced by
+ * a single div "c = a + m b".
+ */
+static int div_find_coalesce(struct isl_basic_map *bmap, int *pairs,
+ unsigned div, unsigned l, unsigned u)
+{
+ int i, j;
+ unsigned dim;
+ int coalesce = -1;
+
+ if (bmap->n_div <= 1)
+ return -1;
+ dim = isl_space_dim(bmap->dim, isl_dim_all);
+ if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim, div) != -1)
+ return -1;
+ if (isl_seq_first_non_zero(bmap->ineq[l] + 1 + dim + div + 1,
+ bmap->n_div - div - 1) != -1)
+ return -1;
+ if (!isl_seq_is_neg(bmap->ineq[l] + 1, bmap->ineq[u] + 1,
+ dim + bmap->n_div))
+ return -1;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (!isl_int_is_zero(bmap->div[i][1 + 1 + dim + div]))
+ return -1;
+ }
+
+ isl_int_add(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
+ if (isl_int_is_neg(bmap->ineq[l][0])) {
+ isl_int_sub(bmap->ineq[l][0],
+ bmap->ineq[l][0], bmap->ineq[u][0]);
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_set_to_empty(bmap);
+ isl_basic_map_free(bmap);
+ return -1;
+ }
+ isl_int_add_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (i == div)
+ continue;
+ if (!pairs[i])
+ continue;
+ for (j = 0; j < bmap->n_div; ++j) {
+ if (isl_int_is_zero(bmap->div[j][0]))
+ continue;
+ if (!isl_int_is_zero(bmap->div[j][1 + 1 + dim + i]))
+ break;
+ }
+ if (j < bmap->n_div)
+ continue;
+ for (j = 0; j < bmap->n_ineq; ++j) {
+ 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 + i]))
+ break;
+ isl_int_mul(bmap->ineq[j][1 + dim + div],
+ bmap->ineq[j][1 + dim + div],
+ bmap->ineq[l][0]);
+ valid = isl_int_eq(bmap->ineq[j][1 + dim + div],
+ bmap->ineq[j][1 + dim + i]);
+ isl_int_divexact(bmap->ineq[j][1 + dim + div],
+ bmap->ineq[j][1 + dim + div],
+ bmap->ineq[l][0]);
+ if (!valid)
+ break;
+ }
+ if (j < bmap->n_ineq)
+ continue;
+ coalesce = i;
+ break;
+ }
+ isl_int_sub_ui(bmap->ineq[l][0], bmap->ineq[l][0], 1);
+ isl_int_sub(bmap->ineq[l][0], bmap->ineq[l][0], bmap->ineq[u][0]);
+ return coalesce;
+}
+
+/* Given a lower and an upper bound on div i, construct an inequality
+ * that when nonnegative ensures that this pair of bounds always allows
+ * for an integer value of the given div.
+ * The lower bound is inequality l, while the upper bound is inequality u.
+ * The constructed inequality is stored in ineq.
+ * g, fl, fu are temporary scalars.
+ *
+ * Let the upper bound be
+ *
+ * -n_u a + e_u >= 0
+ *
+ * and the lower bound
+ *
+ * n_l a + e_l >= 0
+ *
+ * Let n_u = f_u g and n_l = f_l g, with g = gcd(n_u, n_l).
+ * We have
+ *
+ * - f_u e_l <= f_u f_l g a <= f_l e_u
+ *
+ * Since all variables are integer valued, this is equivalent to
+ *
+ * - f_u e_l - (f_u - 1) <= f_u f_l g a <= f_l e_u + (f_l - 1)
+ *
+ * If this interval is at least f_u f_l g, then it contains at least
+ * one integer value for a.
+ * That is, the test constraint is
+ *
+ * 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)
+{
+ 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],
+ 1 + dim + bmap->n_div);
+ 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);
+}
+
+/* Remove more kinds of divs that are not strictly needed.
+ * In particular, if all pairs of lower and upper bounds on a div
+ * are such that they allow at least one integer value of the div,
+ * the we can eliminate the div using Fourier-Motzkin without
+ * introducing any spurious solutions.
+ */
+static struct isl_basic_map *drop_more_redundant_divs(
+ struct isl_basic_map *bmap, int *pairs, int n)
+{
+ struct isl_tab *tab = NULL;
+ struct isl_vec *vec = NULL;
+ unsigned dim;
+ int remove = -1;
+ isl_int g, fl, fu;
+
+ isl_int_init(g);
+ isl_int_init(fl);
+ isl_int_init(fu);
+
+ if (!bmap)
+ goto error;
+
+ dim = isl_space_dim(bmap->dim, isl_dim_all);
+ vec = isl_vec_alloc(bmap->ctx, 1 + dim + bmap->n_div);
+ if (!vec)
+ goto error;
+
+ tab = isl_tab_from_basic_map(bmap, 0);
+
+ while (n > 0) {
+ int i, l, u;
+ int best = -1;
+ enum isl_lp_result res;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (!pairs[i])
+ continue;
+ if (best >= 0 && pairs[best] <= pairs[i])
+ continue;
+ best = i;
+ }
+
+ i = best;
+ for (l = 0; l < bmap->n_ineq; ++l) {
+ if (!isl_int_is_pos(bmap->ineq[l][1 + dim + i]))
+ continue;
+ for (u = 0; u < bmap->n_ineq; ++u) {
+ if (!isl_int_is_neg(bmap->ineq[u][1 + dim + i]))
+ continue;
+ construct_test_ineq(bmap, i, l, u,
+ vec->el, g, fl, fu);
+ res = isl_tab_min(tab, vec->el,
+ bmap->ctx->one, &g, NULL, 0);
+ if (res == isl_lp_error)
+ goto error;
+ if (res == isl_lp_empty) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ break;
+ }
+ if (res != isl_lp_ok || isl_int_is_neg(g))
+ break;
+ }
+ if (u < bmap->n_ineq)
+ break;
+ }
+ if (l == bmap->n_ineq) {
+ remove = i;
+ break;
+ }
+ pairs[i] = 0;
+ --n;
+ }
+
+ isl_tab_free(tab);
+ isl_vec_free(vec);
+
+ isl_int_clear(g);
+ isl_int_clear(fl);
+ isl_int_clear(fu);
+
+ free(pairs);
+
+ if (remove < 0)
+ return bmap;
+
+ bmap = isl_basic_map_remove_dims(bmap, isl_dim_div, remove, 1);
+ return isl_basic_map_drop_redundant_divs(bmap);
+error:
+ free(pairs);
+ isl_basic_map_free(bmap);
+ isl_tab_free(tab);
+ isl_vec_free(vec);
+ isl_int_clear(g);
+ isl_int_clear(fl);
+ isl_int_clear(fu);
+ 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
+ * (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.
+ *
+ * The new div will appear in the location that contains div2.
+ * We need to modify all constraints that contain
+ * div2 = (div - div1) / m
+ * (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,
+ * i.e., the coefficient of div is f.
+ *
+ * Otherwise, we first need to introduce div1 into the constraint.
+ * Let the l be
+ *
+ * div1 + f >=0
+ *
+ * and u
+ *
+ * -div1 + f' >= 0
+ *
+ * A lower bound on div2
+ *
+ * n div2 + t >= 0
+ *
+ * can be replaced by
+ *
+ * (n * (m div 2 + div1) + m t + n f)/g >= 0
+ *
+ * with g = gcd(m,n).
+ * An upper bound
+ *
+ * -n div2 + t >= 0
+ *
+ * can be replaced by
+ *
+ * (-n * (m div2 + div1) + m t + n f')/g >= 0
+ *
+ * These constraint are those that we would obtain from eliminating
+ * div1 using Fourier-Motzkin.
+ *
+ * After all constraints have been modified, we drop the lower and upper
+ * bound and then drop div1.
+ */
+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_int m;
+ unsigned dim, total;
+ int i;
+
+ 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);
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (i == l || i == u)
+ 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);
+ }
+ }
+ 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);
+ isl_basic_map_drop_inequality(bmap, u);
+ } else {
+ isl_basic_map_drop_inequality(bmap, u);
+ isl_basic_map_drop_inequality(bmap, l);
+ }
+ bmap = isl_basic_map_drop_div(bmap, div1);
+ return bmap;
+}
+
+/* First check if we can coalesce any pair of divs and
+ * then continue with dropping more redundant divs.
+ *
+ * We loop over all pairs of lower and upper bounds on a div
+ * with coefficient 1 and -1, respectively, check if there
+ * is any other div "c" with which we can coalesce the div
+ * and if so, perform the coalescing.
+ */
+static struct isl_basic_map *coalesce_or_drop_more_redundant_divs(
+ struct isl_basic_map *bmap, int *pairs, int n)
+{
+ int i, l, u;
+ unsigned dim;
+
+ dim = isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (!pairs[i])
+ continue;
+ for (l = 0; l < bmap->n_ineq; ++l) {
+ if (!isl_int_is_one(bmap->ineq[l][1 + dim + i]))
+ continue;
+ for (u = 0; u < bmap->n_ineq; ++u) {
+ int c;
+
+ if (!isl_int_is_negone(bmap->ineq[u][1+dim+i]))
+ continue;
+ c = div_find_coalesce(bmap, pairs, i, l, u);
+ if (c < 0)
+ continue;
+ free(pairs);
+ bmap = coalesce_divs(bmap, i, c, l, u);
+ return isl_basic_map_drop_redundant_divs(bmap);
+ }
+ }
+ }
+
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+ return bmap;
+
+ return drop_more_redundant_divs(bmap, pairs, n);
+}
+
+/* Remove divs that are not strictly needed.
+ * In particular, if a div only occurs positively (or negatively)
+ * in constraints, then it can simply be dropped.
+ * Also, if a div occurs in only two constraints and if moreover
+ * those two constraints are opposite to each other, except for the constant
+ * term and if the sum of the constant terms is such that for any value
+ * of the other values, there is always at least one integer value of the
+ * div, i.e., if one plus this sum is greater than or equal to
+ * the (absolute value) of the coefficent of the div in the constraints,
+ * then we can also simply drop the div.
+ *
+ * We skip divs that appear in equalities or in the definition of other divs.
+ * Divs that appear in the definition of other divs usually occur in at least
+ * 4 constraints, but the constraints may have been simplified.
+ *
+ * If any divs are left after these simple checks then we move on
+ * to more complicated cases in drop_more_redundant_divs.
+ */
+struct isl_basic_map *isl_basic_map_drop_redundant_divs(
+ struct isl_basic_map *bmap)
+{
+ int i, j;
+ unsigned off;
+ int *pairs = NULL;
+ int n = 0;
+
+ if (!bmap)
+ goto error;
+ if (bmap->n_div == 0)
+ return bmap;
+
+ off = isl_space_dim(bmap->dim, isl_dim_all);
+ pairs = isl_calloc_array(bmap->ctx, int, bmap->n_div);
+ if (!pairs)
+ goto error;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ int pos, neg;
+ int last_pos, last_neg;
+ int redundant;
+ int defined;
+
+ defined = !isl_int_is_zero(bmap->div[i][0]);
+ for (j = i; j < bmap->n_div; ++j)
+ if (!isl_int_is_zero(bmap->div[j][1 + 1 + off + i]))
+ break;
+ if (j < bmap->n_div)
+ continue;
+ for (j = 0; j < bmap->n_eq; ++j)
+ if (!isl_int_is_zero(bmap->eq[j][1 + off + i]))
+ break;
+ if (j < bmap->n_eq)
+ continue;
+ ++n;
+ pos = neg = 0;
+ for (j = 0; j < bmap->n_ineq; ++j) {
+ if (isl_int_is_pos(bmap->ineq[j][1 + off + i])) {
+ last_pos = j;
+ ++pos;
+ }
+ if (isl_int_is_neg(bmap->ineq[j][1 + off + i])) {
+ last_neg = j;
+ ++neg;
+ }
+ }
+ pairs[i] = pos * neg;
+ if (pairs[i] == 0) {
+ for (j = bmap->n_ineq - 1; j >= 0; --j)
+ if (!isl_int_is_zero(bmap->ineq[j][1+off+i]))
+ isl_basic_map_drop_inequality(bmap, j);
+ bmap = isl_basic_map_drop_div(bmap, i);
+ free(pairs);
+ return isl_basic_map_drop_redundant_divs(bmap);
+ }
+ if (pairs[i] != 1)
+ continue;
+ if (!isl_seq_is_neg(bmap->ineq[last_pos] + 1,
+ bmap->ineq[last_neg] + 1,
+ off + bmap->n_div))
+ continue;
+
+ isl_int_add(bmap->ineq[last_pos][0],
+ bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
+ isl_int_add_ui(bmap->ineq[last_pos][0],
+ bmap->ineq[last_pos][0], 1);
+ redundant = isl_int_ge(bmap->ineq[last_pos][0],
+ bmap->ineq[last_pos][1+off+i]);
+ isl_int_sub_ui(bmap->ineq[last_pos][0],
+ bmap->ineq[last_pos][0], 1);
+ isl_int_sub(bmap->ineq[last_pos][0],
+ bmap->ineq[last_pos][0], bmap->ineq[last_neg][0]);
+ if (!redundant) {
+ if (defined ||
+ !ok_to_set_div_from_bound(bmap, i, last_pos)) {
+ pairs[i] = 0;
+ --n;
+ continue;
+ }
+ bmap = set_div_from_lower_bound(bmap, i, last_pos);
+ bmap = isl_basic_map_simplify(bmap);
+ free(pairs);
+ return isl_basic_map_drop_redundant_divs(bmap);
+ }
+ if (last_pos > last_neg) {
+ isl_basic_map_drop_inequality(bmap, last_pos);
+ isl_basic_map_drop_inequality(bmap, last_neg);
+ } else {
+ isl_basic_map_drop_inequality(bmap, last_neg);
+ isl_basic_map_drop_inequality(bmap, last_pos);
+ }
+ bmap = isl_basic_map_drop_div(bmap, i);
+ free(pairs);
+ return isl_basic_map_drop_redundant_divs(bmap);
+ }
+
+ if (n > 0)
+ return coalesce_or_drop_more_redundant_divs(bmap, pairs, n);
+
+ free(pairs);
+ return bmap;
+error:
+ free(pairs);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_drop_redundant_divs(
+ struct isl_basic_set *bset)
+{
+ return (struct isl_basic_set *)
+ isl_basic_map_drop_redundant_divs((struct isl_basic_map *)bset);
+}
+
+struct isl_map *isl_map_drop_redundant_divs(struct isl_map *map)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+ for (i = 0; i < map->n; ++i) {
+ map->p[i] = isl_basic_map_drop_redundant_divs(map->p[i]);
+ if (!map->p[i])
+ goto error;
+ }
+ ISL_F_CLR(map, ISL_MAP_NORMALIZED);
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+struct isl_set *isl_set_drop_redundant_divs(struct isl_set *set)
+{
+ return (struct isl_set *)
+ isl_map_drop_redundant_divs((struct isl_map *)set);
+}
diff --git a/polly/lib/External/isl/isl_map_subtract.c b/polly/lib/External/isl/isl_map_subtract.c
new file mode 100644
index 00000000000..4d10cab807d
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_subtract.c
@@ -0,0 +1,900 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_map_private.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include "isl_tab.h"
+#include <isl_point_private.h>
+#include <isl_vec_private.h>
+
+/* Expand the constraint "c" into "v". The initial "dim" dimensions
+ * are the same, but "v" may have more divs than "c" and the divs of "c"
+ * may appear in different positions in "v".
+ * The number of divs in "c" is given by "n_div" and the mapping
+ * of divs in "c" to divs in "v" is given by "div_map".
+ *
+ * Although it shouldn't happen in practice, it is theoretically
+ * possible that two or more divs in "c" are mapped to the same div in "v".
+ * These divs are then necessarily the same, so we simply add their
+ * coefficients.
+ */
+static void expand_constraint(isl_vec *v, unsigned dim,
+ isl_int *c, int *div_map, unsigned n_div)
+{
+ int i;
+
+ isl_seq_cpy(v->el, c, 1 + dim);
+ isl_seq_clr(v->el + 1 + dim, v->size - (1 + dim));
+
+ for (i = 0; i < n_div; ++i) {
+ int pos = 1 + dim + div_map[i];
+ isl_int_add(v->el[pos], v->el[pos], c[1 + dim + i]);
+ }
+}
+
+/* Add all constraints of bmap to tab. The equalities of bmap
+ * are added as a pair of inequalities.
+ */
+static int tab_add_constraints(struct isl_tab *tab,
+ __isl_keep isl_basic_map *bmap, int *div_map)
+{
+ int i;
+ unsigned dim;
+ unsigned tab_total;
+ unsigned bmap_total;
+ isl_vec *v;
+
+ if (!tab || !bmap)
+ return -1;
+
+ tab_total = isl_basic_map_total_dim(tab->bmap);
+ bmap_total = isl_basic_map_total_dim(bmap);
+ dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
+
+ if (isl_tab_extend_cons(tab, 2 * bmap->n_eq + bmap->n_ineq) < 0)
+ return -1;
+
+ v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
+ if (!v)
+ return -1;
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
+ if (isl_tab_add_ineq(tab, v->el) < 0)
+ goto error;
+ isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
+ expand_constraint(v, dim, bmap->eq[i], div_map, bmap->n_div);
+ if (isl_tab_add_ineq(tab, v->el) < 0)
+ goto error;
+ isl_seq_neg(bmap->eq[i], bmap->eq[i], 1 + bmap_total);
+ if (tab->empty)
+ break;
+ }
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ expand_constraint(v, dim, bmap->ineq[i], div_map, bmap->n_div);
+ if (isl_tab_add_ineq(tab, v->el) < 0)
+ goto error;
+ if (tab->empty)
+ break;
+ }
+
+ isl_vec_free(v);
+ return 0;
+error:
+ isl_vec_free(v);
+ return -1;
+}
+
+/* Add a specific constraint of bmap (or its opposite) to tab.
+ * The position of the constraint is specified by "c", where
+ * the equalities of bmap are counted twice, once for the inequality
+ * that is equal to the equality, and once for its negation.
+ */
+static int tab_add_constraint(struct isl_tab *tab,
+ __isl_keep isl_basic_map *bmap, int *div_map, int c, int oppose)
+{
+ unsigned dim;
+ unsigned tab_total;
+ unsigned bmap_total;
+ isl_vec *v;
+ int r;
+
+ if (!tab || !bmap)
+ return -1;
+
+ tab_total = isl_basic_map_total_dim(tab->bmap);
+ bmap_total = isl_basic_map_total_dim(bmap);
+ dim = isl_space_dim(tab->bmap->dim, isl_dim_all);
+
+ v = isl_vec_alloc(bmap->ctx, 1 + tab_total);
+ if (!v)
+ return -1;
+
+ if (c < 2 * bmap->n_eq) {
+ if ((c % 2) != oppose)
+ isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
+ 1 + bmap_total);
+ if (oppose)
+ isl_int_sub_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
+ expand_constraint(v, dim, bmap->eq[c/2], div_map, bmap->n_div);
+ r = isl_tab_add_ineq(tab, v->el);
+ if (oppose)
+ isl_int_add_ui(bmap->eq[c/2][0], bmap->eq[c/2][0], 1);
+ if ((c % 2) != oppose)
+ isl_seq_neg(bmap->eq[c/2], bmap->eq[c/2],
+ 1 + bmap_total);
+ } else {
+ c -= 2 * bmap->n_eq;
+ if (oppose) {
+ isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
+ 1 + bmap_total);
+ isl_int_sub_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
+ }
+ expand_constraint(v, dim, bmap->ineq[c], div_map, bmap->n_div);
+ r = isl_tab_add_ineq(tab, v->el);
+ if (oppose) {
+ isl_int_add_ui(bmap->ineq[c][0], bmap->ineq[c][0], 1);
+ isl_seq_neg(bmap->ineq[c], bmap->ineq[c],
+ 1 + bmap_total);
+ }
+ }
+
+ isl_vec_free(v);
+ return r;
+}
+
+static int tab_add_divs(struct isl_tab *tab, __isl_keep isl_basic_map *bmap,
+ int **div_map)
+{
+ int i, j;
+ struct isl_vec *vec;
+ unsigned total;
+ unsigned dim;
+
+ if (!bmap)
+ return -1;
+ if (!bmap->n_div)
+ return 0;
+
+ if (!*div_map)
+ *div_map = isl_alloc_array(bmap->ctx, int, bmap->n_div);
+ if (!*div_map)
+ return -1;
+
+ total = isl_basic_map_total_dim(tab->bmap);
+ dim = total - tab->bmap->n_div;
+ vec = isl_vec_alloc(bmap->ctx, 2 + total + bmap->n_div);
+ if (!vec)
+ return -1;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ isl_seq_cpy(vec->el, bmap->div[i], 2 + dim);
+ isl_seq_clr(vec->el + 2 + dim, tab->bmap->n_div);
+ for (j = 0; j < i; ++j)
+ isl_int_set(vec->el[2 + dim + (*div_map)[j]],
+ bmap->div[i][2 + dim + j]);
+ for (j = 0; j < tab->bmap->n_div; ++j)
+ if (isl_seq_eq(tab->bmap->div[j],
+ vec->el, 2 + dim + tab->bmap->n_div))
+ break;
+ (*div_map)[i] = j;
+ if (j == tab->bmap->n_div) {
+ vec->size = 2 + dim + tab->bmap->n_div;
+ if (isl_tab_add_div(tab, vec, NULL, NULL) < 0)
+ goto error;
+ }
+ }
+
+ isl_vec_free(vec);
+
+ return 0;
+error:
+ isl_vec_free(vec);
+
+ return -1;
+}
+
+/* Freeze all constraints of tableau tab.
+ */
+static int tab_freeze_constraints(struct isl_tab *tab)
+{
+ int i;
+
+ for (i = 0; i < tab->n_con; ++i)
+ if (isl_tab_freeze_constraint(tab, i) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check for redundant constraints starting at offset.
+ * Put the indices of the redundant constraints in index
+ * and return the number of redundant constraints.
+ */
+static int n_non_redundant(isl_ctx *ctx, struct isl_tab *tab,
+ int offset, int **index)
+{
+ int i, n;
+ int n_test = tab->n_con - offset;
+
+ if (isl_tab_detect_redundant(tab) < 0)
+ return -1;
+
+ if (n_test == 0)
+ return 0;
+ if (!*index)
+ *index = isl_alloc_array(ctx, int, n_test);
+ if (!*index)
+ return -1;
+
+ for (n = 0, i = 0; i < n_test; ++i) {
+ int r;
+ r = isl_tab_is_redundant(tab, offset + i);
+ if (r < 0)
+ return -1;
+ if (r)
+ continue;
+ (*index)[n++] = i;
+ }
+
+ return n;
+}
+
+/* basic_map_collect_diff calls add on each of the pieces of
+ * the set difference between bmap and map until the add method
+ * return a negative value.
+ */
+struct isl_diff_collector {
+ int (*add)(struct isl_diff_collector *dc,
+ __isl_take isl_basic_map *bmap);
+};
+
+/* Compute the set difference between bmap and map and call
+ * dc->add on each of the piece until this function returns
+ * a negative value.
+ * Return 0 on success and -1 on error. dc->add returning
+ * a negative value is treated as an error, but the calling
+ * function can interpret the results based on the state of dc.
+ *
+ * Assumes that map has known divs.
+ *
+ * The difference is computed by a backtracking algorithm.
+ * Each level corresponds to a basic map in "map".
+ * When a node in entered for the first time, we check
+ * if the corresonding basic map intersects the current piece
+ * of "bmap". If not, we move to the next level.
+ * Otherwise, we split the current piece into as many
+ * pieces as there are non-redundant constraints of the current
+ * basic map in the intersection. Each of these pieces is
+ * handled by a child of the current node.
+ * In particular, if there are n non-redundant constraints,
+ * then for each 0 <= i < n, a piece is cut off by adding
+ * constraints 0 <= j < i and adding the opposite of constraint i.
+ * If there are no non-redundant constraints, meaning that the current
+ * piece is a subset of the current basic map, then we simply backtrack.
+ *
+ * In the leaves, we check if the remaining piece has any integer points
+ * and if so, pass it along to dc->add. As a special case, if nothing
+ * has been removed when we end up in a leaf, we simply pass along
+ * the original basic map.
+ */
+static int basic_map_collect_diff(__isl_take isl_basic_map *bmap,
+ __isl_take isl_map *map, struct isl_diff_collector *dc)
+{
+ int i;
+ int modified;
+ int level;
+ int init;
+ int empty;
+ isl_ctx *ctx;
+ struct isl_tab *tab = NULL;
+ struct isl_tab_undo **snap = NULL;
+ int *k = NULL;
+ int *n = NULL;
+ int **index = NULL;
+ int **div_map = NULL;
+
+ empty = isl_basic_map_is_empty(bmap);
+ if (empty) {
+ isl_basic_map_free(bmap);
+ isl_map_free(map);
+ return empty < 0 ? -1 : 0;
+ }
+
+ bmap = isl_basic_map_cow(bmap);
+ map = isl_map_cow(map);
+
+ if (!bmap || !map)
+ goto error;
+
+ ctx = map->ctx;
+ snap = isl_alloc_array(map->ctx, struct isl_tab_undo *, map->n);
+ k = isl_alloc_array(map->ctx, int, map->n);
+ n = isl_alloc_array(map->ctx, int, map->n);
+ index = isl_calloc_array(map->ctx, int *, map->n);
+ div_map = isl_calloc_array(map->ctx, int *, map->n);
+ if (!snap || !k || !n || !index || !div_map)
+ goto error;
+
+ bmap = isl_basic_map_order_divs(bmap);
+ map = isl_map_order_divs(map);
+
+ tab = isl_tab_from_basic_map(bmap, 1);
+ if (!tab)
+ goto error;
+
+ modified = 0;
+ level = 0;
+ init = 1;
+
+ while (level >= 0) {
+ if (level >= map->n) {
+ int empty;
+ struct isl_basic_map *bm;
+ if (!modified) {
+ if (dc->add(dc, isl_basic_map_copy(bmap)) < 0)
+ goto error;
+ break;
+ }
+ bm = isl_basic_map_copy(tab->bmap);
+ bm = isl_basic_map_cow(bm);
+ bm = isl_basic_map_update_from_tab(bm, tab);
+ bm = isl_basic_map_simplify(bm);
+ bm = isl_basic_map_finalize(bm);
+ empty = isl_basic_map_is_empty(bm);
+ if (empty)
+ isl_basic_map_free(bm);
+ else if (dc->add(dc, bm) < 0)
+ goto error;
+ if (empty < 0)
+ goto error;
+ level--;
+ init = 0;
+ continue;
+ }
+ if (init) {
+ int offset;
+ struct isl_tab_undo *snap2;
+ snap2 = isl_tab_snap(tab);
+ if (tab_add_divs(tab, map->p[level],
+ &div_map[level]) < 0)
+ goto error;
+ offset = tab->n_con;
+ snap[level] = isl_tab_snap(tab);
+ if (tab_freeze_constraints(tab) < 0)
+ goto error;
+ if (tab_add_constraints(tab, map->p[level],
+ div_map[level]) < 0)
+ goto error;
+ k[level] = 0;
+ n[level] = 0;
+ if (tab->empty) {
+ if (isl_tab_rollback(tab, snap2) < 0)
+ goto error;
+ level++;
+ continue;
+ }
+ modified = 1;
+ n[level] = n_non_redundant(ctx, tab, offset,
+ &index[level]);
+ if (n[level] < 0)
+ goto error;
+ if (n[level] == 0) {
+ level--;
+ init = 0;
+ continue;
+ }
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ if (tab_add_constraint(tab, map->p[level],
+ div_map[level], index[level][0], 1) < 0)
+ goto error;
+ level++;
+ continue;
+ } else {
+ if (k[level] + 1 >= n[level]) {
+ level--;
+ continue;
+ }
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ if (tab_add_constraint(tab, map->p[level],
+ div_map[level],
+ index[level][k[level]], 0) < 0)
+ goto error;
+ snap[level] = isl_tab_snap(tab);
+ k[level]++;
+ if (tab_add_constraint(tab, map->p[level],
+ div_map[level],
+ index[level][k[level]], 1) < 0)
+ goto error;
+ level++;
+ init = 1;
+ continue;
+ }
+ }
+
+ isl_tab_free(tab);
+ free(snap);
+ free(n);
+ free(k);
+ for (i = 0; index && i < map->n; ++i)
+ free(index[i]);
+ free(index);
+ for (i = 0; div_map && i < map->n; ++i)
+ free(div_map[i]);
+ free(div_map);
+
+ isl_basic_map_free(bmap);
+ isl_map_free(map);
+
+ return 0;
+error:
+ isl_tab_free(tab);
+ free(snap);
+ free(n);
+ free(k);
+ for (i = 0; index && i < map->n; ++i)
+ free(index[i]);
+ free(index);
+ for (i = 0; div_map && i < map->n; ++i)
+ free(div_map[i]);
+ free(div_map);
+ isl_basic_map_free(bmap);
+ isl_map_free(map);
+ return -1;
+}
+
+/* A diff collector that actually collects all parts of the
+ * set difference in the field diff.
+ */
+struct isl_subtract_diff_collector {
+ struct isl_diff_collector dc;
+ struct isl_map *diff;
+};
+
+/* isl_subtract_diff_collector callback.
+ */
+static int basic_map_subtract_add(struct isl_diff_collector *dc,
+ __isl_take isl_basic_map *bmap)
+{
+ struct isl_subtract_diff_collector *sdc;
+ sdc = (struct isl_subtract_diff_collector *)dc;
+
+ sdc->diff = isl_map_union_disjoint(sdc->diff,
+ isl_map_from_basic_map(bmap));
+
+ return sdc->diff ? 0 : -1;
+}
+
+/* Return the set difference between bmap and map.
+ */
+static __isl_give isl_map *basic_map_subtract(__isl_take isl_basic_map *bmap,
+ __isl_take isl_map *map)
+{
+ struct isl_subtract_diff_collector sdc;
+ sdc.dc.add = &basic_map_subtract_add;
+ sdc.diff = isl_map_empty_like_basic_map(bmap);
+ if (basic_map_collect_diff(bmap, map, &sdc.dc) < 0) {
+ isl_map_free(sdc.diff);
+ sdc.diff = NULL;
+ }
+ return sdc.diff;
+}
+
+/* Return the set difference between map1 and map2.
+ * (U_i A_i) \ (U_j B_j) is computed as U_i (A_i \ (U_j B_j))
+ *
+ * If "map1" and "map2" are disjoint, then simply return "map1".
+ */
+static __isl_give isl_map *map_subtract( __isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ int i;
+ int disjoint;
+ struct isl_map *diff;
+
+ if (!map1 || !map2)
+ goto error;
+
+ isl_assert(map1->ctx, isl_space_is_equal(map1->dim, map2->dim), goto error);
+
+ disjoint = isl_map_is_disjoint(map1, map2);
+ if (disjoint < 0)
+ goto error;
+ if (disjoint) {
+ isl_map_free(map2);
+ return map1;
+ }
+
+ map1 = isl_map_compute_divs(map1);
+ map2 = isl_map_compute_divs(map2);
+ if (!map1 || !map2)
+ goto error;
+
+ map1 = isl_map_remove_empty_parts(map1);
+ map2 = isl_map_remove_empty_parts(map2);
+
+ diff = isl_map_empty_like(map1);
+ for (i = 0; i < map1->n; ++i) {
+ struct isl_map *d;
+ d = basic_map_subtract(isl_basic_map_copy(map1->p[i]),
+ isl_map_copy(map2));
+ if (ISL_F_ISSET(map1, ISL_MAP_DISJOINT))
+ diff = isl_map_union_disjoint(diff, d);
+ else
+ diff = isl_map_union(diff, d);
+ }
+
+ isl_map_free(map1);
+ isl_map_free(map2);
+
+ return diff;
+error:
+ isl_map_free(map1);
+ isl_map_free(map2);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_subtract( __isl_take isl_map *map1,
+ __isl_take isl_map *map2)
+{
+ return isl_map_align_params_map_map_and(map1, map2, &map_subtract);
+}
+
+struct isl_set *isl_set_subtract(struct isl_set *set1, struct isl_set *set2)
+{
+ return (struct isl_set *)
+ isl_map_subtract(
+ (struct isl_map *)set1, (struct isl_map *)set2);
+}
+
+/* Remove the elements of "dom" from the domain of "map".
+ */
+static __isl_give isl_map *map_subtract_domain(__isl_take isl_map *map,
+ __isl_take isl_set *dom)
+{
+ isl_map *ext_dom;
+
+ if (!isl_map_compatible_domain(map, dom))
+ isl_die(isl_set_get_ctx(dom), isl_error_invalid,
+ "incompatible spaces", goto error);
+
+ ext_dom = isl_map_universe(isl_map_get_space(map));
+ ext_dom = isl_map_intersect_domain(ext_dom, dom);
+ return isl_map_subtract(map, ext_dom);
+error:
+ isl_map_free(map);
+ isl_set_free(dom);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
+ __isl_take isl_set *dom)
+{
+ return isl_map_align_params_map_map_and(map, dom, &map_subtract_domain);
+}
+
+/* Remove the elements of "dom" from the range of "map".
+ */
+static __isl_give isl_map *map_subtract_range(__isl_take isl_map *map,
+ __isl_take isl_set *dom)
+{
+ isl_map *ext_dom;
+
+ if (!isl_map_compatible_range(map, dom))
+ isl_die(isl_set_get_ctx(dom), isl_error_invalid,
+ "incompatible spaces", goto error);
+
+ ext_dom = isl_map_universe(isl_map_get_space(map));
+ ext_dom = isl_map_intersect_range(ext_dom, dom);
+ return isl_map_subtract(map, ext_dom);
+error:
+ isl_map_free(map);
+ isl_set_free(dom);
+ return NULL;
+}
+
+__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
+ __isl_take isl_set *dom)
+{
+ return isl_map_align_params_map_map_and(map, dom, &map_subtract_range);
+}
+
+/* A diff collector that aborts as soon as its add function is called,
+ * setting empty to 0.
+ */
+struct isl_is_empty_diff_collector {
+ struct isl_diff_collector dc;
+ int empty;
+};
+
+/* isl_is_empty_diff_collector callback.
+ */
+static int basic_map_is_empty_add(struct isl_diff_collector *dc,
+ __isl_take isl_basic_map *bmap)
+{
+ struct isl_is_empty_diff_collector *edc;
+ edc = (struct isl_is_empty_diff_collector *)dc;
+
+ edc->empty = 0;
+
+ isl_basic_map_free(bmap);
+ return -1;
+}
+
+/* Check if bmap \ map is empty by computing this set difference
+ * and breaking off as soon as the difference is known to be non-empty.
+ */
+static int basic_map_diff_is_empty(__isl_keep isl_basic_map *bmap,
+ __isl_keep isl_map *map)
+{
+ int r;
+ struct isl_is_empty_diff_collector edc;
+
+ r = isl_basic_map_plain_is_empty(bmap);
+ if (r)
+ return r;
+
+ edc.dc.add = &basic_map_is_empty_add;
+ edc.empty = 1;
+ r = basic_map_collect_diff(isl_basic_map_copy(bmap),
+ isl_map_copy(map), &edc.dc);
+ if (!edc.empty)
+ return 0;
+
+ return r < 0 ? -1 : 1;
+}
+
+/* Check if map1 \ map2 is empty by checking if the set difference is empty
+ * for each of the basic maps in map1.
+ */
+static int map_diff_is_empty(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ int i;
+ int is_empty = 1;
+
+ if (!map1 || !map2)
+ return -1;
+
+ for (i = 0; i < map1->n; ++i) {
+ is_empty = basic_map_diff_is_empty(map1->p[i], map2);
+ if (is_empty < 0 || !is_empty)
+ break;
+ }
+
+ return is_empty;
+}
+
+/* Return 1 if "bmap" contains a single element.
+ */
+int isl_basic_map_plain_is_singleton(__isl_keep isl_basic_map *bmap)
+{
+ if (!bmap)
+ return -1;
+ if (bmap->n_div)
+ return 0;
+ if (bmap->n_ineq)
+ return 0;
+ return bmap->n_eq == isl_basic_map_total_dim(bmap);
+}
+
+/* Return 1 if "map" contains a single element.
+ */
+int isl_map_plain_is_singleton(__isl_keep isl_map *map)
+{
+ if (!map)
+ return -1;
+ if (map->n != 1)
+ return 0;
+
+ return isl_basic_map_plain_is_singleton(map->p[0]);
+}
+
+/* Given a singleton basic map, extract the single element
+ * as an isl_point.
+ */
+static __isl_give isl_point *singleton_extract_point(
+ __isl_keep isl_basic_map *bmap)
+{
+ int j;
+ unsigned dim;
+ struct isl_vec *point;
+ isl_int m;
+
+ if (!bmap)
+ return NULL;
+
+ dim = isl_basic_map_total_dim(bmap);
+ isl_assert(bmap->ctx, bmap->n_eq == dim, return NULL);
+ point = isl_vec_alloc(bmap->ctx, 1 + dim);
+ if (!point)
+ return NULL;
+
+ isl_int_init(m);
+
+ isl_int_set_si(point->el[0], 1);
+ for (j = 0; j < bmap->n_eq; ++j) {
+ int i = dim - 1 - j;
+ isl_assert(bmap->ctx,
+ isl_seq_first_non_zero(bmap->eq[j] + 1, i) == -1,
+ goto error);
+ isl_assert(bmap->ctx,
+ isl_int_is_one(bmap->eq[j][1 + i]) ||
+ isl_int_is_negone(bmap->eq[j][1 + i]),
+ goto error);
+ isl_assert(bmap->ctx,
+ isl_seq_first_non_zero(bmap->eq[j]+1+i+1, dim-i-1) == -1,
+ goto error);
+
+ isl_int_gcd(m, point->el[0], bmap->eq[j][1 + i]);
+ isl_int_divexact(m, bmap->eq[j][1 + i], m);
+ isl_int_abs(m, m);
+ isl_seq_scale(point->el, point->el, m, 1 + i);
+ isl_int_divexact(m, point->el[0], bmap->eq[j][1 + i]);
+ isl_int_neg(m, m);
+ isl_int_mul(point->el[1 + i], m, bmap->eq[j][0]);
+ }
+
+ isl_int_clear(m);
+ return isl_point_alloc(isl_basic_map_get_space(bmap), point);
+error:
+ isl_int_clear(m);
+ isl_vec_free(point);
+ return NULL;
+}
+
+/* Return 1 is the singleton map "map1" is a subset of "map2",
+ * i.e., if the single element of "map1" is also an element of "map2".
+ * Assumes "map2" has known divs.
+ */
+static int map_is_singleton_subset(__isl_keep isl_map *map1,
+ __isl_keep isl_map *map2)
+{
+ int i;
+ int is_subset = 0;
+ struct isl_point *point;
+
+ if (!map1 || !map2)
+ return -1;
+ if (map1->n != 1)
+ return -1;
+
+ point = singleton_extract_point(map1->p[0]);
+ if (!point)
+ return -1;
+
+ for (i = 0; i < map2->n; ++i) {
+ is_subset = isl_basic_map_contains_point(map2->p[i], point);
+ if (is_subset)
+ break;
+ }
+
+ isl_point_free(point);
+ return is_subset;
+}
+
+static int map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ int is_subset = 0;
+ int empty;
+ int rat1, rat2;
+
+ if (!map1 || !map2)
+ return -1;
+
+ if (!isl_map_has_equal_space(map1, map2))
+ return 0;
+
+ empty = isl_map_is_empty(map1);
+ if (empty < 0)
+ return -1;
+ if (empty)
+ return 1;
+
+ empty = isl_map_is_empty(map2);
+ if (empty < 0)
+ return -1;
+ if (empty)
+ return 0;
+
+ rat1 = isl_map_has_rational(map1);
+ rat2 = isl_map_has_rational(map2);
+ if (rat1 < 0 || rat2 < 0)
+ return -1;
+ if (rat1 && !rat2)
+ return 0;
+
+ if (isl_map_plain_is_universe(map2))
+ return 1;
+
+ map2 = isl_map_compute_divs(isl_map_copy(map2));
+ if (isl_map_plain_is_singleton(map1)) {
+ is_subset = map_is_singleton_subset(map1, map2);
+ isl_map_free(map2);
+ return is_subset;
+ }
+ is_subset = map_diff_is_empty(map1, map2);
+ isl_map_free(map2);
+
+ return is_subset;
+}
+
+int isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2)
+{
+ return isl_map_align_params_map_map_and_test(map1, map2,
+ &map_is_subset);
+}
+
+int isl_set_is_subset(struct isl_set *set1, struct isl_set *set2)
+{
+ return isl_map_is_subset(
+ (struct isl_map *)set1, (struct isl_map *)set2);
+}
+
+__isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map)
+{
+ int i;
+ struct isl_subtract_diff_collector sdc;
+ sdc.dc.add = &basic_map_subtract_add;
+
+ if (!map)
+ return NULL;
+ if (ISL_F_ISSET(map, ISL_MAP_DISJOINT))
+ return map;
+ if (map->n <= 1)
+ return map;
+
+ map = isl_map_compute_divs(map);
+ map = isl_map_remove_empty_parts(map);
+
+ if (!map || map->n <= 1)
+ return map;
+
+ sdc.diff = isl_map_from_basic_map(isl_basic_map_copy(map->p[0]));
+
+ for (i = 1; i < map->n; ++i) {
+ struct isl_basic_map *bmap = isl_basic_map_copy(map->p[i]);
+ struct isl_map *copy = isl_map_copy(sdc.diff);
+ if (basic_map_collect_diff(bmap, copy, &sdc.dc) < 0) {
+ isl_map_free(sdc.diff);
+ sdc.diff = NULL;
+ break;
+ }
+ }
+
+ isl_map_free(map);
+
+ return sdc.diff;
+}
+
+__isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set)
+{
+ return (struct isl_set *)isl_map_make_disjoint((struct isl_map *)set);
+}
+
+__isl_give isl_map *isl_map_complement(__isl_take isl_map *map)
+{
+ isl_map *universe;
+
+ if (!map)
+ return NULL;
+
+ universe = isl_map_universe(isl_map_get_space(map));
+
+ return isl_map_subtract(universe, map);
+}
+
+__isl_give isl_set *isl_set_complement(__isl_take isl_set *set)
+{
+ return isl_map_complement(set);
+}
diff --git a/polly/lib/External/isl/isl_map_to_basic_set.c b/polly/lib/External/isl/isl_map_to_basic_set.c
new file mode 100644
index 00000000000..6755d52bcdd
--- /dev/null
+++ b/polly/lib/External/isl/isl_map_to_basic_set.c
@@ -0,0 +1,10 @@
+#include <isl/map_to_basic_set.h>
+#include <isl/map.h>
+#include <isl/set.h>
+
+#define KEY_BASE map
+#define KEY_EQUAL isl_map_plain_is_equal
+#define VAL_BASE basic_set
+#define VAL_EQUAL isl_basic_set_plain_is_equal
+
+#include <isl_hmap_templ.c>
diff --git a/polly/lib/External/isl/isl_mat.c b/polly/lib/External/isl/isl_mat.c
new file mode 100644
index 00000000000..3a8d31034be
--- /dev/null
+++ b/polly/lib/External/isl/isl_mat.c
@@ -0,0 +1,1742 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2014 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/space.h>
+#include <isl_seq.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_space_private.h>
+#include <isl_val_private.h>
+#include <isl/deprecated/mat_int.h>
+
+isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat)
+{
+ return mat ? mat->ctx : NULL;
+}
+
+struct isl_mat *isl_mat_alloc(struct isl_ctx *ctx,
+ unsigned n_row, unsigned n_col)
+{
+ int i;
+ struct isl_mat *mat;
+
+ mat = isl_alloc_type(ctx, struct isl_mat);
+ if (!mat)
+ return NULL;
+
+ mat->row = NULL;
+ mat->block = isl_blk_alloc(ctx, n_row * n_col);
+ if (isl_blk_is_error(mat->block))
+ goto error;
+ mat->row = isl_alloc_array(ctx, isl_int *, n_row);
+ if (n_row && !mat->row)
+ goto error;
+
+ for (i = 0; i < n_row; ++i)
+ mat->row[i] = mat->block.data + i * n_col;
+
+ mat->ctx = ctx;
+ isl_ctx_ref(ctx);
+ mat->ref = 1;
+ mat->n_row = n_row;
+ mat->n_col = n_col;
+ mat->max_col = n_col;
+ mat->flags = 0;
+
+ return mat;
+error:
+ isl_blk_free(ctx, mat->block);
+ free(mat);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_extend(struct isl_mat *mat,
+ unsigned n_row, unsigned n_col)
+{
+ int i;
+ isl_int *old;
+ isl_int **row;
+
+ if (!mat)
+ return NULL;
+
+ if (mat->max_col >= n_col && mat->n_row >= n_row) {
+ if (mat->n_col < n_col)
+ mat->n_col = n_col;
+ return mat;
+ }
+
+ if (mat->max_col < n_col) {
+ struct isl_mat *new_mat;
+
+ if (n_row < mat->n_row)
+ n_row = mat->n_row;
+ new_mat = isl_mat_alloc(mat->ctx, n_row, n_col);
+ if (!new_mat)
+ goto error;
+ for (i = 0; i < mat->n_row; ++i)
+ isl_seq_cpy(new_mat->row[i], mat->row[i], mat->n_col);
+ isl_mat_free(mat);
+ return new_mat;
+ }
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ goto error;
+
+ old = mat->block.data;
+ mat->block = isl_blk_extend(mat->ctx, mat->block, n_row * mat->max_col);
+ if (isl_blk_is_error(mat->block))
+ goto error;
+ row = isl_realloc_array(mat->ctx, mat->row, isl_int *, n_row);
+ if (n_row && !row)
+ goto error;
+ mat->row = row;
+
+ for (i = 0; i < mat->n_row; ++i)
+ mat->row[i] = mat->block.data + (mat->row[i] - old);
+ for (i = mat->n_row; i < n_row; ++i)
+ mat->row[i] = mat->block.data + i * mat->max_col;
+ mat->n_row = n_row;
+ if (mat->n_col < n_col)
+ mat->n_col = n_col;
+
+ return mat;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_sub_alloc6(isl_ctx *ctx, isl_int **row,
+ unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col)
+{
+ int i;
+ struct isl_mat *mat;
+
+ mat = isl_alloc_type(ctx, struct isl_mat);
+ if (!mat)
+ return NULL;
+ mat->row = isl_alloc_array(ctx, isl_int *, n_row);
+ if (n_row && !mat->row)
+ goto error;
+ for (i = 0; i < n_row; ++i)
+ mat->row[i] = row[first_row+i] + first_col;
+ mat->ctx = ctx;
+ isl_ctx_ref(ctx);
+ mat->ref = 1;
+ mat->n_row = n_row;
+ mat->n_col = n_col;
+ mat->block = isl_blk_empty();
+ mat->flags = ISL_MAT_BORROWED;
+ return mat;
+error:
+ free(mat);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_sub_alloc(__isl_keep isl_mat *mat,
+ unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col)
+{
+ if (!mat)
+ return NULL;
+ return isl_mat_sub_alloc6(mat->ctx, mat->row, first_row, n_row,
+ first_col, n_col);
+}
+
+void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
+ unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
+{
+ int i;
+
+ for (i = 0; i < n_row; ++i)
+ isl_seq_cpy(dst[i]+dst_col, src[i]+src_col, n_col);
+}
+
+void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
+ unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col)
+{
+ int i;
+
+ for (i = 0; i < n_row; ++i)
+ isl_seq_neg(dst[i]+dst_col, src[i]+src_col, n_col);
+}
+
+struct isl_mat *isl_mat_copy(struct isl_mat *mat)
+{
+ if (!mat)
+ return NULL;
+
+ mat->ref++;
+ return mat;
+}
+
+struct isl_mat *isl_mat_dup(struct isl_mat *mat)
+{
+ int i;
+ struct isl_mat *mat2;
+
+ if (!mat)
+ return NULL;
+ mat2 = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col);
+ if (!mat2)
+ return NULL;
+ for (i = 0; i < mat->n_row; ++i)
+ isl_seq_cpy(mat2->row[i], mat->row[i], mat->n_col);
+ return mat2;
+}
+
+struct isl_mat *isl_mat_cow(struct isl_mat *mat)
+{
+ struct isl_mat *mat2;
+ if (!mat)
+ return NULL;
+
+ if (mat->ref == 1 && !ISL_F_ISSET(mat, ISL_MAT_BORROWED))
+ return mat;
+
+ mat2 = isl_mat_dup(mat);
+ isl_mat_free(mat);
+ return mat2;
+}
+
+__isl_null isl_mat *isl_mat_free(__isl_take isl_mat *mat)
+{
+ if (!mat)
+ return NULL;
+
+ if (--mat->ref > 0)
+ return NULL;
+
+ if (!ISL_F_ISSET(mat, ISL_MAT_BORROWED))
+ isl_blk_free(mat->ctx, mat->block);
+ isl_ctx_deref(mat->ctx);
+ free(mat->row);
+ free(mat);
+
+ return NULL;
+}
+
+int isl_mat_rows(__isl_keep isl_mat *mat)
+{
+ return mat ? mat->n_row : -1;
+}
+
+int isl_mat_cols(__isl_keep isl_mat *mat)
+{
+ return mat ? mat->n_col : -1;
+}
+
+int isl_mat_get_element(__isl_keep isl_mat *mat, int row, int col, isl_int *v)
+{
+ if (!mat)
+ return -1;
+ if (row < 0 || row >= mat->n_row)
+ isl_die(mat->ctx, isl_error_invalid, "row out of range",
+ return -1);
+ if (col < 0 || col >= mat->n_col)
+ isl_die(mat->ctx, isl_error_invalid, "column out of range",
+ return -1);
+ isl_int_set(*v, mat->row[row][col]);
+ return 0;
+}
+
+/* Extract the element at row "row", oolumn "col" of "mat".
+ */
+__isl_give isl_val *isl_mat_get_element_val(__isl_keep isl_mat *mat,
+ int row, int col)
+{
+ isl_ctx *ctx;
+
+ if (!mat)
+ return NULL;
+ ctx = isl_mat_get_ctx(mat);
+ if (row < 0 || row >= mat->n_row)
+ isl_die(ctx, isl_error_invalid, "row out of range",
+ return NULL);
+ if (col < 0 || col >= mat->n_col)
+ isl_die(ctx, isl_error_invalid, "column out of range",
+ return NULL);
+ return isl_val_int_from_isl_int(ctx, mat->row[row][col]);
+}
+
+__isl_give isl_mat *isl_mat_set_element(__isl_take isl_mat *mat,
+ int row, int col, isl_int v)
+{
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+ if (row < 0 || row >= mat->n_row)
+ isl_die(mat->ctx, isl_error_invalid, "row out of range",
+ goto error);
+ if (col < 0 || col >= mat->n_col)
+ isl_die(mat->ctx, isl_error_invalid, "column out of range",
+ goto error);
+ isl_int_set(mat->row[row][col], v);
+ return mat;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_set_element_si(__isl_take isl_mat *mat,
+ int row, int col, int v)
+{
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+ if (row < 0 || row >= mat->n_row)
+ isl_die(mat->ctx, isl_error_invalid, "row out of range",
+ goto error);
+ if (col < 0 || col >= mat->n_col)
+ isl_die(mat->ctx, isl_error_invalid, "column out of range",
+ goto error);
+ isl_int_set_si(mat->row[row][col], v);
+ return mat;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+/* Replace the element at row "row", column "col" of "mat" by "v".
+ */
+__isl_give isl_mat *isl_mat_set_element_val(__isl_take isl_mat *mat,
+ int row, int col, __isl_take isl_val *v)
+{
+ if (!v)
+ return isl_mat_free(mat);
+ if (!isl_val_is_int(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting integer value", goto error);
+ mat = isl_mat_set_element(mat, row, col, v->n);
+ isl_val_free(v);
+ return mat;
+error:
+ isl_val_free(v);
+ return isl_mat_free(mat);
+}
+
+__isl_give isl_mat *isl_mat_diag(isl_ctx *ctx, unsigned n_row, isl_int d)
+{
+ int i;
+ struct isl_mat *mat;
+
+ mat = isl_mat_alloc(ctx, n_row, n_row);
+ if (!mat)
+ return NULL;
+ for (i = 0; i < n_row; ++i) {
+ isl_seq_clr(mat->row[i], i);
+ isl_int_set(mat->row[i][i], d);
+ isl_seq_clr(mat->row[i]+i+1, n_row-(i+1));
+ }
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_identity(isl_ctx *ctx, unsigned n_row)
+{
+ if (!ctx)
+ return NULL;
+ return isl_mat_diag(ctx, n_row, ctx->one);
+}
+
+/* Is "mat" a (possibly scaled) identity matrix?
+ */
+int isl_mat_is_scaled_identity(__isl_keep isl_mat *mat)
+{
+ int i;
+
+ if (!mat)
+ return -1;
+ if (mat->n_row != mat->n_col)
+ return 0;
+
+ for (i = 0; i < mat->n_row; ++i) {
+ if (isl_seq_first_non_zero(mat->row[i], i) != -1)
+ return 0;
+ if (isl_int_ne(mat->row[0][0], mat->row[i][i]))
+ return 0;
+ if (isl_seq_first_non_zero(mat->row[i] + i + 1,
+ mat->n_col - (i + 1)) != -1)
+ return 0;
+ }
+
+ return 1;
+}
+
+struct isl_vec *isl_mat_vec_product(struct isl_mat *mat, struct isl_vec *vec)
+{
+ int i;
+ struct isl_vec *prod;
+
+ if (!mat || !vec)
+ goto error;
+
+ isl_assert(mat->ctx, mat->n_col == vec->size, goto error);
+
+ prod = isl_vec_alloc(mat->ctx, mat->n_row);
+ if (!prod)
+ goto error;
+
+ for (i = 0; i < prod->size; ++i)
+ isl_seq_inner_product(mat->row[i], vec->el, vec->size,
+ &prod->block.data[i]);
+ isl_mat_free(mat);
+ isl_vec_free(vec);
+ return prod;
+error:
+ isl_mat_free(mat);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_mat_vec_inverse_product(__isl_take isl_mat *mat,
+ __isl_take isl_vec *vec)
+{
+ struct isl_mat *vec_mat;
+ int i;
+
+ if (!mat || !vec)
+ goto error;
+ vec_mat = isl_mat_alloc(vec->ctx, vec->size, 1);
+ if (!vec_mat)
+ goto error;
+ for (i = 0; i < vec->size; ++i)
+ isl_int_set(vec_mat->row[i][0], vec->el[i]);
+ vec_mat = isl_mat_inverse_product(mat, vec_mat);
+ isl_vec_free(vec);
+ if (!vec_mat)
+ return NULL;
+ vec = isl_vec_alloc(vec_mat->ctx, vec_mat->n_row);
+ if (vec)
+ for (i = 0; i < vec->size; ++i)
+ isl_int_set(vec->el[i], vec_mat->row[i][0]);
+ isl_mat_free(vec_mat);
+ return vec;
+error:
+ isl_mat_free(mat);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+struct isl_vec *isl_vec_mat_product(struct isl_vec *vec, struct isl_mat *mat)
+{
+ int i, j;
+ struct isl_vec *prod;
+
+ if (!mat || !vec)
+ goto error;
+
+ isl_assert(mat->ctx, mat->n_row == vec->size, goto error);
+
+ prod = isl_vec_alloc(mat->ctx, mat->n_col);
+ if (!prod)
+ goto error;
+
+ for (i = 0; i < prod->size; ++i) {
+ isl_int_set_si(prod->el[i], 0);
+ for (j = 0; j < vec->size; ++j)
+ isl_int_addmul(prod->el[i], vec->el[j], mat->row[j][i]);
+ }
+ isl_mat_free(mat);
+ isl_vec_free(vec);
+ return prod;
+error:
+ isl_mat_free(mat);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_aff_direct_sum(struct isl_mat *left,
+ struct isl_mat *right)
+{
+ int i;
+ struct isl_mat *sum;
+
+ if (!left || !right)
+ goto error;
+
+ isl_assert(left->ctx, left->n_row == right->n_row, goto error);
+ isl_assert(left->ctx, left->n_row >= 1, goto error);
+ isl_assert(left->ctx, left->n_col >= 1, goto error);
+ isl_assert(left->ctx, right->n_col >= 1, goto error);
+ isl_assert(left->ctx,
+ isl_seq_first_non_zero(left->row[0]+1, left->n_col-1) == -1,
+ goto error);
+ isl_assert(left->ctx,
+ isl_seq_first_non_zero(right->row[0]+1, right->n_col-1) == -1,
+ goto error);
+
+ sum = isl_mat_alloc(left->ctx, left->n_row, left->n_col + right->n_col - 1);
+ if (!sum)
+ goto error;
+ isl_int_lcm(sum->row[0][0], left->row[0][0], right->row[0][0]);
+ isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
+ isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
+
+ isl_seq_clr(sum->row[0]+1, sum->n_col-1);
+ for (i = 1; i < sum->n_row; ++i) {
+ isl_int_mul(sum->row[i][0], left->row[0][0], left->row[i][0]);
+ isl_int_addmul(sum->row[i][0],
+ right->row[0][0], right->row[i][0]);
+ isl_seq_scale(sum->row[i]+1, left->row[i]+1, left->row[0][0],
+ left->n_col-1);
+ isl_seq_scale(sum->row[i]+left->n_col,
+ right->row[i]+1, right->row[0][0],
+ right->n_col-1);
+ }
+
+ isl_int_divexact(left->row[0][0], sum->row[0][0], left->row[0][0]);
+ isl_int_divexact(right->row[0][0], sum->row[0][0], right->row[0][0]);
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return sum;
+error:
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return NULL;
+}
+
+static void exchange(struct isl_mat *M, struct isl_mat **U,
+ struct isl_mat **Q, unsigned row, unsigned i, unsigned j)
+{
+ int r;
+ for (r = row; r < M->n_row; ++r)
+ isl_int_swap(M->row[r][i], M->row[r][j]);
+ if (U) {
+ for (r = 0; r < (*U)->n_row; ++r)
+ isl_int_swap((*U)->row[r][i], (*U)->row[r][j]);
+ }
+ if (Q)
+ isl_mat_swap_rows(*Q, i, j);
+}
+
+static void subtract(struct isl_mat *M, struct isl_mat **U,
+ struct isl_mat **Q, unsigned row, unsigned i, unsigned j, isl_int m)
+{
+ int r;
+ for (r = row; r < M->n_row; ++r)
+ isl_int_submul(M->row[r][j], m, M->row[r][i]);
+ if (U) {
+ for (r = 0; r < (*U)->n_row; ++r)
+ isl_int_submul((*U)->row[r][j], m, (*U)->row[r][i]);
+ }
+ if (Q) {
+ for (r = 0; r < (*Q)->n_col; ++r)
+ isl_int_addmul((*Q)->row[i][r], m, (*Q)->row[j][r]);
+ }
+}
+
+static void oppose(struct isl_mat *M, struct isl_mat **U,
+ struct isl_mat **Q, unsigned row, unsigned col)
+{
+ int r;
+ for (r = row; r < M->n_row; ++r)
+ isl_int_neg(M->row[r][col], M->row[r][col]);
+ if (U) {
+ for (r = 0; r < (*U)->n_row; ++r)
+ isl_int_neg((*U)->row[r][col], (*U)->row[r][col]);
+ }
+ if (Q)
+ isl_seq_neg((*Q)->row[col], (*Q)->row[col], (*Q)->n_col);
+}
+
+/* Given matrix M, compute
+ *
+ * M U = H
+ * M = H Q
+ *
+ * with U and Q unimodular matrices and H a matrix in column echelon form
+ * such that on each echelon row the entries in the non-echelon column
+ * are non-negative (if neg == 0) or non-positive (if neg == 1)
+ * and strictly smaller (in absolute value) than the entries in the echelon
+ * column.
+ * If U or Q are NULL, then these matrices are not computed.
+ */
+struct isl_mat *isl_mat_left_hermite(struct isl_mat *M, int neg,
+ struct isl_mat **U, struct isl_mat **Q)
+{
+ isl_int c;
+ int row, col;
+
+ if (U)
+ *U = NULL;
+ if (Q)
+ *Q = NULL;
+ if (!M)
+ goto error;
+ M = isl_mat_cow(M);
+ if (!M)
+ goto error;
+ if (U) {
+ *U = isl_mat_identity(M->ctx, M->n_col);
+ if (!*U)
+ goto error;
+ }
+ if (Q) {
+ *Q = isl_mat_identity(M->ctx, M->n_col);
+ if (!*Q)
+ goto error;
+ }
+
+ col = 0;
+ isl_int_init(c);
+ for (row = 0; row < M->n_row; ++row) {
+ int first, i, off;
+ first = isl_seq_abs_min_non_zero(M->row[row]+col, M->n_col-col);
+ if (first == -1)
+ continue;
+ first += col;
+ if (first != col)
+ exchange(M, U, Q, row, first, col);
+ if (isl_int_is_neg(M->row[row][col]))
+ oppose(M, U, Q, row, col);
+ first = col+1;
+ while ((off = isl_seq_first_non_zero(M->row[row]+first,
+ M->n_col-first)) != -1) {
+ first += off;
+ isl_int_fdiv_q(c, M->row[row][first], M->row[row][col]);
+ subtract(M, U, Q, row, col, first, c);
+ if (!isl_int_is_zero(M->row[row][first]))
+ exchange(M, U, Q, row, first, col);
+ else
+ ++first;
+ }
+ for (i = 0; i < col; ++i) {
+ if (isl_int_is_zero(M->row[row][i]))
+ continue;
+ if (neg)
+ isl_int_cdiv_q(c, M->row[row][i], M->row[row][col]);
+ else
+ isl_int_fdiv_q(c, M->row[row][i], M->row[row][col]);
+ if (isl_int_is_zero(c))
+ continue;
+ subtract(M, U, Q, row, col, i, c);
+ }
+ ++col;
+ }
+ isl_int_clear(c);
+
+ return M;
+error:
+ if (Q) {
+ isl_mat_free(*Q);
+ *Q = NULL;
+ }
+ if (U) {
+ isl_mat_free(*U);
+ *U = NULL;
+ }
+ isl_mat_free(M);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_right_kernel(struct isl_mat *mat)
+{
+ int i, rank;
+ struct isl_mat *U = NULL;
+ struct isl_mat *K;
+
+ mat = isl_mat_left_hermite(mat, 0, &U, NULL);
+ if (!mat || !U)
+ goto error;
+
+ for (i = 0, rank = 0; rank < mat->n_col; ++rank) {
+ while (i < mat->n_row && isl_int_is_zero(mat->row[i][rank]))
+ ++i;
+ if (i >= mat->n_row)
+ break;
+ }
+ K = isl_mat_alloc(U->ctx, U->n_row, U->n_col - rank);
+ if (!K)
+ goto error;
+ isl_mat_sub_copy(K->ctx, K->row, U->row, U->n_row, 0, rank, U->n_col-rank);
+ isl_mat_free(mat);
+ isl_mat_free(U);
+ return K;
+error:
+ isl_mat_free(mat);
+ isl_mat_free(U);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat)
+{
+ int i;
+ struct isl_mat *mat2;
+
+ if (!mat)
+ return NULL;
+ mat2 = isl_mat_alloc(mat->ctx, 1+mat->n_row, 1+mat->n_col);
+ if (!mat2)
+ goto error;
+ isl_int_set_si(mat2->row[0][0], 1);
+ isl_seq_clr(mat2->row[0]+1, mat->n_col);
+ for (i = 0; i < mat->n_row; ++i) {
+ isl_int_set_si(mat2->row[1+i][0], 0);
+ isl_seq_cpy(mat2->row[1+i]+1, mat->row[i], mat->n_col);
+ }
+ isl_mat_free(mat);
+ return mat2;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+/* Given two matrices M1 and M2, return the block matrix
+ *
+ * [ M1 0 ]
+ * [ 0 M2 ]
+ */
+__isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1,
+ __isl_take isl_mat *mat2)
+{
+ int i;
+ isl_mat *mat;
+
+ if (!mat1 || !mat2)
+ goto error;
+
+ mat = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
+ mat1->n_col + mat2->n_col);
+ if (!mat)
+ goto error;
+ for (i = 0; i < mat1->n_row; ++i) {
+ isl_seq_cpy(mat->row[i], mat1->row[i], mat1->n_col);
+ isl_seq_clr(mat->row[i] + mat1->n_col, mat2->n_col);
+ }
+ for (i = 0; i < mat2->n_row; ++i) {
+ isl_seq_clr(mat->row[mat1->n_row + i], mat1->n_col);
+ isl_seq_cpy(mat->row[mat1->n_row + i] + mat1->n_col,
+ mat2->row[i], mat2->n_col);
+ }
+ isl_mat_free(mat1);
+ isl_mat_free(mat2);
+ return mat;
+error:
+ isl_mat_free(mat1);
+ isl_mat_free(mat2);
+ return NULL;
+}
+
+static int row_first_non_zero(isl_int **row, unsigned n_row, unsigned col)
+{
+ int i;
+
+ for (i = 0; i < n_row; ++i)
+ if (!isl_int_is_zero(row[i][col]))
+ return i;
+ return -1;
+}
+
+static int row_abs_min_non_zero(isl_int **row, unsigned n_row, unsigned col)
+{
+ int i, min = row_first_non_zero(row, n_row, col);
+ if (min < 0)
+ return -1;
+ for (i = min + 1; i < n_row; ++i) {
+ if (isl_int_is_zero(row[i][col]))
+ continue;
+ if (isl_int_abs_lt(row[i][col], row[min][col]))
+ min = i;
+ }
+ return min;
+}
+
+static void inv_exchange(struct isl_mat *left, struct isl_mat *right,
+ unsigned i, unsigned j)
+{
+ left = isl_mat_swap_rows(left, i, j);
+ right = isl_mat_swap_rows(right, i, j);
+}
+
+static void inv_oppose(
+ struct isl_mat *left, struct isl_mat *right, unsigned row)
+{
+ isl_seq_neg(left->row[row]+row, left->row[row]+row, left->n_col-row);
+ isl_seq_neg(right->row[row], right->row[row], right->n_col);
+}
+
+static void inv_subtract(struct isl_mat *left, struct isl_mat *right,
+ unsigned row, unsigned i, isl_int m)
+{
+ isl_int_neg(m, m);
+ isl_seq_combine(left->row[i]+row,
+ left->ctx->one, left->row[i]+row,
+ m, left->row[row]+row,
+ left->n_col-row);
+ isl_seq_combine(right->row[i], right->ctx->one, right->row[i],
+ m, right->row[row], right->n_col);
+}
+
+/* Compute inv(left)*right
+ */
+struct isl_mat *isl_mat_inverse_product(struct isl_mat *left,
+ struct isl_mat *right)
+{
+ int row;
+ isl_int a, b;
+
+ if (!left || !right)
+ goto error;
+
+ isl_assert(left->ctx, left->n_row == left->n_col, goto error);
+ isl_assert(left->ctx, left->n_row == right->n_row, goto error);
+
+ if (left->n_row == 0) {
+ isl_mat_free(left);
+ return right;
+ }
+
+ left = isl_mat_cow(left);
+ right = isl_mat_cow(right);
+ if (!left || !right)
+ goto error;
+
+ isl_int_init(a);
+ isl_int_init(b);
+ for (row = 0; row < left->n_row; ++row) {
+ int pivot, first, i, off;
+ pivot = row_abs_min_non_zero(left->row+row, left->n_row-row, row);
+ if (pivot < 0) {
+ isl_int_clear(a);
+ isl_int_clear(b);
+ isl_assert(left->ctx, pivot >= 0, goto error);
+ }
+ pivot += row;
+ if (pivot != row)
+ inv_exchange(left, right, pivot, row);
+ if (isl_int_is_neg(left->row[row][row]))
+ inv_oppose(left, right, row);
+ first = row+1;
+ while ((off = row_first_non_zero(left->row+first,
+ left->n_row-first, row)) != -1) {
+ first += off;
+ isl_int_fdiv_q(a, left->row[first][row],
+ left->row[row][row]);
+ inv_subtract(left, right, row, first, a);
+ if (!isl_int_is_zero(left->row[first][row]))
+ inv_exchange(left, right, row, first);
+ else
+ ++first;
+ }
+ for (i = 0; i < row; ++i) {
+ if (isl_int_is_zero(left->row[i][row]))
+ continue;
+ isl_int_gcd(a, left->row[row][row], left->row[i][row]);
+ isl_int_divexact(b, left->row[i][row], a);
+ isl_int_divexact(a, left->row[row][row], a);
+ isl_int_neg(b, b);
+ isl_seq_combine(left->row[i] + i,
+ a, left->row[i] + i,
+ b, left->row[row] + i,
+ left->n_col - i);
+ isl_seq_combine(right->row[i], a, right->row[i],
+ b, right->row[row], right->n_col);
+ }
+ }
+ isl_int_clear(b);
+
+ isl_int_set(a, left->row[0][0]);
+ for (row = 1; row < left->n_row; ++row)
+ isl_int_lcm(a, a, left->row[row][row]);
+ if (isl_int_is_zero(a)){
+ isl_int_clear(a);
+ isl_assert(left->ctx, 0, goto error);
+ }
+ for (row = 0; row < left->n_row; ++row) {
+ isl_int_divexact(left->row[row][row], a, left->row[row][row]);
+ if (isl_int_is_one(left->row[row][row]))
+ continue;
+ isl_seq_scale(right->row[row], right->row[row],
+ left->row[row][row], right->n_col);
+ }
+ isl_int_clear(a);
+
+ isl_mat_free(left);
+ return right;
+error:
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return NULL;
+}
+
+void isl_mat_col_scale(struct isl_mat *mat, unsigned col, isl_int m)
+{
+ int i;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_int_mul(mat->row[i][col], mat->row[i][col], m);
+}
+
+void isl_mat_col_combine(struct isl_mat *mat, unsigned dst,
+ isl_int m1, unsigned src1, isl_int m2, unsigned src2)
+{
+ int i;
+ isl_int tmp;
+
+ isl_int_init(tmp);
+ for (i = 0; i < mat->n_row; ++i) {
+ isl_int_mul(tmp, m1, mat->row[i][src1]);
+ isl_int_addmul(tmp, m2, mat->row[i][src2]);
+ isl_int_set(mat->row[i][dst], tmp);
+ }
+ isl_int_clear(tmp);
+}
+
+struct isl_mat *isl_mat_right_inverse(struct isl_mat *mat)
+{
+ struct isl_mat *inv;
+ int row;
+ isl_int a, b;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ inv = isl_mat_identity(mat->ctx, mat->n_col);
+ inv = isl_mat_cow(inv);
+ if (!inv)
+ goto error;
+
+ isl_int_init(a);
+ isl_int_init(b);
+ for (row = 0; row < mat->n_row; ++row) {
+ int pivot, first, i, off;
+ pivot = isl_seq_abs_min_non_zero(mat->row[row]+row, mat->n_col-row);
+ if (pivot < 0) {
+ isl_int_clear(a);
+ isl_int_clear(b);
+ isl_assert(mat->ctx, pivot >= 0, goto error);
+ }
+ pivot += row;
+ if (pivot != row)
+ exchange(mat, &inv, NULL, row, pivot, row);
+ if (isl_int_is_neg(mat->row[row][row]))
+ oppose(mat, &inv, NULL, row, row);
+ first = row+1;
+ while ((off = isl_seq_first_non_zero(mat->row[row]+first,
+ mat->n_col-first)) != -1) {
+ first += off;
+ isl_int_fdiv_q(a, mat->row[row][first],
+ mat->row[row][row]);
+ subtract(mat, &inv, NULL, row, row, first, a);
+ if (!isl_int_is_zero(mat->row[row][first]))
+ exchange(mat, &inv, NULL, row, row, first);
+ else
+ ++first;
+ }
+ for (i = 0; i < row; ++i) {
+ if (isl_int_is_zero(mat->row[row][i]))
+ continue;
+ isl_int_gcd(a, mat->row[row][row], mat->row[row][i]);
+ isl_int_divexact(b, mat->row[row][i], a);
+ isl_int_divexact(a, mat->row[row][row], a);
+ isl_int_neg(a, a);
+ isl_mat_col_combine(mat, i, a, i, b, row);
+ isl_mat_col_combine(inv, i, a, i, b, row);
+ }
+ }
+ isl_int_clear(b);
+
+ isl_int_set(a, mat->row[0][0]);
+ for (row = 1; row < mat->n_row; ++row)
+ isl_int_lcm(a, a, mat->row[row][row]);
+ if (isl_int_is_zero(a)){
+ isl_int_clear(a);
+ goto error;
+ }
+ for (row = 0; row < mat->n_row; ++row) {
+ isl_int_divexact(mat->row[row][row], a, mat->row[row][row]);
+ if (isl_int_is_one(mat->row[row][row]))
+ continue;
+ isl_mat_col_scale(inv, row, mat->row[row][row]);
+ }
+ isl_int_clear(a);
+
+ isl_mat_free(mat);
+
+ return inv;
+error:
+ isl_mat_free(mat);
+ isl_mat_free(inv);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_transpose(struct isl_mat *mat)
+{
+ struct isl_mat *transpose = NULL;
+ int i, j;
+
+ if (!mat)
+ return NULL;
+
+ if (mat->n_col == mat->n_row) {
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+ for (i = 0; i < mat->n_row; ++i)
+ for (j = i + 1; j < mat->n_col; ++j)
+ isl_int_swap(mat->row[i][j], mat->row[j][i]);
+ return mat;
+ }
+ transpose = isl_mat_alloc(mat->ctx, mat->n_col, mat->n_row);
+ if (!transpose)
+ goto error;
+ for (i = 0; i < mat->n_row; ++i)
+ for (j = 0; j < mat->n_col; ++j)
+ isl_int_set(transpose->row[j][i], mat->row[i][j]);
+ isl_mat_free(mat);
+ return transpose;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_swap_cols(struct isl_mat *mat, unsigned i, unsigned j)
+{
+ int r;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+ isl_assert(mat->ctx, i < mat->n_col, goto error);
+ isl_assert(mat->ctx, j < mat->n_col, goto error);
+
+ for (r = 0; r < mat->n_row; ++r)
+ isl_int_swap(mat->row[r][i], mat->row[r][j]);
+ return mat;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+struct isl_mat *isl_mat_swap_rows(struct isl_mat *mat, unsigned i, unsigned j)
+{
+ isl_int *t;
+
+ if (!mat)
+ return NULL;
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+ t = mat->row[i];
+ mat->row[i] = mat->row[j];
+ mat->row[j] = t;
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_product(__isl_take isl_mat *left,
+ __isl_take isl_mat *right)
+{
+ int i, j, k;
+ struct isl_mat *prod;
+
+ if (!left || !right)
+ goto error;
+ isl_assert(left->ctx, left->n_col == right->n_row, goto error);
+ prod = isl_mat_alloc(left->ctx, left->n_row, right->n_col);
+ if (!prod)
+ goto error;
+ if (left->n_col == 0) {
+ for (i = 0; i < prod->n_row; ++i)
+ isl_seq_clr(prod->row[i], prod->n_col);
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return prod;
+ }
+ for (i = 0; i < prod->n_row; ++i) {
+ for (j = 0; j < prod->n_col; ++j) {
+ isl_int_mul(prod->row[i][j],
+ left->row[i][0], right->row[0][j]);
+ for (k = 1; k < left->n_col; ++k)
+ isl_int_addmul(prod->row[i][j],
+ left->row[i][k], right->row[k][j]);
+ }
+ }
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return prod;
+error:
+ isl_mat_free(left);
+ isl_mat_free(right);
+ return NULL;
+}
+
+/* Replace the variables x in the rows q by x' given by x = M x',
+ * with M the matrix mat.
+ *
+ * If the number of new variables is greater than the original
+ * number of variables, then the rows q have already been
+ * preextended. If the new number is smaller, then the coefficients
+ * of the divs, which are not changed, need to be shifted down.
+ * The row q may be the equalities, the inequalities or the
+ * div expressions. In the latter case, has_div is true and
+ * we need to take into account the extra denominator column.
+ */
+static int preimage(struct isl_ctx *ctx, isl_int **q, unsigned n,
+ unsigned n_div, int has_div, struct isl_mat *mat)
+{
+ int i;
+ struct isl_mat *t;
+ int e;
+
+ if (mat->n_col >= mat->n_row)
+ e = 0;
+ else
+ e = mat->n_row - mat->n_col;
+ if (has_div)
+ for (i = 0; i < n; ++i)
+ isl_int_mul(q[i][0], q[i][0], mat->row[0][0]);
+ t = isl_mat_sub_alloc6(mat->ctx, q, 0, n, has_div, mat->n_row);
+ t = isl_mat_product(t, mat);
+ if (!t)
+ return -1;
+ for (i = 0; i < n; ++i) {
+ isl_seq_swp_or_cpy(q[i] + has_div, t->row[i], t->n_col);
+ isl_seq_cpy(q[i] + has_div + t->n_col,
+ q[i] + has_div + t->n_col + e, n_div);
+ isl_seq_clr(q[i] + has_div + t->n_col + n_div, e);
+ }
+ isl_mat_free(t);
+ return 0;
+}
+
+/* Replace the variables x in bset by x' given by x = M x', with
+ * 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,
+ * 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
+ * to be equal to extra.
+ */
+struct isl_basic_set *isl_basic_set_preimage(struct isl_basic_set *bset,
+ struct isl_mat *mat)
+{
+ struct isl_ctx *ctx;
+
+ if (!bset || !mat)
+ goto error;
+
+ ctx = bset->ctx;
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ goto error;
+
+ isl_assert(ctx, bset->dim->nparam == 0, goto error);
+ isl_assert(ctx, 1+bset->dim->n_out == mat->n_row, goto error);
+ isl_assert(ctx, mat->n_col > 0, goto error);
+
+ if (mat->n_col > mat->n_row) {
+ bset = isl_basic_set_extend(bset, 0, mat->n_col-1, 0, 0, 0);
+ if (!bset)
+ goto error;
+ } else if (mat->n_col < mat->n_row) {
+ bset->dim = isl_space_cow(bset->dim);
+ if (!bset->dim)
+ goto error;
+ bset->dim->n_out -= mat->n_row - mat->n_col;
+ }
+
+ if (preimage(ctx, bset->eq, bset->n_eq, bset->n_div, 0,
+ isl_mat_copy(mat)) < 0)
+ goto error;
+
+ if (preimage(ctx, bset->ineq, bset->n_ineq, bset->n_div, 0,
+ isl_mat_copy(mat)) < 0)
+ goto error;
+
+ if (preimage(ctx, bset->div, bset->n_div, bset->n_div, 1, mat) < 0)
+ goto error2;
+
+ ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
+ ISL_F_CLR(bset, ISL_BASIC_SET_NO_REDUNDANT);
+ ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
+ ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
+ ISL_F_CLR(bset, ISL_BASIC_SET_ALL_EQUALITIES);
+
+ bset = isl_basic_set_simplify(bset);
+ bset = isl_basic_set_finalize(bset);
+
+ return bset;
+error:
+ isl_mat_free(mat);
+error2:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_set *isl_set_preimage(struct isl_set *set, struct isl_mat *mat)
+{
+ struct isl_ctx *ctx;
+ int i;
+
+ set = isl_set_cow(set);
+ if (!set)
+ return NULL;
+
+ ctx = set->ctx;
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_basic_set_preimage(set->p[i],
+ isl_mat_copy(mat));
+ if (!set->p[i])
+ goto error;
+ }
+ if (mat->n_col != mat->n_row) {
+ set->dim = isl_space_cow(set->dim);
+ if (!set->dim)
+ goto error;
+ set->dim->n_out += mat->n_col;
+ set->dim->n_out -= mat->n_row;
+ }
+ isl_mat_free(mat);
+ ISL_F_CLR(set, ISL_SET_NORMALIZED);
+ return set;
+error:
+ isl_set_free(set);
+ isl_mat_free(mat);
+ return NULL;
+}
+
+/* Replace the variables x starting at pos in the rows q
+ * by x' with x = M x' with M the matrix mat.
+ * That is, replace the corresponding coefficients c by c M.
+ */
+static int transform(isl_ctx *ctx, isl_int **q, unsigned n,
+ unsigned pos, __isl_take isl_mat *mat)
+{
+ int i;
+ isl_mat *t;
+
+ t = isl_mat_sub_alloc6(ctx, q, 0, n, pos, mat->n_row);
+ t = isl_mat_product(t, mat);
+ if (!t)
+ return -1;
+ for (i = 0; i < n; ++i)
+ isl_seq_swp_or_cpy(q[i] + pos, t->row[i], t->n_col);
+ isl_mat_free(t);
+ return 0;
+}
+
+/* Replace the variables x of type "type" starting at "first" in "bset"
+ * by x' with x = M x' with M the matrix trans.
+ * That is, replace the corresponding coefficients c by c M.
+ *
+ * The transformation matrix should be a square matrix.
+ */
+__isl_give isl_basic_set *isl_basic_set_transform_dims(
+ __isl_take isl_basic_set *bset, enum isl_dim_type type, unsigned first,
+ __isl_take isl_mat *trans)
+{
+ isl_ctx *ctx;
+ unsigned pos;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset || !trans)
+ goto error;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ if (trans->n_row != trans->n_col)
+ isl_die(trans->ctx, isl_error_invalid,
+ "expecting square transformation matrix", goto error);
+ if (first + trans->n_row > isl_basic_set_dim(bset, type))
+ isl_die(trans->ctx, isl_error_invalid,
+ "oversized transformation matrix", goto error);
+
+ pos = isl_basic_set_offset(bset, type) + first;
+
+ if (transform(ctx, bset->eq, bset->n_eq, pos, isl_mat_copy(trans)) < 0)
+ goto error;
+ if (transform(ctx, bset->ineq, bset->n_ineq, pos,
+ isl_mat_copy(trans)) < 0)
+ goto error;
+ if (transform(ctx, bset->div, bset->n_div, 1 + pos,
+ isl_mat_copy(trans)) < 0)
+ goto error;
+
+ ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED);
+ ISL_F_CLR(bset, ISL_BASIC_SET_NORMALIZED_DIVS);
+
+ isl_mat_free(trans);
+ return bset;
+error:
+ isl_mat_free(trans);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+void isl_mat_print_internal(__isl_keep isl_mat *mat, FILE *out, int indent)
+{
+ int i, j;
+
+ if (!mat) {
+ fprintf(out, "%*snull mat\n", indent, "");
+ return;
+ }
+
+ if (mat->n_row == 0)
+ fprintf(out, "%*s[]\n", indent, "");
+
+ for (i = 0; i < mat->n_row; ++i) {
+ if (!i)
+ fprintf(out, "%*s[[", indent, "");
+ else
+ fprintf(out, "%*s[", indent+1, "");
+ for (j = 0; j < mat->n_col; ++j) {
+ if (j)
+ fprintf(out, ",");
+ isl_int_print(out, mat->row[i][j], 0);
+ }
+ if (i == mat->n_row-1)
+ fprintf(out, "]]\n");
+ else
+ fprintf(out, "]\n");
+ }
+}
+
+void isl_mat_dump(__isl_keep isl_mat *mat)
+{
+ isl_mat_print_internal(mat, stderr, 0);
+}
+
+struct isl_mat *isl_mat_drop_cols(struct isl_mat *mat, unsigned col, unsigned n)
+{
+ int r;
+
+ if (n == 0)
+ return mat;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ if (col != mat->n_col-n) {
+ for (r = 0; r < mat->n_row; ++r)
+ isl_seq_cpy(mat->row[r]+col, mat->row[r]+col+n,
+ mat->n_col - col - n);
+ }
+ mat->n_col -= n;
+ return mat;
+}
+
+struct isl_mat *isl_mat_drop_rows(struct isl_mat *mat, unsigned row, unsigned n)
+{
+ int r;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ for (r = row; r+n < mat->n_row; ++r)
+ mat->row[r] = mat->row[r+n];
+
+ mat->n_row -= n;
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_insert_cols(__isl_take isl_mat *mat,
+ unsigned col, unsigned n)
+{
+ isl_mat *ext;
+
+ if (!mat)
+ return NULL;
+ if (n == 0)
+ return mat;
+
+ ext = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col + n);
+ if (!ext)
+ goto error;
+
+ isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row, 0, 0, col);
+ isl_mat_sub_copy(mat->ctx, ext->row, mat->row, mat->n_row,
+ col + n, col, mat->n_col - col);
+
+ isl_mat_free(mat);
+ return ext;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_insert_zero_cols(__isl_take isl_mat *mat,
+ unsigned first, unsigned n)
+{
+ int i;
+
+ if (!mat)
+ return NULL;
+ mat = isl_mat_insert_cols(mat, first, n);
+ if (!mat)
+ return NULL;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_seq_clr(mat->row[i] + first, n);
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_add_zero_cols(__isl_take isl_mat *mat, unsigned n)
+{
+ if (!mat)
+ return NULL;
+
+ return isl_mat_insert_zero_cols(mat, mat->n_col, n);
+}
+
+__isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat,
+ unsigned row, unsigned n)
+{
+ isl_mat *ext;
+
+ if (!mat)
+ return NULL;
+ if (n == 0)
+ return mat;
+
+ ext = isl_mat_alloc(mat->ctx, mat->n_row + n, mat->n_col);
+ if (!ext)
+ goto error;
+
+ isl_mat_sub_copy(mat->ctx, ext->row, mat->row, row, 0, 0, mat->n_col);
+ isl_mat_sub_copy(mat->ctx, ext->row + row + n, mat->row + row,
+ mat->n_row - row, 0, 0, mat->n_col);
+
+ isl_mat_free(mat);
+ return ext;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_add_rows(__isl_take isl_mat *mat, unsigned n)
+{
+ if (!mat)
+ return NULL;
+
+ return isl_mat_insert_rows(mat, mat->n_row, n);
+}
+
+__isl_give isl_mat *isl_mat_insert_zero_rows(__isl_take isl_mat *mat,
+ unsigned row, unsigned n)
+{
+ int i;
+
+ mat = isl_mat_insert_rows(mat, row, n);
+ if (!mat)
+ return NULL;
+
+ for (i = 0; i < n; ++i)
+ isl_seq_clr(mat->row[row + i], mat->n_col);
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_add_zero_rows(__isl_take isl_mat *mat, unsigned n)
+{
+ if (!mat)
+ return NULL;
+
+ return isl_mat_insert_zero_rows(mat, mat->n_row, n);
+}
+
+void isl_mat_col_submul(struct isl_mat *mat,
+ int dst_col, isl_int f, int src_col)
+{
+ int i;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_int_submul(mat->row[i][dst_col], f, mat->row[i][src_col]);
+}
+
+void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col)
+{
+ int i;
+
+ if (!mat)
+ return;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_int_add(mat->row[i][dst_col],
+ mat->row[i][dst_col], mat->row[i][src_col]);
+}
+
+void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col)
+{
+ int i;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_int_mul(mat->row[i][dst_col], f, mat->row[i][src_col]);
+}
+
+struct isl_mat *isl_mat_unimodular_complete(struct isl_mat *M, int row)
+{
+ int r;
+ struct isl_mat *H = NULL, *Q = NULL;
+
+ if (!M)
+ return NULL;
+
+ isl_assert(M->ctx, M->n_row == M->n_col, goto error);
+ M->n_row = row;
+ H = isl_mat_left_hermite(isl_mat_copy(M), 0, NULL, &Q);
+ M->n_row = M->n_col;
+ if (!H)
+ goto error;
+ for (r = 0; r < row; ++r)
+ isl_assert(M->ctx, isl_int_is_one(H->row[r][r]), goto error);
+ for (r = row; r < M->n_row; ++r)
+ isl_seq_cpy(M->row[r], Q->row[r], M->n_col);
+ isl_mat_free(H);
+ isl_mat_free(Q);
+ return M;
+error:
+ isl_mat_free(H);
+ isl_mat_free(Q);
+ isl_mat_free(M);
+ return NULL;
+}
+
+__isl_give isl_mat *isl_mat_concat(__isl_take isl_mat *top,
+ __isl_take isl_mat *bot)
+{
+ struct isl_mat *mat;
+
+ if (!top || !bot)
+ goto error;
+
+ isl_assert(top->ctx, top->n_col == bot->n_col, goto error);
+ if (top->n_row == 0) {
+ isl_mat_free(top);
+ return bot;
+ }
+ if (bot->n_row == 0) {
+ isl_mat_free(bot);
+ return top;
+ }
+
+ mat = isl_mat_alloc(top->ctx, top->n_row + bot->n_row, top->n_col);
+ if (!mat)
+ goto error;
+ isl_mat_sub_copy(mat->ctx, mat->row, top->row, top->n_row,
+ 0, 0, mat->n_col);
+ isl_mat_sub_copy(mat->ctx, mat->row + top->n_row, bot->row, bot->n_row,
+ 0, 0, mat->n_col);
+ isl_mat_free(top);
+ isl_mat_free(bot);
+ return mat;
+error:
+ isl_mat_free(top);
+ isl_mat_free(bot);
+ return NULL;
+}
+
+int isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2)
+{
+ int i;
+
+ if (!mat1 || !mat2)
+ return -1;
+
+ if (mat1->n_row != mat2->n_row)
+ return 0;
+
+ if (mat1->n_col != mat2->n_col)
+ return 0;
+
+ for (i = 0; i < mat1->n_row; ++i)
+ if (!isl_seq_eq(mat1->row[i], mat2->row[i], mat1->n_col))
+ return 0;
+
+ return 1;
+}
+
+__isl_give isl_mat *isl_mat_from_row_vec(__isl_take isl_vec *vec)
+{
+ struct isl_mat *mat;
+
+ if (!vec)
+ return NULL;
+ mat = isl_mat_alloc(vec->ctx, 1, vec->size);
+ if (!mat)
+ goto error;
+
+ isl_seq_cpy(mat->row[0], vec->el, vec->size);
+
+ isl_vec_free(vec);
+ return mat;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+/* Return a copy of row "row" of "mat" as an isl_vec.
+ */
+__isl_give isl_vec *isl_mat_get_row(__isl_keep isl_mat *mat, unsigned row)
+{
+ isl_vec *v;
+
+ if (!mat)
+ return NULL;
+ if (row >= mat->n_row)
+ isl_die(mat->ctx, isl_error_invalid, "row out of range",
+ return NULL);
+
+ v = isl_vec_alloc(isl_mat_get_ctx(mat), mat->n_col);
+ if (!v)
+ return NULL;
+ isl_seq_cpy(v->el, mat->row[row], mat->n_col);
+
+ return v;
+}
+
+__isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
+ __isl_take isl_vec *bot)
+{
+ return isl_mat_concat(top, isl_mat_from_row_vec(bot));
+}
+
+__isl_give isl_mat *isl_mat_move_cols(__isl_take isl_mat *mat,
+ unsigned dst_col, unsigned src_col, unsigned n)
+{
+ isl_mat *res;
+
+ if (!mat)
+ return NULL;
+ if (n == 0 || dst_col == src_col)
+ return mat;
+
+ res = isl_mat_alloc(mat->ctx, mat->n_row, mat->n_col);
+ if (!res)
+ goto error;
+
+ if (dst_col < src_col) {
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ 0, 0, dst_col);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ dst_col, src_col, n);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ dst_col + n, dst_col, src_col - dst_col);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ src_col + n, src_col + n,
+ res->n_col - src_col - n);
+ } else {
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ 0, 0, src_col);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ src_col, src_col + n, dst_col - src_col);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ dst_col, src_col, n);
+ isl_mat_sub_copy(res->ctx, res->row, mat->row, mat->n_row,
+ dst_col + n, dst_col + n,
+ res->n_col - dst_col - n);
+ }
+ isl_mat_free(mat);
+
+ return res;
+error:
+ isl_mat_free(mat);
+ return NULL;
+}
+
+void isl_mat_gcd(__isl_keep isl_mat *mat, isl_int *gcd)
+{
+ int i;
+ isl_int g;
+
+ isl_int_set_si(*gcd, 0);
+ if (!mat)
+ return;
+
+ isl_int_init(g);
+ for (i = 0; i < mat->n_row; ++i) {
+ isl_seq_gcd(mat->row[i], mat->n_col, &g);
+ isl_int_gcd(*gcd, *gcd, g);
+ }
+ isl_int_clear(g);
+}
+
+__isl_give isl_mat *isl_mat_scale_down(__isl_take isl_mat *mat, isl_int m)
+{
+ int i;
+
+ if (isl_int_is_one(m))
+ return mat;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ for (i = 0; i < mat->n_row; ++i)
+ isl_seq_scale_down(mat->row[i], mat->row[i], m, mat->n_col);
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_scale_down_row(__isl_take isl_mat *mat, int row,
+ isl_int m)
+{
+ if (isl_int_is_one(m))
+ return mat;
+
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ isl_seq_scale_down(mat->row[row], mat->row[row], m, mat->n_col);
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat)
+{
+ isl_int gcd;
+
+ if (!mat)
+ return NULL;
+
+ isl_int_init(gcd);
+ isl_mat_gcd(mat, &gcd);
+ mat = isl_mat_scale_down(mat, gcd);
+ isl_int_clear(gcd);
+
+ return mat;
+}
+
+__isl_give isl_mat *isl_mat_normalize_row(__isl_take isl_mat *mat, int row)
+{
+ mat = isl_mat_cow(mat);
+ if (!mat)
+ return NULL;
+
+ isl_seq_normalize(mat->ctx, mat->row[row], mat->n_col);
+
+ return mat;
+}
+
+/* Number of initial non-zero columns.
+ */
+int isl_mat_initial_non_zero_cols(__isl_keep isl_mat *mat)
+{
+ int i;
+
+ if (!mat)
+ return -1;
+
+ for (i = 0; i < mat->n_col; ++i)
+ if (row_first_non_zero(mat->row, mat->n_row, i) < 0)
+ break;
+
+ return i;
+}
diff --git a/polly/lib/External/isl/isl_mat_private.h b/polly/lib/External/isl/isl_mat_private.h
new file mode 100644
index 00000000000..566634d352b
--- /dev/null
+++ b/polly/lib/External/isl/isl_mat_private.h
@@ -0,0 +1,46 @@
+#include <isl/mat.h>
+#include <isl_blk.h>
+
+struct isl_mat {
+ int ref;
+
+ struct isl_ctx *ctx;
+
+#define ISL_MAT_BORROWED (1 << 0)
+ unsigned flags;
+
+ unsigned n_row;
+ unsigned n_col;
+
+ isl_int **row;
+
+ /* actual size of the rows in memory; n_col <= max_col */
+ unsigned max_col;
+
+ struct isl_blk block;
+};
+
+__isl_give isl_mat *isl_mat_sub_alloc(__isl_keep isl_mat *mat,
+ unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col);
+__isl_give isl_mat *isl_mat_sub_alloc6(isl_ctx *ctx, isl_int **row,
+ unsigned first_row, unsigned n_row, unsigned first_col, unsigned n_col);
+void isl_mat_sub_copy(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
+ unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col);
+void isl_mat_sub_neg(struct isl_ctx *ctx, isl_int **dst, isl_int **src,
+ unsigned n_row, unsigned dst_col, unsigned src_col, unsigned n_col);
+__isl_give isl_mat *isl_mat_diag(isl_ctx *ctx, unsigned n_row, isl_int d);
+
+__isl_give isl_mat *isl_mat_scale_down_row(__isl_take isl_mat *mat, int row,
+ isl_int m);
+
+__isl_give isl_vec *isl_mat_get_row(__isl_keep isl_mat *mat, unsigned row);
+
+int isl_mat_is_scaled_identity(__isl_keep isl_mat *mat);
+
+void isl_mat_col_mul(struct isl_mat *mat, int dst_col, isl_int f, int src_col);
+void isl_mat_col_submul(struct isl_mat *mat,
+ int dst_col, isl_int f, int src_col);
+
+int isl_mat_get_element(__isl_keep isl_mat *mat, int row, int col, isl_int *v);
+__isl_give isl_mat *isl_mat_set_element(__isl_take isl_mat *mat,
+ int row, int col, isl_int v);
diff --git a/polly/lib/External/isl/isl_morph.c b/polly/lib/External/isl/isl_morph.c
new file mode 100644
index 00000000000..9030cab1bda
--- /dev/null
+++ b/polly/lib/External/isl/isl_morph.c
@@ -0,0 +1,917 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2014 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_map_private.h>
+#include <isl_aff_private.h>
+#include <isl_morph.h>
+#include <isl_seq.h>
+#include <isl_mat_private.h>
+#include <isl_space_private.h>
+#include <isl_equalities.h>
+
+isl_ctx *isl_morph_get_ctx(__isl_keep isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+ return isl_basic_set_get_ctx(morph->dom);
+}
+
+__isl_give isl_morph *isl_morph_alloc(
+ __isl_take isl_basic_set *dom, __isl_take isl_basic_set *ran,
+ __isl_take isl_mat *map, __isl_take isl_mat *inv)
+{
+ isl_morph *morph;
+
+ if (!dom || !ran || !map || !inv)
+ goto error;
+
+ morph = isl_alloc_type(dom->ctx, struct isl_morph);
+ if (!morph)
+ goto error;
+
+ morph->ref = 1;
+ morph->dom = dom;
+ morph->ran = ran;
+ morph->map = map;
+ morph->inv = inv;
+
+ return morph;
+error:
+ isl_basic_set_free(dom);
+ isl_basic_set_free(ran);
+ isl_mat_free(map);
+ isl_mat_free(inv);
+ return NULL;
+}
+
+__isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+
+ morph->ref++;
+ return morph;
+}
+
+__isl_give isl_morph *isl_morph_dup(__isl_keep isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+
+ return isl_morph_alloc(isl_basic_set_copy(morph->dom),
+ isl_basic_set_copy(morph->ran),
+ isl_mat_copy(morph->map), isl_mat_copy(morph->inv));
+}
+
+__isl_give isl_morph *isl_morph_cow(__isl_take isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+
+ if (morph->ref == 1)
+ return morph;
+ morph->ref--;
+ return isl_morph_dup(morph);
+}
+
+void isl_morph_free(__isl_take isl_morph *morph)
+{
+ if (!morph)
+ return;
+
+ if (--morph->ref > 0)
+ return;
+
+ isl_basic_set_free(morph->dom);
+ isl_basic_set_free(morph->ran);
+ isl_mat_free(morph->map);
+ isl_mat_free(morph->inv);
+ free(morph);
+}
+
+/* Is "morph" an identity on the parameters?
+ */
+static int identity_on_parameters(__isl_keep isl_morph *morph)
+{
+ int is_identity;
+ unsigned nparam;
+ isl_mat *sub;
+
+ nparam = isl_morph_dom_dim(morph, isl_dim_param);
+ if (nparam != isl_morph_ran_dim(morph, isl_dim_param))
+ return 0;
+ if (nparam == 0)
+ return 1;
+ sub = isl_mat_sub_alloc(morph->map, 0, 1 + nparam, 0, 1 + nparam);
+ is_identity = isl_mat_is_scaled_identity(sub);
+ isl_mat_free(sub);
+
+ return is_identity;
+}
+
+/* Return an affine expression of the variables of the range of "morph"
+ * in terms of the parameters and the variables of the domain on "morph".
+ *
+ * In order for the space manipulations to make sense, we require
+ * that the parameters are not modified by "morph".
+ */
+__isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
+ __isl_keep isl_morph *morph)
+{
+ isl_space *dom, *ran, *space;
+ isl_local_space *ls;
+ isl_multi_aff *ma;
+ unsigned nparam, nvar;
+ int i;
+ int is_identity;
+
+ if (!morph)
+ return NULL;
+
+ is_identity = identity_on_parameters(morph);
+ if (is_identity < 0)
+ return NULL;
+ if (!is_identity)
+ isl_die(isl_morph_get_ctx(morph), isl_error_invalid,
+ "cannot handle parameter compression", return NULL);
+
+ dom = isl_morph_get_dom_space(morph);
+ ls = isl_local_space_from_space(isl_space_copy(dom));
+ ran = isl_morph_get_ran_space(morph);
+ space = isl_space_map_from_domain_and_range(dom, ran);
+ ma = isl_multi_aff_zero(space);
+
+ nparam = isl_multi_aff_dim(ma, isl_dim_param);
+ nvar = isl_multi_aff_dim(ma, isl_dim_out);
+ for (i = 0; i < nvar; ++i) {
+ isl_val *val;
+ isl_vec *v;
+ isl_aff *aff;
+
+ v = isl_mat_get_row(morph->map, 1 + nparam + i);
+ v = isl_vec_insert_els(v, 0, 1);
+ val = isl_mat_get_element_val(morph->map, 0, 0);
+ v = isl_vec_set_element_val(v, 0, val);
+ aff = isl_aff_alloc_vec(isl_local_space_copy(ls), v);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ isl_local_space_free(ls);
+ return ma;
+}
+
+/* Return the domain space of "morph".
+ */
+__isl_give isl_space *isl_morph_get_dom_space(__isl_keep isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+
+ return isl_basic_set_get_space(morph->dom);
+}
+
+__isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph)
+{
+ if (!morph)
+ return NULL;
+
+ return isl_space_copy(morph->ran->dim);
+}
+
+unsigned isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
+{
+ if (!morph)
+ return 0;
+
+ return isl_basic_set_dim(morph->dom, type);
+}
+
+unsigned isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type)
+{
+ if (!morph)
+ return 0;
+
+ return isl_basic_set_dim(morph->ran, type);
+}
+
+__isl_give isl_morph *isl_morph_remove_dom_dims(__isl_take isl_morph *morph,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ unsigned dom_offset;
+
+ if (n == 0)
+ return morph;
+
+ morph = isl_morph_cow(morph);
+ if (!morph)
+ return NULL;
+
+ dom_offset = 1 + isl_space_offset(morph->dom->dim, type);
+
+ morph->dom = isl_basic_set_remove_dims(morph->dom, type, first, n);
+
+ morph->map = isl_mat_drop_cols(morph->map, dom_offset + first, n);
+
+ morph->inv = isl_mat_drop_rows(morph->inv, dom_offset + first, n);
+
+ if (morph->dom && morph->ran && morph->map && morph->inv)
+ return morph;
+
+ isl_morph_free(morph);
+ return NULL;
+}
+
+__isl_give isl_morph *isl_morph_remove_ran_dims(__isl_take isl_morph *morph,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ unsigned ran_offset;
+
+ if (n == 0)
+ return morph;
+
+ morph = isl_morph_cow(morph);
+ if (!morph)
+ return NULL;
+
+ ran_offset = 1 + isl_space_offset(morph->ran->dim, type);
+
+ morph->ran = isl_basic_set_remove_dims(morph->ran, type, first, n);
+
+ morph->map = isl_mat_drop_rows(morph->map, ran_offset + first, n);
+
+ morph->inv = isl_mat_drop_cols(morph->inv, ran_offset + first, n);
+
+ if (morph->dom && morph->ran && morph->map && morph->inv)
+ return morph;
+
+ isl_morph_free(morph);
+ return NULL;
+}
+
+/* Project domain of morph onto its parameter domain.
+ */
+__isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph)
+{
+ unsigned n;
+
+ morph = isl_morph_cow(morph);
+ if (!morph)
+ return NULL;
+ n = isl_basic_set_dim(morph->dom, isl_dim_set);
+ morph = isl_morph_remove_dom_dims(morph, isl_dim_set, 0, n);
+ if (!morph)
+ return NULL;
+ morph->dom = isl_basic_set_params(morph->dom);
+ if (morph->dom)
+ return morph;
+
+ isl_morph_free(morph);
+ return NULL;
+}
+
+/* Project range of morph onto its parameter domain.
+ */
+__isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph)
+{
+ unsigned n;
+
+ morph = isl_morph_cow(morph);
+ if (!morph)
+ return NULL;
+ n = isl_basic_set_dim(morph->ran, isl_dim_set);
+ morph = isl_morph_remove_ran_dims(morph, isl_dim_set, 0, n);
+ if (!morph)
+ return NULL;
+ morph->ran = isl_basic_set_params(morph->ran);
+ if (morph->ran)
+ return morph;
+
+ isl_morph_free(morph);
+ return NULL;
+}
+
+void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out)
+{
+ if (!morph)
+ return;
+
+ isl_basic_set_print(morph->dom, out, 0, "", "", ISL_FORMAT_ISL);
+ isl_basic_set_print(morph->ran, out, 0, "", "", ISL_FORMAT_ISL);
+ isl_mat_print_internal(morph->map, out, 4);
+ isl_mat_print_internal(morph->inv, out, 4);
+}
+
+void isl_morph_dump(__isl_take isl_morph *morph)
+{
+ isl_morph_print_internal(morph, stderr);
+}
+
+__isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset)
+{
+ isl_mat *id;
+ isl_basic_set *universe;
+ unsigned total;
+
+ if (!bset)
+ return NULL;
+
+ total = isl_basic_set_total_dim(bset);
+ id = isl_mat_identity(bset->ctx, 1 + total);
+ universe = isl_basic_set_universe(isl_space_copy(bset->dim));
+
+ return isl_morph_alloc(universe, isl_basic_set_copy(universe),
+ id, isl_mat_copy(id));
+}
+
+/* Create a(n identity) morphism between empty sets of the same dimension
+ * a "bset".
+ */
+__isl_give isl_morph *isl_morph_empty(__isl_keep isl_basic_set *bset)
+{
+ isl_mat *id;
+ isl_basic_set *empty;
+ unsigned total;
+
+ if (!bset)
+ return NULL;
+
+ total = isl_basic_set_total_dim(bset);
+ id = isl_mat_identity(bset->ctx, 1 + total);
+ empty = isl_basic_set_empty(isl_space_copy(bset->dim));
+
+ return isl_morph_alloc(empty, isl_basic_set_copy(empty),
+ id, isl_mat_copy(id));
+}
+
+/* Given a matrix that maps a (possibly) parametric domain to
+ * a parametric domain, add in rows that map the "nparam" parameters onto
+ * themselves.
+ */
+static __isl_give isl_mat *insert_parameter_rows(__isl_take isl_mat *mat,
+ unsigned nparam)
+{
+ int i;
+
+ if (nparam == 0)
+ return mat;
+ if (!mat)
+ return NULL;
+
+ mat = isl_mat_insert_rows(mat, 1, nparam);
+ if (!mat)
+ return NULL;
+
+ for (i = 0; i < nparam; ++i) {
+ isl_seq_clr(mat->row[1 + i], mat->n_col);
+ isl_int_set(mat->row[1 + i][1 + i], mat->row[0][0]);
+ }
+
+ return mat;
+}
+
+/* Construct a basic set described by the "n" equalities of "bset" starting
+ * at "first".
+ */
+static __isl_give isl_basic_set *copy_equalities(__isl_keep isl_basic_set *bset,
+ unsigned first, unsigned n)
+{
+ int i, k;
+ isl_basic_set *eq;
+ unsigned total;
+
+ isl_assert(bset->ctx, bset->n_div == 0, return NULL);
+
+ total = isl_basic_set_total_dim(bset);
+ eq = isl_basic_set_alloc_space(isl_space_copy(bset->dim), 0, n, 0);
+ if (!eq)
+ return NULL;
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_set_alloc_equality(eq);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(eq->eq[k], bset->eq[first + k], 1 + total);
+ }
+
+ return eq;
+error:
+ isl_basic_set_free(eq);
+ return NULL;
+}
+
+/* Given a basic set, exploit the equalties in the basic set to construct
+ * a morphishm that maps the basic set to a lower-dimensional space.
+ * Specifically, the morphism reduces the number of dimensions of type "type".
+ *
+ * This function is a slight generalization of isl_mat_variable_compression
+ * in that it allows the input to be parametric and that it allows for the
+ * compression of either parameters or set variables.
+ *
+ * We first select the equalities of interest, that is those that involve
+ * variables of type "type" and no later variables.
+ * Denote those equalities as
+ *
+ * -C(p) + M x = 0
+ *
+ * where C(p) depends on the parameters if type == isl_dim_set and
+ * is a constant if type == isl_dim_param.
+ *
+ * First compute the (left) Hermite normal form of M,
+ *
+ * M [U1 U2] = M U = H = [H1 0]
+ * or
+ * M = H Q = [H1 0] [Q1]
+ * [Q2]
+ *
+ * with U, Q unimodular, Q = U^{-1} (and H lower triangular).
+ * Define the transformed variables as
+ *
+ * x = [U1 U2] [ x1' ] = [U1 U2] [Q1] x
+ * [ x2' ] [Q2]
+ *
+ * The equalities then become
+ *
+ * -C(p) + H1 x1' = 0 or x1' = H1^{-1} C(p) = C'(p)
+ *
+ * If the denominator of the constant term does not divide the
+ * the common denominator of the parametric terms, then every
+ * integer point is mapped to a non-integer point and then the original set has no
+ * integer solutions (since the x' are a unimodular transformation
+ * of the x). In this case, an empty morphism is returned.
+ * Otherwise, the transformation is given by
+ *
+ * x = U1 H1^{-1} C(p) + U2 x2'
+ *
+ * The inverse transformation is simply
+ *
+ * x2' = Q2 x
+ *
+ * Both matrices are extended to map the full original space to the full
+ * compressed space.
+ */
+__isl_give isl_morph *isl_basic_set_variable_compression(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type type)
+{
+ unsigned otype;
+ unsigned ntype;
+ unsigned orest;
+ unsigned nrest;
+ int f_eq, n_eq;
+ isl_space *dim;
+ isl_mat *H, *U, *Q, *C = NULL, *H1, *U1, *U2;
+ isl_basic_set *dom, *ran;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return isl_morph_empty(bset);
+
+ isl_assert(bset->ctx, bset->n_div == 0, return NULL);
+
+ otype = 1 + isl_space_offset(bset->dim, type);
+ ntype = isl_basic_set_dim(bset, type);
+ orest = otype + ntype;
+ nrest = isl_basic_set_total_dim(bset) - (orest - 1);
+
+ for (f_eq = 0; f_eq < bset->n_eq; ++f_eq)
+ if (isl_seq_first_non_zero(bset->eq[f_eq] + orest, nrest) == -1)
+ break;
+ for (n_eq = 0; f_eq + n_eq < bset->n_eq; ++n_eq)
+ if (isl_seq_first_non_zero(bset->eq[f_eq + n_eq] + otype, ntype) == -1)
+ break;
+ if (n_eq == 0)
+ return isl_morph_identity(bset);
+
+ H = isl_mat_sub_alloc6(bset->ctx, bset->eq, f_eq, n_eq, otype, ntype);
+ H = isl_mat_left_hermite(H, 0, &U, &Q);
+ if (!H || !U || !Q)
+ goto error;
+ Q = isl_mat_drop_rows(Q, 0, n_eq);
+ Q = isl_mat_diagonal(isl_mat_identity(bset->ctx, otype), Q);
+ Q = isl_mat_diagonal(Q, isl_mat_identity(bset->ctx, nrest));
+ C = isl_mat_alloc(bset->ctx, 1 + n_eq, otype);
+ if (!C)
+ goto error;
+ isl_int_set_si(C->row[0][0], 1);
+ isl_seq_clr(C->row[0] + 1, otype - 1);
+ isl_mat_sub_neg(C->ctx, C->row + 1, bset->eq + f_eq, n_eq, 0, 0, otype);
+ H1 = isl_mat_sub_alloc(H, 0, H->n_row, 0, H->n_row);
+ H1 = isl_mat_lin_to_aff(H1);
+ C = isl_mat_inverse_product(H1, C);
+ if (!C)
+ goto error;
+ isl_mat_free(H);
+
+ if (!isl_int_is_one(C->row[0][0])) {
+ int i;
+ isl_int g;
+
+ isl_int_init(g);
+ for (i = 0; i < n_eq; ++i) {
+ isl_seq_gcd(C->row[1 + i] + 1, otype - 1, &g);
+ isl_int_gcd(g, g, C->row[0][0]);
+ if (!isl_int_is_divisible_by(C->row[1 + i][0], g))
+ break;
+ }
+ isl_int_clear(g);
+
+ if (i < n_eq) {
+ isl_mat_free(C);
+ isl_mat_free(U);
+ isl_mat_free(Q);
+ return isl_morph_empty(bset);
+ }
+
+ C = isl_mat_normalize(C);
+ }
+
+ U1 = isl_mat_sub_alloc(U, 0, U->n_row, 0, n_eq);
+ U1 = isl_mat_lin_to_aff(U1);
+ U2 = isl_mat_sub_alloc(U, 0, U->n_row, n_eq, U->n_row - n_eq);
+ U2 = isl_mat_lin_to_aff(U2);
+ isl_mat_free(U);
+
+ C = isl_mat_product(U1, C);
+ C = isl_mat_aff_direct_sum(C, U2);
+ C = insert_parameter_rows(C, otype - 1);
+ C = isl_mat_diagonal(C, isl_mat_identity(bset->ctx, nrest));
+
+ dim = isl_space_copy(bset->dim);
+ dim = isl_space_drop_dims(dim, type, 0, ntype);
+ dim = isl_space_add_dims(dim, type, ntype - n_eq);
+ ran = isl_basic_set_universe(dim);
+ dom = copy_equalities(bset, f_eq, n_eq);
+
+ return isl_morph_alloc(dom, ran, Q, C);
+error:
+ isl_mat_free(C);
+ isl_mat_free(H);
+ isl_mat_free(U);
+ isl_mat_free(Q);
+ return NULL;
+}
+
+/* Construct a parameter compression for "bset".
+ * We basically just call isl_mat_parameter_compression with the right input
+ * and then extend the resulting matrix to include the variables.
+ *
+ * The implementation assumes that "bset" does not have any equalities
+ * that only involve the parameters and that isl_basic_set_gauss has
+ * been applied to "bset".
+ *
+ * Let the equalities be given as
+ *
+ * B(p) + A x = 0.
+ *
+ * We use isl_mat_parameter_compression_ext to compute the compression
+ *
+ * p = T p'.
+ */
+__isl_give isl_morph *isl_basic_set_parameter_compression(
+ __isl_keep isl_basic_set *bset)
+{
+ unsigned nparam;
+ unsigned nvar;
+ unsigned n_div;
+ int n_eq;
+ isl_mat *H, *B;
+ isl_mat *map, *inv;
+ isl_basic_set *dom, *ran;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return isl_morph_empty(bset);
+ if (bset->n_eq == 0)
+ return isl_morph_identity(bset);
+
+ n_eq = bset->n_eq;
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+
+ if (isl_seq_first_non_zero(bset->eq[bset->n_eq - 1] + 1 + nparam,
+ nvar + n_div) == -1)
+ isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
+ "input not allowed to have parameter equalities",
+ return NULL);
+ if (n_eq > nvar + n_div)
+ isl_die(isl_basic_set_get_ctx(bset), isl_error_invalid,
+ "input not gaussed", return NULL);
+
+ B = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, n_eq, 0, 1 + nparam);
+ H = isl_mat_sub_alloc6(bset->ctx, bset->eq,
+ 0, n_eq, 1 + nparam, nvar + n_div);
+ inv = isl_mat_parameter_compression_ext(B, H);
+ inv = isl_mat_diagonal(inv, isl_mat_identity(bset->ctx, nvar));
+ map = isl_mat_right_inverse(isl_mat_copy(inv));
+
+ dom = isl_basic_set_universe(isl_space_copy(bset->dim));
+ ran = isl_basic_set_universe(isl_space_copy(bset->dim));
+
+ return isl_morph_alloc(dom, ran, map, inv);
+}
+
+/* Add stride constraints to "bset" based on the inverse mapping
+ * that was plugged in. In particular, if morph maps x' to x,
+ * the the constraints of the original input
+ *
+ * A x' + b >= 0
+ *
+ * have been rewritten to
+ *
+ * A inv x + b >= 0
+ *
+ * However, this substitution may loose information on the integrality of x',
+ * so we need to impose that
+ *
+ * inv x
+ *
+ * is integral. If inv = B/d, this means that we need to impose that
+ *
+ * B x = 0 mod d
+ *
+ * or
+ *
+ * exists alpha in Z^m: B x = d alpha
+ *
+ * This function is similar to add_strides in isl_affine_hull.c
+ */
+static __isl_give isl_basic_set *add_strides(__isl_take isl_basic_set *bset,
+ __isl_keep isl_morph *morph)
+{
+ int i, div, k;
+ isl_int gcd;
+
+ if (isl_int_is_one(morph->inv->row[0][0]))
+ return bset;
+
+ isl_int_init(gcd);
+
+ for (i = 0; 1 + i < morph->inv->n_row; ++i) {
+ isl_seq_gcd(morph->inv->row[1 + i], morph->inv->n_col, &gcd);
+ if (isl_int_is_divisible_by(gcd, morph->inv->row[0][0]))
+ continue;
+ div = isl_basic_set_alloc_div(bset);
+ if (div < 0)
+ goto error;
+ isl_int_set_si(bset->div[div][0], 0);
+ k = isl_basic_set_alloc_equality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->eq[k], morph->inv->row[1 + i],
+ morph->inv->n_col);
+ isl_seq_clr(bset->eq[k] + morph->inv->n_col, bset->n_div);
+ isl_int_set(bset->eq[k][morph->inv->n_col + div],
+ morph->inv->row[0][0]);
+ }
+
+ isl_int_clear(gcd);
+
+ return bset;
+error:
+ isl_int_clear(gcd);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Apply the morphism to the basic set.
+ * We basically just compute the preimage of "bset" under the inverse mapping
+ * in morph, add in stride constraints and intersect with the range
+ * of the morphism.
+ */
+__isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,
+ __isl_take isl_basic_set *bset)
+{
+ isl_basic_set *res = NULL;
+ isl_mat *mat = NULL;
+ int i, k;
+ int max_stride;
+
+ if (!morph || !bset)
+ goto error;
+
+ isl_assert(bset->ctx, isl_space_is_equal(bset->dim, morph->dom->dim),
+ goto error);
+
+ max_stride = morph->inv->n_row - 1;
+ if (isl_int_is_one(morph->inv->row[0][0]))
+ max_stride = 0;
+ res = isl_basic_set_alloc_space(isl_space_copy(morph->ran->dim),
+ bset->n_div + max_stride, bset->n_eq + max_stride, bset->n_ineq);
+
+ for (i = 0; i < bset->n_div; ++i)
+ if (isl_basic_set_alloc_div(res) < 0)
+ goto error;
+
+ mat = isl_mat_sub_alloc6(bset->ctx, bset->eq, 0, bset->n_eq,
+ 0, morph->inv->n_row);
+ mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
+ if (!mat)
+ goto error;
+ for (i = 0; i < bset->n_eq; ++i) {
+ k = isl_basic_set_alloc_equality(res);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(res->eq[k], mat->row[i], mat->n_col);
+ isl_seq_scale(res->eq[k] + mat->n_col, bset->eq[i] + mat->n_col,
+ morph->inv->row[0][0], bset->n_div);
+ }
+ isl_mat_free(mat);
+
+ mat = isl_mat_sub_alloc6(bset->ctx, bset->ineq, 0, bset->n_ineq,
+ 0, morph->inv->n_row);
+ mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
+ if (!mat)
+ goto error;
+ for (i = 0; i < bset->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(res);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(res->ineq[k], mat->row[i], mat->n_col);
+ isl_seq_scale(res->ineq[k] + mat->n_col,
+ bset->ineq[i] + mat->n_col,
+ morph->inv->row[0][0], bset->n_div);
+ }
+ isl_mat_free(mat);
+
+ mat = isl_mat_sub_alloc6(bset->ctx, bset->div, 0, bset->n_div,
+ 1, morph->inv->n_row);
+ mat = isl_mat_product(mat, isl_mat_copy(morph->inv));
+ if (!mat)
+ goto error;
+ for (i = 0; i < bset->n_div; ++i) {
+ isl_int_mul(res->div[i][0],
+ morph->inv->row[0][0], bset->div[i][0]);
+ isl_seq_cpy(res->div[i] + 1, mat->row[i], mat->n_col);
+ isl_seq_scale(res->div[i] + 1 + mat->n_col,
+ bset->div[i] + 1 + mat->n_col,
+ morph->inv->row[0][0], bset->n_div);
+ }
+ isl_mat_free(mat);
+
+ res = add_strides(res, morph);
+
+ if (isl_basic_set_is_rational(bset))
+ res = isl_basic_set_set_rational(res);
+
+ res = isl_basic_set_simplify(res);
+ res = isl_basic_set_finalize(res);
+
+ res = isl_basic_set_intersect(res, isl_basic_set_copy(morph->ran));
+
+ isl_morph_free(morph);
+ isl_basic_set_free(bset);
+ return res;
+error:
+ isl_mat_free(mat);
+ isl_morph_free(morph);
+ isl_basic_set_free(bset);
+ isl_basic_set_free(res);
+ return NULL;
+}
+
+/* Apply the morphism to the set.
+ */
+__isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph,
+ __isl_take isl_set *set)
+{
+ int i;
+
+ if (!morph || !set)
+ goto error;
+
+ isl_assert(set->ctx, isl_space_is_equal(set->dim, morph->dom->dim), goto error);
+
+ set = isl_set_cow(set);
+ if (!set)
+ goto error;
+
+ isl_space_free(set->dim);
+ set->dim = isl_space_copy(morph->ran->dim);
+ if (!set->dim)
+ goto error;
+
+ for (i = 0; i < set->n; ++i) {
+ set->p[i] = isl_morph_basic_set(isl_morph_copy(morph), set->p[i]);
+ if (!set->p[i])
+ goto error;
+ }
+
+ isl_morph_free(morph);
+
+ ISL_F_CLR(set, ISL_SET_NORMALIZED);
+
+ return set;
+error:
+ isl_set_free(set);
+ isl_morph_free(morph);
+ return NULL;
+}
+
+/* Construct a morphism that first does morph2 and then morph1.
+ */
+__isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1,
+ __isl_take isl_morph *morph2)
+{
+ isl_mat *map, *inv;
+ isl_basic_set *dom, *ran;
+
+ if (!morph1 || !morph2)
+ goto error;
+
+ map = isl_mat_product(isl_mat_copy(morph1->map), isl_mat_copy(morph2->map));
+ inv = isl_mat_product(isl_mat_copy(morph2->inv), isl_mat_copy(morph1->inv));
+ dom = isl_morph_basic_set(isl_morph_inverse(isl_morph_copy(morph2)),
+ isl_basic_set_copy(morph1->dom));
+ dom = isl_basic_set_intersect(dom, isl_basic_set_copy(morph2->dom));
+ ran = isl_morph_basic_set(isl_morph_copy(morph1),
+ isl_basic_set_copy(morph2->ran));
+ ran = isl_basic_set_intersect(ran, isl_basic_set_copy(morph1->ran));
+
+ isl_morph_free(morph1);
+ isl_morph_free(morph2);
+
+ return isl_morph_alloc(dom, ran, map, inv);
+error:
+ isl_morph_free(morph1);
+ isl_morph_free(morph2);
+ return NULL;
+}
+
+__isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph)
+{
+ isl_basic_set *bset;
+ isl_mat *mat;
+
+ morph = isl_morph_cow(morph);
+ if (!morph)
+ return NULL;
+
+ bset = morph->dom;
+ morph->dom = morph->ran;
+ morph->ran = bset;
+
+ mat = morph->map;
+ morph->map = morph->inv;
+ morph->inv = mat;
+
+ return morph;
+}
+
+/* We detect all the equalities first to avoid implicit equalties
+ * being discovered during the computations. In particular,
+ * the compression on the variables could expose additional stride
+ * constraints on the parameters. This would result in existentially
+ * quantified variables after applying the resulting morph, which
+ * in turn could break invariants of the calling functions.
+ */
+__isl_give isl_morph *isl_basic_set_full_compression(
+ __isl_keep isl_basic_set *bset)
+{
+ isl_morph *morph, *morph2;
+
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_detect_equalities(bset);
+
+ morph = isl_basic_set_variable_compression(bset, isl_dim_param);
+ bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+
+ morph2 = isl_basic_set_parameter_compression(bset);
+ bset = isl_morph_basic_set(isl_morph_copy(morph2), bset);
+
+ morph = isl_morph_compose(morph2, morph);
+
+ morph2 = isl_basic_set_variable_compression(bset, isl_dim_set);
+ isl_basic_set_free(bset);
+
+ morph = isl_morph_compose(morph2, morph);
+
+ return morph;
+}
+
+__isl_give isl_vec *isl_morph_vec(__isl_take isl_morph *morph,
+ __isl_take isl_vec *vec)
+{
+ if (!morph)
+ goto error;
+
+ vec = isl_mat_vec_product(isl_mat_copy(morph->map), vec);
+
+ isl_morph_free(morph);
+ return vec;
+error:
+ isl_morph_free(morph);
+ isl_vec_free(vec);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_morph.h b/polly/lib/External/isl/isl_morph.h
new file mode 100644
index 00000000000..4f6b8d491be
--- /dev/null
+++ b/polly/lib/External/isl/isl_morph.h
@@ -0,0 +1,86 @@
+/*
+ * 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
+ */
+
+#ifndef ISL_MORHP_H
+#define ISL_MORHP_H
+
+#include <stdio.h>
+#include <isl/space.h>
+#include <isl/mat.h>
+#include <isl/set.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* An isl_morph is a "morphism" on (basic) sets.
+ * "map" is an affine mapping from "dom" to "ran"
+ * and "inv" is the inverse mapping.
+ */
+struct isl_morph {
+ int ref;
+
+ isl_basic_set *dom;
+ isl_basic_set *ran;
+
+ isl_mat *map;
+ isl_mat *inv;
+};
+typedef struct isl_morph isl_morph;
+
+isl_ctx *isl_morph_get_ctx(__isl_keep isl_morph *morph);
+
+__isl_give isl_morph *isl_morph_alloc(
+ __isl_take isl_basic_set *dom, __isl_take isl_basic_set *ran,
+ __isl_take isl_mat *map, __isl_take isl_mat *inv);
+__isl_give isl_morph *isl_morph_copy(__isl_keep isl_morph *morph);
+__isl_give isl_morph *isl_morph_identity(__isl_keep isl_basic_set *bset);
+void isl_morph_free(__isl_take isl_morph *morph);
+
+__isl_give isl_space *isl_morph_get_dom_space(__isl_keep isl_morph *morph);
+__isl_give isl_space *isl_morph_get_ran_space(__isl_keep isl_morph *morph);
+__isl_give isl_multi_aff *isl_morph_get_var_multi_aff(
+ __isl_keep isl_morph *morph);
+unsigned isl_morph_dom_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
+unsigned isl_morph_ran_dim(__isl_keep isl_morph *morph, enum isl_dim_type type);
+
+__isl_give isl_morph *isl_morph_remove_dom_dims(__isl_take isl_morph *morph,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_morph *isl_morph_remove_ran_dims(__isl_take isl_morph *morph,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_morph *isl_morph_dom_params(__isl_take isl_morph *morph);
+__isl_give isl_morph *isl_morph_ran_params(__isl_take isl_morph *morph);
+
+__isl_give isl_morph *isl_morph_compose(__isl_take isl_morph *morph1,
+ __isl_take isl_morph *morph2);
+__isl_give isl_morph *isl_morph_inverse(__isl_take isl_morph *morph);
+
+void isl_morph_print_internal(__isl_take isl_morph *morph, FILE *out);
+void isl_morph_dump(__isl_take isl_morph *morph);
+
+__isl_give isl_morph *isl_basic_set_variable_compression(
+ __isl_keep isl_basic_set *bset, enum isl_dim_type type);
+__isl_give isl_morph *isl_basic_set_parameter_compression(
+ __isl_keep isl_basic_set *bset);
+__isl_give isl_morph *isl_basic_set_full_compression(
+ __isl_keep isl_basic_set *bset);
+
+__isl_give isl_basic_set *isl_morph_basic_set(__isl_take isl_morph *morph,
+ __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_morph_set(__isl_take isl_morph *morph,
+ __isl_take isl_set *set);
+__isl_give isl_vec *isl_morph_vec(__isl_take isl_morph *morph,
+ __isl_take isl_vec *vec);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_multi_templ.c b/polly/lib/External/isl/isl_multi_templ.c
new file mode 100644
index 00000000000..69dc93c3007
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_templ.c
@@ -0,0 +1,1498 @@
+/*
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-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_space_private.h>
+#include <isl/set.h>
+#include <isl_reordering.h>
+
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xMULTI(BASE) isl_multi_ ## BASE
+#define MULTI(BASE) xMULTI(BASE)
+#define MULTI_NAME(BASE) "isl_multi_" #BASE
+#define xLIST(EL) EL ## _list
+#define LIST(EL) xLIST(EL)
+
+isl_ctx *FN(MULTI(BASE),get_ctx)(__isl_keep MULTI(BASE) *multi)
+{
+ return multi ? isl_space_get_ctx(multi->space) : NULL;
+}
+
+__isl_give isl_space *FN(MULTI(BASE),get_space)(__isl_keep MULTI(BASE) *multi)
+{
+ return multi ? isl_space_copy(multi->space) : NULL;
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "multi".
+ * Return -1 if no such dimension can be found.
+ */
+int FN(MULTI(BASE),find_dim_by_name)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type, const char *name)
+{
+ if (!multi)
+ return -1;
+ return isl_space_find_dim_by_name(multi->space, type, name);
+}
+
+__isl_give isl_space *FN(MULTI(BASE),get_domain_space)(
+ __isl_keep MULTI(BASE) *multi)
+{
+ return multi ? isl_space_domain(isl_space_copy(multi->space)) : NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),alloc)(__isl_take isl_space *space)
+{
+ isl_ctx *ctx;
+ int n;
+ MULTI(BASE) *multi;
+
+ if (!space)
+ return NULL;
+
+ ctx = isl_space_get_ctx(space);
+ n = isl_space_dim(space, isl_dim_out);
+ multi = isl_calloc(ctx, MULTI(BASE),
+ sizeof(MULTI(BASE)) + (n - 1) * sizeof(struct EL *));
+ if (!multi)
+ goto error;
+
+ multi->space = space;
+ multi->n = n;
+ multi->ref = 1;
+ return multi;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),dup)(__isl_keep MULTI(BASE) *multi)
+{
+ int i;
+ MULTI(BASE) *dup;
+
+ if (!multi)
+ return NULL;
+
+ dup = FN(MULTI(BASE),alloc)(isl_space_copy(multi->space));
+ if (!dup)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i)
+ dup = FN(FN(MULTI(BASE),set),BASE)(dup, i,
+ FN(EL,copy)(multi->p[i]));
+
+ return dup;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),cow)(__isl_take MULTI(BASE) *multi)
+{
+ if (!multi)
+ return NULL;
+
+ if (multi->ref == 1)
+ return multi;
+
+ multi->ref--;
+ return FN(MULTI(BASE),dup)(multi);
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),copy)(__isl_keep MULTI(BASE) *multi)
+{
+ if (!multi)
+ return NULL;
+
+ multi->ref++;
+ return multi;
+}
+
+__isl_null MULTI(BASE) *FN(MULTI(BASE),free)(__isl_take MULTI(BASE) *multi)
+{
+ int i;
+
+ if (!multi)
+ return NULL;
+
+ if (--multi->ref > 0)
+ return NULL;
+
+ isl_space_free(multi->space);
+ for (i = 0; i < multi->n; ++i)
+ FN(EL,free)(multi->p[i]);
+ free(multi);
+
+ return NULL;
+}
+
+/* Check whether "multi" has non-zero coefficients for any dimension
+ * in the given range or if any of these dimensions appear
+ * with non-zero coefficients in any of the integer divisions involved.
+ */
+int FN(MULTI(BASE),involves_dims)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!multi)
+ return -1;
+ if (multi->n == 0 || n == 0)
+ return 0;
+
+ for (i = 0; i < multi->n; ++i) {
+ int involves;
+
+ involves = FN(EL,involves_dims)(multi->p[i], type, first, n);
+ if (involves < 0 || involves)
+ return involves;
+ }
+
+ return 0;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),insert_dims)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!multi)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "cannot insert output/set dimensions",
+ return FN(MULTI(BASE),free)(multi));
+ if (n == 0 && !isl_space_is_named_or_nested(multi->space, type))
+ return multi;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ multi->space = isl_space_insert_dims(multi->space, type, first, n);
+ if (!multi->space)
+ return FN(MULTI(BASE),free)(multi);
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,insert_dims)(multi->p[i], type, first, n);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),free)(multi);
+ }
+
+ return multi;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),add_dims)(__isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned n)
+{
+ unsigned pos;
+
+ pos = FN(MULTI(BASE),dim)(multi, type);
+
+ return FN(MULTI(BASE),insert_dims)(multi, type, pos, n);
+}
+
+unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type)
+{
+ return multi ? isl_space_dim(multi->space, type) : 0;
+}
+
+/* Return the position of the first dimension of "type" with id "id".
+ * Return -1 if there is no such dimension.
+ */
+int FN(MULTI(BASE),find_dim_by_id)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type, __isl_keep isl_id *id)
+{
+ if (!multi)
+ return -1;
+ return isl_space_find_dim_by_id(multi->space, type, id);
+}
+
+/* Return the id of the given dimension.
+ */
+__isl_give isl_id *FN(MULTI(BASE),get_dim_id)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos)
+{
+ return multi ? isl_space_get_dim_id(multi->space, type, pos) : NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_name)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ multi->space = isl_space_set_dim_name(multi->space, type, pos, s);
+ if (!multi->space)
+ return FN(MULTI(BASE),free)(multi);
+
+ if (type == isl_dim_out)
+ return multi;
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,set_dim_name)(multi->p[i], type, pos, s);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),free)(multi);
+ }
+
+ return multi;
+}
+
+const char *FN(MULTI(BASE),get_tuple_name)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type)
+{
+ return multi ? isl_space_get_tuple_name(multi->space, type) : NULL;
+}
+
+/* Does the specified tuple have an id?
+ */
+int FN(MULTI(BASE),has_tuple_id)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type)
+{
+ return multi ? isl_space_has_tuple_id(multi->space, type) : -1;
+}
+
+/* Return the id of the specified tuple.
+ */
+__isl_give isl_id *FN(MULTI(BASE),get_tuple_id)(__isl_keep MULTI(BASE) *multi,
+ enum isl_dim_type type)
+{
+ return multi ? isl_space_get_tuple_id(multi->space, type) : NULL;
+}
+
+__isl_give EL *FN(FN(MULTI(BASE),get),BASE)(__isl_keep MULTI(BASE) *multi,
+ int pos)
+{
+ isl_ctx *ctx;
+
+ if (!multi)
+ return NULL;
+ ctx = FN(MULTI(BASE),get_ctx)(multi);
+ if (pos < 0 || pos >= multi->n)
+ isl_die(ctx, isl_error_invalid,
+ "index out of bounds", return NULL);
+ return FN(EL,copy)(multi->p[pos]);
+}
+
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),set),BASE)(
+ __isl_take MULTI(BASE) *multi, int pos, __isl_take EL *el)
+{
+ isl_space *multi_space = NULL;
+ isl_space *el_space = NULL;
+ int match;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !el)
+ goto error;
+
+ multi_space = FN(MULTI(BASE),get_space)(multi);
+ match = FN(EL,matching_params)(el, multi_space);
+ if (match < 0)
+ goto error;
+ if (!match) {
+ multi = FN(MULTI(BASE),align_params)(multi,
+ FN(EL,get_space)(el));
+ isl_space_free(multi_space);
+ multi_space = FN(MULTI(BASE),get_space)(multi);
+ el = FN(EL,align_params)(el, isl_space_copy(multi_space));
+ }
+ if (FN(EL,check_match_domain_space)(el, multi_space) < 0)
+ goto error;
+
+ if (pos < 0 || pos >= multi->n)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ FN(EL,free)(multi->p[pos]);
+ multi->p[pos] = el;
+
+ isl_space_free(multi_space);
+ isl_space_free(el_space);
+
+ return multi;
+error:
+ FN(MULTI(BASE),free)(multi);
+ FN(EL,free)(el);
+ isl_space_free(multi_space);
+ isl_space_free(el_space);
+ return NULL;
+}
+
+/* Reset the space of "multi". This function is called from isl_pw_templ.c
+ * and doesn't know if the space of an element object is represented
+ * directly or through its domain. It therefore passes along both,
+ * which we pass along to the element function since we don't how
+ * that is represented either.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space_and_domain)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space,
+ __isl_take isl_space *domain)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !space || !domain)
+ goto error;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,reset_domain_space)(multi->p[i],
+ isl_space_copy(domain));
+ if (!multi->p[i])
+ goto error;
+ }
+ isl_space_free(domain);
+ isl_space_free(multi->space);
+ multi->space = space;
+
+ return multi;
+error:
+ isl_space_free(domain);
+ isl_space_free(space);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_domain_space)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *domain)
+{
+ isl_space *space;
+
+ space = isl_space_extend_domain_with_range(isl_space_copy(domain),
+ isl_space_copy(multi->space));
+ return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_space)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *space)
+{
+ isl_space *domain;
+
+ domain = isl_space_domain(isl_space_copy(space));
+ return FN(MULTI(BASE),reset_space_and_domain)(multi, space, domain);
+}
+
+/* Set the id of the given dimension of "multi" to "id".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_dim_id)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ isl_space *space;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !id)
+ goto error;
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_set_dim_id(space, type, pos, id);
+
+ return FN(MULTI(BASE),reset_space)(multi, space);
+error:
+ isl_id_free(id);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_name)(
+ __isl_keep MULTI(BASE) *multi, enum isl_dim_type type,
+ const char *s)
+{
+ isl_space *space;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_set_tuple_name(space, type, s);
+
+ return FN(MULTI(BASE),reset_space)(multi, space);
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),set_tuple_id)(
+ __isl_take MULTI(BASE) *multi, enum isl_dim_type type,
+ __isl_take isl_id *id)
+{
+ isl_space *space;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ goto error;
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_set_tuple_id(space, type, id);
+
+ return FN(MULTI(BASE),reset_space)(multi, space);
+error:
+ isl_id_free(id);
+ return NULL;
+}
+
+/* Drop the id on the specified tuple.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_tuple_id)(
+ __isl_take MULTI(BASE) *multi, enum isl_dim_type type)
+{
+ isl_space *space;
+
+ if (!multi)
+ return NULL;
+ if (!FN(MULTI(BASE),has_tuple_id)(multi, type))
+ return multi;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_reset_tuple_id(space, type);
+
+ return FN(MULTI(BASE),reset_space)(multi, space);
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of "multi".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),reset_user)(
+ __isl_take MULTI(BASE) *multi)
+{
+ isl_space *space;
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_reset_user(space);
+
+ return FN(MULTI(BASE),reset_space)(multi, space);
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),realign_domain)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_reordering *exp)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !exp)
+ goto error;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,realign_domain)(multi->p[i],
+ isl_reordering_copy(exp));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ multi = FN(MULTI(BASE),reset_domain_space)(multi,
+ isl_space_copy(exp->dim));
+
+ isl_reordering_free(exp);
+ return multi;
+error:
+ isl_reordering_free(exp);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+/* Align the parameters of "multi" to those of "model".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),align_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_space *model)
+{
+ isl_ctx *ctx;
+ isl_reordering *exp;
+
+ if (!multi || !model)
+ goto error;
+
+ if (isl_space_match(multi->space, isl_dim_param,
+ model, isl_dim_param)) {
+ isl_space_free(model);
+ return multi;
+ }
+
+ ctx = isl_space_get_ctx(model);
+ if (!isl_space_has_named_params(model))
+ isl_die(ctx, isl_error_invalid,
+ "model has unnamed parameters", goto error);
+ if (!isl_space_has_named_params(multi->space))
+ isl_die(ctx, isl_error_invalid,
+ "input has unnamed parameters", goto error);
+
+ model = isl_space_params(model);
+ exp = isl_parameter_alignment_reordering(multi->space, model);
+ exp = isl_reordering_extend_space(exp,
+ FN(MULTI(BASE),get_domain_space)(multi));
+ multi = FN(MULTI(BASE),realign_domain)(multi, exp);
+
+ isl_space_free(model);
+ return multi;
+error:
+ isl_space_free(model);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+#if !defined(NO_GIST) || !defined(NO_INTERSECT_DOMAIN)
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_set_and)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *set,
+ __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi,
+ __isl_take isl_set *set))
+{
+ isl_ctx *ctx;
+
+ if (!multi || !set)
+ goto error;
+ if (isl_space_match(multi->space, isl_dim_param,
+ set->dim, isl_dim_param))
+ return fn(multi, set);
+ ctx = FN(MULTI(BASE),get_ctx)(multi);
+ if (!isl_space_has_named_params(multi->space) ||
+ !isl_space_has_named_params(set->dim))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ multi = FN(MULTI(BASE),align_params)(multi, isl_set_get_space(set));
+ set = isl_set_align_params(set, FN(MULTI(BASE),get_space)(multi));
+ return fn(multi, set);
+error:
+ FN(MULTI(BASE),free)(multi);
+ isl_set_free(set);
+ return NULL;
+}
+#endif
+
+#ifndef NO_GIST
+__isl_give MULTI(BASE) *FN(MULTI(BASE),gist_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *context)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi || !context)
+ goto error;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,gist)(multi->p[i], isl_set_copy(context));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_set_free(context);
+ return multi;
+error:
+ isl_set_free(context);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),gist)(__isl_take MULTI(BASE) *multi,
+ __isl_take isl_set *context)
+{
+ return FN(MULTI(BASE),align_params_multi_set_and)(multi, context,
+ &FN(MULTI(BASE),gist_aligned));
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),gist_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *context)
+{
+ isl_space *space = FN(MULTI(BASE),get_domain_space)(multi);
+ isl_set *dom_context = isl_set_universe(space);
+ dom_context = isl_set_intersect_params(dom_context, context);
+ return FN(MULTI(BASE),gist)(multi, dom_context);
+}
+#endif
+
+#ifndef NO_INTERSECT_DOMAIN
+/* Transform the domain of "multi" by combining it with "domain"
+ * using "fn".
+ *
+ * The parameters of "multi" and "domain" are assumed to have been aligned.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain,
+ __isl_give EL *(*fn)(EL *el, __isl_take isl_set *set2))
+{
+ int i;
+
+ if (!multi || !domain)
+ goto error;
+
+ if (multi->n == 0) {
+ isl_set_free(domain);
+ return multi;
+ }
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ goto error;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = fn(multi->p[i], isl_set_copy(domain));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_set_free(domain);
+ return multi;
+error:
+ isl_set_free(domain);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+/* Intersect the domain of "multi" with "domain".
+ *
+ * The parameters of "multi" and "domain" are assumed to have been aligned.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(MULTI(BASE),intersect_aligned)(multi, domain,
+ &FN(EL,intersect_domain));
+}
+
+/* Intersect the domain of "multi" with "domain".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(MULTI(BASE),align_params_multi_set_and)(multi, domain,
+ &FN(MULTI(BASE),intersect_domain_aligned));
+}
+
+/* Intersect the parameter domain of "multi" with "domain".
+ *
+ * The parameters of "multi" and "domain" are assumed to have been aligned.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params_aligned)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(MULTI(BASE),intersect_aligned)(multi, domain,
+ &FN(EL,intersect_params));
+}
+
+/* Intersect the parameter domain of "multi" with "domain".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(MULTI(BASE),align_params_multi_set_and)(multi, domain,
+ &FN(MULTI(BASE),intersect_params_aligned));
+}
+#endif
+
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
+ __isl_take isl_space *space, __isl_take LIST(EL) *list)
+{
+ int i;
+ int n;
+ isl_ctx *ctx;
+ MULTI(BASE) *multi;
+
+ if (!space || !list)
+ goto error;
+
+ ctx = isl_space_get_ctx(space);
+ n = FN(FN(LIST(EL),n),BASE)(list);
+ if (n != isl_space_dim(space, isl_dim_out))
+ isl_die(ctx, isl_error_invalid,
+ "invalid number of elements in list", goto error);
+
+ multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+ for (i = 0; i < n; ++i) {
+ multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
+ FN(FN(LIST(EL),get),BASE)(list, i));
+ }
+
+ isl_space_free(space);
+ FN(LIST(EL),free)(list);
+ return multi;
+error:
+ isl_space_free(space);
+ FN(LIST(EL),free)(list);
+ return NULL;
+}
+
+#ifndef NO_IDENTITY
+/* Create a multi expression in the given space that maps each
+ * input dimension to the corresponding output dimension.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),identity)(__isl_take isl_space *space)
+{
+ int i, n;
+ isl_local_space *ls;
+ MULTI(BASE) *multi;
+
+ if (!space)
+ return NULL;
+
+ if (isl_space_is_set(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "expecting map space", goto error);
+
+ n = isl_space_dim(space, isl_dim_out);
+ if (n != isl_space_dim(space, isl_dim_in))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "number of input and output dimensions needs to be "
+ "the same", goto error);
+
+ multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+
+ if (!n) {
+ isl_space_free(space);
+ return multi;
+ }
+
+ space = isl_space_domain(space);
+ ls = isl_local_space_from_space(space);
+
+ for (i = 0; i < n; ++i) {
+ EL *el;
+ el = FN(EL,var_on_domain)(isl_local_space_copy(ls),
+ isl_dim_set, i);
+ multi = FN(FN(MULTI(BASE),set),BASE)(multi, i, el);
+ }
+
+ isl_local_space_free(ls);
+
+ return multi;
+error:
+ isl_space_free(space);
+ return NULL;
+}
+#endif
+
+/* Construct a multi expression in the given space with value zero in
+ * each of the output dimensions.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),zero)(__isl_take isl_space *space)
+{
+ int n;
+ MULTI(BASE) *multi;
+
+ if (!space)
+ return NULL;
+
+ n = isl_space_dim(space , isl_dim_out);
+ multi = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+
+ if (!n)
+ isl_space_free(space);
+ else {
+ int i;
+ isl_local_space *ls;
+ EL *el;
+
+ space = isl_space_domain(space);
+ ls = isl_local_space_from_space(space);
+ el = FN(EL,zero_on_domain)(ls);
+
+ for (i = 0; i < n; ++i)
+ multi = FN(FN(MULTI(BASE),set),BASE)(multi, i,
+ FN(EL,copy)(el));
+
+ FN(EL,free)(el);
+ }
+
+ return multi;
+}
+
+#ifndef NO_FROM_BASE
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
+{
+ MULTI(BASE) *multi;
+
+ multi = FN(MULTI(BASE),alloc)(FN(EL,get_space)(el));
+ multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
+
+ return multi;
+}
+#endif
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),drop_dims)(
+ __isl_take MULTI(BASE) *multi,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ unsigned dim;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ dim = FN(MULTI(BASE),dim)(multi, type);
+ if (first + n > dim || first + n < first)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "index out of bounds",
+ return FN(MULTI(BASE),cow)(multi));
+
+ multi->space = isl_space_drop_dims(multi->space, type, first, n);
+ if (!multi->space)
+ return FN(MULTI(BASE),cow)(multi);
+
+ if (type == isl_dim_out) {
+ for (i = 0; i < n; ++i)
+ FN(EL,free)(multi->p[first + i]);
+ for (i = first; i + n < multi->n; ++i)
+ multi->p[i] = multi->p[i + n];
+ multi->n -= n;
+
+ return multi;
+ }
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,drop_dims)(multi->p[i], type, first, n);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),cow)(multi);
+ }
+
+ return multi;
+}
+
+/* Align the parameters of "multi1" and "multi2" (if needed) and call "fn".
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_multi_and)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
+ __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi1,
+ __isl_take MULTI(BASE) *multi2))
+{
+ isl_ctx *ctx;
+
+ if (!multi1 || !multi2)
+ goto error;
+ if (isl_space_match(multi1->space, isl_dim_param,
+ multi2->space, isl_dim_param))
+ return fn(multi1, multi2);
+ ctx = FN(MULTI(BASE),get_ctx)(multi1);
+ if (!isl_space_has_named_params(multi1->space) ||
+ !isl_space_has_named_params(multi2->space))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ multi1 = FN(MULTI(BASE),align_params)(multi1,
+ FN(MULTI(BASE),get_space)(multi2));
+ multi2 = FN(MULTI(BASE),align_params)(multi2,
+ FN(MULTI(BASE),get_space)(multi1));
+ return fn(multi1, multi2);
+error:
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return NULL;
+}
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) (A * C) -> [B -> D].
+ *
+ * The parameters are assumed to have been aligned.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),range_product_aligned)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ int i, n1, n2;
+ EL *el;
+ isl_space *space;
+ MULTI(BASE) *res;
+
+ if (!multi1 || !multi2)
+ goto error;
+
+ space = isl_space_range_product(FN(MULTI(BASE),get_space)(multi1),
+ FN(MULTI(BASE),get_space)(multi2));
+ res = FN(MULTI(BASE),alloc)(space);
+
+ n1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
+ n2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
+
+ for (i = 0; i < n1; ++i) {
+ el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
+ res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
+ }
+
+ for (i = 0; i < n2; ++i) {
+ el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
+ res = FN(FN(MULTI(BASE),set),BASE)(res, n1 + i, el);
+ }
+
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return res;
+error:
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return NULL;
+}
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) (A * C) -> [B -> D].
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),range_product)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
+ &FN(MULTI(BASE),range_product_aligned));
+}
+
+/* Is the range of "multi" a wrapped relation?
+ */
+int FN(MULTI(BASE),range_is_wrapping)(__isl_keep MULTI(BASE) *multi)
+{
+ if (!multi)
+ return -1;
+ return isl_space_range_is_wrapping(multi->space);
+}
+
+/* Given a function A -> [B -> C], extract the function A -> B.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_domain)(
+ __isl_take MULTI(BASE) *multi)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!multi)
+ return NULL;
+ if (!isl_space_range_is_wrapping(multi->space))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "range is 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_range_factor_domain(space);
+ keep = isl_space_dim(space, isl_dim_out);
+ multi = FN(MULTI(BASE),drop_dims)(multi,
+ isl_dim_out, keep, total - keep);
+ multi = FN(MULTI(BASE),reset_space)(multi, space);
+
+ return multi;
+}
+
+/* Given a function A -> [B -> C], extract the function A -> C.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),range_factor_range)(
+ __isl_take MULTI(BASE) *multi)
+{
+ isl_space *space;
+ int total, keep;
+
+ if (!multi)
+ return NULL;
+ if (!isl_space_range_is_wrapping(multi->space))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "range is 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_range_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;
+}
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) [A -> C] -> [B -> D].
+ *
+ * The parameters are assumed to have been aligned.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),product_aligned)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ int i;
+ EL *el;
+ isl_space *space;
+ MULTI(BASE) *res;
+ int in1, in2, out1, out2;
+
+ in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
+ in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
+ out1 = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
+ out2 = FN(MULTI(BASE),dim)(multi2, isl_dim_out);
+ space = isl_space_product(FN(MULTI(BASE),get_space)(multi1),
+ FN(MULTI(BASE),get_space)(multi2));
+ res = FN(MULTI(BASE),alloc)(isl_space_copy(space));
+ space = isl_space_domain(space);
+
+ for (i = 0; i < out1; ++i) {
+ el = FN(FN(MULTI(BASE),get),BASE)(multi1, i);
+ el = FN(EL,insert_dims)(el, isl_dim_in, in1, in2);
+ el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
+ res = FN(FN(MULTI(BASE),set),BASE)(res, i, el);
+ }
+
+ for (i = 0; i < out2; ++i) {
+ el = FN(FN(MULTI(BASE),get),BASE)(multi2, i);
+ el = FN(EL,insert_dims)(el, isl_dim_in, 0, in1);
+ el = FN(EL,reset_domain_space)(el, isl_space_copy(space));
+ res = FN(FN(MULTI(BASE),set),BASE)(res, out1 + i, el);
+ }
+
+ isl_space_free(space);
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return res;
+}
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) [A -> C] -> [B -> D].
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),product)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
+ &FN(MULTI(BASE),product_aligned));
+}
+
+__isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
+ __isl_take MULTI(BASE) *multi)
+{
+ if (!multi)
+ return NULL;
+
+ if (!multi->space->nested[1])
+ return multi;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ multi->space = isl_space_flatten_range(multi->space);
+ if (!multi->space)
+ return FN(MULTI(BASE),free)(multi);
+
+ return multi;
+}
+
+/* Given two MULTI(BASE)s A -> B and C -> D,
+ * construct a MULTI(BASE) (A * C) -> (B, D).
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),flat_range_product)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ MULTI(BASE) *multi;
+
+ multi = FN(MULTI(BASE),range_product)(multi1, multi2);
+ multi = FN(MULTI(BASE),flatten_range)(multi);
+ return multi;
+}
+
+/* Given two multi expressions, "multi1"
+ *
+ * [A] -> [B1 B2]
+ *
+ * where B2 starts at position "pos", and "multi2"
+ *
+ * [A] -> [D]
+ *
+ * return the multi expression
+ *
+ * [A] -> [B1 D B2]
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),range_splice)(
+ __isl_take MULTI(BASE) *multi1, unsigned pos,
+ __isl_take MULTI(BASE) *multi2)
+{
+ MULTI(BASE) *res;
+ unsigned dim;
+
+ if (!multi1 || !multi2)
+ goto error;
+
+ dim = FN(MULTI(BASE),dim)(multi1, isl_dim_out);
+ if (pos > dim)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ res = FN(MULTI(BASE),copy)(multi1);
+ res = FN(MULTI(BASE),drop_dims)(res, isl_dim_out, pos, dim - pos);
+ multi1 = FN(MULTI(BASE),drop_dims)(multi1, isl_dim_out, 0, pos);
+
+ res = FN(MULTI(BASE),flat_range_product)(res, multi2);
+ res = FN(MULTI(BASE),flat_range_product)(res, multi1);
+
+ return res;
+error:
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return NULL;
+}
+
+/* Given two multi expressions, "multi1"
+ *
+ * [A1 A2] -> [B1 B2]
+ *
+ * where A2 starts at position "in_pos" and B2 starts at position "out_pos",
+ * and "multi2"
+ *
+ * [C] -> [D]
+ *
+ * return the multi expression
+ *
+ * [A1 C A2] -> [B1 D B2]
+ *
+ * We first insert input dimensions to obtain
+ *
+ * [A1 C A2] -> [B1 B2]
+ *
+ * and
+ *
+ * [A1 C A2] -> [D]
+ *
+ * and then apply range_splice.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),splice)(
+ __isl_take MULTI(BASE) *multi1, unsigned in_pos, unsigned out_pos,
+ __isl_take MULTI(BASE) *multi2)
+{
+ unsigned n_in1;
+ unsigned n_in2;
+
+ if (!multi1 || !multi2)
+ goto error;
+
+ n_in1 = FN(MULTI(BASE),dim)(multi1, isl_dim_in);
+ if (in_pos > n_in1)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi1), isl_error_invalid,
+ "index out of bounds", goto error);
+
+ n_in2 = FN(MULTI(BASE),dim)(multi2, isl_dim_in);
+
+ multi1 = FN(MULTI(BASE),insert_dims)(multi1, isl_dim_in, in_pos, n_in2);
+ multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, n_in2,
+ n_in1 - in_pos);
+ multi2 = FN(MULTI(BASE),insert_dims)(multi2, isl_dim_in, 0, in_pos);
+
+ return FN(MULTI(BASE),range_splice)(multi1, out_pos, multi2);
+error:
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return NULL;
+}
+
+/* This function is currently only used from isl_aff.c
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
+ __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
+ __attribute__ ((unused));
+
+/* Pairwise perform "fn" to the elements of "multi1" and "multi2" and
+ * return the result.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),bin_op)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2,
+ __isl_give EL *(*fn)(__isl_take EL *, __isl_take EL *))
+{
+ int i;
+ isl_ctx *ctx;
+
+ multi1 = FN(MULTI(BASE),cow)(multi1);
+ if (!multi1 || !multi2)
+ goto error;
+
+ ctx = FN(MULTI(BASE),get_ctx)(multi1);
+ if (!isl_space_is_equal(multi1->space, multi2->space))
+ isl_die(ctx, isl_error_invalid,
+ "spaces don't match", goto error);
+
+ for (i = 0; i < multi1->n; ++i) {
+ multi1->p[i] = fn(multi1->p[i], FN(EL,copy)(multi2->p[i]));
+ if (!multi1->p[i])
+ goto error;
+ }
+
+ FN(MULTI(BASE),free)(multi2);
+ return multi1;
+error:
+ FN(MULTI(BASE),free)(multi1);
+ FN(MULTI(BASE),free)(multi2);
+ return NULL;
+}
+
+/* Multiply the elements of "multi" by "v" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
+ __isl_take isl_val *v)
+{
+ int i;
+
+ if (!multi || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return multi;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational factor", goto error);
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,scale_val)(multi->p[i], isl_val_copy(v));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_val_free(v);
+ return multi;
+error:
+ isl_val_free(v);
+ return FN(MULTI(BASE),free)(multi);
+}
+
+/* Divide the elements of "multi" by "v" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_val)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_val *v)
+{
+ int i;
+
+ if (!multi || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return multi;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (isl_val_is_zero(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "cannot scale down by zero", goto error);
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,scale_down_val)(multi->p[i],
+ isl_val_copy(v));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_val_free(v);
+ return multi;
+error:
+ isl_val_free(v);
+ return FN(MULTI(BASE),free)(multi);
+}
+
+/* Multiply the elements of "multi" by the corresponding element of "mv"
+ * and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_multi_val)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+ int i;
+
+ if (!multi || !mv)
+ goto error;
+
+ if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+ mv->space, isl_dim_set))
+ isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ isl_val *v;
+
+ v = isl_multi_val_get_val(mv, i);
+ multi->p[i] = FN(EL,scale_val)(multi->p[i], v);
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_multi_val_free(mv);
+ return multi;
+error:
+ isl_multi_val_free(mv);
+ return FN(MULTI(BASE),free)(multi);
+}
+
+/* Divide the elements of "multi" by the corresponding element of "mv"
+ * and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_down_multi_val)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+ int i;
+
+ if (!multi || !mv)
+ goto error;
+
+ if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+ mv->space, isl_dim_set))
+ isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ isl_val *v;
+
+ v = isl_multi_val_get_val(mv, i);
+ multi->p[i] = FN(EL,scale_down_val)(multi->p[i], v);
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_multi_val_free(mv);
+ return multi;
+error:
+ isl_multi_val_free(mv);
+ return FN(MULTI(BASE),free)(multi);
+}
+
+#ifndef NO_MOVE_DIMS
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
+ * to dimensions of "dst_type" at "dst_pos".
+ *
+ * We only support moving input dimensions to parameters and vice versa.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),move_dims)(__isl_take MULTI(BASE) *multi,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ int i;
+
+ if (!multi)
+ return NULL;
+
+ if (n == 0 &&
+ !isl_space_is_named_or_nested(multi->space, src_type) &&
+ !isl_space_is_named_or_nested(multi->space, dst_type))
+ return multi;
+
+ if (dst_type == isl_dim_out || src_type == isl_dim_out)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "cannot move output/set dimension",
+ return FN(MULTI(BASE),free)(multi));
+ if (dst_type == isl_dim_div || src_type == isl_dim_div)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "cannot move divs",
+ return FN(MULTI(BASE),free)(multi));
+ if (src_pos + n > isl_space_dim(multi->space, src_type))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "range out of bounds",
+ return FN(MULTI(BASE),free)(multi));
+ if (dst_type == src_type)
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_unsupported,
+ "moving dims within the same type not supported",
+ return FN(MULTI(BASE),free)(multi));
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ multi->space = isl_space_move_dims(multi->space, dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!multi->space)
+ return FN(MULTI(BASE),free)(multi);
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,move_dims)(multi->p[i], dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),free)(multi);
+ }
+
+ return multi;
+}
+#endif
+
+/* Convert a multiple expression defined over a parameter domain
+ * into one that is defined over a zero-dimensional set.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),from_range)(
+ __isl_take MULTI(BASE) *multi)
+{
+ isl_space *space;
+
+ if (!multi)
+ return NULL;
+ if (!isl_space_is_set(multi->space))
+ isl_die(FN(MULTI(BASE),get_ctx)(multi), isl_error_invalid,
+ "not living in a set space",
+ return FN(MULTI(BASE),free)(multi));
+
+ space = FN(MULTI(BASE),get_space)(multi);
+ space = isl_space_from_range(space);
+ multi = FN(MULTI(BASE),reset_space)(multi, space);
+
+ return multi;
+}
+
+/* Are "multi1" and "multi2" obviously equal?
+ */
+int FN(MULTI(BASE),plain_is_equal)(__isl_keep MULTI(BASE) *multi1,
+ __isl_keep MULTI(BASE) *multi2)
+{
+ int i;
+ int equal;
+
+ if (!multi1 || !multi2)
+ return -1;
+ if (multi1->n != multi2->n)
+ return 0;
+ equal = isl_space_is_equal(multi1->space, multi2->space);
+ if (equal < 0 || !equal)
+ return equal;
+
+ for (i = 0; i < multi1->n; ++i) {
+ equal = FN(EL,plain_is_equal)(multi1->p[i], multi2->p[i]);
+ if (equal < 0 || !equal)
+ return equal;
+ }
+
+ return 1;
+}
+
+#ifndef NO_DOMAIN
+/* Return the shared domain of the elements of "multi".
+ */
+__isl_give isl_set *FN(MULTI(BASE),domain)(__isl_take MULTI(BASE) *multi)
+{
+ int i;
+ isl_set *dom;
+
+ if (!multi)
+ return NULL;
+
+ dom = isl_set_universe(FN(MULTI(BASE),get_domain_space)(multi));
+ for (i = 0; i < multi->n; ++i) {
+ isl_set *dom_i;
+
+ dom_i = FN(EL,domain)(FN(FN(MULTI(BASE),get),BASE)(multi, i));
+ dom = isl_set_intersect(dom, dom_i);
+ }
+
+ FN(MULTI(BASE),free)(multi);
+ return dom;
+}
+#endif
diff --git a/polly/lib/External/isl/isl_multi_templ.h b/polly/lib/External/isl/isl_multi_templ.h
new file mode 100644
index 00000000000..342d9a22315
--- /dev/null
+++ b/polly/lib/External/isl/isl_multi_templ.h
@@ -0,0 +1,18 @@
+#include <isl/space.h>
+
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,BASE)
+#define xMULTI(BASE) isl_multi_ ## BASE
+#define MULTI(BASE) xMULTI(BASE)
+
+struct MULTI(BASE) {
+ int ref;
+ isl_space *space;
+
+ int n;
+ EL *p[1];
+};
+
+__isl_give MULTI(BASE) *CAT(MULTI(BASE),_alloc)(__isl_take isl_space *space);
diff --git a/polly/lib/External/isl/isl_obj.c b/polly/lib/External/isl/isl_obj.c
new file mode 100644
index 00000000000..5bc26ce6cc7
--- /dev/null
+++ b/polly/lib/External/isl/isl_obj.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2014 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/aff.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/polynomial.h>
+#include <isl/obj.h>
+
+static void *isl_obj_val_copy(void *v)
+{
+ return isl_val_copy((isl_val *)v);
+}
+
+static void isl_obj_val_free(void *v)
+{
+ isl_val_free((isl_val *)v);
+}
+
+static __isl_give isl_printer *isl_obj_val_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_val(p, (isl_val *)v);
+}
+
+static void *isl_obj_val_add(void *v1, void *v2)
+{
+ return isl_val_add((isl_val *) v1, (isl_val *) v2);
+}
+
+struct isl_obj_vtable isl_obj_val_vtable = {
+ isl_obj_val_copy,
+ isl_obj_val_add,
+ isl_obj_val_print,
+ isl_obj_val_free
+};
+
+static void *isl_obj_map_copy(void *v)
+{
+ return isl_map_copy((struct isl_map *)v);
+}
+
+static void isl_obj_map_free(void *v)
+{
+ isl_map_free((struct isl_map *)v);
+}
+
+static __isl_give isl_printer *isl_obj_map_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_map(p, (struct isl_map *)v);
+}
+
+static void *isl_obj_map_add(void *v1, void *v2)
+{
+ return isl_map_union((struct isl_map *)v1, (struct isl_map *)v2);
+}
+
+struct isl_obj_vtable isl_obj_map_vtable = {
+ isl_obj_map_copy,
+ isl_obj_map_add,
+ isl_obj_map_print,
+ isl_obj_map_free
+};
+
+static void *isl_obj_union_map_copy(void *v)
+{
+ return isl_union_map_copy((isl_union_map *)v);
+}
+
+static void isl_obj_union_map_free(void *v)
+{
+ isl_union_map_free((isl_union_map *)v);
+}
+
+static __isl_give isl_printer *isl_obj_union_map_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_union_map(p, (isl_union_map *)v);
+}
+
+static void *isl_obj_union_map_add(void *v1, void *v2)
+{
+ return isl_union_map_union((isl_union_map *)v1, (isl_union_map *)v2);
+}
+
+struct isl_obj_vtable isl_obj_union_map_vtable = {
+ isl_obj_union_map_copy,
+ isl_obj_union_map_add,
+ isl_obj_union_map_print,
+ isl_obj_union_map_free
+};
+
+static void *isl_obj_set_copy(void *v)
+{
+ return isl_set_copy((struct isl_set *)v);
+}
+
+static void isl_obj_set_free(void *v)
+{
+ isl_set_free((struct isl_set *)v);
+}
+
+static __isl_give isl_printer *isl_obj_set_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_set(p, (struct isl_set *)v);
+}
+
+static void *isl_obj_set_add(void *v1, void *v2)
+{
+ return isl_set_union((struct isl_set *)v1, (struct isl_set *)v2);
+}
+
+struct isl_obj_vtable isl_obj_set_vtable = {
+ isl_obj_set_copy,
+ isl_obj_set_add,
+ isl_obj_set_print,
+ isl_obj_set_free
+};
+
+static void *isl_obj_union_set_copy(void *v)
+{
+ return isl_union_set_copy((isl_union_set *)v);
+}
+
+static void isl_obj_union_set_free(void *v)
+{
+ isl_union_set_free((isl_union_set *)v);
+}
+
+static __isl_give isl_printer *isl_obj_union_set_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_union_set(p, (isl_union_set *)v);
+}
+
+static void *isl_obj_union_set_add(void *v1, void *v2)
+{
+ return isl_union_set_union((isl_union_set *)v1, (isl_union_set *)v2);
+}
+
+struct isl_obj_vtable isl_obj_union_set_vtable = {
+ isl_obj_union_set_copy,
+ isl_obj_union_set_add,
+ isl_obj_union_set_print,
+ isl_obj_union_set_free
+};
+
+static void *isl_obj_pw_multi_aff_copy(void *v)
+{
+ return isl_pw_multi_aff_copy((isl_pw_multi_aff *) v);
+}
+
+static void isl_obj_pw_multi_aff_free(void *v)
+{
+ isl_pw_multi_aff_free((isl_pw_multi_aff *) v);
+}
+
+static __isl_give isl_printer *isl_obj_pw_multi_aff_print(
+ __isl_take isl_printer *p, void *v)
+{
+ return isl_printer_print_pw_multi_aff(p, (isl_pw_multi_aff *) v);
+}
+
+static void *isl_obj_pw_multi_aff_add(void *v1, void *v2)
+{
+ return isl_pw_multi_aff_add((isl_pw_multi_aff *) v1,
+ (isl_pw_multi_aff *) v2);
+}
+
+struct isl_obj_vtable isl_obj_pw_multi_aff_vtable = {
+ isl_obj_pw_multi_aff_copy,
+ isl_obj_pw_multi_aff_add,
+ isl_obj_pw_multi_aff_print,
+ isl_obj_pw_multi_aff_free
+};
+
+static void *isl_obj_none_copy(void *v)
+{
+ return v;
+}
+
+static void isl_obj_none_free(void *v)
+{
+}
+
+static __isl_give isl_printer *isl_obj_none_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return p;
+}
+
+static void *isl_obj_none_add(void *v1, void *v2)
+{
+ return NULL;
+}
+
+struct isl_obj_vtable isl_obj_none_vtable = {
+ isl_obj_none_copy,
+ isl_obj_none_add,
+ isl_obj_none_print,
+ isl_obj_none_free
+};
+
+static void *isl_obj_pw_qp_copy(void *v)
+{
+ return isl_pw_qpolynomial_copy((struct isl_pw_qpolynomial *)v);
+}
+
+static void isl_obj_pw_qp_free(void *v)
+{
+ isl_pw_qpolynomial_free((struct isl_pw_qpolynomial *)v);
+}
+
+static __isl_give isl_printer *isl_obj_pw_qp_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_pw_qpolynomial(p,
+ (struct isl_pw_qpolynomial *)v);
+}
+
+static void *isl_obj_pw_qp_add(void *v1, void *v2)
+{
+ return isl_pw_qpolynomial_add((struct isl_pw_qpolynomial *)v1,
+ (struct isl_pw_qpolynomial *)v2);
+}
+
+struct isl_obj_vtable isl_obj_pw_qpolynomial_vtable = {
+ isl_obj_pw_qp_copy,
+ isl_obj_pw_qp_add,
+ isl_obj_pw_qp_print,
+ isl_obj_pw_qp_free
+};
+
+static void *isl_obj_union_pw_qp_copy(void *v)
+{
+ return isl_union_pw_qpolynomial_copy((struct isl_union_pw_qpolynomial *)v);
+}
+
+static void isl_obj_union_pw_qp_free(void *v)
+{
+ isl_union_pw_qpolynomial_free((struct isl_union_pw_qpolynomial *)v);
+}
+
+static __isl_give isl_printer *isl_obj_union_pw_qp_print(
+ __isl_take isl_printer *p, void *v)
+{
+ return isl_printer_print_union_pw_qpolynomial(p,
+ (struct isl_union_pw_qpolynomial *)v);
+}
+
+static void *isl_obj_union_pw_qp_add(void *v1, void *v2)
+{
+ return isl_union_pw_qpolynomial_add(
+ (struct isl_union_pw_qpolynomial *)v1,
+ (struct isl_union_pw_qpolynomial *)v2);
+}
+
+struct isl_obj_vtable isl_obj_union_pw_qpolynomial_vtable = {
+ isl_obj_union_pw_qp_copy,
+ isl_obj_union_pw_qp_add,
+ isl_obj_union_pw_qp_print,
+ isl_obj_union_pw_qp_free
+};
+
+static void *isl_obj_pw_qpf_copy(void *v)
+{
+ return isl_pw_qpolynomial_fold_copy((struct isl_pw_qpolynomial_fold *)v);
+}
+
+static void isl_obj_pw_qpf_free(void *v)
+{
+ isl_pw_qpolynomial_fold_free((struct isl_pw_qpolynomial_fold *)v);
+}
+
+static __isl_give isl_printer *isl_obj_pw_qpf_print(__isl_take isl_printer *p,
+ void *v)
+{
+ return isl_printer_print_pw_qpolynomial_fold(p,
+ (struct isl_pw_qpolynomial_fold *)v);
+}
+
+static void *isl_obj_pw_qpf_add(void *v1, void *v2)
+{
+ return isl_pw_qpolynomial_fold_fold((struct isl_pw_qpolynomial_fold *)v1,
+ (struct isl_pw_qpolynomial_fold *)v2);
+}
+
+struct isl_obj_vtable isl_obj_pw_qpolynomial_fold_vtable = {
+ isl_obj_pw_qpf_copy,
+ isl_obj_pw_qpf_add,
+ isl_obj_pw_qpf_print,
+ isl_obj_pw_qpf_free
+};
+
+static void *isl_obj_union_pw_qpf_copy(void *v)
+{
+ return isl_union_pw_qpolynomial_fold_copy((struct isl_union_pw_qpolynomial_fold *)v);
+}
+
+static void isl_obj_union_pw_qpf_free(void *v)
+{
+ isl_union_pw_qpolynomial_fold_free((struct isl_union_pw_qpolynomial_fold *)v);
+}
+
+static __isl_give isl_printer *isl_obj_union_pw_qpf_print(
+ __isl_take isl_printer *p, void *v)
+{
+ return isl_printer_print_union_pw_qpolynomial_fold(p,
+ (struct isl_union_pw_qpolynomial_fold *)v);
+}
+
+static void *isl_obj_union_pw_qpf_add(void *v1, void *v2)
+{
+ return isl_union_pw_qpolynomial_fold_fold(
+ (struct isl_union_pw_qpolynomial_fold *)v1,
+ (struct isl_union_pw_qpolynomial_fold *)v2);
+}
+
+struct isl_obj_vtable isl_obj_union_pw_qpolynomial_fold_vtable = {
+ isl_obj_union_pw_qpf_copy,
+ isl_obj_union_pw_qpf_add,
+ isl_obj_union_pw_qpf_print,
+ isl_obj_union_pw_qpf_free
+};
diff --git a/polly/lib/External/isl/isl_options.c b/polly/lib/External/isl/isl_options.c
new file mode 100644
index 00000000000..f41b6e0ec45
--- /dev/null
+++ b/polly/lib/External/isl/isl_options.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isl/ctx.h>
+#include <isl_options_private.h>
+#include <isl/ast_build.h>
+#include <isl/schedule.h>
+#include <isl/version.h>
+
+struct isl_arg_choice isl_pip_context_choice[] = {
+ {"gbr", ISL_CONTEXT_GBR},
+ {"lexmin", ISL_CONTEXT_LEXMIN},
+ {0}
+};
+
+struct isl_arg_choice isl_gbr_choice[] = {
+ {"never", ISL_GBR_NEVER},
+ {"once", ISL_GBR_ONCE},
+ {"always", ISL_GBR_ALWAYS},
+ {0}
+};
+
+struct isl_arg_choice isl_closure_choice[] = {
+ {"isl", ISL_CLOSURE_ISL},
+ {"box", ISL_CLOSURE_BOX},
+ {0}
+};
+
+static struct isl_arg_choice bound[] = {
+ {"bernstein", ISL_BOUND_BERNSTEIN},
+ {"range", ISL_BOUND_RANGE},
+ {0}
+};
+
+static struct isl_arg_choice on_error[] = {
+ {"warn", ISL_ON_ERROR_WARN},
+ {"continue", ISL_ON_ERROR_CONTINUE},
+ {"abort", ISL_ON_ERROR_ABORT},
+ {0}
+};
+
+static struct isl_arg_choice isl_schedule_algorithm_choice[] = {
+ {"isl", ISL_SCHEDULE_ALGORITHM_ISL},
+ {"feautrier", ISL_SCHEDULE_ALGORITHM_FEAUTRIER},
+ {0}
+};
+
+static struct isl_arg_flags bernstein_recurse[] = {
+ {"none", ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS, 0},
+ {"factors", ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS,
+ ISL_BERNSTEIN_FACTORS},
+ {"intervals", ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS,
+ ISL_BERNSTEIN_INTERVALS},
+ {"full", ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS,
+ ISL_BERNSTEIN_FACTORS | ISL_BERNSTEIN_INTERVALS},
+ {0}
+};
+
+static struct isl_arg_choice convex[] = {
+ {"wrap", ISL_CONVEX_HULL_WRAP},
+ {"fm", ISL_CONVEX_HULL_FM},
+ {0}
+};
+
+static struct isl_arg_choice fuse[] = {
+ {"max", ISL_SCHEDULE_FUSE_MAX},
+ {"min", ISL_SCHEDULE_FUSE_MIN},
+ {0}
+};
+
+static struct isl_arg_choice separation_bounds[] = {
+ {"explicit", ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT},
+ {"implicit", ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT},
+ {0}
+};
+
+static void print_version(void)
+{
+ printf("%s", isl_version());
+}
+
+ISL_ARGS_START(struct isl_options, isl_options_args)
+ISL_ARG_CHOICE(struct isl_options, context, 0, "context", \
+ isl_pip_context_choice, ISL_CONTEXT_GBR,
+ "how to handle the pip context tableau")
+ISL_ARG_CHOICE(struct isl_options, gbr, 0, "gbr", \
+ isl_gbr_choice, ISL_GBR_ALWAYS,
+ "how often to use generalized basis reduction")
+ISL_ARG_CHOICE(struct isl_options, closure, 0, "closure", \
+ isl_closure_choice, ISL_CLOSURE_ISL,
+ "closure operation to use")
+ISL_ARG_BOOL(struct isl_options, gbr_only_first, 0, "gbr-only-first", 0,
+ "only perform basis reduction in first direction")
+ISL_ARG_CHOICE(struct isl_options, bound, 0, "bound", bound,
+ ISL_BOUND_BERNSTEIN, "algorithm to use for computing bounds")
+ISL_ARG_CHOICE(struct isl_options, on_error, 0, "on-error", on_error,
+ ISL_ON_ERROR_WARN, "how to react if an error is detected")
+ISL_ARG_FLAGS(struct isl_options, bernstein_recurse, 0,
+ "bernstein-recurse", bernstein_recurse, ISL_BERNSTEIN_FACTORS, NULL)
+ISL_ARG_BOOL(struct isl_options, bernstein_triangulate, 0,
+ "bernstein-triangulate", 1,
+ "triangulate domains during Bernstein expansion")
+ISL_ARG_BOOL(struct isl_options, pip_symmetry, 0, "pip-symmetry", 1,
+ "detect simple symmetries in PIP input")
+ISL_ARG_CHOICE(struct isl_options, convex, 0, "convex-hull", \
+ convex, ISL_CONVEX_HULL_WRAP, "convex hull algorithm to use")
+ISL_ARG_BOOL(struct isl_options, coalesce_bounded_wrapping, 0,
+ "coalesce-bounded-wrapping", 1, "bound wrapping during coalescing")
+ISL_ARG_INT(struct isl_options, schedule_max_coefficient, 0,
+ "schedule-max-coefficient", "limit", -1, "Only consider schedules "
+ "where the coefficients of the variable and parameter dimensions "
+ "do not exceed <limit>. A value of -1 allows arbitrary coefficients.")
+ISL_ARG_INT(struct isl_options, schedule_max_constant_term, 0,
+ "schedule-max-constant-term", "limit", -1, "Only consider schedules "
+ "where the coefficients of the constant dimension do not exceed "
+ "<limit>. A value of -1 allows arbitrary coefficients.")
+ISL_ARG_BOOL(struct isl_options, schedule_parametric, 0,
+ "schedule-parametric", 1, "construct possibly parametric schedules")
+ISL_ARG_BOOL(struct isl_options, schedule_outer_coincidence, 0,
+ "schedule-outer-coincidence", 0,
+ "try to construct schedules where the outer member of each band "
+ "satisfies the coincidence constraints")
+ISL_ARG_BOOL(struct isl_options, schedule_maximize_band_depth, 0,
+ "schedule-maximize-band-depth", 0,
+ "maximize the number of scheduling dimensions in a band")
+ISL_ARG_BOOL(struct isl_options, schedule_split_scaled, 0,
+ "schedule-split-scaled", 1,
+ "split non-tilable bands with scaled schedules")
+ISL_ARG_BOOL(struct isl_options, schedule_separate_components, 0,
+ "schedule-separate-components", 1,
+ "separate components in dependence graph")
+ISL_ARG_CHOICE(struct isl_options, schedule_algorithm, 0,
+ "schedule-algorithm", isl_schedule_algorithm_choice,
+ ISL_SCHEDULE_ALGORITHM_ISL, "scheduling algorithm to use")
+ISL_ARG_CHOICE(struct isl_options, schedule_fuse, 0, "schedule-fuse", fuse,
+ ISL_SCHEDULE_FUSE_MAX, "level of fusion during scheduling")
+ISL_ARG_BOOL(struct isl_options, tile_scale_tile_loops, 0,
+ "tile-scale-tile-loops", 1, "scale tile loops")
+ISL_ARG_BOOL(struct isl_options, tile_shift_point_loops, 0,
+ "tile-shift-point-loops", 1, "shift point loops to start at zero")
+ISL_ARG_STR(struct isl_options, ast_iterator_type, 0,
+ "ast-iterator-type", "type", "int",
+ "type used for iterators during printing of AST")
+ISL_ARG_BOOL(struct isl_options, ast_always_print_block, 0,
+ "ast-always-print-block", 0, "print for and if bodies as a block "
+ "regardless of the number of statements in the body")
+ISL_ARG_BOOL(struct isl_options, ast_build_atomic_upper_bound, 0,
+ "ast-build-atomic-upper-bound", 1, "generate atomic upper bounds")
+ISL_ARG_BOOL(struct isl_options, ast_build_prefer_pdiv, 0,
+ "ast-build-prefer-pdiv", 1, "prefer pdiv operation over fdiv")
+ISL_ARG_BOOL(struct isl_options, ast_build_exploit_nested_bounds, 0,
+ "ast-build-exploit-nested-bounds", 1,
+ "simplify conditions based on bounds of nested for loops")
+ISL_ARG_BOOL(struct isl_options, ast_build_group_coscheduled, 0,
+ "ast-build-group-coscheduled", 0,
+ "keep coscheduled domain elements together")
+ISL_ARG_CHOICE(struct isl_options, ast_build_separation_bounds, 0,
+ "ast-build-separation-bounds", separation_bounds,
+ ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT,
+ "bounds to use during separation")
+ISL_ARG_BOOL(struct isl_options, ast_build_scale_strides, 0,
+ "ast-build-scale-strides", 1,
+ "allow iterators of strided loops to be scaled down")
+ISL_ARG_BOOL(struct isl_options, ast_build_allow_else, 0,
+ "ast-build-allow-else", 1, "generate if statements with else branches")
+ISL_ARG_BOOL(struct isl_options, ast_build_allow_or, 0,
+ "ast-build-allow-or", 1, "generate if conditions with disjunctions")
+ISL_ARG_BOOL(struct isl_options, print_stats, 0, "print-stats", 0,
+ "print statistics for every isl_ctx")
+ISL_ARG_ULONG(struct isl_options, max_operations, 0,
+ "max-operations", 0, "default number of maximal operations per isl_ctx")
+ISL_ARG_VERSION(print_version)
+ISL_ARGS_END
+
+ISL_ARG_DEF(isl_options, struct isl_options, isl_options_args)
+
+ISL_ARG_CTX_DEF(isl_options, struct isl_options, isl_options_args)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args, bound)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args, bound)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ on_error)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ on_error)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ coalesce_bounded_wrapping)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ coalesce_bounded_wrapping)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ gbr_only_first)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ gbr_only_first)
+
+ISL_CTX_SET_INT_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_max_coefficient)
+ISL_CTX_GET_INT_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_max_coefficient)
+
+ISL_CTX_SET_INT_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_max_constant_term)
+ISL_CTX_GET_INT_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_max_constant_term)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_maximize_band_depth)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_maximize_band_depth)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_split_scaled)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_split_scaled)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_separate_components)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_separate_components)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_outer_coincidence)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_outer_coincidence)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_algorithm)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_algorithm)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_fuse)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ schedule_fuse)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ tile_scale_tile_loops)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ tile_scale_tile_loops)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ tile_shift_point_loops)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ tile_shift_point_loops)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_atomic_upper_bound)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_atomic_upper_bound)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_prefer_pdiv)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_prefer_pdiv)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_exploit_nested_bounds)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_exploit_nested_bounds)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_group_coscheduled)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_group_coscheduled)
+
+ISL_CTX_SET_STR_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_iterator_type)
+ISL_CTX_GET_STR_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_iterator_type)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_always_print_block)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_always_print_block)
+
+ISL_CTX_SET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_separation_bounds)
+ISL_CTX_GET_CHOICE_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_separation_bounds)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_scale_strides)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_scale_strides)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_allow_else)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_allow_else)
+
+ISL_CTX_SET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_allow_or)
+ISL_CTX_GET_BOOL_DEF(isl_options, struct isl_options, isl_options_args,
+ ast_build_allow_or)
diff --git a/polly/lib/External/isl/isl_options_private.h b/polly/lib/External/isl/isl_options_private.h
new file mode 100644
index 00000000000..fbf81fa6ed0
--- /dev/null
+++ b/polly/lib/External/isl/isl_options_private.h
@@ -0,0 +1,67 @@
+#ifndef ISL_OPTIONS_PRIVATE_H
+#define ISL_OPTIONS_PRIVATE_H
+
+#include <isl/options.h>
+
+struct isl_options {
+ #define ISL_CONTEXT_GBR 0
+ #define ISL_CONTEXT_LEXMIN 1
+ unsigned context;
+
+ #define ISL_GBR_NEVER 0
+ #define ISL_GBR_ONCE 1
+ #define ISL_GBR_ALWAYS 2
+ unsigned gbr;
+ unsigned gbr_only_first;
+
+ #define ISL_CLOSURE_ISL 0
+ #define ISL_CLOSURE_BOX 1
+ unsigned closure;
+
+ int bound;
+ unsigned on_error;
+
+ #define ISL_BERNSTEIN_FACTORS 1
+ #define ISL_BERNSTEIN_INTERVALS 2
+ int bernstein_recurse;
+
+ int bernstein_triangulate;
+
+ int pip_symmetry;
+
+ #define ISL_CONVEX_HULL_WRAP 0
+ #define ISL_CONVEX_HULL_FM 1
+ int convex;
+
+ int coalesce_bounded_wrapping;
+
+ int schedule_max_coefficient;
+ int schedule_max_constant_term;
+ int schedule_parametric;
+ int schedule_outer_coincidence;
+ int schedule_maximize_band_depth;
+ int schedule_split_scaled;
+ int schedule_separate_components;
+ unsigned schedule_algorithm;
+ int schedule_fuse;
+
+ int tile_scale_tile_loops;
+ int tile_shift_point_loops;
+
+ char *ast_iterator_type;
+ int ast_always_print_block;
+
+ int ast_build_atomic_upper_bound;
+ int ast_build_prefer_pdiv;
+ int ast_build_exploit_nested_bounds;
+ int ast_build_group_coscheduled;
+ int ast_build_separation_bounds;
+ int ast_build_scale_strides;
+ int ast_build_allow_else;
+ int ast_build_allow_or;
+
+ int print_stats;
+ unsigned long max_operations;
+};
+
+#endif
diff --git a/polly/lib/External/isl/isl_output.c b/polly/lib/External/isl/isl_output.c
new file mode 100644
index 00000000000..b5d6c923384
--- /dev/null
+++ b/polly/lib/External/isl/isl_output.c
@@ -0,0 +1,2698 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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 <stdlib.h>
+#include <string.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_polynomial_private.h>
+#include <isl_printer_private.h>
+#include <isl_space_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl/union_map.h>
+#include <isl/constraint.h>
+#include <isl_local_space_private.h>
+#include <isl_aff_private.h>
+#include <isl_val_private.h>
+#include <isl/ast_build.h>
+#include <isl_sort.h>
+
+static const char *s_to[2] = { " -> ", " \\to " };
+static const char *s_and[2] = { " and ", " \\wedge " };
+static const char *s_or[2] = { " or ", " \\vee " };
+static const char *s_le[2] = { "<=", "\\le" };
+static const char *s_ge[2] = { ">=", "\\ge" };
+static const char *s_open_set[2] = { "{ ", "\\{\\, " };
+static const char *s_close_set[2] = { " }", " \\,\\}" };
+static const char *s_open_list[2] = { "[", "(" };
+static const char *s_close_list[2] = { "]", ")" };
+static const char *s_such_that[2] = { " : ", " \\mid " };
+static const char *s_open_exists[2] = { "exists (", "\\exists \\, " };
+static const char *s_close_exists[2] = { ")", "" };
+static const char *s_div_prefix[2] = { "e", "\\alpha_" };
+static const char *s_param_prefix[2] = { "p", "p_" };
+static const char *s_input_prefix[2] = { "i", "i_" };
+static const char *s_output_prefix[2] = { "o", "o_" };
+
+static __isl_give isl_printer *print_constraint_polylib(
+ struct isl_basic_map *bmap, int ineq, int n, __isl_take isl_printer *p)
+{
+ int i;
+ unsigned n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ unsigned n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ unsigned nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ isl_int *c = ineq ? bmap->ineq[n] : bmap->eq[n];
+
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_int(p, ineq);
+ for (i = 0; i < n_out; ++i) {
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_isl_int(p, c[1+nparam+n_in+i]);
+ }
+ for (i = 0; i < n_in; ++i) {
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_isl_int(p, c[1+nparam+i]);
+ }
+ for (i = 0; i < bmap->n_div; ++i) {
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_isl_int(p, c[1+nparam+n_in+n_out+i]);
+ }
+ for (i = 0; i < nparam; ++i) {
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_isl_int(p, c[1+i]);
+ }
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_isl_int(p, c[0]);
+ p = isl_printer_end_line(p);
+ return p;
+}
+
+static __isl_give isl_printer *print_constraints_polylib(
+ struct isl_basic_map *bmap, __isl_take isl_printer *p)
+{
+ int i;
+
+ p = isl_printer_set_isl_int_width(p, 5);
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ p = print_constraint_polylib(bmap, 0, i, p);
+ for (i = 0; i < bmap->n_ineq; ++i)
+ p = print_constraint_polylib(bmap, 1, i, p);
+
+ return p;
+}
+
+static __isl_give isl_printer *bset_print_constraints_polylib(
+ struct isl_basic_set *bset, __isl_take isl_printer *p)
+{
+ return print_constraints_polylib((struct isl_basic_map *)bset, p);
+}
+
+static __isl_give isl_printer *isl_basic_map_print_polylib(
+ __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p, int ext)
+{
+ unsigned total = isl_basic_map_total_dim(bmap);
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_int(p, bmap->n_eq + bmap->n_ineq);
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_int(p, 1 + total + 1);
+ if (ext) {
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_int(p,
+ isl_basic_map_dim(bmap, isl_dim_out));
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_int(p,
+ isl_basic_map_dim(bmap, isl_dim_in));
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_int(p,
+ isl_basic_map_dim(bmap, isl_dim_div));
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_int(p,
+ isl_basic_map_dim(bmap, isl_dim_param));
+ }
+ p = isl_printer_end_line(p);
+ return print_constraints_polylib(bmap, p);
+}
+
+static __isl_give isl_printer *isl_basic_set_print_polylib(
+ __isl_keep isl_basic_set *bset, __isl_take isl_printer *p, int ext)
+{
+ return isl_basic_map_print_polylib((struct isl_basic_map *)bset, p, ext);
+}
+
+static __isl_give isl_printer *isl_map_print_polylib(__isl_keep isl_map *map,
+ __isl_take isl_printer *p, int ext)
+{
+ int i;
+
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_int(p, map->n);
+ p = isl_printer_end_line(p);
+ for (i = 0; i < map->n; ++i) {
+ p = isl_printer_start_line(p);
+ p = isl_printer_end_line(p);
+ p = isl_basic_map_print_polylib(map->p[i], p, ext);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *isl_set_print_polylib(__isl_keep isl_set *set,
+ __isl_take isl_printer *p, int ext)
+{
+ return isl_map_print_polylib((struct isl_map *)set, p, ext);
+}
+
+static int count_same_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos, const char *name)
+{
+ enum isl_dim_type t;
+ unsigned p, s;
+ int count = 0;
+
+ for (t = isl_dim_param; t <= type && t <= isl_dim_out; ++t) {
+ s = t == type ? pos : isl_space_dim(dim, t);
+ for (p = 0; p < s; ++p) {
+ const char *n = isl_space_get_dim_name(dim, t, p);
+ if (n && !strcmp(n, name))
+ count++;
+ }
+ }
+ return count;
+}
+
+static __isl_give isl_printer *print_name(__isl_keep isl_space *dim,
+ __isl_take isl_printer *p, enum isl_dim_type type, unsigned pos,
+ int latex)
+{
+ const char *name;
+ char buffer[20];
+ int primes;
+
+ name = type == isl_dim_div ? NULL : isl_space_get_dim_name(dim, type, pos);
+
+ if (!name) {
+ const char *prefix;
+ if (type == isl_dim_param)
+ 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)
+ 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,
+ pos, name);
+ p = isl_printer_print_str(p, name);
+ while (primes-- > 0)
+ p = isl_printer_print_str(p, "'");
+ return p;
+}
+
+static enum isl_dim_type pos2type(__isl_keep isl_space *dim, unsigned *pos)
+{
+ enum isl_dim_type type;
+ unsigned n_in = isl_space_dim(dim, isl_dim_in);
+ unsigned n_out = isl_space_dim(dim, isl_dim_out);
+ unsigned nparam = isl_space_dim(dim, isl_dim_param);
+
+ if (*pos < 1 + nparam) {
+ type = isl_dim_param;
+ *pos -= 1;
+ } else if (*pos < 1 + nparam + n_in) {
+ type = isl_dim_in;
+ *pos -= 1 + nparam;
+ } else if (*pos < 1 + nparam + n_in + n_out) {
+ type = isl_dim_out;
+ *pos -= 1 + nparam + n_in;
+ } else {
+ type = isl_dim_div;
+ *pos -= 1 + nparam + n_in + n_out;
+ }
+
+ return type;
+}
+
+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,
+ __isl_keep isl_mat *div,
+ isl_int c, unsigned pos, __isl_take isl_printer *p, int latex)
+{
+ enum isl_dim_type type;
+ int print_div_def;
+
+ 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]);
+
+ if (isl_int_is_one(c))
+ ;
+ else if (isl_int_is_negone(c))
+ p = isl_printer_print_str(p, "-");
+ else {
+ p = isl_printer_print_isl_int(p, c);
+ if (p->output_format == ISL_FORMAT_C || print_div_def)
+ p = isl_printer_print_str(p, "*");
+ }
+ if (print_div_def)
+ p = print_div(dim, div, pos, p);
+ else
+ p = print_name(dim, p, type, pos, latex);
+ return p;
+}
+
+static __isl_give isl_printer *print_affine_of_len(__isl_keep isl_space *dim,
+ __isl_keep isl_mat *div,
+ __isl_take isl_printer *p, isl_int *c, int len)
+{
+ int i;
+ int first;
+
+ for (i = 0, first = 1; i < len; ++i) {
+ int flip = 0;
+ if (isl_int_is_zero(c[i]))
+ continue;
+ if (!first) {
+ if (isl_int_is_neg(c[i])) {
+ flip = 1;
+ isl_int_neg(c[i], c[i]);
+ p = isl_printer_print_str(p, " - ");
+ } else
+ p = isl_printer_print_str(p, " + ");
+ }
+ first = 0;
+ p = print_term(dim, div, c[i], i, p, 0);
+ if (flip)
+ isl_int_neg(c[i], c[i]);
+ }
+ if (first)
+ p = isl_printer_print_str(p, "0");
+ return p;
+}
+
+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)
+{
+ unsigned len = 1 + isl_basic_map_total_dim(bmap);
+ return print_affine_of_len(dim, NULL, 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,
+ __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
+ struct isl_print_space_data *data, int offset)
+{
+ int i;
+
+ if (data->space != local_dim && local_type == isl_dim_out)
+ offset += local_dim->n_in;
+
+ for (i = 0; i < isl_space_dim(local_dim, local_type); ++i) {
+ if (i)
+ p = isl_printer_print_str(p, ", ");
+ if (data->print_dim)
+ p = data->print_dim(p, data, offset + i);
+ else
+ p = print_name(data->space, p, data->type, offset + i,
+ data->latex);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *print_var_list(__isl_take isl_printer *p,
+ __isl_keep isl_space *space, enum isl_dim_type type)
+{
+ struct isl_print_space_data data = { .space = space, .type = type };
+
+ return print_nested_var_list(p, space, type, &data, 0);
+}
+
+static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
+ __isl_keep isl_space *local_dim,
+ struct isl_print_space_data *data, int offset);
+
+static __isl_give isl_printer *print_nested_tuple(__isl_take isl_printer *p,
+ __isl_keep isl_space *local_dim, enum isl_dim_type local_type,
+ struct isl_print_space_data *data, int offset)
+{
+ const char *name = NULL;
+ unsigned n = isl_space_dim(local_dim, local_type);
+ if ((local_type == isl_dim_in || local_type == isl_dim_out)) {
+ name = isl_space_get_tuple_name(local_dim, local_type);
+ if (name) {
+ if (data->latex)
+ p = isl_printer_print_str(p, "\\mathrm{");
+ p = isl_printer_print_str(p, name);
+ if (data->latex)
+ p = isl_printer_print_str(p, "}");
+ }
+ }
+ if (!data->latex || n != 1 || name)
+ p = isl_printer_print_str(p, s_open_list[data->latex]);
+ if ((local_type == isl_dim_in || local_type == isl_dim_out) &&
+ local_dim->nested[local_type - isl_dim_in]) {
+ if (data->space != local_dim && local_type == isl_dim_out)
+ offset += local_dim->n_in;
+ p = print_nested_map_dim(p,
+ local_dim->nested[local_type - isl_dim_in],
+ data, offset);
+ } else
+ p = print_nested_var_list(p, local_dim, local_type, data,
+ offset);
+ if (!data->latex || n != 1 || name)
+ p = isl_printer_print_str(p, s_close_list[data->latex]);
+ return p;
+}
+
+static __isl_give isl_printer *print_tuple(__isl_keep isl_space *dim,
+ __isl_take isl_printer *p, enum isl_dim_type type,
+ struct isl_print_space_data *data)
+{
+ data->space = dim;
+ data->type = type;
+ return print_nested_tuple(p, dim, type, data, 0);
+}
+
+static __isl_give isl_printer *print_nested_map_dim(__isl_take isl_printer *p,
+ __isl_keep isl_space *local_dim,
+ struct isl_print_space_data *data, int offset)
+{
+ p = print_nested_tuple(p, local_dim, isl_dim_in, data, offset);
+ p = isl_printer_print_str(p, s_to[data->latex]);
+ p = print_nested_tuple(p, local_dim, isl_dim_out, data, offset);
+
+ return p;
+}
+
+static __isl_give isl_printer *print_space(__isl_keep isl_space *dim,
+ __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))
+ ;
+ else if (isl_space_is_set(dim))
+ p = print_tuple(dim, p, isl_dim_set, data);
+ else {
+ p = print_tuple(dim, p, isl_dim_in, data);
+ p = isl_printer_print_str(p, s_to[data->latex]);
+ p = print_tuple(dim, p, isl_dim_out, data);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *print_omega_parameters(__isl_keep isl_space *dim,
+ __isl_take isl_printer *p)
+{
+ if (isl_space_dim(dim, isl_dim_param) == 0)
+ return p;
+
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_str(p, "symbolic ");
+ p = print_var_list(p, dim, isl_dim_param);
+ p = isl_printer_print_str(p, ";");
+ p = isl_printer_end_line(p);
+ return p;
+}
+
+static __isl_give isl_printer *print_constraint(struct isl_basic_map *bmap,
+ __isl_keep isl_space *dim, __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_abs(c[last], c[last]);
+
+ p = print_term(dim, NULL, 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);
+
+ return p;
+}
+
+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)
+{
+ int i;
+ struct isl_vec *c;
+ unsigned total = isl_basic_map_total_dim(bmap);
+
+ c = isl_vec_alloc(bmap->ctx, 1 + total);
+ if (!c)
+ goto error;
+
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ int l = isl_seq_last_non_zero(bmap->eq[i], 1 + total);
+ if (l < 0) {
+ if (i != bmap->n_eq - 1)
+ p = isl_printer_print_str(p, s_and[latex]);
+ p = isl_printer_print_str(p, "0 = 0");
+ continue;
+ }
+ if (isl_int_is_neg(bmap->eq[i][l]))
+ 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);
+ }
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ int l = isl_seq_last_non_zero(bmap->ineq[i], 1 + total);
+ int s;
+ const char *op;
+ if (l < 0)
+ continue;
+ s = isl_int_sgn(bmap->ineq[i][l]);
+ 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);
+ }
+
+ isl_vec_free(c);
+
+ return p;
+error:
+ isl_vec_free(c);
+ isl_printer_free(p);
+ return NULL;
+}
+
+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;
+ 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);
+ p = isl_printer_print_str(p, c ? ", " : ")/");
+ p = isl_printer_print_isl_int(p, div->row[pos][0]);
+ p = isl_printer_print_str(p, ")");
+ 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).
+ */
+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)
+{
+ int i;
+ unsigned n_div;
+
+ if (!p || !space || !div)
+ return isl_printer_free(p);
+
+ n_div = isl_mat_rows(div);
+
+ for (i = 0; i < n_div; ++i) {
+ if (i)
+ 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]))
+ continue;
+ p = isl_printer_print_str(p, " = ");
+ p = print_div(space, div, i, p);
+ }
+
+ return p;
+}
+
+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)
+{
+ if (bmap->n_div > 0) {
+ isl_space *space;
+ isl_mat *div;
+
+ space = isl_basic_map_get_space(bmap);
+ div = isl_basic_map_get_divs(bmap);
+ 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 = isl_printer_print_str(p, ": ");
+ }
+
+ p = print_constraints(bmap, dim, p, latex);
+
+ if (bmap->n_div > 0)
+ p = isl_printer_print_str(p, s_close_exists[latex]);
+ return p;
+}
+
+/* Print a colon followed by the constraints of "bmap"
+ * to "p", provided there are any constraints.
+ * 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_optional_disjunct(
+ __isl_keep isl_basic_map *bmap, __isl_keep isl_space *space,
+ __isl_take isl_printer *p, int latex)
+{
+ if (isl_basic_map_is_universe(bmap))
+ return p;
+
+ p = isl_printer_print_str(p, ": ");
+ p = print_disjunct(bmap, space, p, latex);
+
+ return p;
+}
+
+static __isl_give isl_printer *basic_map_print_omega(
+ __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p)
+{
+ p = isl_printer_print_str(p, "{ [");
+ p = print_var_list(p, bmap->dim, isl_dim_in);
+ p = isl_printer_print_str(p, "] -> [");
+ p = print_var_list(p, bmap->dim, isl_dim_out);
+ p = isl_printer_print_str(p, "] ");
+ p = print_optional_disjunct(bmap, bmap->dim, p, 0);
+ p = isl_printer_print_str(p, " }");
+ return p;
+}
+
+static __isl_give isl_printer *basic_set_print_omega(
+ __isl_keep isl_basic_set *bset, __isl_take isl_printer *p)
+{
+ p = isl_printer_print_str(p, "{ [");
+ p = print_var_list(p, bset->dim, isl_dim_set);
+ p = isl_printer_print_str(p, "] ");
+ p = print_optional_disjunct(bset, bset->dim, p, 0);
+ p = isl_printer_print_str(p, " }");
+ return p;
+}
+
+static __isl_give isl_printer *isl_map_print_omega(__isl_keep isl_map *map,
+ __isl_take isl_printer *p)
+{
+ int i;
+
+ for (i = 0; i < map->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, " union ");
+ p = basic_map_print_omega(map->p[i], p);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *isl_set_print_omega(__isl_keep isl_set *set,
+ __isl_take isl_printer *p)
+{
+ int i;
+
+ for (i = 0; i < set->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, " union ");
+ p = basic_set_print_omega(set->p[i], p);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *isl_basic_map_print_isl(
+ __isl_keep isl_basic_map *bmap, __isl_take isl_printer *p,
+ int latex)
+{
+ struct isl_print_space_data data = { .latex = latex };
+ int rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+
+ if (isl_basic_map_dim(bmap, isl_dim_param) > 0) {
+ p = print_tuple(bmap->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ p = 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)
+{
+ 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) {
+ if (i)
+ 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);
+ 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).
+ * 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)
+{
+ 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);
+}
+
+struct isl_aff_split {
+ isl_basic_map *aff;
+ isl_map *map;
+};
+
+static void free_split(__isl_take struct isl_aff_split *split, int n)
+{
+ int i;
+
+ if (!split)
+ return;
+
+ for (i = 0; i < n; ++i) {
+ isl_basic_map_free(split[i].aff);
+ isl_map_free(split[i].map);
+ }
+
+ free(split);
+}
+
+static __isl_give isl_basic_map *get_aff(__isl_take isl_basic_map *bmap)
+{
+ int i, j;
+ unsigned nparam, n_in, n_out, total;
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ return NULL;
+ if (isl_basic_map_free_inequality(bmap, bmap->n_ineq) < 0)
+ goto error;
+
+ nparam = isl_basic_map_dim(bmap, isl_dim_param);
+ n_in = isl_basic_map_dim(bmap, isl_dim_in);
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ j = isl_seq_last_non_zero(bmap->eq[i] + 1, total);
+ if (j >= nparam && j < nparam + n_in + n_out &&
+ (isl_int_is_one(bmap->eq[i][1 + j]) ||
+ isl_int_is_negone(bmap->eq[i][1 + j])))
+ continue;
+ if (isl_basic_map_drop_equality(bmap, i) < 0)
+ goto error;
+ }
+
+ bmap = isl_basic_map_finalize(bmap);
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static int aff_split_cmp(const void *p1, const void *p2, void *user)
+{
+ const struct isl_aff_split *s1, *s2;
+ s1 = (const struct isl_aff_split *) p1;
+ s2 = (const struct isl_aff_split *) p2;
+
+ return isl_basic_map_plain_cmp(s1->aff, s2->aff);
+}
+
+static __isl_give isl_basic_map *drop_aff(__isl_take isl_basic_map *bmap,
+ __isl_keep isl_basic_map *aff)
+{
+ int i, j;
+ unsigned total;
+
+ if (!bmap || !aff)
+ goto error;
+
+ total = isl_space_dim(bmap->dim, isl_dim_all);
+
+ for (i = bmap->n_eq - 1; i >= 0; --i) {
+ if (isl_seq_first_non_zero(bmap->eq[i] + 1 + total,
+ bmap->n_div) != -1)
+ continue;
+ for (j = 0; j < aff->n_eq; ++j) {
+ if (!isl_seq_eq(bmap->eq[i], aff->eq[j], 1 + total) &&
+ !isl_seq_is_neg(bmap->eq[i], aff->eq[j], 1 + total))
+ continue;
+ if (isl_basic_map_drop_equality(bmap, i) < 0)
+ goto error;
+ break;
+ }
+ }
+
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+static __isl_give struct isl_aff_split *split_aff(__isl_keep isl_map *map)
+{
+ int i, n;
+ struct isl_aff_split *split;
+ isl_ctx *ctx;
+
+ ctx = isl_map_get_ctx(map);
+ split = isl_calloc_array(ctx, struct isl_aff_split, map->n);
+ if (!split)
+ return NULL;
+
+ for (i = 0; i < map->n; ++i) {
+ isl_basic_map *bmap;
+ split[i].aff = get_aff(isl_basic_map_copy(map->p[i]));
+ bmap = isl_basic_map_copy(map->p[i]);
+ bmap = isl_basic_map_cow(bmap);
+ bmap = drop_aff(bmap, split[i].aff);
+ split[i].map = isl_map_from_basic_map(bmap);
+ if (!split[i].aff || !split[i].map)
+ goto error;
+ }
+
+ if (isl_sort(split, map->n, sizeof(struct isl_aff_split),
+ &aff_split_cmp, NULL) < 0)
+ goto error;
+
+ n = map->n;
+ for (i = n - 1; i >= 1; --i) {
+ if (!isl_basic_map_plain_is_equal(split[i - 1].aff,
+ split[i].aff))
+ continue;
+ isl_basic_map_free(split[i].aff);
+ split[i - 1].map = isl_map_union(split[i - 1].map,
+ split[i].map);
+ if (i != n - 1)
+ split[i] = split[n - 1];
+ split[n - 1].aff = NULL;
+ split[n - 1].map = NULL;
+ --n;
+ }
+
+ return split;
+error:
+ free_split(split, map->n);
+ return NULL;
+}
+
+static int defining_equality(__isl_keep isl_basic_map *eq,
+ __isl_keep isl_space *dim, enum isl_dim_type type, int pos)
+{
+ int i;
+ unsigned total;
+
+ if (!eq)
+ return -1;
+
+ pos += isl_space_offset(dim, type);
+ total = isl_basic_map_total_dim(eq);
+
+ for (i = 0; i < eq->n_eq; ++i) {
+ if (isl_seq_last_non_zero(eq->eq[i] + 1, total) != pos)
+ continue;
+ if (isl_int_is_one(eq->eq[i][1 + pos]))
+ isl_seq_neg(eq->eq[i], eq->eq[i], 1 + total);
+ return i;
+ }
+
+ return -1;
+}
+
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_basic_map keeping track of equalities.
+ *
+ * If the current dimension is defined by these equalities, then print
+ * the corresponding expression. Otherwise, print the name of the dimension.
+ */
+static __isl_give isl_printer *print_dim_eq(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ isl_basic_map *eq = data->user;
+ int j;
+
+ j = defining_equality(eq, data->space, data->type, pos);
+ if (j >= 0) {
+ pos += 1 + isl_space_offset(data->space, data->type);
+ p = print_affine_of_len(eq->dim, NULL, p, eq->eq[j], pos);
+ } else {
+ p = print_name(data->space, p, data->type, pos, data->latex);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *print_split_map(__isl_take isl_printer *p,
+ struct isl_aff_split *split, int n)
+{
+ struct isl_print_space_data data = { 0 };
+ int i;
+ int rational;
+
+ 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);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *isl_map_print_isl_body(__isl_keep isl_map *map,
+ __isl_take isl_printer *p)
+{
+ struct isl_print_space_data data = { 0 };
+ struct isl_aff_split *split = NULL;
+ int rational;
+
+ if (map->n > 0)
+ split = split_aff(map);
+ if (split) {
+ p = print_split_map(p, split, map->n);
+ } 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);
+ }
+ free_split(split, map->n);
+ return p;
+}
+
+static __isl_give isl_printer *isl_map_print_isl(__isl_keep isl_map *map,
+ __isl_take isl_printer *p)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (isl_map_dim(map, isl_dim_param) > 0) {
+ p = print_tuple(map->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, s_to[0]);
+ }
+ p = isl_printer_print_str(p, s_open_set[0]);
+ p = isl_map_print_isl_body(map, p);
+ p = isl_printer_print_str(p, s_close_set[0]);
+ return p;
+}
+
+static __isl_give isl_printer *print_latex_map(__isl_keep isl_map *map,
+ __isl_take isl_printer *p, __isl_keep isl_basic_map *aff)
+{
+ struct isl_print_space_data data = { 0 };
+
+ data.latex = 1;
+ if (isl_map_dim(map, isl_dim_param) > 0) {
+ p = print_tuple(map->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, s_to[1]);
+ }
+ 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_printer_print_str(p, s_close_set[1]);
+
+ return p;
+}
+
+static __isl_give isl_printer *isl_map_print_latex(__isl_keep isl_map *map,
+ __isl_take isl_printer *p)
+{
+ int i;
+ struct isl_aff_split *split = NULL;
+
+ if (map->n > 0)
+ split = split_aff(map);
+
+ if (!split)
+ return print_latex_map(map, p, NULL);
+
+ for (i = 0; i < map->n; ++i) {
+ if (!split[i].map)
+ break;
+ if (i)
+ p = isl_printer_print_str(p, " \\cup ");
+ p = print_latex_map(split[i].map, p, split[i].aff);
+ }
+
+ free_split(split, map->n);
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_basic_map(__isl_take isl_printer *p,
+ __isl_keep isl_basic_map *bmap)
+{
+ if (!p || !bmap)
+ goto error;
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_basic_map_print_isl(bmap, p, 0);
+ else if (p->output_format == ISL_FORMAT_OMEGA)
+ return basic_map_print_omega(bmap, p);
+ isl_assert(bmap->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_basic_map_print(__isl_keep isl_basic_map *bmap, FILE *out, int indent,
+ const char *prefix, const char *suffix, unsigned output_format)
+{
+ isl_printer *printer;
+
+ if (!bmap)
+ return;
+
+ printer = isl_printer_to_file(bmap->ctx, out);
+ printer = isl_printer_set_indent(printer, indent);
+ printer = isl_printer_set_prefix(printer, prefix);
+ printer = isl_printer_set_suffix(printer, suffix);
+ printer = isl_printer_set_output_format(printer, output_format);
+ isl_printer_print_basic_map(printer, bmap);
+
+ isl_printer_free(printer);
+}
+
+__isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,
+ __isl_keep isl_basic_set *bset)
+{
+ if (!p || !bset)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_basic_map_print_isl(bset, p, 0);
+ else if (p->output_format == ISL_FORMAT_POLYLIB)
+ return isl_basic_set_print_polylib(bset, p, 0);
+ else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
+ return isl_basic_set_print_polylib(bset, p, 1);
+ else if (p->output_format == ISL_FORMAT_POLYLIB_CONSTRAINTS)
+ return bset_print_constraints_polylib(bset, p);
+ else if (p->output_format == ISL_FORMAT_OMEGA)
+ return basic_set_print_omega(bset, p);
+ isl_assert(p->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_basic_set_print(struct isl_basic_set *bset, FILE *out, int indent,
+ const char *prefix, const char *suffix, unsigned output_format)
+{
+ isl_printer *printer;
+
+ if (!bset)
+ return;
+
+ printer = isl_printer_to_file(bset->ctx, out);
+ printer = isl_printer_set_indent(printer, indent);
+ printer = isl_printer_set_prefix(printer, prefix);
+ printer = isl_printer_set_suffix(printer, suffix);
+ printer = isl_printer_set_output_format(printer, output_format);
+ isl_printer_print_basic_set(printer, bset);
+
+ isl_printer_free(printer);
+}
+
+__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p,
+ __isl_keep isl_set *set)
+{
+ if (!p || !set)
+ goto error;
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_map_print_isl((isl_map *)set, p);
+ else if (p->output_format == ISL_FORMAT_POLYLIB)
+ return isl_set_print_polylib(set, p, 0);
+ else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
+ return isl_set_print_polylib(set, p, 1);
+ else if (p->output_format == ISL_FORMAT_OMEGA)
+ return isl_set_print_omega(set, p);
+ else if (p->output_format == ISL_FORMAT_LATEX)
+ return isl_map_print_latex((isl_map *)set, p);
+ isl_assert(set->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_set_print(struct isl_set *set, FILE *out, int indent,
+ unsigned output_format)
+{
+ isl_printer *printer;
+
+ if (!set)
+ return;
+
+ printer = isl_printer_to_file(set->ctx, out);
+ printer = isl_printer_set_indent(printer, indent);
+ printer = isl_printer_set_output_format(printer, output_format);
+ printer = isl_printer_print_set(printer, set);
+
+ isl_printer_free(printer);
+}
+
+__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p,
+ __isl_keep isl_map *map)
+{
+ if (!p || !map)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_map_print_isl(map, p);
+ else if (p->output_format == ISL_FORMAT_POLYLIB)
+ return isl_map_print_polylib(map, p, 0);
+ else if (p->output_format == ISL_FORMAT_EXT_POLYLIB)
+ return isl_map_print_polylib(map, p, 1);
+ else if (p->output_format == ISL_FORMAT_OMEGA)
+ return isl_map_print_omega(map, p);
+ else if (p->output_format == ISL_FORMAT_LATEX)
+ return isl_map_print_latex(map, p);
+ isl_assert(map->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+struct isl_union_print_data {
+ isl_printer *p;
+ int first;
+};
+
+static int print_map_body(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *)user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, "; ");
+ data->first = 0;
+
+ data->p = isl_map_print_isl_body(map, data->p);
+ isl_map_free(map);
+
+ return 0;
+}
+
+static __isl_give isl_printer *isl_union_map_print_isl(
+ __isl_keep isl_union_map *umap, __isl_take isl_printer *p)
+{
+ struct isl_union_print_data data = { p, 1 };
+ struct isl_print_space_data space_data = { 0 };
+ isl_space *dim;
+
+ dim = isl_union_map_get_space(umap);
+ if (isl_space_dim(dim, isl_dim_param) > 0) {
+ p = print_tuple(dim, p, isl_dim_param, &space_data);
+ p = isl_printer_print_str(p, s_to[0]);
+ }
+ isl_space_free(dim);
+ p = isl_printer_print_str(p, s_open_set[0]);
+ isl_union_map_foreach_map(umap, &print_map_body, &data);
+ p = data.p;
+ p = isl_printer_print_str(p, s_close_set[0]);
+ return p;
+}
+
+static int print_latex_map_body(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *)user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, " \\cup ");
+ data->first = 0;
+
+ data->p = isl_map_print_latex(map, data->p);
+ isl_map_free(map);
+
+ return 0;
+}
+
+static __isl_give isl_printer *isl_union_map_print_latex(
+ __isl_keep isl_union_map *umap, __isl_take isl_printer *p)
+{
+ struct isl_union_print_data data = { p, 1 };
+ isl_union_map_foreach_map(umap, &print_latex_map_body, &data);
+ p = data.p;
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
+ __isl_keep isl_union_map *umap)
+{
+ if (!p || !umap)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_union_map_print_isl(umap, p);
+ if (p->output_format == ISL_FORMAT_LATEX)
+ return isl_union_map_print_latex(umap, p);
+
+ isl_die(p->ctx, isl_error_invalid,
+ "invalid output format for isl_union_map", goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
+ __isl_keep isl_union_set *uset)
+{
+ if (!p || !uset)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_union_map_print_isl((isl_union_map *)uset, p);
+ if (p->output_format == ISL_FORMAT_LATEX)
+ return isl_union_map_print_latex((isl_union_map *)uset, p);
+
+ isl_die(p->ctx, isl_error_invalid,
+ "invalid output format for isl_union_set", goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_map_print(__isl_keep isl_map *map, FILE *out, int indent,
+ unsigned output_format)
+{
+ isl_printer *printer;
+
+ if (!map)
+ return;
+
+ printer = isl_printer_to_file(map->ctx, out);
+ printer = isl_printer_set_indent(printer, indent);
+ printer = isl_printer_set_output_format(printer, output_format);
+ printer = isl_printer_print_map(printer, map);
+
+ isl_printer_free(printer);
+}
+
+static int upoly_rec_n_non_zero(__isl_keep struct isl_upoly_rec *rec)
+{
+ int i;
+ int n;
+
+ for (i = 0, n = 0; i < rec->n; ++i)
+ if (!isl_upoly_is_zero(rec->p[i]))
+ ++n;
+
+ return n;
+}
+
+static __isl_give isl_printer *upoly_print_cst(__isl_keep struct isl_upoly *up,
+ __isl_take isl_printer *p, int first)
+{
+ struct isl_upoly_cst *cst;
+ int neg;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ goto error;
+ neg = !first && isl_int_is_neg(cst->n);
+ if (!first)
+ p = isl_printer_print_str(p, neg ? " - " : " + ");
+ if (neg)
+ isl_int_neg(cst->n, cst->n);
+ if (isl_int_is_zero(cst->d)) {
+ int sgn = isl_int_sgn(cst->n);
+ p = isl_printer_print_str(p, sgn < 0 ? "-infty" :
+ sgn == 0 ? "NaN" : "infty");
+ } else
+ p = isl_printer_print_isl_int(p, cst->n);
+ if (neg)
+ isl_int_neg(cst->n, cst->n);
+ if (!isl_int_is_zero(cst->d) && !isl_int_is_one(cst->d)) {
+ p = isl_printer_print_str(p, "/");
+ p = isl_printer_print_isl_int(p, cst->d);
+ }
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_base(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_mat *div, int var)
+{
+ unsigned total;
+
+ total = isl_space_dim(dim, isl_dim_all);
+ if (var < total)
+ p = print_term(dim, NULL, dim->ctx->one, 1 + var, p, 0);
+ else
+ p = print_div(dim, div, var - total, p);
+ return p;
+}
+
+static __isl_give isl_printer *print_pow(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_mat *div, int var, int exp)
+{
+ p = print_base(p, dim, div, var);
+ if (exp == 1)
+ return p;
+ if (p->output_format == ISL_FORMAT_C) {
+ int i;
+ for (i = 1; i < exp; ++i) {
+ p = isl_printer_print_str(p, "*");
+ p = print_base(p, dim, div, var);
+ }
+ } else {
+ p = isl_printer_print_str(p, "^");
+ p = isl_printer_print_int(p, exp);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *upoly_print(__isl_keep struct isl_upoly *up,
+ __isl_keep isl_space *dim, __isl_keep isl_mat *div,
+ __isl_take isl_printer *p, int outer)
+{
+ int i, n, first, print_parens;
+ struct isl_upoly_rec *rec;
+
+ if (!p || !up || !dim || !div)
+ goto error;
+
+ if (isl_upoly_is_cst(up))
+ return upoly_print_cst(up, p, 1);
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+ n = upoly_rec_n_non_zero(rec);
+ print_parens = n > 1 ||
+ (outer && rec->up.var >= isl_space_dim(dim, isl_dim_all));
+ if (print_parens)
+ p = isl_printer_print_str(p, "(");
+ for (i = 0, first = 1; i < rec->n; ++i) {
+ if (isl_upoly_is_zero(rec->p[i]))
+ continue;
+ if (isl_upoly_is_negone(rec->p[i])) {
+ if (!i)
+ p = isl_printer_print_str(p, "-1");
+ else if (first)
+ p = isl_printer_print_str(p, "-");
+ else
+ p = isl_printer_print_str(p, " - ");
+ } else if (isl_upoly_is_cst(rec->p[i]) &&
+ !isl_upoly_is_one(rec->p[i]))
+ p = upoly_print_cst(rec->p[i], p, first);
+ else {
+ if (!first)
+ p = isl_printer_print_str(p, " + ");
+ if (i == 0 || !isl_upoly_is_one(rec->p[i]))
+ p = upoly_print(rec->p[i], dim, div, p, 0);
+ }
+ first = 0;
+ if (i == 0)
+ continue;
+ if (!isl_upoly_is_one(rec->p[i]) &&
+ !isl_upoly_is_negone(rec->p[i]))
+ p = isl_printer_print_str(p, " * ");
+ p = print_pow(p, dim, div, rec->up.var, i);
+ }
+ if (print_parens)
+ p = isl_printer_print_str(p, ")");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_qpolynomial(__isl_take isl_printer *p,
+ __isl_keep isl_qpolynomial *qp)
+{
+ if (!p || !qp)
+ goto error;
+ p = upoly_print(qp->upoly, qp->dim, qp->div, p, 1);
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_qpolynomial_isl(__isl_take isl_printer *p,
+ __isl_keep isl_qpolynomial *qp)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!p || !qp)
+ goto error;
+
+ if (isl_space_dim(qp->dim, isl_dim_param) > 0) {
+ p = print_tuple(qp->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ if (!isl_space_is_params(qp->dim)) {
+ p = print_space(qp->dim, p, 0, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = print_qpolynomial(p, qp);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_qpolynomial_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_qpolynomial *qp)
+{
+ isl_int den;
+
+ isl_int_init(den);
+ isl_qpolynomial_get_den(qp, &den);
+ if (!isl_int_is_one(den)) {
+ isl_qpolynomial *f;
+ p = isl_printer_print_str(p, "(");
+ qp = isl_qpolynomial_copy(qp);
+ f = isl_qpolynomial_rat_cst_on_domain(isl_space_copy(qp->dim),
+ den, qp->dim->ctx->one);
+ qp = isl_qpolynomial_mul(qp, f);
+ }
+ if (qp)
+ p = upoly_print(qp->upoly, dim, qp->div, p, 0);
+ else
+ p = isl_printer_free(p);
+ if (!isl_int_is_one(den)) {
+ p = isl_printer_print_str(p, ")/");
+ p = isl_printer_print_isl_int(p, den);
+ isl_qpolynomial_free(qp);
+ }
+ isl_int_clear(den);
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp)
+{
+ if (!p || !qp)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_qpolynomial_isl(p, qp);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_qpolynomial_c(p, qp->dim, qp);
+ else
+ isl_die(qp->dim->ctx, isl_error_unsupported,
+ "output format not supported for isl_qpolynomials",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
+ unsigned output_format)
+{
+ isl_printer *p;
+
+ if (!qp)
+ return;
+
+ isl_assert(qp->dim->ctx, output_format == ISL_FORMAT_ISL, return);
+ p = isl_printer_to_file(qp->dim->ctx, out);
+ p = isl_printer_print_qpolynomial(p, qp);
+ isl_printer_free(p);
+}
+
+static __isl_give isl_printer *qpolynomial_fold_print(
+ __isl_keep isl_qpolynomial_fold *fold, __isl_take isl_printer *p)
+{
+ int i;
+
+ if (fold->type == isl_fold_min)
+ p = isl_printer_print_str(p, "min");
+ else if (fold->type == isl_fold_max)
+ p = isl_printer_print_str(p, "max");
+ p = isl_printer_print_str(p, "(");
+ for (i = 0; i < fold->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, ", ");
+ p = print_qpolynomial(p, fold->qp[i]);
+ }
+ p = isl_printer_print_str(p, ")");
+ return p;
+}
+
+void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold,
+ FILE *out, unsigned output_format)
+{
+ isl_printer *p;
+
+ if (!fold)
+ return;
+
+ isl_assert(fold->dim->ctx, output_format == ISL_FORMAT_ISL, return);
+
+ p = isl_printer_to_file(fold->dim->ctx, out);
+ p = isl_printer_print_qpolynomial_fold(p, fold);
+
+ isl_printer_free(p);
+}
+
+static __isl_give isl_printer *isl_pwqp_print_isl_body(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
+{
+ struct isl_print_space_data data = { 0 };
+ int i = 0;
+
+ for (i = 0; i < pwqp->n; ++i) {
+ 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);
+ 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);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *print_pw_qpolynomial_isl(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!p || !pwqp)
+ goto error;
+
+ if (isl_space_dim(pwqp->dim, isl_dim_param) > 0) {
+ p = print_tuple(pwqp->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ if (pwqp->n == 0) {
+ if (!isl_space_is_set(pwqp->dim)) {
+ p = print_tuple(pwqp->dim, p, isl_dim_in, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "0");
+ }
+ p = isl_pwqp_print_isl_body(p, pwqp);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
+ unsigned output_format)
+{
+ isl_printer *p;
+
+ if (!pwqp)
+ return;
+
+ p = isl_printer_to_file(pwqp->dim->ctx, out);
+ p = isl_printer_set_output_format(p, output_format);
+ p = isl_printer_print_pw_qpolynomial(p, pwqp);
+
+ isl_printer_free(p);
+}
+
+static __isl_give isl_printer *isl_pwf_print_isl_body(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ struct isl_print_space_data data = { 0 };
+ int i = 0;
+
+ for (i = 0; i < pwf->n; ++i) {
+ 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);
+ 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);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *print_pw_qpolynomial_fold_isl(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (isl_space_dim(pwf->dim, isl_dim_param) > 0) {
+ p = print_tuple(pwf->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ if (pwf->n == 0) {
+ if (!isl_space_is_set(pwf->dim)) {
+ p = print_tuple(pwf->dim, p, isl_dim_in, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "0");
+ }
+ p = isl_pwf_print_isl_body(p, pwf);
+ p = isl_printer_print_str(p, " }");
+ return p;
+}
+
+static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c);
+
+static __isl_give isl_printer *print_name_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim,
+ __isl_keep isl_basic_set *bset, enum isl_dim_type type, unsigned pos)
+{
+ if (type == isl_dim_div) {
+ p = isl_printer_print_str(p, "floord(");
+ p = print_affine_c(p, dim, bset, bset->div[pos] + 1);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_isl_int(p, bset->div[pos][0]);
+ p = isl_printer_print_str(p, ")");
+ } else {
+ const char *name;
+
+ name = isl_space_get_dim_name(dim, type, pos);
+ if (!name)
+ name = "UNNAMED";
+ p = isl_printer_print_str(p, name);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *print_term_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim,
+ __isl_keep isl_basic_set *bset, isl_int c, unsigned pos)
+{
+ enum isl_dim_type type;
+
+ if (pos == 0)
+ return isl_printer_print_isl_int(p, c);
+
+ if (isl_int_is_one(c))
+ ;
+ else if (isl_int_is_negone(c))
+ p = isl_printer_print_str(p, "-");
+ else {
+ p = isl_printer_print_isl_int(p, c);
+ p = isl_printer_print_str(p, "*");
+ }
+ type = pos2type(dim, &pos);
+ p = print_name_c(p, dim, bset, type, pos);
+ return p;
+}
+
+static __isl_give isl_printer *print_partial_affine_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim,
+ __isl_keep isl_basic_set *bset, isl_int *c, unsigned len)
+{
+ int i;
+ int first;
+
+ for (i = 0, first = 1; i < len; ++i) {
+ int flip = 0;
+ if (isl_int_is_zero(c[i]))
+ continue;
+ if (!first) {
+ if (isl_int_is_neg(c[i])) {
+ flip = 1;
+ isl_int_neg(c[i], c[i]);
+ p = isl_printer_print_str(p, " - ");
+ } else
+ p = isl_printer_print_str(p, " + ");
+ }
+ first = 0;
+ p = print_term_c(p, dim, bset, c[i], i);
+ if (flip)
+ isl_int_neg(c[i], c[i]);
+ }
+ if (first)
+ p = isl_printer_print_str(p, "0");
+ return p;
+}
+
+static __isl_give isl_printer *print_affine_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset, isl_int *c)
+{
+ unsigned len = 1 + isl_basic_set_total_dim(bset);
+ return print_partial_affine_c(p, dim, bset, c, len);
+}
+
+/* We skip the constraint if it is implied by the div expression.
+ *
+ * *first indicates whether this is the first constraint in the conjunction and
+ * is updated if the constraint is actually printed.
+ */
+static __isl_give isl_printer *print_constraint_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim,
+ __isl_keep isl_basic_set *bset, isl_int *c, const char *op, int *first)
+{
+ unsigned o_div;
+ unsigned n_div;
+ int div;
+
+ o_div = isl_basic_set_offset(bset, isl_dim_div);
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+ div = isl_seq_last_non_zero(c + o_div, n_div);
+ if (div >= 0 && isl_basic_set_is_div_constraint(bset, c, div))
+ return p;
+
+ if (!*first)
+ p = isl_printer_print_str(p, " && ");
+
+ p = print_affine_c(p, dim, bset, c);
+ p = isl_printer_print_str(p, " ");
+ p = isl_printer_print_str(p, op);
+ p = isl_printer_print_str(p, " 0");
+
+ *first = 0;
+
+ return p;
+}
+
+static __isl_give isl_printer *print_basic_set_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_basic_set *bset)
+{
+ int i, j;
+ int first = 1;
+ unsigned n_div = isl_basic_set_dim(bset, isl_dim_div);
+ unsigned total = isl_basic_set_total_dim(bset) - n_div;
+
+ for (i = 0; i < bset->n_eq; ++i) {
+ j = isl_seq_last_non_zero(bset->eq[i] + 1 + total, n_div);
+ if (j < 0)
+ p = print_constraint_c(p, dim, bset,
+ bset->eq[i], "==", &first);
+ else {
+ if (i)
+ p = isl_printer_print_str(p, " && ");
+ p = isl_printer_print_str(p, "(");
+ p = print_partial_affine_c(p, dim, bset, bset->eq[i],
+ 1 + total + j);
+ p = isl_printer_print_str(p, ") % ");
+ p = isl_printer_print_isl_int(p,
+ bset->eq[i][1 + total + j]);
+ p = isl_printer_print_str(p, " == 0");
+ first = 0;
+ }
+ }
+ for (i = 0; i < bset->n_ineq; ++i)
+ p = print_constraint_c(p, dim, bset, bset->ineq[i], ">=",
+ &first);
+ return p;
+}
+
+static __isl_give isl_printer *print_set_c(__isl_take isl_printer *p,
+ __isl_keep isl_space *dim, __isl_keep isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return isl_printer_free(p);
+
+ if (set->n == 0)
+ p = isl_printer_print_str(p, "0");
+
+ for (i = 0; i < set->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, " || ");
+ if (set->n > 1)
+ p = isl_printer_print_str(p, "(");
+ p = print_basic_set_c(p, dim, set->p[i]);
+ if (set->n > 1)
+ p = isl_printer_print_str(p, ")");
+ }
+ return p;
+}
+
+static __isl_give isl_printer *print_pw_qpolynomial_c(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
+{
+ int i;
+
+ if (pwqp->n == 1 && isl_set_plain_is_universe(pwqp->p[0].set))
+ return print_qpolynomial_c(p, pwqp->dim, pwqp->p[0].qp);
+
+ for (i = 0; i < pwqp->n; ++i) {
+ p = isl_printer_print_str(p, "(");
+ p = print_set_c(p, pwqp->dim, pwqp->p[i].set);
+ p = isl_printer_print_str(p, ") ? (");
+ p = print_qpolynomial_c(p, pwqp->dim, pwqp->p[i].qp);
+ p = isl_printer_print_str(p, ") : ");
+ }
+
+ p = isl_printer_print_str(p, "0");
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp)
+{
+ if (!p || !pwqp)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_pw_qpolynomial_isl(p, pwqp);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_pw_qpolynomial_c(p, pwqp);
+ isl_assert(p->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static int print_pwqp_body(__isl_take isl_pw_qpolynomial *pwqp, void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *)user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, "; ");
+ data->first = 0;
+
+ data->p = isl_pwqp_print_isl_body(data->p, pwqp);
+ isl_pw_qpolynomial_free(pwqp);
+
+ return 0;
+}
+
+static __isl_give isl_printer *print_union_pw_qpolynomial_isl(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
+{
+ struct isl_union_print_data data = { p, 1 };
+ struct isl_print_space_data space_data = { 0 };
+ isl_space *dim;
+
+ dim = isl_union_pw_qpolynomial_get_space(upwqp);
+ if (isl_space_dim(dim, isl_dim_param) > 0) {
+ p = print_tuple(dim, p, isl_dim_param, &space_data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ isl_space_free(dim);
+ p = isl_printer_print_str(p, "{ ");
+ isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp, &print_pwqp_body,
+ &data);
+ p = data.p;
+ p = isl_printer_print_str(p, " }");
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp)
+{
+ if (!p || !upwqp)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_union_pw_qpolynomial_isl(p, upwqp);
+ isl_die(p->ctx, isl_error_invalid,
+ "invalid output format for isl_union_pw_qpolynomial",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_qpolynomial_fold_c(
+ __isl_take isl_printer *p, __isl_keep isl_space *dim,
+ __isl_keep isl_qpolynomial_fold *fold)
+{
+ int i;
+
+ for (i = 0; i < fold->n - 1; ++i)
+ if (fold->type == isl_fold_min)
+ p = isl_printer_print_str(p, "min(");
+ else if (fold->type == isl_fold_max)
+ p = isl_printer_print_str(p, "max(");
+
+ for (i = 0; i < fold->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, ", ");
+ p = print_qpolynomial_c(p, dim, fold->qp[i]);
+ if (i)
+ p = isl_printer_print_str(p, ")");
+ }
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_qpolynomial_fold(
+ __isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold)
+{
+ if (!p || !fold)
+ goto error;
+ if (p->output_format == ISL_FORMAT_ISL)
+ return qpolynomial_fold_print(fold, p);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_qpolynomial_fold_c(p, fold->dim, fold);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_pw_qpolynomial_fold_c(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ int i;
+
+ if (pwf->n == 1 && isl_set_plain_is_universe(pwf->p[0].set))
+ return print_qpolynomial_fold_c(p, pwf->dim, pwf->p[0].fold);
+
+ for (i = 0; i < pwf->n; ++i) {
+ p = isl_printer_print_str(p, "(");
+ p = print_set_c(p, pwf->dim, pwf->p[i].set);
+ p = isl_printer_print_str(p, ") ? (");
+ p = print_qpolynomial_fold_c(p, pwf->dim, pwf->p[i].fold);
+ p = isl_printer_print_str(p, ") : ");
+ }
+
+ p = isl_printer_print_str(p, "0");
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
+ __isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf)
+{
+ if (!p || !pwf)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_pw_qpolynomial_fold_isl(p, pwf);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_pw_qpolynomial_fold_c(p, pwf);
+ isl_assert(p->ctx, 0, goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
+ FILE *out, unsigned output_format)
+{
+ isl_printer *p;
+
+ if (!pwf)
+ return;
+
+ p = isl_printer_to_file(pwf->dim->ctx, out);
+ p = isl_printer_set_output_format(p, output_format);
+ p = isl_printer_print_pw_qpolynomial_fold(p, pwf);
+
+ isl_printer_free(p);
+}
+
+static int print_pwf_body(__isl_take isl_pw_qpolynomial_fold *pwf, void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *)user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, "; ");
+ data->first = 0;
+
+ data->p = isl_pwf_print_isl_body(data->p, pwf);
+ isl_pw_qpolynomial_fold_free(pwf);
+
+ return 0;
+}
+
+static __isl_give isl_printer *print_union_pw_qpolynomial_fold_isl(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf)
+{
+ struct isl_union_print_data data = { p, 1 };
+ struct isl_print_space_data space_data = { 0 };
+ isl_space *dim;
+
+ dim = isl_union_pw_qpolynomial_fold_get_space(upwf);
+ if (isl_space_dim(dim, isl_dim_param) > 0) {
+ p = print_tuple(dim, p, isl_dim_param, &space_data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ isl_space_free(dim);
+ p = isl_printer_print_str(p, "{ ");
+ isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(upwf,
+ &print_pwf_body, &data);
+ p = data.p;
+ p = isl_printer_print_str(p, " }");
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf)
+{
+ if (!p || !upwf)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_union_pw_qpolynomial_fold_isl(p, upwf);
+ isl_die(p->ctx, isl_error_invalid,
+ "invalid output format for isl_union_pw_qpolynomial_fold",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,
+ __isl_keep isl_constraint *c)
+{
+ isl_basic_map *bmap;
+
+ if (!p || !c)
+ goto error;
+
+ bmap = isl_basic_map_from_constraint(isl_constraint_copy(c));
+ p = isl_printer_print_basic_map(p, bmap);
+ isl_basic_map_free(bmap);
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *isl_printer_print_space_isl(
+ __isl_take isl_printer *p, __isl_keep isl_space *dim)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!dim)
+ goto error;
+
+ if (isl_space_dim(dim, isl_dim_param) > 0) {
+ p = print_tuple(dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+
+ p = isl_printer_print_str(p, "{ ");
+ if (isl_space_is_params(dim))
+ p = isl_printer_print_str(p, s_such_that[0]);
+ else
+ p = print_space(dim, p, 0, &data);
+ p = isl_printer_print_str(p, " }");
+
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
+ __isl_keep isl_space *space)
+{
+ if (!p || !space)
+ return isl_printer_free(p);
+ if (p->output_format == ISL_FORMAT_ISL)
+ return isl_printer_print_space_isl(p, space);
+ else if (p->output_format == ISL_FORMAT_OMEGA)
+ return print_omega_parameters(space, p);
+
+ isl_die(isl_space_get_ctx(space), isl_error_unsupported,
+ "output format not supported for space",
+ return isl_printer_free(p));
+}
+
+__isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls)
+{
+ struct isl_print_space_data data = { 0 };
+ unsigned total;
+ unsigned n_div;
+
+ if (!ls)
+ goto error;
+
+ total = isl_local_space_dim(ls, isl_dim_all);
+ if (isl_local_space_dim(ls, isl_dim_param) > 0) {
+ p = print_tuple(ls->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ p = 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);
+ } else if (isl_space_is_params(ls->dim))
+ p = isl_printer_print_str(p, s_such_that[0]);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_aff_body(__isl_take isl_printer *p,
+ __isl_keep isl_aff *aff)
+{
+ unsigned total;
+
+ if (isl_aff_is_nan(aff))
+ return isl_printer_print_str(p, "NaN");
+
+ total = isl_local_space_dim(aff->ls, isl_dim_all);
+ p = isl_printer_print_str(p, "(");
+ p = print_affine_of_len(aff->ls->dim, aff->ls->div, p,
+ aff->v->el + 1, 1 + total);
+ if (isl_int_is_one(aff->v->el[0]))
+ p = isl_printer_print_str(p, ")");
+ else {
+ p = isl_printer_print_str(p, ")/");
+ p = isl_printer_print_isl_int(p, aff->v->el[0]);
+ }
+
+ return p;
+}
+
+static __isl_give isl_printer *print_aff(__isl_take isl_printer *p,
+ __isl_keep isl_aff *aff)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (isl_space_is_params(aff->ls->dim))
+ ;
+ else {
+ p = print_tuple(aff->ls->dim, p, isl_dim_set, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "[");
+ p = print_aff_body(p, aff);
+ p = isl_printer_print_str(p, "]");
+
+ return p;
+}
+
+static __isl_give isl_printer *print_aff_isl(__isl_take isl_printer *p,
+ __isl_keep isl_aff *aff)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!aff)
+ goto error;
+
+ if (isl_local_space_dim(aff->ls, isl_dim_param) > 0) {
+ p = print_tuple(aff->ls->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ p = print_aff(p, aff);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
+ __isl_keep isl_pw_aff *pwaff)
+{
+ struct isl_print_space_data data = { 0 };
+ int i;
+
+ if (!pwaff)
+ goto error;
+
+ if (isl_space_dim(pwaff->dim, isl_dim_param) > 0) {
+ p = print_tuple(pwaff->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ for (i = 0; i < pwaff->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, "; ");
+ p = print_aff(p, pwaff->p[i].aff);
+ p = print_disjuncts((isl_map *)pwaff->p[i].set, p, 0);
+ }
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls, isl_int *c);
+
+static __isl_give isl_printer *print_ls_name_c(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls, enum isl_dim_type type, unsigned pos)
+{
+ if (type == isl_dim_div) {
+ p = isl_printer_print_str(p, "floord(");
+ p = print_ls_affine_c(p, ls, ls->div->row[pos] + 1);
+ p = isl_printer_print_str(p, ", ");
+ p = isl_printer_print_isl_int(p, ls->div->row[pos][0]);
+ p = isl_printer_print_str(p, ")");
+ } else {
+ const char *name;
+
+ name = isl_space_get_dim_name(ls->dim, type, pos);
+ if (!name)
+ name = "UNNAMED";
+ p = isl_printer_print_str(p, name);
+ }
+ return p;
+}
+
+static __isl_give isl_printer *print_ls_term_c(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls, isl_int c, unsigned pos)
+{
+ enum isl_dim_type type;
+
+ if (pos == 0)
+ return isl_printer_print_isl_int(p, c);
+
+ if (isl_int_is_one(c))
+ ;
+ else if (isl_int_is_negone(c))
+ p = isl_printer_print_str(p, "-");
+ else {
+ p = isl_printer_print_isl_int(p, c);
+ p = isl_printer_print_str(p, "*");
+ }
+ type = pos2type(ls->dim, &pos);
+ p = print_ls_name_c(p, ls, type, pos);
+ return p;
+}
+
+static __isl_give isl_printer *print_ls_partial_affine_c(
+ __isl_take isl_printer *p, __isl_keep isl_local_space *ls,
+ isl_int *c, unsigned len)
+{
+ int i;
+ int first;
+
+ for (i = 0, first = 1; i < len; ++i) {
+ int flip = 0;
+ if (isl_int_is_zero(c[i]))
+ continue;
+ if (!first) {
+ if (isl_int_is_neg(c[i])) {
+ flip = 1;
+ isl_int_neg(c[i], c[i]);
+ p = isl_printer_print_str(p, " - ");
+ } else
+ p = isl_printer_print_str(p, " + ");
+ }
+ first = 0;
+ p = print_ls_term_c(p, ls, c[i], i);
+ if (flip)
+ isl_int_neg(c[i], c[i]);
+ }
+ if (first)
+ p = isl_printer_print_str(p, "0");
+ return p;
+}
+
+static __isl_give isl_printer *print_ls_affine_c(__isl_take isl_printer *p,
+ __isl_keep isl_local_space *ls, isl_int *c)
+{
+ unsigned len = 1 + isl_local_space_dim(ls, isl_dim_all);
+ return print_ls_partial_affine_c(p, ls, c, len);
+}
+
+static __isl_give isl_printer *print_aff_c(__isl_take isl_printer *p,
+ __isl_keep isl_aff *aff)
+{
+ unsigned total;
+
+ total = isl_local_space_dim(aff->ls, isl_dim_all);
+ if (!isl_int_is_one(aff->v->el[0]))
+ p = isl_printer_print_str(p, "(");
+ p = print_ls_partial_affine_c(p, aff->ls, aff->v->el + 1, 1 + total);
+ if (!isl_int_is_one(aff->v->el[0])) {
+ p = isl_printer_print_str(p, ")/");
+ p = isl_printer_print_isl_int(p, aff->v->el[0]);
+ }
+ return p;
+}
+
+/* In the C format, we cannot express that "pwaff" may be undefined
+ * on parts of the domain space. We therefore assume that the expression
+ * will only be evaluated on its definition domain and compute the gist
+ * of each cell with respect to this domain.
+ */
+static __isl_give isl_printer *print_pw_aff_c(__isl_take isl_printer *p,
+ __isl_keep isl_pw_aff *pwaff)
+{
+ isl_set *domain;
+ isl_ast_build *build;
+ isl_ast_expr *expr;
+
+ if (pwaff->n < 1)
+ isl_die(p->ctx, isl_error_unsupported,
+ "cannot print empty isl_pw_aff in C format",
+ return isl_printer_free(p));
+
+ domain = isl_pw_aff_domain(isl_pw_aff_copy(pwaff));
+ build = isl_ast_build_from_context(domain);
+ expr = isl_ast_build_expr_from_pw_aff(build, isl_pw_aff_copy(pwaff));
+ p = isl_printer_print_ast_expr(p, expr);
+ isl_ast_expr_free(expr);
+ isl_ast_build_free(build);
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
+ __isl_keep isl_aff *aff)
+{
+ if (!p || !aff)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_aff_isl(p, aff);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_aff_c(p, aff);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,
+ __isl_keep isl_pw_aff *pwaff)
+{
+ if (!p || !pwaff)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_pw_aff_isl(p, pwaff);
+ else if (p->output_format == ISL_FORMAT_C)
+ return print_pw_aff_c(p, pwaff);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_multi_aff.
+ *
+ * If the current dimension is an output dimension, then print
+ * the corresponding expression. Otherwise, print the name of the dimension.
+ */
+static __isl_give isl_printer *print_dim_ma(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ isl_multi_aff *ma = data->user;
+
+ if (data->type == isl_dim_out)
+ p = print_aff_body(p, ma->p[pos]);
+ else
+ p = print_name(data->space, p, data->type, pos, data->latex);
+
+ return p;
+}
+
+static __isl_give isl_printer *print_multi_aff(__isl_take isl_printer *p,
+ __isl_keep isl_multi_aff *maff)
+{
+ struct isl_print_space_data data = { 0 };
+
+ data.print_dim = &print_dim_ma;
+ data.user = maff;
+ return print_space(maff->space, p, 0, &data);
+}
+
+static __isl_give isl_printer *print_multi_aff_isl(__isl_take isl_printer *p,
+ __isl_keep isl_multi_aff *maff)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!maff)
+ goto error;
+
+ if (isl_space_dim(maff->space, isl_dim_param) > 0) {
+ p = print_tuple(maff->space, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ p = print_multi_aff(p, maff);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
+ __isl_keep isl_multi_aff *maff)
+{
+ if (!p || !maff)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_multi_aff_isl(p, maff);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_body(
+ __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+ int i;
+
+ if (!pma)
+ goto error;
+
+ for (i = 0; i < pma->n; ++i) {
+ 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);
+ }
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_isl(__isl_take isl_printer *p,
+ __isl_keep isl_pw_multi_aff *pma)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!pma)
+ goto error;
+
+ if (isl_space_dim(pma->dim, isl_dim_param) > 0) {
+ p = print_tuple(pma->dim, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, " -> ");
+ }
+ p = isl_printer_print_str(p, "{ ");
+ p = print_pw_multi_aff_body(p, pma);
+ p = isl_printer_print_str(p, " }");
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *print_unnamed_pw_multi_aff_c(
+ __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+ int i;
+
+ for (i = 0; i < pma->n - 1; ++i) {
+ p = isl_printer_print_str(p, "(");
+ p = print_set_c(p, pma->dim, pma->p[i].set);
+ p = isl_printer_print_str(p, ") ? (");
+ p = print_aff_c(p, pma->p[i].maff->p[0]);
+ p = isl_printer_print_str(p, ") : ");
+ }
+
+ return print_aff_c(p, pma->p[pma->n - 1].maff->p[0]);
+}
+
+static __isl_give isl_printer *print_pw_multi_aff_c(__isl_take isl_printer *p,
+ __isl_keep isl_pw_multi_aff *pma)
+{
+ int n;
+ const char *name;
+
+ if (!pma)
+ goto error;
+ if (pma->n < 1)
+ isl_die(p->ctx, isl_error_unsupported,
+ "cannot print empty isl_pw_multi_aff in C format",
+ goto error);
+ name = isl_pw_multi_aff_get_tuple_name(pma, isl_dim_out);
+ if (!name && isl_pw_multi_aff_dim(pma, isl_dim_out) == 1)
+ return print_unnamed_pw_multi_aff_c(p, pma);
+ if (!name)
+ isl_die(p->ctx, isl_error_unsupported,
+ "cannot print unnamed isl_pw_multi_aff in C format",
+ goto error);
+
+ p = isl_printer_print_str(p, name);
+ n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+ if (n != 0)
+ isl_die(p->ctx, isl_error_unsupported,
+ "not supported yet", goto error);
+
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_pw_multi_aff(
+ __isl_take isl_printer *p, __isl_keep isl_pw_multi_aff *pma)
+{
+ if (!p || !pma)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_pw_multi_aff_isl(p, pma);
+ if (p->output_format == ISL_FORMAT_C)
+ return print_pw_multi_aff_c(p, pma);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static int print_pw_multi_aff_body_wrap(__isl_take isl_pw_multi_aff *pma,
+ void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *) user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, "; ");
+ data->first = 0;
+
+ data->p = print_pw_multi_aff_body(data->p, pma);
+ isl_pw_multi_aff_free(pma);
+
+ return 0;
+}
+
+static __isl_give isl_printer *print_union_pw_multi_aff_isl(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
+{
+ struct isl_union_print_data data = { p, 1 };
+ struct isl_print_space_data space_data = { 0 };
+ isl_space *space;
+
+ space = isl_union_pw_multi_aff_get_space(upma);
+ if (isl_space_dim(space, isl_dim_param) > 0) {
+ p = print_tuple(space, p, isl_dim_param, &space_data);
+ p = isl_printer_print_str(p, s_to[0]);
+ }
+ isl_space_free(space);
+ p = isl_printer_print_str(p, s_open_set[0]);
+ isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &print_pw_multi_aff_body_wrap, &data);
+ p = data.p;
+ p = isl_printer_print_str(p, s_close_set[0]);
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_multi_aff *upma)
+{
+ if (!p || !upma)
+ goto error;
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_union_pw_multi_aff_isl(p, upma);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ goto error);
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_multi_pw_aff.
+ *
+ * If the current dimension is an output dimension, then print
+ * the corresponding piecewise affine expression.
+ * Otherwise, print the name of the dimension.
+ */
+static __isl_give isl_printer *print_dim_mpa(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ int i;
+ int need_parens;
+ isl_multi_pw_aff *mpa = data->user;
+ isl_pw_aff *pa;
+
+ if (data->type != isl_dim_out)
+ return print_name(data->space, p, data->type, pos, data->latex);
+
+ pa = mpa->p[pos];
+ if (pa->n == 0)
+ return isl_printer_print_str(p, "(0 : 1 = 0)");
+
+ need_parens = pa->n != 1 || !isl_set_plain_is_universe(pa->p[0].set);
+ if (need_parens)
+ p = isl_printer_print_str(p, "(");
+ for (i = 0; i < pa->n; ++i) {
+ 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);
+ }
+ if (need_parens)
+ p = isl_printer_print_str(p, ")");
+
+ return p;
+}
+
+/* Print "mpa" to "p" in isl format.
+ */
+static __isl_give isl_printer *print_multi_pw_aff_isl(__isl_take isl_printer *p,
+ __isl_keep isl_multi_pw_aff *mpa)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!mpa)
+ return isl_printer_free(p);
+
+ if (isl_space_dim(mpa->space, isl_dim_param) > 0) {
+ p = print_tuple(mpa->space, p, isl_dim_param, &data);
+ p = isl_printer_print_str(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_printer_print_str(p, " }");
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_multi_pw_aff(
+ __isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa)
+{
+ if (!p || !mpa)
+ return isl_printer_free(p);
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_multi_pw_aff_isl(p, mpa);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ return isl_printer_free(p));
+}
+
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_multi_val.
+ *
+ * If the current dimension is an output dimension, then print
+ * the corresponding value. Otherwise, print the name of the dimension.
+ */
+static __isl_give isl_printer *print_dim_mv(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ isl_multi_val *mv = data->user;
+
+ if (data->type == isl_dim_out)
+ return isl_printer_print_val(p, mv->p[pos]);
+ else
+ return print_name(data->space, p, data->type, pos, data->latex);
+}
+
+/* Print the isl_multi_val "mv" to "p" in isl format.
+ */
+static __isl_give isl_printer *print_multi_val_isl(__isl_take isl_printer *p,
+ __isl_keep isl_multi_val *mv)
+{
+ struct isl_print_space_data data = { 0 };
+
+ if (!mv)
+ return isl_printer_free(p);
+
+ if (isl_space_dim(mv->space, isl_dim_param) > 0) {
+ p = print_tuple(mv->space, p, isl_dim_param, &data);
+ p = isl_printer_print_str(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_printer_print_str(p, " }");
+ return p;
+}
+
+/* Print the isl_multi_val "mv" to "p".
+ *
+ * Currently only supported in isl format.
+ */
+__isl_give isl_printer *isl_printer_print_multi_val(
+ __isl_take isl_printer *p, __isl_keep isl_multi_val *mv)
+{
+ if (!p || !mv)
+ return isl_printer_free(p);
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_multi_val_isl(p, mv);
+ isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
+ return isl_printer_free(p));
+}
diff --git a/polly/lib/External/isl/isl_point.c b/polly/lib/External/isl/isl_point.c
new file mode 100644
index 00000000000..f5320f2ede8
--- /dev/null
+++ b/polly/lib/External/isl/isl_point.c
@@ -0,0 +1,585 @@
+#include <isl_map_private.h>
+#include <isl_point_private.h>
+#include <isl/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/deprecated/point_int.h>
+
+isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt)
+{
+ return pnt ? isl_space_get_ctx(pnt->dim) : NULL;
+}
+
+__isl_give isl_space *isl_point_get_space(__isl_keep isl_point *pnt)
+{
+ return pnt ? isl_space_copy(pnt->dim) : NULL;
+}
+
+__isl_give isl_point *isl_point_alloc(__isl_take isl_space *dim,
+ __isl_take isl_vec *vec)
+{
+ struct isl_point *pnt;
+
+ if (!dim || !vec)
+ goto error;
+
+ if (vec->size > 1 + isl_space_dim(dim, isl_dim_all)) {
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ goto error;
+ vec->size = 1 + isl_space_dim(dim, isl_dim_all);
+ }
+
+ pnt = isl_alloc_type(dim->ctx, struct isl_point);
+ if (!pnt)
+ goto error;
+
+ pnt->ref = 1;
+ pnt->dim = dim;
+ pnt->vec = vec;
+
+ return pnt;
+error:
+ isl_space_free(dim);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_point *isl_point_zero(__isl_take isl_space *dim)
+{
+ isl_vec *vec;
+
+ if (!dim)
+ return NULL;
+ vec = isl_vec_alloc(dim->ctx, 1 + isl_space_dim(dim, isl_dim_all));
+ if (!vec)
+ goto error;
+ isl_int_set_si(vec->el[0], 1);
+ isl_seq_clr(vec->el + 1, vec->size - 1);
+ return isl_point_alloc(dim, vec);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_point *isl_point_dup(__isl_keep isl_point *pnt)
+{
+ struct isl_point *pnt2;
+
+ if (!pnt)
+ return NULL;
+ pnt2 = isl_point_alloc(isl_space_copy(pnt->dim), isl_vec_copy(pnt->vec));
+ return pnt2;
+}
+
+__isl_give isl_point *isl_point_cow(__isl_take isl_point *pnt)
+{
+ struct isl_point *pnt2;
+ if (!pnt)
+ return NULL;
+
+ if (pnt->ref == 1)
+ return pnt;
+
+ pnt2 = isl_point_dup(pnt);
+ isl_point_free(pnt);
+ return pnt2;
+}
+
+__isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt)
+{
+ if (!pnt)
+ return NULL;
+
+ pnt->ref++;
+ return pnt;
+}
+
+void isl_point_free(__isl_take isl_point *pnt)
+{
+ if (!pnt)
+ return;
+
+ if (--pnt->ref > 0)
+ return;
+
+ isl_space_free(pnt->dim);
+ isl_vec_free(pnt->vec);
+ free(pnt);
+}
+
+__isl_give isl_point *isl_point_void(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+
+ return isl_point_alloc(dim, isl_vec_alloc(dim->ctx, 0));
+}
+
+int isl_point_is_void(__isl_keep isl_point *pnt)
+{
+ if (!pnt)
+ return -1;
+
+ return pnt->vec->size == 0;
+}
+
+int isl_point_get_coordinate(__isl_keep isl_point *pnt,
+ enum isl_dim_type type, int pos, isl_int *v)
+{
+ if (!pnt || isl_point_is_void(pnt))
+ return -1;
+
+ if (pos < 0 || pos >= isl_space_dim(pnt->dim, type))
+ isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
+ "position out of bounds", return -1);
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(pnt->dim, isl_dim_param);
+ isl_int_set(*v, pnt->vec->el[1 + pos]);
+
+ return 0;
+}
+
+/* Return the value of coordinate "pos" of type "type" of "pnt".
+ */
+__isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
+ enum isl_dim_type type, int pos)
+{
+ isl_ctx *ctx;
+ isl_val *v;
+
+ if (!pnt)
+ return NULL;
+
+ ctx = isl_point_get_ctx(pnt);
+ if (isl_point_is_void(pnt))
+ isl_die(ctx, isl_error_invalid,
+ "void point does not have coordinates", return NULL);
+ if (pos < 0 || pos >= isl_space_dim(pnt->dim, type))
+ isl_die(ctx, isl_error_invalid,
+ "position out of bounds", return NULL);
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(pnt->dim, isl_dim_param);
+
+ v = isl_val_rat_from_isl_int(ctx, pnt->vec->el[1 + pos],
+ pnt->vec->el[0]);
+ return isl_val_normalize(v);
+}
+
+__isl_give isl_point *isl_point_set_coordinate(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, isl_int v)
+{
+ if (!pnt || isl_point_is_void(pnt))
+ return pnt;
+
+ pnt = isl_point_cow(pnt);
+ if (!pnt)
+ return NULL;
+ pnt->vec = isl_vec_cow(pnt->vec);
+ if (!pnt->vec)
+ goto error;
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(pnt->dim, isl_dim_param);
+
+ isl_int_set(pnt->vec->el[1 + pos], v);
+
+ return pnt;
+error:
+ isl_point_free(pnt);
+ return NULL;
+}
+
+/* Replace coordinate "pos" of type "type" of "pnt" by "v".
+ */
+__isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+ if (!pnt || !v)
+ goto error;
+ if (isl_point_is_void(pnt))
+ isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
+ "void point does not have coordinates", goto error);
+ if (pos < 0 || pos >= isl_space_dim(pnt->dim, type))
+ isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
+ "position out of bounds", goto error);
+ if (!isl_val_is_rat(v))
+ isl_die(isl_point_get_ctx(pnt), isl_error_invalid,
+ "expecting rational value", goto error);
+
+ if (isl_int_eq(pnt->vec->el[1 + pos], v->n) &&
+ isl_int_eq(pnt->vec->el[0], v->d)) {
+ isl_val_free(v);
+ return pnt;
+ }
+
+ pnt = isl_point_cow(pnt);
+ if (!pnt)
+ goto error;
+ pnt->vec = isl_vec_cow(pnt->vec);
+ if (!pnt->vec)
+ goto error;
+
+ if (isl_int_eq(pnt->vec->el[0], v->d)) {
+ isl_int_set(pnt->vec->el[1 + pos], v->n);
+ } else if (isl_int_is_one(v->d)) {
+ isl_int_mul(pnt->vec->el[1 + pos], pnt->vec->el[0], v->n);
+ } else {
+ isl_seq_scale(pnt->vec->el + 1,
+ pnt->vec->el + 1, v->d, pnt->vec->size - 1);
+ isl_int_mul(pnt->vec->el[1 + pos], pnt->vec->el[0], v->n);
+ isl_int_mul(pnt->vec->el[0], pnt->vec->el[0], v->d);
+ pnt->vec = isl_vec_normalize(pnt->vec);
+ if (!pnt->vec)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return pnt;
+error:
+ isl_val_free(v);
+ isl_point_free(pnt);
+ return NULL;
+}
+
+__isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val)
+{
+ if (!pnt || isl_point_is_void(pnt))
+ return pnt;
+
+ pnt = isl_point_cow(pnt);
+ if (!pnt)
+ return NULL;
+ pnt->vec = isl_vec_cow(pnt->vec);
+ if (!pnt->vec)
+ goto error;
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(pnt->dim, isl_dim_param);
+
+ isl_int_add_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
+
+ return pnt;
+error:
+ isl_point_free(pnt);
+ return NULL;
+}
+
+__isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
+ enum isl_dim_type type, int pos, unsigned val)
+{
+ if (!pnt || isl_point_is_void(pnt))
+ return pnt;
+
+ pnt = isl_point_cow(pnt);
+ if (!pnt)
+ return NULL;
+ pnt->vec = isl_vec_cow(pnt->vec);
+ if (!pnt->vec)
+ goto error;
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(pnt->dim, isl_dim_param);
+
+ isl_int_sub_ui(pnt->vec->el[1 + pos], pnt->vec->el[1 + pos], val);
+
+ return pnt;
+error:
+ isl_point_free(pnt);
+ return NULL;
+}
+
+struct isl_foreach_point {
+ struct isl_scan_callback callback;
+ int (*fn)(__isl_take isl_point *pnt, void *user);
+ void *user;
+ isl_space *dim;
+};
+
+static int foreach_point(struct isl_scan_callback *cb, __isl_take isl_vec *sample)
+{
+ struct isl_foreach_point *fp = (struct isl_foreach_point *)cb;
+ isl_point *pnt;
+
+ pnt = isl_point_alloc(isl_space_copy(fp->dim), sample);
+
+ return fp->fn(pnt, fp->user);
+}
+
+int isl_set_foreach_point(__isl_keep isl_set *set,
+ int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
+{
+ struct isl_foreach_point fp = { { &foreach_point }, fn, user };
+ int i;
+
+ if (!set)
+ return -1;
+
+ fp.dim = isl_set_get_space(set);
+ if (!fp.dim)
+ return -1;
+
+ set = isl_set_copy(set);
+ set = isl_set_cow(set);
+ set = isl_set_make_disjoint(set);
+ set = isl_set_compute_divs(set);
+ if (!set)
+ goto error;
+
+ for (i = 0; i < set->n; ++i)
+ if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
+ &fp.callback) < 0)
+ goto error;
+
+ isl_set_free(set);
+ isl_space_free(fp.dim);
+
+ return 0;
+error:
+ isl_set_free(set);
+ isl_space_free(fp.dim);
+ return -1;
+}
+
+/* Return 1 if "bmap" contains the point "point".
+ * "bmap" is assumed to have known divs.
+ * The point is first extended with the divs and then passed
+ * to basic_map_contains.
+ */
+int isl_basic_map_contains_point(__isl_keep isl_basic_map *bmap,
+ __isl_keep isl_point *point)
+{
+ int i;
+ struct isl_vec *vec;
+ unsigned dim;
+ int contains;
+
+ if (!bmap || !point)
+ return -1;
+ isl_assert(bmap->ctx, isl_space_is_equal(bmap->dim, point->dim), return -1);
+ if (bmap->n_div == 0)
+ return isl_basic_map_contains(bmap, point->vec);
+
+ dim = isl_basic_map_total_dim(bmap) - bmap->n_div;
+ vec = isl_vec_alloc(bmap->ctx, 1 + dim + bmap->n_div);
+ if (!vec)
+ return -1;
+
+ isl_seq_cpy(vec->el, point->vec->el, point->vec->size);
+ for (i = 0; i < bmap->n_div; ++i) {
+ isl_seq_inner_product(bmap->div[i] + 1, vec->el,
+ 1 + dim + i, &vec->el[1+dim+i]);
+ isl_int_fdiv_q(vec->el[1+dim+i], vec->el[1+dim+i],
+ bmap->div[i][0]);
+ }
+
+ contains = isl_basic_map_contains(bmap, vec);
+
+ isl_vec_free(vec);
+ return contains;
+}
+
+int isl_map_contains_point(__isl_keep isl_map *map, __isl_keep isl_point *point)
+{
+ int i;
+ int found = 0;
+
+ if (!map || !point)
+ return -1;
+
+ map = isl_map_copy(map);
+ map = isl_map_compute_divs(map);
+ if (!map)
+ return -1;
+
+ for (i = 0; i < map->n; ++i) {
+ found = isl_basic_map_contains_point(map->p[i], point);
+ if (found < 0)
+ goto error;
+ if (found)
+ break;
+ }
+ isl_map_free(map);
+
+ return found;
+error:
+ isl_map_free(map);
+ return -1;
+}
+
+int isl_set_contains_point(__isl_keep isl_set *set, __isl_keep isl_point *point)
+{
+ return isl_map_contains_point((isl_map *)set, point);
+}
+
+__isl_give isl_basic_set *isl_basic_set_from_point(__isl_take isl_point *pnt)
+{
+ isl_basic_set *bset;
+ isl_basic_set *model;
+
+ if (!pnt)
+ return NULL;
+
+ model = isl_basic_set_empty(isl_space_copy(pnt->dim));
+ bset = isl_basic_set_from_vec(isl_vec_copy(pnt->vec));
+ bset = isl_basic_set_from_underlying_set(bset, model);
+ isl_point_free(pnt);
+
+ return bset;
+}
+
+__isl_give isl_set *isl_set_from_point(__isl_take isl_point *pnt)
+{
+ isl_basic_set *bset;
+ bset = isl_basic_set_from_point(pnt);
+ return isl_set_from_basic_set(bset);
+}
+
+__isl_give isl_basic_set *isl_basic_set_box_from_points(
+ __isl_take isl_point *pnt1, __isl_take isl_point *pnt2)
+{
+ isl_basic_set *bset;
+ unsigned total;
+ int i;
+ int k;
+ isl_int t;
+
+ isl_int_init(t);
+
+ if (!pnt1 || !pnt2)
+ goto error;
+
+ isl_assert(pnt1->dim->ctx,
+ isl_space_is_equal(pnt1->dim, pnt2->dim), goto error);
+
+ if (isl_point_is_void(pnt1) && isl_point_is_void(pnt2)) {
+ isl_space *dim = isl_space_copy(pnt1->dim);
+ isl_point_free(pnt1);
+ isl_point_free(pnt2);
+ isl_int_clear(t);
+ return isl_basic_set_empty(dim);
+ }
+ if (isl_point_is_void(pnt1)) {
+ isl_point_free(pnt1);
+ isl_int_clear(t);
+ return isl_basic_set_from_point(pnt2);
+ }
+ if (isl_point_is_void(pnt2)) {
+ isl_point_free(pnt2);
+ isl_int_clear(t);
+ return isl_basic_set_from_point(pnt1);
+ }
+
+ total = isl_space_dim(pnt1->dim, isl_dim_all);
+ bset = isl_basic_set_alloc_space(isl_space_copy(pnt1->dim), 0, 0, 2 * total);
+
+ for (i = 0; i < total; ++i) {
+ isl_int_mul(t, pnt1->vec->el[1 + i], pnt2->vec->el[0]);
+ isl_int_submul(t, pnt2->vec->el[1 + i], pnt1->vec->el[0]);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[k] + 1, total);
+ if (isl_int_is_pos(t)) {
+ isl_int_set_si(bset->ineq[k][1 + i], -1);
+ isl_int_set(bset->ineq[k][0], pnt1->vec->el[1 + i]);
+ } else {
+ isl_int_set_si(bset->ineq[k][1 + i], 1);
+ isl_int_neg(bset->ineq[k][0], pnt1->vec->el[1 + i]);
+ }
+ isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt1->vec->el[0]);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[k] + 1, total);
+ if (isl_int_is_pos(t)) {
+ isl_int_set_si(bset->ineq[k][1 + i], 1);
+ isl_int_neg(bset->ineq[k][0], pnt2->vec->el[1 + i]);
+ } else {
+ isl_int_set_si(bset->ineq[k][1 + i], -1);
+ isl_int_set(bset->ineq[k][0], pnt2->vec->el[1 + i]);
+ }
+ isl_int_fdiv_q(bset->ineq[k][0], bset->ineq[k][0], pnt2->vec->el[0]);
+ }
+
+ bset = isl_basic_set_finalize(bset);
+
+ isl_point_free(pnt1);
+ isl_point_free(pnt2);
+
+ isl_int_clear(t);
+
+ return bset;
+error:
+ isl_point_free(pnt1);
+ isl_point_free(pnt2);
+ isl_int_clear(t);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
+ __isl_take isl_point *pnt2)
+{
+ isl_basic_set *bset;
+ bset = isl_basic_set_box_from_points(pnt1, pnt2);
+ return isl_set_from_basic_set(bset);
+}
+
+__isl_give isl_printer *isl_printer_print_point(
+ __isl_take isl_printer *p, __isl_keep isl_point *pnt)
+{
+ int i;
+ unsigned nparam;
+ unsigned dim;
+
+ if (!pnt)
+ return p;
+ if (isl_point_is_void(pnt)) {
+ p = isl_printer_print_str(p, "void");
+ return p;
+ }
+
+ nparam = isl_space_dim(pnt->dim, isl_dim_param);
+ dim = isl_space_dim(pnt->dim, isl_dim_set);
+ if (nparam > 0) {
+ p = isl_printer_print_str(p, "[");
+ for (i = 0; i < nparam; ++i) {
+ const char *name;
+ if (i)
+ p = isl_printer_print_str(p, ", ");
+ name = isl_space_get_dim_name(pnt->dim, isl_dim_param, i);
+ if (name) {
+ p = isl_printer_print_str(p, name);
+ p = isl_printer_print_str(p, " = ");
+ }
+ p = isl_printer_print_isl_int(p, pnt->vec->el[1 + 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, "]");
+ 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, "]");
+ return p;
+}
diff --git a/polly/lib/External/isl/isl_point_private.h b/polly/lib/External/isl/isl_point_private.h
new file mode 100644
index 00000000000..305b81e381a
--- /dev/null
+++ b/polly/lib/External/isl/isl_point_private.h
@@ -0,0 +1,12 @@
+#include <isl/space.h>
+#include <isl/point.h>
+#include <isl/vec.h>
+
+struct isl_point {
+ int ref;
+ isl_space *dim;
+ struct isl_vec *vec;
+};
+
+__isl_give isl_point *isl_point_alloc(__isl_take isl_space *dim,
+ __isl_take isl_vec *vec);
diff --git a/polly/lib/External/isl/isl_polynomial.c b/polly/lib/External/isl/isl_polynomial.c
new file mode 100644
index 00000000000..6b73bb397d0
--- /dev/null
+++ b/polly/lib/External/isl/isl_polynomial.c
@@ -0,0 +1,4866 @@
+/*
+ * 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 <stdlib.h>
+#define ISL_DIM_H
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_factorization.h>
+#include <isl_lp_private.h>
+#include <isl_seq.h>
+#include <isl_union_map_private.h>
+#include <isl_constraint_private.h>
+#include <isl_polynomial_private.h>
+#include <isl_point_private.h>
+#include <isl_space_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_range.h>
+#include <isl_local_space_private.h>
+#include <isl_aff_private.h>
+#include <isl_val_private.h>
+#include <isl_config.h>
+#include <isl/deprecated/polynomial_int.h>
+
+static unsigned pos(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param: return 0;
+ case isl_dim_in: return dim->nparam;
+ case isl_dim_out: return dim->nparam + dim->n_in;
+ default: return 0;
+ }
+}
+
+int isl_upoly_is_cst(__isl_keep struct isl_upoly *up)
+{
+ if (!up)
+ return -1;
+
+ return up->var < 0;
+}
+
+__isl_keep struct isl_upoly_cst *isl_upoly_as_cst(__isl_keep struct isl_upoly *up)
+{
+ if (!up)
+ return NULL;
+
+ isl_assert(up->ctx, up->var < 0, return NULL);
+
+ return (struct isl_upoly_cst *)up;
+}
+
+__isl_keep struct isl_upoly_rec *isl_upoly_as_rec(__isl_keep struct isl_upoly *up)
+{
+ if (!up)
+ return NULL;
+
+ isl_assert(up->ctx, up->var >= 0, return NULL);
+
+ return (struct isl_upoly_rec *)up;
+}
+
+int isl_upoly_is_equal(__isl_keep struct isl_upoly *up1,
+ __isl_keep struct isl_upoly *up2)
+{
+ int i;
+ struct isl_upoly_rec *rec1, *rec2;
+
+ if (!up1 || !up2)
+ return -1;
+ if (up1 == up2)
+ return 1;
+ if (up1->var != up2->var)
+ return 0;
+ if (isl_upoly_is_cst(up1)) {
+ struct isl_upoly_cst *cst1, *cst2;
+ cst1 = isl_upoly_as_cst(up1);
+ cst2 = isl_upoly_as_cst(up2);
+ if (!cst1 || !cst2)
+ return -1;
+ return isl_int_eq(cst1->n, cst2->n) &&
+ isl_int_eq(cst1->d, cst2->d);
+ }
+
+ rec1 = isl_upoly_as_rec(up1);
+ rec2 = isl_upoly_as_rec(up2);
+ if (!rec1 || !rec2)
+ return -1;
+
+ if (rec1->n != rec2->n)
+ return 0;
+
+ for (i = 0; i < rec1->n; ++i) {
+ int eq = isl_upoly_is_equal(rec1->p[i], rec2->p[i]);
+ if (eq < 0 || !eq)
+ return eq;
+ }
+
+ return 1;
+}
+
+int isl_upoly_is_zero(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_is_zero(cst->n) && isl_int_is_pos(cst->d);
+}
+
+int isl_upoly_sgn(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return 0;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return 0;
+
+ return isl_int_sgn(cst->n);
+}
+
+int isl_upoly_is_nan(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_is_zero(cst->n) && isl_int_is_zero(cst->d);
+}
+
+int isl_upoly_is_infty(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_is_pos(cst->n) && isl_int_is_zero(cst->d);
+}
+
+int isl_upoly_is_neginfty(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_is_neg(cst->n) && isl_int_is_zero(cst->d);
+}
+
+int isl_upoly_is_one(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_eq(cst->n, cst->d) && isl_int_is_pos(cst->d);
+}
+
+int isl_upoly_is_negone(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return -1;
+ if (!isl_upoly_is_cst(up))
+ return 0;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+
+ return isl_int_is_negone(cst->n) && isl_int_is_one(cst->d);
+}
+
+__isl_give struct isl_upoly_cst *isl_upoly_cst_alloc(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_alloc_type(ctx, struct isl_upoly_cst);
+ if (!cst)
+ return NULL;
+
+ cst->up.ref = 1;
+ cst->up.ctx = ctx;
+ isl_ctx_ref(ctx);
+ cst->up.var = -1;
+
+ isl_int_init(cst->n);
+ isl_int_init(cst->d);
+
+ return cst;
+}
+
+__isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set_si(cst->n, 0);
+ isl_int_set_si(cst->d, 1);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_one(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set_si(cst->n, 1);
+ isl_int_set_si(cst->d, 1);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_infty(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set_si(cst->n, 1);
+ isl_int_set_si(cst->d, 0);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_neginfty(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set_si(cst->n, -1);
+ isl_int_set_si(cst->d, 0);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_nan(struct isl_ctx *ctx)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set_si(cst->n, 0);
+ isl_int_set_si(cst->d, 0);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_rat_cst(struct isl_ctx *ctx,
+ isl_int n, isl_int d)
+{
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_cst_alloc(ctx);
+ if (!cst)
+ return NULL;
+
+ isl_int_set(cst->n, n);
+ isl_int_set(cst->d, d);
+
+ return &cst->up;
+}
+
+__isl_give struct isl_upoly_rec *isl_upoly_alloc_rec(struct isl_ctx *ctx,
+ int var, int size)
+{
+ struct isl_upoly_rec *rec;
+
+ isl_assert(ctx, var >= 0, return NULL);
+ isl_assert(ctx, size >= 0, return NULL);
+ rec = isl_calloc(ctx, struct isl_upoly_rec,
+ sizeof(struct isl_upoly_rec) +
+ size * sizeof(struct isl_upoly *));
+ if (!rec)
+ return NULL;
+
+ rec->up.ref = 1;
+ rec->up.ctx = ctx;
+ isl_ctx_ref(ctx);
+ rec->up.var = var;
+
+ rec->n = 0;
+ rec->size = size;
+
+ return rec;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_reset_domain_space(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *dim)
+{
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp || !dim)
+ goto error;
+
+ isl_space_free(qp->dim);
+ qp->dim = dim;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Reset the space of "qp". This function is called from isl_pw_templ.c
+ * and doesn't know if the space of an element object is represented
+ * directly or through its domain. It therefore passes along both.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_reset_space_and_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *space,
+ __isl_take isl_space *domain)
+{
+ isl_space_free(space);
+ return isl_qpolynomial_reset_domain_space(qp, domain);
+}
+
+isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? qp->dim->ctx : NULL;
+}
+
+__isl_give isl_space *isl_qpolynomial_get_domain_space(
+ __isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_space_copy(qp->dim) : NULL;
+}
+
+__isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp)
+{
+ isl_space *space;
+ if (!qp)
+ return NULL;
+ space = isl_space_copy(qp->dim);
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ return space;
+}
+
+/* Externally, an isl_qpolynomial has a map space, but internally, the
+ * ls field corresponds to the domain of that space.
+ */
+unsigned isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
+ enum isl_dim_type type)
+{
+ if (!qp)
+ return 0;
+ if (type == isl_dim_out)
+ return 1;
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ return isl_space_dim(qp->dim, type);
+}
+
+int isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_is_zero(qp->upoly) : -1;
+}
+
+int isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_is_one(qp->upoly) : -1;
+}
+
+int isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_is_nan(qp->upoly) : -1;
+}
+
+int isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_is_infty(qp->upoly) : -1;
+}
+
+int isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_is_neginfty(qp->upoly) : -1;
+}
+
+int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp)
+{
+ return qp ? isl_upoly_sgn(qp->upoly) : 0;
+}
+
+static void upoly_free_cst(__isl_take struct isl_upoly_cst *cst)
+{
+ isl_int_clear(cst->n);
+ isl_int_clear(cst->d);
+}
+
+static void upoly_free_rec(__isl_take struct isl_upoly_rec *rec)
+{
+ int i;
+
+ for (i = 0; i < rec->n; ++i)
+ isl_upoly_free(rec->p[i]);
+}
+
+__isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up)
+{
+ if (!up)
+ return NULL;
+
+ up->ref++;
+ return up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_dup_cst(__isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+ struct isl_upoly_cst *dup;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return NULL;
+
+ dup = isl_upoly_as_cst(isl_upoly_zero(up->ctx));
+ if (!dup)
+ return NULL;
+ isl_int_set(dup->n, cst->n);
+ isl_int_set(dup->d, cst->d);
+
+ return &dup->up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_dup_rec(__isl_keep struct isl_upoly *up)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+ struct isl_upoly_rec *dup;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return NULL;
+
+ dup = isl_upoly_alloc_rec(up->ctx, up->var, rec->n);
+ if (!dup)
+ return NULL;
+
+ for (i = 0; i < rec->n; ++i) {
+ dup->p[i] = isl_upoly_copy(rec->p[i]);
+ if (!dup->p[i])
+ goto error;
+ dup->n++;
+ }
+
+ return &dup->up;
+error:
+ isl_upoly_free(&dup->up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_dup(__isl_keep struct isl_upoly *up)
+{
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up))
+ return isl_upoly_dup_cst(up);
+ else
+ return isl_upoly_dup_rec(up);
+}
+
+__isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up)
+{
+ if (!up)
+ return NULL;
+
+ if (up->ref == 1)
+ return up;
+ up->ref--;
+ return isl_upoly_dup(up);
+}
+
+void isl_upoly_free(__isl_take struct isl_upoly *up)
+{
+ if (!up)
+ return;
+
+ if (--up->ref > 0)
+ return;
+
+ if (up->var < 0)
+ upoly_free_cst((struct isl_upoly_cst *)up);
+ else
+ upoly_free_rec((struct isl_upoly_rec *)up);
+
+ isl_ctx_deref(up->ctx);
+ free(up);
+}
+
+static void isl_upoly_cst_reduce(__isl_keep struct isl_upoly_cst *cst)
+{
+ isl_int gcd;
+
+ isl_int_init(gcd);
+ isl_int_gcd(gcd, cst->n, cst->d);
+ if (!isl_int_is_zero(gcd) && !isl_int_is_one(gcd)) {
+ isl_int_divexact(cst->n, cst->n, gcd);
+ isl_int_divexact(cst->d, cst->d, gcd);
+ }
+ isl_int_clear(gcd);
+}
+
+__isl_give struct isl_upoly *isl_upoly_sum_cst(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2)
+{
+ struct isl_upoly_cst *cst1;
+ struct isl_upoly_cst *cst2;
+
+ up1 = isl_upoly_cow(up1);
+ if (!up1 || !up2)
+ goto error;
+
+ cst1 = isl_upoly_as_cst(up1);
+ cst2 = isl_upoly_as_cst(up2);
+
+ if (isl_int_eq(cst1->d, cst2->d))
+ isl_int_add(cst1->n, cst1->n, cst2->n);
+ else {
+ isl_int_mul(cst1->n, cst1->n, cst2->d);
+ isl_int_addmul(cst1->n, cst2->n, cst1->d);
+ isl_int_mul(cst1->d, cst1->d, cst2->d);
+ }
+
+ isl_upoly_cst_reduce(cst1);
+
+ isl_upoly_free(up2);
+ return up1;
+error:
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ return NULL;
+}
+
+static __isl_give struct isl_upoly *replace_by_zero(
+ __isl_take struct isl_upoly *up)
+{
+ struct isl_ctx *ctx;
+
+ if (!up)
+ return NULL;
+ ctx = up->ctx;
+ isl_upoly_free(up);
+ return isl_upoly_zero(ctx);
+}
+
+static __isl_give struct isl_upoly *replace_by_constant_term(
+ __isl_take struct isl_upoly *up)
+{
+ struct isl_upoly_rec *rec;
+ struct isl_upoly *cst;
+
+ if (!up)
+ return NULL;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+ cst = isl_upoly_copy(rec->p[0]);
+ isl_upoly_free(up);
+ return cst;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_sum(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2)
+{
+ int i;
+ struct isl_upoly_rec *rec1, *rec2;
+
+ if (!up1 || !up2)
+ goto error;
+
+ if (isl_upoly_is_nan(up1)) {
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (isl_upoly_is_nan(up2)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+
+ if (isl_upoly_is_zero(up1)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+
+ if (isl_upoly_is_zero(up2)) {
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (up1->var < up2->var)
+ return isl_upoly_sum(up2, up1);
+
+ if (up2->var < up1->var) {
+ struct isl_upoly_rec *rec;
+ if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+ up1 = isl_upoly_cow(up1);
+ rec = isl_upoly_as_rec(up1);
+ if (!rec)
+ goto error;
+ rec->p[0] = isl_upoly_sum(rec->p[0], up2);
+ if (rec->n == 1)
+ up1 = replace_by_constant_term(up1);
+ return up1;
+ }
+
+ if (isl_upoly_is_cst(up1))
+ return isl_upoly_sum_cst(up1, up2);
+
+ rec1 = isl_upoly_as_rec(up1);
+ rec2 = isl_upoly_as_rec(up2);
+ if (!rec1 || !rec2)
+ goto error;
+
+ if (rec1->n < rec2->n)
+ return isl_upoly_sum(up2, up1);
+
+ up1 = isl_upoly_cow(up1);
+ rec1 = isl_upoly_as_rec(up1);
+ if (!rec1)
+ goto error;
+
+ for (i = rec2->n - 1; i >= 0; --i) {
+ rec1->p[i] = isl_upoly_sum(rec1->p[i],
+ isl_upoly_copy(rec2->p[i]));
+ if (!rec1->p[i])
+ goto error;
+ if (i == rec1->n - 1 && isl_upoly_is_zero(rec1->p[i])) {
+ isl_upoly_free(rec1->p[i]);
+ rec1->n--;
+ }
+ }
+
+ if (rec1->n == 0)
+ up1 = replace_by_zero(up1);
+ else if (rec1->n == 1)
+ up1 = replace_by_constant_term(up1);
+
+ isl_upoly_free(up2);
+
+ return up1;
+error:
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_cst_add_isl_int(
+ __isl_take struct isl_upoly *up, isl_int v)
+{
+ struct isl_upoly_cst *cst;
+
+ up = isl_upoly_cow(up);
+ if (!up)
+ return NULL;
+
+ cst = isl_upoly_as_cst(up);
+
+ isl_int_addmul(cst->n, cst->d, v);
+
+ return up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_add_isl_int(
+ __isl_take struct isl_upoly *up, isl_int v)
+{
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up))
+ return isl_upoly_cst_add_isl_int(up, v);
+
+ up = isl_upoly_cow(up);
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ rec->p[0] = isl_upoly_add_isl_int(rec->p[0], v);
+ if (!rec->p[0])
+ goto error;
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_cst_mul_isl_int(
+ __isl_take struct isl_upoly *up, isl_int v)
+{
+ struct isl_upoly_cst *cst;
+
+ if (isl_upoly_is_zero(up))
+ return up;
+
+ up = isl_upoly_cow(up);
+ if (!up)
+ return NULL;
+
+ cst = isl_upoly_as_cst(up);
+
+ isl_int_mul(cst->n, cst->n, v);
+
+ return up;
+}
+
+__isl_give struct isl_upoly *isl_upoly_mul_isl_int(
+ __isl_take struct isl_upoly *up, isl_int v)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up))
+ return isl_upoly_cst_mul_isl_int(up, v);
+
+ up = isl_upoly_cow(up);
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ rec->p[i] = isl_upoly_mul_isl_int(rec->p[i], v);
+ if (!rec->p[i])
+ goto error;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+/* Multiply the constant polynomial "up" by "v".
+ */
+static __isl_give struct isl_upoly *isl_upoly_cst_scale_val(
+ __isl_take struct isl_upoly *up, __isl_keep isl_val *v)
+{
+ struct isl_upoly_cst *cst;
+
+ if (isl_upoly_is_zero(up))
+ return up;
+
+ up = isl_upoly_cow(up);
+ if (!up)
+ return NULL;
+
+ cst = isl_upoly_as_cst(up);
+
+ isl_int_mul(cst->n, cst->n, v->n);
+ isl_int_mul(cst->d, cst->d, v->d);
+ isl_upoly_cst_reduce(cst);
+
+ return up;
+}
+
+/* Multiply the polynomial "up" by "v".
+ */
+static __isl_give struct isl_upoly *isl_upoly_scale_val(
+ __isl_take struct isl_upoly *up, __isl_keep isl_val *v)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up))
+ return isl_upoly_cst_scale_val(up, v);
+
+ up = isl_upoly_cow(up);
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ rec->p[i] = isl_upoly_scale_val(rec->p[i], v);
+ if (!rec->p[i])
+ goto error;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_mul_cst(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2)
+{
+ struct isl_upoly_cst *cst1;
+ struct isl_upoly_cst *cst2;
+
+ up1 = isl_upoly_cow(up1);
+ if (!up1 || !up2)
+ goto error;
+
+ cst1 = isl_upoly_as_cst(up1);
+ cst2 = isl_upoly_as_cst(up2);
+
+ isl_int_mul(cst1->n, cst1->n, cst2->n);
+ isl_int_mul(cst1->d, cst1->d, cst2->d);
+
+ isl_upoly_cst_reduce(cst1);
+
+ isl_upoly_free(up2);
+ return up1;
+error:
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_mul_rec(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2)
+{
+ struct isl_upoly_rec *rec1;
+ struct isl_upoly_rec *rec2;
+ struct isl_upoly_rec *res = NULL;
+ int i, j;
+ int size;
+
+ rec1 = isl_upoly_as_rec(up1);
+ rec2 = isl_upoly_as_rec(up2);
+ if (!rec1 || !rec2)
+ goto error;
+ size = rec1->n + rec2->n - 1;
+ res = isl_upoly_alloc_rec(up1->ctx, up1->var, size);
+ if (!res)
+ goto error;
+
+ for (i = 0; i < rec1->n; ++i) {
+ res->p[i] = isl_upoly_mul(isl_upoly_copy(rec2->p[0]),
+ isl_upoly_copy(rec1->p[i]));
+ if (!res->p[i])
+ goto error;
+ res->n++;
+ }
+ for (; i < size; ++i) {
+ res->p[i] = isl_upoly_zero(up1->ctx);
+ if (!res->p[i])
+ goto error;
+ res->n++;
+ }
+ for (i = 0; i < rec1->n; ++i) {
+ for (j = 1; j < rec2->n; ++j) {
+ struct isl_upoly *up;
+ up = isl_upoly_mul(isl_upoly_copy(rec2->p[j]),
+ isl_upoly_copy(rec1->p[i]));
+ res->p[i + j] = isl_upoly_sum(res->p[i + j], up);
+ if (!res->p[i + j])
+ goto error;
+ }
+ }
+
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+
+ return &res->up;
+error:
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ isl_upoly_free(&res->up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_mul(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2)
+{
+ if (!up1 || !up2)
+ goto error;
+
+ if (isl_upoly_is_nan(up1)) {
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (isl_upoly_is_nan(up2)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+
+ if (isl_upoly_is_zero(up1)) {
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (isl_upoly_is_zero(up2)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+
+ if (isl_upoly_is_one(up1)) {
+ isl_upoly_free(up1);
+ return up2;
+ }
+
+ if (isl_upoly_is_one(up2)) {
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (up1->var < up2->var)
+ return isl_upoly_mul(up2, up1);
+
+ if (up2->var < up1->var) {
+ int i;
+ struct isl_upoly_rec *rec;
+ if (isl_upoly_is_infty(up2) || isl_upoly_is_neginfty(up2)) {
+ isl_ctx *ctx = up1->ctx;
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ return isl_upoly_nan(ctx);
+ }
+ up1 = isl_upoly_cow(up1);
+ rec = isl_upoly_as_rec(up1);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ rec->p[i] = isl_upoly_mul(rec->p[i],
+ isl_upoly_copy(up2));
+ if (!rec->p[i])
+ goto error;
+ }
+ isl_upoly_free(up2);
+ return up1;
+ }
+
+ if (isl_upoly_is_cst(up1))
+ return isl_upoly_mul_cst(up1, up2);
+
+ return isl_upoly_mul_rec(up1, up2);
+error:
+ isl_upoly_free(up1);
+ isl_upoly_free(up2);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_pow(__isl_take struct isl_upoly *up,
+ unsigned power)
+{
+ struct isl_upoly *res;
+
+ if (!up)
+ return NULL;
+ if (power == 1)
+ return up;
+
+ if (power % 2)
+ res = isl_upoly_copy(up);
+ else
+ res = isl_upoly_one(up->ctx);
+
+ while (power >>= 1) {
+ up = isl_upoly_mul(up, isl_upoly_copy(up));
+ if (power % 2)
+ res = isl_upoly_mul(res, isl_upoly_copy(up));
+ }
+
+ isl_upoly_free(up);
+ return res;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *dim,
+ unsigned n_div, __isl_take struct isl_upoly *up)
+{
+ struct isl_qpolynomial *qp = NULL;
+ unsigned total;
+
+ if (!dim || !up)
+ goto error;
+
+ if (!isl_space_is_set(dim))
+ isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+ "domain of polynomial should be a set", goto error);
+
+ total = isl_space_dim(dim, isl_dim_all);
+
+ qp = isl_calloc_type(dim->ctx, struct isl_qpolynomial);
+ if (!qp)
+ goto error;
+
+ qp->ref = 1;
+ qp->div = isl_mat_alloc(dim->ctx, n_div, 1 + 1 + total + n_div);
+ if (!qp->div)
+ goto error;
+
+ qp->dim = dim;
+ qp->upoly = up;
+
+ return qp;
+error:
+ isl_space_free(dim);
+ isl_upoly_free(up);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp)
+{
+ if (!qp)
+ return NULL;
+
+ qp->ref++;
+ return qp;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp)
+{
+ struct isl_qpolynomial *dup;
+
+ if (!qp)
+ return NULL;
+
+ dup = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row,
+ isl_upoly_copy(qp->upoly));
+ if (!dup)
+ return NULL;
+ isl_mat_free(dup->div);
+ dup->div = isl_mat_copy(qp->div);
+ if (!dup->div)
+ goto error;
+
+ return dup;
+error:
+ isl_qpolynomial_free(dup);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp)
+{
+ if (!qp)
+ return NULL;
+
+ if (qp->ref == 1)
+ return qp;
+ qp->ref--;
+ return isl_qpolynomial_dup(qp);
+}
+
+__isl_null isl_qpolynomial *isl_qpolynomial_free(
+ __isl_take isl_qpolynomial *qp)
+{
+ if (!qp)
+ return NULL;
+
+ if (--qp->ref > 0)
+ return NULL;
+
+ isl_space_free(qp->dim);
+ isl_mat_free(qp->div);
+ isl_upoly_free(qp->upoly);
+
+ free(qp);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_var_pow(isl_ctx *ctx, int pos, int power)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+ struct isl_upoly_cst *cst;
+
+ rec = isl_upoly_alloc_rec(ctx, pos, 1 + power);
+ if (!rec)
+ return NULL;
+ for (i = 0; i < 1 + power; ++i) {
+ rec->p[i] = isl_upoly_zero(ctx);
+ if (!rec->p[i])
+ goto error;
+ rec->n++;
+ }
+ cst = isl_upoly_as_cst(rec->p[power]);
+ isl_int_set_si(cst->n, 1);
+
+ return &rec->up;
+error:
+ isl_upoly_free(&rec->up);
+ return NULL;
+}
+
+/* r array maps original positions to new positions.
+ */
+static __isl_give struct isl_upoly *reorder(__isl_take struct isl_upoly *up,
+ int *r)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+ struct isl_upoly *base;
+ struct isl_upoly *res;
+
+ if (isl_upoly_is_cst(up))
+ return up;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ isl_assert(up->ctx, rec->n >= 1, goto error);
+
+ base = isl_upoly_var_pow(up->ctx, r[up->var], 1);
+ res = reorder(isl_upoly_copy(rec->p[rec->n - 1]), r);
+
+ for (i = rec->n - 2; i >= 0; --i) {
+ res = isl_upoly_mul(res, isl_upoly_copy(base));
+ res = isl_upoly_sum(res, reorder(isl_upoly_copy(rec->p[i]), r));
+ }
+
+ isl_upoly_free(base);
+ isl_upoly_free(up);
+
+ return res;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+static int compatible_divs(__isl_keep isl_mat *div1, __isl_keep isl_mat *div2)
+{
+ int n_row, n_col;
+ int equal;
+
+ isl_assert(div1->ctx, div1->n_row >= div2->n_row &&
+ div1->n_col >= div2->n_col, return -1);
+
+ if (div1->n_row == div2->n_row)
+ return isl_mat_is_equal(div1, div2);
+
+ n_row = div1->n_row;
+ n_col = div1->n_col;
+ div1->n_row = div2->n_row;
+ div1->n_col = div2->n_col;
+
+ equal = isl_mat_is_equal(div1, div2);
+
+ div1->n_row = n_row;
+ div1->n_col = n_col;
+
+ return equal;
+}
+
+static int cmp_row(__isl_keep isl_mat *div, int i, int j)
+{
+ int li, lj;
+
+ li = isl_seq_last_non_zero(div->row[i], div->n_col);
+ lj = isl_seq_last_non_zero(div->row[j], div->n_col);
+
+ if (li != lj)
+ return li - lj;
+
+ return isl_seq_cmp(div->row[i], div->row[j], div->n_col);
+}
+
+struct isl_div_sort_info {
+ isl_mat *div;
+ int row;
+};
+
+static int div_sort_cmp(const void *p1, const void *p2)
+{
+ const struct isl_div_sort_info *i1, *i2;
+ i1 = (const struct isl_div_sort_info *) p1;
+ i2 = (const struct isl_div_sort_info *) p2;
+
+ return cmp_row(i1->div, i1->row, i2->row);
+}
+
+/* Sort divs and remove duplicates.
+ */
+static __isl_give isl_qpolynomial *sort_divs(__isl_take isl_qpolynomial *qp)
+{
+ int i;
+ int skip;
+ int len;
+ struct isl_div_sort_info *array = NULL;
+ int *pos = NULL, *at = NULL;
+ int *reordering = NULL;
+ unsigned div_pos;
+
+ if (!qp)
+ return NULL;
+ if (qp->div->n_row <= 1)
+ return qp;
+
+ div_pos = isl_space_dim(qp->dim, isl_dim_all);
+
+ array = isl_alloc_array(qp->div->ctx, struct isl_div_sort_info,
+ qp->div->n_row);
+ pos = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
+ at = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
+ len = qp->div->n_col - 2;
+ reordering = isl_alloc_array(qp->div->ctx, int, len);
+ if (!array || !pos || !at || !reordering)
+ goto error;
+
+ for (i = 0; i < qp->div->n_row; ++i) {
+ array[i].div = qp->div;
+ array[i].row = i;
+ pos[i] = i;
+ at[i] = i;
+ }
+
+ qsort(array, qp->div->n_row, sizeof(struct isl_div_sort_info),
+ div_sort_cmp);
+
+ for (i = 0; i < div_pos; ++i)
+ reordering[i] = i;
+
+ for (i = 0; i < qp->div->n_row; ++i) {
+ if (pos[array[i].row] == i)
+ continue;
+ qp->div = isl_mat_swap_rows(qp->div, i, pos[array[i].row]);
+ pos[at[i]] = pos[array[i].row];
+ at[pos[array[i].row]] = at[i];
+ at[i] = array[i].row;
+ pos[array[i].row] = i;
+ }
+
+ skip = 0;
+ for (i = 0; i < len - div_pos; ++i) {
+ if (i > 0 &&
+ isl_seq_eq(qp->div->row[i - skip - 1],
+ qp->div->row[i - skip], qp->div->n_col)) {
+ qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);
+ isl_mat_col_add(qp->div, 2 + div_pos + i - skip - 1,
+ 2 + div_pos + i - skip);
+ qp->div = isl_mat_drop_cols(qp->div,
+ 2 + div_pos + i - skip, 1);
+ skip++;
+ }
+ reordering[div_pos + array[i].row] = div_pos + i - skip;
+ }
+
+ qp->upoly = reorder(qp->upoly, reordering);
+
+ if (!qp->upoly || !qp->div)
+ goto error;
+
+ free(at);
+ free(pos);
+ free(array);
+ free(reordering);
+
+ return qp;
+error:
+ free(at);
+ free(pos);
+ free(array);
+ free(reordering);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+static __isl_give struct isl_upoly *expand(__isl_take struct isl_upoly *up,
+ int *exp, int first)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (isl_upoly_is_cst(up))
+ return up;
+
+ if (up->var < first)
+ return up;
+
+ if (exp[up->var - first] == up->var - first)
+ return up;
+
+ up = isl_upoly_cow(up);
+ if (!up)
+ goto error;
+
+ up->var = exp[up->var - first] + first;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ rec->p[i] = expand(rec->p[i], exp, first);
+ if (!rec->p[i])
+ goto error;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+static __isl_give isl_qpolynomial *with_merged_divs(
+ __isl_give isl_qpolynomial *(*fn)(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2),
+ __isl_take isl_qpolynomial *qp1, __isl_take isl_qpolynomial *qp2)
+{
+ int *exp1 = NULL;
+ int *exp2 = NULL;
+ isl_mat *div = NULL;
+ int n_div1, n_div2;
+
+ qp1 = isl_qpolynomial_cow(qp1);
+ qp2 = isl_qpolynomial_cow(qp2);
+
+ if (!qp1 || !qp2)
+ goto error;
+
+ isl_assert(qp1->div->ctx, qp1->div->n_row >= qp2->div->n_row &&
+ qp1->div->n_col >= qp2->div->n_col, goto error);
+
+ n_div1 = qp1->div->n_row;
+ n_div2 = qp2->div->n_row;
+ exp1 = isl_alloc_array(qp1->div->ctx, int, n_div1);
+ exp2 = isl_alloc_array(qp2->div->ctx, int, n_div2);
+ if ((n_div1 && !exp1) || (n_div2 && !exp2))
+ goto error;
+
+ div = isl_merge_divs(qp1->div, qp2->div, exp1, exp2);
+ if (!div)
+ goto error;
+
+ isl_mat_free(qp1->div);
+ qp1->div = isl_mat_copy(div);
+ isl_mat_free(qp2->div);
+ qp2->div = isl_mat_copy(div);
+
+ qp1->upoly = expand(qp1->upoly, exp1, div->n_col - div->n_row - 2);
+ qp2->upoly = expand(qp2->upoly, exp2, div->n_col - div->n_row - 2);
+
+ if (!qp1->upoly || !qp2->upoly)
+ goto error;
+
+ isl_mat_free(div);
+ free(exp1);
+ free(exp2);
+
+ return fn(qp1, qp2);
+error:
+ isl_mat_free(div);
+ free(exp1);
+ free(exp2);
+ isl_qpolynomial_free(qp1);
+ isl_qpolynomial_free(qp2);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2)
+{
+ qp1 = isl_qpolynomial_cow(qp1);
+
+ if (!qp1 || !qp2)
+ goto error;
+
+ if (qp1->div->n_row < qp2->div->n_row)
+ return isl_qpolynomial_add(qp2, qp1);
+
+ isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
+ if (!compatible_divs(qp1->div, qp2->div))
+ return with_merged_divs(isl_qpolynomial_add, qp1, qp2);
+
+ qp1->upoly = isl_upoly_sum(qp1->upoly, isl_upoly_copy(qp2->upoly));
+ if (!qp1->upoly)
+ goto error;
+
+ isl_qpolynomial_free(qp2);
+
+ return qp1;
+error:
+ isl_qpolynomial_free(qp1);
+ isl_qpolynomial_free(qp2);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_add_on_domain(
+ __isl_keep isl_set *dom,
+ __isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2)
+{
+ qp1 = isl_qpolynomial_add(qp1, qp2);
+ qp1 = isl_qpolynomial_gist(qp1, isl_set_copy(dom));
+ return qp1;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2)
+{
+ return isl_qpolynomial_add(qp1, isl_qpolynomial_neg(qp2));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(
+ __isl_take isl_qpolynomial *qp, isl_int v)
+{
+ if (isl_int_is_zero(v))
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ qp->upoly = isl_upoly_add_isl_int(qp->upoly, v);
+ if (!qp->upoly)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp)
+{
+ if (!qp)
+ return NULL;
+
+ return isl_qpolynomial_mul_isl_int(qp, qp->dim->ctx->negone);
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(
+ __isl_take isl_qpolynomial *qp, isl_int v)
+{
+ if (isl_int_is_one(v))
+ return qp;
+
+ if (qp && isl_int_is_zero(v)) {
+ isl_qpolynomial *zero;
+ zero = isl_qpolynomial_zero_on_domain(isl_space_copy(qp->dim));
+ isl_qpolynomial_free(qp);
+ return zero;
+ }
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ qp->upoly = isl_upoly_mul_isl_int(qp->upoly, v);
+ if (!qp->upoly)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_scale(
+ __isl_take isl_qpolynomial *qp, isl_int v)
+{
+ return isl_qpolynomial_mul_isl_int(qp, v);
+}
+
+/* Multiply "qp" by "v".
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_val *v)
+{
+ if (!qp || !v)
+ goto error;
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
+ "expecting rational factor", goto error);
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return qp;
+ }
+
+ if (isl_val_is_zero(v)) {
+ isl_space *space;
+
+ space = isl_qpolynomial_get_domain_space(qp);
+ isl_qpolynomial_free(qp);
+ isl_val_free(v);
+ return isl_qpolynomial_zero_on_domain(space);
+ }
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ goto error;
+
+ qp->upoly = isl_upoly_scale_val(qp->upoly, v);
+ if (!qp->upoly)
+ qp = isl_qpolynomial_free(qp);
+
+ isl_val_free(v);
+ return qp;
+error:
+ isl_val_free(v);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+/* Divide "qp" by "v".
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_down_val(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_val *v)
+{
+ if (!qp || !v)
+ goto error;
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (isl_val_is_zero(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "cannot scale down by zero", goto error);
+
+ return isl_qpolynomial_scale_val(qp, isl_val_inv(v));
+error:
+ isl_val_free(v);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2)
+{
+ qp1 = isl_qpolynomial_cow(qp1);
+
+ if (!qp1 || !qp2)
+ goto error;
+
+ if (qp1->div->n_row < qp2->div->n_row)
+ return isl_qpolynomial_mul(qp2, qp1);
+
+ isl_assert(qp1->dim->ctx, isl_space_is_equal(qp1->dim, qp2->dim), goto error);
+ if (!compatible_divs(qp1->div, qp2->div))
+ return with_merged_divs(isl_qpolynomial_mul, qp1, qp2);
+
+ qp1->upoly = isl_upoly_mul(qp1->upoly, isl_upoly_copy(qp2->upoly));
+ if (!qp1->upoly)
+ goto error;
+
+ isl_qpolynomial_free(qp2);
+
+ return qp1;
+error:
+ isl_qpolynomial_free(qp1);
+ isl_qpolynomial_free(qp2);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,
+ unsigned power)
+{
+ qp = isl_qpolynomial_cow(qp);
+
+ if (!qp)
+ return NULL;
+
+ qp->upoly = isl_upoly_pow(qp->upoly, power);
+ if (!qp->upoly)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
+ __isl_take isl_pw_qpolynomial *pwqp, unsigned power)
+{
+ int i;
+
+ if (power == 1)
+ return pwqp;
+
+ pwqp = isl_pw_qpolynomial_cow(pwqp);
+ if (!pwqp)
+ return NULL;
+
+ for (i = 0; i < pwqp->n; ++i) {
+ pwqp->p[i].qp = isl_qpolynomial_pow(pwqp->p[i].qp, power);
+ if (!pwqp->p[i].qp)
+ return isl_pw_qpolynomial_free(pwqp);
+ }
+
+ return pwqp;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(
+ __isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(
+ __isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_one(dim->ctx));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(
+ __isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_infty(dim->ctx));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(
+ __isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_neginfty(dim->ctx));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(
+ __isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_nan(dim->ctx));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_cst_on_domain(
+ __isl_take isl_space *dim,
+ isl_int v)
+{
+ struct isl_qpolynomial *qp;
+ struct isl_upoly_cst *cst;
+
+ if (!dim)
+ return NULL;
+
+ qp = isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+ if (!qp)
+ return NULL;
+
+ cst = isl_upoly_as_cst(qp->upoly);
+ isl_int_set(cst->n, v);
+
+ return qp;
+}
+
+int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+ isl_int *n, isl_int *d)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!qp)
+ return -1;
+
+ if (!isl_upoly_is_cst(qp->upoly))
+ return 0;
+
+ cst = isl_upoly_as_cst(qp->upoly);
+ if (!cst)
+ return -1;
+
+ if (n)
+ isl_int_set(*n, cst->n);
+ if (d)
+ isl_int_set(*d, cst->d);
+
+ return 1;
+}
+
+/* Return the constant term of "up".
+ */
+static __isl_give isl_val *isl_upoly_get_constant_val(
+ __isl_keep struct isl_upoly *up)
+{
+ struct isl_upoly_cst *cst;
+
+ if (!up)
+ return NULL;
+
+ while (!isl_upoly_is_cst(up)) {
+ struct isl_upoly_rec *rec;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return NULL;
+ up = rec->p[0];
+ }
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return NULL;
+ return isl_val_rat_from_isl_int(cst->up.ctx, cst->n, cst->d);
+}
+
+/* Return the constant term of "qp".
+ */
+__isl_give isl_val *isl_qpolynomial_get_constant_val(
+ __isl_keep isl_qpolynomial *qp)
+{
+ if (!qp)
+ return NULL;
+
+ return isl_upoly_get_constant_val(qp->upoly);
+}
+
+int isl_upoly_is_affine(__isl_keep struct isl_upoly *up)
+{
+ int is_cst;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return -1;
+
+ if (up->var < 0)
+ return 1;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return -1;
+
+ if (rec->n > 2)
+ return 0;
+
+ isl_assert(up->ctx, rec->n > 1, return -1);
+
+ is_cst = isl_upoly_is_cst(rec->p[1]);
+ if (is_cst < 0)
+ return -1;
+ if (!is_cst)
+ return 0;
+
+ return isl_upoly_is_affine(rec->p[0]);
+}
+
+int isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp)
+{
+ if (!qp)
+ return -1;
+
+ if (qp->div->n_row > 0)
+ return 0;
+
+ return isl_upoly_is_affine(qp->upoly);
+}
+
+static void update_coeff(__isl_keep isl_vec *aff,
+ __isl_keep struct isl_upoly_cst *cst, int pos)
+{
+ isl_int gcd;
+ isl_int f;
+
+ if (isl_int_is_zero(cst->n))
+ return;
+
+ isl_int_init(gcd);
+ isl_int_init(f);
+ isl_int_gcd(gcd, cst->d, aff->el[0]);
+ isl_int_divexact(f, cst->d, gcd);
+ isl_int_divexact(gcd, aff->el[0], gcd);
+ isl_seq_scale(aff->el, aff->el, f, aff->size);
+ isl_int_mul(aff->el[1 + pos], gcd, cst->n);
+ isl_int_clear(gcd);
+ isl_int_clear(f);
+}
+
+int isl_upoly_update_affine(__isl_keep struct isl_upoly *up,
+ __isl_keep isl_vec *aff)
+{
+ struct isl_upoly_cst *cst;
+ struct isl_upoly_rec *rec;
+
+ if (!up || !aff)
+ return -1;
+
+ if (up->var < 0) {
+ struct isl_upoly_cst *cst;
+
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return -1;
+ update_coeff(aff, cst, 0);
+ return 0;
+ }
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return -1;
+ isl_assert(up->ctx, rec->n == 2, return -1);
+
+ cst = isl_upoly_as_cst(rec->p[1]);
+ if (!cst)
+ return -1;
+ update_coeff(aff, cst, 1 + up->var);
+
+ return isl_upoly_update_affine(rec->p[0], aff);
+}
+
+__isl_give isl_vec *isl_qpolynomial_extract_affine(
+ __isl_keep isl_qpolynomial *qp)
+{
+ isl_vec *aff;
+ unsigned d;
+
+ if (!qp)
+ return NULL;
+
+ d = isl_space_dim(qp->dim, isl_dim_all);
+ aff = isl_vec_alloc(qp->div->ctx, 2 + d + qp->div->n_row);
+ if (!aff)
+ return NULL;
+
+ isl_seq_clr(aff->el + 1, 1 + d + qp->div->n_row);
+ isl_int_set_si(aff->el[0], 1);
+
+ if (isl_upoly_update_affine(qp->upoly, aff) < 0)
+ goto error;
+
+ return aff;
+error:
+ isl_vec_free(aff);
+ return NULL;
+}
+
+int isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,
+ __isl_keep isl_qpolynomial *qp2)
+{
+ int equal;
+
+ if (!qp1 || !qp2)
+ return -1;
+
+ equal = isl_space_is_equal(qp1->dim, qp2->dim);
+ if (equal < 0 || !equal)
+ return equal;
+
+ equal = isl_mat_is_equal(qp1->div, qp2->div);
+ if (equal < 0 || !equal)
+ return equal;
+
+ return isl_upoly_is_equal(qp1->upoly, qp2->upoly);
+}
+
+static void upoly_update_den(__isl_keep struct isl_upoly *up, isl_int *d)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (isl_upoly_is_cst(up)) {
+ struct isl_upoly_cst *cst;
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ return;
+ isl_int_lcm(*d, *d, cst->d);
+ return;
+ }
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return;
+
+ for (i = 0; i < rec->n; ++i)
+ upoly_update_den(rec->p[i], d);
+}
+
+void isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp, isl_int *d)
+{
+ isl_int_set_si(*d, 1);
+ if (!qp)
+ return;
+ upoly_update_den(qp->upoly, d);
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(
+ __isl_take isl_space *dim, int pos, int power)
+{
+ struct isl_ctx *ctx;
+
+ if (!dim)
+ return NULL;
+
+ ctx = dim->ctx;
+
+ return isl_qpolynomial_alloc(dim, 0, isl_upoly_var_pow(ctx, pos, power));
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!dim)
+ return NULL;
+
+ isl_assert(dim->ctx, isl_space_dim(dim, isl_dim_in) == 0, goto error);
+ isl_assert(dim->ctx, pos < isl_space_dim(dim, type), goto error);
+
+ if (type == isl_dim_set)
+ pos += isl_space_dim(dim, isl_dim_param);
+
+ return isl_qpolynomial_var_pow_on_domain(dim, pos, 1);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_subs(__isl_take struct isl_upoly *up,
+ unsigned first, unsigned n, __isl_keep struct isl_upoly **subs)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+ struct isl_upoly *base, *res;
+
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up))
+ return up;
+
+ if (up->var < first)
+ return up;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ isl_assert(up->ctx, rec->n >= 1, goto error);
+
+ if (up->var >= first + n)
+ base = isl_upoly_var_pow(up->ctx, up->var, 1);
+ else
+ base = isl_upoly_copy(subs[up->var - first]);
+
+ res = isl_upoly_subs(isl_upoly_copy(rec->p[rec->n - 1]), first, n, subs);
+ for (i = rec->n - 2; i >= 0; --i) {
+ struct isl_upoly *t;
+ t = isl_upoly_subs(isl_upoly_copy(rec->p[i]), first, n, subs);
+ res = isl_upoly_mul(res, isl_upoly_copy(base));
+ res = isl_upoly_sum(res, t);
+ }
+
+ isl_upoly_free(base);
+ isl_upoly_free(up);
+
+ return res;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_from_affine(isl_ctx *ctx, isl_int *f,
+ isl_int denom, unsigned len)
+{
+ int i;
+ struct isl_upoly *up;
+
+ isl_assert(ctx, len >= 1, return NULL);
+
+ up = isl_upoly_rat_cst(ctx, f[0], denom);
+ for (i = 0; i < len - 1; ++i) {
+ struct isl_upoly *t;
+ struct isl_upoly *c;
+
+ if (isl_int_is_zero(f[1 + i]))
+ continue;
+
+ c = isl_upoly_rat_cst(ctx, f[1 + i], denom);
+ t = isl_upoly_var_pow(ctx, i, 1);
+ t = isl_upoly_mul(c, t);
+ up = isl_upoly_sum(up, t);
+ }
+
+ return up;
+}
+
+/* Remove common factor of non-constant terms and denominator.
+ */
+static void normalize_div(__isl_keep isl_qpolynomial *qp, int div)
+{
+ isl_ctx *ctx = qp->div->ctx;
+ unsigned total = qp->div->n_col - 2;
+
+ isl_seq_gcd(qp->div->row[div] + 2, total, &ctx->normalize_gcd);
+ isl_int_gcd(ctx->normalize_gcd,
+ ctx->normalize_gcd, qp->div->row[div][0]);
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return;
+
+ isl_seq_scale_down(qp->div->row[div] + 2, qp->div->row[div] + 2,
+ ctx->normalize_gcd, total);
+ isl_int_divexact(qp->div->row[div][0], qp->div->row[div][0],
+ ctx->normalize_gcd);
+ isl_int_fdiv_q(qp->div->row[div][1], qp->div->row[div][1],
+ ctx->normalize_gcd);
+}
+
+/* Replace the integer division identified by "div" by the polynomial "s".
+ * The integer division is assumed not to appear in the definition
+ * of any other integer divisions.
+ */
+static __isl_give isl_qpolynomial *substitute_div(
+ __isl_take isl_qpolynomial *qp,
+ int div, __isl_take struct isl_upoly *s)
+{
+ int i;
+ int total;
+ int *reordering;
+
+ if (!qp || !s)
+ goto error;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ goto error;
+
+ total = isl_space_dim(qp->dim, isl_dim_all);
+ qp->upoly = isl_upoly_subs(qp->upoly, total + div, 1, &s);
+ if (!qp->upoly)
+ goto error;
+
+ reordering = isl_alloc_array(qp->dim->ctx, int, total + qp->div->n_row);
+ if (!reordering)
+ goto error;
+ for (i = 0; i < total + div; ++i)
+ reordering[i] = i;
+ for (i = total + div + 1; i < total + qp->div->n_row; ++i)
+ reordering[i] = i - 1;
+ qp->div = isl_mat_drop_rows(qp->div, div, 1);
+ qp->div = isl_mat_drop_cols(qp->div, 2 + total + div, 1);
+ qp->upoly = reorder(qp->upoly, reordering);
+ free(reordering);
+
+ if (!qp->upoly || !qp->div)
+ goto error;
+
+ isl_upoly_free(s);
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_upoly_free(s);
+ return NULL;
+}
+
+/* Replace all integer divisions [e/d] that turn out to not actually be integer
+ * divisions because d is equal to 1 by their definition, i.e., e.
+ */
+static __isl_give isl_qpolynomial *substitute_non_divs(
+ __isl_take isl_qpolynomial *qp)
+{
+ int i, j;
+ int total;
+ struct isl_upoly *s;
+
+ if (!qp)
+ return NULL;
+
+ total = isl_space_dim(qp->dim, isl_dim_all);
+ for (i = 0; qp && i < qp->div->n_row; ++i) {
+ if (!isl_int_is_one(qp->div->row[i][0]))
+ continue;
+ for (j = i + 1; j < qp->div->n_row; ++j) {
+ if (isl_int_is_zero(qp->div->row[j][2 + total + i]))
+ continue;
+ isl_seq_combine(qp->div->row[j] + 1,
+ qp->div->ctx->one, qp->div->row[j] + 1,
+ qp->div->row[j][2 + total + i],
+ qp->div->row[i] + 1, 1 + total + i);
+ isl_int_set_si(qp->div->row[j][2 + total + i], 0);
+ normalize_div(qp, j);
+ }
+ s = isl_upoly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
+ qp->div->row[i][0], qp->div->n_col - 1);
+ qp = substitute_div(qp, i, s);
+ --i;
+ }
+
+ return qp;
+}
+
+/* Reduce the coefficients of div "div" to lie in the interval [0, d-1],
+ * with d the denominator. When replacing the coefficient e of x by
+ * d * frac(e/d) = e - d * floor(e/d), we are subtracting d * floor(e/d) * x
+ * inside the division, so we need to add floor(e/d) * x outside.
+ * That is, we replace q by q' + floor(e/d) * x and we therefore need
+ * to adjust the coefficient of x in each later div that depends on the
+ * current div "div" and also in the affine expression "aff"
+ * (if it too depends on "div").
+ */
+static void reduce_div(__isl_keep isl_qpolynomial *qp, int div,
+ __isl_keep isl_vec *aff)
+{
+ int i, j;
+ isl_int v;
+ unsigned total = qp->div->n_col - qp->div->n_row - 2;
+
+ isl_int_init(v);
+ for (i = 0; i < 1 + total + div; ++i) {
+ if (isl_int_is_nonneg(qp->div->row[div][1 + i]) &&
+ isl_int_lt(qp->div->row[div][1 + i], qp->div->row[div][0]))
+ continue;
+ isl_int_fdiv_q(v, qp->div->row[div][1 + i], qp->div->row[div][0]);
+ isl_int_fdiv_r(qp->div->row[div][1 + i],
+ qp->div->row[div][1 + i], qp->div->row[div][0]);
+ if (!isl_int_is_zero(aff->el[1 + total + div]))
+ isl_int_addmul(aff->el[i], v, aff->el[1 + total + div]);
+ for (j = div + 1; j < qp->div->n_row; ++j) {
+ if (isl_int_is_zero(qp->div->row[j][2 + total + div]))
+ continue;
+ isl_int_addmul(qp->div->row[j][1 + i],
+ v, qp->div->row[j][2 + total + div]);
+ }
+ }
+ isl_int_clear(v);
+}
+
+/* Check if the last non-zero coefficient is bigger that half of the
+ * denominator. If so, we will invert the div to further reduce the number
+ * of distinct divs that may appear.
+ * If the last non-zero coefficient is exactly half the denominator,
+ * then we continue looking for earlier coefficients that are bigger
+ * than half the denominator.
+ */
+static int needs_invert(__isl_keep isl_mat *div, int row)
+{
+ int i;
+ int cmp;
+
+ for (i = div->n_col - 1; i >= 1; --i) {
+ if (isl_int_is_zero(div->row[row][i]))
+ continue;
+ isl_int_mul_ui(div->row[row][i], div->row[row][i], 2);
+ cmp = isl_int_cmp(div->row[row][i], div->row[row][0]);
+ isl_int_divexact_ui(div->row[row][i], div->row[row][i], 2);
+ if (cmp)
+ return cmp > 0;
+ if (i == 1)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Replace div "div" q = [e/d] by -[(-e+(d-1))/d].
+ * We only invert the coefficients of e (and the coefficient of q in
+ * later divs and in "aff"). After calling this function, the
+ * coefficients of e should be reduced again.
+ */
+static void invert_div(__isl_keep isl_qpolynomial *qp, int div,
+ __isl_keep isl_vec *aff)
+{
+ unsigned total = qp->div->n_col - qp->div->n_row - 2;
+
+ isl_seq_neg(qp->div->row[div] + 1,
+ qp->div->row[div] + 1, qp->div->n_col - 1);
+ isl_int_sub_ui(qp->div->row[div][1], qp->div->row[div][1], 1);
+ isl_int_add(qp->div->row[div][1],
+ qp->div->row[div][1], qp->div->row[div][0]);
+ if (!isl_int_is_zero(aff->el[1 + total + div]))
+ isl_int_neg(aff->el[1 + total + div], aff->el[1 + total + div]);
+ isl_mat_col_mul(qp->div, 2 + total + div,
+ qp->div->ctx->negone, 2 + total + div);
+}
+
+/* Assuming "qp" is a monomial, reduce all its divs to have coefficients
+ * in the interval [0, d-1], with d the denominator and such that the
+ * last non-zero coefficient that is not equal to d/2 is smaller than d/2.
+ *
+ * After the reduction, some divs may have become redundant or identical,
+ * so we call substitute_non_divs and sort_divs. If these functions
+ * eliminate divs or merge two or more divs into one, the coefficients
+ * of the enclosing divs may have to be reduced again, so we call
+ * ourselves recursively if the number of divs decreases.
+ */
+static __isl_give isl_qpolynomial *reduce_divs(__isl_take isl_qpolynomial *qp)
+{
+ int i;
+ isl_vec *aff = NULL;
+ struct isl_upoly *s;
+ unsigned n_div;
+
+ if (!qp)
+ return NULL;
+
+ aff = isl_vec_alloc(qp->div->ctx, qp->div->n_col - 1);
+ aff = isl_vec_clr(aff);
+ if (!aff)
+ goto error;
+
+ isl_int_set_si(aff->el[1 + qp->upoly->var], 1);
+
+ for (i = 0; i < qp->div->n_row; ++i) {
+ normalize_div(qp, i);
+ reduce_div(qp, i, aff);
+ if (needs_invert(qp->div, i)) {
+ invert_div(qp, i, aff);
+ reduce_div(qp, i, aff);
+ }
+ }
+
+ s = isl_upoly_from_affine(qp->div->ctx, aff->el,
+ qp->div->ctx->one, aff->size);
+ qp->upoly = isl_upoly_subs(qp->upoly, qp->upoly->var, 1, &s);
+ isl_upoly_free(s);
+ if (!qp->upoly)
+ goto error;
+
+ isl_vec_free(aff);
+
+ n_div = qp->div->n_row;
+ qp = substitute_non_divs(qp);
+ qp = sort_divs(qp);
+ if (qp && qp->div->n_row < n_div)
+ return reduce_divs(qp);
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_vec_free(aff);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
+ __isl_take isl_space *dim, const isl_int n, const isl_int d)
+{
+ struct isl_qpolynomial *qp;
+ struct isl_upoly_cst *cst;
+
+ if (!dim)
+ return NULL;
+
+ qp = isl_qpolynomial_alloc(dim, 0, isl_upoly_zero(dim->ctx));
+ if (!qp)
+ return NULL;
+
+ cst = isl_upoly_as_cst(qp->upoly);
+ isl_int_set(cst->n, n);
+ isl_int_set(cst->d, d);
+
+ return qp;
+}
+
+/* Return an isl_qpolynomial that is equal to "val" on domain space "domain".
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
+ __isl_take isl_space *domain, __isl_take isl_val *val)
+{
+ isl_qpolynomial *qp;
+ struct isl_upoly_cst *cst;
+
+ if (!domain || !val)
+ goto error;
+
+ qp = isl_qpolynomial_alloc(isl_space_copy(domain), 0,
+ isl_upoly_zero(domain->ctx));
+ if (!qp)
+ goto error;
+
+ cst = isl_upoly_as_cst(qp->upoly);
+ isl_int_set(cst->n, val->n);
+ isl_int_set(cst->d, val->d);
+
+ isl_space_free(domain);
+ isl_val_free(val);
+ return qp;
+error:
+ isl_space_free(domain);
+ isl_val_free(val);
+ return NULL;
+}
+
+static int up_set_active(__isl_keep struct isl_upoly *up, int *active, int d)
+{
+ struct isl_upoly_rec *rec;
+ int i;
+
+ if (!up)
+ return -1;
+
+ if (isl_upoly_is_cst(up))
+ return 0;
+
+ if (up->var < d)
+ active[up->var] = 1;
+
+ rec = isl_upoly_as_rec(up);
+ for (i = 0; i < rec->n; ++i)
+ if (up_set_active(rec->p[i], active, d) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int set_active(__isl_keep isl_qpolynomial *qp, int *active)
+{
+ int i, j;
+ int d = isl_space_dim(qp->dim, isl_dim_all);
+
+ if (!qp || !active)
+ return -1;
+
+ for (i = 0; i < d; ++i)
+ for (j = 0; j < qp->div->n_row; ++j) {
+ if (isl_int_is_zero(qp->div->row[j][2 + i]))
+ continue;
+ active[i] = 1;
+ break;
+ }
+
+ return up_set_active(qp->upoly, active, d);
+}
+
+int isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ int *active = NULL;
+ int involves = 0;
+
+ if (!qp)
+ return -1;
+ if (n == 0)
+ return 0;
+
+ isl_assert(qp->dim->ctx,
+ first + n <= isl_qpolynomial_dim(qp, type), return -1);
+ isl_assert(qp->dim->ctx, type == isl_dim_param ||
+ type == isl_dim_in, return -1);
+
+ active = isl_calloc_array(qp->dim->ctx, int,
+ isl_space_dim(qp->dim, isl_dim_all));
+ if (set_active(qp, active) < 0)
+ goto error;
+
+ if (type == isl_dim_in)
+ first += isl_space_dim(qp->dim, isl_dim_param);
+ for (i = 0; i < n; ++i)
+ if (active[first + i]) {
+ involves = 1;
+ break;
+ }
+
+ free(active);
+
+ return involves;
+error:
+ free(active);
+ return -1;
+}
+
+/* Remove divs that do not appear in the quasi-polynomial, nor in any
+ * of the divs that do appear in the quasi-polynomial.
+ */
+static __isl_give isl_qpolynomial *remove_redundant_divs(
+ __isl_take isl_qpolynomial *qp)
+{
+ int i, j;
+ int d;
+ int len;
+ int skip;
+ int *active = NULL;
+ int *reordering = NULL;
+ int redundant = 0;
+ int n_div;
+ isl_ctx *ctx;
+
+ if (!qp)
+ return NULL;
+ if (qp->div->n_row == 0)
+ return qp;
+
+ d = isl_space_dim(qp->dim, isl_dim_all);
+ len = qp->div->n_col - 2;
+ ctx = isl_qpolynomial_get_ctx(qp);
+ active = isl_calloc_array(ctx, int, len);
+ if (!active)
+ goto error;
+
+ if (up_set_active(qp->upoly, active, len) < 0)
+ goto error;
+
+ for (i = qp->div->n_row - 1; i >= 0; --i) {
+ if (!active[d + i]) {
+ redundant = 1;
+ continue;
+ }
+ for (j = 0; j < i; ++j) {
+ if (isl_int_is_zero(qp->div->row[i][2 + d + j]))
+ continue;
+ active[d + j] = 1;
+ break;
+ }
+ }
+
+ if (!redundant) {
+ free(active);
+ return qp;
+ }
+
+ reordering = isl_alloc_array(qp->div->ctx, int, len);
+ if (!reordering)
+ goto error;
+
+ for (i = 0; i < d; ++i)
+ reordering[i] = i;
+
+ skip = 0;
+ n_div = qp->div->n_row;
+ for (i = 0; i < n_div; ++i) {
+ if (!active[d + i]) {
+ qp->div = isl_mat_drop_rows(qp->div, i - skip, 1);
+ qp->div = isl_mat_drop_cols(qp->div,
+ 2 + d + i - skip, 1);
+ skip++;
+ }
+ reordering[d + i] = d + i - skip;
+ }
+
+ qp->upoly = reorder(qp->upoly, reordering);
+
+ if (!qp->upoly || !qp->div)
+ goto error;
+
+ free(active);
+ free(reordering);
+
+ return qp;
+error:
+ free(active);
+ free(reordering);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give struct isl_upoly *isl_upoly_drop(__isl_take struct isl_upoly *up,
+ unsigned first, unsigned n)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+ if (n == 0 || up->var < 0 || up->var < first)
+ return up;
+ if (up->var < first + n) {
+ up = replace_by_constant_term(up);
+ return isl_upoly_drop(up, first, n);
+ }
+ up = isl_upoly_cow(up);
+ if (!up)
+ return NULL;
+ up->var -= n;
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ rec->p[i] = isl_upoly_drop(rec->p[i], first, n);
+ if (!rec->p[i])
+ goto error;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+ qp->dim = isl_space_set_dim_name(qp->dim, type, pos, s);
+ if (!qp->dim)
+ goto error;
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ if (!qp)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(qp->dim->ctx, isl_error_invalid,
+ "cannot drop output/set dimension",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ isl_assert(qp->dim->ctx, first + n <= isl_space_dim(qp->dim, type),
+ goto error);
+ isl_assert(qp->dim->ctx, type == isl_dim_param ||
+ type == isl_dim_set, goto error);
+
+ qp->dim = isl_space_drop_dims(qp->dim, type, first, n);
+ if (!qp->dim)
+ goto error;
+
+ if (type == isl_dim_set)
+ first += isl_space_dim(qp->dim, isl_dim_param);
+
+ qp->div = isl_mat_drop_cols(qp->div, 2 + first, n);
+ if (!qp->div)
+ goto error;
+
+ qp->upoly = isl_upoly_drop(qp->upoly, first, n);
+ if (!qp->upoly)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+/* Project the domain of the quasi-polynomial onto its parameter space.
+ * The quasi-polynomial may not involve any of the domain dimensions.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(
+ __isl_take isl_qpolynomial *qp)
+{
+ isl_space *space;
+ unsigned n;
+ int involves;
+
+ n = isl_qpolynomial_dim(qp, isl_dim_in);
+ involves = isl_qpolynomial_involves_dims(qp, isl_dim_in, 0, n);
+ if (involves < 0)
+ return isl_qpolynomial_free(qp);
+ if (involves)
+ isl_die(isl_qpolynomial_get_ctx(qp), isl_error_invalid,
+ "polynomial involves some of the domain dimensions",
+ return isl_qpolynomial_free(qp));
+ qp = isl_qpolynomial_drop_dims(qp, isl_dim_in, 0, n);
+ space = isl_qpolynomial_get_domain_space(qp);
+ space = isl_space_params(space);
+ qp = isl_qpolynomial_reset_domain_space(qp, space);
+ return qp;
+}
+
+static __isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities_lifted(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)
+{
+ int i, j, k;
+ isl_int denom;
+ unsigned total;
+ unsigned n_div;
+ struct isl_upoly *up;
+
+ if (!eq)
+ goto error;
+ if (eq->n_eq == 0) {
+ isl_basic_set_free(eq);
+ return qp;
+ }
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ goto error;
+ qp->div = isl_mat_cow(qp->div);
+ if (!qp->div)
+ goto error;
+
+ total = 1 + isl_space_dim(eq->dim, isl_dim_all);
+ n_div = eq->n_div;
+ isl_int_init(denom);
+ for (i = 0; i < eq->n_eq; ++i) {
+ j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
+ if (j < 0 || j == 0 || j >= total)
+ continue;
+
+ for (k = 0; k < qp->div->n_row; ++k) {
+ if (isl_int_is_zero(qp->div->row[k][1 + j]))
+ continue;
+ isl_seq_elim(qp->div->row[k] + 1, eq->eq[i], j, total,
+ &qp->div->row[k][0]);
+ normalize_div(qp, k);
+ }
+
+ if (isl_int_is_pos(eq->eq[i][j]))
+ isl_seq_neg(eq->eq[i], eq->eq[i], total);
+ isl_int_abs(denom, eq->eq[i][j]);
+ isl_int_set_si(eq->eq[i][j], 0);
+
+ up = isl_upoly_from_affine(qp->dim->ctx,
+ eq->eq[i], denom, total);
+ qp->upoly = isl_upoly_subs(qp->upoly, j - 1, 1, &up);
+ isl_upoly_free(up);
+ }
+ isl_int_clear(denom);
+
+ if (!qp->upoly)
+ goto error;
+
+ isl_basic_set_free(eq);
+
+ qp = substitute_non_divs(qp);
+ qp = sort_divs(qp);
+
+ return qp;
+error:
+ isl_basic_set_free(eq);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+/* Exploit the equalities in "eq" to simplify the quasi-polynomial.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq)
+{
+ if (!qp || !eq)
+ goto error;
+ if (qp->div->n_row > 0)
+ eq = isl_basic_set_add_dims(eq, isl_dim_set, qp->div->n_row);
+ return isl_qpolynomial_substitute_equalities_lifted(qp, eq);
+error:
+ isl_basic_set_free(eq);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+static __isl_give isl_basic_set *add_div_constraints(
+ __isl_take isl_basic_set *bset, __isl_take isl_mat *div)
+{
+ int i;
+ unsigned total;
+
+ if (!bset || !div)
+ goto error;
+
+ bset = isl_basic_set_extend_constraints(bset, 0, 2 * div->n_row);
+ if (!bset)
+ goto error;
+ total = isl_basic_set_total_dim(bset);
+ for (i = 0; i < div->n_row; ++i)
+ if (isl_basic_set_add_div_constraints_var(bset,
+ total - div->n_row + i, div->row[i]) < 0)
+ goto error;
+
+ isl_mat_free(div);
+ return bset;
+error:
+ isl_mat_free(div);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Look for equalities among the variables shared by context and qp
+ * and the integer divisions of qp, if any.
+ * The equalities are then used to eliminate variables and/or integer
+ * divisions from qp.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_gist(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
+{
+ isl_basic_set *aff;
+
+ if (!qp)
+ goto error;
+ if (qp->div->n_row > 0) {
+ isl_basic_set *bset;
+ context = isl_set_add_dims(context, isl_dim_set,
+ qp->div->n_row);
+ bset = isl_basic_set_universe(isl_set_get_space(context));
+ bset = add_div_constraints(bset, isl_mat_copy(qp->div));
+ context = isl_set_intersect(context,
+ isl_set_from_basic_set(bset));
+ }
+
+ aff = isl_set_affine_hull(context);
+ return isl_qpolynomial_substitute_equalities_lifted(qp, aff);
+error:
+ isl_qpolynomial_free(qp);
+ isl_set_free(context);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *context)
+{
+ isl_space *space = isl_qpolynomial_get_domain_space(qp);
+ isl_set *dom_context = isl_set_universe(space);
+ dom_context = isl_set_intersect_params(dom_context, context);
+ return isl_qpolynomial_gist(qp, dom_context);
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
+ __isl_take isl_qpolynomial *qp)
+{
+ isl_set *dom;
+
+ if (!qp)
+ return NULL;
+ if (isl_qpolynomial_is_zero(qp)) {
+ isl_space *dim = isl_qpolynomial_get_space(qp);
+ isl_qpolynomial_free(qp);
+ return isl_pw_qpolynomial_zero(dim);
+ }
+
+ dom = isl_set_universe(isl_qpolynomial_get_domain_space(qp));
+ return isl_pw_qpolynomial_alloc(dom, qp);
+}
+
+#undef PW
+#define PW isl_pw_qpolynomial
+#undef EL
+#define EL isl_qpolynomial
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_zero
+#undef ZERO
+#define ZERO zero
+#undef IS_ZERO
+#define IS_ZERO is_zero
+#undef FIELD
+#define FIELD qp
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 1
+
+#define NO_PULLBACK
+
+#include <isl_pw_templ.c>
+
+#undef UNION
+#define UNION isl_union_pw_qpolynomial
+#undef PART
+#define PART isl_pw_qpolynomial
+#undef PARTS
+#define PARTS pw_qpolynomial
+#define ALIGN_DOMAIN
+
+#include <isl_union_templ.c>
+
+int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp)
+{
+ if (!pwqp)
+ return -1;
+
+ if (pwqp->n != -1)
+ return 0;
+
+ if (!isl_set_plain_is_universe(pwqp->p[0].set))
+ return 0;
+
+ return isl_qpolynomial_is_one(pwqp->p[0].qp);
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2)
+{
+ return isl_pw_qpolynomial_union_add_(pwqp1, pwqp2);
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
+ __isl_take isl_pw_qpolynomial *pwqp1,
+ __isl_take isl_pw_qpolynomial *pwqp2)
+{
+ int i, j, n;
+ struct isl_pw_qpolynomial *res;
+
+ if (!pwqp1 || !pwqp2)
+ goto error;
+
+ isl_assert(pwqp1->dim->ctx, isl_space_is_equal(pwqp1->dim, pwqp2->dim),
+ goto error);
+
+ if (isl_pw_qpolynomial_is_zero(pwqp1)) {
+ isl_pw_qpolynomial_free(pwqp2);
+ return pwqp1;
+ }
+
+ if (isl_pw_qpolynomial_is_zero(pwqp2)) {
+ isl_pw_qpolynomial_free(pwqp1);
+ return pwqp2;
+ }
+
+ if (isl_pw_qpolynomial_is_one(pwqp1)) {
+ isl_pw_qpolynomial_free(pwqp1);
+ return pwqp2;
+ }
+
+ if (isl_pw_qpolynomial_is_one(pwqp2)) {
+ isl_pw_qpolynomial_free(pwqp2);
+ return pwqp1;
+ }
+
+ n = pwqp1->n * pwqp2->n;
+ res = isl_pw_qpolynomial_alloc_size(isl_space_copy(pwqp1->dim), n);
+
+ for (i = 0; i < pwqp1->n; ++i) {
+ for (j = 0; j < pwqp2->n; ++j) {
+ struct isl_set *common;
+ struct isl_qpolynomial *prod;
+ common = isl_set_intersect(isl_set_copy(pwqp1->p[i].set),
+ isl_set_copy(pwqp2->p[j].set));
+ if (isl_set_plain_is_empty(common)) {
+ isl_set_free(common);
+ continue;
+ }
+
+ prod = isl_qpolynomial_mul(
+ isl_qpolynomial_copy(pwqp1->p[i].qp),
+ isl_qpolynomial_copy(pwqp2->p[j].qp));
+
+ res = isl_pw_qpolynomial_add_piece(res, common, prod);
+ }
+ }
+
+ isl_pw_qpolynomial_free(pwqp1);
+ isl_pw_qpolynomial_free(pwqp2);
+
+ return res;
+error:
+ isl_pw_qpolynomial_free(pwqp1);
+ isl_pw_qpolynomial_free(pwqp2);
+ return NULL;
+}
+
+__isl_give isl_val *isl_upoly_eval(__isl_take struct isl_upoly *up,
+ __isl_take isl_vec *vec)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+ isl_val *res;
+ isl_val *base;
+
+ if (isl_upoly_is_cst(up)) {
+ isl_vec_free(vec);
+ res = isl_upoly_get_constant_val(up);
+ isl_upoly_free(up);
+ return res;
+ }
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ isl_assert(up->ctx, rec->n >= 1, goto error);
+
+ base = isl_val_rat_from_isl_int(up->ctx,
+ vec->el[1 + up->var], vec->el[0]);
+
+ res = isl_upoly_eval(isl_upoly_copy(rec->p[rec->n - 1]),
+ isl_vec_copy(vec));
+
+ for (i = rec->n - 2; i >= 0; --i) {
+ res = isl_val_mul(res, isl_val_copy(base));
+ res = isl_val_add(res,
+ isl_upoly_eval(isl_upoly_copy(rec->p[i]),
+ isl_vec_copy(vec)));
+ }
+
+ isl_val_free(base);
+ isl_upoly_free(up);
+ isl_vec_free(vec);
+ return res;
+error:
+ isl_upoly_free(up);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
+ __isl_take isl_point *pnt)
+{
+ isl_vec *ext;
+ isl_val *v;
+
+ if (!qp || !pnt)
+ goto error;
+ isl_assert(pnt->dim->ctx, isl_space_is_equal(pnt->dim, qp->dim), goto error);
+
+ if (qp->div->n_row == 0)
+ ext = isl_vec_copy(pnt->vec);
+ else {
+ int i;
+ unsigned dim = isl_space_dim(qp->dim, isl_dim_all);
+ ext = isl_vec_alloc(qp->dim->ctx, 1 + dim + qp->div->n_row);
+ if (!ext)
+ goto error;
+
+ isl_seq_cpy(ext->el, pnt->vec->el, pnt->vec->size);
+ for (i = 0; i < qp->div->n_row; ++i) {
+ isl_seq_inner_product(qp->div->row[i] + 1, ext->el,
+ 1 + dim + i, &ext->el[1+dim+i]);
+ isl_int_fdiv_q(ext->el[1+dim+i], ext->el[1+dim+i],
+ qp->div->row[i][0]);
+ }
+ }
+
+ v = isl_upoly_eval(isl_upoly_copy(qp->upoly), ext);
+
+ isl_qpolynomial_free(qp);
+ isl_point_free(pnt);
+
+ return v;
+error:
+ isl_qpolynomial_free(qp);
+ isl_point_free(pnt);
+ return NULL;
+}
+
+int isl_upoly_cmp(__isl_keep struct isl_upoly_cst *cst1,
+ __isl_keep struct isl_upoly_cst *cst2)
+{
+ int cmp;
+ isl_int t;
+ isl_int_init(t);
+ isl_int_mul(t, cst1->n, cst2->d);
+ isl_int_submul(t, cst2->n, cst1->d);
+ cmp = isl_int_sgn(t);
+ isl_int_clear(t);
+ return cmp;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
+ __isl_take isl_qpolynomial *qp, enum isl_dim_type type,
+ unsigned first, unsigned n)
+{
+ unsigned total;
+ unsigned g_pos;
+ int *exp;
+
+ if (!qp)
+ return NULL;
+ if (type == isl_dim_out)
+ isl_die(qp->div->ctx, isl_error_invalid,
+ "cannot insert output/set dimensions",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+ if (n == 0 && !isl_space_is_named_or_nested(qp->dim, type))
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ isl_assert(qp->div->ctx, first <= isl_space_dim(qp->dim, type),
+ goto error);
+
+ g_pos = pos(qp->dim, type) + first;
+
+ qp->div = isl_mat_insert_zero_cols(qp->div, 2 + g_pos, n);
+ if (!qp->div)
+ goto error;
+
+ total = qp->div->n_col - 2;
+ if (total > g_pos) {
+ int i;
+ exp = isl_alloc_array(qp->div->ctx, int, total - g_pos);
+ if (!exp)
+ goto error;
+ for (i = 0; i < total - g_pos; ++i)
+ exp[i] = i + n;
+ qp->upoly = expand(qp->upoly, exp, g_pos);
+ free(exp);
+ if (!qp->upoly)
+ goto error;
+ }
+
+ qp->dim = isl_space_insert_dims(qp->dim, type, first, n);
+ if (!qp->dim)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_add_dims(
+ __isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n)
+{
+ unsigned pos;
+
+ pos = isl_qpolynomial_dim(qp, type);
+
+ return isl_qpolynomial_insert_dims(qp, type, pos, n);
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_dims(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned n)
+{
+ unsigned pos;
+
+ pos = isl_pw_qpolynomial_dim(pwqp, type);
+
+ return isl_pw_qpolynomial_insert_dims(pwqp, type, pos, n);
+}
+
+static int *reordering_move(isl_ctx *ctx,
+ unsigned len, unsigned dst, unsigned src, unsigned n)
+{
+ int i;
+ int *reordering;
+
+ reordering = isl_alloc_array(ctx, int, len);
+ if (!reordering)
+ return NULL;
+
+ if (dst <= src) {
+ for (i = 0; i < dst; ++i)
+ reordering[i] = i;
+ for (i = 0; i < n; ++i)
+ reordering[src + i] = dst + i;
+ for (i = 0; i < src - dst; ++i)
+ reordering[dst + i] = dst + n + i;
+ for (i = 0; i < len - src - n; ++i)
+ reordering[src + n + i] = src + n + i;
+ } else {
+ for (i = 0; i < src; ++i)
+ reordering[i] = i;
+ for (i = 0; i < n; ++i)
+ reordering[src + i] = dst + i;
+ for (i = 0; i < dst - src; ++i)
+ reordering[src + n + i] = src + i;
+ for (i = 0; i < len - dst - n; ++i)
+ reordering[dst + n + i] = dst + n + i;
+ }
+
+ return reordering;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ unsigned g_dst_pos;
+ unsigned g_src_pos;
+ int *reordering;
+
+ if (n == 0)
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ if (dst_type == isl_dim_out || src_type == isl_dim_out)
+ isl_die(qp->dim->ctx, isl_error_invalid,
+ "cannot move output/set dimension",
+ goto error);
+ if (dst_type == isl_dim_in)
+ dst_type = isl_dim_set;
+ if (src_type == isl_dim_in)
+ src_type = isl_dim_set;
+
+ isl_assert(qp->dim->ctx, src_pos + n <= isl_space_dim(qp->dim, src_type),
+ goto error);
+
+ g_dst_pos = pos(qp->dim, dst_type) + dst_pos;
+ g_src_pos = pos(qp->dim, src_type) + src_pos;
+ if (dst_type > src_type)
+ g_dst_pos -= n;
+
+ qp->div = isl_mat_move_cols(qp->div, 2 + g_dst_pos, 2 + g_src_pos, n);
+ if (!qp->div)
+ goto error;
+ qp = sort_divs(qp);
+ if (!qp)
+ goto error;
+
+ reordering = reordering_move(qp->dim->ctx,
+ qp->div->n_col - 2, g_dst_pos, g_src_pos, n);
+ if (!reordering)
+ goto error;
+
+ qp->upoly = reorder(qp->upoly, reordering);
+ free(reordering);
+ if (!qp->upoly)
+ goto error;
+
+ qp->dim = isl_space_move_dims(qp->dim, dst_type, dst_pos, src_type, src_pos, n);
+ if (!qp->dim)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(__isl_take isl_space *dim,
+ isl_int *f, isl_int denom)
+{
+ struct isl_upoly *up;
+
+ dim = isl_space_domain(dim);
+ if (!dim)
+ return NULL;
+
+ up = isl_upoly_from_affine(dim->ctx, f, denom,
+ 1 + isl_space_dim(dim, isl_dim_all));
+
+ return isl_qpolynomial_alloc(dim, 0, up);
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff)
+{
+ isl_ctx *ctx;
+ struct isl_upoly *up;
+ isl_qpolynomial *qp;
+
+ if (!aff)
+ return NULL;
+
+ ctx = isl_aff_get_ctx(aff);
+ up = isl_upoly_from_affine(ctx, aff->v->el + 1, aff->v->el[0],
+ aff->v->size - 1);
+
+ qp = isl_qpolynomial_alloc(isl_aff_get_domain_space(aff),
+ aff->ls->div->n_row, up);
+ if (!qp)
+ goto error;
+
+ isl_mat_free(qp->div);
+ qp->div = isl_mat_copy(aff->ls->div);
+ qp->div = isl_mat_cow(qp->div);
+ if (!qp->div)
+ goto error;
+
+ isl_aff_free(aff);
+ qp = reduce_divs(qp);
+ qp = remove_redundant_divs(qp);
+ return qp;
+error:
+ isl_aff_free(aff);
+ return isl_qpolynomial_free(qp);
+}
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(
+ __isl_take isl_pw_aff *pwaff)
+{
+ int i;
+ isl_pw_qpolynomial *pwqp;
+
+ if (!pwaff)
+ return NULL;
+
+ pwqp = isl_pw_qpolynomial_alloc_size(isl_pw_aff_get_space(pwaff),
+ pwaff->n);
+
+ for (i = 0; i < pwaff->n; ++i) {
+ isl_set *dom;
+ isl_qpolynomial *qp;
+
+ dom = isl_set_copy(pwaff->p[i].set);
+ qp = isl_qpolynomial_from_aff(isl_aff_copy(pwaff->p[i].aff));
+ pwqp = isl_pw_qpolynomial_add_piece(pwqp, dom, qp);
+ }
+
+ isl_pw_aff_free(pwaff);
+ return pwqp;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_constraint(
+ __isl_take isl_constraint *c, enum isl_dim_type type, unsigned pos)
+{
+ isl_aff *aff;
+
+ aff = isl_constraint_get_bound(c, type, pos);
+ isl_constraint_free(c);
+ return isl_qpolynomial_from_aff(aff);
+}
+
+/* For each 0 <= i < "n", replace variable "first" + i of type "type"
+ * in "qp" by subs[i].
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_substitute(
+ __isl_take isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned first, unsigned n,
+ __isl_keep isl_qpolynomial **subs)
+{
+ int i;
+ struct isl_upoly **ups;
+
+ if (n == 0)
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(qp->dim->ctx, isl_error_invalid,
+ "cannot substitute output/set dimension",
+ goto error);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ for (i = 0; i < n; ++i)
+ if (!subs[i])
+ goto error;
+
+ isl_assert(qp->dim->ctx, first + n <= isl_space_dim(qp->dim, type),
+ goto error);
+
+ for (i = 0; i < n; ++i)
+ isl_assert(qp->dim->ctx, isl_space_is_equal(qp->dim, subs[i]->dim),
+ goto error);
+
+ isl_assert(qp->dim->ctx, qp->div->n_row == 0, goto error);
+ for (i = 0; i < n; ++i)
+ isl_assert(qp->dim->ctx, subs[i]->div->n_row == 0, goto error);
+
+ first += pos(qp->dim, type);
+
+ ups = isl_alloc_array(qp->dim->ctx, struct isl_upoly *, n);
+ if (!ups)
+ goto error;
+ for (i = 0; i < n; ++i)
+ ups[i] = subs[i]->upoly;
+
+ qp->upoly = isl_upoly_subs(qp->upoly, first, n, ups);
+
+ free(ups);
+
+ if (!qp->upoly)
+ goto error;
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+/* Extend "bset" with extra set dimensions for each integer division
+ * in "qp" and then call "fn" with the extended bset and the polynomial
+ * that results from replacing each of the integer divisions by the
+ * corresponding extra set dimension.
+ */
+int isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
+ __isl_keep isl_basic_set *bset,
+ int (*fn)(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, void *user), void *user)
+{
+ isl_space *dim;
+ isl_mat *div;
+ isl_qpolynomial *poly;
+
+ if (!qp || !bset)
+ goto error;
+ if (qp->div->n_row == 0)
+ return fn(isl_basic_set_copy(bset), isl_qpolynomial_copy(qp),
+ user);
+
+ div = isl_mat_copy(qp->div);
+ dim = isl_space_copy(qp->dim);
+ dim = isl_space_add_dims(dim, isl_dim_set, qp->div->n_row);
+ poly = isl_qpolynomial_alloc(dim, 0, isl_upoly_copy(qp->upoly));
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_add_dims(bset, isl_dim_set, qp->div->n_row);
+ bset = add_div_constraints(bset, div);
+
+ return fn(bset, poly, user);
+error:
+ return -1;
+}
+
+/* Return total degree in variables first (inclusive) up to last (exclusive).
+ */
+int isl_upoly_degree(__isl_keep struct isl_upoly *up, int first, int last)
+{
+ int deg = -1;
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return -2;
+ if (isl_upoly_is_zero(up))
+ return -1;
+ if (isl_upoly_is_cst(up) || up->var < first)
+ return 0;
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return -2;
+
+ for (i = 0; i < rec->n; ++i) {
+ int d;
+
+ if (isl_upoly_is_zero(rec->p[i]))
+ continue;
+ d = isl_upoly_degree(rec->p[i], first, last);
+ if (up->var < last)
+ d += i;
+ if (d > deg)
+ deg = d;
+ }
+
+ return deg;
+}
+
+/* Return total degree in set variables.
+ */
+int isl_qpolynomial_degree(__isl_keep isl_qpolynomial *poly)
+{
+ unsigned ovar;
+ unsigned nvar;
+
+ if (!poly)
+ return -2;
+
+ ovar = isl_space_offset(poly->dim, isl_dim_set);
+ nvar = isl_space_dim(poly->dim, isl_dim_set);
+ return isl_upoly_degree(poly->upoly, ovar, ovar + nvar);
+}
+
+__isl_give struct isl_upoly *isl_upoly_coeff(__isl_keep struct isl_upoly *up,
+ unsigned pos, int deg)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+
+ if (isl_upoly_is_cst(up) || up->var < pos) {
+ if (deg == 0)
+ return isl_upoly_copy(up);
+ else
+ return isl_upoly_zero(up->ctx);
+ }
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ return NULL;
+
+ if (up->var == pos) {
+ if (deg < rec->n)
+ return isl_upoly_copy(rec->p[deg]);
+ else
+ return isl_upoly_zero(up->ctx);
+ }
+
+ up = isl_upoly_copy(up);
+ up = isl_upoly_cow(up);
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ struct isl_upoly *t;
+ t = isl_upoly_coeff(rec->p[i], pos, deg);
+ if (!t)
+ goto error;
+ isl_upoly_free(rec->p[i]);
+ rec->p[i] = t;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+/* Return coefficient of power "deg" of variable "t_pos" of type "type".
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_coeff(
+ __isl_keep isl_qpolynomial *qp,
+ enum isl_dim_type type, unsigned t_pos, int deg)
+{
+ unsigned g_pos;
+ struct isl_upoly *up;
+ isl_qpolynomial *c;
+
+ if (!qp)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(qp->div->ctx, isl_error_invalid,
+ "output/set dimension does not have a coefficient",
+ return NULL);
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ isl_assert(qp->div->ctx, t_pos < isl_space_dim(qp->dim, type),
+ return NULL);
+
+ g_pos = pos(qp->dim, type) + t_pos;
+ up = isl_upoly_coeff(qp->upoly, g_pos, deg);
+
+ c = isl_qpolynomial_alloc(isl_space_copy(qp->dim), qp->div->n_row, up);
+ if (!c)
+ return NULL;
+ isl_mat_free(c->div);
+ c->div = isl_mat_copy(qp->div);
+ if (!c->div)
+ goto error;
+ return c;
+error:
+ isl_qpolynomial_free(c);
+ return NULL;
+}
+
+/* Homogenize the polynomial in the variables first (inclusive) up to
+ * last (exclusive) by inserting powers of variable first.
+ * Variable first is assumed not to appear in the input.
+ */
+__isl_give struct isl_upoly *isl_upoly_homogenize(
+ __isl_take struct isl_upoly *up, int deg, int target,
+ int first, int last)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up)
+ return NULL;
+ if (isl_upoly_is_zero(up))
+ return up;
+ if (deg == target)
+ return up;
+ if (isl_upoly_is_cst(up) || up->var < first) {
+ struct isl_upoly *hom;
+
+ hom = isl_upoly_var_pow(up->ctx, first, target - deg);
+ if (!hom)
+ goto error;
+ rec = isl_upoly_as_rec(hom);
+ rec->p[target - deg] = isl_upoly_mul(rec->p[target - deg], up);
+
+ return hom;
+ }
+
+ up = isl_upoly_cow(up);
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ if (isl_upoly_is_zero(rec->p[i]))
+ continue;
+ rec->p[i] = isl_upoly_homogenize(rec->p[i],
+ up->var < last ? deg + i : i, target,
+ first, last);
+ if (!rec->p[i])
+ goto error;
+ }
+
+ return up;
+error:
+ isl_upoly_free(up);
+ return NULL;
+}
+
+/* Homogenize the polynomial in the set variables by introducing
+ * powers of an extra set variable at position 0.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
+ __isl_take isl_qpolynomial *poly)
+{
+ unsigned ovar;
+ unsigned nvar;
+ int deg = isl_qpolynomial_degree(poly);
+
+ if (deg < -1)
+ goto error;
+
+ poly = isl_qpolynomial_insert_dims(poly, isl_dim_in, 0, 1);
+ poly = isl_qpolynomial_cow(poly);
+ if (!poly)
+ goto error;
+
+ ovar = isl_space_offset(poly->dim, isl_dim_set);
+ nvar = isl_space_dim(poly->dim, isl_dim_set);
+ poly->upoly = isl_upoly_homogenize(poly->upoly, 0, deg,
+ ovar, ovar + nvar);
+ if (!poly->upoly)
+ goto error;
+
+ return poly;
+error:
+ isl_qpolynomial_free(poly);
+ return NULL;
+}
+
+__isl_give isl_term *isl_term_alloc(__isl_take isl_space *dim,
+ __isl_take isl_mat *div)
+{
+ isl_term *term;
+ int n;
+
+ if (!dim || !div)
+ goto error;
+
+ n = isl_space_dim(dim, isl_dim_all) + div->n_row;
+
+ term = isl_calloc(dim->ctx, struct isl_term,
+ sizeof(struct isl_term) + (n - 1) * sizeof(int));
+ if (!term)
+ goto error;
+
+ term->ref = 1;
+ term->dim = dim;
+ term->div = div;
+ isl_int_init(term->n);
+ isl_int_init(term->d);
+
+ return term;
+error:
+ isl_space_free(dim);
+ isl_mat_free(div);
+ return NULL;
+}
+
+__isl_give isl_term *isl_term_copy(__isl_keep isl_term *term)
+{
+ if (!term)
+ return NULL;
+
+ term->ref++;
+ return term;
+}
+
+__isl_give isl_term *isl_term_dup(__isl_keep isl_term *term)
+{
+ int i;
+ isl_term *dup;
+ unsigned total;
+
+ if (!term)
+ return NULL;
+
+ total = isl_space_dim(term->dim, isl_dim_all) + term->div->n_row;
+
+ dup = isl_term_alloc(isl_space_copy(term->dim), isl_mat_copy(term->div));
+ if (!dup)
+ return NULL;
+
+ isl_int_set(dup->n, term->n);
+ isl_int_set(dup->d, term->d);
+
+ for (i = 0; i < total; ++i)
+ dup->pow[i] = term->pow[i];
+
+ return dup;
+}
+
+__isl_give isl_term *isl_term_cow(__isl_take isl_term *term)
+{
+ if (!term)
+ return NULL;
+
+ if (term->ref == 1)
+ return term;
+ term->ref--;
+ return isl_term_dup(term);
+}
+
+void isl_term_free(__isl_take isl_term *term)
+{
+ if (!term)
+ return;
+
+ if (--term->ref > 0)
+ return;
+
+ isl_space_free(term->dim);
+ isl_mat_free(term->div);
+ isl_int_clear(term->n);
+ isl_int_clear(term->d);
+ free(term);
+}
+
+unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type)
+{
+ if (!term)
+ return 0;
+
+ switch (type) {
+ case isl_dim_param:
+ case isl_dim_in:
+ case isl_dim_out: return isl_space_dim(term->dim, type);
+ case isl_dim_div: return term->div->n_row;
+ case isl_dim_all: return isl_space_dim(term->dim, isl_dim_all) +
+ term->div->n_row;
+ default: return 0;
+ }
+}
+
+isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term)
+{
+ return term ? term->dim->ctx : NULL;
+}
+
+void isl_term_get_num(__isl_keep isl_term *term, isl_int *n)
+{
+ if (!term)
+ return;
+ isl_int_set(*n, term->n);
+}
+
+void isl_term_get_den(__isl_keep isl_term *term, isl_int *d)
+{
+ if (!term)
+ return;
+ isl_int_set(*d, term->d);
+}
+
+/* Return the coefficient of the term "term".
+ */
+__isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term)
+{
+ if (!term)
+ return NULL;
+
+ return isl_val_rat_from_isl_int(isl_term_get_ctx(term),
+ term->n, term->d);
+}
+
+int isl_term_get_exp(__isl_keep isl_term *term,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!term)
+ return -1;
+
+ isl_assert(term->dim->ctx, pos < isl_term_dim(term, type), return -1);
+
+ if (type >= isl_dim_set)
+ pos += isl_space_dim(term->dim, isl_dim_param);
+ if (type >= isl_dim_div)
+ pos += isl_space_dim(term->dim, isl_dim_set);
+
+ return term->pow[pos];
+}
+
+__isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos)
+{
+ isl_local_space *ls;
+ isl_aff *aff;
+
+ if (!term)
+ return NULL;
+
+ isl_assert(term->dim->ctx, pos < isl_term_dim(term, isl_dim_div),
+ return NULL);
+
+ ls = isl_local_space_alloc_div(isl_space_copy(term->dim),
+ isl_mat_copy(term->div));
+ aff = isl_aff_alloc(ls);
+ if (!aff)
+ return NULL;
+
+ isl_seq_cpy(aff->v->el, term->div->row[pos], aff->v->size);
+
+ aff = isl_aff_normalize(aff);
+
+ return aff;
+}
+
+__isl_give isl_term *isl_upoly_foreach_term(__isl_keep struct isl_upoly *up,
+ int (*fn)(__isl_take isl_term *term, void *user),
+ __isl_take isl_term *term, void *user)
+{
+ int i;
+ struct isl_upoly_rec *rec;
+
+ if (!up || !term)
+ goto error;
+
+ if (isl_upoly_is_zero(up))
+ return term;
+
+ isl_assert(up->ctx, !isl_upoly_is_nan(up), goto error);
+ isl_assert(up->ctx, !isl_upoly_is_infty(up), goto error);
+ isl_assert(up->ctx, !isl_upoly_is_neginfty(up), goto error);
+
+ if (isl_upoly_is_cst(up)) {
+ struct isl_upoly_cst *cst;
+ cst = isl_upoly_as_cst(up);
+ if (!cst)
+ goto error;
+ term = isl_term_cow(term);
+ if (!term)
+ goto error;
+ isl_int_set(term->n, cst->n);
+ isl_int_set(term->d, cst->d);
+ if (fn(isl_term_copy(term), user) < 0)
+ goto error;
+ return term;
+ }
+
+ rec = isl_upoly_as_rec(up);
+ if (!rec)
+ goto error;
+
+ for (i = 0; i < rec->n; ++i) {
+ term = isl_term_cow(term);
+ if (!term)
+ goto error;
+ term->pow[up->var] = i;
+ term = isl_upoly_foreach_term(rec->p[i], fn, term, user);
+ if (!term)
+ goto error;
+ }
+ term->pow[up->var] = 0;
+
+ return term;
+error:
+ isl_term_free(term);
+ return NULL;
+}
+
+int isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
+ int (*fn)(__isl_take isl_term *term, void *user), void *user)
+{
+ isl_term *term;
+
+ if (!qp)
+ return -1;
+
+ term = isl_term_alloc(isl_space_copy(qp->dim), isl_mat_copy(qp->div));
+ if (!term)
+ return -1;
+
+ term = isl_upoly_foreach_term(qp->upoly, fn, term, user);
+
+ isl_term_free(term);
+
+ return term ? 0 : -1;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term)
+{
+ struct isl_upoly *up;
+ isl_qpolynomial *qp;
+ int i, n;
+
+ if (!term)
+ return NULL;
+
+ n = isl_space_dim(term->dim, isl_dim_all) + term->div->n_row;
+
+ up = isl_upoly_rat_cst(term->dim->ctx, term->n, term->d);
+ for (i = 0; i < n; ++i) {
+ if (!term->pow[i])
+ continue;
+ up = isl_upoly_mul(up,
+ isl_upoly_var_pow(term->dim->ctx, i, term->pow[i]));
+ }
+
+ qp = isl_qpolynomial_alloc(isl_space_copy(term->dim), term->div->n_row, up);
+ if (!qp)
+ goto error;
+ isl_mat_free(qp->div);
+ qp->div = isl_mat_copy(term->div);
+ if (!qp->div)
+ goto error;
+
+ isl_term_free(term);
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_term_free(term);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
+ __isl_take isl_space *dim)
+{
+ int i;
+ int extra;
+ unsigned total;
+
+ if (!qp || !dim)
+ goto error;
+
+ if (isl_space_is_equal(qp->dim, dim)) {
+ isl_space_free(dim);
+ return qp;
+ }
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ goto error;
+
+ extra = isl_space_dim(dim, isl_dim_set) -
+ isl_space_dim(qp->dim, isl_dim_set);
+ total = isl_space_dim(qp->dim, isl_dim_all);
+ if (qp->div->n_row) {
+ int *exp;
+
+ exp = isl_alloc_array(qp->div->ctx, int, qp->div->n_row);
+ if (!exp)
+ goto error;
+ for (i = 0; i < qp->div->n_row; ++i)
+ exp[i] = extra + i;
+ qp->upoly = expand(qp->upoly, exp, total);
+ free(exp);
+ if (!qp->upoly)
+ goto error;
+ }
+ qp->div = isl_mat_insert_cols(qp->div, 2 + total, extra);
+ if (!qp->div)
+ goto error;
+ for (i = 0; i < qp->div->n_row; ++i)
+ isl_seq_clr(qp->div->row[i] + 2 + total, extra);
+
+ isl_space_free(qp->dim);
+ qp->dim = dim;
+
+ return qp;
+error:
+ isl_space_free(dim);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+/* For each parameter or variable that does not appear in qp,
+ * first eliminate the variable from all constraints and then set it to zero.
+ */
+static __isl_give isl_set *fix_inactive(__isl_take isl_set *set,
+ __isl_keep isl_qpolynomial *qp)
+{
+ int *active = NULL;
+ int i;
+ int d;
+ unsigned nparam;
+ unsigned nvar;
+
+ if (!set || !qp)
+ goto error;
+
+ d = isl_space_dim(set->dim, isl_dim_all);
+ active = isl_calloc_array(set->ctx, int, d);
+ if (set_active(qp, active) < 0)
+ goto error;
+
+ for (i = 0; i < d; ++i)
+ if (!active[i])
+ break;
+
+ if (i == d) {
+ free(active);
+ return set;
+ }
+
+ nparam = isl_space_dim(set->dim, isl_dim_param);
+ nvar = isl_space_dim(set->dim, isl_dim_set);
+ for (i = 0; i < nparam; ++i) {
+ if (active[i])
+ continue;
+ set = isl_set_eliminate(set, isl_dim_param, i, 1);
+ set = isl_set_fix_si(set, isl_dim_param, i, 0);
+ }
+ for (i = 0; i < nvar; ++i) {
+ if (active[nparam + i])
+ continue;
+ set = isl_set_eliminate(set, isl_dim_set, i, 1);
+ set = isl_set_fix_si(set, isl_dim_set, i, 0);
+ }
+
+ free(active);
+
+ return set;
+error:
+ free(active);
+ isl_set_free(set);
+ return NULL;
+}
+
+struct isl_opt_data {
+ isl_qpolynomial *qp;
+ int first;
+ isl_val *opt;
+ int max;
+};
+
+static int opt_fn(__isl_take isl_point *pnt, void *user)
+{
+ struct isl_opt_data *data = (struct isl_opt_data *)user;
+ isl_val *val;
+
+ val = isl_qpolynomial_eval(isl_qpolynomial_copy(data->qp), pnt);
+ if (data->first) {
+ data->first = 0;
+ data->opt = val;
+ } else if (data->max) {
+ data->opt = isl_val_max(data->opt, val);
+ } else {
+ data->opt = isl_val_min(data->opt, val);
+ }
+
+ return 0;
+}
+
+__isl_give isl_val *isl_qpolynomial_opt_on_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *set, int max)
+{
+ struct isl_opt_data data = { NULL, 1, NULL, max };
+
+ if (!set || !qp)
+ goto error;
+
+ if (isl_upoly_is_cst(qp->upoly)) {
+ isl_set_free(set);
+ data.opt = isl_qpolynomial_get_constant_val(qp);
+ isl_qpolynomial_free(qp);
+ return data.opt;
+ }
+
+ set = fix_inactive(set, qp);
+
+ data.qp = qp;
+ if (isl_set_foreach_point(set, opt_fn, &data) < 0)
+ goto error;
+
+ if (data.first)
+ data.opt = isl_val_zero(isl_set_get_ctx(set));
+
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ return data.opt;
+error:
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ isl_val_free(data.opt);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_morph *morph)
+{
+ int i;
+ int n_sub;
+ isl_ctx *ctx;
+ struct isl_upoly **subs;
+ isl_mat *mat, *diag;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp || !morph)
+ goto error;
+
+ ctx = qp->dim->ctx;
+ isl_assert(ctx, isl_space_is_equal(qp->dim, morph->dom->dim), goto error);
+
+ n_sub = morph->inv->n_row - 1;
+ if (morph->inv->n_row != morph->inv->n_col)
+ n_sub += qp->div->n_row;
+ subs = isl_calloc_array(ctx, struct isl_upoly *, n_sub);
+ if (n_sub && !subs)
+ goto error;
+
+ for (i = 0; 1 + i < morph->inv->n_row; ++i)
+ subs[i] = isl_upoly_from_affine(ctx, morph->inv->row[1 + i],
+ morph->inv->row[0][0], morph->inv->n_col);
+ if (morph->inv->n_row != morph->inv->n_col)
+ for (i = 0; i < qp->div->n_row; ++i)
+ subs[morph->inv->n_row - 1 + i] =
+ isl_upoly_var_pow(ctx, morph->inv->n_col - 1 + i, 1);
+
+ qp->upoly = isl_upoly_subs(qp->upoly, 0, n_sub, subs);
+
+ for (i = 0; i < n_sub; ++i)
+ isl_upoly_free(subs[i]);
+ free(subs);
+
+ diag = isl_mat_diag(ctx, 1, morph->inv->row[0][0]);
+ mat = isl_mat_diagonal(diag, isl_mat_copy(morph->inv));
+ diag = isl_mat_diag(ctx, qp->div->n_row, morph->inv->row[0][0]);
+ mat = isl_mat_diagonal(mat, diag);
+ qp->div = isl_mat_product(qp->div, mat);
+ isl_space_free(qp->dim);
+ qp->dim = isl_space_copy(morph->ran->dim);
+
+ if (!qp->upoly || !qp->div || !qp->dim)
+ goto error;
+
+ isl_morph_free(morph);
+
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_morph_free(morph);
+ return NULL;
+}
+
+static int neg_entry(void **entry, void *user)
+{
+ isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
+
+ *pwqp = isl_pw_qpolynomial_neg(*pwqp);
+
+ return *pwqp ? 0 : -1;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_neg(
+ __isl_take isl_union_pw_qpolynomial *upwqp)
+{
+ upwqp = isl_union_pw_qpolynomial_cow(upwqp);
+ if (!upwqp)
+ return NULL;
+
+ if (isl_hash_table_foreach(upwqp->space->ctx, &upwqp->table,
+ &neg_entry, NULL) < 0)
+ goto error;
+
+ return upwqp;
+error:
+ isl_union_pw_qpolynomial_free(upwqp);
+ return NULL;
+}
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(
+ __isl_take isl_union_pw_qpolynomial *upwqp1,
+ __isl_take isl_union_pw_qpolynomial *upwqp2)
+{
+ return match_bin_op(upwqp1, upwqp2, &isl_pw_qpolynomial_mul);
+}
+
+/* Reorder the columns of the given div definitions according to the
+ * given reordering.
+ */
+static __isl_give isl_mat *reorder_divs(__isl_take isl_mat *div,
+ __isl_take isl_reordering *r)
+{
+ int i, j;
+ isl_mat *mat;
+ int extra;
+
+ if (!div || !r)
+ goto error;
+
+ extra = isl_space_dim(r->dim, isl_dim_all) + div->n_row - r->len;
+ mat = isl_mat_alloc(div->ctx, div->n_row, div->n_col + extra);
+ if (!mat)
+ goto error;
+
+ for (i = 0; i < div->n_row; ++i) {
+ isl_seq_cpy(mat->row[i], div->row[i], 2);
+ isl_seq_clr(mat->row[i] + 2, mat->n_col - 2);
+ for (j = 0; j < r->len; ++j)
+ isl_int_set(mat->row[i][2 + r->pos[j]],
+ div->row[i][2 + j]);
+ }
+
+ isl_reordering_free(r);
+ isl_mat_free(div);
+ return mat;
+error:
+ isl_reordering_free(r);
+ isl_mat_free(div);
+ return NULL;
+}
+
+/* Reorder the dimension of "qp" according to the given reordering.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_realign_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_reordering *r)
+{
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ goto error;
+
+ r = isl_reordering_extend(r, qp->div->n_row);
+ if (!r)
+ goto error;
+
+ qp->div = reorder_divs(qp->div, isl_reordering_copy(r));
+ if (!qp->div)
+ goto error;
+
+ qp->upoly = reorder(qp->upoly, r->pos);
+ if (!qp->upoly)
+ goto error;
+
+ qp = isl_qpolynomial_reset_domain_space(qp, isl_space_copy(r->dim));
+
+ isl_reordering_free(r);
+ return qp;
+error:
+ isl_qpolynomial_free(qp);
+ isl_reordering_free(r);
+ return NULL;
+}
+
+__isl_give isl_qpolynomial *isl_qpolynomial_align_params(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *model)
+{
+ if (!qp || !model)
+ goto error;
+
+ if (!isl_space_match(qp->dim, isl_dim_param, model, isl_dim_param)) {
+ isl_reordering *exp;
+
+ model = isl_space_drop_dims(model, isl_dim_in,
+ 0, isl_space_dim(model, isl_dim_in));
+ model = isl_space_drop_dims(model, isl_dim_out,
+ 0, isl_space_dim(model, isl_dim_out));
+ exp = isl_parameter_alignment_reordering(qp->dim, model);
+ exp = isl_reordering_extend_space(exp,
+ isl_qpolynomial_get_domain_space(qp));
+ qp = isl_qpolynomial_realign_domain(qp, exp);
+ }
+
+ isl_space_free(model);
+ return qp;
+error:
+ isl_space_free(model);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+struct isl_split_periods_data {
+ int max_periods;
+ isl_pw_qpolynomial *res;
+};
+
+/* Create a slice where the integer division "div" has the fixed value "v".
+ * In particular, if "div" refers to floor(f/m), then create a slice
+ *
+ * m v <= f <= m v + (m - 1)
+ *
+ * or
+ *
+ * f - m v >= 0
+ * -f + m v + (m - 1) >= 0
+ */
+static __isl_give isl_set *set_div_slice(__isl_take isl_space *dim,
+ __isl_keep isl_qpolynomial *qp, int div, isl_int v)
+{
+ int total;
+ isl_basic_set *bset = NULL;
+ int k;
+
+ if (!dim || !qp)
+ goto error;
+
+ total = isl_space_dim(dim, isl_dim_all);
+ bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0, 0, 2);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->ineq[k], qp->div->row[div] + 1, 1 + total);
+ isl_int_submul(bset->ineq[k][0], v, qp->div->row[div][0]);
+
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_neg(bset->ineq[k], qp->div->row[div] + 1, 1 + total);
+ isl_int_addmul(bset->ineq[k][0], v, qp->div->row[div][0]);
+ isl_int_add(bset->ineq[k][0], bset->ineq[k][0], qp->div->row[div][0]);
+ isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+
+ isl_space_free(dim);
+ return isl_set_from_basic_set(bset);
+error:
+ isl_basic_set_free(bset);
+ isl_space_free(dim);
+ return NULL;
+}
+
+static int split_periods(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp, void *user);
+
+/* Create a slice of the domain "set" such that integer division "div"
+ * has the fixed value "v" and add the results to data->res,
+ * replacing the integer division by "v" in "qp".
+ */
+static int set_div(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp, int div, isl_int v,
+ struct isl_split_periods_data *data)
+{
+ int i;
+ int total;
+ isl_set *slice;
+ struct isl_upoly *cst;
+
+ slice = set_div_slice(isl_set_get_space(set), qp, div, v);
+ set = isl_set_intersect(set, slice);
+
+ if (!qp)
+ goto error;
+
+ total = isl_space_dim(qp->dim, isl_dim_all);
+
+ for (i = div + 1; i < qp->div->n_row; ++i) {
+ if (isl_int_is_zero(qp->div->row[i][2 + total + div]))
+ continue;
+ isl_int_addmul(qp->div->row[i][1],
+ qp->div->row[i][2 + total + div], v);
+ isl_int_set_si(qp->div->row[i][2 + total + div], 0);
+ }
+
+ cst = isl_upoly_rat_cst(qp->dim->ctx, v, qp->dim->ctx->one);
+ qp = substitute_div(qp, div, cst);
+
+ return split_periods(set, qp, data);
+error:
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ return -1;
+}
+
+/* Split the domain "set" such that integer division "div"
+ * has a fixed value (ranging from "min" to "max") on each slice
+ * and add the results to data->res.
+ */
+static int split_div(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp, int div, isl_int min, isl_int max,
+ struct isl_split_periods_data *data)
+{
+ for (; isl_int_le(min, max); isl_int_add_ui(min, min, 1)) {
+ isl_set *set_i = isl_set_copy(set);
+ isl_qpolynomial *qp_i = isl_qpolynomial_copy(qp);
+
+ if (set_div(set_i, qp_i, div, min, data) < 0)
+ goto error;
+ }
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ return 0;
+error:
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ return -1;
+}
+
+/* If "qp" refers to any integer division
+ * that can only attain "max_periods" distinct values on "set"
+ * then split the domain along those distinct values.
+ * Add the results (or the original if no splitting occurs)
+ * to data->res.
+ */
+static int split_periods(__isl_take isl_set *set,
+ __isl_take isl_qpolynomial *qp, void *user)
+{
+ int i;
+ isl_pw_qpolynomial *pwqp;
+ struct isl_split_periods_data *data;
+ isl_int min, max;
+ int total;
+ int r = 0;
+
+ data = (struct isl_split_periods_data *)user;
+
+ if (!set || !qp)
+ goto error;
+
+ if (qp->div->n_row == 0) {
+ pwqp = isl_pw_qpolynomial_alloc(set, qp);
+ data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);
+ return 0;
+ }
+
+ isl_int_init(min);
+ isl_int_init(max);
+ total = isl_space_dim(qp->dim, isl_dim_all);
+ for (i = 0; i < qp->div->n_row; ++i) {
+ enum isl_lp_result lp_res;
+
+ if (isl_seq_first_non_zero(qp->div->row[i] + 2 + total,
+ qp->div->n_row) != -1)
+ continue;
+
+ lp_res = isl_set_solve_lp(set, 0, qp->div->row[i] + 1,
+ set->ctx->one, &min, NULL, NULL);
+ if (lp_res == isl_lp_error)
+ goto error2;
+ if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)
+ continue;
+ isl_int_fdiv_q(min, min, qp->div->row[i][0]);
+
+ lp_res = isl_set_solve_lp(set, 1, qp->div->row[i] + 1,
+ set->ctx->one, &max, NULL, NULL);
+ if (lp_res == isl_lp_error)
+ goto error2;
+ if (lp_res == isl_lp_unbounded || lp_res == isl_lp_empty)
+ continue;
+ isl_int_fdiv_q(max, max, qp->div->row[i][0]);
+
+ isl_int_sub(max, max, min);
+ if (isl_int_cmp_si(max, data->max_periods) < 0) {
+ isl_int_add(max, max, min);
+ break;
+ }
+ }
+
+ if (i < qp->div->n_row) {
+ r = split_div(set, qp, i, min, max, data);
+ } else {
+ pwqp = isl_pw_qpolynomial_alloc(set, qp);
+ data->res = isl_pw_qpolynomial_add_disjoint(data->res, pwqp);
+ }
+
+ isl_int_clear(max);
+ isl_int_clear(min);
+
+ return r;
+error2:
+ isl_int_clear(max);
+ isl_int_clear(min);
+error:
+ isl_set_free(set);
+ isl_qpolynomial_free(qp);
+ return -1;
+}
+
+/* If any quasi-polynomial in pwqp refers to any integer division
+ * that can only attain "max_periods" distinct values on its domain
+ * then split the domain along those distinct values.
+ */
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_periods(
+ __isl_take isl_pw_qpolynomial *pwqp, int max_periods)
+{
+ struct isl_split_periods_data data;
+
+ data.max_periods = max_periods;
+ data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));
+
+ if (isl_pw_qpolynomial_foreach_piece(pwqp, &split_periods, &data) < 0)
+ goto error;
+
+ isl_pw_qpolynomial_free(pwqp);
+
+ return data.res;
+error:
+ isl_pw_qpolynomial_free(data.res);
+ isl_pw_qpolynomial_free(pwqp);
+ return NULL;
+}
+
+/* Construct a piecewise quasipolynomial that is constant on the given
+ * domain. In particular, it is
+ * 0 if cst == 0
+ * 1 if cst == 1
+ * infinity if cst == -1
+ */
+static __isl_give isl_pw_qpolynomial *constant_on_domain(
+ __isl_take isl_basic_set *bset, int cst)
+{
+ isl_space *dim;
+ isl_qpolynomial *qp;
+
+ if (!bset)
+ return NULL;
+
+ bset = isl_basic_set_params(bset);
+ dim = isl_basic_set_get_space(bset);
+ if (cst < 0)
+ qp = isl_qpolynomial_infty_on_domain(dim);
+ else if (cst == 0)
+ qp = isl_qpolynomial_zero_on_domain(dim);
+ else
+ qp = isl_qpolynomial_one_on_domain(dim);
+ return isl_pw_qpolynomial_alloc(isl_set_from_basic_set(bset), qp);
+}
+
+/* Factor bset, call fn on each of the factors and return the product.
+ *
+ * If no factors can be found, simply call fn on the input.
+ * Otherwise, construct the factors based on the factorizer,
+ * call fn on each factor and compute the product.
+ */
+static __isl_give isl_pw_qpolynomial *compressed_multiplicative_call(
+ __isl_take isl_basic_set *bset,
+ __isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))
+{
+ int i, n;
+ isl_space *dim;
+ isl_set *set;
+ isl_factorizer *f;
+ isl_qpolynomial *qp;
+ isl_pw_qpolynomial *pwqp;
+ unsigned nparam;
+ unsigned nvar;
+
+ f = isl_basic_set_factorizer(bset);
+ if (!f)
+ goto error;
+ if (f->n_group == 0) {
+ isl_factorizer_free(f);
+ return fn(bset);
+ }
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ dim = isl_basic_set_get_space(bset);
+ dim = isl_space_domain(dim);
+ set = isl_set_universe(isl_space_copy(dim));
+ qp = isl_qpolynomial_one_on_domain(dim);
+ pwqp = isl_pw_qpolynomial_alloc(set, qp);
+
+ bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset);
+
+ for (i = 0, n = 0; i < f->n_group; ++i) {
+ isl_basic_set *bset_i;
+ isl_pw_qpolynomial *pwqp_i;
+
+ bset_i = isl_basic_set_copy(bset);
+ bset_i = isl_basic_set_drop_constraints_involving(bset_i,
+ nparam + n + f->len[i], nvar - n - f->len[i]);
+ bset_i = isl_basic_set_drop_constraints_involving(bset_i,
+ nparam, n);
+ bset_i = isl_basic_set_drop(bset_i, isl_dim_set,
+ n + f->len[i], nvar - n - f->len[i]);
+ bset_i = isl_basic_set_drop(bset_i, isl_dim_set, 0, n);
+
+ pwqp_i = fn(bset_i);
+ pwqp = isl_pw_qpolynomial_mul(pwqp, pwqp_i);
+
+ n += f->len[i];
+ }
+
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+
+ return pwqp;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Factor bset, call fn on each of the factors and return the product.
+ * The function is assumed to evaluate to zero on empty domains,
+ * to one on zero-dimensional domains and to infinity on unbounded domains
+ * and will not be called explicitly on zero-dimensional or unbounded domains.
+ *
+ * We first check for some special cases and remove all equalities.
+ * Then we hand over control to compressed_multiplicative_call.
+ */
+__isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
+ __isl_take isl_basic_set *bset,
+ __isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset))
+{
+ int bounded;
+ isl_morph *morph;
+ isl_pw_qpolynomial *pwqp;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return constant_on_domain(bset, 0);
+
+ if (isl_basic_set_dim(bset, isl_dim_set) == 0)
+ return constant_on_domain(bset, 1);
+
+ bounded = isl_basic_set_is_bounded(bset);
+ if (bounded < 0)
+ goto error;
+ if (!bounded)
+ return constant_on_domain(bset, -1);
+
+ if (bset->n_eq == 0)
+ return compressed_multiplicative_call(bset, fn);
+
+ morph = isl_basic_set_full_compression(bset);
+ bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+
+ pwqp = compressed_multiplicative_call(bset, fn);
+
+ morph = isl_morph_dom_params(morph);
+ morph = isl_morph_ran_params(morph);
+ morph = isl_morph_inverse(morph);
+
+ pwqp = isl_pw_qpolynomial_morph_domain(pwqp, morph);
+
+ return pwqp;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Drop all floors in "qp", turning each integer division [a/m] into
+ * a rational division a/m. If "down" is set, then the integer division
+ * is replaced by (a-(m-1))/m instead.
+ */
+static __isl_give isl_qpolynomial *qp_drop_floors(
+ __isl_take isl_qpolynomial *qp, int down)
+{
+ int i;
+ struct isl_upoly *s;
+
+ if (!qp)
+ return NULL;
+ if (qp->div->n_row == 0)
+ return qp;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+
+ for (i = qp->div->n_row - 1; i >= 0; --i) {
+ if (down) {
+ isl_int_sub(qp->div->row[i][1],
+ qp->div->row[i][1], qp->div->row[i][0]);
+ isl_int_add_ui(qp->div->row[i][1],
+ qp->div->row[i][1], 1);
+ }
+ s = isl_upoly_from_affine(qp->dim->ctx, qp->div->row[i] + 1,
+ qp->div->row[i][0], qp->div->n_col - 1);
+ qp = substitute_div(qp, i, s);
+ if (!qp)
+ return NULL;
+ }
+
+ return qp;
+}
+
+/* Drop all floors in "pwqp", turning each integer division [a/m] into
+ * a rational division a/m.
+ */
+static __isl_give isl_pw_qpolynomial *pwqp_drop_floors(
+ __isl_take isl_pw_qpolynomial *pwqp)
+{
+ int i;
+
+ if (!pwqp)
+ return NULL;
+
+ if (isl_pw_qpolynomial_is_zero(pwqp))
+ return pwqp;
+
+ pwqp = isl_pw_qpolynomial_cow(pwqp);
+ if (!pwqp)
+ return NULL;
+
+ for (i = 0; i < pwqp->n; ++i) {
+ pwqp->p[i].qp = qp_drop_floors(pwqp->p[i].qp, 0);
+ if (!pwqp->p[i].qp)
+ goto error;
+ }
+
+ return pwqp;
+error:
+ isl_pw_qpolynomial_free(pwqp);
+ return NULL;
+}
+
+/* Adjust all the integer divisions in "qp" such that they are at least
+ * one over the given orthant (identified by "signs"). This ensures
+ * that they will still be non-negative even after subtracting (m-1)/m.
+ *
+ * In particular, f is replaced by f' + v, changing f = [a/m]
+ * to f' = [(a - m v)/m].
+ * If the constant term k in a is smaller than m,
+ * the constant term of v is set to floor(k/m) - 1.
+ * For any other term, if the coefficient c and the variable x have
+ * the same sign, then no changes are needed.
+ * Otherwise, if the variable is positive (and c is negative),
+ * then the coefficient of x in v is set to floor(c/m).
+ * If the variable is negative (and c is positive),
+ * then the coefficient of x in v is set to ceil(c/m).
+ */
+static __isl_give isl_qpolynomial *make_divs_pos(__isl_take isl_qpolynomial *qp,
+ int *signs)
+{
+ int i, j;
+ int total;
+ isl_vec *v = NULL;
+ struct isl_upoly *s;
+
+ qp = isl_qpolynomial_cow(qp);
+ if (!qp)
+ return NULL;
+ qp->div = isl_mat_cow(qp->div);
+ if (!qp->div)
+ goto error;
+
+ total = isl_space_dim(qp->dim, isl_dim_all);
+ v = isl_vec_alloc(qp->div->ctx, qp->div->n_col - 1);
+
+ for (i = 0; i < qp->div->n_row; ++i) {
+ isl_int *row = qp->div->row[i];
+ v = isl_vec_clr(v);
+ if (!v)
+ goto error;
+ if (isl_int_lt(row[1], row[0])) {
+ isl_int_fdiv_q(v->el[0], row[1], row[0]);
+ isl_int_sub_ui(v->el[0], v->el[0], 1);
+ isl_int_submul(row[1], row[0], v->el[0]);
+ }
+ for (j = 0; j < total; ++j) {
+ if (isl_int_sgn(row[2 + j]) * signs[j] >= 0)
+ continue;
+ if (signs[j] < 0)
+ isl_int_cdiv_q(v->el[1 + j], row[2 + j], row[0]);
+ else
+ isl_int_fdiv_q(v->el[1 + j], row[2 + j], row[0]);
+ isl_int_submul(row[2 + j], row[0], v->el[1 + j]);
+ }
+ for (j = 0; j < i; ++j) {
+ if (isl_int_sgn(row[2 + total + j]) >= 0)
+ continue;
+ isl_int_fdiv_q(v->el[1 + total + j],
+ row[2 + total + j], row[0]);
+ isl_int_submul(row[2 + total + j],
+ row[0], v->el[1 + total + j]);
+ }
+ for (j = i + 1; j < qp->div->n_row; ++j) {
+ if (isl_int_is_zero(qp->div->row[j][2 + total + i]))
+ continue;
+ isl_seq_combine(qp->div->row[j] + 1,
+ qp->div->ctx->one, qp->div->row[j] + 1,
+ qp->div->row[j][2 + total + i], v->el, v->size);
+ }
+ isl_int_set_si(v->el[1 + total + i], 1);
+ s = isl_upoly_from_affine(qp->dim->ctx, v->el,
+ qp->div->ctx->one, v->size);
+ qp->upoly = isl_upoly_subs(qp->upoly, total + i, 1, &s);
+ isl_upoly_free(s);
+ if (!qp->upoly)
+ goto error;
+ }
+
+ isl_vec_free(v);
+ return qp;
+error:
+ isl_vec_free(v);
+ isl_qpolynomial_free(qp);
+ return NULL;
+}
+
+struct isl_to_poly_data {
+ int sign;
+ isl_pw_qpolynomial *res;
+ isl_qpolynomial *qp;
+};
+
+/* Appoximate data->qp by a polynomial on the orthant identified by "signs".
+ * We first make all integer divisions positive and then split the
+ * quasipolynomials into terms with sign data->sign (the direction
+ * of the requested approximation) and terms with the opposite sign.
+ * In the first set of terms, each integer division [a/m] is
+ * overapproximated by a/m, while in the second it is underapproximated
+ * by (a-(m-1))/m.
+ */
+static int to_polynomial_on_orthant(__isl_take isl_set *orthant, int *signs,
+ void *user)
+{
+ struct isl_to_poly_data *data = user;
+ isl_pw_qpolynomial *t;
+ isl_qpolynomial *qp, *up, *down;
+
+ qp = isl_qpolynomial_copy(data->qp);
+ qp = make_divs_pos(qp, signs);
+
+ up = isl_qpolynomial_terms_of_sign(qp, signs, data->sign);
+ up = qp_drop_floors(up, 0);
+ down = isl_qpolynomial_terms_of_sign(qp, signs, -data->sign);
+ down = qp_drop_floors(down, 1);
+
+ isl_qpolynomial_free(qp);
+ qp = isl_qpolynomial_add(up, down);
+
+ t = isl_pw_qpolynomial_alloc(orthant, qp);
+ data->res = isl_pw_qpolynomial_add_disjoint(data->res, t);
+
+ return 0;
+}
+
+/* Approximate each quasipolynomial by a polynomial. If "sign" is positive,
+ * the polynomial will be an overapproximation. If "sign" is negative,
+ * it will be an underapproximation. If "sign" is zero, the approximation
+ * will lie somewhere in between.
+ *
+ * In particular, is sign == 0, we simply drop the floors, turning
+ * the integer divisions into rational divisions.
+ * Otherwise, we split the domains into orthants, make all integer divisions
+ * positive and then approximate each [a/m] by either a/m or (a-(m-1))/m,
+ * depending on the requested sign and the sign of the term in which
+ * the integer division appears.
+ */
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
+ __isl_take isl_pw_qpolynomial *pwqp, int sign)
+{
+ int i;
+ struct isl_to_poly_data data;
+
+ if (sign == 0)
+ return pwqp_drop_floors(pwqp);
+
+ if (!pwqp)
+ return NULL;
+
+ data.sign = sign;
+ data.res = isl_pw_qpolynomial_zero(isl_pw_qpolynomial_get_space(pwqp));
+
+ for (i = 0; i < pwqp->n; ++i) {
+ if (pwqp->p[i].qp->div->n_row == 0) {
+ isl_pw_qpolynomial *t;
+ t = isl_pw_qpolynomial_alloc(
+ isl_set_copy(pwqp->p[i].set),
+ isl_qpolynomial_copy(pwqp->p[i].qp));
+ data.res = isl_pw_qpolynomial_add_disjoint(data.res, t);
+ continue;
+ }
+ data.qp = pwqp->p[i].qp;
+ if (isl_set_foreach_orthant(pwqp->p[i].set,
+ &to_polynomial_on_orthant, &data) < 0)
+ goto error;
+ }
+
+ isl_pw_qpolynomial_free(pwqp);
+
+ return data.res;
+error:
+ isl_pw_qpolynomial_free(pwqp);
+ isl_pw_qpolynomial_free(data.res);
+ return NULL;
+}
+
+static int poly_entry(void **entry, void *user)
+{
+ int *sign = user;
+ isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
+
+ *pwqp = isl_pw_qpolynomial_to_polynomial(*pwqp, *sign);
+
+ return *pwqp ? 0 : -1;
+}
+
+__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;
+}
+
+__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
+ __isl_take isl_qpolynomial *qp)
+{
+ int i, k;
+ isl_space *dim;
+ isl_vec *aff = NULL;
+ isl_basic_map *bmap = NULL;
+ unsigned pos;
+ unsigned n_div;
+
+ if (!qp)
+ return NULL;
+ if (!isl_upoly_is_affine(qp->upoly))
+ isl_die(qp->dim->ctx, isl_error_invalid,
+ "input quasi-polynomial not affine", goto error);
+ aff = isl_qpolynomial_extract_affine(qp);
+ if (!aff)
+ goto error;
+ dim = isl_qpolynomial_get_space(qp);
+ pos = 1 + isl_space_offset(dim, isl_dim_out);
+ n_div = qp->div->n_row;
+ bmap = isl_basic_map_alloc_space(dim, n_div, 1, 2 * n_div);
+
+ for (i = 0; i < n_div; ++i) {
+ k = isl_basic_map_alloc_div(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->div[k], qp->div->row[i], qp->div->n_col);
+ isl_int_set_si(bmap->div[k][qp->div->n_col], 0);
+ if (isl_basic_map_add_div_constraints(bmap, k) < 0)
+ goto error;
+ }
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_int_neg(bmap->eq[k][pos], aff->el[0]);
+ isl_seq_cpy(bmap->eq[k], aff->el + 1, pos);
+ isl_seq_cpy(bmap->eq[k] + pos + 1, aff->el + 1 + pos, n_div);
+
+ isl_vec_free(aff);
+ isl_qpolynomial_free(qp);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+error:
+ isl_vec_free(aff);
+ isl_qpolynomial_free(qp);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_polynomial_private.h b/polly/lib/External/isl/isl_polynomial_private.h
new file mode 100644
index 00000000000..a668469e124
--- /dev/null
+++ b/polly/lib/External/isl/isl_polynomial_private.h
@@ -0,0 +1,253 @@
+#include <stdio.h>
+#include <isl_int.h>
+#include <isl/map.h>
+#include <isl/mat.h>
+#include <isl_morph.h>
+#include <isl/polynomial.h>
+#include <isl_reordering.h>
+
+struct isl_upoly {
+ int ref;
+ struct isl_ctx *ctx;
+
+ int var;
+};
+
+struct isl_upoly_cst {
+ struct isl_upoly up;
+ isl_int n;
+ isl_int d;
+};
+
+struct isl_upoly_rec {
+ struct isl_upoly up;
+ int n;
+
+ size_t size;
+ struct isl_upoly *p[];
+};
+
+/* dim represents the domain space.
+ */
+struct isl_qpolynomial {
+ int ref;
+
+ isl_space *dim;
+ struct isl_mat *div;
+ struct isl_upoly *upoly;
+};
+
+struct isl_term {
+ int ref;
+
+ isl_int n;
+ isl_int d;
+
+ isl_space *dim;
+ struct isl_mat *div;
+
+ int pow[1];
+};
+
+struct isl_pw_qpolynomial_piece {
+ struct isl_set *set;
+ struct isl_qpolynomial *qp;
+};
+
+struct isl_pw_qpolynomial {
+ int ref;
+
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_pw_qpolynomial_piece p[1];
+};
+
+/* dim represents the domain space.
+ */
+struct isl_qpolynomial_fold {
+ int ref;
+
+ enum isl_fold type;
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_qpolynomial *qp[1];
+};
+
+struct isl_pw_qpolynomial_fold_piece {
+ struct isl_set *set;
+ struct isl_qpolynomial_fold *fold;
+};
+
+struct isl_pw_qpolynomial_fold {
+ int ref;
+
+ enum isl_fold type;
+ isl_space *dim;
+
+ int n;
+
+ size_t size;
+ struct isl_pw_qpolynomial_fold_piece p[1];
+};
+
+void isl_term_get_num(__isl_keep isl_term *term, isl_int *n);
+
+__isl_give struct isl_upoly *isl_upoly_zero(struct isl_ctx *ctx);
+__isl_give struct isl_upoly *isl_upoly_copy(__isl_keep struct isl_upoly *up);
+__isl_give struct isl_upoly *isl_upoly_cow(__isl_take struct isl_upoly *up);
+__isl_give struct isl_upoly *isl_upoly_dup(__isl_keep struct isl_upoly *up);
+void isl_upoly_free(__isl_take struct isl_upoly *up);
+__isl_give struct isl_upoly *isl_upoly_mul(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2);
+
+int isl_upoly_is_cst(__isl_keep struct isl_upoly *up);
+int isl_upoly_is_zero(__isl_keep struct isl_upoly *up);
+int isl_upoly_is_one(__isl_keep struct isl_upoly *up);
+int isl_upoly_is_negone(__isl_keep struct isl_upoly *up);
+__isl_keep struct isl_upoly_cst *isl_upoly_as_cst(__isl_keep struct isl_upoly *up);
+__isl_keep struct isl_upoly_rec *isl_upoly_as_rec(__isl_keep struct isl_upoly *up);
+
+__isl_give struct isl_upoly *isl_upoly_sum(__isl_take struct isl_upoly *up1,
+ __isl_take struct isl_upoly *up2);
+__isl_give struct isl_upoly *isl_upoly_mul_isl_int(
+ __isl_take struct isl_upoly *up, isl_int v);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_alloc(__isl_take isl_space *dim,
+ unsigned n_div, __isl_take struct isl_upoly *up);
+__isl_give isl_qpolynomial *isl_qpolynomial_cow(__isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_dup(__isl_keep isl_qpolynomial *qp);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_cst_on_domain(__isl_take isl_space *dim,
+ isl_int v);
+__isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
+ __isl_take isl_space *space, const isl_int n, const isl_int d);
+__isl_give isl_qpolynomial *isl_qpolynomial_var_pow_on_domain(__isl_take isl_space *dim,
+ int pos, int power);
+int isl_qpolynomial_is_one(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_affine(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+ isl_int *n, isl_int *d);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_add_on_domain(
+ __isl_keep isl_set *dom,
+ __isl_take isl_qpolynomial *qp1,
+ __isl_take isl_qpolynomial *qp2);
+
+int isl_qpolynomial_degree(__isl_keep isl_qpolynomial *poly);
+__isl_give isl_qpolynomial *isl_qpolynomial_coeff(
+ __isl_keep isl_qpolynomial *poly,
+ enum isl_dim_type type, unsigned pos, int deg);
+
+__isl_give isl_vec *isl_qpolynomial_extract_affine(
+ __isl_keep isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_affine(__isl_take isl_space *dim,
+ isl_int *f, isl_int denom);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_cow(
+ __isl_take isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_piece(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ __isl_take isl_set *set, __isl_take isl_qpolynomial *qp);
+int isl_pw_qpolynomial_is_one(__isl_keep isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_project_out(
+ __isl_take isl_pw_qpolynomial *pwqp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_val *isl_qpolynomial_opt_on_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_set *set, int max);
+
+enum isl_fold isl_fold_type_negate(enum isl_fold type);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_cow(
+ __isl_take isl_qpolynomial_fold *fold);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_dup(
+ __isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_cow(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_add_on_domain(
+ __isl_keep isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold_on_domain(
+ __isl_keep isl_set *set,
+ __isl_take isl_qpolynomial_fold *fold1,
+ __isl_take isl_qpolynomial_fold *fold2);
+
+__isl_give isl_val *isl_qpolynomial_fold_opt_on_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *set, int max);
+
+int isl_pw_qpolynomial_fold_covers(__isl_keep isl_pw_qpolynomial_fold *pwf1,
+ __isl_keep isl_pw_qpolynomial_fold *pwf2);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_morph_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_morph *morph);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_morph_domain(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_morph *morph);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_morph_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_morph *morph);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_morph_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_morph *morph);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_lift(__isl_take isl_qpolynomial *qp,
+ __isl_take isl_space *dim);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_lift(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_substitute_equalities(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_basic_set *eq);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute_equalities(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_basic_set *eq);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_realign_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_reordering *r);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_realign_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_reordering *r);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_realign_domain(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_reordering *r);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_realign_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_reordering *r);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_reset_space(
+ __isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_space *space);
+__isl_give isl_qpolynomial *isl_qpolynomial_reset_domain_space(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_reset_space_and_domain(
+ __isl_take isl_qpolynomial *qp, __isl_take isl_space *space,
+ __isl_take isl_space *domain);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_domain_space(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *dim);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_reset_space_and_domain(
+ __isl_take isl_qpolynomial_fold *fold, __isl_take isl_space *space,
+ __isl_take isl_space *domain);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_reset_domain_space(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_space *dim);
+
+void isl_qpolynomial_get_den(__isl_keep isl_qpolynomial *qp, isl_int *d);
+__isl_give isl_qpolynomial *isl_qpolynomial_add_isl_int(
+ __isl_take isl_qpolynomial *qp, isl_int v);
+__isl_give isl_qpolynomial *isl_qpolynomial_mul_isl_int(
+ __isl_take isl_qpolynomial *qp, isl_int v);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul_isl_int(
+ __isl_take isl_pw_qpolynomial *pwqp, isl_int v);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_mul_isl_int(
+ __isl_take isl_qpolynomial_fold *fold, isl_int v);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_mul_isl_int(
+ __isl_take isl_pw_qpolynomial_fold *pwf, isl_int v);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul_isl_int(
+ __isl_take isl_union_pw_qpolynomial *upwqp, isl_int v);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_mul_isl_int(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf, isl_int v);
diff --git a/polly/lib/External/isl/isl_power_templ.c b/polly/lib/External/isl/isl_power_templ.c
new file mode 100644
index 00000000000..65253bdcb96
--- /dev/null
+++ b/polly/lib/External/isl/isl_power_templ.c
@@ -0,0 +1,81 @@
+#include <isl_val_private.h>
+
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+/* Compute the given non-zero power of "map" and return the result.
+ * If the exponent "exp" is negative, then the -exp th power of the inverse
+ * relation is computed.
+ */
+__isl_give TYPE *FN(TYPE,fixed_power)(__isl_take TYPE *map, isl_int exp)
+{
+ isl_ctx *ctx;
+ TYPE *res = NULL;
+ isl_int r;
+
+ if (!map)
+ return NULL;
+
+ ctx = FN(TYPE,get_ctx)(map);
+ if (isl_int_is_zero(exp))
+ isl_die(ctx, isl_error_invalid,
+ "expecting non-zero exponent", goto error);
+
+ if (isl_int_is_neg(exp)) {
+ isl_int_neg(exp, exp);
+ map = FN(TYPE,reverse)(map);
+ return FN(TYPE,fixed_power)(map, exp);
+ }
+
+ isl_int_init(r);
+ for (;;) {
+ isl_int_fdiv_r(r, exp, ctx->two);
+
+ if (!isl_int_is_zero(r)) {
+ if (!res)
+ res = FN(TYPE,copy)(map);
+ else {
+ res = FN(TYPE,apply_range)(res,
+ FN(TYPE,copy)(map));
+ res = FN(TYPE,coalesce)(res);
+ }
+ if (!res)
+ break;
+ }
+
+ isl_int_fdiv_q(exp, exp, ctx->two);
+ if (isl_int_is_zero(exp))
+ break;
+
+ map = FN(TYPE,apply_range)(map, FN(TYPE,copy)(map));
+ map = FN(TYPE,coalesce)(map);
+ }
+ isl_int_clear(r);
+
+ FN(TYPE,free)(map);
+ return res;
+error:
+ FN(TYPE,free)(map);
+ return NULL;
+}
+
+/* Compute the given non-zero power of "map" and return the result.
+ * If the exponent "exp" is negative, then the -exp th power of the inverse
+ * relation is computed.
+ */
+__isl_give TYPE *FN(TYPE,fixed_power_val)(__isl_take TYPE *map,
+ __isl_take isl_val *exp)
+{
+ if (!map || !exp)
+ goto error;
+ if (!isl_val_is_int(exp))
+ isl_die(FN(TYPE,get_ctx)(map), isl_error_invalid,
+ "expecting integer exponent", goto error);
+ map = FN(TYPE,fixed_power)(map, exp->n);
+ isl_val_free(exp);
+ return map;
+error:
+ FN(TYPE,free)(map);
+ isl_val_free(exp);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_printer.c b/polly/lib/External/isl/isl_printer.c
new file mode 100644
index 00000000000..d5407fce6ad
--- /dev/null
+++ b/polly/lib/External/isl/isl_printer.c
@@ -0,0 +1,449 @@
+#include <string.h>
+#include <isl_int.h>
+#include <isl_printer_private.h>
+
+static __isl_give isl_printer *file_start_line(__isl_take isl_printer *p)
+{
+ fprintf(p->file, "%s%*s%s", p->indent_prefix ? p->indent_prefix : "",
+ p->indent, "", p->prefix ? p->prefix : "");
+ return p;
+}
+
+static __isl_give isl_printer *file_end_line(__isl_take isl_printer *p)
+{
+ fprintf(p->file, "%s\n", p->suffix ? p->suffix : "");
+ return p;
+}
+
+static __isl_give isl_printer *file_flush(__isl_take isl_printer *p)
+{
+ fflush(p->file);
+ return p;
+}
+
+static __isl_give isl_printer *file_print_str(__isl_take isl_printer *p,
+ const char *s)
+{
+ fprintf(p->file, "%s", s);
+ return p;
+}
+
+static __isl_give isl_printer *file_print_double(__isl_take isl_printer *p,
+ double d)
+{
+ fprintf(p->file, "%g", d);
+ return p;
+}
+
+static __isl_give isl_printer *file_print_int(__isl_take isl_printer *p, int i)
+{
+ fprintf(p->file, "%d", i);
+ return p;
+}
+
+static __isl_give isl_printer *file_print_isl_int(__isl_take isl_printer *p, isl_int i)
+{
+ isl_int_print(p->file, i, p->width);
+ return p;
+}
+
+static int grow_buf(__isl_keep isl_printer *p, int extra)
+{
+ int new_size;
+ char *new_buf;
+
+ if (p->buf_size == 0)
+ return -1;
+
+ new_size = ((p->buf_n + extra + 1) * 3) / 2;
+ new_buf = isl_realloc_array(p->ctx, p->buf, char, new_size);
+ if (!new_buf) {
+ p->buf_size = 0;
+ return -1;
+ }
+ p->buf = new_buf;
+ p->buf_size = new_size;
+
+ return 0;
+}
+
+static __isl_give isl_printer *str_print(__isl_take isl_printer *p,
+ const char *s, int len)
+{
+ if (p->buf_n + len + 1 >= p->buf_size && grow_buf(p, len))
+ goto error;
+ memcpy(p->buf + p->buf_n, s, len);
+ p->buf_n += len;
+
+ p->buf[p->buf_n] = '\0';
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *str_print_indent(__isl_take isl_printer *p,
+ int indent)
+{
+ int i;
+
+ if (p->buf_n + indent + 1 >= p->buf_size && grow_buf(p, indent))
+ goto error;
+ for (i = 0; i < indent; ++i)
+ p->buf[p->buf_n++] = ' ';
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *str_start_line(__isl_take isl_printer *p)
+{
+ if (p->indent_prefix)
+ p = str_print(p, p->indent_prefix, strlen(p->indent_prefix));
+ p = str_print_indent(p, p->indent);
+ if (p->prefix)
+ p = str_print(p, p->prefix, strlen(p->prefix));
+ return p;
+}
+
+static __isl_give isl_printer *str_end_line(__isl_take isl_printer *p)
+{
+ if (p->suffix)
+ p = str_print(p, p->suffix, strlen(p->suffix));
+ p = str_print(p, "\n", strlen("\n"));
+ return p;
+}
+
+static __isl_give isl_printer *str_flush(__isl_take isl_printer *p)
+{
+ p->buf_n = 0;
+ return p;
+}
+
+static __isl_give isl_printer *str_print_str(__isl_take isl_printer *p,
+ const char *s)
+{
+ return str_print(p, s, strlen(s));
+}
+
+static __isl_give isl_printer *str_print_double(__isl_take isl_printer *p,
+ double d)
+{
+ int left = p->buf_size - p->buf_n;
+ int need = snprintf(p->buf + p->buf_n, left, "%g", d);
+ if (need >= left) {
+ if (grow_buf(p, need))
+ goto error;
+ left = p->buf_size - p->buf_n;
+ need = snprintf(p->buf + p->buf_n, left, "%g", d);
+ }
+ p->buf_n += need;
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *str_print_int(__isl_take isl_printer *p, int i)
+{
+ int left = p->buf_size - p->buf_n;
+ int need = snprintf(p->buf + p->buf_n, left, "%d", i);
+ if (need >= left) {
+ if (grow_buf(p, need))
+ goto error;
+ left = p->buf_size - p->buf_n;
+ need = snprintf(p->buf + p->buf_n, left, "%d", i);
+ }
+ p->buf_n += need;
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+static __isl_give isl_printer *str_print_isl_int(__isl_take isl_printer *p,
+ isl_int i)
+{
+ char *s;
+ int len;
+
+ s = isl_int_get_str(i);
+ len = strlen(s);
+ if (len < p->width)
+ p = str_print_indent(p, p->width - len);
+ p = str_print(p, s, len);
+ isl_int_free_str(s);
+ return p;
+}
+
+struct isl_printer_ops {
+ __isl_give isl_printer *(*start_line)(__isl_take isl_printer *p);
+ __isl_give isl_printer *(*end_line)(__isl_take isl_printer *p);
+ __isl_give isl_printer *(*print_double)(__isl_take isl_printer *p,
+ double d);
+ __isl_give isl_printer *(*print_int)(__isl_take isl_printer *p, int i);
+ __isl_give isl_printer *(*print_isl_int)(__isl_take isl_printer *p,
+ isl_int i);
+ __isl_give isl_printer *(*print_str)(__isl_take isl_printer *p,
+ const char *s);
+ __isl_give isl_printer *(*flush)(__isl_take isl_printer *p);
+};
+
+static struct isl_printer_ops file_ops = {
+ file_start_line,
+ file_end_line,
+ file_print_double,
+ file_print_int,
+ file_print_isl_int,
+ file_print_str,
+ file_flush
+};
+
+static struct isl_printer_ops str_ops = {
+ str_start_line,
+ str_end_line,
+ str_print_double,
+ str_print_int,
+ str_print_isl_int,
+ str_print_str,
+ str_flush
+};
+
+__isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file)
+{
+ struct isl_printer *p = isl_alloc_type(ctx, struct isl_printer);
+ if (!p)
+ return NULL;
+ p->ctx = ctx;
+ isl_ctx_ref(p->ctx);
+ p->ops = &file_ops;
+ p->file = file;
+ p->buf = NULL;
+ p->buf_n = 0;
+ p->buf_size = 0;
+ p->indent = 0;
+ p->output_format = ISL_FORMAT_ISL;
+ p->indent_prefix = NULL;
+ p->prefix = NULL;
+ p->suffix = NULL;
+ p->width = 0;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx)
+{
+ struct isl_printer *p = isl_calloc_type(ctx, struct isl_printer);
+ if (!p)
+ return NULL;
+ p->ctx = ctx;
+ isl_ctx_ref(p->ctx);
+ p->ops = &str_ops;
+ p->file = NULL;
+ p->buf = isl_alloc_array(ctx, char, 256);
+ if (!p->buf)
+ goto error;
+ p->buf_n = 0;
+ p->buf[0] = '\0';
+ p->buf_size = 256;
+ p->indent = 0;
+ p->output_format = ISL_FORMAT_ISL;
+ p->indent_prefix = NULL;
+ p->prefix = NULL;
+ p->suffix = NULL;
+ p->width = 0;
+
+ return p;
+error:
+ isl_printer_free(p);
+ return NULL;
+}
+
+__isl_null isl_printer *isl_printer_free(__isl_take isl_printer *p)
+{
+ if (!p)
+ return NULL;
+ free(p->buf);
+ free(p->indent_prefix);
+ free(p->prefix);
+ free(p->suffix);
+ isl_ctx_deref(p->ctx);
+ free(p);
+
+ return NULL;
+}
+
+isl_ctx *isl_printer_get_ctx(__isl_keep isl_printer *printer)
+{
+ return printer ? printer->ctx : NULL;
+}
+
+FILE *isl_printer_get_file(__isl_keep isl_printer *printer)
+{
+ if (!printer)
+ return NULL;
+ if (!printer->file)
+ isl_die(isl_printer_get_ctx(printer), isl_error_invalid,
+ "not a file printer", return NULL);
+ return printer->file;
+}
+
+__isl_give isl_printer *isl_printer_set_isl_int_width(__isl_take isl_printer *p,
+ int width)
+{
+ if (!p)
+ return NULL;
+
+ p->width = width;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_set_indent(__isl_take isl_printer *p,
+ int indent)
+{
+ if (!p)
+ return NULL;
+
+ p->indent = indent;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_indent(__isl_take isl_printer *p,
+ int indent)
+{
+ if (!p)
+ return NULL;
+
+ p->indent += indent;
+ if (p->indent < 0)
+ p->indent = 0;
+
+ return p;
+}
+
+/* Replace the indent prefix of "p" by "prefix".
+ */
+__isl_give isl_printer *isl_printer_set_indent_prefix(__isl_take isl_printer *p,
+ const char *prefix)
+{
+ if (!p)
+ return NULL;
+
+ free(p->indent_prefix);
+ p->indent_prefix = prefix ? strdup(prefix) : NULL;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_set_prefix(__isl_take isl_printer *p,
+ const char *prefix)
+{
+ if (!p)
+ return NULL;
+
+ free(p->prefix);
+ p->prefix = prefix ? strdup(prefix) : NULL;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_set_suffix(__isl_take isl_printer *p,
+ const char *suffix)
+{
+ if (!p)
+ return NULL;
+
+ free(p->suffix);
+ p->suffix = suffix ? strdup(suffix) : NULL;
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_set_output_format(__isl_take isl_printer *p,
+ int output_format)
+{
+ if (!p)
+ return NULL;
+
+ p->output_format = output_format;
+
+ return p;
+}
+
+int isl_printer_get_output_format(__isl_keep isl_printer *p)
+{
+ if (!p)
+ return -1;
+ return p->output_format;
+}
+
+__isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
+ const char *s)
+{
+ if (!p)
+ return NULL;
+ if (!s)
+ return isl_printer_free(p);
+
+ return p->ops->print_str(p, s);
+}
+
+__isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
+ double d)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->print_double(p, d);
+}
+
+__isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->print_int(p, i);
+}
+
+__isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
+ isl_int i)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->print_isl_int(p, i);
+}
+
+__isl_give isl_printer *isl_printer_start_line(__isl_take isl_printer *p)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->start_line(p);
+}
+
+__isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->end_line(p);
+}
+
+char *isl_printer_get_str(__isl_keep isl_printer *printer)
+{
+ if (!printer || !printer->buf)
+ return NULL;
+ return strdup(printer->buf);
+}
+
+__isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p)
+{
+ if (!p)
+ return NULL;
+
+ return p->ops->flush(p);
+}
diff --git a/polly/lib/External/isl/isl_printer_private.h b/polly/lib/External/isl/isl_printer_private.h
new file mode 100644
index 00000000000..c977214ce49
--- /dev/null
+++ b/polly/lib/External/isl/isl_printer_private.h
@@ -0,0 +1,18 @@
+#include <isl/printer.h>
+
+struct isl_printer_ops;
+
+struct isl_printer {
+ struct isl_ctx *ctx;
+ struct isl_printer_ops *ops;
+ FILE *file;
+ int buf_n;
+ int buf_size;
+ char *buf;
+ int indent;
+ int output_format;
+ char *indent_prefix;
+ char *prefix;
+ char *suffix;
+ int width;
+};
diff --git a/polly/lib/External/isl/isl_pw_templ.c b/polly/lib/External/isl/isl_pw_templ.c
new file mode 100644
index 00000000000..594f6b73cc6
--- /dev/null
+++ b/polly/lib/External/isl/isl_pw_templ.c
@@ -0,0 +1,2100 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-2014 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/aff.h>
+#include <isl_val_private.h>
+
+#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)
+
+#ifdef HAS_TYPE
+__isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim,
+ enum isl_fold type, int n)
+#else
+__isl_give PW *FN(PW,alloc_size)(__isl_take isl_space *dim, int n)
+#endif
+{
+ isl_ctx *ctx;
+ struct PW *pw;
+
+ if (!dim)
+ return NULL;
+ ctx = isl_space_get_ctx(dim);
+ isl_assert(ctx, n >= 0, goto error);
+ pw = isl_alloc(ctx, struct PW,
+ sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
+ if (!pw)
+ goto error;
+
+ pw->ref = 1;
+#ifdef HAS_TYPE
+ pw->type = type;
+#endif
+ pw->size = n;
+ pw->n = 0;
+ pw->dim = dim;
+ return pw;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+#ifdef HAS_TYPE
+__isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
+{
+ return FN(PW,alloc_size)(dim, type, 0);
+}
+#else
+__isl_give PW *FN(PW,ZERO)(__isl_take isl_space *dim)
+{
+ return FN(PW,alloc_size)(dim, 0);
+}
+#endif
+
+__isl_give PW *FN(PW,add_piece)(__isl_take PW *pw,
+ __isl_take isl_set *set, __isl_take EL *el)
+{
+ isl_ctx *ctx;
+ isl_space *el_dim = NULL;
+
+ if (!pw || !set || !el)
+ goto error;
+
+ if (isl_set_plain_is_empty(set) || FN(EL,EL_IS_ZERO)(el)) {
+ isl_set_free(set);
+ FN(EL,free)(el);
+ return pw;
+ }
+
+ ctx = isl_set_get_ctx(set);
+#ifdef HAS_TYPE
+ if (pw->type != el->type)
+ isl_die(ctx, isl_error_invalid, "fold types don't match",
+ goto error);
+#endif
+ el_dim = FN(EL,get_space(el));
+ isl_assert(ctx, isl_space_is_equal(pw->dim, el_dim), goto error);
+ isl_assert(ctx, pw->n < pw->size, goto error);
+
+ pw->p[pw->n].set = set;
+ pw->p[pw->n].FIELD = el;
+ pw->n++;
+
+ isl_space_free(el_dim);
+ return pw;
+error:
+ isl_space_free(el_dim);
+ FN(PW,free)(pw);
+ isl_set_free(set);
+ FN(EL,free)(el);
+ return NULL;
+}
+
+#ifdef HAS_TYPE
+__isl_give PW *FN(PW,alloc)(enum isl_fold type,
+ __isl_take isl_set *set, __isl_take EL *el)
+#else
+__isl_give PW *FN(PW,alloc)(__isl_take isl_set *set, __isl_take EL *el)
+#endif
+{
+ PW *pw;
+
+ if (!set || !el)
+ goto error;
+
+#ifdef HAS_TYPE
+ pw = FN(PW,alloc_size)(FN(EL,get_space)(el), type, 1);
+#else
+ pw = FN(PW,alloc_size)(FN(EL,get_space)(el), 1);
+#endif
+
+ return FN(PW,add_piece)(pw, set, el);
+error:
+ isl_set_free(set);
+ FN(EL,free)(el);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,dup)(__isl_keep PW *pw)
+{
+ int i;
+ PW *dup;
+
+ if (!pw)
+ return NULL;
+
+#ifdef HAS_TYPE
+ dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, pw->n);
+#else
+ dup = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->n);
+#endif
+ if (!dup)
+ return NULL;
+
+ for (i = 0; i < pw->n; ++i)
+ dup = FN(PW,add_piece)(dup, isl_set_copy(pw->p[i].set),
+ FN(EL,copy)(pw->p[i].FIELD));
+
+ return dup;
+}
+
+__isl_give PW *FN(PW,cow)(__isl_take PW *pw)
+{
+ if (!pw)
+ return NULL;
+
+ if (pw->ref == 1)
+ return pw;
+ pw->ref--;
+ return FN(PW,dup)(pw);
+}
+
+__isl_give PW *FN(PW,copy)(__isl_keep PW *pw)
+{
+ if (!pw)
+ return NULL;
+
+ pw->ref++;
+ return pw;
+}
+
+__isl_null PW *FN(PW,free)(__isl_take PW *pw)
+{
+ int i;
+
+ if (!pw)
+ return NULL;
+ if (--pw->ref > 0)
+ return NULL;
+
+ for (i = 0; i < pw->n; ++i) {
+ isl_set_free(pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ }
+ isl_space_free(pw->dim);
+ free(pw);
+
+ return NULL;
+}
+
+const char *FN(PW,get_dim_name)(__isl_keep PW *pw, enum isl_dim_type type,
+ unsigned pos)
+{
+ return pw ? isl_space_get_dim_name(pw->dim, type, pos) : NULL;
+}
+
+int FN(PW,has_dim_id)(__isl_keep PW *pw, enum isl_dim_type type, unsigned pos)
+{
+ return pw ? isl_space_has_dim_id(pw->dim, type, pos) : -1;
+}
+
+__isl_give isl_id *FN(PW,get_dim_id)(__isl_keep PW *pw, enum isl_dim_type type,
+ unsigned pos)
+{
+ return pw ? isl_space_get_dim_id(pw->dim, type, pos) : NULL;
+}
+
+int FN(PW,has_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
+{
+ return pw ? isl_space_has_tuple_name(pw->dim, type) : -1;
+}
+
+const char *FN(PW,get_tuple_name)(__isl_keep PW *pw, enum isl_dim_type type)
+{
+ return pw ? isl_space_get_tuple_name(pw->dim, type) : NULL;
+}
+
+int FN(PW,has_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
+{
+ return pw ? isl_space_has_tuple_id(pw->dim, type) : -1;
+}
+
+__isl_give isl_id *FN(PW,get_tuple_id)(__isl_keep PW *pw, enum isl_dim_type type)
+{
+ return pw ? isl_space_get_tuple_id(pw->dim, type) : NULL;
+}
+
+int FN(PW,IS_ZERO)(__isl_keep PW *pw)
+{
+ if (!pw)
+ return -1;
+
+ return pw->n == 0;
+}
+
+#ifndef NO_REALIGN
+__isl_give PW *FN(PW,realign_domain)(__isl_take PW *pw,
+ __isl_take isl_reordering *exp)
+{
+ int i;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw || !exp)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_realign(pw->p[i].set,
+ isl_reordering_copy(exp));
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,realign_domain)(pw->p[i].FIELD,
+ isl_reordering_copy(exp));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ pw = FN(PW,reset_domain_space)(pw, isl_space_copy(exp->dim));
+
+ isl_reordering_free(exp);
+ return pw;
+error:
+ isl_reordering_free(exp);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+/* Align the parameters of "pw" to those of "model".
+ */
+__isl_give PW *FN(PW,align_params)(__isl_take PW *pw, __isl_take isl_space *model)
+{
+ isl_ctx *ctx;
+
+ if (!pw || !model)
+ goto error;
+
+ ctx = isl_space_get_ctx(model);
+ if (!isl_space_has_named_params(model))
+ isl_die(ctx, isl_error_invalid,
+ "model has unnamed parameters", goto error);
+ if (!isl_space_has_named_params(pw->dim))
+ isl_die(ctx, isl_error_invalid,
+ "input has unnamed parameters", goto error);
+ if (!isl_space_match(pw->dim, isl_dim_param, model, isl_dim_param)) {
+ isl_reordering *exp;
+
+ model = isl_space_drop_dims(model, isl_dim_in,
+ 0, isl_space_dim(model, isl_dim_in));
+ model = isl_space_drop_dims(model, isl_dim_out,
+ 0, isl_space_dim(model, isl_dim_out));
+ exp = isl_parameter_alignment_reordering(pw->dim, model);
+ exp = isl_reordering_extend_space(exp,
+ FN(PW,get_domain_space)(pw));
+ pw = FN(PW,realign_domain)(pw, exp);
+ }
+
+ isl_space_free(model);
+ return pw;
+error:
+ isl_space_free(model);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+static __isl_give PW *FN(PW,align_params_pw_pw_and)(__isl_take PW *pw1,
+ __isl_take PW *pw2,
+ __isl_give PW *(*fn)(__isl_take PW *pw1, __isl_take PW *pw2))
+{
+ isl_ctx *ctx;
+
+ if (!pw1 || !pw2)
+ goto error;
+ if (isl_space_match(pw1->dim, isl_dim_param, pw2->dim, isl_dim_param))
+ return fn(pw1, pw2);
+ ctx = FN(PW,get_ctx)(pw1);
+ if (!isl_space_has_named_params(pw1->dim) ||
+ !isl_space_has_named_params(pw2->dim))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pw1 = FN(PW,align_params)(pw1, FN(PW,get_space)(pw2));
+ pw2 = FN(PW,align_params)(pw2, FN(PW,get_space)(pw1));
+ return fn(pw1, pw2);
+error:
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return NULL;
+}
+
+static __isl_give PW *FN(PW,align_params_pw_set_and)(__isl_take PW *pw,
+ __isl_take isl_set *set,
+ __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_set *set))
+{
+ isl_ctx *ctx;
+
+ if (!pw || !set)
+ goto error;
+ if (isl_space_match(pw->dim, isl_dim_param, set->dim, isl_dim_param))
+ return fn(pw, set);
+ ctx = FN(PW,get_ctx)(pw);
+ if (!isl_space_has_named_params(pw->dim) ||
+ !isl_space_has_named_params(set->dim))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pw = FN(PW,align_params)(pw, isl_set_get_space(set));
+ set = isl_set_align_params(set, FN(PW,get_space)(pw));
+ return fn(pw, set);
+error:
+ FN(PW,free)(pw);
+ isl_set_free(set);
+ return NULL;
+}
+#endif
+
+static __isl_give PW *FN(PW,union_add_aligned)(__isl_take PW *pw1,
+ __isl_take PW *pw2)
+{
+ int i, j, n;
+ struct PW *res;
+ isl_ctx *ctx;
+ isl_set *set;
+
+ if (!pw1 || !pw2)
+ goto error;
+
+ ctx = isl_space_get_ctx(pw1->dim);
+#ifdef HAS_TYPE
+ if (pw1->type != pw2->type)
+ isl_die(ctx, isl_error_invalid,
+ "fold types don't match", goto error);
+#endif
+ isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
+
+ if (FN(PW,IS_ZERO)(pw1)) {
+ FN(PW,free)(pw1);
+ return pw2;
+ }
+
+ if (FN(PW,IS_ZERO)(pw2)) {
+ FN(PW,free)(pw2);
+ return pw1;
+ }
+
+ n = (pw1->n + 1) * (pw2->n + 1);
+#ifdef HAS_TYPE
+ res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), pw1->type, n);
+#else
+ res = FN(PW,alloc_size)(isl_space_copy(pw1->dim), n);
+#endif
+
+ for (i = 0; i < pw1->n; ++i) {
+ set = isl_set_copy(pw1->p[i].set);
+ for (j = 0; j < pw2->n; ++j) {
+ struct isl_set *common;
+ EL *sum;
+ common = isl_set_intersect(isl_set_copy(pw1->p[i].set),
+ isl_set_copy(pw2->p[j].set));
+ if (isl_set_plain_is_empty(common)) {
+ isl_set_free(common);
+ continue;
+ }
+ set = isl_set_subtract(set,
+ isl_set_copy(pw2->p[j].set));
+
+ sum = FN(EL,add_on_domain)(common,
+ FN(EL,copy)(pw1->p[i].FIELD),
+ FN(EL,copy)(pw2->p[j].FIELD));
+
+ res = FN(PW,add_piece)(res, common, sum);
+ }
+ res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw1->p[i].FIELD));
+ }
+
+ for (j = 0; j < pw2->n; ++j) {
+ set = isl_set_copy(pw2->p[j].set);
+ for (i = 0; i < pw1->n; ++i)
+ set = isl_set_subtract(set,
+ isl_set_copy(pw1->p[i].set));
+ res = FN(PW,add_piece)(res, set, FN(EL,copy)(pw2->p[j].FIELD));
+ }
+
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+
+ return res;
+error:
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return NULL;
+}
+
+/* Private version of "union_add". For isl_pw_qpolynomial and
+ * isl_pw_qpolynomial_fold, we prefer to simply call it "add".
+ */
+static __isl_give PW *FN(PW,union_add_)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+ return FN(PW,align_params_pw_pw_and)(pw1, pw2,
+ &FN(PW,union_add_aligned));
+}
+
+/* Make sure "pw" has room for at least "n" more pieces.
+ *
+ * If there is only one reference to pw, we extend it in place.
+ * Otherwise, we create a new PW and copy the pieces.
+ */
+static __isl_give PW *FN(PW,grow)(__isl_take PW *pw, int n)
+{
+ int i;
+ isl_ctx *ctx;
+ PW *res;
+
+ if (!pw)
+ return NULL;
+ if (pw->n + n <= pw->size)
+ return pw;
+ ctx = FN(PW,get_ctx)(pw);
+ n += pw->n;
+ if (pw->ref == 1) {
+ res = isl_realloc(ctx, pw, struct PW,
+ sizeof(struct PW) + (n - 1) * sizeof(S(PW,piece)));
+ if (!res)
+ return FN(PW,free)(pw);
+ res->size = n;
+ return res;
+ }
+#ifdef HAS_TYPE
+ res = FN(PW,alloc_size)(isl_space_copy(pw->dim), pw->type, n);
+#else
+ res = FN(PW,alloc_size)(isl_space_copy(pw->dim), n);
+#endif
+ if (!res)
+ return FN(PW,free)(pw);
+ for (i = 0; i < pw->n; ++i)
+ res = FN(PW,add_piece)(res, isl_set_copy(pw->p[i].set),
+ FN(EL,copy)(pw->p[i].FIELD));
+ FN(PW,free)(pw);
+ return res;
+}
+
+static __isl_give PW *FN(PW,add_disjoint_aligned)(__isl_take PW *pw1,
+ __isl_take PW *pw2)
+{
+ int i;
+ isl_ctx *ctx;
+
+ if (!pw1 || !pw2)
+ goto error;
+
+ if (pw1->size < pw1->n + pw2->n && pw1->n < pw2->n)
+ return FN(PW,add_disjoint_aligned)(pw2, pw1);
+
+ ctx = isl_space_get_ctx(pw1->dim);
+#ifdef HAS_TYPE
+ if (pw1->type != pw2->type)
+ isl_die(ctx, isl_error_invalid,
+ "fold types don't match", goto error);
+#endif
+ isl_assert(ctx, isl_space_is_equal(pw1->dim, pw2->dim), goto error);
+
+ if (FN(PW,IS_ZERO)(pw1)) {
+ FN(PW,free)(pw1);
+ return pw2;
+ }
+
+ if (FN(PW,IS_ZERO)(pw2)) {
+ FN(PW,free)(pw2);
+ return pw1;
+ }
+
+ pw1 = FN(PW,grow)(pw1, pw2->n);
+ if (!pw1)
+ goto error;
+
+ for (i = 0; i < pw2->n; ++i)
+ pw1 = FN(PW,add_piece)(pw1,
+ isl_set_copy(pw2->p[i].set),
+ FN(EL,copy)(pw2->p[i].FIELD));
+
+ FN(PW,free)(pw2);
+
+ return pw1;
+error:
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,add_disjoint)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+ return FN(PW,align_params_pw_pw_and)(pw1, pw2,
+ &FN(PW,add_disjoint_aligned));
+}
+
+/* This function is currently only used from isl_aff.c
+ */
+static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
+ __isl_take PW *pw2, __isl_take isl_space *space,
+ __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
+ __attribute__ ((unused));
+
+/* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
+ * The result of "fn" (and therefore also of this function) lives in "space".
+ */
+static __isl_give PW *FN(PW,on_shared_domain_in)(__isl_take PW *pw1,
+ __isl_take PW *pw2, __isl_take isl_space *space,
+ __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
+{
+ int i, j, n;
+ PW *res = NULL;
+
+ if (!pw1 || !pw2)
+ goto error;
+
+ n = pw1->n * pw2->n;
+#ifdef HAS_TYPE
+ res = FN(PW,alloc_size)(isl_space_copy(space), pw1->type, n);
+#else
+ res = FN(PW,alloc_size)(isl_space_copy(space), n);
+#endif
+
+ for (i = 0; i < pw1->n; ++i) {
+ for (j = 0; j < pw2->n; ++j) {
+ isl_set *common;
+ EL *res_ij;
+ int empty;
+
+ common = isl_set_intersect(
+ isl_set_copy(pw1->p[i].set),
+ isl_set_copy(pw2->p[j].set));
+ empty = isl_set_plain_is_empty(common);
+ if (empty < 0 || empty) {
+ isl_set_free(common);
+ if (empty < 0)
+ goto error;
+ continue;
+ }
+
+ res_ij = fn(FN(EL,copy)(pw1->p[i].FIELD),
+ FN(EL,copy)(pw2->p[j].FIELD));
+ res_ij = FN(EL,gist)(res_ij, isl_set_copy(common));
+
+ res = FN(PW,add_piece)(res, common, res_ij);
+ }
+ }
+
+ isl_space_free(space);
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return res;
+error:
+ isl_space_free(space);
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ FN(PW,free)(res);
+ return NULL;
+}
+
+/* This function is currently only used from isl_aff.c
+ */
+static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
+ __isl_take PW *pw2,
+ __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
+ __attribute__ ((unused));
+
+/* Apply "fn" to pairs of elements from pw1 and pw2 on shared domains.
+ * The result of "fn" is assumed to live in the same space as "pw1" and "pw2".
+ */
+static __isl_give PW *FN(PW,on_shared_domain)(__isl_take PW *pw1,
+ __isl_take PW *pw2,
+ __isl_give EL *(*fn)(__isl_take EL *el1, __isl_take EL *el2))
+{
+ isl_space *space;
+
+ if (!pw1 || !pw2)
+ goto error;
+
+ space = isl_space_copy(pw1->dim);
+ return FN(PW,on_shared_domain_in)(pw1, pw2, space, fn);
+error:
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return NULL;
+}
+
+#ifndef NO_NEG
+__isl_give PW *FN(PW,neg)(__isl_take PW *pw)
+{
+ int i;
+
+ if (!pw)
+ return NULL;
+
+ if (FN(PW,IS_ZERO)(pw))
+ return pw;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,neg)(pw->p[i].FIELD);
+ if (!pw->p[i].FIELD)
+ return FN(PW,free)(pw);
+ }
+
+ return pw;
+}
+
+__isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
+{
+ return FN(PW,add)(pw1, FN(PW,neg)(pw2));
+}
+#endif
+
+#ifndef NO_EVAL
+__isl_give isl_val *FN(PW,eval)(__isl_take PW *pw, __isl_take isl_point *pnt)
+{
+ int i;
+ int found = 0;
+ isl_ctx *ctx;
+ isl_space *pnt_dim = NULL;
+ isl_val *v;
+
+ if (!pw || !pnt)
+ goto error;
+ ctx = isl_point_get_ctx(pnt);
+ pnt_dim = isl_point_get_space(pnt);
+ isl_assert(ctx, isl_space_is_domain_internal(pnt_dim, pw->dim),
+ goto error);
+
+ for (i = 0; i < pw->n; ++i) {
+ found = isl_set_contains_point(pw->p[i].set, pnt);
+ if (found < 0)
+ goto error;
+ if (found)
+ break;
+ }
+ if (found)
+ v = FN(EL,eval)(FN(EL,copy)(pw->p[i].FIELD),
+ isl_point_copy(pnt));
+ else
+ v = isl_val_zero(ctx);
+ FN(PW,free)(pw);
+ isl_space_free(pnt_dim);
+ isl_point_free(pnt);
+ return v;
+error:
+ FN(PW,free)(pw);
+ isl_space_free(pnt_dim);
+ isl_point_free(pnt);
+ return NULL;
+}
+#endif
+
+/* Return the parameter domain of "pw".
+ */
+__isl_give isl_set *FN(PW,params)(__isl_take PW *pw)
+{
+ return isl_set_params(FN(PW,domain)(pw));
+}
+
+__isl_give isl_set *FN(PW,domain)(__isl_take PW *pw)
+{
+ int i;
+ isl_set *dom;
+
+ if (!pw)
+ return NULL;
+
+ dom = isl_set_empty(FN(PW,get_domain_space)(pw));
+ for (i = 0; i < pw->n; ++i)
+ dom = isl_set_union_disjoint(dom, isl_set_copy(pw->p[i].set));
+
+ FN(PW,free)(pw);
+
+ return dom;
+}
+
+/* Exploit the equalities in the domain of piece "i" of "pw"
+ * to simplify the associated function.
+ * If the domain of piece "i" is empty, then remove it entirely,
+ * replacing it with the final piece.
+ */
+static int FN(PW,exploit_equalities_and_remove_if_empty)(__isl_keep PW *pw,
+ int i)
+{
+ isl_basic_set *aff;
+ int empty = isl_set_plain_is_empty(pw->p[i].set);
+
+ if (empty < 0)
+ return -1;
+ if (empty) {
+ isl_set_free(pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ if (i != pw->n - 1)
+ pw->p[i] = pw->p[pw->n - 1];
+ pw->n--;
+
+ return 0;
+ }
+
+ aff = isl_set_affine_hull(isl_set_copy(pw->p[i].set));
+ pw->p[i].FIELD = FN(EL,substitute_equalities)(pw->p[i].FIELD, aff);
+ if (!pw->p[i].FIELD)
+ return -1;
+
+ return 0;
+}
+
+/* Convert a piecewise expression defined over a parameter domain
+ * into one that is defined over a zero-dimensional set.
+ */
+__isl_give PW *FN(PW,from_range)(__isl_take PW *pw)
+{
+ isl_space *space;
+
+ if (!pw)
+ return NULL;
+ if (!isl_space_is_set(pw->dim))
+ isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
+ "not living in a set space", return FN(PW,free)(pw));
+
+ space = FN(PW,get_space)(pw);
+ space = isl_space_from_range(space);
+ pw = FN(PW,reset_space)(pw, space);
+
+ return pw;
+}
+
+/* Fix the value of the given parameter or domain dimension of "pw"
+ * to be equal to "value".
+ */
+__isl_give PW *FN(PW,fix_si)(__isl_take PW *pw, enum isl_dim_type type,
+ unsigned pos, int value)
+{
+ int i;
+
+ if (!pw)
+ return NULL;
+
+ if (type == isl_dim_out)
+ isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
+ "cannot fix output dimension", return FN(PW,free)(pw));
+
+ if (pw->n == 0)
+ return pw;
+
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return FN(PW,free)(pw);
+
+ for (i = pw->n - 1; i >= 0; --i) {
+ pw->p[i].set = isl_set_fix_si(pw->p[i].set, type, pos, value);
+ if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
+ return FN(PW,free)(pw);
+ }
+
+ return pw;
+}
+
+/* Restrict the domain of "pw" by combining each cell
+ * with "set" through a call to "fn", where "fn" may be
+ * isl_set_intersect or isl_set_intersect_params.
+ */
+static __isl_give PW *FN(PW,intersect_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *set,
+ __isl_give isl_set *(*fn)(__isl_take isl_set *set1,
+ __isl_take isl_set *set2))
+{
+ int i;
+
+ if (!pw || !set)
+ goto error;
+
+ if (pw->n == 0) {
+ isl_set_free(set);
+ return pw;
+ }
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+
+ for (i = pw->n - 1; i >= 0; --i) {
+ pw->p[i].set = fn(pw->p[i].set, isl_set_copy(set));
+ if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
+ goto error;
+ }
+
+ isl_set_free(set);
+ return pw;
+error:
+ isl_set_free(set);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *set)
+{
+ return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect);
+}
+
+__isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
+ __isl_take isl_set *context)
+{
+ return FN(PW,align_params_pw_set_and)(pw, context,
+ &FN(PW,intersect_domain_aligned));
+}
+
+static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *set)
+{
+ return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect_params);
+}
+
+/* Intersect the domain of "pw" with the parameter domain "context".
+ */
+__isl_give PW *FN(PW,intersect_params)(__isl_take PW *pw,
+ __isl_take isl_set *context)
+{
+ return FN(PW,align_params_pw_set_and)(pw, context,
+ &FN(PW,intersect_params_aligned));
+}
+
+/* Compute the gist of "pw" with respect to the domain constraints
+ * of "context" for the case where the domain of the last element
+ * of "pw" is equal to "context".
+ * Call "fn_el" to compute the gist of this element, replace
+ * its domain by the universe and drop all other elements
+ * as their domains are necessarily disjoint from "context".
+ */
+static __isl_give PW *FN(PW,gist_last)(__isl_take PW *pw,
+ __isl_take isl_set *context,
+ __isl_give EL *(*fn_el)(__isl_take EL *el, __isl_take isl_set *set))
+{
+ int i;
+ isl_space *space;
+
+ for (i = 0; i < pw->n - 1; ++i) {
+ isl_set_free(pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ }
+ pw->p[0].FIELD = pw->p[pw->n - 1].FIELD;
+ pw->p[0].set = pw->p[pw->n - 1].set;
+ pw->n = 1;
+
+ space = isl_set_get_space(context);
+ pw->p[0].FIELD = fn_el(pw->p[0].FIELD, context);
+ context = isl_set_universe(space);
+ isl_set_free(pw->p[0].set);
+ pw->p[0].set = context;
+
+ if (!pw->p[0].FIELD || !pw->p[0].set)
+ return FN(PW,free)(pw);
+
+ return pw;
+}
+
+/* Compute the gist of "pw" with respect to the domain constraints
+ * of "context". Call "fn_el" to compute the gist of the elements
+ * and "fn_dom" to compute the gist of the domains.
+ *
+ * If the piecewise expression is empty or the context is the universe,
+ * then nothing can be simplified.
+ */
+static __isl_give PW *FN(PW,gist_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *context,
+ __isl_give EL *(*fn_el)(__isl_take EL *el,
+ __isl_take isl_set *set),
+ __isl_give isl_set *(*fn_dom)(__isl_take isl_set *set,
+ __isl_take isl_basic_set *bset))
+{
+ int i;
+ int is_universe;
+ isl_basic_set *hull = NULL;
+
+ if (!pw || !context)
+ goto error;
+
+ if (pw->n == 0) {
+ isl_set_free(context);
+ return pw;
+ }
+
+ is_universe = isl_set_plain_is_universe(context);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_set_free(context);
+ return pw;
+ }
+
+ if (!isl_space_match(pw->dim, isl_dim_param,
+ context->dim, isl_dim_param)) {
+ pw = FN(PW,align_params)(pw, isl_set_get_space(context));
+ context = isl_set_align_params(context, FN(PW,get_space)(pw));
+ }
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+
+ if (pw->n == 1) {
+ int equal;
+
+ equal = isl_set_plain_is_equal(pw->p[0].set, context);
+ if (equal < 0)
+ goto error;
+ if (equal)
+ return FN(PW,gist_last)(pw, context, fn_el);
+ }
+
+ context = isl_set_compute_divs(context);
+ hull = isl_set_simple_hull(isl_set_copy(context));
+
+ for (i = pw->n - 1; i >= 0; --i) {
+ isl_set *set_i;
+ int empty;
+
+ if (i == pw->n - 1) {
+ int equal;
+ equal = isl_set_plain_is_equal(pw->p[i].set, context);
+ if (equal < 0)
+ goto error;
+ if (equal) {
+ isl_basic_set_free(hull);
+ return FN(PW,gist_last)(pw, context, fn_el);
+ }
+ }
+ set_i = isl_set_intersect(isl_set_copy(pw->p[i].set),
+ isl_set_copy(context));
+ empty = isl_set_plain_is_empty(set_i);
+ pw->p[i].FIELD = fn_el(pw->p[i].FIELD, set_i);
+ pw->p[i].set = fn_dom(pw->p[i].set, isl_basic_set_copy(hull));
+ if (empty < 0 || !pw->p[i].FIELD || !pw->p[i].set)
+ goto error;
+ if (empty) {
+ isl_set_free(pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ if (i != pw->n - 1)
+ pw->p[i] = pw->p[pw->n - 1];
+ pw->n--;
+ }
+ }
+
+ isl_basic_set_free(hull);
+ isl_set_free(context);
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ isl_basic_set_free(hull);
+ isl_set_free(context);
+ return NULL;
+}
+
+static __isl_give PW *FN(PW,gist_domain_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *set)
+{
+ return FN(PW,gist_aligned)(pw, set, &FN(EL,gist),
+ &isl_set_gist_basic_set);
+}
+
+__isl_give PW *FN(PW,gist)(__isl_take PW *pw, __isl_take isl_set *context)
+{
+ return FN(PW,align_params_pw_set_and)(pw, context,
+ &FN(PW,gist_domain_aligned));
+}
+
+static __isl_give PW *FN(PW,gist_params_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *set)
+{
+ return FN(PW,gist_aligned)(pw, set, &FN(EL,gist_params),
+ &isl_set_gist_params_basic_set);
+}
+
+__isl_give PW *FN(PW,gist_params)(__isl_take PW *pw,
+ __isl_take isl_set *context)
+{
+ return FN(PW,align_params_pw_set_and)(pw, context,
+ &FN(PW,gist_params_aligned));
+}
+
+__isl_give PW *FN(PW,coalesce)(__isl_take PW *pw)
+{
+ int i, j;
+
+ if (!pw)
+ return NULL;
+ if (pw->n == 0)
+ return pw;
+
+ for (i = pw->n - 1; i >= 0; --i) {
+ for (j = i - 1; j >= 0; --j) {
+ if (!FN(EL,plain_is_equal)(pw->p[i].FIELD,
+ pw->p[j].FIELD))
+ continue;
+ pw->p[j].set = isl_set_union(pw->p[j].set,
+ pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ if (i != pw->n - 1)
+ pw->p[i] = pw->p[pw->n - 1];
+ pw->n--;
+ break;
+ }
+ if (j >= 0)
+ continue;
+ pw->p[i].set = isl_set_coalesce(pw->p[i].set);
+ if (!pw->p[i].set)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+isl_ctx *FN(PW,get_ctx)(__isl_keep PW *pw)
+{
+ return pw ? isl_space_get_ctx(pw->dim) : NULL;
+}
+
+#ifndef NO_INVOLVES_DIMS
+int FN(PW,involves_dims)(__isl_keep PW *pw, enum isl_dim_type type,
+ unsigned first, unsigned n)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ if (!pw)
+ return -1;
+ if (pw->n == 0 || n == 0)
+ return 0;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ for (i = 0; i < pw->n; ++i) {
+ int involves = FN(EL,involves_dims)(pw->p[i].FIELD,
+ type, first, n);
+ if (involves < 0 || involves)
+ return involves;
+ involves = isl_set_involves_dims(pw->p[i].set,
+ set_type, first, n);
+ if (involves < 0 || involves)
+ return involves;
+ }
+ return 0;
+}
+#endif
+
+__isl_give PW *FN(PW,set_dim_name)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ pw->dim = isl_space_set_dim_name(pw->dim, type, pos, s);
+ if (!pw->dim)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_set_dim_name(pw->p[i].set,
+ set_type, pos, s);
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,set_dim_name)(pw->p[i].FIELD, type, pos, s);
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+#ifndef NO_DROP_DIMS
+__isl_give PW *FN(PW,drop_dims)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ if (!pw)
+ return NULL;
+ if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
+ return pw;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+ pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
+ if (!pw->dim)
+ goto error;
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
+ if (!pw->p[i].FIELD)
+ goto error;
+ if (type == isl_dim_out)
+ continue;
+ pw->p[i].set = isl_set_drop(pw->p[i].set, set_type, first, n);
+ if (!pw->p[i].set)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+/* This function is very similar to drop_dims.
+ * The only difference is that the cells may still involve
+ * the specified dimensions. They are removed using
+ * isl_set_project_out instead of isl_set_drop.
+ */
+__isl_give PW *FN(PW,project_out)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ if (!pw)
+ return NULL;
+ if (n == 0 && !isl_space_get_tuple_name(pw->dim, type))
+ return pw;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+ pw->dim = isl_space_drop_dims(pw->dim, type, first, n);
+ if (!pw->dim)
+ goto error;
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_project_out(pw->p[i].set,
+ set_type, first, n);
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,drop_dims)(pw->p[i].FIELD, type, first, n);
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+/* Project the domain of pw onto its parameter space.
+ */
+__isl_give PW *FN(PW,project_domain_on_params)(__isl_take PW *pw)
+{
+ isl_space *space;
+ unsigned n;
+
+ n = FN(PW,dim)(pw, isl_dim_in);
+ pw = FN(PW,project_out)(pw, isl_dim_in, 0, n);
+ space = FN(PW,get_domain_space)(pw);
+ space = isl_space_params(space);
+ pw = FN(PW,reset_domain_space)(pw, space);
+ return pw;
+}
+#endif
+
+#ifndef NO_INSERT_DIMS
+__isl_give PW *FN(PW,insert_dims)(__isl_take PW *pw, enum isl_dim_type type,
+ unsigned first, unsigned n)
+{
+ int i;
+ enum isl_dim_type set_type;
+
+ if (!pw)
+ return NULL;
+ if (n == 0 && !isl_space_is_named_or_nested(pw->dim, type))
+ return pw;
+
+ set_type = type == isl_dim_in ? isl_dim_set : type;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+
+ pw->dim = isl_space_insert_dims(pw->dim, type, first, n);
+ if (!pw->dim)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_insert_dims(pw->p[i].set,
+ set_type, first, n);
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,insert_dims)(pw->p[i].FIELD,
+ type, first, n);
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+#endif
+
+__isl_give PW *FN(PW,fix_dim)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned pos, isl_int v)
+{
+ int i;
+
+ if (!pw)
+ return NULL;
+
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_fix(pw->p[i].set, type, pos, v);
+ if (FN(PW,exploit_equalities_and_remove_if_empty)(pw, i) < 0)
+ return FN(PW,free)(pw);
+ }
+
+ return pw;
+}
+
+/* Fix the value of the variable at position "pos" of type "type" of "pw"
+ * to be equal to "v".
+ */
+__isl_give PW *FN(PW,fix_val)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_val *v)
+{
+ if (!v)
+ return FN(PW,free)(pw);
+ if (!isl_val_is_int(v))
+ isl_die(FN(PW,get_ctx)(pw), isl_error_invalid,
+ "expecting integer value", goto error);
+
+ pw = FN(PW,fix_dim)(pw, type, pos, v->n);
+ isl_val_free(v);
+
+ return pw;
+error:
+ isl_val_free(v);
+ return FN(PW,free)(pw);
+}
+
+unsigned FN(PW,dim)(__isl_keep PW *pw, enum isl_dim_type type)
+{
+ return pw ? isl_space_dim(pw->dim, type) : 0;
+}
+
+__isl_give PW *FN(PW,split_dims)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ int i;
+
+ if (!pw)
+ return NULL;
+ if (n == 0)
+ return pw;
+
+ if (type == isl_dim_in)
+ type = isl_dim_set;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+ if (!pw->dim)
+ goto error;
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_split_dims(pw->p[i].set, type, first, n);
+ if (!pw->p[i].set)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+#ifndef NO_OPT
+/* Compute the maximal value attained by the piecewise quasipolynomial
+ * on its domain or zero if the domain is empty.
+ * In the worst case, the domain is scanned completely,
+ * so the domain is assumed to be bounded.
+ */
+__isl_give isl_val *FN(PW,opt)(__isl_take PW *pw, int max)
+{
+ int i;
+ isl_val *opt;
+
+ if (!pw)
+ return NULL;
+
+ if (pw->n == 0) {
+ opt = isl_val_zero(FN(PW,get_ctx)(pw));
+ FN(PW,free)(pw);
+ return opt;
+ }
+
+ opt = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[0].FIELD),
+ isl_set_copy(pw->p[0].set), max);
+ for (i = 1; i < pw->n; ++i) {
+ isl_val *opt_i;
+ opt_i = FN(EL,opt_on_domain)(FN(EL,copy)(pw->p[i].FIELD),
+ isl_set_copy(pw->p[i].set), max);
+ if (max)
+ opt = isl_val_max(opt, opt_i);
+ else
+ opt = isl_val_min(opt, opt_i);
+ }
+
+ FN(PW,free)(pw);
+ return opt;
+}
+
+__isl_give isl_val *FN(PW,max)(__isl_take PW *pw)
+{
+ return FN(PW,opt)(pw, 1);
+}
+
+__isl_give isl_val *FN(PW,min)(__isl_take PW *pw)
+{
+ return FN(PW,opt)(pw, 0);
+}
+#endif
+
+__isl_give isl_space *FN(PW,get_space)(__isl_keep PW *pw)
+{
+ return pw ? isl_space_copy(pw->dim) : NULL;
+}
+
+__isl_give isl_space *FN(PW,get_domain_space)(__isl_keep PW *pw)
+{
+ return pw ? isl_space_domain(isl_space_copy(pw->dim)) : NULL;
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "pw".
+ * Return -1 if no such dimension can be found.
+ */
+int FN(PW,find_dim_by_name)(__isl_keep PW *pw,
+ enum isl_dim_type type, const char *name)
+{
+ if (!pw)
+ return -1;
+ return isl_space_find_dim_by_name(pw->dim, type, name);
+}
+
+#ifndef NO_RESET_DIM
+/* Reset the space of "pw". Since we don't know if the elements
+ * represent the spaces themselves or their domains, we pass along
+ * both when we call their reset_space_and_domain.
+ */
+static __isl_give PW *FN(PW,reset_space_and_domain)(__isl_take PW *pw,
+ __isl_take isl_space *space, __isl_take isl_space *domain)
+{
+ int i;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw || !space || !domain)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_reset_space(pw->p[i].set,
+ isl_space_copy(domain));
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,reset_space_and_domain)(pw->p[i].FIELD,
+ isl_space_copy(space), isl_space_copy(domain));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ isl_space_free(domain);
+
+ isl_space_free(pw->dim);
+ pw->dim = space;
+
+ return pw;
+error:
+ isl_space_free(domain);
+ isl_space_free(space);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,reset_domain_space)(__isl_take PW *pw,
+ __isl_take isl_space *domain)
+{
+ isl_space *space;
+
+ space = isl_space_extend_domain_with_range(isl_space_copy(domain),
+ FN(PW,get_space)(pw));
+ return FN(PW,reset_space_and_domain)(pw, space, domain);
+}
+
+__isl_give PW *FN(PW,reset_space)(__isl_take PW *pw, __isl_take isl_space *dim)
+{
+ isl_space *domain;
+
+ domain = isl_space_domain(isl_space_copy(dim));
+ return FN(PW,reset_space_and_domain)(pw, dim, domain);
+}
+
+__isl_give PW *FN(PW,set_tuple_id)(__isl_take PW *pw, enum isl_dim_type type,
+ __isl_take isl_id *id)
+{
+ isl_space *space;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+
+ space = FN(PW,get_space)(pw);
+ space = isl_space_set_tuple_id(space, type, id);
+
+ return FN(PW,reset_space)(pw, space);
+error:
+ isl_id_free(id);
+ return FN(PW,free)(pw);
+}
+
+/* Drop the id on the specified tuple.
+ */
+__isl_give PW *FN(PW,reset_tuple_id)(__isl_take PW *pw, enum isl_dim_type type)
+{
+ isl_space *space;
+
+ if (!pw)
+ return NULL;
+ if (!FN(PW,has_tuple_id)(pw, type))
+ return pw;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+
+ space = FN(PW,get_space)(pw);
+ space = isl_space_reset_tuple_id(space, type);
+
+ return FN(PW,reset_space)(pw, space);
+}
+
+__isl_give PW *FN(PW,set_dim_id)(__isl_take PW *pw,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+ pw->dim = isl_space_set_dim_id(pw->dim, type, pos, id);
+ return FN(PW,reset_space)(pw, isl_space_copy(pw->dim));
+error:
+ isl_id_free(id);
+ return FN(PW,free)(pw);
+}
+#endif
+
+int FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
+{
+ if (!pw1 || !pw2)
+ return -1;
+
+ return isl_space_is_equal(pw1->dim, pw2->dim);
+}
+
+#ifndef NO_MORPH
+__isl_give PW *FN(PW,morph_domain)(__isl_take PW *pw,
+ __isl_take isl_morph *morph)
+{
+ int i;
+ isl_ctx *ctx;
+
+ if (!pw || !morph)
+ goto error;
+
+ ctx = isl_space_get_ctx(pw->dim);
+ isl_assert(ctx, isl_space_is_domain_internal(morph->dom->dim, pw->dim),
+ goto error);
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+ pw->dim = isl_space_extend_domain_with_range(
+ isl_space_copy(morph->ran->dim), pw->dim);
+ if (!pw->dim)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_morph_set(isl_morph_copy(morph), pw->p[i].set);
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,morph_domain)(pw->p[i].FIELD,
+ isl_morph_copy(morph));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ isl_morph_free(morph);
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ isl_morph_free(morph);
+ return NULL;
+}
+#endif
+
+int FN(PW,n_piece)(__isl_keep PW *pw)
+{
+ return pw ? pw->n : 0;
+}
+
+int FN(PW,foreach_piece)(__isl_keep PW *pw,
+ int (*fn)(__isl_take isl_set *set, __isl_take EL *el, void *user),
+ void *user)
+{
+ int i;
+
+ if (!pw)
+ return -1;
+
+ for (i = 0; i < pw->n; ++i)
+ if (fn(isl_set_copy(pw->p[i].set),
+ FN(EL,copy)(pw->p[i].FIELD), user) < 0)
+ return -1;
+
+ return 0;
+}
+
+#ifndef NO_LIFT
+static int any_divs(__isl_keep isl_set *set)
+{
+ int i;
+
+ if (!set)
+ return -1;
+
+ for (i = 0; i < set->n; ++i)
+ if (set->p[i]->n_div > 0)
+ return 1;
+
+ return 0;
+}
+
+static int foreach_lifted_subset(__isl_take isl_set *set, __isl_take EL *el,
+ int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
+ void *user), void *user)
+{
+ int i;
+
+ if (!set || !el)
+ goto error;
+
+ for (i = 0; i < set->n; ++i) {
+ isl_set *lift;
+ EL *copy;
+
+ lift = isl_set_from_basic_set(isl_basic_set_copy(set->p[i]));
+ lift = isl_set_lift(lift);
+
+ copy = FN(EL,copy)(el);
+ copy = FN(EL,lift)(copy, isl_set_get_space(lift));
+
+ if (fn(lift, copy, user) < 0)
+ goto error;
+ }
+
+ isl_set_free(set);
+ FN(EL,free)(el);
+
+ return 0;
+error:
+ isl_set_free(set);
+ FN(EL,free)(el);
+ return -1;
+}
+
+int FN(PW,foreach_lifted_piece)(__isl_keep PW *pw,
+ int (*fn)(__isl_take isl_set *set, __isl_take EL *el,
+ void *user), void *user)
+{
+ int i;
+
+ if (!pw)
+ return -1;
+
+ for (i = 0; i < pw->n; ++i) {
+ isl_set *set;
+ EL *el;
+
+ set = isl_set_copy(pw->p[i].set);
+ el = FN(EL,copy)(pw->p[i].FIELD);
+ if (!any_divs(set)) {
+ if (fn(set, el, user) < 0)
+ return -1;
+ continue;
+ }
+ if (foreach_lifted_subset(set, el, fn, user) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+#endif
+
+#ifndef NO_MOVE_DIMS
+__isl_give PW *FN(PW,move_dims)(__isl_take PW *pw,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ int i;
+
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+
+ pw->dim = isl_space_move_dims(pw->dim, dst_type, dst_pos, src_type, src_pos, n);
+ if (!pw->dim)
+ goto error;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,move_dims)(pw->p[i].FIELD,
+ dst_type, dst_pos, src_type, src_pos, n);
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ if (dst_type == isl_dim_in)
+ dst_type = isl_dim_set;
+ if (src_type == isl_dim_in)
+ src_type = isl_dim_set;
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_move_dims(pw->p[i].set,
+ dst_type, dst_pos,
+ src_type, src_pos, n);
+ if (!pw->p[i].set)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+#endif
+
+__isl_give PW *FN(PW,mul_isl_int)(__isl_take PW *pw, isl_int v)
+{
+ int i;
+
+ if (isl_int_is_one(v))
+ return pw;
+ if (pw && DEFAULT_IS_ZERO && isl_int_is_zero(v)) {
+ PW *zero;
+ isl_space *dim = FN(PW,get_space)(pw);
+#ifdef HAS_TYPE
+ zero = FN(PW,ZERO)(dim, pw->type);
+#else
+ zero = FN(PW,ZERO)(dim);
+#endif
+ FN(PW,free)(pw);
+ return zero;
+ }
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ return NULL;
+ if (pw->n == 0)
+ return pw;
+
+#ifdef HAS_TYPE
+ if (isl_int_is_neg(v))
+ pw->type = isl_fold_type_negate(pw->type);
+#endif
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,scale)(pw->p[i].FIELD, v);
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ return pw;
+error:
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+/* Multiply the pieces of "pw" by "v" and return the result.
+ */
+__isl_give PW *FN(PW,scale_val)(__isl_take PW *pw, __isl_take isl_val *v)
+{
+ int i;
+
+ if (!pw || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return pw;
+ }
+ if (pw && DEFAULT_IS_ZERO && isl_val_is_zero(v)) {
+ PW *zero;
+ isl_space *space = FN(PW,get_space)(pw);
+#ifdef HAS_TYPE
+ zero = FN(PW,ZERO)(space, pw->type);
+#else
+ zero = FN(PW,ZERO)(space);
+#endif
+ FN(PW,free)(pw);
+ isl_val_free(v);
+ return zero;
+ }
+ if (pw->n == 0) {
+ isl_val_free(v);
+ return pw;
+ }
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+
+#ifdef HAS_TYPE
+ if (isl_val_is_neg(v))
+ pw->type = isl_fold_type_negate(pw->type);
+#endif
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,scale_val)(pw->p[i].FIELD,
+ isl_val_copy(v));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return pw;
+error:
+ isl_val_free(v);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+/* Divide the pieces of "pw" by "v" and return the result.
+ */
+__isl_give PW *FN(PW,scale_down_val)(__isl_take PW *pw, __isl_take isl_val *v)
+{
+ int i;
+
+ if (!pw || !v)
+ goto error;
+
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return pw;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (isl_val_is_zero(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "cannot scale down by zero", goto error);
+
+ if (pw->n == 0) {
+ isl_val_free(v);
+ return pw;
+ }
+ pw = FN(PW,cow)(pw);
+ if (!pw)
+ goto error;
+
+#ifdef HAS_TYPE
+ if (isl_val_is_neg(v))
+ pw->type = isl_fold_type_negate(pw->type);
+#endif
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].FIELD = FN(EL,scale_down_val)(pw->p[i].FIELD,
+ isl_val_copy(v));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ isl_val_free(v);
+ return pw;
+error:
+ isl_val_free(v);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,scale)(__isl_take PW *pw, isl_int v)
+{
+ return FN(PW,mul_isl_int)(pw, v);
+}
+
+static int FN(PW,qsort_set_cmp)(const void *p1, const void *p2)
+{
+ isl_set *set1 = *(isl_set * const *)p1;
+ isl_set *set2 = *(isl_set * const *)p2;
+
+ return isl_set_plain_cmp(set1, set2);
+}
+
+/* We normalize in place, but if anything goes wrong we need
+ * to return NULL, so we need to make sure we don't change the
+ * meaning of any possible other copies of map.
+ */
+__isl_give PW *FN(PW,normalize)(__isl_take PW *pw)
+{
+ int i, j;
+ isl_set *set;
+
+ if (!pw)
+ return NULL;
+ for (i = 0; i < pw->n; ++i) {
+ set = isl_set_normalize(isl_set_copy(pw->p[i].set));
+ if (!set)
+ return FN(PW,free)(pw);
+ isl_set_free(pw->p[i].set);
+ pw->p[i].set = set;
+ }
+ qsort(pw->p, pw->n, sizeof(pw->p[0]), &FN(PW,qsort_set_cmp));
+ for (i = pw->n - 1; i >= 1; --i) {
+ if (!isl_set_plain_is_equal(pw->p[i - 1].set, pw->p[i].set))
+ continue;
+ if (!FN(EL,plain_is_equal)(pw->p[i - 1].FIELD, pw->p[i].FIELD))
+ continue;
+ set = isl_set_union(isl_set_copy(pw->p[i - 1].set),
+ isl_set_copy(pw->p[i].set));
+ if (!set)
+ return FN(PW,free)(pw);
+ isl_set_free(pw->p[i].set);
+ FN(EL,free)(pw->p[i].FIELD);
+ isl_set_free(pw->p[i - 1].set);
+ pw->p[i - 1].set = set;
+ for (j = i + 1; j < pw->n; ++j)
+ pw->p[j - 1] = pw->p[j];
+ pw->n--;
+ }
+
+ return pw;
+}
+
+/* Is pw1 obviously equal to pw2?
+ * That is, do they have obviously identical cells and obviously identical
+ * elements on each cell?
+ */
+int FN(PW,plain_is_equal)(__isl_keep PW *pw1, __isl_keep PW *pw2)
+{
+ int i;
+ int equal;
+
+ if (!pw1 || !pw2)
+ return -1;
+
+ if (pw1 == pw2)
+ return 1;
+ if (!isl_space_is_equal(pw1->dim, pw2->dim))
+ return 0;
+
+ pw1 = FN(PW,copy)(pw1);
+ pw2 = FN(PW,copy)(pw2);
+ pw1 = FN(PW,normalize)(pw1);
+ pw2 = FN(PW,normalize)(pw2);
+ if (!pw1 || !pw2)
+ goto error;
+
+ equal = pw1->n == pw2->n;
+ for (i = 0; equal && i < pw1->n; ++i) {
+ equal = isl_set_plain_is_equal(pw1->p[i].set, pw2->p[i].set);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ break;
+ equal = FN(EL,plain_is_equal)(pw1->p[i].FIELD, pw2->p[i].FIELD);
+ if (equal < 0)
+ goto error;
+ }
+
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return equal;
+error:
+ FN(PW,free)(pw1);
+ FN(PW,free)(pw2);
+ return -1;
+}
+
+#ifndef NO_PULLBACK
+static __isl_give PW *FN(PW,align_params_pw_multi_aff_and)(__isl_take PW *pw,
+ __isl_take isl_multi_aff *ma,
+ __isl_give PW *(*fn)(__isl_take PW *pw, __isl_take isl_multi_aff *ma))
+{
+ isl_ctx *ctx;
+ isl_space *ma_space;
+
+ ma_space = isl_multi_aff_get_space(ma);
+ if (!pw || !ma || !ma_space)
+ goto error;
+ if (isl_space_match(pw->dim, isl_dim_param, ma_space, isl_dim_param)) {
+ isl_space_free(ma_space);
+ return fn(pw, ma);
+ }
+ ctx = FN(PW,get_ctx)(pw);
+ if (!isl_space_has_named_params(pw->dim) ||
+ !isl_space_has_named_params(ma_space))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pw = FN(PW,align_params)(pw, ma_space);
+ ma = isl_multi_aff_align_params(ma, FN(PW,get_space)(pw));
+ return fn(pw, ma);
+error:
+ isl_space_free(ma_space);
+ FN(PW,free)(pw);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+static __isl_give PW *FN(PW,align_params_pw_pw_multi_aff_and)(__isl_take PW *pw,
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_give PW *(*fn)(__isl_take PW *pw,
+ __isl_take isl_pw_multi_aff *ma))
+{
+ isl_ctx *ctx;
+ isl_space *pma_space;
+
+ pma_space = isl_pw_multi_aff_get_space(pma);
+ if (!pw || !pma || !pma_space)
+ goto error;
+ if (isl_space_match(pw->dim, isl_dim_param, pma_space, isl_dim_param)) {
+ isl_space_free(pma_space);
+ return fn(pw, pma);
+ }
+ ctx = FN(PW,get_ctx)(pw);
+ if (!isl_space_has_named_params(pw->dim) ||
+ !isl_space_has_named_params(pma_space))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pw = FN(PW,align_params)(pw, pma_space);
+ pma = isl_pw_multi_aff_align_params(pma, FN(PW,get_space)(pw));
+ return fn(pw, pma);
+error:
+ isl_space_free(pma_space);
+ FN(PW,free)(pw);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Compute the pullback of "pw" by the function represented by "ma".
+ * In other words, plug in "ma" in "pw".
+ */
+static __isl_give PW *FN(PW,pullback_multi_aff_aligned)(__isl_take PW *pw,
+ __isl_take isl_multi_aff *ma)
+{
+ int i;
+ isl_space *space = NULL;
+
+ ma = isl_multi_aff_align_divs(ma);
+ pw = FN(PW,cow)(pw);
+ if (!pw || !ma)
+ goto error;
+
+ space = isl_space_join(isl_multi_aff_get_space(ma),
+ FN(PW,get_space)(pw));
+
+ for (i = 0; i < pw->n; ++i) {
+ pw->p[i].set = isl_set_preimage_multi_aff(pw->p[i].set,
+ isl_multi_aff_copy(ma));
+ if (!pw->p[i].set)
+ goto error;
+ pw->p[i].FIELD = FN(EL,pullback_multi_aff)(pw->p[i].FIELD,
+ isl_multi_aff_copy(ma));
+ if (!pw->p[i].FIELD)
+ goto error;
+ }
+
+ pw = FN(PW,reset_space)(pw, space);
+ isl_multi_aff_free(ma);
+ return pw;
+error:
+ isl_space_free(space);
+ isl_multi_aff_free(ma);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,pullback_multi_aff)(__isl_take PW *pw,
+ __isl_take isl_multi_aff *ma)
+{
+ return FN(PW,align_params_pw_multi_aff_and)(pw, ma,
+ &FN(PW,pullback_multi_aff_aligned));
+}
+
+/* Compute the pullback of "pw" by the function represented by "pma".
+ * In other words, plug in "pma" in "pw".
+ */
+static __isl_give PW *FN(PW,pullback_pw_multi_aff_aligned)(__isl_take PW *pw,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ int i;
+ PW *res;
+
+ if (!pma)
+ goto error;
+
+ if (pma->n == 0) {
+ isl_space *space;
+ space = isl_space_join(isl_pw_multi_aff_get_space(pma),
+ FN(PW,get_space)(pw));
+ isl_pw_multi_aff_free(pma);
+ res = FN(PW,empty)(space);
+ FN(PW,free)(pw);
+ return res;
+ }
+
+ res = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
+ isl_multi_aff_copy(pma->p[0].maff));
+ res = FN(PW,intersect_domain)(res, isl_set_copy(pma->p[0].set));
+
+ for (i = 1; i < pma->n; ++i) {
+ PW *res_i;
+
+ res_i = FN(PW,pullback_multi_aff)(FN(PW,copy)(pw),
+ isl_multi_aff_copy(pma->p[i].maff));
+ res_i = FN(PW,intersect_domain)(res_i,
+ isl_set_copy(pma->p[i].set));
+ res = FN(PW,add_disjoint)(res, res_i);
+ }
+
+ isl_pw_multi_aff_free(pma);
+ FN(PW,free)(pw);
+ return res;
+error:
+ isl_pw_multi_aff_free(pma);
+ FN(PW,free)(pw);
+ return NULL;
+}
+
+__isl_give PW *FN(PW,pullback_pw_multi_aff)(__isl_take PW *pw,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ return FN(PW,align_params_pw_pw_multi_aff_and)(pw, pma,
+ &FN(PW,pullback_pw_multi_aff_aligned));
+}
+#endif
diff --git a/polly/lib/External/isl/isl_range.c b/polly/lib/External/isl/isl_range.c
new file mode 100644
index 00000000000..5599582cb83
--- /dev/null
+++ b/polly/lib/External/isl/isl_range.c
@@ -0,0 +1,491 @@
+#include <isl_ctx_private.h>
+#include <isl_constraint_private.h>
+#include <isl/set.h>
+#include <isl_polynomial_private.h>
+#include <isl_morph.h>
+#include <isl_range.h>
+
+struct range_data {
+ struct isl_bound *bound;
+ int *signs;
+ int sign;
+ int test_monotonicity;
+ int monotonicity;
+ int tight;
+ isl_qpolynomial *poly;
+ isl_pw_qpolynomial_fold *pwf;
+ isl_pw_qpolynomial_fold *pwf_tight;
+};
+
+static int propagate_on_domain(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct range_data *data);
+
+/* Check whether the polynomial "poly" has sign "sign" over "bset",
+ * i.e., if sign == 1, check that the lower bound on the polynomial
+ * is non-negative and if sign == -1, check that the upper bound on
+ * the polynomial is non-positive.
+ */
+static int has_sign(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_qpolynomial *poly, int sign, int *signs)
+{
+ struct range_data data_m;
+ unsigned nvar;
+ unsigned nparam;
+ isl_space *dim;
+ isl_val *opt;
+ int r;
+ enum isl_fold type;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ bset = isl_basic_set_copy(bset);
+ poly = isl_qpolynomial_copy(poly);
+
+ bset = isl_basic_set_move_dims(bset, isl_dim_set, 0,
+ isl_dim_param, 0, nparam);
+ poly = isl_qpolynomial_move_dims(poly, isl_dim_in, 0,
+ isl_dim_param, 0, nparam);
+
+ dim = isl_qpolynomial_get_space(poly);
+ dim = isl_space_params(dim);
+ dim = isl_space_from_domain(dim);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+
+ data_m.test_monotonicity = 0;
+ data_m.signs = signs;
+ data_m.sign = -sign;
+ type = data_m.sign < 0 ? isl_fold_min : isl_fold_max;
+ data_m.pwf = isl_pw_qpolynomial_fold_zero(dim, type);
+ data_m.tight = 0;
+ data_m.pwf_tight = NULL;
+
+ if (propagate_on_domain(bset, poly, &data_m) < 0)
+ goto error;
+
+ if (sign > 0)
+ opt = isl_pw_qpolynomial_fold_min(data_m.pwf);
+ else
+ opt = isl_pw_qpolynomial_fold_max(data_m.pwf);
+
+ if (!opt)
+ r = -1;
+ else if (isl_val_is_nan(opt) ||
+ isl_val_is_infty(opt) ||
+ isl_val_is_neginfty(opt))
+ r = 0;
+ else
+ r = sign * isl_val_sgn(opt) >= 0;
+
+ isl_val_free(opt);
+
+ return r;
+error:
+ isl_pw_qpolynomial_fold_free(data_m.pwf);
+ return -1;
+}
+
+/* Return 1 if poly is monotonically increasing in the last set variable,
+ * -1 if poly is monotonically decreasing in the last set variable,
+ * 0 if no conclusion,
+ * -2 on error.
+ *
+ * We simply check the sign of p(x+1)-p(x)
+ */
+static int monotonicity(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_qpolynomial *poly, struct range_data *data)
+{
+ isl_ctx *ctx;
+ isl_space *dim;
+ isl_qpolynomial *sub = NULL;
+ isl_qpolynomial *diff = NULL;
+ int result = 0;
+ int s;
+ unsigned nvar;
+
+ ctx = isl_qpolynomial_get_ctx(poly);
+ dim = isl_qpolynomial_get_domain_space(poly);
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ sub = isl_qpolynomial_var_on_domain(isl_space_copy(dim), isl_dim_set, nvar - 1);
+ sub = isl_qpolynomial_add(sub,
+ isl_qpolynomial_rat_cst_on_domain(dim, ctx->one, ctx->one));
+
+ diff = isl_qpolynomial_substitute(isl_qpolynomial_copy(poly),
+ isl_dim_in, nvar - 1, 1, &sub);
+ diff = isl_qpolynomial_sub(diff, isl_qpolynomial_copy(poly));
+
+ s = has_sign(bset, diff, 1, data->signs);
+ if (s < 0)
+ goto error;
+ if (s)
+ result = 1;
+ else {
+ s = has_sign(bset, diff, -1, data->signs);
+ if (s < 0)
+ goto error;
+ if (s)
+ result = -1;
+ }
+
+ isl_qpolynomial_free(diff);
+ isl_qpolynomial_free(sub);
+
+ return result;
+error:
+ isl_qpolynomial_free(diff);
+ isl_qpolynomial_free(sub);
+ return -2;
+}
+
+static __isl_give isl_qpolynomial *bound2poly(__isl_take isl_constraint *bound,
+ __isl_take isl_space *dim, 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);
+ return isl_qpolynomial_from_constraint(bound, isl_dim_set, pos);
+}
+
+static int bound_is_integer(__isl_take isl_constraint *bound, unsigned pos)
+{
+ isl_int c;
+ int is_int;
+
+ if (!bound)
+ return 1;
+
+ isl_int_init(c);
+ isl_constraint_get_coefficient(bound, isl_dim_set, pos, &c);
+ is_int = isl_int_is_one(c) || isl_int_is_negone(c);
+ isl_int_clear(c);
+
+ return is_int;
+}
+
+struct isl_fixed_sign_data {
+ int *signs;
+ int sign;
+ isl_qpolynomial *poly;
+};
+
+/* Add term "term" to data->poly if it has sign data->sign.
+ * The sign is determined based on the signs of the parameters
+ * and variables in data->signs. The integer divisions, if
+ * any, are assumed to be non-negative.
+ */
+static int collect_fixed_sign_terms(__isl_take isl_term *term, void *user)
+{
+ struct isl_fixed_sign_data *data = (struct isl_fixed_sign_data *)user;
+ isl_int n;
+ int i;
+ int sign;
+ unsigned nparam;
+ unsigned nvar;
+
+ if (!term)
+ return -1;
+
+ nparam = isl_term_dim(term, isl_dim_param);
+ nvar = isl_term_dim(term, isl_dim_set);
+
+ isl_int_init(n);
+
+ isl_term_get_num(term, &n);
+
+ sign = isl_int_sgn(n);
+ for (i = 0; i < nparam; ++i) {
+ if (data->signs[i] > 0)
+ continue;
+ if (isl_term_get_exp(term, isl_dim_param, i) % 2)
+ sign = -sign;
+ }
+ for (i = 0; i < nvar; ++i) {
+ if (data->signs[nparam + i] > 0)
+ continue;
+ if (isl_term_get_exp(term, isl_dim_set, i) % 2)
+ sign = -sign;
+ }
+
+ if (sign == data->sign) {
+ isl_qpolynomial *t = isl_qpolynomial_from_term(term);
+
+ data->poly = isl_qpolynomial_add(data->poly, t);
+ } else
+ isl_term_free(term);
+
+ isl_int_clear(n);
+
+ return 0;
+}
+
+/* Construct and return a polynomial that consists of the terms
+ * in "poly" that have sign "sign". The integer divisions, if
+ * any, are assumed to be non-negative.
+ */
+__isl_give isl_qpolynomial *isl_qpolynomial_terms_of_sign(
+ __isl_keep isl_qpolynomial *poly, int *signs, int sign)
+{
+ isl_space *space;
+ struct isl_fixed_sign_data data = { signs, sign };
+
+ space = isl_qpolynomial_get_domain_space(poly);
+ data.poly = isl_qpolynomial_zero_on_domain(space);
+
+ if (isl_qpolynomial_foreach_term(poly, collect_fixed_sign_terms, &data) < 0)
+ goto error;
+
+ return data.poly;
+error:
+ isl_qpolynomial_free(data.poly);
+ return NULL;
+}
+
+/* Helper function to add a guarded polynomial to either pwf_tight or pwf,
+ * depending on whether the result has been determined to be tight.
+ */
+static int add_guarded_poly(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct range_data *data)
+{
+ enum isl_fold type = data->sign < 0 ? isl_fold_min : isl_fold_max;
+ isl_set *set;
+ isl_qpolynomial_fold *fold;
+ isl_pw_qpolynomial_fold *pwf;
+
+ bset = isl_basic_set_params(bset);
+ poly = isl_qpolynomial_project_domain_on_params(poly);
+
+ fold = isl_qpolynomial_fold_alloc(type, poly);
+ set = isl_set_from_basic_set(bset);
+ pwf = isl_pw_qpolynomial_fold_alloc(type, set, fold);
+ if (data->tight)
+ data->pwf_tight = isl_pw_qpolynomial_fold_fold(
+ data->pwf_tight, pwf);
+ else
+ data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, pwf);
+
+ return 0;
+}
+
+/* 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.
+ * If the polynomial has been determined to be monotonic
+ * in the variable, then simply plug in the appropriate bound.
+ * If the current polynomial is tight and if this bound is integer,
+ * then the result is still tight. In all other cases, the results
+ * may not be tight.
+ * Otherwise, plug in the largest bound (in absolute value) in
+ * the positive terms (if an upper bound is wanted) or the negative terms
+ * (if a lower bounded is wanted) and the other bound in the other terms.
+ *
+ * If all variables have been eliminated, then record the result.
+ * Ohterwise, recurse on the next variable.
+ */
+static int propagate_on_bound_pair(__isl_take isl_constraint *lower,
+ __isl_take isl_constraint *upper, __isl_take isl_basic_set *bset,
+ void *user)
+{
+ struct range_data *data = (struct range_data *)user;
+ int save_tight = data->tight;
+ isl_qpolynomial *poly;
+ int r;
+ unsigned nvar;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ if (data->monotonicity) {
+ isl_qpolynomial *sub;
+ isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
+ if (data->monotonicity * data->sign > 0) {
+ if (data->tight)
+ data->tight = bound_is_integer(upper, nvar);
+ sub = bound2poly(upper, dim, nvar, 1);
+ isl_constraint_free(lower);
+ } else {
+ if (data->tight)
+ data->tight = bound_is_integer(lower, nvar);
+ sub = bound2poly(lower, dim, nvar, -1);
+ isl_constraint_free(upper);
+ }
+ poly = isl_qpolynomial_copy(data->poly);
+ poly = isl_qpolynomial_substitute(poly, isl_dim_in, nvar, 1, &sub);
+ poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, nvar, 1);
+
+ isl_qpolynomial_free(sub);
+ } else {
+ isl_qpolynomial *l, *u;
+ isl_qpolynomial *pos, *neg;
+ isl_space *dim = isl_qpolynomial_get_domain_space(data->poly);
+ unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
+ int sign = data->sign * data->signs[nparam + nvar];
+
+ data->tight = 0;
+
+ u = bound2poly(upper, isl_space_copy(dim), nvar, 1);
+ l = bound2poly(lower, dim, nvar, -1);
+
+ 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);
+
+ 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)
+ r = add_guarded_poly(bset, poly, data);
+ else
+ r = propagate_on_domain(bset, poly, data);
+
+ data->tight = save_tight;
+
+ return r;
+}
+
+/* Recursively perform range propagation on the polynomial "poly"
+ * defined over the basic set "bset" and collect the results in "data".
+ */
+static int propagate_on_domain(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct range_data *data)
+{
+ isl_ctx *ctx;
+ isl_qpolynomial *save_poly = data->poly;
+ int save_monotonicity = data->monotonicity;
+ unsigned d;
+
+ if (!bset || !poly)
+ goto error;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ d = isl_basic_set_dim(bset, isl_dim_set);
+ isl_assert(ctx, d >= 1, goto error);
+
+ if (isl_qpolynomial_is_cst(poly, NULL, NULL)) {
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 0, d);
+ poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, 0, d);
+ return add_guarded_poly(bset, poly, data);
+ }
+
+ if (data->test_monotonicity)
+ data->monotonicity = monotonicity(bset, poly, data);
+ else
+ data->monotonicity = 0;
+ if (data->monotonicity < -1)
+ goto error;
+
+ data->poly = poly;
+ if (isl_basic_set_foreach_bound_pair(bset, isl_dim_set, d - 1,
+ &propagate_on_bound_pair, data) < 0)
+ goto error;
+
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ data->monotonicity = save_monotonicity;
+ data->poly = save_poly;
+
+ return 0;
+error:
+ isl_basic_set_free(bset);
+ isl_qpolynomial_free(poly);
+ data->monotonicity = save_monotonicity;
+ data->poly = save_poly;
+ return -1;
+}
+
+static int basic_guarded_poly_bound(__isl_take isl_basic_set *bset, void *user)
+{
+ struct range_data *data = (struct range_data *)user;
+ isl_ctx *ctx;
+ unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
+ unsigned dim = isl_basic_set_dim(bset, isl_dim_set);
+ int r;
+
+ data->signs = NULL;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ data->signs = isl_alloc_array(ctx, int,
+ isl_basic_set_dim(bset, isl_dim_all));
+
+ if (isl_basic_set_dims_get_sign(bset, isl_dim_set, 0, dim,
+ data->signs + nparam) < 0)
+ goto error;
+ if (isl_basic_set_dims_get_sign(bset, isl_dim_param, 0, nparam,
+ data->signs) < 0)
+ goto error;
+
+ r = propagate_on_domain(bset, isl_qpolynomial_copy(data->poly), data);
+
+ free(data->signs);
+
+ return r;
+error:
+ free(data->signs);
+ isl_basic_set_free(bset);
+ return -1;
+}
+
+static int qpolynomial_bound_on_domain_range(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct range_data *data)
+{
+ unsigned nparam = isl_basic_set_dim(bset, isl_dim_param);
+ unsigned nvar = isl_basic_set_dim(bset, isl_dim_set);
+ isl_set *set = NULL;
+
+ if (!bset)
+ goto error;
+
+ if (nvar == 0)
+ return add_guarded_poly(bset, poly, data);
+
+ set = isl_set_from_basic_set(bset);
+ set = isl_set_split_dims(set, isl_dim_param, 0, nparam);
+ set = isl_set_split_dims(set, isl_dim_set, 0, nvar);
+
+ data->poly = poly;
+
+ data->test_monotonicity = 1;
+ if (isl_set_foreach_basic_set(set, &basic_guarded_poly_bound, data) < 0)
+ goto error;
+
+ isl_set_free(set);
+ isl_qpolynomial_free(poly);
+
+ return 0;
+error:
+ isl_set_free(set);
+ isl_qpolynomial_free(poly);
+ return -1;
+}
+
+int isl_qpolynomial_bound_on_domain_range(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct isl_bound *bound)
+{
+ struct range_data data;
+ int r;
+
+ data.pwf = bound->pwf;
+ data.pwf_tight = bound->pwf_tight;
+ data.tight = bound->check_tight;
+ if (bound->type == isl_fold_min)
+ data.sign = -1;
+ else
+ data.sign = 1;
+
+ r = qpolynomial_bound_on_domain_range(bset, poly, &data);
+
+ bound->pwf = data.pwf;
+ bound->pwf_tight = data.pwf_tight;
+
+ return r;
+}
diff --git a/polly/lib/External/isl/isl_range.h b/polly/lib/External/isl/isl_range.h
new file mode 100644
index 00000000000..c0970790d9e
--- /dev/null
+++ b/polly/lib/External/isl/isl_range.h
@@ -0,0 +1,6 @@
+#include <isl_bound.h>
+
+int isl_qpolynomial_bound_on_domain_range(__isl_take isl_basic_set *bset,
+ __isl_take isl_qpolynomial *poly, struct isl_bound *bound);
+__isl_give isl_qpolynomial *isl_qpolynomial_terms_of_sign(
+ __isl_keep isl_qpolynomial *poly, int *signs, int sign);
diff --git a/polly/lib/External/isl/isl_reordering.c b/polly/lib/External/isl/isl_reordering.c
new file mode 100644
index 00000000000..ca9c9737f76
--- /dev/null
+++ b/polly/lib/External/isl/isl_reordering.c
@@ -0,0 +1,205 @@
+/*
+ * 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_ctx_private.h>
+#include <isl_space_private.h>
+#include <isl_reordering.h>
+
+__isl_give isl_reordering *isl_reordering_alloc(isl_ctx *ctx, int len)
+{
+ isl_reordering *exp;
+
+ exp = isl_alloc(ctx, struct isl_reordering,
+ sizeof(struct isl_reordering) + (len - 1) * sizeof(int));
+ if (!exp)
+ return NULL;
+
+ exp->ref = 1;
+ exp->len = len;
+ exp->dim = NULL;
+
+ return exp;
+}
+
+__isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp)
+{
+ if (!exp)
+ return NULL;
+
+ exp->ref++;
+ return exp;
+}
+
+__isl_give isl_reordering *isl_reordering_dup(__isl_keep isl_reordering *r)
+{
+ int i;
+ isl_reordering *dup;
+
+ if (!r)
+ return NULL;
+
+ dup = isl_reordering_alloc(r->dim->ctx, r->len);
+ if (!dup)
+ return NULL;
+
+ dup->dim = isl_space_copy(r->dim);
+ if (!dup->dim)
+ return isl_reordering_free(dup);
+ for (i = 0; i < dup->len; ++i)
+ dup->pos[i] = r->pos[i];
+
+ return dup;
+}
+
+__isl_give isl_reordering *isl_reordering_cow(__isl_take isl_reordering *r)
+{
+ if (!r)
+ return NULL;
+
+ if (r->ref == 1)
+ return r;
+ r->ref--;
+ return isl_reordering_dup(r);
+}
+
+void *isl_reordering_free(__isl_take isl_reordering *exp)
+{
+ if (!exp)
+ return NULL;
+
+ if (--exp->ref > 0)
+ return NULL;
+
+ isl_space_free(exp->dim);
+ free(exp);
+ return NULL;
+}
+
+/* Construct a reordering that maps the parameters of "alignee"
+ * to the corresponding parameters in a new dimension specification
+ * that has the parameters of "aligner" first, followed by
+ * any remaining parameters of "alignee" that do not occur in "aligner".
+ */
+__isl_give isl_reordering *isl_parameter_alignment_reordering(
+ __isl_keep isl_space *alignee, __isl_keep isl_space *aligner)
+{
+ int i, j;
+ isl_reordering *exp;
+
+ if (!alignee || !aligner)
+ return NULL;
+
+ exp = isl_reordering_alloc(alignee->ctx, alignee->nparam);
+ if (!exp)
+ return NULL;
+
+ exp->dim = isl_space_copy(aligner);
+
+ for (i = 0; i < alignee->nparam; ++i) {
+ isl_id *id_i;
+ id_i = isl_space_get_dim_id(alignee, isl_dim_param, i);
+ if (!id_i)
+ isl_die(alignee->ctx, isl_error_invalid,
+ "cannot align unnamed parameters", goto error);
+ for (j = 0; j < aligner->nparam; ++j) {
+ isl_id *id_j;
+ id_j = isl_space_get_dim_id(aligner, isl_dim_param, j);
+ isl_id_free(id_j);
+ if (id_i == id_j)
+ break;
+ }
+ if (j < aligner->nparam) {
+ exp->pos[i] = j;
+ isl_id_free(id_i);
+ } else {
+ int pos;
+ pos = isl_space_dim(exp->dim, isl_dim_param);
+ exp->dim = isl_space_add_dims(exp->dim, isl_dim_param, 1);
+ exp->dim = isl_space_set_dim_id(exp->dim,
+ isl_dim_param, pos, id_i);
+ exp->pos[i] = pos;
+ }
+ }
+
+ if (!exp->dim)
+ return isl_reordering_free(exp);
+ return exp;
+error:
+ isl_reordering_free(exp);
+ return NULL;
+}
+
+__isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
+ unsigned extra)
+{
+ int i;
+ isl_reordering *res;
+ int offset;
+
+ if (!exp)
+ return NULL;
+ if (extra == 0)
+ return exp;
+
+ offset = isl_space_dim(exp->dim, isl_dim_all) - exp->len;
+ res = isl_reordering_alloc(exp->dim->ctx, exp->len + extra);
+ if (!res)
+ goto error;
+ res->dim = isl_space_copy(exp->dim);
+ for (i = 0; i < exp->len; ++i)
+ res->pos[i] = exp->pos[i];
+ for (i = exp->len; i < res->len; ++i)
+ res->pos[i] = offset + i;
+
+ isl_reordering_free(exp);
+
+ return res;
+error:
+ isl_reordering_free(exp);
+ return NULL;
+}
+
+__isl_give isl_reordering *isl_reordering_extend_space(
+ __isl_take isl_reordering *exp, __isl_take isl_space *dim)
+{
+ isl_reordering *res;
+
+ if (!exp || !dim)
+ goto error;
+
+ res = isl_reordering_extend(isl_reordering_copy(exp),
+ isl_space_dim(dim, isl_dim_all) - exp->len);
+ res = isl_reordering_cow(res);
+ if (!res)
+ goto error;
+ isl_space_free(res->dim);
+ res->dim = isl_space_replace(dim, isl_dim_param, exp->dim);
+
+ isl_reordering_free(exp);
+
+ if (!res->dim)
+ return isl_reordering_free(res);
+
+ return res;
+error:
+ isl_reordering_free(exp);
+ isl_space_free(dim);
+ return NULL;
+}
+
+void isl_reordering_dump(__isl_keep isl_reordering *exp)
+{
+ int i;
+
+ isl_space_dump(exp->dim);
+ for (i = 0; i < exp->len; ++i)
+ fprintf(stderr, "%d -> %d; ", i, exp->pos[i]);
+ fprintf(stderr, "\n");
+}
diff --git a/polly/lib/External/isl/isl_reordering.h b/polly/lib/External/isl/isl_reordering.h
new file mode 100644
index 00000000000..ac5b6facaba
--- /dev/null
+++ b/polly/lib/External/isl/isl_reordering.h
@@ -0,0 +1,31 @@
+#ifndef ISL_REORDERING_H
+#define ISL_REORDERING_H
+
+#include <isl/space.h>
+
+/* pos maps original dimensions to new dimensions.
+ * The final dimension is given by dim.
+ * The number of dimensions (i.e., the range of values) in the result
+ * may be larger than the number of dimensions in the input.
+ * In particular, the possible values of the entries in pos ranges from 0 to
+ * the total dimension of dim - 1, unless isl_reordering_extend
+ * has been called.
+ */
+struct isl_reordering {
+ int ref;
+ isl_space *dim;
+ unsigned len;
+ int pos[1];
+};
+typedef struct isl_reordering isl_reordering;
+
+__isl_give isl_reordering *isl_parameter_alignment_reordering(
+ __isl_keep isl_space *alignee, __isl_keep isl_space *aligner);
+__isl_give isl_reordering *isl_reordering_copy(__isl_keep isl_reordering *exp);
+void *isl_reordering_free(__isl_take isl_reordering *exp);
+__isl_give isl_reordering *isl_reordering_extend_space(
+ __isl_take isl_reordering *exp, __isl_take isl_space *dim);
+__isl_give isl_reordering *isl_reordering_extend(__isl_take isl_reordering *exp,
+ unsigned extra);
+
+#endif
diff --git a/polly/lib/External/isl/isl_sample.c b/polly/lib/External/isl/isl_sample.c
new file mode 100644
index 00000000000..eaa07543140
--- /dev/null
+++ b/polly/lib/External/isl/isl_sample.c
@@ -0,0 +1,1301 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include "isl_sample.h"
+#include <isl/vec.h>
+#include <isl/mat.h>
+#include <isl_seq.h>
+#include "isl_equalities.h"
+#include "isl_tab.h"
+#include "isl_basis_reduction.h"
+#include <isl_factorization.h>
+#include <isl_point_private.h>
+#include <isl_options_private.h>
+#include <isl_vec_private.h>
+
+static struct isl_vec *empty_sample(struct isl_basic_set *bset)
+{
+ struct isl_vec *vec;
+
+ vec = isl_vec_alloc(bset->ctx, 0);
+ isl_basic_set_free(bset);
+ return vec;
+}
+
+/* Construct a zero sample of the same dimension as bset.
+ * As a special case, if bset is zero-dimensional, this
+ * function creates a zero-dimensional sample point.
+ */
+static struct isl_vec *zero_sample(struct isl_basic_set *bset)
+{
+ unsigned dim;
+ struct isl_vec *sample;
+
+ dim = isl_basic_set_total_dim(bset);
+ sample = isl_vec_alloc(bset->ctx, 1 + dim);
+ if (sample) {
+ isl_int_set_si(sample->el[0], 1);
+ isl_seq_clr(sample->el + 1, dim);
+ }
+ isl_basic_set_free(bset);
+ return sample;
+}
+
+static struct isl_vec *interval_sample(struct isl_basic_set *bset)
+{
+ int i;
+ isl_int t;
+ struct isl_vec *sample;
+
+ bset = isl_basic_set_simplify(bset);
+ if (!bset)
+ return NULL;
+ if (isl_basic_set_plain_is_empty(bset))
+ return empty_sample(bset);
+ if (bset->n_eq == 0 && bset->n_ineq == 0)
+ return zero_sample(bset);
+
+ sample = isl_vec_alloc(bset->ctx, 2);
+ if (!sample)
+ goto error;
+ if (!bset)
+ return NULL;
+ isl_int_set_si(sample->block.data[0], 1);
+
+ if (bset->n_eq > 0) {
+ isl_assert(bset->ctx, bset->n_eq == 1, goto error);
+ isl_assert(bset->ctx, bset->n_ineq == 0, goto error);
+ if (isl_int_is_one(bset->eq[0][1]))
+ isl_int_neg(sample->el[1], bset->eq[0][0]);
+ else {
+ isl_assert(bset->ctx, isl_int_is_negone(bset->eq[0][1]),
+ goto error);
+ isl_int_set(sample->el[1], bset->eq[0][0]);
+ }
+ isl_basic_set_free(bset);
+ return sample;
+ }
+
+ isl_int_init(t);
+ if (isl_int_is_one(bset->ineq[0][1]))
+ isl_int_neg(sample->block.data[1], bset->ineq[0][0]);
+ else
+ isl_int_set(sample->block.data[1], bset->ineq[0][0]);
+ for (i = 1; i < bset->n_ineq; ++i) {
+ isl_seq_inner_product(sample->block.data,
+ bset->ineq[i], 2, &t);
+ if (isl_int_is_neg(t))
+ break;
+ }
+ isl_int_clear(t);
+ if (i < bset->n_ineq) {
+ isl_vec_free(sample);
+ return empty_sample(bset);
+ }
+
+ isl_basic_set_free(bset);
+ return sample;
+error:
+ isl_basic_set_free(bset);
+ isl_vec_free(sample);
+ return NULL;
+}
+
+/* Find a sample integer point, if any, in bset, which is known
+ * to have equalities. If bset contains no integer points, then
+ * return a zero-length vector.
+ * We simply remove the known equalities, compute a sample
+ * in the resulting bset, using the specified recurse function,
+ * and then transform the sample back to the original space.
+ */
+static struct isl_vec *sample_eq(struct isl_basic_set *bset,
+ struct isl_vec *(*recurse)(struct isl_basic_set *))
+{
+ struct isl_mat *T;
+ struct isl_vec *sample;
+
+ if (!bset)
+ return NULL;
+
+ bset = isl_basic_set_remove_equalities(bset, &T, NULL);
+ sample = recurse(bset);
+ if (!sample || sample->size == 0)
+ isl_mat_free(T);
+ else
+ sample = isl_mat_vec_product(T, sample);
+ return sample;
+}
+
+/* Return a matrix containing the equalities of the tableau
+ * in constraint form. The tableau is assumed to have
+ * an associated bset that has been kept up-to-date.
+ */
+static struct isl_mat *tab_equalities(struct isl_tab *tab)
+{
+ int i, j;
+ int n_eq;
+ struct isl_mat *eq;
+ struct isl_basic_set *bset;
+
+ if (!tab)
+ return NULL;
+
+ bset = isl_tab_peek_bset(tab);
+ isl_assert(tab->mat->ctx, bset, return NULL);
+
+ n_eq = tab->n_var - tab->n_col + tab->n_dead;
+ if (tab->empty || n_eq == 0)
+ return isl_mat_alloc(tab->mat->ctx, 0, tab->n_var);
+ if (n_eq == tab->n_var)
+ return isl_mat_identity(tab->mat->ctx, tab->n_var);
+
+ eq = isl_mat_alloc(tab->mat->ctx, n_eq, tab->n_var);
+ if (!eq)
+ return NULL;
+ for (i = 0, j = 0; i < tab->n_con; ++i) {
+ if (tab->con[i].is_row)
+ continue;
+ if (tab->con[i].index >= 0 && tab->con[i].index >= tab->n_dead)
+ continue;
+ if (i < bset->n_eq)
+ isl_seq_cpy(eq->row[j], bset->eq[i] + 1, tab->n_var);
+ else
+ isl_seq_cpy(eq->row[j],
+ bset->ineq[i - bset->n_eq] + 1, tab->n_var);
+ ++j;
+ }
+ isl_assert(bset->ctx, j == n_eq, goto error);
+ return eq;
+error:
+ isl_mat_free(eq);
+ return NULL;
+}
+
+/* Compute and return an initial basis for the bounded tableau "tab".
+ *
+ * If the tableau is either full-dimensional or zero-dimensional,
+ * the we simply return an identity matrix.
+ * Otherwise, we construct a basis whose first directions correspond
+ * to equalities.
+ */
+static struct isl_mat *initial_basis(struct isl_tab *tab)
+{
+ int n_eq;
+ struct isl_mat *eq;
+ struct isl_mat *Q;
+
+ tab->n_unbounded = 0;
+ tab->n_zero = n_eq = tab->n_var - tab->n_col + tab->n_dead;
+ if (tab->empty || n_eq == 0 || n_eq == tab->n_var)
+ return isl_mat_identity(tab->mat->ctx, 1 + tab->n_var);
+
+ eq = tab_equalities(tab);
+ eq = isl_mat_left_hermite(eq, 0, NULL, &Q);
+ if (!eq)
+ return NULL;
+ isl_mat_free(eq);
+
+ Q = isl_mat_lin_to_aff(Q);
+ return Q;
+}
+
+/* Compute the minimum of the current ("level") basis row over "tab"
+ * and store the result in position "level" of "min".
+ */
+static enum isl_lp_result compute_min(isl_ctx *ctx, struct isl_tab *tab,
+ __isl_keep isl_vec *min, int level)
+{
+ return isl_tab_min(tab, tab->basis->row[1 + level],
+ ctx->one, &min->el[level], NULL, 0);
+}
+
+/* Compute the maximum of the current ("level") basis row over "tab"
+ * and store the result in position "level" of "max".
+ */
+static enum isl_lp_result compute_max(isl_ctx *ctx, struct isl_tab *tab,
+ __isl_keep isl_vec *max, int level)
+{
+ enum isl_lp_result res;
+ unsigned dim = tab->n_var;
+
+ isl_seq_neg(tab->basis->row[1 + level] + 1,
+ tab->basis->row[1 + level] + 1, dim);
+ res = isl_tab_min(tab, tab->basis->row[1 + level],
+ ctx->one, &max->el[level], NULL, 0);
+ isl_seq_neg(tab->basis->row[1 + level] + 1,
+ tab->basis->row[1 + level] + 1, dim);
+ isl_int_neg(max->el[level], max->el[level]);
+
+ return res;
+}
+
+/* Perform a greedy search for an integer point in the set represented
+ * by "tab", given that the minimal rational value (rounded up to the
+ * nearest integer) at "level" is smaller than the maximal rational
+ * value (rounded down to the nearest integer).
+ *
+ * Return 1 if we have found an integer point (if tab->n_unbounded > 0
+ * then we may have only found integer values for the bounded dimensions
+ * and it is the responsibility of the caller to extend this solution
+ * to the unbounded dimensions).
+ * Return 0 if greedy search did not result in a solution.
+ * Return -1 if some error occurred.
+ *
+ * We assign a value half-way between the minimum and the maximum
+ * to the current dimension and check if the minimal value of the
+ * next dimension is still smaller than (or equal) to the maximal value.
+ * We continue this process until either
+ * - the minimal value (rounded up) is greater than the maximal value
+ * (rounded down). In this case, greedy search has failed.
+ * - we have exhausted all bounded dimensions, meaning that we have
+ * found a solution.
+ * - the sample value of the tableau is integral.
+ * - some error has occurred.
+ */
+static int greedy_search(isl_ctx *ctx, struct isl_tab *tab,
+ __isl_keep isl_vec *min, __isl_keep isl_vec *max, int level)
+{
+ struct isl_tab_undo *snap;
+ enum isl_lp_result res;
+
+ snap = isl_tab_snap(tab);
+
+ do {
+ isl_int_add(tab->basis->row[1 + level][0],
+ min->el[level], max->el[level]);
+ isl_int_fdiv_q_ui(tab->basis->row[1 + level][0],
+ tab->basis->row[1 + level][0], 2);
+ isl_int_neg(tab->basis->row[1 + level][0],
+ tab->basis->row[1 + level][0]);
+ if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0)
+ return -1;
+ isl_int_set_si(tab->basis->row[1 + level][0], 0);
+
+ if (++level >= tab->n_var - tab->n_unbounded)
+ return 1;
+ if (isl_tab_sample_is_integer(tab))
+ return 1;
+
+ res = compute_min(ctx, tab, min, level);
+ if (res == isl_lp_error)
+ return -1;
+ if (res != isl_lp_ok)
+ isl_die(ctx, isl_error_internal,
+ "expecting bounded rational solution",
+ return -1);
+ res = compute_max(ctx, tab, max, level);
+ if (res == isl_lp_error)
+ return -1;
+ if (res != isl_lp_ok)
+ isl_die(ctx, isl_error_internal,
+ "expecting bounded rational solution",
+ return -1);
+ } while (isl_int_le(min->el[level], max->el[level]));
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Given a tableau representing a set, find and return
+ * an integer point in the set, if there is any.
+ *
+ * We perform a depth first search
+ * for an integer point, by scanning all possible values in the range
+ * attained by a basis vector, where an initial basis may have been set
+ * by the calling function. Otherwise an initial basis that exploits
+ * the equalities in the tableau is created.
+ * tab->n_zero is currently ignored and is clobbered by this function.
+ *
+ * The tableau is allowed to have unbounded direction, but then
+ * the calling function needs to set an initial basis, with the
+ * unbounded directions last and with tab->n_unbounded set
+ * to the number of unbounded directions.
+ * Furthermore, the calling functions needs to add shifted copies
+ * of all constraints involving unbounded directions to ensure
+ * that any feasible rational value in these directions can be rounded
+ * up to yield a feasible integer value.
+ * In particular, let B define the given basis x' = B x
+ * and let T be the inverse of B, i.e., X = T x'.
+ * Let a x + c >= 0 be a constraint of the set represented by the tableau,
+ * or a T x' + c >= 0 in terms of the given basis. Assume that
+ * the bounded directions have an integer value, then we can safely
+ * round up the values for the unbounded directions if we make sure
+ * that x' not only satisfies the original constraint, but also
+ * the constraint "a T x' + c + s >= 0" with s the sum of all
+ * negative values in the last n_unbounded entries of "a T".
+ * The calling function therefore needs to add the constraint
+ * a x + c + s >= 0. The current function then scans the first
+ * directions for an integer value and once those have been found,
+ * it can compute "T ceil(B x)" to yield an integer point in the set.
+ * Note that during the search, the first rows of B may be changed
+ * by a basis reduction, but the last n_unbounded rows of B remain
+ * unaltered and are also not mixed into the first rows.
+ *
+ * The search is implemented iteratively. "level" identifies the current
+ * basis vector. "init" is true if we want the first value at the current
+ * level and false if we want the next value.
+ *
+ * At the start of each level, we first check if we can find a solution
+ * using greedy search. If not, we continue with the exhaustive search.
+ *
+ * The initial basis is the identity matrix. If the range in some direction
+ * contains more than one integer value, we perform basis reduction based
+ * on the value of ctx->opt->gbr
+ * - ISL_GBR_NEVER: never perform basis reduction
+ * - ISL_GBR_ONCE: only perform basis reduction the first
+ * time such a range is encountered
+ * - ISL_GBR_ALWAYS: always perform basis reduction when
+ * such a range is encountered
+ *
+ * When ctx->opt->gbr is set to ISL_GBR_ALWAYS, then we allow the basis
+ * reduction computation to return early. That is, as soon as it
+ * finds a reasonable first direction.
+ */
+struct isl_vec *isl_tab_sample(struct isl_tab *tab)
+{
+ unsigned dim;
+ unsigned gbr;
+ struct isl_ctx *ctx;
+ struct isl_vec *sample;
+ struct isl_vec *min;
+ struct isl_vec *max;
+ enum isl_lp_result res;
+ int level;
+ int init;
+ int reduced;
+ struct isl_tab_undo **snap;
+
+ if (!tab)
+ return NULL;
+ if (tab->empty)
+ return isl_vec_alloc(tab->mat->ctx, 0);
+
+ if (!tab->basis)
+ tab->basis = initial_basis(tab);
+ if (!tab->basis)
+ return NULL;
+ isl_assert(tab->mat->ctx, tab->basis->n_row == tab->n_var + 1,
+ return NULL);
+ isl_assert(tab->mat->ctx, tab->basis->n_col == tab->n_var + 1,
+ return NULL);
+
+ ctx = tab->mat->ctx;
+ dim = tab->n_var;
+ gbr = ctx->opt->gbr;
+
+ if (tab->n_unbounded == tab->n_var) {
+ sample = isl_tab_get_sample_value(tab);
+ sample = isl_mat_vec_product(isl_mat_copy(tab->basis), sample);
+ sample = isl_vec_ceil(sample);
+ sample = isl_mat_vec_inverse_product(isl_mat_copy(tab->basis),
+ sample);
+ return sample;
+ }
+
+ if (isl_tab_extend_cons(tab, dim + 1) < 0)
+ return NULL;
+
+ min = isl_vec_alloc(ctx, dim);
+ max = isl_vec_alloc(ctx, dim);
+ snap = isl_alloc_array(ctx, struct isl_tab_undo *, dim);
+
+ if (!min || !max || !snap)
+ goto error;
+
+ level = 0;
+ init = 1;
+ reduced = 0;
+
+ while (level >= 0) {
+ if (init) {
+ int choice;
+
+ res = compute_min(ctx, tab, min, level);
+ if (res == isl_lp_error)
+ goto error;
+ if (res != isl_lp_ok)
+ isl_die(ctx, isl_error_internal,
+ "expecting bounded rational solution",
+ goto error);
+ if (isl_tab_sample_is_integer(tab))
+ break;
+ res = compute_max(ctx, tab, max, level);
+ if (res == isl_lp_error)
+ goto error;
+ if (res != isl_lp_ok)
+ isl_die(ctx, isl_error_internal,
+ "expecting bounded rational solution",
+ goto error);
+ if (isl_tab_sample_is_integer(tab))
+ break;
+ choice = isl_int_lt(min->el[level], max->el[level]);
+ if (choice) {
+ int g;
+ g = greedy_search(ctx, tab, min, max, level);
+ if (g < 0)
+ goto error;
+ if (g)
+ break;
+ }
+ if (!reduced && choice &&
+ ctx->opt->gbr != ISL_GBR_NEVER) {
+ unsigned gbr_only_first;
+ if (ctx->opt->gbr == ISL_GBR_ONCE)
+ ctx->opt->gbr = ISL_GBR_NEVER;
+ tab->n_zero = level;
+ gbr_only_first = ctx->opt->gbr_only_first;
+ ctx->opt->gbr_only_first =
+ ctx->opt->gbr == ISL_GBR_ALWAYS;
+ tab = isl_tab_compute_reduced_basis(tab);
+ ctx->opt->gbr_only_first = gbr_only_first;
+ if (!tab || !tab->basis)
+ goto error;
+ reduced = 1;
+ continue;
+ }
+ reduced = 0;
+ snap[level] = isl_tab_snap(tab);
+ } else
+ isl_int_add_ui(min->el[level], min->el[level], 1);
+
+ if (isl_int_gt(min->el[level], max->el[level])) {
+ level--;
+ init = 0;
+ if (level >= 0)
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ continue;
+ }
+ isl_int_neg(tab->basis->row[1 + level][0], min->el[level]);
+ if (isl_tab_add_valid_eq(tab, tab->basis->row[1 + level]) < 0)
+ goto error;
+ isl_int_set_si(tab->basis->row[1 + level][0], 0);
+ if (level + tab->n_unbounded < dim - 1) {
+ ++level;
+ init = 1;
+ continue;
+ }
+ break;
+ }
+
+ if (level >= 0) {
+ sample = isl_tab_get_sample_value(tab);
+ if (!sample)
+ goto error;
+ if (tab->n_unbounded && !isl_int_is_one(sample->el[0])) {
+ sample = isl_mat_vec_product(isl_mat_copy(tab->basis),
+ sample);
+ sample = isl_vec_ceil(sample);
+ sample = isl_mat_vec_inverse_product(
+ isl_mat_copy(tab->basis), sample);
+ }
+ } else
+ sample = isl_vec_alloc(ctx, 0);
+
+ ctx->opt->gbr = gbr;
+ isl_vec_free(min);
+ isl_vec_free(max);
+ free(snap);
+ return sample;
+error:
+ ctx->opt->gbr = gbr;
+ isl_vec_free(min);
+ isl_vec_free(max);
+ free(snap);
+ return NULL;
+}
+
+static struct isl_vec *sample_bounded(struct isl_basic_set *bset);
+
+/* Compute a sample point of the given basic set, based on the given,
+ * non-trivial factorization.
+ */
+static __isl_give isl_vec *factored_sample(__isl_take isl_basic_set *bset,
+ __isl_take isl_factorizer *f)
+{
+ int i, n;
+ isl_vec *sample = NULL;
+ isl_ctx *ctx;
+ unsigned nparam;
+ unsigned nvar;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ if (!ctx)
+ goto error;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ sample = isl_vec_alloc(ctx, 1 + isl_basic_set_total_dim(bset));
+ if (!sample)
+ goto error;
+ isl_int_set_si(sample->el[0], 1);
+
+ bset = isl_morph_basic_set(isl_morph_copy(f->morph), bset);
+
+ for (i = 0, n = 0; i < f->n_group; ++i) {
+ isl_basic_set *bset_i;
+ isl_vec *sample_i;
+
+ bset_i = isl_basic_set_copy(bset);
+ bset_i = isl_basic_set_drop_constraints_involving(bset_i,
+ nparam + n + f->len[i], nvar - n - f->len[i]);
+ bset_i = isl_basic_set_drop_constraints_involving(bset_i,
+ nparam, n);
+ bset_i = isl_basic_set_drop(bset_i, isl_dim_set,
+ n + f->len[i], nvar - n - f->len[i]);
+ bset_i = isl_basic_set_drop(bset_i, isl_dim_set, 0, n);
+
+ sample_i = sample_bounded(bset_i);
+ if (!sample_i)
+ goto error;
+ if (sample_i->size == 0) {
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+ isl_vec_free(sample);
+ return sample_i;
+ }
+ isl_seq_cpy(sample->el + 1 + nparam + n,
+ sample_i->el + 1, f->len[i]);
+ isl_vec_free(sample_i);
+
+ n += f->len[i];
+ }
+
+ f->morph = isl_morph_inverse(f->morph);
+ sample = isl_morph_vec(isl_morph_copy(f->morph), sample);
+
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+ return sample;
+error:
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+ isl_vec_free(sample);
+ return NULL;
+}
+
+/* Given a basic set that is known to be bounded, find and return
+ * an integer point in the basic set, if there is any.
+ *
+ * After handling some trivial cases, we construct a tableau
+ * and then use isl_tab_sample to find a sample, passing it
+ * the identity matrix as initial basis.
+ */
+static struct isl_vec *sample_bounded(struct isl_basic_set *bset)
+{
+ unsigned dim;
+ struct isl_ctx *ctx;
+ struct isl_vec *sample;
+ struct isl_tab *tab = NULL;
+ isl_factorizer *f;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return empty_sample(bset);
+
+ dim = isl_basic_set_total_dim(bset);
+ if (dim == 0)
+ return zero_sample(bset);
+ if (dim == 1)
+ return interval_sample(bset);
+ if (bset->n_eq > 0)
+ return sample_eq(bset, sample_bounded);
+
+ f = isl_basic_set_factorizer(bset);
+ if (!f)
+ goto error;
+ if (f->n_group != 0)
+ return factored_sample(bset, f);
+ isl_factorizer_free(f);
+
+ ctx = bset->ctx;
+
+ tab = isl_tab_from_basic_set(bset, 1);
+ if (tab && tab->empty) {
+ isl_tab_free(tab);
+ ISL_F_SET(bset, ISL_BASIC_SET_EMPTY);
+ sample = isl_vec_alloc(bset->ctx, 0);
+ isl_basic_set_free(bset);
+ return sample;
+ }
+
+ if (!ISL_F_ISSET(bset, ISL_BASIC_SET_NO_IMPLICIT))
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
+ goto error;
+
+ sample = isl_tab_sample(tab);
+ if (!sample)
+ goto error;
+
+ if (sample->size > 0) {
+ isl_vec_free(bset->sample);
+ bset->sample = isl_vec_copy(sample);
+ }
+
+ isl_basic_set_free(bset);
+ isl_tab_free(tab);
+ return sample;
+error:
+ isl_basic_set_free(bset);
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Given a basic set "bset" and a value "sample" for the first coordinates
+ * of bset, plug in these values and drop the corresponding coordinates.
+ *
+ * We do this by computing the preimage of the transformation
+ *
+ * [ 1 0 ]
+ * x = [ s 0 ] x'
+ * [ 0 I ]
+ *
+ * where [1 s] is the sample value and I is the identity matrix of the
+ * appropriate dimension.
+ */
+static struct isl_basic_set *plug_in(struct isl_basic_set *bset,
+ struct isl_vec *sample)
+{
+ int i;
+ unsigned total;
+ struct isl_mat *T;
+
+ if (!bset || !sample)
+ goto error;
+
+ total = isl_basic_set_total_dim(bset);
+ T = isl_mat_alloc(bset->ctx, 1 + total, 1 + total - (sample->size - 1));
+ if (!T)
+ goto error;
+
+ for (i = 0; i < sample->size; ++i) {
+ isl_int_set(T->row[i][0], sample->el[i]);
+ isl_seq_clr(T->row[i] + 1, T->n_col - 1);
+ }
+ for (i = 0; i < T->n_col - 1; ++i) {
+ isl_seq_clr(T->row[sample->size + i], T->n_col);
+ isl_int_set_si(T->row[sample->size + i][1 + i], 1);
+ }
+ isl_vec_free(sample);
+
+ bset = isl_basic_set_preimage(bset, T);
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_vec_free(sample);
+ return NULL;
+}
+
+/* Given a basic set "bset", return any (possibly non-integer) point
+ * in the basic set.
+ */
+static struct isl_vec *rational_sample(struct isl_basic_set *bset)
+{
+ struct isl_tab *tab;
+ struct isl_vec *sample;
+
+ if (!bset)
+ return NULL;
+
+ tab = isl_tab_from_basic_set(bset, 0);
+ sample = isl_tab_get_sample_value(tab);
+ isl_tab_free(tab);
+
+ isl_basic_set_free(bset);
+
+ return sample;
+}
+
+/* Given a linear cone "cone" and a rational point "vec",
+ * construct a polyhedron with shifted copies of the constraints in "cone",
+ * i.e., a polyhedron with "cone" as its recession cone, such that each
+ * point x in this polyhedron is such that the unit box positioned at x
+ * lies entirely inside the affine cone 'vec + cone'.
+ * Any rational point in this polyhedron may therefore be rounded up
+ * to yield an integer point that lies inside said affine cone.
+ *
+ * Denote the constraints of cone by "<a_i, x> >= 0" and the rational
+ * point "vec" by v/d.
+ * Let b_i = <a_i, v>. Then the affine cone 'vec + cone' is given
+ * by <a_i, x> - b/d >= 0.
+ * The polyhedron <a_i, x> - ceil{b/d} >= 0 is a subset of this affine cone.
+ * We prefer this polyhedron over the actual affine cone because it doesn't
+ * require a scaling of the constraints.
+ * If each of the vertices of the unit cube positioned at x lies inside
+ * this polyhedron, then the whole unit cube at x lies inside the affine cone.
+ * We therefore impose that x' = x + \sum e_i, for any selection of unit
+ * vectors lies inside the polyhedron, i.e.,
+ *
+ * <a_i, x'> - ceil{b/d} = <a_i, x> + sum a_i - ceil{b/d} >= 0
+ *
+ * The most stringent of these constraints is the one that selects
+ * all negative a_i, so the polyhedron we are looking for has constraints
+ *
+ * <a_i, x> + sum_{a_i < 0} a_i - ceil{b/d} >= 0
+ *
+ * Note that if cone were known to have only non-negative rays
+ * (which can be accomplished by a unimodular transformation),
+ * then we would only have to check the points x' = x + e_i
+ * and we only have to add the smallest negative a_i (if any)
+ * instead of the sum of all negative a_i.
+ */
+static struct isl_basic_set *shift_cone(struct isl_basic_set *cone,
+ struct isl_vec *vec)
+{
+ int i, j, k;
+ unsigned total;
+
+ struct isl_basic_set *shift = NULL;
+
+ if (!cone || !vec)
+ goto error;
+
+ isl_assert(cone->ctx, cone->n_eq == 0, goto error);
+
+ total = isl_basic_set_total_dim(cone);
+
+ shift = isl_basic_set_alloc_space(isl_basic_set_get_space(cone),
+ 0, 0, cone->n_ineq);
+
+ for (i = 0; i < cone->n_ineq; ++i) {
+ k = isl_basic_set_alloc_inequality(shift);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(shift->ineq[k] + 1, cone->ineq[i] + 1, total);
+ isl_seq_inner_product(shift->ineq[k] + 1, vec->el + 1, total,
+ &shift->ineq[k][0]);
+ isl_int_cdiv_q(shift->ineq[k][0],
+ shift->ineq[k][0], vec->el[0]);
+ isl_int_neg(shift->ineq[k][0], shift->ineq[k][0]);
+ for (j = 0; j < total; ++j) {
+ if (isl_int_is_nonneg(shift->ineq[k][1 + j]))
+ continue;
+ isl_int_add(shift->ineq[k][0],
+ shift->ineq[k][0], shift->ineq[k][1 + j]);
+ }
+ }
+
+ isl_basic_set_free(cone);
+ isl_vec_free(vec);
+
+ return isl_basic_set_finalize(shift);
+error:
+ isl_basic_set_free(shift);
+ isl_basic_set_free(cone);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+/* Given a rational point vec in a (transformed) basic set,
+ * such that cone is the recession cone of the original basic set,
+ * "round up" the rational point to an integer point.
+ *
+ * We first check if the rational point just happens to be integer.
+ * If not, we transform the cone in the same way as the basic set,
+ * pick a point x in this cone shifted to the rational point such that
+ * the whole unit cube at x is also inside this affine cone.
+ * Then we simply round up the coordinates of x and return the
+ * resulting integer point.
+ */
+static struct isl_vec *round_up_in_cone(struct isl_vec *vec,
+ struct isl_basic_set *cone, struct isl_mat *U)
+{
+ unsigned total;
+
+ if (!vec || !cone || !U)
+ goto error;
+
+ isl_assert(vec->ctx, vec->size != 0, goto error);
+ if (isl_int_is_one(vec->el[0])) {
+ isl_mat_free(U);
+ isl_basic_set_free(cone);
+ return vec;
+ }
+
+ total = isl_basic_set_total_dim(cone);
+ cone = isl_basic_set_preimage(cone, U);
+ cone = isl_basic_set_remove_dims(cone, isl_dim_set,
+ 0, total - (vec->size - 1));
+
+ cone = shift_cone(cone, vec);
+
+ vec = rational_sample(cone);
+ vec = isl_vec_ceil(vec);
+ return vec;
+error:
+ isl_mat_free(U);
+ isl_vec_free(vec);
+ isl_basic_set_free(cone);
+ return NULL;
+}
+
+/* Concatenate two integer vectors, i.e., two vectors with denominator
+ * (stored in element 0) equal to 1.
+ */
+static struct isl_vec *vec_concat(struct isl_vec *vec1, struct isl_vec *vec2)
+{
+ struct isl_vec *vec;
+
+ if (!vec1 || !vec2)
+ goto error;
+ isl_assert(vec1->ctx, vec1->size > 0, goto error);
+ isl_assert(vec2->ctx, vec2->size > 0, goto error);
+ isl_assert(vec1->ctx, isl_int_is_one(vec1->el[0]), goto error);
+ isl_assert(vec2->ctx, isl_int_is_one(vec2->el[0]), goto error);
+
+ vec = isl_vec_alloc(vec1->ctx, vec1->size + vec2->size - 1);
+ if (!vec)
+ goto error;
+
+ isl_seq_cpy(vec->el, vec1->el, vec1->size);
+ isl_seq_cpy(vec->el + vec1->size, vec2->el + 1, vec2->size - 1);
+
+ isl_vec_free(vec1);
+ isl_vec_free(vec2);
+
+ return vec;
+error:
+ isl_vec_free(vec1);
+ isl_vec_free(vec2);
+ return NULL;
+}
+
+/* Give a basic set "bset" with recession cone "cone", compute and
+ * return an integer point in bset, if any.
+ *
+ * If the recession cone is full-dimensional, then we know that
+ * bset contains an infinite number of integer points and it is
+ * fairly easy to pick one of them.
+ * If the recession cone is not full-dimensional, then we first
+ * transform bset such that the bounded directions appear as
+ * the first dimensions of the transformed basic set.
+ * We do this by using a unimodular transformation that transforms
+ * the equalities in the recession cone to equalities on the first
+ * dimensions.
+ *
+ * The transformed set is then projected onto its bounded dimensions.
+ * Note that to compute this projection, we can simply drop all constraints
+ * involving any of the unbounded dimensions since these constraints
+ * cannot be combined to produce a constraint on the bounded dimensions.
+ * To see this, assume that there is such a combination of constraints
+ * that produces a constraint on the bounded dimensions. This means
+ * that some combination of the unbounded dimensions has both an upper
+ * bound and a lower bound in terms of the bounded dimensions, but then
+ * this combination would be a bounded direction too and would have been
+ * transformed into a bounded dimensions.
+ *
+ * We then compute a sample value in the bounded dimensions.
+ * If no such value can be found, then the original set did not contain
+ * any integer points and we are done.
+ * Otherwise, we plug in the value we found in the bounded dimensions,
+ * project out these bounded dimensions and end up with a set with
+ * a full-dimensional recession cone.
+ * A sample point in this set is computed by "rounding up" any
+ * rational point in the set.
+ *
+ * The sample points in the bounded and unbounded dimensions are
+ * then combined into a single sample point and transformed back
+ * to the original space.
+ */
+__isl_give isl_vec *isl_basic_set_sample_with_cone(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone)
+{
+ unsigned total;
+ unsigned cone_dim;
+ struct isl_mat *M, *U;
+ struct isl_vec *sample;
+ struct isl_vec *cone_sample;
+ struct isl_ctx *ctx;
+ struct isl_basic_set *bounded;
+
+ if (!bset || !cone)
+ goto error;
+
+ ctx = bset->ctx;
+ total = isl_basic_set_total_dim(cone);
+ cone_dim = total - cone->n_eq;
+
+ M = isl_mat_sub_alloc6(bset->ctx, cone->eq, 0, cone->n_eq, 1, total);
+ M = isl_mat_left_hermite(M, 0, &U, NULL);
+ if (!M)
+ goto error;
+ isl_mat_free(M);
+
+ U = isl_mat_lin_to_aff(U);
+ bset = isl_basic_set_preimage(bset, isl_mat_copy(U));
+
+ bounded = isl_basic_set_copy(bset);
+ bounded = isl_basic_set_drop_constraints_involving(bounded,
+ total - cone_dim, cone_dim);
+ bounded = isl_basic_set_drop_dims(bounded, total - cone_dim, cone_dim);
+ sample = sample_bounded(bounded);
+ if (!sample || sample->size == 0) {
+ isl_basic_set_free(bset);
+ isl_basic_set_free(cone);
+ isl_mat_free(U);
+ return sample;
+ }
+ bset = plug_in(bset, isl_vec_copy(sample));
+ cone_sample = rational_sample(bset);
+ cone_sample = round_up_in_cone(cone_sample, cone, isl_mat_copy(U));
+ sample = vec_concat(sample, cone_sample);
+ sample = isl_mat_vec_product(U, sample);
+ return sample;
+error:
+ isl_basic_set_free(cone);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static void vec_sum_of_neg(struct isl_vec *v, isl_int *s)
+{
+ int i;
+
+ isl_int_set_si(*s, 0);
+
+ for (i = 0; i < v->size; ++i)
+ if (isl_int_is_neg(v->el[i]))
+ isl_int_add(*s, *s, v->el[i]);
+}
+
+/* Given a tableau "tab", a tableau "tab_cone" that corresponds
+ * to the recession cone and the inverse of a new basis U = inv(B),
+ * with the unbounded directions in B last,
+ * add constraints to "tab" that ensure any rational value
+ * in the unbounded directions can be rounded up to an integer value.
+ *
+ * The new basis is given by x' = B x, i.e., x = U x'.
+ * For any rational value of the last tab->n_unbounded coordinates
+ * in the update tableau, the value that is obtained by rounding
+ * up this value should be contained in the original tableau.
+ * For any constraint "a x + c >= 0", we therefore need to add
+ * a constraint "a x + c + s >= 0", with s the sum of all negative
+ * entries in the last elements of "a U".
+ *
+ * Since we are not interested in the first entries of any of the "a U",
+ * we first drop the columns of U that correpond to bounded directions.
+ */
+static int tab_shift_cone(struct isl_tab *tab,
+ struct isl_tab *tab_cone, struct isl_mat *U)
+{
+ int i;
+ isl_int v;
+ struct isl_basic_set *bset = NULL;
+
+ if (tab && tab->n_unbounded == 0) {
+ isl_mat_free(U);
+ return 0;
+ }
+ isl_int_init(v);
+ if (!tab || !tab_cone || !U)
+ goto error;
+ bset = isl_tab_peek_bset(tab_cone);
+ U = isl_mat_drop_cols(U, 0, tab->n_var - tab->n_unbounded);
+ for (i = 0; i < bset->n_ineq; ++i) {
+ int ok;
+ struct isl_vec *row = NULL;
+ if (isl_tab_is_equality(tab_cone, tab_cone->n_eq + i))
+ continue;
+ row = isl_vec_alloc(bset->ctx, tab_cone->n_var);
+ if (!row)
+ goto error;
+ isl_seq_cpy(row->el, bset->ineq[i] + 1, tab_cone->n_var);
+ row = isl_vec_mat_product(row, isl_mat_copy(U));
+ if (!row)
+ goto error;
+ vec_sum_of_neg(row, &v);
+ isl_vec_free(row);
+ if (isl_int_is_zero(v))
+ continue;
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ goto error;
+ isl_int_add(bset->ineq[i][0], bset->ineq[i][0], v);
+ ok = isl_tab_add_ineq(tab, bset->ineq[i]) >= 0;
+ isl_int_sub(bset->ineq[i][0], bset->ineq[i][0], v);
+ if (!ok)
+ goto error;
+ }
+
+ isl_mat_free(U);
+ isl_int_clear(v);
+ return 0;
+error:
+ isl_mat_free(U);
+ isl_int_clear(v);
+ return -1;
+}
+
+/* Compute and return an initial basis for the possibly
+ * unbounded tableau "tab". "tab_cone" is a tableau
+ * for the corresponding recession cone.
+ * Additionally, add constraints to "tab" that ensure
+ * that any rational value for the unbounded directions
+ * can be rounded up to an integer value.
+ *
+ * If the tableau is bounded, i.e., if the recession cone
+ * is zero-dimensional, then we just use inital_basis.
+ * Otherwise, we construct a basis whose first directions
+ * correspond to equalities, followed by bounded directions,
+ * i.e., equalities in the recession cone.
+ * The remaining directions are then unbounded.
+ */
+int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab,
+ struct isl_tab *tab_cone)
+{
+ struct isl_mat *eq;
+ struct isl_mat *cone_eq;
+ struct isl_mat *U, *Q;
+
+ if (!tab || !tab_cone)
+ return -1;
+
+ if (tab_cone->n_col == tab_cone->n_dead) {
+ tab->basis = initial_basis(tab);
+ return tab->basis ? 0 : -1;
+ }
+
+ eq = tab_equalities(tab);
+ if (!eq)
+ return -1;
+ tab->n_zero = eq->n_row;
+ cone_eq = tab_equalities(tab_cone);
+ eq = isl_mat_concat(eq, cone_eq);
+ if (!eq)
+ return -1;
+ tab->n_unbounded = tab->n_var - (eq->n_row - tab->n_zero);
+ eq = isl_mat_left_hermite(eq, 0, &U, &Q);
+ if (!eq)
+ return -1;
+ isl_mat_free(eq);
+ tab->basis = isl_mat_lin_to_aff(Q);
+ if (tab_shift_cone(tab, tab_cone, U) < 0)
+ return -1;
+ if (!tab->basis)
+ return -1;
+ return 0;
+}
+
+/* Compute and return a sample point in bset using generalized basis
+ * reduction. We first check if the input set has a non-trivial
+ * recession cone. If so, we perform some extra preprocessing in
+ * sample_with_cone. Otherwise, we directly perform generalized basis
+ * reduction.
+ */
+static struct isl_vec *gbr_sample(struct isl_basic_set *bset)
+{
+ unsigned dim;
+ struct isl_basic_set *cone;
+
+ dim = isl_basic_set_total_dim(bset);
+
+ cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
+ if (!cone)
+ goto error;
+
+ if (cone->n_eq < dim)
+ return isl_basic_set_sample_with_cone(bset, cone);
+
+ isl_basic_set_free(cone);
+ return sample_bounded(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static struct isl_vec *basic_set_sample(struct isl_basic_set *bset, int bounded)
+{
+ struct isl_ctx *ctx;
+ unsigned dim;
+ if (!bset)
+ return NULL;
+
+ ctx = bset->ctx;
+ if (isl_basic_set_plain_is_empty(bset))
+ return empty_sample(bset);
+
+ dim = isl_basic_set_n_dim(bset);
+ isl_assert(ctx, isl_basic_set_n_param(bset) == 0, goto error);
+ isl_assert(ctx, bset->n_div == 0, goto error);
+
+ if (bset->sample && bset->sample->size == 1 + dim) {
+ int contains = isl_basic_set_contains(bset, bset->sample);
+ if (contains < 0)
+ goto error;
+ if (contains) {
+ struct isl_vec *sample = isl_vec_copy(bset->sample);
+ isl_basic_set_free(bset);
+ return sample;
+ }
+ }
+ isl_vec_free(bset->sample);
+ bset->sample = NULL;
+
+ if (bset->n_eq > 0)
+ return sample_eq(bset, bounded ? isl_basic_set_sample_bounded
+ : isl_basic_set_sample_vec);
+ if (dim == 0)
+ return zero_sample(bset);
+ if (dim == 1)
+ return interval_sample(bset);
+
+ return bounded ? sample_bounded(bset) : gbr_sample(bset);
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_basic_set_sample_vec(__isl_take isl_basic_set *bset)
+{
+ return basic_set_sample(bset, 0);
+}
+
+/* Compute an integer sample in "bset", where the caller guarantees
+ * that "bset" is bounded.
+ */
+struct isl_vec *isl_basic_set_sample_bounded(struct isl_basic_set *bset)
+{
+ return basic_set_sample(bset, 1);
+}
+
+__isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec)
+{
+ int i;
+ int k;
+ struct isl_basic_set *bset = NULL;
+ struct isl_ctx *ctx;
+ unsigned dim;
+
+ if (!vec)
+ return NULL;
+ ctx = vec->ctx;
+ isl_assert(ctx, vec->size != 0, goto error);
+
+ bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0);
+ if (!bset)
+ goto error;
+ dim = isl_basic_set_n_dim(bset);
+ for (i = dim - 1; i >= 0; --i) {
+ k = isl_basic_set_alloc_equality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->eq[k], 1 + dim);
+ isl_int_neg(bset->eq[k][0], vec->el[1 + i]);
+ isl_int_set(bset->eq[k][1 + i], vec->el[0]);
+ }
+ bset->sample = vec;
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap)
+{
+ struct isl_basic_set *bset;
+ struct isl_vec *sample_vec;
+
+ bset = isl_basic_map_underlying_set(isl_basic_map_copy(bmap));
+ sample_vec = isl_basic_set_sample_vec(bset);
+ if (!sample_vec)
+ goto error;
+ if (sample_vec->size == 0) {
+ struct isl_basic_map *sample;
+ sample = isl_basic_map_empty_like(bmap);
+ isl_vec_free(sample_vec);
+ isl_basic_map_free(bmap);
+ return sample;
+ }
+ bset = isl_basic_set_from_vec(sample_vec);
+ return isl_basic_map_overlying_set(bset, bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset)
+{
+ return isl_basic_map_sample(bset);
+}
+
+__isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map)
+{
+ int i;
+ isl_basic_map *sample = NULL;
+
+ if (!map)
+ goto error;
+
+ for (i = 0; i < map->n; ++i) {
+ sample = isl_basic_map_sample(isl_basic_map_copy(map->p[i]));
+ if (!sample)
+ goto error;
+ if (!ISL_F_ISSET(sample, ISL_BASIC_MAP_EMPTY))
+ break;
+ isl_basic_map_free(sample);
+ }
+ if (i == map->n)
+ sample = isl_basic_map_empty_like_map(map);
+ isl_map_free(map);
+ return sample;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set)
+{
+ return (isl_basic_set *) isl_map_sample((isl_map *)set);
+}
+
+__isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset)
+{
+ isl_vec *vec;
+ isl_space *dim;
+
+ dim = isl_basic_set_get_space(bset);
+ bset = isl_basic_set_underlying_set(bset);
+ vec = isl_basic_set_sample_vec(bset);
+
+ return isl_point_alloc(dim, vec);
+}
+
+__isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set)
+{
+ int i;
+ isl_point *pnt;
+
+ if (!set)
+ return NULL;
+
+ for (i = 0; i < set->n; ++i) {
+ pnt = isl_basic_set_sample_point(isl_basic_set_copy(set->p[i]));
+ if (!pnt)
+ goto error;
+ if (!isl_point_is_void(pnt))
+ break;
+ isl_point_free(pnt);
+ }
+ if (i == set->n)
+ pnt = isl_point_void(isl_set_get_space(set));
+
+ isl_set_free(set);
+ return pnt;
+error:
+ isl_set_free(set);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_sample.h b/polly/lib/External/isl/isl_sample.h
new file mode 100644
index 00000000000..57898b25ce0
--- /dev/null
+++ b/polly/lib/External/isl/isl_sample.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_SAMPLE_H
+#define ISL_SAMPLE_H
+
+#include <isl/set.h>
+#include <isl_tab.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_vec *isl_basic_set_sample_vec(__isl_take isl_basic_set *bset);
+struct isl_vec *isl_basic_set_sample_bounded(struct isl_basic_set *bset);
+__isl_give isl_vec *isl_basic_set_sample_with_cone(
+ __isl_take isl_basic_set *bset, __isl_take isl_basic_set *cone);
+
+__isl_give isl_basic_set *isl_basic_set_from_vec(__isl_take isl_vec *vec);
+
+int isl_tab_set_initial_basis_with_cone(struct isl_tab *tab,
+ struct isl_tab *tab_cone);
+struct isl_vec *isl_tab_sample(struct isl_tab *tab);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_scan.c b/polly/lib/External/isl/isl_scan.c
new file mode 100644
index 00000000000..eb8423c6e35
--- /dev/null
+++ b/polly/lib/External/isl/isl_scan.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include "isl_basis_reduction.h"
+#include "isl_scan.h"
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+
+struct isl_counter {
+ struct isl_scan_callback callback;
+ isl_int count;
+ isl_int max;
+};
+
+static int increment_counter(struct isl_scan_callback *cb,
+ __isl_take isl_vec *sample)
+{
+ struct isl_counter *cnt = (struct isl_counter *)cb;
+
+ isl_int_add_ui(cnt->count, cnt->count, 1);
+
+ isl_vec_free(sample);
+
+ if (isl_int_is_zero(cnt->max) || isl_int_lt(cnt->count, cnt->max))
+ return 0;
+ return -1;
+}
+
+static int increment_range(struct isl_scan_callback *cb, isl_int min, isl_int max)
+{
+ struct isl_counter *cnt = (struct isl_counter *)cb;
+
+ isl_int_add(cnt->count, cnt->count, max);
+ isl_int_sub(cnt->count, cnt->count, min);
+ isl_int_add_ui(cnt->count, cnt->count, 1);
+
+ if (isl_int_is_zero(cnt->max) || isl_int_lt(cnt->count, cnt->max))
+ return 0;
+ isl_int_set(cnt->count, cnt->max);
+ return -1;
+}
+
+/* Call callback->add with the current sample value of the tableau "tab".
+ */
+static int add_solution(struct isl_tab *tab, struct isl_scan_callback *callback)
+{
+ struct isl_vec *sample;
+
+ if (!tab)
+ return -1;
+ sample = isl_tab_get_sample_value(tab);
+ if (!sample)
+ return -1;
+
+ return callback->add(callback, sample);
+}
+
+static int scan_0D(struct isl_basic_set *bset,
+ struct isl_scan_callback *callback)
+{
+ struct isl_vec *sample;
+
+ sample = isl_vec_alloc(bset->ctx, 1);
+ isl_basic_set_free(bset);
+
+ if (!sample)
+ return -1;
+
+ isl_int_set_si(sample->el[0], 1);
+
+ return callback->add(callback, sample);
+}
+
+/* Look for all integer points in "bset", which is assumed to be bounded,
+ * and call callback->add on each of them.
+ *
+ * We first compute a reduced basis for the set and then scan
+ * the set in the directions of this basis.
+ * We basically perform a depth first search, where in each level i
+ * we compute the range in the i-th basis vector direction, given
+ * fixed values in the directions of the previous basis vector.
+ * We then add an equality to the tableau fixing the value in the
+ * direction of the current basis vector to each value in the range
+ * in turn and then continue to the next level.
+ *
+ * The search is implemented iteratively. "level" identifies the current
+ * basis vector. "init" is true if we want the first value at the current
+ * level and false if we want the next value.
+ * Solutions are added in the leaves of the search tree, i.e., after
+ * we have fixed a value in each direction of the basis.
+ */
+int isl_basic_set_scan(struct isl_basic_set *bset,
+ struct isl_scan_callback *callback)
+{
+ unsigned dim;
+ struct isl_mat *B = NULL;
+ struct isl_tab *tab = NULL;
+ struct isl_vec *min;
+ struct isl_vec *max;
+ struct isl_tab_undo **snap;
+ int level;
+ int init;
+ enum isl_lp_result res;
+
+ if (!bset)
+ return -1;
+
+ dim = isl_basic_set_total_dim(bset);
+ if (dim == 0)
+ return scan_0D(bset, callback);
+
+ min = isl_vec_alloc(bset->ctx, dim);
+ max = isl_vec_alloc(bset->ctx, dim);
+ snap = isl_alloc_array(bset->ctx, struct isl_tab_undo *, dim);
+
+ if (!min || !max || !snap)
+ goto error;
+
+ tab = isl_tab_from_basic_set(bset, 0);
+ if (!tab)
+ goto error;
+ if (isl_tab_extend_cons(tab, dim + 1) < 0)
+ goto error;
+
+ tab->basis = isl_mat_identity(bset->ctx, 1 + dim);
+ if (1)
+ tab = isl_tab_compute_reduced_basis(tab);
+ if (!tab)
+ goto error;
+ B = isl_mat_copy(tab->basis);
+ if (!B)
+ goto error;
+
+ level = 0;
+ init = 1;
+
+ while (level >= 0) {
+ int empty = 0;
+ if (init) {
+ res = isl_tab_min(tab, B->row[1 + level],
+ bset->ctx->one, &min->el[level], NULL, 0);
+ if (res == isl_lp_empty)
+ empty = 1;
+ if (res == isl_lp_error || res == isl_lp_unbounded)
+ goto error;
+ isl_seq_neg(B->row[1 + level] + 1,
+ B->row[1 + level] + 1, dim);
+ res = isl_tab_min(tab, B->row[1 + level],
+ bset->ctx->one, &max->el[level], NULL, 0);
+ isl_seq_neg(B->row[1 + level] + 1,
+ B->row[1 + level] + 1, dim);
+ isl_int_neg(max->el[level], max->el[level]);
+ if (res == isl_lp_empty)
+ empty = 1;
+ if (res == isl_lp_error || res == isl_lp_unbounded)
+ goto error;
+ snap[level] = isl_tab_snap(tab);
+ } else
+ isl_int_add_ui(min->el[level], min->el[level], 1);
+
+ if (empty || isl_int_gt(min->el[level], max->el[level])) {
+ level--;
+ init = 0;
+ if (level >= 0)
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ continue;
+ }
+ if (level == dim - 1 && callback->add == increment_counter) {
+ if (increment_range(callback,
+ min->el[level], max->el[level]))
+ goto error;
+ level--;
+ init = 0;
+ if (level >= 0)
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ continue;
+ }
+ isl_int_neg(B->row[1 + level][0], min->el[level]);
+ if (isl_tab_add_valid_eq(tab, B->row[1 + level]) < 0)
+ goto error;
+ isl_int_set_si(B->row[1 + level][0], 0);
+ if (level < dim - 1) {
+ ++level;
+ init = 1;
+ continue;
+ }
+ if (add_solution(tab, callback) < 0)
+ goto error;
+ init = 0;
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ }
+
+ isl_tab_free(tab);
+ free(snap);
+ isl_vec_free(min);
+ isl_vec_free(max);
+ isl_basic_set_free(bset);
+ isl_mat_free(B);
+ return 0;
+error:
+ isl_tab_free(tab);
+ free(snap);
+ isl_vec_free(min);
+ isl_vec_free(max);
+ isl_basic_set_free(bset);
+ isl_mat_free(B);
+ return -1;
+}
+
+int isl_set_scan(__isl_take isl_set *set, struct isl_scan_callback *callback)
+{
+ int i;
+
+ if (!set || !callback)
+ goto error;
+
+ set = isl_set_cow(set);
+ set = isl_set_make_disjoint(set);
+ set = isl_set_compute_divs(set);
+ if (!set)
+ goto error;
+
+ for (i = 0; i < set->n; ++i)
+ if (isl_basic_set_scan(isl_basic_set_copy(set->p[i]),
+ callback) < 0)
+ goto error;
+
+ isl_set_free(set);
+ return 0;
+error:
+ isl_set_free(set);
+ return -1;
+}
+
+int isl_basic_set_count_upto(__isl_keep isl_basic_set *bset,
+ isl_int max, isl_int *count)
+{
+ struct isl_counter cnt = { { &increment_counter } };
+
+ if (!bset)
+ return -1;
+
+ isl_int_init(cnt.count);
+ isl_int_init(cnt.max);
+
+ isl_int_set_si(cnt.count, 0);
+ isl_int_set(cnt.max, max);
+ if (isl_basic_set_scan(isl_basic_set_copy(bset), &cnt.callback) < 0 &&
+ isl_int_lt(cnt.count, cnt.max))
+ goto error;
+
+ isl_int_set(*count, cnt.count);
+ isl_int_clear(cnt.max);
+ isl_int_clear(cnt.count);
+
+ return 0;
+error:
+ isl_int_clear(cnt.count);
+ return -1;
+}
+
+int isl_set_count_upto(__isl_keep isl_set *set, isl_int max, isl_int *count)
+{
+ struct isl_counter cnt = { { &increment_counter } };
+
+ if (!set)
+ return -1;
+
+ isl_int_init(cnt.count);
+ isl_int_init(cnt.max);
+
+ isl_int_set_si(cnt.count, 0);
+ isl_int_set(cnt.max, max);
+ if (isl_set_scan(isl_set_copy(set), &cnt.callback) < 0 &&
+ isl_int_lt(cnt.count, cnt.max))
+ goto error;
+
+ isl_int_set(*count, cnt.count);
+ isl_int_clear(cnt.max);
+ isl_int_clear(cnt.count);
+
+ return 0;
+error:
+ isl_int_clear(cnt.count);
+ return -1;
+}
+
+int isl_set_count(__isl_keep isl_set *set, isl_int *count)
+{
+ if (!set)
+ return -1;
+ return isl_set_count_upto(set, set->ctx->zero, count);
+}
+
+/* Count the total number of elements in "set" (in an inefficient way) and
+ * return the result.
+ */
+__isl_give isl_val *isl_set_count_val(__isl_keep isl_set *set)
+{
+ isl_val *v;
+
+ if (!set)
+ return NULL;
+ v = isl_val_zero(isl_set_get_ctx(set));
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ if (isl_set_count(set, &v->n) < 0)
+ v = isl_val_free(v);
+ return v;
+}
diff --git a/polly/lib/External/isl/isl_scan.h b/polly/lib/External/isl/isl_scan.h
new file mode 100644
index 00000000000..d186df4e53f
--- /dev/null
+++ b/polly/lib/External/isl/isl_scan.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_SCAN_H
+#define ISL_SCAN_H
+
+#include <isl/set.h>
+#include <isl/vec.h>
+
+struct isl_scan_callback {
+ int (*add)(struct isl_scan_callback *cb, __isl_take isl_vec *sample);
+};
+
+int isl_basic_set_scan(struct isl_basic_set *bset,
+ struct isl_scan_callback *callback);
+int isl_set_scan(__isl_take isl_set *set, struct isl_scan_callback *callback);
+
+#endif
diff --git a/polly/lib/External/isl/isl_schedule.c b/polly/lib/External/isl/isl_schedule.c
new file mode 100644
index 00000000000..1ad98d5df4d
--- /dev/null
+++ b/polly/lib/External/isl/isl_schedule.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2012-2014 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/ctx.h>
+#include <isl_aff_private.h>
+#include <isl/map.h>
+#include <isl/set.h>
+#include <isl_sort.h>
+#include <isl_schedule_private.h>
+#include <isl_band_private.h>
+
+__isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched)
+{
+ int i;
+ if (!sched)
+ return NULL;
+
+ if (--sched->ref > 0)
+ return NULL;
+
+ for (i = 0; i < sched->n; ++i) {
+ isl_multi_aff_free(sched->node[i].sched);
+ free(sched->node[i].band_end);
+ free(sched->node[i].band_id);
+ free(sched->node[i].coincident);
+ }
+ isl_space_free(sched->dim);
+ isl_band_list_free(sched->band_forest);
+ free(sched);
+ return NULL;
+}
+
+isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *schedule)
+{
+ return schedule ? isl_space_get_ctx(schedule->dim) : NULL;
+}
+
+/* Set max_out to the maximal number of output dimensions over
+ * all maps.
+ */
+static int update_max_out(__isl_take isl_map *map, void *user)
+{
+ int *max_out = user;
+ int n_out = isl_map_dim(map, isl_dim_out);
+
+ if (n_out > *max_out)
+ *max_out = n_out;
+
+ isl_map_free(map);
+ return 0;
+}
+
+/* Internal data structure for map_pad_range.
+ *
+ * "max_out" is the maximal schedule dimension.
+ * "res" collects the results.
+ */
+struct isl_pad_schedule_map_data {
+ int max_out;
+ isl_union_map *res;
+};
+
+/* Pad the range of the given map with zeros to data->max_out and
+ * then add the result to data->res.
+ */
+static int map_pad_range(__isl_take isl_map *map, void *user)
+{
+ struct isl_pad_schedule_map_data *data = user;
+ int i;
+ int n_out = isl_map_dim(map, isl_dim_out);
+
+ map = isl_map_add_dims(map, isl_dim_out, data->max_out - n_out);
+ for (i = n_out; i < data->max_out; ++i)
+ map = isl_map_fix_si(map, isl_dim_out, i, 0);
+
+ data->res = isl_union_map_add_map(data->res, map);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Pad the ranges of the maps in the union map with zeros such they all have
+ * the same dimension.
+ */
+static __isl_give isl_union_map *pad_schedule_map(
+ __isl_take isl_union_map *umap)
+{
+ struct isl_pad_schedule_map_data data;
+
+ if (!umap)
+ return NULL;
+ if (isl_union_map_n_map(umap) <= 1)
+ return umap;
+
+ data.max_out = 0;
+ if (isl_union_map_foreach_map(umap, &update_max_out, &data.max_out) < 0)
+ return isl_union_map_free(umap);
+
+ data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+ if (isl_union_map_foreach_map(umap, &map_pad_range, &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_union_map_free(umap);
+ return data.res;
+}
+
+/* Return an isl_union_map of the schedule. If we have already constructed
+ * a band forest, then this band forest may have been modified so we need
+ * to extract the isl_union_map from the forest rather than from
+ * the originally computed schedule. This reconstructed schedule map
+ * then needs to be padded with zeros to unify the schedule space
+ * since the result of isl_band_list_get_suffix_schedule may not have
+ * a unified schedule space.
+ */
+__isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
+{
+ int i;
+ isl_union_map *umap;
+
+ if (!sched)
+ return NULL;
+
+ if (sched->band_forest) {
+ umap = isl_band_list_get_suffix_schedule(sched->band_forest);
+ return pad_schedule_map(umap);
+ }
+
+ umap = isl_union_map_empty(isl_space_copy(sched->dim));
+ for (i = 0; i < sched->n; ++i) {
+ isl_multi_aff *ma;
+
+ ma = isl_multi_aff_copy(sched->node[i].sched);
+ umap = isl_union_map_add_map(umap, isl_map_from_multi_aff(ma));
+ }
+
+ return umap;
+}
+
+static __isl_give isl_band_list *construct_band_list(
+ __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
+ int band_nr, int *parent_active, int n_active);
+
+/* Construct an isl_band structure for the band in the given schedule
+ * with sequence number band_nr for the n_active nodes marked by active.
+ * If the nodes don't have a band with the given sequence number,
+ * then a band without members is created.
+ *
+ * Because of the way the schedule is constructed, we know that
+ * the position of the band inside the schedule of a node is the same
+ * for all active nodes.
+ *
+ * The partial schedule for the band is created before the children
+ * are created to that construct_band_list can refer to the partial
+ * schedule of the parent.
+ */
+static __isl_give isl_band *construct_band(__isl_keep isl_schedule *schedule,
+ __isl_keep isl_band *parent,
+ int band_nr, int *active, int n_active)
+{
+ int i, j;
+ isl_ctx *ctx = isl_schedule_get_ctx(schedule);
+ isl_band *band;
+ unsigned start, end;
+
+ band = isl_band_alloc(ctx);
+ if (!band)
+ return NULL;
+
+ band->schedule = schedule;
+ band->parent = parent;
+
+ for (i = 0; i < schedule->n; ++i)
+ if (active[i])
+ break;
+
+ if (i >= schedule->n)
+ isl_die(ctx, isl_error_internal,
+ "band without active statements", goto error);
+
+ start = band_nr ? schedule->node[i].band_end[band_nr - 1] : 0;
+ end = band_nr < schedule->node[i].n_band ?
+ schedule->node[i].band_end[band_nr] : start;
+ band->n = end - start;
+
+ band->coincident = isl_alloc_array(ctx, int, band->n);
+ if (band->n && !band->coincident)
+ goto error;
+
+ for (j = 0; j < band->n; ++j)
+ band->coincident[j] = schedule->node[i].coincident[start + j];
+
+ band->pma = isl_union_pw_multi_aff_empty(isl_space_copy(schedule->dim));
+ for (i = 0; i < schedule->n; ++i) {
+ isl_multi_aff *ma;
+ isl_pw_multi_aff *pma;
+ unsigned n_out;
+
+ if (!active[i])
+ continue;
+
+ ma = isl_multi_aff_copy(schedule->node[i].sched);
+ n_out = isl_multi_aff_dim(ma, isl_dim_out);
+ ma = isl_multi_aff_drop_dims(ma, isl_dim_out, end, n_out - end);
+ ma = isl_multi_aff_drop_dims(ma, isl_dim_out, 0, start);
+ pma = isl_pw_multi_aff_from_multi_aff(ma);
+ band->pma = isl_union_pw_multi_aff_add_pw_multi_aff(band->pma,
+ pma);
+ }
+ if (!band->pma)
+ goto error;
+
+ for (i = 0; i < schedule->n; ++i)
+ if (active[i] && schedule->node[i].n_band > band_nr + 1)
+ break;
+
+ if (i < schedule->n) {
+ band->children = construct_band_list(schedule, band,
+ band_nr + 1, active, n_active);
+ if (!band->children)
+ goto error;
+ }
+
+ return band;
+error:
+ isl_band_free(band);
+ return NULL;
+}
+
+/* Internal data structure used inside cmp_band and pw_multi_aff_extract_int.
+ *
+ * r is set to a negative value if anything goes wrong.
+ *
+ * c1 stores the result of extract_int.
+ * c2 is a temporary value used inside cmp_band_in_ancestor.
+ * t is a temporary value used inside extract_int.
+ *
+ * first and equal are used inside extract_int.
+ * first is set if we are looking at the first isl_multi_aff inside
+ * the isl_union_pw_multi_aff.
+ * equal is set if all the isl_multi_affs have been equal so far.
+ */
+struct isl_cmp_band_data {
+ int r;
+
+ int first;
+ int equal;
+
+ isl_int t;
+ isl_int c1;
+ isl_int c2;
+};
+
+/* Check if "ma" assigns a constant value.
+ * Note that this function is only called on isl_multi_affs
+ * with a single output dimension.
+ *
+ * If "ma" assigns a constant value then we compare it to data->c1
+ * or assign it to data->c1 if this is the first isl_multi_aff we consider.
+ * If "ma" does not assign a constant value or if it assigns a value
+ * that is different from data->c1, then we set data->equal to zero
+ * and terminate the check.
+ */
+static int multi_aff_extract_int(__isl_take isl_set *set,
+ __isl_take isl_multi_aff *ma, void *user)
+{
+ isl_aff *aff;
+ struct isl_cmp_band_data *data = user;
+
+ aff = isl_multi_aff_get_aff(ma, 0);
+ data->r = isl_aff_is_cst(aff);
+ if (data->r >= 0 && data->r) {
+ isl_aff_get_constant(aff, &data->t);
+ if (data->first) {
+ isl_int_set(data->c1, data->t);
+ data->first = 0;
+ } else if (!isl_int_eq(data->c1, data->t))
+ data->equal = 0;
+ } else if (data->r >= 0 && !data->r)
+ data->equal = 0;
+
+ isl_aff_free(aff);
+ isl_set_free(set);
+ isl_multi_aff_free(ma);
+
+ if (data->r < 0)
+ return -1;
+ if (!data->equal)
+ return -1;
+ return 0;
+}
+
+/* This function is called for each isl_pw_multi_aff in
+ * the isl_union_pw_multi_aff checked by extract_int.
+ * Check all the isl_multi_affs inside "pma".
+ */
+static int pw_multi_aff_extract_int(__isl_take isl_pw_multi_aff *pma,
+ void *user)
+{
+ int r;
+
+ r = isl_pw_multi_aff_foreach_piece(pma, &multi_aff_extract_int, user);
+ isl_pw_multi_aff_free(pma);
+
+ return r;
+}
+
+/* Check if "upma" assigns a single constant value to its domain.
+ * If so, return 1 and store the result in data->c1.
+ * If not, return 0.
+ *
+ * A negative return value from isl_union_pw_multi_aff_foreach_pw_multi_aff
+ * means that either an error occurred or that we have broken off the check
+ * because we already know the result is going to be negative.
+ * In the latter case, data->equal is set to zero.
+ */
+static int extract_int(__isl_keep isl_union_pw_multi_aff *upma,
+ struct isl_cmp_band_data *data)
+{
+ data->first = 1;
+ data->equal = 1;
+
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &pw_multi_aff_extract_int, data) < 0) {
+ if (!data->equal)
+ return 0;
+ return -1;
+ }
+
+ return !data->first && data->equal;
+}
+
+/* Compare "b1" and "b2" based on the parent schedule of their ancestor
+ * "ancestor".
+ *
+ * If the parent of "ancestor" also has a single member, then we
+ * first try to compare the two band based on the partial schedule
+ * of this parent.
+ *
+ * Otherwise, or if the result is inconclusive, we look at the partial schedule
+ * of "ancestor" itself.
+ * In particular, we specialize the parent schedule based
+ * on the domains of the child schedules, check if both assign
+ * a single constant value and, if so, compare the two constant values.
+ * If the specialized parent schedules do not assign a constant value,
+ * then they cannot be used to order the two bands and so in this case
+ * we return 0.
+ */
+static int cmp_band_in_ancestor(__isl_keep isl_band *b1,
+ __isl_keep isl_band *b2, struct isl_cmp_band_data *data,
+ __isl_keep isl_band *ancestor)
+{
+ isl_union_pw_multi_aff *upma;
+ isl_union_set *domain;
+ int r;
+
+ if (data->r < 0)
+ return 0;
+
+ if (ancestor->parent && ancestor->parent->n == 1) {
+ r = cmp_band_in_ancestor(b1, b2, data, ancestor->parent);
+ if (data->r < 0)
+ return 0;
+ if (r)
+ return r;
+ }
+
+ upma = isl_union_pw_multi_aff_copy(b1->pma);
+ domain = isl_union_pw_multi_aff_domain(upma);
+ upma = isl_union_pw_multi_aff_copy(ancestor->pma);
+ upma = isl_union_pw_multi_aff_intersect_domain(upma, domain);
+ r = extract_int(upma, data);
+ isl_union_pw_multi_aff_free(upma);
+
+ if (r < 0)
+ data->r = -1;
+ if (r < 0 || !r)
+ return 0;
+
+ isl_int_set(data->c2, data->c1);
+
+ upma = isl_union_pw_multi_aff_copy(b2->pma);
+ domain = isl_union_pw_multi_aff_domain(upma);
+ upma = isl_union_pw_multi_aff_copy(ancestor->pma);
+ upma = isl_union_pw_multi_aff_intersect_domain(upma, domain);
+ r = extract_int(upma, data);
+ isl_union_pw_multi_aff_free(upma);
+
+ if (r < 0)
+ data->r = -1;
+ if (r < 0 || !r)
+ return 0;
+
+ return isl_int_cmp(data->c2, data->c1);
+}
+
+/* Compare "a" and "b" based on the parent schedule of their parent.
+ */
+static int cmp_band(const void *a, const void *b, void *user)
+{
+ isl_band *b1 = *(isl_band * const *) a;
+ isl_band *b2 = *(isl_band * const *) b;
+ struct isl_cmp_band_data *data = user;
+
+ return cmp_band_in_ancestor(b1, b2, data, b1->parent);
+}
+
+/* Sort the elements in "list" based on the partial schedules of its parent
+ * (and ancestors). In particular if the parent assigns constant values
+ * to the domains of the bands in "list", then the elements are sorted
+ * according to that order.
+ * This order should be a more "natural" order for the user, but otherwise
+ * shouldn't have any effect.
+ * If we would be constructing an isl_band forest directly in
+ * isl_schedule_constraints_compute_schedule then there wouldn't be any need
+ * for a reordering, since the children would be added to the list
+ * in their natural order automatically.
+ *
+ * If there is only one element in the list, then there is no need to sort
+ * anything.
+ * If the partial schedule of the parent has more than one member
+ * (or if there is no parent), then it's
+ * defnitely not assigning constant values to the different children in
+ * the list and so we wouldn't be able to use it to sort the list.
+ */
+static __isl_give isl_band_list *sort_band_list(__isl_take isl_band_list *list,
+ __isl_keep isl_band *parent)
+{
+ struct isl_cmp_band_data data;
+
+ if (!list)
+ return NULL;
+ if (list->n <= 1)
+ return list;
+ if (!parent || parent->n != 1)
+ return list;
+
+ data.r = 0;
+ isl_int_init(data.c1);
+ isl_int_init(data.c2);
+ isl_int_init(data.t);
+ isl_sort(list->p, list->n, sizeof(list->p[0]), &cmp_band, &data);
+ if (data.r < 0)
+ list = isl_band_list_free(list);
+ isl_int_clear(data.c1);
+ isl_int_clear(data.c2);
+ isl_int_clear(data.t);
+
+ return list;
+}
+
+/* Construct a list of bands that start at the same position (with
+ * sequence number band_nr) in the schedules of the nodes that
+ * were active in the parent band.
+ *
+ * A separate isl_band structure is created for each band_id
+ * and for each node that does not have a band with sequence
+ * number band_nr. In the latter case, a band without members
+ * is created.
+ * This ensures that if a band has any children, then each node
+ * that was active in the band is active in exactly one of the children.
+ */
+static __isl_give isl_band_list *construct_band_list(
+ __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
+ int band_nr, int *parent_active, int n_active)
+{
+ int i, j;
+ isl_ctx *ctx = isl_schedule_get_ctx(schedule);
+ int *active;
+ int n_band;
+ isl_band_list *list;
+
+ n_band = 0;
+ for (i = 0; i < n_active; ++i) {
+ for (j = 0; j < schedule->n; ++j) {
+ if (!parent_active[j])
+ continue;
+ if (schedule->node[j].n_band <= band_nr)
+ continue;
+ if (schedule->node[j].band_id[band_nr] == i) {
+ n_band++;
+ break;
+ }
+ }
+ }
+ for (j = 0; j < schedule->n; ++j)
+ if (schedule->node[j].n_band <= band_nr)
+ n_band++;
+
+ if (n_band == 1) {
+ isl_band *band;
+ list = isl_band_list_alloc(ctx, n_band);
+ band = construct_band(schedule, parent, band_nr,
+ parent_active, n_active);
+ return isl_band_list_add(list, band);
+ }
+
+ active = isl_alloc_array(ctx, int, schedule->n);
+ if (schedule->n && !active)
+ return NULL;
+
+ list = isl_band_list_alloc(ctx, n_band);
+
+ for (i = 0; i < n_active; ++i) {
+ int n = 0;
+ isl_band *band;
+
+ for (j = 0; j < schedule->n; ++j) {
+ active[j] = parent_active[j] &&
+ schedule->node[j].n_band > band_nr &&
+ schedule->node[j].band_id[band_nr] == i;
+ if (active[j])
+ n++;
+ }
+ if (n == 0)
+ continue;
+
+ band = construct_band(schedule, parent, band_nr, active, n);
+
+ list = isl_band_list_add(list, band);
+ }
+ for (i = 0; i < schedule->n; ++i) {
+ isl_band *band;
+ if (!parent_active[i])
+ continue;
+ if (schedule->node[i].n_band > band_nr)
+ continue;
+ for (j = 0; j < schedule->n; ++j)
+ active[j] = j == i;
+ band = construct_band(schedule, parent, band_nr, active, 1);
+ list = isl_band_list_add(list, band);
+ }
+
+ free(active);
+
+ list = sort_band_list(list, parent);
+
+ return list;
+}
+
+/* Construct a band forest representation of the schedule and
+ * return the list of roots.
+ */
+static __isl_give isl_band_list *construct_forest(
+ __isl_keep isl_schedule *schedule)
+{
+ int i;
+ isl_ctx *ctx = isl_schedule_get_ctx(schedule);
+ isl_band_list *forest;
+ int *active;
+
+ active = isl_alloc_array(ctx, int, schedule->n);
+ if (schedule->n && !active)
+ return NULL;
+
+ for (i = 0; i < schedule->n; ++i)
+ active[i] = 1;
+
+ forest = construct_band_list(schedule, NULL, 0, active, schedule->n);
+
+ free(active);
+
+ return forest;
+}
+
+/* Return the roots of a band forest representation of the schedule.
+ */
+__isl_give isl_band_list *isl_schedule_get_band_forest(
+ __isl_keep isl_schedule *schedule)
+{
+ if (!schedule)
+ return NULL;
+ if (!schedule->band_forest)
+ schedule->band_forest = construct_forest(schedule);
+ return isl_band_list_dup(schedule->band_forest);
+}
+
+/* Call "fn" on each band in the schedule in depth-first post-order.
+ */
+int isl_schedule_foreach_band(__isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_band *band, void *user), void *user)
+{
+ int r;
+ isl_band_list *forest;
+
+ if (!sched)
+ return -1;
+
+ forest = isl_schedule_get_band_forest(sched);
+ r = isl_band_list_foreach_band(forest, fn, user);
+ isl_band_list_free(forest);
+
+ return r;
+}
+
+static __isl_give isl_printer *print_band_list(__isl_take isl_printer *p,
+ __isl_keep isl_band_list *list);
+
+static __isl_give isl_printer *print_band(__isl_take isl_printer *p,
+ __isl_keep isl_band *band)
+{
+ isl_band_list *children;
+
+ p = isl_printer_start_line(p);
+ p = isl_printer_print_union_pw_multi_aff(p, band->pma);
+ p = isl_printer_end_line(p);
+
+ if (!isl_band_has_children(band))
+ return p;
+
+ children = isl_band_get_children(band);
+
+ p = isl_printer_indent(p, 4);
+ p = print_band_list(p, children);
+ p = isl_printer_indent(p, -4);
+
+ isl_band_list_free(children);
+
+ return p;
+}
+
+static __isl_give isl_printer *print_band_list(__isl_take isl_printer *p,
+ __isl_keep isl_band_list *list)
+{
+ int i, n;
+
+ n = isl_band_list_n_band(list);
+ for (i = 0; i < n; ++i) {
+ isl_band *band;
+ band = isl_band_list_get_band(list, i);
+ p = print_band(p, band);
+ isl_band_free(band);
+ }
+
+ return p;
+}
+
+__isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
+ __isl_keep isl_schedule *schedule)
+{
+ isl_band_list *forest;
+
+ forest = isl_schedule_get_band_forest(schedule);
+
+ p = print_band_list(p, forest);
+
+ isl_band_list_free(forest);
+
+ return p;
+}
+
+void isl_schedule_dump(__isl_keep isl_schedule *schedule)
+{
+ isl_printer *printer;
+
+ if (!schedule)
+ return;
+
+ printer = isl_printer_to_file(isl_schedule_get_ctx(schedule), stderr);
+ printer = isl_printer_print_schedule(printer, schedule);
+
+ isl_printer_free(printer);
+}
diff --git a/polly/lib/External/isl/isl_schedule_private.h b/polly/lib/External/isl/isl_schedule_private.h
new file mode 100644
index 00000000000..f40a72a0146
--- /dev/null
+++ b/polly/lib/External/isl/isl_schedule_private.h
@@ -0,0 +1,44 @@
+#ifndef ISL_SCHEDLUE_PRIVATE_H
+#define ISL_SCHEDLUE_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/schedule.h>
+
+/* The schedule for an individual domain, plus information about the bands
+ * and scheduling dimensions.
+ * In particular, we keep track of the number of bands and for each
+ * band, the starting position of the next band. The first band starts at
+ * position 0.
+ * For each scheduling dimension, we keep track of whether it satisfies
+ * the coincidence constraints (within its band).
+ */
+struct isl_schedule_node {
+ isl_multi_aff *sched;
+ int n_band;
+ int *band_end;
+ int *band_id;
+ int *coincident;
+};
+
+/* Information about the computed schedule.
+ * n is the number of nodes/domains/statements.
+ * n_band is the maximal number of bands.
+ * n_total_row is the number of coordinates of the schedule.
+ * dim contains a description of the parameters.
+ * band_forest points to a band forest representation of the schedule
+ * and may be NULL if the forest hasn't been created yet.
+ */
+struct isl_schedule {
+ int ref;
+
+ int n;
+ int n_band;
+ int n_total_row;
+ isl_space *dim;
+
+ isl_band_list *band_forest;
+
+ struct isl_schedule_node node[1];
+};
+
+#endif
diff --git a/polly/lib/External/isl/isl_scheduler.c b/polly/lib/External/isl/isl_scheduler.c
new file mode 100644
index 00000000000..4a7428045e0
--- /dev/null
+++ b/polly/lib/External/isl/isl_scheduler.c
@@ -0,0 +1,4148 @@
+/*
+ * Copyright 2011 INRIA Saclay
+ * Copyright 2012-2014 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_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_space_private.h>
+#include <isl_aff_private.h>
+#include <isl/hash.h>
+#include <isl/constraint.h>
+#include <isl/schedule.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_tab.h>
+#include <isl_dim_map.h>
+#include <isl/map_to_basic_set.h>
+#include <isl_sort.h>
+#include <isl_schedule_private.h>
+#include <isl_options_private.h>
+#include <isl_tarjan.h>
+#include <isl_morph.h>
+
+/*
+ * The scheduling algorithm implemented in this file was inspired by
+ * Bondhugula et al., "Automatic Transformations for Communication-Minimized
+ * Parallelization and Locality Optimization in the Polyhedral Model".
+ */
+
+enum isl_edge_type {
+ isl_edge_validity = 0,
+ isl_edge_first = isl_edge_validity,
+ isl_edge_coincidence,
+ isl_edge_condition,
+ isl_edge_conditional_validity,
+ isl_edge_proximity,
+ isl_edge_last = isl_edge_proximity
+};
+
+/* The constraints that need to be satisfied by a schedule on "domain".
+ *
+ * "validity" constraints map domain elements i to domain elements
+ * that should be scheduled after i. (Hard constraint)
+ * "proximity" constraints map domain elements i to domains elements
+ * that should be scheduled as early as possible after i (or before i).
+ * (Soft constraint)
+ *
+ * "condition" and "conditional_validity" constraints map possibly "tagged"
+ * domain elements i -> s to "tagged" domain elements j -> t.
+ * The elements of the "conditional_validity" constraints, but without the
+ * tags (i.e., the elements i -> j) are treated as validity constraints,
+ * except that during the construction of a tilable band,
+ * the elements of the "conditional_validity" constraints may be violated
+ * provided that all adjacent elements of the "condition" constraints
+ * are local within the band.
+ * A dependence is local within a band if domain and range are mapped
+ * to the same schedule point by the band.
+ */
+struct isl_schedule_constraints {
+ isl_union_set *domain;
+
+ isl_union_map *constraint[isl_edge_last + 1];
+};
+
+ __isl_give isl_schedule_constraints *isl_schedule_constraints_copy(
+ __isl_keep isl_schedule_constraints *sc)
+{
+ isl_ctx *ctx;
+ isl_schedule_constraints *sc_copy;
+ enum isl_edge_type i;
+
+ ctx = isl_union_set_get_ctx(sc->domain);
+ sc_copy = isl_calloc_type(ctx, struct isl_schedule_constraints);
+ if (!sc_copy)
+ return NULL;
+
+ sc_copy->domain = isl_union_set_copy(sc->domain);
+ if (!sc_copy->domain)
+ return isl_schedule_constraints_free(sc_copy);
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ sc_copy->constraint[i] = isl_union_map_copy(sc->constraint[i]);
+ if (!sc_copy->constraint[i])
+ return isl_schedule_constraints_free(sc_copy);
+ }
+
+ return sc_copy;
+}
+
+
+/* Construct an isl_schedule_constraints object for computing a schedule
+ * on "domain". The initial object does not impose any constraints.
+ */
+__isl_give isl_schedule_constraints *isl_schedule_constraints_on_domain(
+ __isl_take isl_union_set *domain)
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_schedule_constraints *sc;
+ isl_union_map *empty;
+ enum isl_edge_type i;
+
+ if (!domain)
+ return NULL;
+
+ ctx = isl_union_set_get_ctx(domain);
+ sc = isl_calloc_type(ctx, struct isl_schedule_constraints);
+ if (!sc)
+ goto error;
+
+ space = isl_union_set_get_space(domain);
+ sc->domain = domain;
+ empty = isl_union_map_empty(space);
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ sc->constraint[i] = isl_union_map_copy(empty);
+ if (!sc->constraint[i])
+ sc->domain = isl_union_set_free(sc->domain);
+ }
+ isl_union_map_free(empty);
+
+ if (!sc->domain)
+ return isl_schedule_constraints_free(sc);
+
+ return sc;
+error:
+ isl_union_set_free(domain);
+ return NULL;
+}
+
+/* Replace the validity constraints of "sc" by "validity".
+ */
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *validity)
+{
+ if (!sc || !validity)
+ goto error;
+
+ isl_union_map_free(sc->constraint[isl_edge_validity]);
+ sc->constraint[isl_edge_validity] = validity;
+
+ return sc;
+error:
+ isl_schedule_constraints_free(sc);
+ isl_union_map_free(validity);
+ return NULL;
+}
+
+/* Replace the coincidence constraints of "sc" by "coincidence".
+ */
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_coincidence(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *coincidence)
+{
+ if (!sc || !coincidence)
+ goto error;
+
+ isl_union_map_free(sc->constraint[isl_edge_coincidence]);
+ sc->constraint[isl_edge_coincidence] = coincidence;
+
+ return sc;
+error:
+ isl_schedule_constraints_free(sc);
+ isl_union_map_free(coincidence);
+ return NULL;
+}
+
+/* Replace the proximity constraints of "sc" by "proximity".
+ */
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_proximity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *proximity)
+{
+ if (!sc || !proximity)
+ goto error;
+
+ isl_union_map_free(sc->constraint[isl_edge_proximity]);
+ sc->constraint[isl_edge_proximity] = proximity;
+
+ return sc;
+error:
+ isl_schedule_constraints_free(sc);
+ isl_union_map_free(proximity);
+ return NULL;
+}
+
+/* Replace the conditional validity constraints of "sc" by "condition"
+ * and "validity".
+ */
+__isl_give isl_schedule_constraints *
+isl_schedule_constraints_set_conditional_validity(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_union_map *condition,
+ __isl_take isl_union_map *validity)
+{
+ if (!sc || !condition || !validity)
+ goto error;
+
+ isl_union_map_free(sc->constraint[isl_edge_condition]);
+ sc->constraint[isl_edge_condition] = condition;
+ isl_union_map_free(sc->constraint[isl_edge_conditional_validity]);
+ sc->constraint[isl_edge_conditional_validity] = validity;
+
+ return sc;
+error:
+ isl_schedule_constraints_free(sc);
+ isl_union_map_free(condition);
+ isl_union_map_free(validity);
+ return NULL;
+}
+
+__isl_null isl_schedule_constraints *isl_schedule_constraints_free(
+ __isl_take isl_schedule_constraints *sc)
+{
+ enum isl_edge_type i;
+
+ if (!sc)
+ return NULL;
+
+ isl_union_set_free(sc->domain);
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ isl_union_map_free(sc->constraint[i]);
+
+ free(sc);
+
+ return NULL;
+}
+
+isl_ctx *isl_schedule_constraints_get_ctx(
+ __isl_keep isl_schedule_constraints *sc)
+{
+ return sc ? isl_union_set_get_ctx(sc->domain) : NULL;
+}
+
+void isl_schedule_constraints_dump(__isl_keep isl_schedule_constraints *sc)
+{
+ if (!sc)
+ return;
+
+ fprintf(stderr, "domain: ");
+ isl_union_set_dump(sc->domain);
+ fprintf(stderr, "validity: ");
+ isl_union_map_dump(sc->constraint[isl_edge_validity]);
+ fprintf(stderr, "proximity: ");
+ isl_union_map_dump(sc->constraint[isl_edge_proximity]);
+ fprintf(stderr, "coincidence: ");
+ isl_union_map_dump(sc->constraint[isl_edge_coincidence]);
+ fprintf(stderr, "condition: ");
+ isl_union_map_dump(sc->constraint[isl_edge_condition]);
+ fprintf(stderr, "conditional_validity: ");
+ isl_union_map_dump(sc->constraint[isl_edge_conditional_validity]);
+}
+
+/* Align the parameters of the fields of "sc".
+ */
+static __isl_give isl_schedule_constraints *
+isl_schedule_constraints_align_params(__isl_take isl_schedule_constraints *sc)
+{
+ isl_space *space;
+ enum isl_edge_type i;
+
+ if (!sc)
+ return NULL;
+
+ space = isl_union_set_get_space(sc->domain);
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ space = isl_space_align_params(space,
+ isl_union_map_get_space(sc->constraint[i]));
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ sc->constraint[i] = isl_union_map_align_params(
+ sc->constraint[i], isl_space_copy(space));
+ if (!sc->constraint[i])
+ space = isl_space_free(space);
+ }
+ sc->domain = isl_union_set_align_params(sc->domain, space);
+ if (!sc->domain)
+ return isl_schedule_constraints_free(sc);
+
+ return sc;
+}
+
+/* Return the total number of isl_maps in the constraints of "sc".
+ */
+static __isl_give int isl_schedule_constraints_n_map(
+ __isl_keep isl_schedule_constraints *sc)
+{
+ enum isl_edge_type i;
+ int n = 0;
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ n += isl_union_map_n_map(sc->constraint[i]);
+
+ return n;
+}
+
+/* Internal information about a node that is used during the construction
+ * of a schedule.
+ * space represents the space in which the domain lives
+ * sched is a matrix representation of the schedule being constructed
+ * for this node; if compressed is set, then this schedule is
+ * defined over the compressed domain space
+ * sched_map is an isl_map representation of the same (partial) schedule
+ * sched_map may be NULL; if compressed is set, then this map
+ * is defined over the uncompressed domain space
+ * rank is the number of linearly independent rows in the linear part
+ * of sched
+ * the columns of cmap represent a change of basis for the schedule
+ * coefficients; the first rank columns span the linear part of
+ * the schedule rows
+ * cinv is the inverse of cmap.
+ * start is the first variable in the LP problem in the sequences that
+ * represents the schedule coefficients of this node
+ * nvar is the dimension of the domain
+ * nparam is the number of parameters or 0 if we are not constructing
+ * a parametric schedule
+ *
+ * If compressed is set, then hull represents the constraints
+ * that were used to derive the compression, while compress and
+ * decompress map the original space to the compressed space and
+ * vice versa.
+ *
+ * scc is the index of SCC (or WCC) this node belongs to
+ *
+ * band contains the band index for each of the rows of the schedule.
+ * band_id is used to differentiate between separate bands at the same
+ * level within the same parent band, i.e., bands that are separated
+ * by the parent band or bands that are independent of each other.
+ * coincident contains a boolean for each of the rows of the schedule,
+ * indicating whether the corresponding scheduling dimension satisfies
+ * the coincidence constraints in the sense that the corresponding
+ * dependence distances are zero.
+ */
+struct isl_sched_node {
+ isl_space *space;
+ int compressed;
+ isl_set *hull;
+ isl_multi_aff *compress;
+ isl_multi_aff *decompress;
+ isl_mat *sched;
+ isl_map *sched_map;
+ int rank;
+ isl_mat *cmap;
+ isl_mat *cinv;
+ int start;
+ int nvar;
+ int nparam;
+
+ int scc;
+
+ int *band;
+ int *band_id;
+ int *coincident;
+};
+
+static int node_has_space(const void *entry, const void *val)
+{
+ struct isl_sched_node *node = (struct isl_sched_node *)entry;
+ isl_space *dim = (isl_space *)val;
+
+ return isl_space_is_equal(node->space, dim);
+}
+
+/* An edge in the dependence graph. An edge may be used to
+ * ensure validity of the generated schedule, to minimize the dependence
+ * distance or both
+ *
+ * map is the dependence relation, with i -> j in the map if j depends on i
+ * tagged_condition and tagged_validity contain the union of all tagged
+ * condition or conditional validity dependence relations that
+ * specialize the dependence relation "map"; that is,
+ * if (i -> a) -> (j -> b) is an element of "tagged_condition"
+ * or "tagged_validity", then i -> j is an element of "map".
+ * If these fields are NULL, then they represent the empty relation.
+ * src is the source node
+ * dst is the sink node
+ * 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
+ * condition is set if the edge represents a condition
+ * for a conditional validity schedule constraint
+ * local can only be set for condition edges and indicates that
+ * the dependence distance over the edge should be zero
+ * conditional_validity is set if the edge is used to conditionally
+ * ensure correctness
+ *
+ * For validity edges, start and end mark the sequence of inequality
+ * constraints in the LP problem that encode the validity constraint
+ * corresponding to this edge.
+ */
+struct isl_sched_edge {
+ isl_map *map;
+ isl_union_map *tagged_condition;
+ isl_union_map *tagged_validity;
+
+ 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;
+
+ int start;
+ int end;
+};
+
+/* Internal information about the dependence graph used during
+ * the construction of the schedule.
+ *
+ * intra_hmap is a cache, mapping dependence relations to their dual,
+ * for dependences from a node to itself
+ * inter_hmap is a cache, mapping dependence relations to their dual,
+ * for dependences between distinct nodes
+ * if compression is involved then the key for these maps
+ * it the original, uncompressed dependence relation, while
+ * the value is the dual of the compressed dependence relation.
+ *
+ * n is the number of nodes
+ * node is the list of nodes
+ * maxvar is the maximal number of variables over all nodes
+ * max_row is the allocated number of rows in the schedule
+ * n_row is the current (maximal) number of linearly independent
+ * rows in the node schedules
+ * n_total_row is the current number of rows in the node schedules
+ * n_band is the current number of completed bands
+ * band_start is the starting row in the node schedules of the current band
+ * root is set if this graph is the original dependence graph,
+ * without any splitting
+ *
+ * sorted contains a list of node indices sorted according to the
+ * SCC to which a node belongs
+ *
+ * n_edge is the number of edges
+ * edge is the list of edges
+ * max_edge contains the maximal number of edges of each type;
+ * in particular, it contains the number of edges in the inital graph.
+ * edge_table contains pointers into the edge array, hashed on the source
+ * 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 of the
+ * sets of dependences
+ *
+ * node_table contains pointers into the node array, hashed on the space
+ *
+ * region contains a list of variable sequences that should be non-trivial
+ *
+ * lp contains the (I)LP problem used to obtain new schedule rows
+ *
+ * src_scc and dst_scc are the source and sink SCCs of an edge with
+ * conflicting constraints
+ *
+ * scc represents the number of components
+ */
+struct isl_sched_graph {
+ isl_map_to_basic_set *intra_hmap;
+ isl_map_to_basic_set *inter_hmap;
+
+ struct isl_sched_node *node;
+ int n;
+ int maxvar;
+ int max_row;
+ int n_row;
+
+ int *sorted;
+
+ int n_band;
+ int n_total_row;
+ int band_start;
+
+ int root;
+
+ struct isl_sched_edge *edge;
+ int n_edge;
+ int max_edge[isl_edge_last + 1];
+ struct isl_hash_table *edge_table[isl_edge_last + 1];
+
+ struct isl_hash_table *node_table;
+ struct isl_region *region;
+
+ isl_basic_set *lp;
+
+ int src_scc;
+ int dst_scc;
+
+ int scc;
+};
+
+/* Initialize node_table based on the list of nodes.
+ */
+static int graph_init_table(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+
+ graph->node_table = isl_hash_table_alloc(ctx, graph->n);
+ if (!graph->node_table)
+ return -1;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_hash_table_entry *entry;
+ uint32_t hash;
+
+ hash = isl_space_get_hash(graph->node[i].space);
+ entry = isl_hash_table_find(ctx, graph->node_table, hash,
+ &node_has_space,
+ graph->node[i].space, 1);
+ if (!entry)
+ return -1;
+ entry->data = &graph->node[i];
+ }
+
+ return 0;
+}
+
+/* Return a pointer to the node that lives within the given space,
+ * or NULL if there is no such node.
+ */
+static struct isl_sched_node *graph_find_node(isl_ctx *ctx,
+ struct isl_sched_graph *graph, __isl_keep isl_space *dim)
+{
+ struct isl_hash_table_entry *entry;
+ uint32_t hash;
+
+ hash = isl_space_get_hash(dim);
+ entry = isl_hash_table_find(ctx, graph->node_table, hash,
+ &node_has_space, dim, 0);
+
+ return entry ? entry->data : NULL;
+}
+
+static int edge_has_src_and_dst(const void *entry, const void *val)
+{
+ const struct isl_sched_edge *edge = entry;
+ const struct isl_sched_edge *temp = val;
+
+ return edge->src == temp->src && edge->dst == temp->dst;
+}
+
+/* Add the given edge to graph->edge_table[type].
+ */
+static int graph_edge_table_add(isl_ctx *ctx, struct isl_sched_graph *graph,
+ enum isl_edge_type type, struct isl_sched_edge *edge)
+{
+ struct isl_hash_table_entry *entry;
+ uint32_t hash;
+
+ hash = isl_hash_init();
+ hash = isl_hash_builtin(hash, edge->src);
+ hash = isl_hash_builtin(hash, edge->dst);
+ entry = isl_hash_table_find(ctx, graph->edge_table[type], hash,
+ &edge_has_src_and_dst, edge, 1);
+ if (!entry)
+ return -1;
+ entry->data = edge;
+
+ return 0;
+}
+
+/* Allocate the edge_tables based on the maximal number of edges of
+ * each type.
+ */
+static int graph_init_edge_tables(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+
+ for (i = 0; i <= isl_edge_last; ++i) {
+ graph->edge_table[i] = isl_hash_table_alloc(ctx,
+ graph->max_edge[i]);
+ if (!graph->edge_table[i])
+ return -1;
+ }
+
+ return 0;
+}
+
+/* If graph->edge_table[type] contains an edge from the given source
+ * to the given destination, then return the hash table entry of this edge.
+ * Otherwise, return NULL.
+ */
+static struct isl_hash_table_entry *graph_find_edge_entry(
+ struct isl_sched_graph *graph,
+ enum isl_edge_type type,
+ struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+ isl_ctx *ctx = isl_space_get_ctx(src->space);
+ uint32_t hash;
+ struct isl_sched_edge temp = { .src = src, .dst = dst };
+
+ hash = isl_hash_init();
+ hash = isl_hash_builtin(hash, temp.src);
+ hash = isl_hash_builtin(hash, temp.dst);
+ return isl_hash_table_find(ctx, graph->edge_table[type], hash,
+ &edge_has_src_and_dst, &temp, 0);
+}
+
+
+/* If graph->edge_table[type] contains an edge from the given source
+ * to the given destination, then return this edge.
+ * Otherwise, return NULL.
+ */
+static struct isl_sched_edge *graph_find_edge(struct isl_sched_graph *graph,
+ enum isl_edge_type type,
+ struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+ struct isl_hash_table_entry *entry;
+
+ entry = graph_find_edge_entry(graph, type, src, dst);
+ if (!entry)
+ return NULL;
+
+ return entry->data;
+}
+
+/* Check whether the dependence graph has an edge of the given type
+ * between the given two nodes.
+ */
+static int graph_has_edge(struct isl_sched_graph *graph,
+ enum isl_edge_type type,
+ struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+ struct isl_sched_edge *edge;
+ int empty;
+
+ edge = graph_find_edge(graph, type, src, dst);
+ if (!edge)
+ return 0;
+
+ empty = isl_map_plain_is_empty(edge->map);
+ if (empty < 0)
+ return -1;
+
+ return !empty;
+}
+
+/* Look for any edge with the same src, dst and map fields as "model".
+ *
+ * Return the matching edge if one can be found.
+ * Return "model" if no matching edge is found.
+ * Return NULL on error.
+ */
+static struct isl_sched_edge *graph_find_matching_edge(
+ struct isl_sched_graph *graph, struct isl_sched_edge *model)
+{
+ enum isl_edge_type i;
+ struct isl_sched_edge *edge;
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ int is_equal;
+
+ edge = graph_find_edge(graph, i, model->src, model->dst);
+ if (!edge)
+ continue;
+ is_equal = isl_map_plain_is_equal(model->map, edge->map);
+ if (is_equal < 0)
+ return NULL;
+ if (is_equal)
+ return edge;
+ }
+
+ return model;
+}
+
+/* Remove the given edge from all the edge_tables that refer to it.
+ */
+static void graph_remove_edge(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge)
+{
+ isl_ctx *ctx = isl_map_get_ctx(edge->map);
+ enum isl_edge_type i;
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ struct isl_hash_table_entry *entry;
+
+ entry = graph_find_edge_entry(graph, i, edge->src, edge->dst);
+ if (!entry)
+ continue;
+ if (entry->data != edge)
+ continue;
+ isl_hash_table_remove(ctx, graph->edge_table[i], entry);
+ }
+}
+
+/* Check whether the dependence graph has any edge
+ * between the given two nodes.
+ */
+static int graph_has_any_edge(struct isl_sched_graph *graph,
+ struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+ enum isl_edge_type i;
+ int r;
+
+ for (i = isl_edge_first; i <= isl_edge_last; ++i) {
+ r = graph_has_edge(graph, i, src, dst);
+ if (r < 0 || r)
+ return r;
+ }
+
+ return r;
+}
+
+/* Check whether the dependence graph has a validity edge
+ * between the given two nodes.
+ *
+ * Conditional validity edges are essentially validity edges that
+ * can be ignored if the corresponding condition edges are iteration private.
+ * Here, we are only checking for the presence of validity
+ * edges, so we need to consider the conditional validity edges too.
+ * In particular, this function is used during the detection
+ * of strongly connected components and we cannot ignore
+ * conditional validity edges during this detection.
+ */
+static int graph_has_validity_edge(struct isl_sched_graph *graph,
+ struct isl_sched_node *src, struct isl_sched_node *dst)
+{
+ int r;
+
+ r = graph_has_edge(graph, isl_edge_validity, src, dst);
+ if (r < 0 || r)
+ return r;
+
+ return graph_has_edge(graph, isl_edge_conditional_validity, src, dst);
+}
+
+static int graph_alloc(isl_ctx *ctx, struct isl_sched_graph *graph,
+ int n_node, int n_edge)
+{
+ int i;
+
+ graph->n = n_node;
+ graph->n_edge = n_edge;
+ graph->node = isl_calloc_array(ctx, struct isl_sched_node, graph->n);
+ graph->sorted = isl_calloc_array(ctx, int, graph->n);
+ graph->region = isl_alloc_array(ctx, struct isl_region, graph->n);
+ graph->edge = isl_calloc_array(ctx,
+ struct isl_sched_edge, graph->n_edge);
+
+ graph->intra_hmap = isl_map_to_basic_set_alloc(ctx, 2 * n_edge);
+ graph->inter_hmap = isl_map_to_basic_set_alloc(ctx, 2 * n_edge);
+
+ if (!graph->node || !graph->region || (graph->n_edge && !graph->edge) ||
+ !graph->sorted)
+ return -1;
+
+ for(i = 0; i < graph->n; ++i)
+ graph->sorted[i] = i;
+
+ return 0;
+}
+
+static void graph_free(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+
+ isl_map_to_basic_set_free(graph->intra_hmap);
+ isl_map_to_basic_set_free(graph->inter_hmap);
+
+ if (graph->node)
+ for (i = 0; i < graph->n; ++i) {
+ isl_space_free(graph->node[i].space);
+ isl_set_free(graph->node[i].hull);
+ isl_multi_aff_free(graph->node[i].compress);
+ isl_multi_aff_free(graph->node[i].decompress);
+ isl_mat_free(graph->node[i].sched);
+ isl_map_free(graph->node[i].sched_map);
+ isl_mat_free(graph->node[i].cmap);
+ isl_mat_free(graph->node[i].cinv);
+ if (graph->root) {
+ free(graph->node[i].band);
+ free(graph->node[i].band_id);
+ free(graph->node[i].coincident);
+ }
+ }
+ free(graph->node);
+ free(graph->sorted);
+ if (graph->edge)
+ for (i = 0; i < graph->n_edge; ++i) {
+ isl_map_free(graph->edge[i].map);
+ isl_union_map_free(graph->edge[i].tagged_condition);
+ isl_union_map_free(graph->edge[i].tagged_validity);
+ }
+ free(graph->edge);
+ free(graph->region);
+ for (i = 0; i <= isl_edge_last; ++i)
+ isl_hash_table_free(ctx, graph->edge_table[i]);
+ isl_hash_table_free(ctx, graph->node_table);
+ isl_basic_set_free(graph->lp);
+}
+
+/* For each "set" on which this function is called, increment
+ * graph->n by one and update graph->maxvar.
+ */
+static int init_n_maxvar(__isl_take isl_set *set, void *user)
+{
+ struct isl_sched_graph *graph = user;
+ int nvar = isl_set_dim(set, isl_dim_set);
+
+ graph->n++;
+ if (nvar > graph->maxvar)
+ graph->maxvar = nvar;
+
+ isl_set_free(set);
+
+ return 0;
+}
+
+/* Add the number of basic maps in "map" to *n.
+ */
+static int add_n_basic_map(__isl_take isl_map *map, void *user)
+{
+ int *n = user;
+
+ *n += isl_map_n_basic_map(map);
+ isl_map_free(map);
+
+ return 0;
+}
+
+/* Compute the number of rows that should be allocated for the schedule.
+ * The graph can be split at most "n - 1" times, there can be at most
+ * one row for each dimension in the iteration domains plus two rows
+ * for each basic map in the dependences (in particular,
+ * we usually have one row, but it may be split by split_scaled),
+ * and there can be one extra row for ordering the statements.
+ * Note that if we have actually split "n - 1" times, then no ordering
+ * is needed, so in principle we could use "graph->n + 2 * graph->maxvar - 1".
+ * It is also practically impossible to exhaust both the number of dependences
+ * and the number of variables.
+ */
+static int compute_max_row(struct isl_sched_graph *graph,
+ __isl_keep isl_schedule_constraints *sc)
+{
+ enum isl_edge_type i;
+ int n_edge;
+
+ graph->n = 0;
+ graph->maxvar = 0;
+ if (isl_union_set_foreach_set(sc->domain, &init_n_maxvar, graph) < 0)
+ return -1;
+ n_edge = 0;
+ for (i = isl_edge_first; i <= isl_edge_last; ++i)
+ if (isl_union_map_foreach_map(sc->constraint[i],
+ &add_n_basic_map, &n_edge) < 0)
+ return -1;
+ graph->max_row = graph->n + 2 * n_edge + graph->maxvar;
+
+ return 0;
+}
+
+/* Does "bset" have any defining equalities for its set variables?
+ */
+static int has_any_defining_equality(__isl_keep isl_basic_set *bset)
+{
+ int i, n;
+
+ if (!bset)
+ return -1;
+
+ n = isl_basic_set_dim(bset, isl_dim_set);
+ for (i = 0; i < n; ++i) {
+ int has;
+
+ has = isl_basic_set_has_defining_equality(bset, isl_dim_set, i,
+ NULL);
+ if (has < 0 || has)
+ return has;
+ }
+
+ return 0;
+}
+
+/* Add a new node to the graph representing the given space.
+ * "nvar" is the (possibly compressed) number of variables and
+ * may be smaller than then number of set variables in "space"
+ * if "compressed" is set.
+ * If "compressed" is set, then "hull" represents the constraints
+ * that were used to derive the compression, while "compress" and
+ * "decompress" map the original space to the compressed space and
+ * vice versa.
+ * If "compressed" is not set, then "hull", "compress" and "decompress"
+ * should be NULL.
+ */
+static int add_node(struct isl_sched_graph *graph, __isl_take isl_space *space,
+ int nvar, int compressed, __isl_take isl_set *hull,
+ __isl_take isl_multi_aff *compress,
+ __isl_take isl_multi_aff *decompress)
+{
+ int nparam;
+ isl_ctx *ctx;
+ isl_mat *sched;
+ int *band, *band_id, *coincident;
+
+ if (!space)
+ return -1;
+
+ ctx = isl_space_get_ctx(space);
+ nparam = isl_space_dim(space, isl_dim_param);
+ if (!ctx->opt->schedule_parametric)
+ nparam = 0;
+ sched = isl_mat_alloc(ctx, 0, 1 + nparam + nvar);
+ graph->node[graph->n].space = space;
+ graph->node[graph->n].nvar = nvar;
+ graph->node[graph->n].nparam = nparam;
+ graph->node[graph->n].sched = sched;
+ graph->node[graph->n].sched_map = NULL;
+ band = isl_alloc_array(ctx, int, graph->max_row);
+ graph->node[graph->n].band = band;
+ band_id = isl_calloc_array(ctx, int, graph->max_row);
+ graph->node[graph->n].band_id = band_id;
+ coincident = isl_calloc_array(ctx, int, graph->max_row);
+ graph->node[graph->n].coincident = coincident;
+ graph->node[graph->n].compressed = compressed;
+ graph->node[graph->n].hull = hull;
+ graph->node[graph->n].compress = compress;
+ graph->node[graph->n].decompress = decompress;
+ graph->n++;
+
+ if (!space || !sched ||
+ (graph->max_row && (!band || !band_id || !coincident)))
+ return -1;
+ if (compressed && (!hull || !compress || !decompress))
+ return -1;
+
+ return 0;
+}
+
+/* Add a new node to the graph representing the given set.
+ *
+ * If any of the set variables is defined by an equality, then
+ * we perform variable compression such that we can perform
+ * the scheduling on the compressed domain.
+ */
+static int extract_node(__isl_take isl_set *set, void *user)
+{
+ int nvar;
+ int has_equality;
+ isl_space *space;
+ isl_basic_set *hull;
+ isl_set *hull_set;
+ isl_morph *morph;
+ isl_multi_aff *compress, *decompress;
+ struct isl_sched_graph *graph = user;
+
+ space = isl_set_get_space(set);
+ hull = isl_set_affine_hull(set);
+ hull = isl_basic_set_remove_divs(hull);
+ nvar = isl_space_dim(space, isl_dim_set);
+ has_equality = has_any_defining_equality(hull);
+
+ if (has_equality < 0)
+ goto error;
+ if (!has_equality) {
+ isl_basic_set_free(hull);
+ return add_node(graph, space, nvar, 0, NULL, NULL, NULL);
+ }
+
+ morph = isl_basic_set_variable_compression(hull, isl_dim_set);
+ nvar = isl_morph_ran_dim(morph, isl_dim_set);
+ compress = isl_morph_get_var_multi_aff(morph);
+ morph = isl_morph_inverse(morph);
+ decompress = isl_morph_get_var_multi_aff(morph);
+ isl_morph_free(morph);
+
+ hull_set = isl_set_from_basic_set(hull);
+ return add_node(graph, space, nvar, 1, hull_set, compress, decompress);
+error:
+ isl_basic_set_free(hull);
+ isl_space_free(space);
+ return -1;
+}
+
+struct isl_extract_edge_data {
+ enum isl_edge_type type;
+ struct isl_sched_graph *graph;
+};
+
+/* 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,
+ 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;
+ isl_map_free(edge2->map);
+
+ if (type == isl_edge_condition) {
+ if (!edge1->tagged_condition)
+ edge1->tagged_condition = edge2->tagged_condition;
+ else
+ edge1->tagged_condition =
+ isl_union_map_union(edge1->tagged_condition,
+ edge2->tagged_condition);
+ }
+
+ if (type == isl_edge_conditional_validity) {
+ if (!edge1->tagged_validity)
+ edge1->tagged_validity = edge2->tagged_validity;
+ else
+ edge1->tagged_validity =
+ isl_union_map_union(edge1->tagged_validity,
+ edge2->tagged_validity);
+ }
+
+ if (type == isl_edge_condition && !edge1->tagged_condition)
+ return -1;
+ if (type == isl_edge_conditional_validity && !edge1->tagged_validity)
+ return -1;
+
+ return 0;
+}
+
+/* Insert dummy tags in domain and range of "map".
+ *
+ * In particular, if "map" is of the form
+ *
+ * A -> B
+ *
+ * then return
+ *
+ * [A -> dummy_tag] -> [B -> dummy_tag]
+ *
+ * where the dummy_tags are identical and equal to any dummy tags
+ * introduced by any other call to this function.
+ */
+static __isl_give isl_map *insert_dummy_tags(__isl_take isl_map *map)
+{
+ static char dummy;
+ isl_ctx *ctx;
+ isl_id *id;
+ isl_space *space;
+ isl_set *domain, *range;
+
+ ctx = isl_map_get_ctx(map);
+
+ id = isl_id_alloc(ctx, NULL, &dummy);
+ space = isl_space_params(isl_map_get_space(map));
+ space = isl_space_set_from_params(space);
+ space = isl_space_set_tuple_id(space, isl_dim_set, id);
+ space = isl_space_map_from_set(space);
+
+ domain = isl_map_wrap(map);
+ range = isl_map_wrap(isl_map_universe(space));
+ map = isl_map_from_domain_and_range(domain, range);
+ map = isl_map_zip(map);
+
+ return map;
+}
+
+/* Given that at least one of "src" or "dst" is compressed, return
+ * a map between the spaces of these nodes restricted to the affine
+ * hull that was used in the compression.
+ */
+static __isl_give isl_map *extract_hull(struct isl_sched_node *src,
+ struct isl_sched_node *dst)
+{
+ isl_set *dom, *ran;
+
+ if (src->compressed)
+ dom = isl_set_copy(src->hull);
+ else
+ dom = isl_set_universe(isl_space_copy(src->space));
+ if (dst->compressed)
+ ran = isl_set_copy(dst->hull);
+ else
+ ran = isl_set_universe(isl_space_copy(dst->space));
+
+ return isl_map_from_domain_and_range(dom, ran);
+}
+
+/* Intersect the domains of the nested relations in domain and range
+ * of "tagged" with "map".
+ */
+static __isl_give isl_map *map_intersect_domains(__isl_take isl_map *tagged,
+ __isl_keep isl_map *map)
+{
+ isl_set *set;
+
+ tagged = isl_map_zip(tagged);
+ set = isl_map_wrap(isl_map_copy(map));
+ tagged = isl_map_intersect_domain(tagged, set);
+ tagged = isl_map_zip(tagged);
+ return tagged;
+}
+
+/* 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
+ * to one of the dependence relations of a type that was added before,
+ * then we don't create a new edge, but instead mark the original edge
+ * as also representing a dependence of the current type.
+ *
+ * Edges of type isl_edge_condition or isl_edge_conditional_validity
+ * may be specified as "tagged" dependence relations. That is, "map"
+ * may contain elements (i -> a) -> (j -> b), where i -> j denotes
+ * the dependence on iterations and a and b are tags.
+ * edge->map is set to the relation containing the elements i -> j,
+ * while edge->tagged_condition and edge->tagged_validity contain
+ * the union of all the "map" relations
+ * for which extract_edge is called that result in the same edge->map.
+ *
+ * If the source or the destination node is compressed, then
+ * intersect both "map" and "tagged" with the constraints that
+ * were used to construct the compression.
+ * This ensures that there are no schedule constraints defined
+ * outside of these domains, while the scheduler no longer has
+ * any control over those outside parts.
+ */
+static int extract_edge(__isl_take isl_map *map, void *user)
+{
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ 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;
+
+ if (data->type == isl_edge_condition ||
+ data->type == isl_edge_conditional_validity) {
+ if (isl_map_can_zip(map)) {
+ tagged = isl_map_copy(map);
+ map = isl_set_unwrap(isl_map_domain(isl_map_zip(map)));
+ } else {
+ tagged = insert_dummy_tags(isl_map_copy(map));
+ }
+ }
+
+ 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);
+
+ if (!src || !dst) {
+ isl_map_free(map);
+ isl_map_free(tagged);
+ return 0;
+ }
+
+ if (src->compressed || dst->compressed) {
+ isl_map *hull;
+ hull = extract_hull(src, dst);
+ if (tagged)
+ tagged = map_intersect_domains(tagged, hull);
+ map = isl_map_intersect(map, hull);
+ }
+
+ 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].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;
+ 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;
+ 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) {
+ graph->n_edge++;
+ return -1;
+ }
+ if (edge == &graph->edge[graph->n_edge])
+ 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)
+ return -1;
+
+ return graph_edge_table_add(ctx, graph, data->type, edge);
+}
+
+/* Check whether there is any dependence from node[j] to node[i]
+ * or from node[i] to node[j].
+ */
+static int node_follows_weak(int i, int j, void *user)
+{
+ int f;
+ struct isl_sched_graph *graph = user;
+
+ f = graph_has_any_edge(graph, &graph->node[j], &graph->node[i]);
+ if (f < 0 || f)
+ return f;
+ return graph_has_any_edge(graph, &graph->node[i], &graph->node[j]);
+}
+
+/* Check whether there is a (conditional) validity dependence from node[j]
+ * to node[i], forcing node[i] to follow node[j].
+ */
+static int node_follows_strong(int i, int j, void *user)
+{
+ struct isl_sched_graph *graph = user;
+
+ return graph_has_validity_edge(graph, &graph->node[j], &graph->node[i]);
+}
+
+/* Use Tarjan's algorithm for computing the strongly connected components
+ * in the dependence graph (only validity edges).
+ * If weak is set, we consider the graph to be undirected and
+ * we effectively compute the (weakly) connected components.
+ * Additionally, we also consider other edges when weak is set.
+ */
+static int detect_ccs(isl_ctx *ctx, struct isl_sched_graph *graph, int weak)
+{
+ int i, n;
+ struct isl_tarjan_graph *g = NULL;
+
+ g = isl_tarjan_graph_init(ctx, graph->n,
+ weak ? &node_follows_weak : &node_follows_strong, graph);
+ if (!g)
+ return -1;
+
+ graph->scc = 0;
+ i = 0;
+ n = graph->n;
+ while (n) {
+ while (g->order[i] != -1) {
+ graph->node[g->order[i]].scc = graph->scc;
+ --n;
+ ++i;
+ }
+ ++i;
+ graph->scc++;
+ }
+
+ isl_tarjan_graph_free(g);
+
+ return 0;
+}
+
+/* Apply Tarjan's algorithm to detect the strongly connected components
+ * in the dependence graph.
+ */
+static int detect_sccs(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ return detect_ccs(ctx, graph, 0);
+}
+
+/* Apply Tarjan's algorithm to detect the (weakly) connected components
+ * in the dependence graph.
+ */
+static int detect_wccs(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ return detect_ccs(ctx, graph, 1);
+}
+
+static int cmp_scc(const void *a, const void *b, void *data)
+{
+ struct isl_sched_graph *graph = data;
+ const int *i1 = a;
+ const int *i2 = b;
+
+ return graph->node[*i1].scc - graph->node[*i2].scc;
+}
+
+/* Sort the elements of graph->sorted according to the corresponding SCCs.
+ */
+static int sort_sccs(struct isl_sched_graph *graph)
+{
+ return isl_sort(graph->sorted, graph->n, sizeof(int), &cmp_scc, graph);
+}
+
+/* Given a dependence relation R from "node" to itself,
+ * construct the set of coefficients of valid constraints for elements
+ * in that dependence relation.
+ * In particular, the result contains tuples of coefficients
+ * c_0, c_n, c_x such that
+ *
+ * c_0 + c_n n + c_x y - c_x x >= 0 for each (x,y) in R
+ *
+ * or, equivalently,
+ *
+ * c_0 + c_n n + c_x d >= 0 for each d in delta R = { y - x | (x,y) in R }
+ *
+ * We choose here to compute the dual of delta R.
+ * Alternatively, we could have computed the dual of R, resulting
+ * in a set of tuples c_0, c_n, c_x, c_y, and then
+ * plugged in (c_0, c_n, c_x, -c_x).
+ *
+ * If "node" has been compressed, then the dependence relation
+ * is also compressed before the set of coefficients is computed.
+ */
+static __isl_give isl_basic_set *intra_coefficients(
+ struct isl_sched_graph *graph, struct isl_sched_node *node,
+ __isl_take isl_map *map)
+{
+ isl_set *delta;
+ isl_map *key;
+ isl_basic_set *coef;
+
+ if (isl_map_to_basic_set_has(graph->intra_hmap, map))
+ return isl_map_to_basic_set_get(graph->intra_hmap, map);
+
+ key = isl_map_copy(map);
+ if (node->compressed) {
+ map = isl_map_preimage_domain_multi_aff(map,
+ isl_multi_aff_copy(node->decompress));
+ map = isl_map_preimage_range_multi_aff(map,
+ isl_multi_aff_copy(node->decompress));
+ }
+ delta = isl_set_remove_divs(isl_map_deltas(map));
+ coef = isl_set_coefficients(delta);
+ graph->intra_hmap = isl_map_to_basic_set_set(graph->intra_hmap, key,
+ isl_basic_set_copy(coef));
+
+ return coef;
+}
+
+/* Given a dependence relation R, construct the set of coefficients
+ * of valid constraints for elements in that dependence relation.
+ * In particular, the result contains tuples of coefficients
+ * c_0, c_n, c_x, c_y such that
+ *
+ * c_0 + c_n n + c_x x + c_y y >= 0 for each (x,y) in R
+ *
+ * If the source or destination nodes of "edge" have been compressed,
+ * then the dependence relation is also compressed before
+ * the set of coefficients is computed.
+ */
+static __isl_give isl_basic_set *inter_coefficients(
+ struct isl_sched_graph *graph, struct isl_sched_edge *edge,
+ __isl_take isl_map *map)
+{
+ isl_set *set;
+ isl_map *key;
+ isl_basic_set *coef;
+
+ if (isl_map_to_basic_set_has(graph->inter_hmap, map))
+ return isl_map_to_basic_set_get(graph->inter_hmap, map);
+
+ key = isl_map_copy(map);
+ if (edge->src->compressed)
+ map = isl_map_preimage_domain_multi_aff(map,
+ isl_multi_aff_copy(edge->src->decompress));
+ if (edge->dst->compressed)
+ map = isl_map_preimage_range_multi_aff(map,
+ isl_multi_aff_copy(edge->dst->decompress));
+ set = isl_map_wrap(isl_map_remove_divs(map));
+ coef = isl_set_coefficients(set);
+ graph->inter_hmap = isl_map_to_basic_set_set(graph->inter_hmap, key,
+ isl_basic_set_copy(coef));
+
+ return coef;
+}
+
+/* Add constraints to graph->lp that force validity for the given
+ * dependence from a node i to itself.
+ * That is, add constraints that enforce
+ *
+ * (c_i_0 + c_i_n n + c_i_x y) - (c_i_0 + c_i_n n + c_i_x x)
+ * = c_i_x (y - x) >= 0
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x)
+ * of valid constraints for (y - x) and then plug in (0, 0, c_i_x^+ - c_i_x^-),
+ * where c_i_x = c_i_x^+ - c_i_x^-, with c_i_x^+ and c_i_x^- non-negative.
+ * In graph->lp, the c_i_x^- appear before their c_i_x^+ counterpart.
+ *
+ * Actually, we do not construct constraints for the c_i_x themselves,
+ * but for the coefficients of c_i_x written as a linear combination
+ * of the columns in node->cmap.
+ */
+static int add_intra_validity_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge)
+{
+ unsigned total;
+ isl_map *map = isl_map_copy(edge->map);
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *node = edge->src;
+
+ coef = intra_coefficients(graph, node, map);
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set), isl_mat_copy(node->cmap));
+ if (!coef)
+ goto error;
+
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, -1);
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, 1);
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ isl_space_free(dim);
+
+ return 0;
+error:
+ isl_space_free(dim);
+ return -1;
+}
+
+/* Add constraints to graph->lp that force validity for the given
+ * dependence from node i to node j.
+ * That is, add constraints that enforce
+ *
+ * (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x) >= 0
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x, c_y)
+ * of valid constraints for R and then plug in
+ * (c_j_0 - c_i_0, c_j_n^+ - c_j_n^- - (c_i_n^+ - c_i_n^-),
+ * c_j_x^+ - c_j_x^- - (c_i_x^+ - c_i_x^-)),
+ * where c_* = c_*^+ - c_*^-, with c_*^+ and c_*^- non-negative.
+ * In graph->lp, the c_*^- appear before their c_*^+ counterpart.
+ *
+ * Actually, we do not construct constraints for the c_*_x themselves,
+ * but for the coefficients of c_*_x written as a linear combination
+ * of the columns in node->cmap.
+ */
+static int add_inter_validity_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge)
+{
+ unsigned total;
+ isl_map *map = isl_map_copy(edge->map);
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *src = edge->src;
+ struct isl_sched_node *dst = edge->dst;
+
+ coef = inter_coefficients(graph, edge, map);
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set), isl_mat_copy(src->cmap));
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set) + src->nvar,
+ isl_mat_copy(dst->cmap));
+ if (!coef)
+ goto error;
+
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+
+ isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, 1);
+ isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, -1);
+ isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, 1);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, -1);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, 1);
+
+ isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, -1);
+ isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, 1);
+ isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, -1);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, 1);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, -1);
+
+ edge->start = graph->lp->n_ineq;
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ if (!graph->lp)
+ goto error;
+ isl_space_free(dim);
+ edge->end = graph->lp->n_ineq;
+
+ return 0;
+error:
+ isl_space_free(dim);
+ return -1;
+}
+
+/* Add constraints to graph->lp that bound the dependence distance for the given
+ * dependence from a node i to itself.
+ * If s = 1, we add the constraint
+ *
+ * c_i_x (y - x) <= m_0 + m_n n
+ *
+ * or
+ *
+ * -c_i_x (y - x) + m_0 + m_n n >= 0
+ *
+ * for each (x,y) in R.
+ * If s = -1, we add the constraint
+ *
+ * -c_i_x (y - x) <= m_0 + m_n n
+ *
+ * or
+ *
+ * c_i_x (y - x) + m_0 + m_n n >= 0
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x)
+ * of valid constraints for (y - x) and then plug in (m_0, m_n, -s * c_i_x),
+ * with each coefficient (except m_0) represented as a pair of non-negative
+ * coefficients.
+ *
+ * Actually, we do not construct constraints for the c_i_x themselves,
+ * but for the coefficients of c_i_x written as a linear combination
+ * of the columns in node->cmap.
+ *
+ *
+ * If "local" is set, then we add constraints
+ *
+ * c_i_x (y - x) <= 0
+ *
+ * or
+ *
+ * -c_i_x (y - x) <= 0
+ *
+ * instead, forcing the dependence distance to be (less than or) equal to 0.
+ * That is, we plug in (0, 0, -s * c_i_x),
+ * Note that dependences marked local are treated as validity constraints
+ * by add_all_validity_constraints and therefore also have
+ * their distances bounded by 0 from below.
+ */
+static int add_intra_proximity_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge, int s, int local)
+{
+ unsigned total;
+ unsigned nparam;
+ isl_map *map = isl_map_copy(edge->map);
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *node = edge->src;
+
+ coef = intra_coefficients(graph, node, map);
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set), isl_mat_copy(node->cmap));
+ if (!coef)
+ goto error;
+
+ nparam = isl_space_dim(node->space, isl_dim_param);
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+
+ if (!local) {
+ isl_dim_map_range(dim_map, 1, 0, 0, 0, 1, 1);
+ isl_dim_map_range(dim_map, 4, 2, 1, 1, nparam, -1);
+ isl_dim_map_range(dim_map, 5, 2, 1, 1, nparam, 1);
+ }
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, s);
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, -s);
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ isl_space_free(dim);
+
+ return 0;
+error:
+ isl_space_free(dim);
+ return -1;
+}
+
+/* Add constraints to graph->lp that bound the dependence distance for the given
+ * dependence from node i to node j.
+ * If s = 1, we add the constraint
+ *
+ * (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x)
+ * <= m_0 + m_n n
+ *
+ * or
+ *
+ * -(c_j_0 + c_j_n n + c_j_x y) + (c_i_0 + c_i_n n + c_i_x x) +
+ * m_0 + m_n n >= 0
+ *
+ * for each (x,y) in R.
+ * If s = -1, we add the constraint
+ *
+ * -((c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x))
+ * <= m_0 + m_n n
+ *
+ * or
+ *
+ * (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x) +
+ * m_0 + m_n n >= 0
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x, c_y)
+ * of valid constraints for R and then plug in
+ * (m_0 - s*c_j_0 + s*c_i_0, m_n - s*c_j_n + s*c_i_n,
+ * -s*c_j_x+s*c_i_x)
+ * with each coefficient (except m_0, c_j_0 and c_i_0)
+ * represented as a pair of non-negative coefficients.
+ *
+ * Actually, we do not construct constraints for the c_*_x themselves,
+ * but for the coefficients of c_*_x written as a linear combination
+ * of the columns in node->cmap.
+ *
+ *
+ * If "local" is set, then we add constraints
+ *
+ * (c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x) <= 0
+ *
+ * or
+ *
+ * -((c_j_0 + c_j_n n + c_j_x y) - (c_i_0 + c_i_n n + c_i_x x)) <= 0
+ *
+ * instead, forcing the dependence distance to be (less than or) equal to 0.
+ * That is, we plug in
+ * (-s*c_j_0 + s*c_i_0, -s*c_j_n + s*c_i_n, -s*c_j_x+s*c_i_x).
+ * Note that dependences marked local are treated as validity constraints
+ * by add_all_validity_constraints and therefore also have
+ * their distances bounded by 0 from below.
+ */
+static int add_inter_proximity_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge, int s, int local)
+{
+ unsigned total;
+ unsigned nparam;
+ isl_map *map = isl_map_copy(edge->map);
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *src = edge->src;
+ struct isl_sched_node *dst = edge->dst;
+
+ coef = inter_coefficients(graph, edge, map);
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set), isl_mat_copy(src->cmap));
+ coef = isl_basic_set_transform_dims(coef, isl_dim_set,
+ isl_space_dim(dim, isl_dim_set) + src->nvar,
+ isl_mat_copy(dst->cmap));
+ if (!coef)
+ goto error;
+
+ nparam = isl_space_dim(src->space, isl_dim_param);
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+
+ if (!local) {
+ isl_dim_map_range(dim_map, 1, 0, 0, 0, 1, 1);
+ isl_dim_map_range(dim_map, 4, 2, 1, 1, nparam, -1);
+ isl_dim_map_range(dim_map, 5, 2, 1, 1, nparam, 1);
+ }
+
+ isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, -s);
+ isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, s);
+ isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, -s);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, s);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, -s);
+
+ isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, s);
+ isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, -s);
+ isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, s);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, -s);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, s);
+
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ isl_space_free(dim);
+
+ return 0;
+error:
+ isl_space_free(dim);
+ return -1;
+}
+
+/* Add all validity constraints to graph->lp.
+ *
+ * An edge that is forced to be local needs to have its dependence
+ * distances equal to zero. We take care of bounding them by 0 from below
+ * here. add_all_proximity_constraints takes care of bounding them by 0
+ * from above.
+ *
+ * If "use_coincidence" is set, then we treat coincidence edges as local edges.
+ * Otherwise, we ignore them.
+ */
+static int add_all_validity_constraints(struct isl_sched_graph *graph,
+ int use_coincidence)
+{
+ int i;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge= &graph->edge[i];
+ int local;
+
+ local = edge->local || (edge->coincidence && use_coincidence);
+ if (!edge->validity && !local)
+ continue;
+ if (edge->src != edge->dst)
+ continue;
+ if (add_intra_validity_constraints(graph, edge) < 0)
+ return -1;
+ }
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge = &graph->edge[i];
+ int local;
+
+ local = edge->local || (edge->coincidence && use_coincidence);
+ if (!edge->validity && !local)
+ continue;
+ if (edge->src == edge->dst)
+ continue;
+ if (add_inter_validity_constraints(graph, edge) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Add constraints to graph->lp that bound the dependence distance
+ * for all dependence relations.
+ * If a given proximity dependence is identical to a validity
+ * dependence, then the dependence distance is already bounded
+ * from below (by zero), so we only need to bound the distance
+ * from above. (This includes the case of "local" dependences
+ * which are treated as validity dependence by add_all_validity_constraints.)
+ * Otherwise, we need to bound the distance both from above and from below.
+ *
+ * If "use_coincidence" is set, then we treat coincidence edges as local edges.
+ * Otherwise, we ignore them.
+ */
+static int add_all_proximity_constraints(struct isl_sched_graph *graph,
+ int use_coincidence)
+{
+ int i;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge= &graph->edge[i];
+ int local;
+
+ local = edge->local || (edge->coincidence && use_coincidence);
+ if (!edge->proximity && !local)
+ continue;
+ if (edge->src == edge->dst &&
+ add_intra_proximity_constraints(graph, edge, 1, local) < 0)
+ return -1;
+ if (edge->src != edge->dst &&
+ add_inter_proximity_constraints(graph, edge, 1, local) < 0)
+ return -1;
+ if (edge->validity || local)
+ continue;
+ if (edge->src == edge->dst &&
+ add_intra_proximity_constraints(graph, edge, -1, 0) < 0)
+ return -1;
+ if (edge->src != edge->dst &&
+ add_inter_proximity_constraints(graph, edge, -1, 0) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Compute a basis for the rows in the linear part of the schedule
+ * and extend this basis to a full basis. The remaining rows
+ * can then be used to force linear independence from the rows
+ * in the schedule.
+ *
+ * In particular, given the schedule rows S, we compute
+ *
+ * S = H Q
+ * S U = H
+ *
+ * with H the Hermite normal form of S. That is, all but the
+ * first rank columns of H are zero and so each row in S is
+ * a linear combination of the first rank rows of Q.
+ * The matrix Q is then transposed because we will write the
+ * coefficients of the next schedule row as a column vector s
+ * and express this s as a linear combination s = Q c of the
+ * computed basis.
+ * Similarly, the matrix U is transposed such that we can
+ * compute the coefficients c = U s from a schedule row s.
+ */
+static int node_update_cmap(struct isl_sched_node *node)
+{
+ isl_mat *H, *U, *Q;
+ int n_row = isl_mat_rows(node->sched);
+
+ H = isl_mat_sub_alloc(node->sched, 0, n_row,
+ 1 + node->nparam, node->nvar);
+
+ H = isl_mat_left_hermite(H, 0, &U, &Q);
+ isl_mat_free(node->cmap);
+ isl_mat_free(node->cinv);
+ node->cmap = isl_mat_transpose(Q);
+ node->cinv = isl_mat_transpose(U);
+ node->rank = isl_mat_initial_non_zero_cols(H);
+ isl_mat_free(H);
+
+ if (!node->cmap || !node->cinv || node->rank < 0)
+ return -1;
+ return 0;
+}
+
+/* How many times should we count the constraints in "edge"?
+ *
+ * If carry is set, then we are counting the number of
+ * (validity or conditional validity) constraints that will be added
+ * in setup_carry_lp and we count each edge exactly once.
+ *
+ * Otherwise, we count as follows
+ * validity -> 1 (>= 0)
+ * validity+proximity -> 2 (>= 0 and upper bound)
+ * proximity -> 2 (lower and upper bound)
+ * local(+any) -> 2 (>= 0 and <= 0)
+ *
+ * If an edge is only marked conditional_validity then it counts
+ * as zero since it is only checked afterwards.
+ *
+ * If "use_coincidence" is set, then we treat coincidence edges as local edges.
+ * Otherwise, we ignore them.
+ */
+static int edge_multiplicity(struct isl_sched_edge *edge, int carry,
+ int use_coincidence)
+{
+ if (carry && !edge->validity && !edge->conditional_validity)
+ return 0;
+ if (carry)
+ return 1;
+ if (edge->proximity || edge->local)
+ return 2;
+ if (use_coincidence && edge->coincidence)
+ return 2;
+ if (edge->validity)
+ return 1;
+ return 0;
+}
+
+/* Count the number of equality and inequality constraints
+ * that will be added for the given map.
+ *
+ * "use_coincidence" is set if we should take into account coincidence edges.
+ */
+static int count_map_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge, __isl_take isl_map *map,
+ int *n_eq, int *n_ineq, int carry, int use_coincidence)
+{
+ isl_basic_set *coef;
+ int f = edge_multiplicity(edge, carry, use_coincidence);
+
+ if (f == 0) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ if (edge->src == edge->dst)
+ coef = intra_coefficients(graph, edge->src, map);
+ else
+ coef = inter_coefficients(graph, edge, map);
+ if (!coef)
+ return -1;
+ *n_eq += f * coef->n_eq;
+ *n_ineq += f * coef->n_ineq;
+ isl_basic_set_free(coef);
+
+ return 0;
+}
+
+/* Count the number of equality and inequality constraints
+ * that will be added to the main lp problem.
+ * We count as follows
+ * validity -> 1 (>= 0)
+ * validity+proximity -> 2 (>= 0 and upper bound)
+ * proximity -> 2 (lower and upper bound)
+ * local(+any) -> 2 (>= 0 and <= 0)
+ *
+ * If "use_coincidence" is set, then we treat coincidence edges as local edges.
+ * Otherwise, we ignore them.
+ */
+static int count_constraints(struct isl_sched_graph *graph,
+ int *n_eq, int *n_ineq, int use_coincidence)
+{
+ int i;
+
+ *n_eq = *n_ineq = 0;
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge= &graph->edge[i];
+ isl_map *map = isl_map_copy(edge->map);
+
+ if (count_map_constraints(graph, edge, map, n_eq, n_ineq,
+ 0, use_coincidence) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Count the number of constraints that will be added by
+ * add_bound_coefficient_constraints and increment *n_eq and *n_ineq
+ * accordingly.
+ *
+ * In practice, add_bound_coefficient_constraints only adds inequalities.
+ */
+static int count_bound_coefficient_constraints(isl_ctx *ctx,
+ struct isl_sched_graph *graph, int *n_eq, int *n_ineq)
+{
+ int i;
+
+ if (ctx->opt->schedule_max_coefficient == -1)
+ return 0;
+
+ for (i = 0; i < graph->n; ++i)
+ *n_ineq += 2 * graph->node[i].nparam + 2 * graph->node[i].nvar;
+
+ return 0;
+}
+
+/* Add constraints that bound the values of the variable and parameter
+ * coefficients of the schedule.
+ *
+ * The maximal value of the coefficients is defined by the option
+ * 'schedule_max_coefficient'.
+ */
+static int add_bound_coefficient_constraints(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ int i, j, k;
+ int max_coefficient;
+ int total;
+
+ max_coefficient = ctx->opt->schedule_max_coefficient;
+
+ if (max_coefficient == -1)
+ return 0;
+
+ total = isl_basic_set_total_dim(graph->lp);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ for (j = 0; j < 2 * node->nparam + 2 * node->nvar; ++j) {
+ int dim;
+ k = isl_basic_set_alloc_inequality(graph->lp);
+ if (k < 0)
+ return -1;
+ dim = 1 + node->start + 1 + j;
+ isl_seq_clr(graph->lp->ineq[k], 1 + total);
+ isl_int_set_si(graph->lp->ineq[k][dim], -1);
+ isl_int_set_si(graph->lp->ineq[k][0], max_coefficient);
+ }
+ }
+
+ return 0;
+}
+
+/* Construct an ILP problem for finding schedule coefficients
+ * that result in non-negative, but small dependence distances
+ * over all dependences.
+ * In particular, the dependence distances over proximity edges
+ * are bounded by m_0 + m_n n and we compute schedule coefficients
+ * with small values (preferably zero) of m_n and m_0.
+ *
+ * All variables of the ILP are non-negative. The actual coefficients
+ * may be negative, so each coefficient is represented as the difference
+ * of two non-negative variables. The negative part always appears
+ * immediately before the positive part.
+ * Other than that, the variables have the following order
+ *
+ * - sum of positive and negative parts of m_n coefficients
+ * - m_0
+ * - sum of positive and negative parts of all c_n coefficients
+ * (unconstrained when computing non-parametric schedules)
+ * - sum of positive and negative parts of all c_x coefficients
+ * - positive and negative parts of m_n coefficients
+ * - for each node
+ * - c_i_0
+ * - positive and negative parts of c_i_n (if parametric)
+ * - positive and negative parts of c_i_x
+ *
+ * The c_i_x are not represented directly, but through the columns of
+ * node->cmap. That is, the computed values are for variable t_i_x
+ * such that c_i_x = Q t_i_x with Q equal to node->cmap.
+ *
+ * The constraints are those from the edges plus two or three equalities
+ * to express the sums.
+ *
+ * If "use_coincidence" is set, then we treat coincidence edges as local edges.
+ * Otherwise, we ignore them.
+ */
+static int setup_lp(isl_ctx *ctx, struct isl_sched_graph *graph,
+ int use_coincidence)
+{
+ int i, j;
+ int k;
+ unsigned nparam;
+ unsigned total;
+ isl_space *dim;
+ int parametric;
+ int param_pos;
+ int n_eq, n_ineq;
+ int max_constant_term;
+
+ max_constant_term = ctx->opt->schedule_max_constant_term;
+
+ parametric = ctx->opt->schedule_parametric;
+ nparam = isl_space_dim(graph->node[0].space, isl_dim_param);
+ param_pos = 4;
+ total = param_pos + 2 * nparam;
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[graph->sorted[i]];
+ if (node_update_cmap(node) < 0)
+ return -1;
+ node->start = total;
+ total += 1 + 2 * (node->nparam + node->nvar);
+ }
+
+ if (count_constraints(graph, &n_eq, &n_ineq, use_coincidence) < 0)
+ return -1;
+ if (count_bound_coefficient_constraints(ctx, graph, &n_eq, &n_ineq) < 0)
+ return -1;
+
+ dim = isl_space_set_alloc(ctx, 0, total);
+ isl_basic_set_free(graph->lp);
+ n_eq += 2 + parametric;
+ if (max_constant_term != -1)
+ n_ineq += graph->n;
+
+ graph->lp = isl_basic_set_alloc_space(dim, 0, n_eq, n_ineq);
+
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][1], -1);
+ for (i = 0; i < 2 * nparam; ++i)
+ isl_int_set_si(graph->lp->eq[k][1 + param_pos + i], 1);
+
+ if (parametric) {
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][3], -1);
+ for (i = 0; i < graph->n; ++i) {
+ int pos = 1 + graph->node[i].start + 1;
+
+ for (j = 0; j < 2 * graph->node[i].nparam; ++j)
+ isl_int_set_si(graph->lp->eq[k][pos + j], 1);
+ }
+ }
+
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][4], -1);
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int pos = 1 + node->start + 1 + 2 * node->nparam;
+
+ for (j = 0; j < 2 * node->nvar; ++j)
+ isl_int_set_si(graph->lp->eq[k][pos + j], 1);
+ }
+
+ if (max_constant_term != -1)
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ k = isl_basic_set_alloc_inequality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->ineq[k], 1 + total);
+ isl_int_set_si(graph->lp->ineq[k][1 + node->start], -1);
+ isl_int_set_si(graph->lp->ineq[k][0], max_constant_term);
+ }
+
+ if (add_bound_coefficient_constraints(ctx, graph) < 0)
+ return -1;
+ if (add_all_validity_constraints(graph, use_coincidence) < 0)
+ return -1;
+ if (add_all_proximity_constraints(graph, use_coincidence) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Analyze the conflicting constraint found by
+ * isl_tab_basic_set_non_trivial_lexmin. If it corresponds to the validity
+ * constraint of one of the edges between distinct nodes, living, moreover
+ * in distinct SCCs, then record the source and sink SCC as this may
+ * be a good place to cut between SCCs.
+ */
+static int check_conflict(int con, void *user)
+{
+ int i;
+ struct isl_sched_graph *graph = user;
+
+ if (graph->src_scc >= 0)
+ return 0;
+
+ con -= graph->lp->n_eq;
+
+ if (con >= graph->lp->n_ineq)
+ return 0;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ if (!graph->edge[i].validity)
+ continue;
+ if (graph->edge[i].src == graph->edge[i].dst)
+ continue;
+ if (graph->edge[i].src->scc == graph->edge[i].dst->scc)
+ continue;
+ if (graph->edge[i].start > con)
+ continue;
+ if (graph->edge[i].end <= con)
+ continue;
+ graph->src_scc = graph->edge[i].src->scc;
+ graph->dst_scc = graph->edge[i].dst->scc;
+ }
+
+ return 0;
+}
+
+/* Check whether the next schedule row of the given node needs to be
+ * non-trivial. Lower-dimensional domains may have some trivial rows,
+ * but as soon as the number of remaining required non-trivial rows
+ * is as large as the number or remaining rows to be computed,
+ * all remaining rows need to be non-trivial.
+ */
+static int needs_row(struct isl_sched_graph *graph, struct isl_sched_node *node)
+{
+ return node->nvar - node->rank >= graph->maxvar - graph->n_row;
+}
+
+/* Solve the ILP problem constructed in setup_lp.
+ * For each node such that all the remaining rows of its schedule
+ * need to be non-trivial, we construct a non-triviality region.
+ * This region imposes that the next row is independent of previous rows.
+ * In particular the coefficients c_i_x are represented by t_i_x
+ * variables with c_i_x = Q t_i_x and Q a unimodular matrix such that
+ * its first columns span the rows of the previously computed part
+ * of the schedule. The non-triviality region enforces that at least
+ * one of the remaining components of t_i_x is non-zero, i.e.,
+ * that the new schedule row depends on at least one of the remaining
+ * columns of Q.
+ */
+static __isl_give isl_vec *solve_lp(struct isl_sched_graph *graph)
+{
+ int i;
+ isl_vec *sol;
+ isl_basic_set *lp;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int skip = node->rank;
+ graph->region[i].pos = node->start + 1 + 2*(node->nparam+skip);
+ if (needs_row(graph, node))
+ graph->region[i].len = 2 * (node->nvar - skip);
+ else
+ graph->region[i].len = 0;
+ }
+ lp = isl_basic_set_copy(graph->lp);
+ sol = isl_tab_basic_set_non_trivial_lexmin(lp, 2, graph->n,
+ graph->region, &check_conflict, graph);
+ return sol;
+}
+
+/* Update the schedules of all nodes based on the given solution
+ * of the LP problem.
+ * The new row is added to the current band.
+ * All possibly negative coefficients are encoded as a difference
+ * of two non-negative variables, so we need to perform the subtraction
+ * here. Moreover, if use_cmap is set, then the solution does
+ * not refer to the actual coefficients c_i_x, but instead to variables
+ * t_i_x such that c_i_x = Q t_i_x and Q is equal to node->cmap.
+ * In this case, we then also need to perform this multiplication
+ * to obtain the values of c_i_x.
+ *
+ * If coincident is set, then the caller guarantees that the new
+ * row satisfies the coincidence constraints.
+ */
+static int update_schedule(struct isl_sched_graph *graph,
+ __isl_take isl_vec *sol, int use_cmap, int coincident)
+{
+ int i, j;
+ isl_vec *csol = NULL;
+
+ if (!sol)
+ goto error;
+ if (sol->size == 0)
+ isl_die(sol->ctx, isl_error_internal,
+ "no solution found", goto error);
+ if (graph->n_total_row >= graph->max_row)
+ isl_die(sol->ctx, isl_error_internal,
+ "too many schedule rows", goto error);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int pos = node->start;
+ int row = isl_mat_rows(node->sched);
+
+ isl_vec_free(csol);
+ csol = isl_vec_alloc(sol->ctx, node->nvar);
+ if (!csol)
+ goto error;
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ node->sched = isl_mat_add_rows(node->sched, 1);
+ if (!node->sched)
+ goto error;
+ node->sched = isl_mat_set_element(node->sched, row, 0,
+ sol->el[1 + pos]);
+ for (j = 0; j < node->nparam + node->nvar; ++j)
+ isl_int_sub(sol->el[1 + pos + 1 + 2 * j + 1],
+ sol->el[1 + pos + 1 + 2 * j + 1],
+ sol->el[1 + pos + 1 + 2 * j]);
+ for (j = 0; j < node->nparam; ++j)
+ node->sched = isl_mat_set_element(node->sched,
+ row, 1 + j, sol->el[1+pos+1+2*j+1]);
+ for (j = 0; j < node->nvar; ++j)
+ isl_int_set(csol->el[j],
+ sol->el[1+pos+1+2*(node->nparam+j)+1]);
+ if (use_cmap)
+ csol = isl_mat_vec_product(isl_mat_copy(node->cmap),
+ csol);
+ if (!csol)
+ goto error;
+ for (j = 0; j < node->nvar; ++j)
+ node->sched = isl_mat_set_element(node->sched,
+ row, 1 + node->nparam + j, csol->el[j]);
+ node->band[graph->n_total_row] = graph->n_band;
+ node->coincident[graph->n_total_row] = coincident;
+ }
+ isl_vec_free(sol);
+ isl_vec_free(csol);
+
+ graph->n_row++;
+ graph->n_total_row++;
+
+ return 0;
+error:
+ isl_vec_free(sol);
+ isl_vec_free(csol);
+ return -1;
+}
+
+/* Convert row "row" of node->sched into an isl_aff living in "ls"
+ * and return this isl_aff.
+ */
+static __isl_give isl_aff *extract_schedule_row(__isl_take isl_local_space *ls,
+ struct isl_sched_node *node, int row)
+{
+ int j;
+ isl_int v;
+ isl_aff *aff;
+
+ isl_int_init(v);
+
+ aff = isl_aff_zero_on_domain(ls);
+ isl_mat_get_element(node->sched, row, 0, &v);
+ aff = isl_aff_set_constant(aff, v);
+ for (j = 0; j < node->nparam; ++j) {
+ isl_mat_get_element(node->sched, row, 1 + j, &v);
+ aff = isl_aff_set_coefficient(aff, isl_dim_param, j, v);
+ }
+ for (j = 0; j < node->nvar; ++j) {
+ isl_mat_get_element(node->sched, row, 1 + node->nparam + j, &v);
+ aff = isl_aff_set_coefficient(aff, isl_dim_in, j, v);
+ }
+
+ isl_int_clear(v);
+
+ return aff;
+}
+
+/* Convert node->sched into a multi_aff and return this multi_aff.
+ *
+ * The result is defined over the uncompressed node domain.
+ */
+static __isl_give isl_multi_aff *node_extract_schedule_multi_aff(
+ struct isl_sched_node *node)
+{
+ int i;
+ isl_space *space;
+ isl_local_space *ls;
+ isl_aff *aff;
+ isl_multi_aff *ma;
+ int nrow, ncol;
+
+ nrow = isl_mat_rows(node->sched);
+ ncol = isl_mat_cols(node->sched) - 1;
+ if (node->compressed)
+ space = isl_multi_aff_get_domain_space(node->decompress);
+ else
+ space = isl_space_copy(node->space);
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, nrow);
+ ma = isl_multi_aff_zero(space);
+
+ for (i = 0; i < nrow; ++i) {
+ aff = extract_schedule_row(isl_local_space_copy(ls), node, i);
+ ma = isl_multi_aff_set_aff(ma, i, aff);
+ }
+
+ isl_local_space_free(ls);
+
+ if (node->compressed)
+ ma = isl_multi_aff_pullback_multi_aff(ma,
+ isl_multi_aff_copy(node->compress));
+
+ return ma;
+}
+
+/* Convert node->sched into a map and return this map.
+ *
+ * The result is cached in node->sched_map, which needs to be released
+ * whenever node->sched is updated.
+ * It is defined over the uncompressed node domain.
+ */
+static __isl_give isl_map *node_extract_schedule(struct isl_sched_node *node)
+{
+ if (!node->sched_map) {
+ isl_multi_aff *ma;
+
+ ma = node_extract_schedule_multi_aff(node);
+ node->sched_map = isl_map_from_multi_aff(ma);
+ }
+
+ return isl_map_copy(node->sched_map);
+}
+
+/* Construct a map that can be used to update a dependence relation
+ * based on the current schedule.
+ * That is, construct a map expressing that source and sink
+ * are executed within the same iteration of the current schedule.
+ * This map can then be intersected with the dependence relation.
+ * This is not the most efficient way, but this shouldn't be a critical
+ * operation.
+ */
+static __isl_give isl_map *specializer(struct isl_sched_node *src,
+ struct isl_sched_node *dst)
+{
+ isl_map *src_sched, *dst_sched;
+
+ src_sched = node_extract_schedule(src);
+ dst_sched = node_extract_schedule(dst);
+ return isl_map_apply_range(src_sched, isl_map_reverse(dst_sched));
+}
+
+/* Intersect the domains of the nested relations in domain and range
+ * of "umap" with "map".
+ */
+static __isl_give isl_union_map *intersect_domains(
+ __isl_take isl_union_map *umap, __isl_keep isl_map *map)
+{
+ isl_union_set *uset;
+
+ umap = isl_union_map_zip(umap);
+ uset = isl_union_set_from_set(isl_map_wrap(isl_map_copy(map)));
+ umap = isl_union_map_intersect_domain(umap, uset);
+ umap = isl_union_map_zip(umap);
+ return umap;
+}
+
+/* Update the dependence relation of the given edge based
+ * on the current schedule.
+ * If the dependence is carried completely by the current schedule, then
+ * it is removed from the edge_tables. It is kept in the list of edges
+ * as otherwise all edge_tables would have to be recomputed.
+ */
+static int update_edge(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge)
+{
+ isl_map *id;
+
+ id = specializer(edge->src, edge->dst);
+ edge->map = isl_map_intersect(edge->map, isl_map_copy(id));
+ if (!edge->map)
+ goto error;
+
+ if (edge->tagged_condition) {
+ edge->tagged_condition =
+ intersect_domains(edge->tagged_condition, id);
+ if (!edge->tagged_condition)
+ goto error;
+ }
+ if (edge->tagged_validity) {
+ edge->tagged_validity =
+ intersect_domains(edge->tagged_validity, id);
+ if (!edge->tagged_validity)
+ goto error;
+ }
+
+ isl_map_free(id);
+ if (isl_map_plain_is_empty(edge->map))
+ graph_remove_edge(graph, edge);
+
+ return 0;
+error:
+ isl_map_free(id);
+ return -1;
+}
+
+/* Update the dependence relations of all edges based on the current schedule.
+ */
+static int update_edges(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+
+ for (i = graph->n_edge - 1; i >= 0; --i) {
+ if (update_edge(graph, &graph->edge[i]) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static void next_band(struct isl_sched_graph *graph)
+{
+ graph->band_start = graph->n_total_row;
+ graph->n_band++;
+}
+
+/* Topologically sort statements mapped to the same schedule iteration
+ * and add a row to the schedule corresponding to this order.
+ */
+static int sort_statements(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i, j;
+
+ if (graph->n <= 1)
+ return 0;
+
+ if (update_edges(ctx, graph) < 0)
+ return -1;
+
+ if (graph->n_edge == 0)
+ return 0;
+
+ if (detect_sccs(ctx, graph) < 0)
+ return -1;
+
+ if (graph->n_total_row >= graph->max_row)
+ isl_die(ctx, isl_error_internal,
+ "too many schedule rows", return -1);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int row = isl_mat_rows(node->sched);
+ int cols = isl_mat_cols(node->sched);
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ node->sched = isl_mat_add_rows(node->sched, 1);
+ if (!node->sched)
+ return -1;
+ node->sched = isl_mat_set_element_si(node->sched, row, 0,
+ node->scc);
+ for (j = 1; j < cols; ++j)
+ node->sched = isl_mat_set_element_si(node->sched,
+ row, j, 0);
+ node->band[graph->n_total_row] = graph->n_band;
+ }
+
+ graph->n_total_row++;
+ next_band(graph);
+
+ return 0;
+}
+
+/* Construct an isl_schedule based on the computed schedule stored
+ * in graph and with parameters specified by dim.
+ */
+static __isl_give isl_schedule *extract_schedule(struct isl_sched_graph *graph,
+ __isl_take isl_space *dim)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_schedule *sched = NULL;
+
+ if (!dim)
+ return NULL;
+
+ ctx = isl_space_get_ctx(dim);
+ sched = isl_calloc(ctx, struct isl_schedule,
+ sizeof(struct isl_schedule) +
+ (graph->n - 1) * sizeof(struct isl_schedule_node));
+ if (!sched)
+ goto error;
+
+ sched->ref = 1;
+ sched->n = graph->n;
+ sched->n_band = graph->n_band;
+ sched->n_total_row = graph->n_total_row;
+
+ for (i = 0; i < sched->n; ++i) {
+ int r, b;
+ int *band_end, *band_id, *coincident;
+
+ sched->node[i].sched =
+ node_extract_schedule_multi_aff(&graph->node[i]);
+ if (!sched->node[i].sched)
+ goto error;
+
+ sched->node[i].n_band = graph->n_band;
+ if (graph->n_band == 0)
+ continue;
+
+ band_end = isl_alloc_array(ctx, int, graph->n_band);
+ band_id = isl_alloc_array(ctx, int, graph->n_band);
+ coincident = isl_alloc_array(ctx, int, graph->n_total_row);
+ sched->node[i].band_end = band_end;
+ sched->node[i].band_id = band_id;
+ sched->node[i].coincident = coincident;
+ if (!band_end || !band_id || !coincident)
+ goto error;
+
+ for (r = 0; r < graph->n_total_row; ++r)
+ coincident[r] = graph->node[i].coincident[r];
+ for (r = b = 0; r < graph->n_total_row; ++r) {
+ if (graph->node[i].band[r] == b)
+ continue;
+ band_end[b++] = r;
+ if (graph->node[i].band[r] == -1)
+ break;
+ }
+ if (r == graph->n_total_row)
+ band_end[b++] = r;
+ sched->node[i].n_band = b;
+ for (--b; b >= 0; --b)
+ band_id[b] = graph->node[i].band_id[b];
+ }
+
+ sched->dim = dim;
+
+ return sched;
+error:
+ isl_space_free(dim);
+ isl_schedule_free(sched);
+ return NULL;
+}
+
+/* Copy nodes that satisfy node_pred from the src dependence graph
+ * to the dst dependence graph.
+ */
+static int copy_nodes(struct isl_sched_graph *dst, struct isl_sched_graph *src,
+ int (*node_pred)(struct isl_sched_node *node, int data), int data)
+{
+ int i;
+
+ dst->n = 0;
+ for (i = 0; i < src->n; ++i) {
+ int j;
+
+ if (!node_pred(&src->node[i], data))
+ continue;
+
+ j = dst->n;
+ dst->node[j].space = isl_space_copy(src->node[i].space);
+ dst->node[j].compressed = src->node[i].compressed;
+ dst->node[j].hull = isl_set_copy(src->node[i].hull);
+ dst->node[j].compress =
+ isl_multi_aff_copy(src->node[i].compress);
+ dst->node[j].decompress =
+ isl_multi_aff_copy(src->node[i].decompress);
+ dst->node[j].nvar = src->node[i].nvar;
+ dst->node[j].nparam = src->node[i].nparam;
+ dst->node[j].sched = isl_mat_copy(src->node[i].sched);
+ dst->node[j].sched_map = isl_map_copy(src->node[i].sched_map);
+ dst->node[j].band = src->node[i].band;
+ dst->node[j].band_id = src->node[i].band_id;
+ dst->node[j].coincident = src->node[i].coincident;
+ dst->n++;
+
+ if (!dst->node[j].space || !dst->node[j].sched)
+ return -1;
+ if (dst->node[j].compressed &&
+ (!dst->node[j].hull || !dst->node[j].compress ||
+ !dst->node[j].decompress))
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Copy non-empty edges that satisfy edge_pred from the src dependence graph
+ * to the dst dependence graph.
+ * If the source or destination node of the edge is not in the destination
+ * graph, then it must be a backward proximity edge and it should simply
+ * be ignored.
+ */
+static int copy_edges(isl_ctx *ctx, struct isl_sched_graph *dst,
+ struct isl_sched_graph *src,
+ int (*edge_pred)(struct isl_sched_edge *edge, int data), int data)
+{
+ int i;
+ enum isl_edge_type t;
+
+ dst->n_edge = 0;
+ for (i = 0; i < src->n_edge; ++i) {
+ struct isl_sched_edge *edge = &src->edge[i];
+ isl_map *map;
+ isl_union_map *tagged_condition;
+ isl_union_map *tagged_validity;
+ struct isl_sched_node *dst_src, *dst_dst;
+
+ if (!edge_pred(edge, data))
+ continue;
+
+ if (isl_map_plain_is_empty(edge->map))
+ continue;
+
+ 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)
+ isl_die(ctx, isl_error_internal,
+ "backward (conditional) validity edge",
+ return -1);
+ continue;
+ }
+
+ map = isl_map_copy(edge->map);
+ tagged_condition = isl_union_map_copy(edge->tagged_condition);
+ tagged_validity = isl_union_map_copy(edge->tagged_validity);
+
+ dst->edge[dst->n_edge].src = dst_src;
+ dst->edge[dst->n_edge].dst = dst_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->n_edge++;
+
+ if (edge->tagged_condition && !tagged_condition)
+ return -1;
+ if (edge->tagged_validity && !tagged_validity)
+ return -1;
+
+ for (t = isl_edge_first; t <= isl_edge_last; ++t) {
+ if (edge !=
+ graph_find_edge(src, t, edge->src, edge->dst))
+ continue;
+ if (graph_edge_table_add(ctx, dst, t,
+ &dst->edge[dst->n_edge - 1]) < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Given a "src" dependence graph that contains the nodes from "dst"
+ * that satisfy node_pred, copy the schedule computed in "src"
+ * for those nodes back to "dst".
+ */
+static int copy_schedule(struct isl_sched_graph *dst,
+ struct isl_sched_graph *src,
+ int (*node_pred)(struct isl_sched_node *node, int data), int data)
+{
+ int i;
+
+ src->n = 0;
+ for (i = 0; i < dst->n; ++i) {
+ if (!node_pred(&dst->node[i], data))
+ continue;
+ isl_mat_free(dst->node[i].sched);
+ isl_map_free(dst->node[i].sched_map);
+ dst->node[i].sched = isl_mat_copy(src->node[src->n].sched);
+ dst->node[i].sched_map =
+ isl_map_copy(src->node[src->n].sched_map);
+ src->n++;
+ }
+
+ dst->max_row = src->max_row;
+ dst->n_total_row = src->n_total_row;
+ dst->n_band = src->n_band;
+
+ return 0;
+}
+
+/* Compute the maximal number of variables over all nodes.
+ * This is the maximal number of linearly independent schedule
+ * rows that we need to compute.
+ * Just in case we end up in a part of the dependence graph
+ * with only lower-dimensional domains, we make sure we will
+ * compute the required amount of extra linearly independent rows.
+ */
+static int compute_maxvar(struct isl_sched_graph *graph)
+{
+ int i;
+
+ graph->maxvar = 0;
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int nvar;
+
+ if (node_update_cmap(node) < 0)
+ return -1;
+ nvar = node->nvar + graph->n_row - node->rank;
+ if (nvar > graph->maxvar)
+ graph->maxvar = nvar;
+ }
+
+ return 0;
+}
+
+static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph);
+static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph);
+
+/* 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".
+ * 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
+ * is connected.
+ */
+static int compute_sub_schedule(isl_ctx *ctx,
+ struct isl_sched_graph *graph, int n, int n_edge,
+ 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 t;
+
+ if (graph_alloc(ctx, &split, n, n_edge) < 0)
+ goto error;
+ if (copy_nodes(&split, graph, node_pred, data) < 0)
+ goto error;
+ if (graph_init_table(ctx, &split) < 0)
+ goto error;
+ for (t = 0; t <= isl_edge_last; ++t)
+ split.max_edge[t] = graph->max_edge[t];
+ if (graph_init_edge_tables(ctx, &split) < 0)
+ goto error;
+ if (copy_edges(ctx, &split, graph, edge_pred, data) < 0)
+ goto error;
+ split.n_row = graph->n_row;
+ split.max_row = graph->max_row;
+ split.n_total_row = graph->n_total_row;
+ split.n_band = graph->n_band;
+ split.band_start = graph->band_start;
+
+ if (wcc && compute_schedule_wcc(ctx, &split) < 0)
+ goto error;
+ if (!wcc && compute_schedule(ctx, &split) < 0)
+ goto error;
+
+ copy_schedule(graph, &split, node_pred, data);
+
+ graph_free(ctx, &split);
+ return 0;
+error:
+ graph_free(ctx, &split);
+ return -1;
+}
+
+static int node_scc_exactly(struct isl_sched_node *node, int scc)
+{
+ return node->scc == scc;
+}
+
+static int node_scc_at_most(struct isl_sched_node *node, int scc)
+{
+ return node->scc <= scc;
+}
+
+static int node_scc_at_least(struct isl_sched_node *node, int scc)
+{
+ return node->scc >= scc;
+}
+
+static int edge_scc_exactly(struct isl_sched_edge *edge, int scc)
+{
+ return edge->src->scc == scc && edge->dst->scc == scc;
+}
+
+static int edge_dst_scc_at_most(struct isl_sched_edge *edge, int scc)
+{
+ return edge->dst->scc <= scc;
+}
+
+static int edge_src_scc_at_least(struct isl_sched_edge *edge, int scc)
+{
+ return edge->src->scc >= scc;
+}
+
+/* Pad the schedules of all nodes with zero rows such that in the end
+ * they all have graph->n_total_row rows.
+ * The extra rows don't belong to any band, so they get assigned band number -1.
+ */
+static int pad_schedule(struct isl_sched_graph *graph)
+{
+ int i, j;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int row = isl_mat_rows(node->sched);
+ if (graph->n_total_row > row) {
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ }
+ node->sched = isl_mat_add_zero_rows(node->sched,
+ graph->n_total_row - row);
+ if (!node->sched)
+ return -1;
+ for (j = row; j < graph->n_total_row; ++j)
+ node->band[j] = -1;
+ }
+
+ return 0;
+}
+
+/* Reset the current band by dropping all its schedule rows.
+ */
+static int reset_band(struct isl_sched_graph *graph)
+{
+ int i;
+ int drop;
+
+ drop = graph->n_total_row - graph->band_start;
+ graph->n_total_row -= drop;
+ graph->n_row -= drop;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+
+ node->sched = isl_mat_drop_rows(node->sched,
+ graph->band_start, drop);
+
+ if (!node->sched)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* 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 in the schedule by constant rows with two different
+ * values (0 and 1). These constant rows replace the previously computed rows
+ * in the current band.
+ * It would be possible to reuse them as the first rows in the next
+ * band, but recomputing them may result in better rows as we are looking
+ * at a smaller part of the dependence graph.
+ *
+ * Since we do not enforce coincidence, we conservatively mark the
+ * splitting row as not coincident.
+ *
+ * The band_id of the second group is set to n, where n is the number
+ * of nodes in the first group. This ensures that the band_ids over
+ * the two groups remain disjoint, even if either or both of the two
+ * groups contain independent components.
+ */
+static int compute_split_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i, j, n, e1, e2;
+ int n_total_row, orig_total_row;
+ int n_band, orig_band;
+
+ if (graph->n_total_row >= graph->max_row)
+ isl_die(ctx, isl_error_internal,
+ "too many schedule rows", return -1);
+
+ if (reset_band(graph) < 0)
+ return -1;
+
+ n = 0;
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int row = isl_mat_rows(node->sched);
+ int cols = isl_mat_cols(node->sched);
+ int before = node->scc <= graph->src_scc;
+
+ if (before)
+ n++;
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ node->sched = isl_mat_add_rows(node->sched, 1);
+ if (!node->sched)
+ return -1;
+ node->sched = isl_mat_set_element_si(node->sched, row, 0,
+ !before);
+ for (j = 1; j < cols; ++j)
+ node->sched = isl_mat_set_element_si(node->sched,
+ row, j, 0);
+ node->band[graph->n_total_row] = graph->n_band;
+ node->coincident[graph->n_total_row] = 0;
+ }
+
+ 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++;
+ }
+
+ graph->n_total_row++;
+ next_band(graph);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ if (node->scc > graph->src_scc)
+ node->band_id[graph->n_band] = n;
+ }
+
+ orig_total_row = graph->n_total_row;
+ orig_band = graph->n_band;
+ if (compute_sub_schedule(ctx, graph, n, e1,
+ &node_scc_at_most, &edge_dst_scc_at_most,
+ graph->src_scc, 0) < 0)
+ return -1;
+ n_total_row = graph->n_total_row;
+ graph->n_total_row = orig_total_row;
+ n_band = graph->n_band;
+ graph->n_band = orig_band;
+ if (compute_sub_schedule(ctx, graph, graph->n - n, e2,
+ &node_scc_at_least, &edge_src_scc_at_least,
+ graph->src_scc + 1, 0) < 0)
+ return -1;
+ if (n_total_row > graph->n_total_row)
+ graph->n_total_row = n_total_row;
+ if (n_band > graph->n_band)
+ graph->n_band = n_band;
+
+ return pad_schedule(graph);
+}
+
+/* Compute the next band of the schedule after updating the dependence
+ * relations based on the the current schedule.
+ */
+static int compute_next_band(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ if (update_edges(ctx, graph) < 0)
+ return -1;
+ next_band(graph);
+
+ return compute_schedule(ctx, graph);
+}
+
+/* Add constraints to graph->lp that force the dependence "map" (which
+ * is part of the dependence relation of "edge")
+ * to be respected and attempt to carry it, where the edge is one from
+ * a node j to itself. "pos" is the sequence number of the given map.
+ * That is, add constraints that enforce
+ *
+ * (c_j_0 + c_j_n n + c_j_x y) - (c_j_0 + c_j_n n + c_j_x x)
+ * = c_j_x (y - x) >= e_i
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x)
+ * of valid constraints for (y - x) and then plug in (-e_i, 0, c_j_x),
+ * with each coefficient in c_j_x represented as a pair of non-negative
+ * coefficients.
+ */
+static int add_intra_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge, __isl_take isl_map *map, int pos)
+{
+ unsigned total;
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *node = edge->src;
+
+ coef = intra_coefficients(graph, node, map);
+ if (!coef)
+ return -1;
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+ isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, -1);
+ isl_dim_map_range(dim_map, node->start + 2 * node->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ node->nvar, 1);
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ isl_space_free(dim);
+
+ return 0;
+}
+
+/* Add constraints to graph->lp that force the dependence "map" (which
+ * is part of the dependence relation of "edge")
+ * to be respected and attempt to carry it, where the edge is one from
+ * node j to node k. "pos" is the sequence number of the given map.
+ * That is, add constraints that enforce
+ *
+ * (c_k_0 + c_k_n n + c_k_x y) - (c_j_0 + c_j_n n + c_j_x x) >= e_i
+ *
+ * for each (x,y) in R.
+ * We obtain general constraints on coefficients (c_0, c_n, c_x)
+ * of valid constraints for R and then plug in
+ * (-e_i + c_k_0 - c_j_0, c_k_n - c_j_n, c_k_x - c_j_x)
+ * with each coefficient (except e_i, c_k_0 and c_j_0)
+ * represented as a pair of non-negative coefficients.
+ */
+static int add_inter_constraints(struct isl_sched_graph *graph,
+ struct isl_sched_edge *edge, __isl_take isl_map *map, int pos)
+{
+ unsigned total;
+ isl_ctx *ctx = isl_map_get_ctx(map);
+ isl_space *dim;
+ isl_dim_map *dim_map;
+ isl_basic_set *coef;
+ struct isl_sched_node *src = edge->src;
+ struct isl_sched_node *dst = edge->dst;
+
+ coef = inter_coefficients(graph, edge, map);
+ if (!coef)
+ return -1;
+
+ dim = isl_space_domain(isl_space_unwrap(isl_basic_set_get_space(coef)));
+
+ total = isl_basic_set_total_dim(graph->lp);
+ dim_map = isl_dim_map_alloc(ctx, total);
+
+ isl_dim_map_range(dim_map, 3 + pos, 0, 0, 0, 1, -1);
+
+ isl_dim_map_range(dim_map, dst->start, 0, 0, 0, 1, 1);
+ isl_dim_map_range(dim_map, dst->start + 1, 2, 1, 1, dst->nparam, -1);
+ isl_dim_map_range(dim_map, dst->start + 2, 2, 1, 1, dst->nparam, 1);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, -1);
+ isl_dim_map_range(dim_map, dst->start + 2 * dst->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set) + src->nvar, 1,
+ dst->nvar, 1);
+
+ isl_dim_map_range(dim_map, src->start, 0, 0, 0, 1, -1);
+ isl_dim_map_range(dim_map, src->start + 1, 2, 1, 1, src->nparam, 1);
+ isl_dim_map_range(dim_map, src->start + 2, 2, 1, 1, src->nparam, -1);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 1, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, 1);
+ isl_dim_map_range(dim_map, src->start + 2 * src->nparam + 2, 2,
+ isl_space_dim(dim, isl_dim_set), 1,
+ src->nvar, -1);
+
+ graph->lp = isl_basic_set_extend_constraints(graph->lp,
+ coef->n_eq, coef->n_ineq);
+ graph->lp = isl_basic_set_add_constraints_dim_map(graph->lp,
+ coef, dim_map);
+ isl_space_free(dim);
+
+ return 0;
+}
+
+/* Add constraints to graph->lp that force all (conditional) validity
+ * dependences to be respected and attempt to carry them.
+ */
+static int add_all_constraints(struct isl_sched_graph *graph)
+{
+ int i, j;
+ int pos;
+
+ pos = 0;
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge= &graph->edge[i];
+
+ if (!edge->validity && !edge->conditional_validity)
+ continue;
+
+ for (j = 0; j < edge->map->n; ++j) {
+ isl_basic_map *bmap;
+ isl_map *map;
+
+ bmap = isl_basic_map_copy(edge->map->p[j]);
+ map = isl_map_from_basic_map(bmap);
+
+ if (edge->src == edge->dst &&
+ add_intra_constraints(graph, edge, map, pos) < 0)
+ return -1;
+ if (edge->src != edge->dst &&
+ add_inter_constraints(graph, edge, map, pos) < 0)
+ return -1;
+ ++pos;
+ }
+ }
+
+ return 0;
+}
+
+/* Count the number of equality and inequality constraints
+ * that will be added to the carry_lp problem.
+ * We count each edge exactly once.
+ */
+static int count_all_constraints(struct isl_sched_graph *graph,
+ int *n_eq, int *n_ineq)
+{
+ int i, j;
+
+ *n_eq = *n_ineq = 0;
+ for (i = 0; i < graph->n_edge; ++i) {
+ struct isl_sched_edge *edge= &graph->edge[i];
+ for (j = 0; j < edge->map->n; ++j) {
+ isl_basic_map *bmap;
+ isl_map *map;
+
+ bmap = isl_basic_map_copy(edge->map->p[j]);
+ map = isl_map_from_basic_map(bmap);
+
+ if (count_map_constraints(graph, edge, map,
+ n_eq, n_ineq, 1, 0) < 0)
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/* Construct an LP problem for finding schedule coefficients
+ * such that the schedule carries as many dependences as possible.
+ * In particular, for each dependence i, we bound the dependence distance
+ * from below by e_i, with 0 <= e_i <= 1 and then maximize the sum
+ * of all e_i's. Dependence with e_i = 0 in the solution are simply
+ * respected, while those with e_i > 0 (in practice e_i = 1) are carried.
+ * Note that if the dependence relation is a union of basic maps,
+ * then we have to consider each basic map individually as it may only
+ * be possible to carry the dependences expressed by some of those
+ * basic maps and not all off them.
+ * Below, we consider each of those basic maps as a separate "edge".
+ *
+ * All variables of the LP are non-negative. The actual coefficients
+ * may be negative, so each coefficient is represented as the difference
+ * of two non-negative variables. The negative part always appears
+ * immediately before the positive part.
+ * Other than that, the variables have the following order
+ *
+ * - sum of (1 - e_i) over all edges
+ * - sum of positive and negative parts of all c_n coefficients
+ * (unconstrained when computing non-parametric schedules)
+ * - sum of positive and negative parts of all c_x coefficients
+ * - for each edge
+ * - e_i
+ * - for each node
+ * - c_i_0
+ * - positive and negative parts of c_i_n (if parametric)
+ * - positive and negative parts of c_i_x
+ *
+ * The constraints are those from the (validity) edges plus three equalities
+ * to express the sums and n_edge inequalities to express e_i <= 1.
+ */
+static int setup_carry_lp(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i, j;
+ int k;
+ isl_space *dim;
+ unsigned total;
+ int n_eq, n_ineq;
+ int n_edge;
+
+ n_edge = 0;
+ for (i = 0; i < graph->n_edge; ++i)
+ n_edge += graph->edge[i].map->n;
+
+ total = 3 + n_edge;
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[graph->sorted[i]];
+ node->start = total;
+ total += 1 + 2 * (node->nparam + node->nvar);
+ }
+
+ if (count_all_constraints(graph, &n_eq, &n_ineq) < 0)
+ return -1;
+ if (count_bound_coefficient_constraints(ctx, graph, &n_eq, &n_ineq) < 0)
+ return -1;
+
+ dim = isl_space_set_alloc(ctx, 0, total);
+ isl_basic_set_free(graph->lp);
+ n_eq += 3;
+ n_ineq += n_edge;
+ graph->lp = isl_basic_set_alloc_space(dim, 0, n_eq, n_ineq);
+ graph->lp = isl_basic_set_set_rational(graph->lp);
+
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][0], -n_edge);
+ isl_int_set_si(graph->lp->eq[k][1], 1);
+ for (i = 0; i < n_edge; ++i)
+ isl_int_set_si(graph->lp->eq[k][4 + i], 1);
+
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][2], -1);
+ for (i = 0; i < graph->n; ++i) {
+ int pos = 1 + graph->node[i].start + 1;
+
+ for (j = 0; j < 2 * graph->node[i].nparam; ++j)
+ isl_int_set_si(graph->lp->eq[k][pos + j], 1);
+ }
+
+ k = isl_basic_set_alloc_equality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->eq[k], 1 + total);
+ isl_int_set_si(graph->lp->eq[k][3], -1);
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int pos = 1 + node->start + 1 + 2 * node->nparam;
+
+ for (j = 0; j < 2 * node->nvar; ++j)
+ isl_int_set_si(graph->lp->eq[k][pos + j], 1);
+ }
+
+ for (i = 0; i < n_edge; ++i) {
+ k = isl_basic_set_alloc_inequality(graph->lp);
+ if (k < 0)
+ return -1;
+ isl_seq_clr(graph->lp->ineq[k], 1 + total);
+ isl_int_set_si(graph->lp->ineq[k][4 + i], -1);
+ isl_int_set_si(graph->lp->ineq[k][0], 1);
+ }
+
+ if (add_bound_coefficient_constraints(ctx, graph) < 0)
+ return -1;
+ if (add_all_constraints(graph) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* If the schedule_split_scaled option is set and if the linear
+ * parts of the scheduling rows for all nodes in the graphs have
+ * non-trivial common divisor, then split off the constant term
+ * from the linear part.
+ * The constant term is then placed in a separate band and
+ * the linear part is reduced.
+ */
+static int split_scaled(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+ int row;
+ isl_int gcd, gcd_i;
+
+ if (!ctx->opt->schedule_split_scaled)
+ return 0;
+ if (graph->n <= 1)
+ return 0;
+
+ if (graph->n_total_row >= graph->max_row)
+ isl_die(ctx, isl_error_internal,
+ "too many schedule rows", return -1);
+
+ isl_int_init(gcd);
+ isl_int_init(gcd_i);
+
+ isl_int_set_si(gcd, 0);
+
+ row = isl_mat_rows(graph->node[0].sched) - 1;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int cols = isl_mat_cols(node->sched);
+
+ isl_seq_gcd(node->sched->row[row] + 1, cols - 1, &gcd_i);
+ isl_int_gcd(gcd, gcd, gcd_i);
+ }
+
+ isl_int_clear(gcd_i);
+
+ if (isl_int_cmp_si(gcd, 1) <= 0) {
+ isl_int_clear(gcd);
+ return 0;
+ }
+
+ next_band(graph);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ node->sched = isl_mat_add_zero_rows(node->sched, 1);
+ if (!node->sched)
+ goto error;
+ isl_int_fdiv_r(node->sched->row[row + 1][0],
+ node->sched->row[row][0], gcd);
+ isl_int_fdiv_q(node->sched->row[row][0],
+ node->sched->row[row][0], gcd);
+ isl_int_mul(node->sched->row[row][0],
+ node->sched->row[row][0], gcd);
+ node->sched = isl_mat_scale_down_row(node->sched, row, gcd);
+ if (!node->sched)
+ goto error;
+ node->band[graph->n_total_row] = graph->n_band;
+ }
+
+ graph->n_total_row++;
+
+ isl_int_clear(gcd);
+ return 0;
+error:
+ isl_int_clear(gcd);
+ return -1;
+}
+
+static int compute_component_schedule(isl_ctx *ctx,
+ struct isl_sched_graph *graph);
+
+/* Is the schedule row "sol" trivial on node "node"?
+ * That is, is the solution zero on the dimensions orthogonal to
+ * the previously found solutions?
+ * Return 1 if the solution is trivial, 0 if it is not and -1 on error.
+ *
+ * Each coefficient is represented as the difference between
+ * two non-negative values in "sol". "sol" has been computed
+ * in terms of the original iterators (i.e., without use of cmap).
+ * We construct the schedule row s and write it as a linear
+ * combination of (linear combinations of) previously computed schedule rows.
+ * s = Q c or c = U s.
+ * If the final entries of c are all zero, then the solution is trivial.
+ */
+static int is_trivial(struct isl_sched_node *node, __isl_keep isl_vec *sol)
+{
+ int i;
+ int pos;
+ int trivial;
+ isl_ctx *ctx;
+ isl_vec *node_sol;
+
+ if (!sol)
+ return -1;
+ if (node->nvar == node->rank)
+ return 0;
+
+ ctx = isl_vec_get_ctx(sol);
+ node_sol = isl_vec_alloc(ctx, node->nvar);
+ if (!node_sol)
+ return -1;
+
+ pos = 1 + node->start + 1 + 2 * node->nparam;
+
+ for (i = 0; i < node->nvar; ++i)
+ isl_int_sub(node_sol->el[i],
+ sol->el[pos + 2 * i + 1], sol->el[pos + 2 * i]);
+
+ node_sol = isl_mat_vec_product(isl_mat_copy(node->cinv), node_sol);
+
+ if (!node_sol)
+ return -1;
+
+ trivial = isl_seq_first_non_zero(node_sol->el + node->rank,
+ node->nvar - node->rank) == -1;
+
+ isl_vec_free(node_sol);
+
+ return trivial;
+}
+
+/* Is the schedule row "sol" trivial on any node where it should
+ * not be trivial?
+ * "sol" has been computed in terms of the original iterators
+ * (i.e., without use of cmap).
+ * Return 1 if any solution is trivial, 0 if they are not and -1 on error.
+ */
+static int is_any_trivial(struct isl_sched_graph *graph,
+ __isl_keep isl_vec *sol)
+{
+ int i;
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int trivial;
+
+ if (!needs_row(graph, node))
+ continue;
+ trivial = is_trivial(node, sol);
+ if (trivial < 0 || trivial)
+ return trivial;
+ }
+
+ return 0;
+}
+
+/* Construct a schedule row for each node such that as many dependences
+ * as possible are carried and then continue with the next band.
+ *
+ * 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.
+ *
+ * If there is only one component, then we accept the schedule row anyway,
+ * but we do not consider it as a complete row and therefore do not
+ * increment graph->n_row. Note that the ranks of the nodes that
+ * do get a non-trivial schedule part will get updated regardless and
+ * graph->maxvar is computed based on these ranks. The test for
+ * whether more schedule rows are required in compute_schedule_wcc
+ * is therefore not affected.
+ */
+static int carry_dependences(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+ int n_edge;
+ int trivial;
+ isl_vec *sol;
+ isl_basic_set *lp;
+
+ n_edge = 0;
+ for (i = 0; i < graph->n_edge; ++i)
+ n_edge += graph->edge[i].map->n;
+
+ if (setup_carry_lp(ctx, graph) < 0)
+ return -1;
+
+ lp = isl_basic_set_copy(graph->lp);
+ sol = isl_tab_basic_set_non_neg_lexmin(lp);
+ if (!sol)
+ return -1;
+
+ if (sol->size == 0) {
+ isl_vec_free(sol);
+ isl_die(ctx, isl_error_internal,
+ "error in schedule construction", return -1);
+ }
+
+ isl_int_divexact(sol->el[1], sol->el[1], sol->el[0]);
+ if (isl_int_cmp_si(sol->el[1], n_edge) >= 0) {
+ isl_vec_free(sol);
+ isl_die(ctx, isl_error_unknown,
+ "unable to carry dependences", return -1);
+ }
+
+ trivial = is_any_trivial(graph, sol);
+ if (trivial < 0) {
+ sol = isl_vec_free(sol);
+ } else if (trivial && graph->scc > 1) {
+ isl_vec_free(sol);
+ return compute_component_schedule(ctx, graph);
+ }
+
+ if (update_schedule(graph, sol, 0, 0) < 0)
+ return -1;
+ if (trivial)
+ graph->n_row--;
+
+ if (split_scaled(ctx, graph) < 0)
+ return -1;
+
+ return compute_next_band(ctx, graph);
+}
+
+/* Are there any (non-empty) (conditional) validity edges in the graph?
+ */
+static int has_validity_edges(struct isl_sched_graph *graph)
+{
+ int i;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ int empty;
+
+ empty = isl_map_plain_is_empty(graph->edge[i].map);
+ if (empty < 0)
+ return -1;
+ if (empty)
+ continue;
+ if (graph->edge[i].validity ||
+ graph->edge[i].conditional_validity)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Should we apply a Feautrier step?
+ * That is, did the user request the Feautrier algorithm and are
+ * there any validity dependences (left)?
+ */
+static int need_feautrier_step(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ if (ctx->opt->schedule_algorithm != ISL_SCHEDULE_ALGORITHM_FEAUTRIER)
+ return 0;
+
+ return has_validity_edges(graph);
+}
+
+/* Compute a schedule for a connected dependence graph using Feautrier's
+ * multi-dimensional scheduling algorithm.
+ * The original algorithm is described in [1].
+ * The main idea is to minimize the number of scheduling dimensions, by
+ * trying to satisfy as many dependences as possible per scheduling dimension.
+ *
+ * [1] P. Feautrier, Some Efficient Solutions to the Affine Scheduling
+ * Problem, Part II: Multi-Dimensional Time.
+ * In Intl. Journal of Parallel Programming, 1992.
+ */
+static int compute_schedule_wcc_feautrier(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ return carry_dependences(ctx, graph);
+}
+
+/* Turn off the "local" bit on all (condition) edges.
+ */
+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;
+}
+
+/* Does "graph" have both condition and conditional validity edges?
+ */
+static int need_condition_check(struct isl_sched_graph *graph)
+{
+ int i;
+ int any_condition = 0;
+ int any_conditional_validity = 0;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ if (graph->edge[i].condition)
+ any_condition = 1;
+ if (graph->edge[i].conditional_validity)
+ any_conditional_validity = 1;
+ }
+
+ return any_condition && any_conditional_validity;
+}
+
+/* Does "graph" contain any coincidence edge?
+ */
+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)
+ return 1;
+
+ return 0;
+}
+
+/* Extract the final schedule row as a map with the iteration domain
+ * of "node" as domain.
+ */
+static __isl_give isl_map *final_row(struct isl_sched_node *node)
+{
+ isl_local_space *ls;
+ isl_aff *aff;
+ int row;
+
+ row = isl_mat_rows(node->sched) - 1;
+ ls = isl_local_space_from_space(isl_space_copy(node->space));
+ aff = extract_schedule_row(ls, node, row);
+ return isl_map_from_aff(aff);
+}
+
+/* Is the conditional validity dependence in the edge with index "edge_index"
+ * violated by the latest (i.e., final) row of the schedule?
+ * That is, is i scheduled after j
+ * for any conditional validity dependence i -> j?
+ */
+static int is_violated(struct isl_sched_graph *graph, int edge_index)
+{
+ isl_map *src_sched, *dst_sched, *map;
+ struct isl_sched_edge *edge = &graph->edge[edge_index];
+ int empty;
+
+ src_sched = final_row(edge->src);
+ dst_sched = final_row(edge->dst);
+ map = isl_map_copy(edge->map);
+ map = isl_map_apply_domain(map, src_sched);
+ map = isl_map_apply_range(map, dst_sched);
+ map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
+ empty = isl_map_is_empty(map);
+ isl_map_free(map);
+
+ if (empty < 0)
+ return -1;
+
+ return !empty;
+}
+
+/* Does the domain of "umap" intersect "uset"?
+ */
+static int domain_intersects(__isl_keep isl_union_map *umap,
+ __isl_keep isl_union_set *uset)
+{
+ int empty;
+
+ umap = isl_union_map_copy(umap);
+ umap = isl_union_map_intersect_domain(umap, isl_union_set_copy(uset));
+ empty = isl_union_map_is_empty(umap);
+ isl_union_map_free(umap);
+
+ return empty < 0 ? -1 : !empty;
+}
+
+/* Does the range of "umap" intersect "uset"?
+ */
+static int range_intersects(__isl_keep isl_union_map *umap,
+ __isl_keep isl_union_set *uset)
+{
+ int empty;
+
+ umap = isl_union_map_copy(umap);
+ umap = isl_union_map_intersect_range(umap, isl_union_set_copy(uset));
+ empty = isl_union_map_is_empty(umap);
+ isl_union_map_free(umap);
+
+ return empty < 0 ? -1 : !empty;
+}
+
+/* Are the condition dependences of "edge" local with respect to
+ * the current schedule?
+ *
+ * That is, are domain and range of the condition dependences mapped
+ * to the same point?
+ *
+ * In other words, is the condition false?
+ */
+static int is_condition_false(struct isl_sched_edge *edge)
+{
+ isl_union_map *umap;
+ isl_map *map, *sched, *test;
+ int local;
+
+ umap = isl_union_map_copy(edge->tagged_condition);
+ umap = isl_union_map_zip(umap);
+ umap = isl_union_set_unwrap(isl_union_map_domain(umap));
+ map = isl_map_from_union_map(umap);
+
+ sched = node_extract_schedule(edge->src);
+ map = isl_map_apply_domain(map, sched);
+ sched = node_extract_schedule(edge->dst);
+ map = isl_map_apply_range(map, sched);
+
+ test = isl_map_identity(isl_map_get_space(map));
+ local = isl_map_is_subset(map, test);
+ isl_map_free(map);
+ isl_map_free(test);
+
+ return local;
+}
+
+/* Does "graph" have any satisfied condition edges that
+ * are adjacent to the conditional validity constraint with
+ * domain "conditional_source" and range "conditional_sink"?
+ *
+ * A satisfied condition is one that is not local.
+ * If a condition was forced to be local already (i.e., marked as local)
+ * then there is no need to check if it is in fact local.
+ *
+ * Additionally, mark all adjacent condition edges found as local.
+ */
+static int has_adjacent_true_conditions(struct isl_sched_graph *graph,
+ __isl_keep isl_union_set *conditional_source,
+ __isl_keep isl_union_set *conditional_sink)
+{
+ int i;
+ int any = 0;
+
+ for (i = 0; i < graph->n_edge; ++i) {
+ int adjacent, local;
+ isl_union_map *condition;
+
+ if (!graph->edge[i].condition)
+ continue;
+ if (graph->edge[i].local)
+ continue;
+
+ condition = graph->edge[i].tagged_condition;
+ adjacent = domain_intersects(condition, conditional_sink);
+ if (adjacent >= 0 && !adjacent)
+ adjacent = range_intersects(condition,
+ conditional_source);
+ if (adjacent < 0)
+ return -1;
+ if (!adjacent)
+ continue;
+
+ graph->edge[i].local = 1;
+
+ local = is_condition_false(&graph->edge[i]);
+ if (local < 0)
+ return -1;
+ if (!local)
+ any = 1;
+ }
+
+ return any;
+}
+
+/* Are there any violated conditional validity dependences with
+ * adjacent condition dependences that are not local with respect
+ * to the current schedule?
+ * That is, is the conditional validity constraint violated?
+ *
+ * Additionally, mark all those adjacent condition dependences as local.
+ * We also mark those adjacent condition dependences that were not marked
+ * as local before, but just happened to be local already. This ensures
+ * that they remain local if the schedule is recomputed.
+ *
+ * We first collect domain and range of all violated conditional validity
+ * dependences and then check if there are any adjacent non-local
+ * condition dependences.
+ */
+static int has_violated_conditional_constraint(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ int i;
+ int any = 0;
+ isl_union_set *source, *sink;
+
+ source = isl_union_set_empty(isl_space_params_alloc(ctx, 0));
+ sink = isl_union_set_empty(isl_space_params_alloc(ctx, 0));
+ for (i = 0; i < graph->n_edge; ++i) {
+ isl_union_set *uset;
+ isl_union_map *umap;
+ int violated;
+
+ if (!graph->edge[i].conditional_validity)
+ continue;
+
+ violated = is_violated(graph, i);
+ if (violated < 0)
+ goto error;
+ if (!violated)
+ continue;
+
+ any = 1;
+
+ umap = isl_union_map_copy(graph->edge[i].tagged_validity);
+ uset = isl_union_map_domain(umap);
+ source = isl_union_set_union(source, uset);
+ source = isl_union_set_coalesce(source);
+
+ umap = isl_union_map_copy(graph->edge[i].tagged_validity);
+ uset = isl_union_map_range(umap);
+ sink = isl_union_set_union(sink, uset);
+ sink = isl_union_set_coalesce(sink);
+ }
+
+ if (any)
+ any = has_adjacent_true_conditions(graph, source, sink);
+
+ isl_union_set_free(source);
+ isl_union_set_free(sink);
+ return any;
+error:
+ isl_union_set_free(source);
+ isl_union_set_free(sink);
+ return -1;
+}
+
+/* Compute a schedule for a connected dependence graph.
+ * We try to find a sequence of as many schedule rows as possible that result
+ * in non-negative dependence distances (independent of the previous rows
+ * in the sequence, i.e., such that the sequence is tilable), with as
+ * many of the initial rows as possible satisfying the coincidence constraints.
+ * If we can't find any more rows we either
+ * - split between SCCs and start over (assuming we found an interesting
+ * pair of SCCs between which to split)
+ * - continue with the next band (assuming the current band has at least
+ * one row)
+ * - try to carry as many dependences as possible and continue with the next
+ * band
+ *
+ * If Feautrier's algorithm is selected, we first recursively try to satisfy
+ * as many validity dependences as possible. When all validity dependences
+ * are satisfied we extend the schedule to a full-dimensional schedule.
+ *
+ * If we manage to complete the schedule, we finish off by topologically
+ * sorting the statements based on the remaining dependences.
+ *
+ * If ctx->opt->schedule_outer_coincidence is set, then we force the
+ * outermost dimension to satisfy the coincidence constraints. If this
+ * turns out to be impossible, we fall back on the general scheme above
+ * and try to carry as many dependences as possible.
+ *
+ * If "graph" contains both condition and conditional validity dependences,
+ * then we need to check that that the conditional schedule constraint
+ * is satisfied, i.e., there are no violated conditional validity dependences
+ * that are adjacent to any non-local condition dependences.
+ * If there are, then we mark all those adjacent condition dependences
+ * as local and recompute the current band. Those dependences that
+ * are marked local will then be forced to be local.
+ * The initial computation is performed with no dependences marked as local.
+ * If we are lucky, then there will be no violated conditional validity
+ * dependences adjacent to any non-local condition dependences.
+ * Otherwise, we mark some additional condition dependences as local and
+ * recompute. We continue this process until there are no violations left or
+ * until we are no longer able to compute a schedule.
+ * Since there are only a finite number of dependences,
+ * there will only be a finite number of iterations.
+ */
+static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int has_coincidence;
+ int use_coincidence;
+ int force_coincidence = 0;
+ int check_conditional;
+
+ if (detect_sccs(ctx, graph) < 0)
+ return -1;
+ if (sort_sccs(graph) < 0)
+ return -1;
+
+ if (compute_maxvar(graph) < 0)
+ return -1;
+
+ if (need_feautrier_step(ctx, graph))
+ return compute_schedule_wcc_feautrier(ctx, graph);
+
+ clear_local_edges(graph);
+ check_conditional = need_condition_check(graph);
+ has_coincidence = has_any_coincidence(graph);
+
+ if (ctx->opt->schedule_outer_coincidence)
+ force_coincidence = 1;
+
+ use_coincidence = has_coincidence;
+ while (graph->n_row < graph->maxvar) {
+ isl_vec *sol;
+ int violated;
+ int coincident;
+
+ graph->src_scc = -1;
+ graph->dst_scc = -1;
+
+ if (setup_lp(ctx, graph, use_coincidence) < 0)
+ return -1;
+ sol = solve_lp(graph);
+ if (!sol)
+ return -1;
+ if (sol->size == 0) {
+ int empty = graph->n_total_row == graph->band_start;
+
+ isl_vec_free(sol);
+ if (use_coincidence && (!force_coincidence || !empty)) {
+ use_coincidence = 0;
+ continue;
+ }
+ if (!ctx->opt->schedule_maximize_band_depth && !empty)
+ return compute_next_band(ctx, graph);
+ if (graph->src_scc >= 0)
+ return compute_split_schedule(ctx, graph);
+ if (!empty)
+ return compute_next_band(ctx, graph);
+ return carry_dependences(ctx, graph);
+ }
+ coincident = !has_coincidence || use_coincidence;
+ if (update_schedule(graph, sol, 1, coincident) < 0)
+ return -1;
+
+ if (!check_conditional)
+ continue;
+ violated = has_violated_conditional_constraint(ctx, graph);
+ if (violated < 0)
+ return -1;
+ if (!violated)
+ continue;
+ if (reset_band(graph) < 0)
+ return -1;
+ use_coincidence = has_coincidence;
+ }
+
+ if (graph->n_total_row > graph->band_start)
+ next_band(graph);
+ return sort_statements(ctx, graph);
+}
+
+/* Add a row to the schedules that separates the SCCs and move
+ * to the next band.
+ */
+static int split_on_scc(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ int i;
+
+ if (graph->n_total_row >= graph->max_row)
+ isl_die(ctx, isl_error_internal,
+ "too many schedule rows", return -1);
+
+ for (i = 0; i < graph->n; ++i) {
+ struct isl_sched_node *node = &graph->node[i];
+ int row = isl_mat_rows(node->sched);
+
+ isl_map_free(node->sched_map);
+ node->sched_map = NULL;
+ node->sched = isl_mat_add_zero_rows(node->sched, 1);
+ node->sched = isl_mat_set_element_si(node->sched, row, 0,
+ node->scc);
+ if (!node->sched)
+ return -1;
+ node->band[graph->n_total_row] = graph->n_band;
+ }
+
+ graph->n_total_row++;
+ next_band(graph);
+
+ return 0;
+}
+
+/* Compute a schedule for each component (identified by node->scc)
+ * of the dependence graph separately and then combine the results.
+ * Depending on the setting of schedule_fuse, a component may be
+ * either weakly or strongly connected.
+ *
+ * The band_id is adjusted such that each component has a separate id.
+ * Note that the band_id may have already been set to a value different
+ * from zero by compute_split_schedule.
+ */
+static int compute_component_schedule(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ int wcc, i;
+ int n, n_edge;
+ int n_total_row, orig_total_row;
+ int n_band, orig_band;
+
+ if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN ||
+ ctx->opt->schedule_separate_components)
+ if (split_on_scc(ctx, graph) < 0)
+ return -1;
+
+ n_total_row = 0;
+ orig_total_row = graph->n_total_row;
+ n_band = 0;
+ orig_band = graph->n_band;
+ for (i = 0; i < graph->n; ++i)
+ graph->node[i].band_id[graph->n_band] += graph->node[i].scc;
+ for (wcc = 0; wcc < graph->scc; ++wcc) {
+ n = 0;
+ for (i = 0; i < graph->n; ++i)
+ if (graph->node[i].scc == wcc)
+ n++;
+ n_edge = 0;
+ for (i = 0; i < graph->n_edge; ++i)
+ if (graph->edge[i].src->scc == wcc &&
+ graph->edge[i].dst->scc == wcc)
+ n_edge++;
+
+ if (compute_sub_schedule(ctx, graph, n, n_edge,
+ &node_scc_exactly,
+ &edge_scc_exactly, wcc, 1) < 0)
+ return -1;
+ if (graph->n_total_row > n_total_row)
+ n_total_row = graph->n_total_row;
+ graph->n_total_row = orig_total_row;
+ if (graph->n_band > n_band)
+ n_band = graph->n_band;
+ graph->n_band = orig_band;
+ }
+
+ graph->n_total_row = n_total_row;
+ graph->n_band = n_band;
+
+ return pad_schedule(graph);
+}
+
+/* Compute a schedule for the given dependence graph.
+ * We first check if the graph is connected (through validity and conditional
+ * validity dependences) and, if not, compute a schedule
+ * for each component separately.
+ * If schedule_fuse is set to minimal fusion, then we check for strongly
+ * connected components instead and compute a separate schedule for
+ * each such strongly connected component.
+ */
+static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
+{
+ if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN) {
+ if (detect_sccs(ctx, graph) < 0)
+ return -1;
+ } else {
+ if (detect_wccs(ctx, graph) < 0)
+ return -1;
+ }
+
+ if (graph->scc > 1)
+ return compute_component_schedule(ctx, graph);
+
+ return compute_schedule_wcc(ctx, graph);
+}
+
+/* Compute a schedule on sc->domain that respects the given schedule
+ * constraints.
+ *
+ * In particular, the schedule respects all the validity dependences.
+ * If the default isl scheduling algorithm is used, it tries to minimize
+ * the dependence distances over the proximity dependences.
+ * If Feautrier's scheduling algorithm is used, the proximity dependence
+ * distances are only minimized during the extension to a full-dimensional
+ * schedule.
+ *
+ * If there are any condition and conditional validity dependences,
+ * then the conditional validity dependences may be violated inside
+ * a tilable band, provided they have no adjacent non-local
+ * condition dependences.
+ */
+__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
+ __isl_take isl_schedule_constraints *sc)
+{
+ isl_ctx *ctx = isl_schedule_constraints_get_ctx(sc);
+ struct isl_sched_graph graph = { 0 };
+ isl_schedule *sched;
+ struct isl_extract_edge_data data;
+ enum isl_edge_type i;
+
+ sc = isl_schedule_constraints_align_params(sc);
+ if (!sc)
+ return NULL;
+
+ graph.n = isl_union_set_n_set(sc->domain);
+ if (graph.n == 0)
+ goto empty;
+ 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;
+ if (isl_union_set_foreach_set(sc->domain, &extract_node, &graph) < 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;
+ }
+
+ if (compute_schedule(ctx, &graph) < 0)
+ goto error;
+
+empty:
+ sched = extract_schedule(&graph, isl_union_set_get_space(sc->domain));
+
+ 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
+ * all the validity dependences and minimizes
+ * the dependence distances over the proximity dependences.
+ *
+ * This function is kept for backward compatibility.
+ */
+__isl_give isl_schedule *isl_union_set_compute_schedule(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_union_map *validity,
+ __isl_take isl_union_map *proximity)
+{
+ isl_schedule_constraints *sc;
+
+ sc = isl_schedule_constraints_on_domain(domain);
+ sc = isl_schedule_constraints_set_validity(sc, validity);
+ sc = isl_schedule_constraints_set_proximity(sc, proximity);
+
+ return isl_schedule_constraints_compute_schedule(sc);
+}
diff --git a/polly/lib/External/isl/isl_seq.c b/polly/lib/External/isl/isl_seq.c
new file mode 100644
index 00000000000..fbbc26f148c
--- /dev/null
+++ b/polly/lib/External/isl/isl_seq.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_seq.h>
+
+void isl_seq_clr(isl_int *p, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_set_si(p[i], 0);
+}
+
+void isl_seq_set_si(isl_int *p, int v, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_set_si(p[i], v);
+}
+
+void isl_seq_set(isl_int *p, isl_int v, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_set(p[i], v);
+}
+
+void isl_seq_neg(isl_int *dst, isl_int *src, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_neg(dst[i], src[i]);
+}
+
+void isl_seq_cpy(isl_int *dst, isl_int *src, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_set(dst[i], src[i]);
+}
+
+void isl_seq_submul(isl_int *dst, isl_int f, isl_int *src, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_submul(dst[i], f, src[i]);
+}
+
+void isl_seq_addmul(isl_int *dst, isl_int f, isl_int *src, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_addmul(dst[i], f, src[i]);
+}
+
+void isl_seq_swp_or_cpy(isl_int *dst, isl_int *src, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_swap_or_set(dst[i], src[i]);
+}
+
+void isl_seq_scale(isl_int *dst, isl_int *src, isl_int m, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_mul(dst[i], src[i], m);
+}
+
+void isl_seq_scale_down(isl_int *dst, isl_int *src, isl_int m, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_divexact(dst[i], src[i], m);
+}
+
+void isl_seq_cdiv_q(isl_int *dst, isl_int *src, isl_int m, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_cdiv_q(dst[i], src[i], m);
+}
+
+void isl_seq_fdiv_q(isl_int *dst, isl_int *src, isl_int m, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_fdiv_q(dst[i], src[i], m);
+}
+
+void isl_seq_fdiv_r(isl_int *dst, isl_int *src, isl_int m, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ isl_int_fdiv_r(dst[i], src[i], m);
+}
+
+void isl_seq_combine(isl_int *dst, isl_int m1, isl_int *src1,
+ isl_int m2, isl_int *src2, unsigned len)
+{
+ int i;
+ isl_int tmp;
+
+ isl_int_init(tmp);
+ for (i = 0; i < len; ++i) {
+ isl_int_mul(tmp, m1, src1[i]);
+ isl_int_addmul(tmp, m2, src2[i]);
+ isl_int_set(dst[i], tmp);
+ }
+ isl_int_clear(tmp);
+}
+
+/*
+ * Let d = dst[pos] and s = src[pos]
+ * dst is replaced by |s| dst - sgn(s)d src
+ */
+void isl_seq_elim(isl_int *dst, isl_int *src, unsigned pos, unsigned len,
+ isl_int *m)
+{
+ isl_int a;
+ isl_int b;
+
+ if (isl_int_is_zero(dst[pos]))
+ return;
+
+ isl_int_init(a);
+ isl_int_init(b);
+
+ isl_int_gcd(a, src[pos], dst[pos]);
+ isl_int_divexact(b, dst[pos], a);
+ if (isl_int_is_pos(src[pos]))
+ isl_int_neg(b, b);
+ isl_int_divexact(a, src[pos], a);
+ isl_int_abs(a, a);
+ isl_seq_combine(dst, a, dst, b, src, len);
+
+ if (m)
+ isl_int_mul(*m, *m, a);
+
+ isl_int_clear(a);
+ isl_int_clear(b);
+}
+
+int isl_seq_eq(isl_int *p1, isl_int *p2, unsigned len)
+{
+ int i;
+ for (i = 0; i < len; ++i)
+ if (isl_int_ne(p1[i], p2[i]))
+ return 0;
+ return 1;
+}
+
+int isl_seq_cmp(isl_int *p1, isl_int *p2, unsigned len)
+{
+ int i;
+ int cmp;
+ for (i = 0; i < len; ++i)
+ if ((cmp = isl_int_cmp(p1[i], p2[i])) != 0)
+ return cmp;
+ return 0;
+}
+
+int isl_seq_is_neg(isl_int *p1, isl_int *p2, unsigned len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ if (isl_int_abs_ne(p1[i], p2[i]))
+ return 0;
+ if (isl_int_is_zero(p1[i]))
+ continue;
+ if (isl_int_eq(p1[i], p2[i]))
+ return 0;
+ }
+ return 1;
+}
+
+int isl_seq_first_non_zero(isl_int *p, unsigned len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i)
+ if (!isl_int_is_zero(p[i]))
+ return i;
+ return -1;
+}
+
+int isl_seq_last_non_zero(isl_int *p, unsigned len)
+{
+ int i;
+
+ for (i = len - 1; i >= 0; --i)
+ if (!isl_int_is_zero(p[i]))
+ return i;
+ return -1;
+}
+
+void isl_seq_abs_max(isl_int *p, unsigned len, isl_int *max)
+{
+ int i;
+
+ isl_int_set_si(*max, 0);
+
+ for (i = 0; i < len; ++i)
+ if (isl_int_abs_gt(p[i], *max))
+ isl_int_abs(*max, p[i]);
+}
+
+int isl_seq_abs_min_non_zero(isl_int *p, unsigned len)
+{
+ int i, min = isl_seq_first_non_zero(p, len);
+ if (min < 0)
+ return -1;
+ for (i = min + 1; i < len; ++i) {
+ if (isl_int_is_zero(p[i]))
+ continue;
+ if (isl_int_abs_lt(p[i], p[min]))
+ min = i;
+ }
+ return min;
+}
+
+void isl_seq_gcd(isl_int *p, unsigned len, isl_int *gcd)
+{
+ int i, min = isl_seq_abs_min_non_zero(p, len);
+
+ if (min < 0) {
+ isl_int_set_si(*gcd, 0);
+ return;
+ }
+ isl_int_abs(*gcd, p[min]);
+ for (i = 0; isl_int_cmp_si(*gcd, 1) > 0 && i < len; ++i) {
+ if (i == min)
+ continue;
+ if (isl_int_is_zero(p[i]))
+ continue;
+ isl_int_gcd(*gcd, *gcd, p[i]);
+ }
+}
+
+void isl_seq_normalize(struct isl_ctx *ctx, isl_int *p, unsigned len)
+{
+ if (len == 0)
+ return;
+ isl_seq_gcd(p, len, &ctx->normalize_gcd);
+ if (!isl_int_is_zero(ctx->normalize_gcd) &&
+ !isl_int_is_one(ctx->normalize_gcd))
+ isl_seq_scale_down(p, p, ctx->normalize_gcd, len);
+}
+
+void isl_seq_lcm(isl_int *p, unsigned len, isl_int *lcm)
+{
+ int i;
+
+ if (len == 0) {
+ isl_int_set_si(*lcm, 1);
+ return;
+ }
+ isl_int_set(*lcm, p[0]);
+ for (i = 1; i < len; ++i)
+ isl_int_lcm(*lcm, *lcm, p[i]);
+}
+
+void isl_seq_inner_product(isl_int *p1, isl_int *p2, unsigned len,
+ isl_int *prod)
+{
+ int i;
+ if (len == 0) {
+ isl_int_set_si(*prod, 0);
+ return;
+ }
+ isl_int_mul(*prod, p1[0], p2[0]);
+ for (i = 1; i < len; ++i)
+ isl_int_addmul(*prod, p1[i], p2[i]);
+}
+
+uint32_t isl_seq_hash(isl_int *p, unsigned len, uint32_t hash)
+{
+ int i;
+ for (i = 0; i < len; ++i) {
+ if (isl_int_is_zero(p[i]))
+ continue;
+ hash *= 16777619;
+ hash ^= (i & 0xFF);
+ hash = isl_int_hash(p[i], hash);
+ }
+ return hash;
+}
+
+uint32_t isl_seq_get_hash(isl_int *p, unsigned len)
+{
+ uint32_t hash = isl_hash_init();
+
+ return isl_seq_hash(p, len, hash);
+}
+
+uint32_t isl_seq_get_hash_bits(isl_int *p, unsigned len, unsigned bits)
+{
+ uint32_t hash;
+
+ hash = isl_seq_get_hash(p, len);
+ return isl_hash_bits(hash, bits);
+}
+
+void isl_seq_dump(isl_int *p, unsigned len)
+{
+ int i;
+
+ for (i = 0; i < len; ++i) {
+ if (i)
+ fprintf(stderr, " ");
+ isl_int_print(stderr, p[i], 0);
+ }
+ fprintf(stderr, "\n");
+}
diff --git a/polly/lib/External/isl/isl_seq.h b/polly/lib/External/isl/isl_seq.h
new file mode 100644
index 00000000000..05825f28720
--- /dev/null
+++ b/polly/lib/External/isl/isl_seq.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_SEQ_H
+#define ISL_SEQ_H
+
+#include <sys/types.h>
+#include <isl_int.h>
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Some common operations on sequences of isl_int's */
+
+void isl_seq_clr(isl_int *p, unsigned len);
+void isl_seq_set(isl_int *p, isl_int v, unsigned len);
+void isl_seq_set_si(isl_int *p, int v, unsigned len);
+void isl_seq_neg(isl_int *dst, isl_int *src, unsigned len);
+void isl_seq_cpy(isl_int *dst, isl_int *src, unsigned len);
+void isl_seq_addmul(isl_int *dst, isl_int f, isl_int *src, unsigned len);
+void isl_seq_submul(isl_int *dst, isl_int f, isl_int *src, unsigned len);
+void isl_seq_swp_or_cpy(isl_int *dst, isl_int *src, unsigned len);
+void isl_seq_scale(isl_int *dst, isl_int *src, isl_int f, unsigned len);
+void isl_seq_scale_down(isl_int *dst, isl_int *src, isl_int f, unsigned len);
+void isl_seq_cdiv_q(isl_int *dst, isl_int *src, isl_int m, unsigned len);
+void isl_seq_fdiv_q(isl_int *dst, isl_int *src, isl_int m, unsigned len);
+void isl_seq_fdiv_r(isl_int *dst, isl_int *src, isl_int m, unsigned len);
+void isl_seq_combine(isl_int *dst, isl_int m1, isl_int *src1,
+ isl_int m2, isl_int *src2, unsigned len);
+void isl_seq_elim(isl_int *dst, isl_int *src, unsigned pos, unsigned len,
+ isl_int *m);
+void isl_seq_abs_max(isl_int *p, unsigned len, isl_int *max);
+void isl_seq_gcd(isl_int *p, unsigned len, isl_int *gcd);
+void isl_seq_lcm(isl_int *p, unsigned len, isl_int *lcm);
+void isl_seq_normalize(struct isl_ctx *ctx, isl_int *p, unsigned len);
+void isl_seq_inner_product(isl_int *p1, isl_int *p2, unsigned len,
+ isl_int *prod);
+int isl_seq_first_non_zero(isl_int *p, unsigned len);
+int isl_seq_last_non_zero(isl_int *p, unsigned len);
+int isl_seq_abs_min_non_zero(isl_int *p, unsigned len);
+int isl_seq_eq(isl_int *p1, isl_int *p2, unsigned len);
+int isl_seq_cmp(isl_int *p1, isl_int *p2, unsigned len);
+int isl_seq_is_neg(isl_int *p1, isl_int *p2, unsigned len);
+
+uint32_t isl_seq_get_hash(isl_int *p, unsigned len);
+uint32_t isl_seq_get_hash_bits(isl_int *p, unsigned len, unsigned bits);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
diff --git a/polly/lib/External/isl/isl_set_list.c b/polly/lib/External/isl/isl_set_list.c
new file mode 100644
index 00000000000..b27982748a7
--- /dev/null
+++ b/polly/lib/External/isl/isl_set_list.c
@@ -0,0 +1,21 @@
+#include <isl/set.h>
+
+#undef EL
+#define EL isl_basic_set
+
+#include <isl_list_templ.h>
+
+#undef EL
+#define EL isl_set
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE basic_set
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE set
+
+#include <isl_list_templ.c>
diff --git a/polly/lib/External/isl/isl_sort.c b/polly/lib/External/isl/isl_sort.c
new file mode 100644
index 00000000000..9ed273caa18
--- /dev/null
+++ b/polly/lib/External/isl/isl_sort.c
@@ -0,0 +1,157 @@
+/*
+ * The code of this file was taken from http://jeffreystedfast.blogspot.be,
+ * where it was posted in 2011 by Jeffrey Stedfast under the MIT license.
+ * The MIT license text is as follows:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <isl_sort.h>
+
+#define MID(lo, hi) (lo + ((hi - lo) >> 1))
+
+/* The code here is an optimized merge sort. Starting from a generic merge sort
+ * the following optimizations were applied:
+ *
+ * o Batching of memcpy() calls: Instead of calling memcpy() to copy each and
+ * every element into a temporary buffer, blocks of elements are copied
+ * at a time.
+ *
+ * o To reduce the number of memcpy() calls further, copying leading
+ * and trailing elements into our temporary buffer is avoided, in case it is
+ * not necessary to merge them.
+ *
+ * A further optimization could be to specialize memcpy calls based on the
+ * size of the types we compare. For now, this code does not include the
+ * relevant optimization, as clang e.g. inlines a very efficient memcpy()
+ * implementation. It is not clear, that the specialized version as provided in
+ * the blog post, is really superior to the one that will be inlined by
+ * default. So we decided to keep the code simple until this optimization was
+ * proven to be beneficial.
+ */
+
+static void
+msort (void *array, void *buf, size_t low, size_t high, size_t size,
+ int (* compare) (const void *, const void *, void *), void *arg)
+{
+ char *a1, *al, *am, *ah, *ls, *hs, *lo, *hi, *b;
+ size_t copied = 0;
+ size_t mid;
+
+ mid = MID (low, high);
+
+ if (mid + 1 < high)
+ msort (array, buf, mid + 1, high, size, compare, arg);
+
+ if (mid > low)
+ msort (array, buf, low, mid, size, compare, arg);
+
+ ah = ((char *) array) + ((high + 1) * size);
+ am = ((char *) array) + ((mid + 1) * size);
+ a1 = al = ((char *) array) + (low * size);
+
+ b = (char *) buf;
+ lo = al;
+ hi = am;
+
+ do {
+ ls = lo;
+ hs = hi;
+
+ if (lo > al || hi > am) {
+ /* our last loop already compared lo & hi and found lo <= hi */
+ lo += size;
+ }
+
+ while (lo < am && compare (lo, hi, arg) <= 0)
+ lo += size;
+
+ if (lo < am) {
+ if (copied == 0) {
+ /* avoid copying the leading items */
+ a1 = lo;
+ ls = lo;
+ }
+
+ /* our last compare tells us hi < lo */
+ hi += size;
+
+ while (hi < ah && compare (hi, lo, arg) < 0)
+ hi += size;
+
+ if (lo > ls) {
+ memcpy (b, ls, lo - ls);
+ copied += (lo - ls);
+ b += (lo - ls);
+ }
+
+ memcpy (b, hs, hi - hs);
+ copied += (hi - hs);
+ b += (hi - hs);
+ } else if (copied) {
+ memcpy (b, ls, lo - ls);
+ copied += (lo - ls);
+ b += (lo - ls);
+
+ /* copy everything we needed to re-order back into array */
+ memcpy (a1, buf, copied);
+ return;
+ } else {
+ /* everything already in order */
+ return;
+ }
+ } while (hi < ah);
+
+ if (lo < am) {
+ memcpy (b, lo, am - lo);
+ copied += (am - lo);
+ }
+
+ memcpy (a1, buf, copied);
+}
+
+static int
+MergeSort (void *base, size_t nmemb, size_t size,
+ int (* compare) (const void *, const void *, void *), void *arg)
+{
+ void *tmp;
+
+ if (nmemb < 2)
+ return 0;
+
+ if (!(tmp = malloc (nmemb * size))) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ msort (base, tmp, 0, nmemb - 1, size, compare, arg);
+
+ free (tmp);
+
+ return 0;
+}
+
+int isl_sort(void *const pbase, size_t total_elems, size_t size,
+ int (*cmp)(const void *, const void *, void *arg), void *arg)
+{
+ return MergeSort (pbase, total_elems, size, cmp, arg);
+}
diff --git a/polly/lib/External/isl/isl_sort.h b/polly/lib/External/isl/isl_sort.h
new file mode 100644
index 00000000000..b69fe01d991
--- /dev/null
+++ b/polly/lib/External/isl/isl_sort.h
@@ -0,0 +1,9 @@
+#ifndef ISL_SORT_H
+#define ISL_SORT_H
+
+#include <stddef.h>
+
+int isl_sort(void *const pbase, size_t total_elems, size_t size,
+ int (*cmp)(const void *, const void *, void *arg), void *arg);
+
+#endif
diff --git a/polly/lib/External/isl/isl_space.c b/polly/lib/External/isl/isl_space.c
new file mode 100644
index 00000000000..1a5d6d3b2d8
--- /dev/null
+++ b/polly/lib/External/isl/isl_space.c
@@ -0,0 +1,2379 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2013-2014 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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 <stdlib.h>
+#include <string.h>
+#include <isl_space_private.h>
+#include <isl_id_private.h>
+#include <isl_reordering.h>
+
+isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim)
+{
+ return dim ? dim->ctx : NULL;
+}
+
+__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned n_in, unsigned n_out)
+{
+ isl_space *dim;
+
+ dim = isl_alloc_type(ctx, struct isl_space);
+ if (!dim)
+ return NULL;
+
+ dim->ctx = ctx;
+ isl_ctx_ref(ctx);
+ dim->ref = 1;
+ dim->nparam = nparam;
+ dim->n_in = n_in;
+ dim->n_out = n_out;
+
+ dim->tuple_id[0] = NULL;
+ dim->tuple_id[1] = NULL;
+
+ dim->nested[0] = NULL;
+ dim->nested[1] = NULL;
+
+ dim->n_id = 0;
+ dim->ids = NULL;
+
+ return dim;
+}
+
+/* Mark the space as being that of a set, by setting the domain tuple
+ * to isl_id_none.
+ */
+static __isl_give isl_space *mark_as_set(__isl_take isl_space *space)
+{
+ space = isl_space_cow(space);
+ if (!space)
+ return NULL;
+ space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
+ return space;
+}
+
+/* Is the space that of a set?
+ */
+int isl_space_is_set(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+ if (space->n_in != 0 || space->nested[0])
+ return 0;
+ if (space->tuple_id[0] != &isl_id_none)
+ return 0;
+ return 1;
+}
+
+/* Is the given space that of a map?
+ */
+int isl_space_is_map(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+ return space->tuple_id[0] != &isl_id_none &&
+ space->tuple_id[1] != &isl_id_none;
+}
+
+__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
+ unsigned nparam, unsigned dim)
+{
+ isl_space *space;
+ space = isl_space_alloc(ctx, nparam, 0, dim);
+ space = mark_as_set(space);
+ return space;
+}
+
+/* Mark the space as being that of a parameter domain, by setting
+ * both tuples to isl_id_none.
+ */
+static __isl_give isl_space *mark_as_params(isl_space *space)
+{
+ if (!space)
+ return NULL;
+ space = isl_space_set_tuple_id(space, isl_dim_in, &isl_id_none);
+ space = isl_space_set_tuple_id(space, isl_dim_out, &isl_id_none);
+ return space;
+}
+
+/* Is the space that of a parameter domain?
+ */
+int isl_space_is_params(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+ if (space->n_in != 0 || space->nested[0] ||
+ space->n_out != 0 || space->nested[1])
+ return 0;
+ if (space->tuple_id[0] != &isl_id_none)
+ return 0;
+ if (space->tuple_id[1] != &isl_id_none)
+ return 0;
+ return 1;
+}
+
+/* Create a space for a parameter domain.
+ */
+__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam)
+{
+ isl_space *space;
+ space = isl_space_alloc(ctx, nparam, 0, 0);
+ space = mark_as_params(space);
+ return space;
+}
+
+static unsigned global_pos(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ struct isl_ctx *ctx = dim->ctx;
+
+ switch (type) {
+ case isl_dim_param:
+ isl_assert(ctx, pos < dim->nparam,
+ return isl_space_dim(dim, isl_dim_all));
+ return pos;
+ case isl_dim_in:
+ isl_assert(ctx, pos < dim->n_in,
+ return isl_space_dim(dim, isl_dim_all));
+ return pos + dim->nparam;
+ case isl_dim_out:
+ isl_assert(ctx, pos < dim->n_out,
+ return isl_space_dim(dim, isl_dim_all));
+ return pos + dim->nparam + dim->n_in;
+ default:
+ isl_assert(ctx, 0, return isl_space_dim(dim, isl_dim_all));
+ }
+ return isl_space_dim(dim, isl_dim_all);
+}
+
+/* Extend length of ids array to the total number of dimensions.
+ */
+static __isl_give isl_space *extend_ids(__isl_take isl_space *dim)
+{
+ isl_id **ids;
+ int i;
+
+ if (isl_space_dim(dim, isl_dim_all) <= dim->n_id)
+ return dim;
+
+ if (!dim->ids) {
+ dim->ids = isl_calloc_array(dim->ctx,
+ isl_id *, isl_space_dim(dim, isl_dim_all));
+ if (!dim->ids)
+ goto error;
+ } else {
+ ids = isl_realloc_array(dim->ctx, dim->ids,
+ isl_id *, isl_space_dim(dim, isl_dim_all));
+ if (!ids)
+ goto error;
+ dim->ids = ids;
+ for (i = dim->n_id; i < isl_space_dim(dim, isl_dim_all); ++i)
+ dim->ids[i] = NULL;
+ }
+
+ dim->n_id = isl_space_dim(dim, isl_dim_all);
+
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+static __isl_give isl_space *set_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ dim = isl_space_cow(dim);
+
+ if (!dim)
+ goto error;
+
+ pos = global_pos(dim, type, pos);
+ if (pos == isl_space_dim(dim, isl_dim_all))
+ goto error;
+
+ if (pos >= dim->n_id) {
+ if (!id)
+ return dim;
+ dim = extend_ids(dim);
+ if (!dim)
+ goto error;
+ }
+
+ dim->ids[pos] = id;
+
+ return dim;
+error:
+ isl_id_free(id);
+ isl_space_free(dim);
+ return NULL;
+}
+
+static __isl_keep isl_id *get_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!dim)
+ return NULL;
+
+ pos = global_pos(dim, type, pos);
+ if (pos == isl_space_dim(dim, isl_dim_all))
+ return NULL;
+ if (pos >= dim->n_id)
+ return NULL;
+ return dim->ids[pos];
+}
+
+static unsigned offset(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param: return 0;
+ case isl_dim_in: return dim->nparam;
+ case isl_dim_out: return dim->nparam + dim->n_in;
+ default: return 0;
+ }
+}
+
+static unsigned n(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param: return dim->nparam;
+ case isl_dim_in: return dim->n_in;
+ case isl_dim_out: return dim->n_out;
+ case isl_dim_all: return dim->nparam + dim->n_in + dim->n_out;
+ default: return 0;
+ }
+}
+
+unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ if (!dim)
+ return 0;
+ return n(dim, type);
+}
+
+unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ if (!dim)
+ return 0;
+ return offset(dim, type);
+}
+
+static __isl_give isl_space *copy_ids(__isl_take isl_space *dst,
+ enum isl_dim_type dst_type, unsigned offset, __isl_keep isl_space *src,
+ enum isl_dim_type src_type)
+{
+ int i;
+ isl_id *id;
+
+ if (!dst)
+ return NULL;
+
+ for (i = 0; i < n(src, src_type); ++i) {
+ id = get_id(src, src_type, i);
+ if (!id)
+ continue;
+ dst = set_id(dst, dst_type, offset + i, isl_id_copy(id));
+ if (!dst)
+ return NULL;
+ }
+ return dst;
+}
+
+__isl_take isl_space *isl_space_dup(__isl_keep isl_space *dim)
+{
+ isl_space *dup;
+ if (!dim)
+ return NULL;
+ dup = isl_space_alloc(dim->ctx, dim->nparam, dim->n_in, dim->n_out);
+ if (!dup)
+ return NULL;
+ if (dim->tuple_id[0] &&
+ !(dup->tuple_id[0] = isl_id_copy(dim->tuple_id[0])))
+ goto error;
+ if (dim->tuple_id[1] &&
+ !(dup->tuple_id[1] = isl_id_copy(dim->tuple_id[1])))
+ goto error;
+ if (dim->nested[0] && !(dup->nested[0] = isl_space_copy(dim->nested[0])))
+ goto error;
+ if (dim->nested[1] && !(dup->nested[1] = isl_space_copy(dim->nested[1])))
+ goto error;
+ if (!dim->ids)
+ return dup;
+ dup = copy_ids(dup, isl_dim_param, 0, dim, isl_dim_param);
+ dup = copy_ids(dup, isl_dim_in, 0, dim, isl_dim_in);
+ dup = copy_ids(dup, isl_dim_out, 0, dim, isl_dim_out);
+ return dup;
+error:
+ isl_space_free(dup);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+
+ if (dim->ref == 1)
+ return dim;
+ dim->ref--;
+ return isl_space_dup(dim);
+}
+
+__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+
+ dim->ref++;
+ return dim;
+}
+
+__isl_null isl_space *isl_space_free(__isl_take isl_space *space)
+{
+ int i;
+
+ if (!space)
+ return NULL;
+
+ if (--space->ref > 0)
+ return NULL;
+
+ isl_id_free(space->tuple_id[0]);
+ isl_id_free(space->tuple_id[1]);
+
+ isl_space_free(space->nested[0]);
+ isl_space_free(space->nested[1]);
+
+ for (i = 0; i < space->n_id; ++i)
+ isl_id_free(space->ids[i]);
+ free(space->ids);
+ isl_ctx_deref(space->ctx);
+
+ free(space);
+
+ return NULL;
+}
+
+/* Check if "s" is a valid dimension or tuple name.
+ * We currently only forbid names that look like a number.
+ *
+ * s is assumed to be non-NULL.
+ */
+static int name_ok(isl_ctx *ctx, const char *s)
+{
+ char *p;
+ long dummy;
+
+ dummy = strtol(s, &p, 0);
+ if (p != s)
+ isl_die(ctx, isl_error_invalid, "name looks like a number",
+ return 0);
+
+ return 1;
+}
+
+/* Is it possible for the given dimension type to have a tuple id?
+ */
+static int space_can_have_id(__isl_keep isl_space *space,
+ enum isl_dim_type type)
+{
+ if (!space)
+ return 0;
+ if (isl_space_is_params(space))
+ isl_die(space->ctx, isl_error_invalid,
+ "parameter spaces don't have tuple ids", return 0);
+ if (isl_space_is_set(space) && type != isl_dim_set)
+ isl_die(space->ctx, isl_error_invalid,
+ "set spaces can only have a set id", return 0);
+ if (type != isl_dim_in && type != isl_dim_out)
+ isl_die(space->ctx, isl_error_invalid,
+ "only input, output and set tuples can have ids",
+ return 0);
+
+ return 1;
+}
+
+/* Does the tuple have an id?
+ */
+int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ if (!space_can_have_id(dim, type))
+ return -1;
+ return dim->tuple_id[type - isl_dim_in] != NULL;
+}
+
+__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ int has_id;
+
+ if (!dim)
+ return NULL;
+ has_id = isl_space_has_tuple_id(dim, type);
+ if (has_id < 0)
+ return NULL;
+ if (!has_id)
+ isl_die(dim->ctx, isl_error_invalid,
+ "tuple has no id", return NULL);
+ return isl_id_copy(dim->tuple_id[type - isl_dim_in]);
+}
+
+__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type, __isl_take isl_id *id)
+{
+ dim = isl_space_cow(dim);
+ if (!dim || !id)
+ goto error;
+ if (type != isl_dim_in && type != isl_dim_out)
+ isl_die(dim->ctx, isl_error_invalid,
+ "only input, output and set tuples can have names",
+ goto error);
+
+ isl_id_free(dim->tuple_id[type - isl_dim_in]);
+ dim->tuple_id[type - isl_dim_in] = id;
+
+ return dim;
+error:
+ isl_id_free(id);
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
+ enum isl_dim_type type)
+{
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+ if (type != isl_dim_in && type != isl_dim_out)
+ isl_die(dim->ctx, isl_error_invalid,
+ "only input, output and set tuples can have names",
+ goto error);
+
+ isl_id_free(dim->tuple_id[type - isl_dim_in]);
+ dim->tuple_id[type - isl_dim_in] = NULL;
+
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Set the id of the given dimension of "space" to "id".
+ * If the dimension already has an id, then it is replaced.
+ * If the dimension is a parameter, then we need to change it
+ * in the nested spaces (if any) as well.
+ */
+__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *space,
+ enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+ space = isl_space_cow(space);
+ if (!space || !id)
+ goto error;
+
+ if (type == isl_dim_param) {
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ if (!space->nested[i])
+ continue;
+ space->nested[i] =
+ isl_space_set_dim_id(space->nested[i],
+ type, pos, isl_id_copy(id));
+ if (!space->nested[i])
+ goto error;
+ }
+ }
+
+ isl_id_free(get_id(space, type, pos));
+ return set_id(space, type, pos, id);
+error:
+ isl_id_free(id);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Reset the id of the given dimension of "space".
+ * If the dimension already has an id, then it is removed.
+ * If the dimension is a parameter, then we need to reset it
+ * in the nested spaces (if any) as well.
+ */
+__isl_give isl_space *isl_space_reset_dim_id(__isl_take isl_space *space,
+ enum isl_dim_type type, unsigned pos)
+{
+ space = isl_space_cow(space);
+ if (!space)
+ goto error;
+
+ if (type == isl_dim_param) {
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ if (!space->nested[i])
+ continue;
+ space->nested[i] =
+ isl_space_reset_dim_id(space->nested[i],
+ type, pos);
+ if (!space->nested[i])
+ goto error;
+ }
+ }
+
+ isl_id_free(get_id(space, type, pos));
+ return set_id(space, type, pos, NULL);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+int isl_space_has_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!dim)
+ return -1;
+ return get_id(dim, type, pos) != NULL;
+}
+
+__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!dim)
+ return NULL;
+ if (!get_id(dim, type, pos))
+ isl_die(dim->ctx, isl_error_invalid,
+ "dim has no id", return NULL);
+ return isl_id_copy(get_id(dim, type, pos));
+}
+
+__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, const char *s)
+{
+ isl_id *id;
+
+ if (!dim)
+ return NULL;
+
+ if (!s)
+ return isl_space_reset_tuple_id(dim, type);
+
+ if (!name_ok(dim->ctx, s))
+ goto error;
+
+ id = isl_id_alloc(dim->ctx, s, NULL);
+ return isl_space_set_tuple_id(dim, type, id);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Does the tuple have a name?
+ */
+int isl_space_has_tuple_name(__isl_keep isl_space *space,
+ enum isl_dim_type type)
+{
+ isl_id *id;
+
+ if (!space_can_have_id(space, type))
+ return -1;
+ id = space->tuple_id[type - isl_dim_in];
+ return id && id->name;
+}
+
+const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ isl_id *id;
+ if (!dim)
+ return NULL;
+ if (type != isl_dim_in && type != isl_dim_out)
+ return NULL;
+ id = dim->tuple_id[type - isl_dim_in];
+ return id ? id->name : NULL;
+}
+
+__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos,
+ const char *s)
+{
+ isl_id *id;
+
+ if (!dim)
+ return NULL;
+ if (!s)
+ return isl_space_reset_dim_id(dim, type, pos);
+ if (!name_ok(dim->ctx, s))
+ goto error;
+ id = isl_id_alloc(dim->ctx, s, NULL);
+ return isl_space_set_dim_id(dim, type, pos, id);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Does the given dimension have a name?
+ */
+int isl_space_has_dim_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, unsigned pos)
+{
+ isl_id *id;
+
+ if (!space)
+ return -1;
+ id = get_id(space, type, pos);
+ return id && id->name;
+}
+
+__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
+ enum isl_dim_type type, unsigned pos)
+{
+ isl_id *id = get_id(dim, type, pos);
+ return id ? id->name : NULL;
+}
+
+int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type,
+ __isl_keep isl_id *id)
+{
+ int i;
+ int offset;
+ int n;
+
+ if (!dim || !id)
+ return -1;
+
+ offset = isl_space_offset(dim, type);
+ n = isl_space_dim(dim, type);
+ for (i = 0; i < n && offset + i < dim->n_id; ++i)
+ if (dim->ids[offset + i] == id)
+ return i;
+
+ return -1;
+}
+
+int isl_space_find_dim_by_name(__isl_keep isl_space *space,
+ enum isl_dim_type type, const char *name)
+{
+ int i;
+ int offset;
+ int n;
+
+ if (!space || !name)
+ return -1;
+
+ offset = isl_space_offset(space, type);
+ n = isl_space_dim(space, type);
+ for (i = 0; i < n && offset + i < space->n_id; ++i)
+ if (space->ids[offset + i]->name &&
+ !strcmp(space->ids[offset + i]->name, name))
+ return i;
+
+ return -1;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of "space".
+ */
+__isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_id *id;
+ const char *name;
+
+ if (!space)
+ return NULL;
+
+ ctx = isl_space_get_ctx(space);
+
+ for (i = 0; i < space->nparam && i < space->n_id; ++i) {
+ if (!isl_id_get_user(space->ids[i]))
+ continue;
+ space = isl_space_cow(space);
+ if (!space)
+ return NULL;
+ name = isl_id_get_name(space->ids[i]);
+ id = isl_id_alloc(ctx, name, NULL);
+ isl_id_free(space->ids[i]);
+ space->ids[i] = id;
+ if (!id)
+ return isl_space_free(space);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ if (!space->tuple_id[i])
+ continue;
+ if (!isl_id_get_user(space->tuple_id[i]))
+ continue;
+ space = isl_space_cow(space);
+ if (!space)
+ return NULL;
+ name = isl_id_get_name(space->tuple_id[i]);
+ id = isl_id_alloc(ctx, name, NULL);
+ isl_id_free(space->tuple_id[i]);
+ space->tuple_id[i] = id;
+ if (!id)
+ return isl_space_free(space);
+ }
+
+ for (i = 0; i < 2; ++i) {
+ if (!space->nested[i])
+ continue;
+ space = isl_space_cow(space);
+ if (!space)
+ return NULL;
+ space->nested[i] = isl_space_reset_user(space->nested[i]);
+ if (!space->nested[i])
+ return isl_space_free(space);
+ }
+
+ return space;
+}
+
+static __isl_keep isl_id *tuple_id(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ if (!dim)
+ return NULL;
+ if (type == isl_dim_in)
+ return dim->tuple_id[0];
+ if (type == isl_dim_out)
+ return dim->tuple_id[1];
+ return NULL;
+}
+
+static __isl_keep isl_space *nested(__isl_keep isl_space *dim,
+ enum isl_dim_type type)
+{
+ if (!dim)
+ return NULL;
+ if (type == isl_dim_in)
+ return dim->nested[0];
+ if (type == isl_dim_out)
+ return dim->nested[1];
+ return NULL;
+}
+
+/* Are the two spaces the same, apart from positions and names of parameters?
+ */
+static int isl_space_has_equal_tuples(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2)
+{
+ if (!space1 || !space2)
+ return -1;
+ if (space1 == space2)
+ return 1;
+ return isl_space_tuple_is_equal(space1, isl_dim_in,
+ space2, isl_dim_in) &&
+ isl_space_tuple_is_equal(space1, isl_dim_out,
+ space2, isl_dim_out);
+}
+
+/* Check if the tuple of type "type1" of "space1" is the same as
+ * the tuple of type "type2" of "space2".
+ *
+ * That is, check if the tuples have the same identifier, the same dimension
+ * and the same internal structure.
+ * The identifiers of the dimensions inside the tuples do not affect the result.
+ *
+ * Note that this function only checks the tuples themselves.
+ * If nested tuples are involved, then we need to be careful not
+ * to have result affected by possibly differing parameters
+ * in those nested tuples.
+ */
+int isl_space_tuple_is_equal(__isl_keep isl_space *space1,
+ enum isl_dim_type type1, __isl_keep isl_space *space2,
+ enum isl_dim_type type2)
+{
+ isl_id *id1, *id2;
+ isl_space *nested1, *nested2;
+
+ if (!space1 || !space2)
+ return -1;
+
+ if (space1 == space2 && type1 == type2)
+ return 1;
+
+ if (n(space1, type1) != n(space2, type2))
+ return 0;
+ id1 = tuple_id(space1, type1);
+ id2 = tuple_id(space2, type2);
+ if (!id1 ^ !id2)
+ return 0;
+ if (id1 && id1 != id2)
+ return 0;
+ nested1 = nested(space1, type1);
+ nested2 = nested(space2, type2);
+ if (!nested1 ^ !nested2)
+ return 0;
+ if (nested1 && !isl_space_has_equal_tuples(nested1, nested2))
+ return 0;
+ return 1;
+}
+
+/* This is the old, undocumented, name for isl_space_tuple_is_equal.
+ * It will be removed at some point.
+ */
+int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
+ __isl_keep isl_space *space2, enum isl_dim_type type2)
+{
+ return isl_space_tuple_is_equal(space1, type1, space2, type2);
+}
+
+static int match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
+ __isl_keep isl_space *dim2, enum isl_dim_type dim2_type)
+{
+ int i;
+
+ if (dim1 == dim2 && dim1_type == dim2_type)
+ return 1;
+
+ if (!isl_space_tuple_is_equal(dim1, dim1_type, dim2, dim2_type))
+ return 0;
+
+ if (!dim1->ids && !dim2->ids)
+ return 1;
+
+ for (i = 0; i < n(dim1, dim1_type); ++i) {
+ if (get_id(dim1, dim1_type, i) != get_id(dim2, dim2_type, i))
+ return 0;
+ }
+ return 1;
+}
+
+int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
+ __isl_keep isl_space *dim2, enum isl_dim_type dim2_type)
+{
+ if (!dim1 || !dim2)
+ return -1;
+
+ return match(dim1, dim1_type, dim2, dim2_type);
+}
+
+static void get_ids(__isl_keep isl_space *dim, enum isl_dim_type type,
+ unsigned first, unsigned n, __isl_keep isl_id **ids)
+{
+ int i;
+
+ for (i = 0; i < n ; ++i)
+ ids[i] = get_id(dim, type, first + i);
+}
+
+__isl_give isl_space *isl_space_extend(__isl_take isl_space *dim,
+ unsigned nparam, unsigned n_in, unsigned n_out)
+{
+ isl_id **ids = NULL;
+
+ if (!dim)
+ return NULL;
+ if (dim->nparam == nparam && dim->n_in == n_in && dim->n_out == n_out)
+ return dim;
+
+ isl_assert(dim->ctx, dim->nparam <= nparam, goto error);
+ isl_assert(dim->ctx, dim->n_in <= n_in, goto error);
+ isl_assert(dim->ctx, dim->n_out <= n_out, goto error);
+
+ dim = isl_space_cow(dim);
+ if (!dim)
+ goto error;
+
+ if (dim->ids) {
+ ids = isl_calloc_array(dim->ctx, isl_id *,
+ nparam + n_in + n_out);
+ if (!ids)
+ goto error;
+ get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
+ get_ids(dim, isl_dim_in, 0, dim->n_in, ids + nparam);
+ get_ids(dim, isl_dim_out, 0, dim->n_out, ids + nparam + n_in);
+ free(dim->ids);
+ dim->ids = ids;
+ dim->n_id = nparam + n_in + n_out;
+ }
+ dim->nparam = nparam;
+ dim->n_in = n_in;
+ dim->n_out = n_out;
+
+ return dim;
+error:
+ free(ids);
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_add_dims(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned n)
+{
+ if (!dim)
+ return NULL;
+ dim = isl_space_reset(dim, type);
+ switch (type) {
+ case isl_dim_param:
+ dim = isl_space_extend(dim,
+ dim->nparam + n, dim->n_in, dim->n_out);
+ if (dim && dim->nested[0] &&
+ !(dim->nested[0] = isl_space_add_dims(dim->nested[0],
+ isl_dim_param, n)))
+ goto error;
+ if (dim && dim->nested[1] &&
+ !(dim->nested[1] = isl_space_add_dims(dim->nested[1],
+ isl_dim_param, n)))
+ goto error;
+ return dim;
+ case isl_dim_in:
+ return isl_space_extend(dim,
+ dim->nparam, dim->n_in + n, dim->n_out);
+ case isl_dim_out:
+ return isl_space_extend(dim,
+ dim->nparam, dim->n_in, dim->n_out + n);
+ default:
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot add dimensions of specified type", goto error);
+ }
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+static int valid_dim_type(enum isl_dim_type type)
+{
+ switch (type) {
+ case isl_dim_param:
+ case isl_dim_in:
+ case isl_dim_out:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Insert "n" dimensions of type "type" at position "pos".
+ * If we are inserting parameters, then they are also inserted in
+ * any nested spaces.
+ */
+__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned pos, unsigned n)
+{
+ isl_id **ids = NULL;
+
+ if (!dim)
+ return NULL;
+ if (n == 0)
+ return isl_space_reset(dim, type);
+
+ if (!valid_dim_type(type))
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot insert dimensions of specified type",
+ goto error);
+
+ isl_assert(dim->ctx, pos <= isl_space_dim(dim, type), goto error);
+
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+
+ if (dim->ids) {
+ enum isl_dim_type t, o = isl_dim_param;
+ int off;
+ int s[3];
+ ids = isl_calloc_array(dim->ctx, isl_id *,
+ dim->nparam + dim->n_in + dim->n_out + n);
+ if (!ids)
+ goto error;
+ off = 0;
+ s[isl_dim_param - o] = dim->nparam;
+ s[isl_dim_in - o] = dim->n_in;
+ s[isl_dim_out - o] = dim->n_out;
+ for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+ if (t != type) {
+ get_ids(dim, t, 0, s[t - o], ids + off);
+ off += s[t - o];
+ } else {
+ get_ids(dim, t, 0, pos, ids + off);
+ off += pos + n;
+ get_ids(dim, t, pos, s[t - o] - pos, ids + off);
+ off += s[t - o] - pos;
+ }
+ }
+ free(dim->ids);
+ dim->ids = ids;
+ dim->n_id = dim->nparam + dim->n_in + dim->n_out + n;
+ }
+ switch (type) {
+ case isl_dim_param: dim->nparam += n; break;
+ case isl_dim_in: dim->n_in += n; break;
+ case isl_dim_out: dim->n_out += n; break;
+ default: ;
+ }
+ dim = isl_space_reset(dim, type);
+
+ if (type == isl_dim_param) {
+ if (dim && dim->nested[0] &&
+ !(dim->nested[0] = isl_space_insert_dims(dim->nested[0],
+ isl_dim_param, pos, n)))
+ goto error;
+ if (dim && dim->nested[1] &&
+ !(dim->nested[1] = isl_space_insert_dims(dim->nested[1],
+ isl_dim_param, pos, n)))
+ goto error;
+ }
+
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim,
+ enum isl_dim_type dst_type, unsigned dst_pos,
+ enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+ int i;
+
+ if (!dim)
+ return NULL;
+ if (n == 0) {
+ dim = isl_space_reset(dim, src_type);
+ return isl_space_reset(dim, dst_type);
+ }
+
+ isl_assert(dim->ctx, src_pos + n <= isl_space_dim(dim, src_type),
+ goto error);
+
+ if (dst_type == src_type && dst_pos == src_pos)
+ return dim;
+
+ isl_assert(dim->ctx, dst_type != src_type, goto error);
+
+ dim = isl_space_reset(dim, src_type);
+ dim = isl_space_reset(dim, dst_type);
+
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+
+ if (dim->ids) {
+ isl_id **ids;
+ enum isl_dim_type t, o = isl_dim_param;
+ int off;
+ int s[3];
+ ids = isl_calloc_array(dim->ctx, isl_id *,
+ dim->nparam + dim->n_in + dim->n_out);
+ if (!ids)
+ goto error;
+ off = 0;
+ s[isl_dim_param - o] = dim->nparam;
+ s[isl_dim_in - o] = dim->n_in;
+ s[isl_dim_out - o] = dim->n_out;
+ for (t = isl_dim_param; t <= isl_dim_out; ++t) {
+ if (t == dst_type) {
+ get_ids(dim, t, 0, dst_pos, ids + off);
+ off += dst_pos;
+ get_ids(dim, src_type, src_pos, n, ids + off);
+ off += n;
+ get_ids(dim, t, dst_pos, s[t - o] - dst_pos,
+ ids + off);
+ off += s[t - o] - dst_pos;
+ } else if (t == src_type) {
+ get_ids(dim, t, 0, src_pos, ids + off);
+ off += src_pos;
+ get_ids(dim, t, src_pos + n,
+ s[t - o] - src_pos - n, ids + off);
+ off += s[t - o] - src_pos - n;
+ } else {
+ get_ids(dim, t, 0, s[t - o], ids + off);
+ off += s[t - o];
+ }
+ }
+ free(dim->ids);
+ dim->ids = ids;
+ dim->n_id = dim->nparam + dim->n_in + dim->n_out;
+ }
+
+ switch (dst_type) {
+ case isl_dim_param: dim->nparam += n; break;
+ case isl_dim_in: dim->n_in += n; break;
+ case isl_dim_out: dim->n_out += n; break;
+ default: ;
+ }
+
+ switch (src_type) {
+ case isl_dim_param: dim->nparam -= n; break;
+ case isl_dim_in: dim->n_in -= n; break;
+ case isl_dim_out: dim->n_out -= n; break;
+ default: ;
+ }
+
+ if (dst_type != isl_dim_param && src_type != isl_dim_param)
+ return dim;
+
+ for (i = 0; i < 2; ++i) {
+ if (!dim->nested[i])
+ continue;
+ dim->nested[i] = isl_space_replace(dim->nested[i],
+ isl_dim_param, dim);
+ if (!dim->nested[i])
+ goto error;
+ }
+
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ isl_space *dim;
+
+ if (!left || !right)
+ goto error;
+
+ isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
+ goto error);
+ isl_assert(left->ctx,
+ isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_in),
+ goto error);
+
+ dim = isl_space_alloc(left->ctx, left->nparam, left->n_in, right->n_out);
+ if (!dim)
+ goto error;
+
+ dim = copy_ids(dim, isl_dim_param, 0, left, isl_dim_param);
+ dim = copy_ids(dim, isl_dim_in, 0, left, isl_dim_in);
+ dim = copy_ids(dim, isl_dim_out, 0, right, isl_dim_out);
+
+ if (dim && left->tuple_id[0] &&
+ !(dim->tuple_id[0] = isl_id_copy(left->tuple_id[0])))
+ goto error;
+ if (dim && right->tuple_id[1] &&
+ !(dim->tuple_id[1] = isl_id_copy(right->tuple_id[1])))
+ goto error;
+ if (dim && left->nested[0] &&
+ !(dim->nested[0] = isl_space_copy(left->nested[0])))
+ goto error;
+ if (dim && right->nested[1] &&
+ !(dim->nested[1] = isl_space_copy(right->nested[1])))
+ goto error;
+
+ isl_space_free(left);
+ isl_space_free(right);
+
+ return dim;
+error:
+ isl_space_free(left);
+ isl_space_free(right);
+ return NULL;
+}
+
+/* Given two map spaces { A -> C } and { B -> D }, construct the space
+ * { [A -> B] -> [C -> D] }.
+ * Given two set spaces { A } and { B }, construct the space { [A -> B] }.
+ */
+__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ isl_space *dom1, *dom2, *nest1, *nest2;
+ int is_set;
+
+ if (!left || !right)
+ goto error;
+
+ is_set = isl_space_is_set(left);
+ if (is_set != isl_space_is_set(right))
+ isl_die(isl_space_get_ctx(left), isl_error_invalid,
+ "expecting either two set spaces or two map spaces",
+ goto error);
+ if (is_set)
+ return isl_space_range_product(left, right);
+
+ isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
+ goto error);
+
+ dom1 = isl_space_domain(isl_space_copy(left));
+ dom2 = isl_space_domain(isl_space_copy(right));
+ nest1 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
+
+ dom1 = isl_space_range(left);
+ dom2 = isl_space_range(right);
+ nest2 = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
+
+ return isl_space_join(isl_space_reverse(nest1), nest2);
+error:
+ isl_space_free(left);
+ isl_space_free(right);
+ return NULL;
+}
+
+/* Given two spaces { A -> C } and { B -> C }, construct the space
+ * { [A -> B] -> C }
+ */
+__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ isl_space *ran, *dom1, *dom2, *nest;
+
+ if (!left || !right)
+ goto error;
+
+ if (!match(left, isl_dim_param, right, isl_dim_param))
+ isl_die(left->ctx, isl_error_invalid,
+ "parameters need to match", goto error);
+ if (!isl_space_tuple_is_equal(left, isl_dim_out, right, isl_dim_out))
+ isl_die(left->ctx, isl_error_invalid,
+ "ranges need to match", goto error);
+
+ ran = isl_space_range(isl_space_copy(left));
+
+ dom1 = isl_space_domain(left);
+ dom2 = isl_space_domain(right);
+ nest = isl_space_wrap(isl_space_join(isl_space_reverse(dom1), dom2));
+
+ return isl_space_join(isl_space_reverse(nest), ran);
+error:
+ isl_space_free(left);
+ isl_space_free(right);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
+ __isl_take isl_space *right)
+{
+ isl_space *dom, *ran1, *ran2, *nest;
+
+ if (!left || !right)
+ goto error;
+
+ isl_assert(left->ctx, match(left, isl_dim_param, right, isl_dim_param),
+ goto error);
+ if (!isl_space_tuple_is_equal(left, isl_dim_in, right, isl_dim_in))
+ isl_die(left->ctx, isl_error_invalid,
+ "domains need to match", goto error);
+
+ dom = isl_space_domain(isl_space_copy(left));
+
+ ran1 = isl_space_range(left);
+ ran2 = isl_space_range(right);
+ nest = isl_space_wrap(isl_space_join(isl_space_reverse(ran1), ran2));
+
+ return isl_space_join(isl_space_reverse(dom), nest);
+error:
+ isl_space_free(left);
+ isl_space_free(right);
+ return NULL;
+}
+
+/* Given a space of the form [A -> B] -> [C -> D], return the space A -> C.
+ */
+__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space)
+{
+ space = isl_space_domain_factor_domain(space);
+ space = isl_space_range_factor_domain(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(
+ __isl_take isl_space *space)
+{
+ isl_space *nested;
+ isl_space *domain;
+
+ if (!space)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "domain not a product", return isl_space_free(space));
+
+ nested = space->nested[0];
+ domain = isl_space_copy(space);
+ domain = isl_space_drop_dims(space, isl_dim_in,
+ nested->n_in, nested->n_out);
+ if (!domain)
+ return isl_space_free(space);
+ if (nested->tuple_id[0]) {
+ domain->tuple_id[0] = isl_id_copy(nested->tuple_id[0]);
+ if (!domain->tuple_id[0])
+ goto error;
+ }
+ if (nested->nested[0]) {
+ domain->nested[0] = isl_space_copy(nested->nested[0]);
+ if (!domain->nested[0])
+ goto error;
+ }
+
+ isl_space_free(space);
+ return domain;
+error:
+ isl_space_free(space);
+ isl_space_free(domain);
+ return NULL;
+}
+
+/* Given a space of the form [A -> B] -> C, return the space B -> C.
+ */
+__isl_give isl_space *isl_space_domain_factor_range(
+ __isl_take isl_space *space)
+{
+ isl_space *nested;
+ isl_space *range;
+
+ if (!space)
+ return NULL;
+ if (!isl_space_domain_is_wrapping(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "domain not a product", return isl_space_free(space));
+
+ nested = space->nested[0];
+ range = isl_space_copy(space);
+ range = isl_space_drop_dims(space, isl_dim_in, 0, nested->n_in);
+ if (!range)
+ return isl_space_free(space);
+ if (nested->tuple_id[1]) {
+ range->tuple_id[0] = isl_id_copy(nested->tuple_id[1]);
+ if (!range->tuple_id[0])
+ goto error;
+ }
+ if (nested->nested[1]) {
+ range->nested[0] = isl_space_copy(nested->nested[1]);
+ if (!range->nested[0])
+ goto error;
+ }
+
+ isl_space_free(space);
+ return range;
+error:
+ isl_space_free(space);
+ isl_space_free(range);
+ return NULL;
+}
+
+/* Given a space of the form A -> [B -> C], return the space A -> B.
+ */
+__isl_give isl_space *isl_space_range_factor_domain(
+ __isl_take isl_space *space)
+{
+ isl_space *nested;
+ isl_space *domain;
+
+ 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];
+ domain = isl_space_copy(space);
+ domain = isl_space_drop_dims(space, isl_dim_out,
+ nested->n_in, nested->n_out);
+ if (!domain)
+ return isl_space_free(space);
+ if (nested->tuple_id[0]) {
+ domain->tuple_id[1] = isl_id_copy(nested->tuple_id[0]);
+ if (!domain->tuple_id[1])
+ goto error;
+ }
+ if (nested->nested[0]) {
+ domain->nested[1] = isl_space_copy(nested->nested[0]);
+ if (!domain->nested[1])
+ goto error;
+ }
+
+ isl_space_free(space);
+ return domain;
+error:
+ isl_space_free(space);
+ isl_space_free(domain);
+ 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)
+{
+ 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);
+ range = isl_space_drop_dims(space, isl_dim_out, 0, nested->n_in);
+ if (!range)
+ return isl_space_free(space);
+ if (nested->tuple_id[1]) {
+ range->tuple_id[1] = isl_id_copy(nested->tuple_id[1]);
+ if (!range->tuple_id[1])
+ goto error;
+ }
+ if (nested->nested[1]) {
+ range->nested[1] = isl_space_copy(nested->nested[1]);
+ if (!range->nested[1])
+ goto error;
+ }
+
+ isl_space_free(space);
+ return range;
+error:
+ isl_space_free(space);
+ isl_space_free(range);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim)
+{
+ isl_ctx *ctx;
+ isl_id **ids = NULL;
+
+ if (!dim)
+ return NULL;
+ ctx = isl_space_get_ctx(dim);
+ if (!isl_space_is_set(dim))
+ isl_die(ctx, isl_error_invalid, "not a set space", goto error);
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+ if (dim->ids) {
+ ids = isl_calloc_array(dim->ctx, isl_id *,
+ dim->nparam + dim->n_out + dim->n_out);
+ if (!ids)
+ goto error;
+ get_ids(dim, isl_dim_param, 0, dim->nparam, ids);
+ get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->nparam);
+ }
+ dim->n_in = dim->n_out;
+ if (ids) {
+ free(dim->ids);
+ dim->ids = ids;
+ dim->n_id = dim->nparam + dim->n_out + dim->n_out;
+ dim = copy_ids(dim, isl_dim_out, 0, dim, isl_dim_in);
+ }
+ isl_id_free(dim->tuple_id[0]);
+ dim->tuple_id[0] = isl_id_copy(dim->tuple_id[1]);
+ isl_space_free(dim->nested[0]);
+ dim->nested[0] = isl_space_copy(dim->nested[1]);
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_map_from_domain_and_range(
+ __isl_take isl_space *domain, __isl_take isl_space *range)
+{
+ if (!domain || !range)
+ goto error;
+ if (!isl_space_is_set(domain))
+ isl_die(isl_space_get_ctx(domain), isl_error_invalid,
+ "domain is not a set space", goto error);
+ if (!isl_space_is_set(range))
+ isl_die(isl_space_get_ctx(range), isl_error_invalid,
+ "range is not a set space", goto error);
+ return isl_space_join(isl_space_reverse(domain), range);
+error:
+ isl_space_free(domain);
+ isl_space_free(range);
+ return NULL;
+}
+
+static __isl_give isl_space *set_ids(__isl_take isl_space *dim,
+ enum isl_dim_type type,
+ unsigned first, unsigned n, __isl_take isl_id **ids)
+{
+ int i;
+
+ for (i = 0; i < n ; ++i)
+ dim = set_id(dim, type, first + i, ids[i]);
+
+ return dim;
+}
+
+__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim)
+{
+ unsigned t;
+ isl_space *nested;
+ isl_id **ids = NULL;
+ isl_id *id;
+
+ if (!dim)
+ return NULL;
+ if (match(dim, isl_dim_in, dim, isl_dim_out))
+ return dim;
+
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+
+ id = dim->tuple_id[0];
+ dim->tuple_id[0] = dim->tuple_id[1];
+ dim->tuple_id[1] = id;
+
+ nested = dim->nested[0];
+ dim->nested[0] = dim->nested[1];
+ dim->nested[1] = nested;
+
+ if (dim->ids) {
+ int n_id = dim->n_in + dim->n_out;
+ ids = isl_alloc_array(dim->ctx, isl_id *, n_id);
+ if (n_id && !ids)
+ goto error;
+ get_ids(dim, isl_dim_in, 0, dim->n_in, ids);
+ get_ids(dim, isl_dim_out, 0, dim->n_out, ids + dim->n_in);
+ }
+
+ t = dim->n_in;
+ dim->n_in = dim->n_out;
+ dim->n_out = t;
+
+ if (dim->ids) {
+ dim = set_ids(dim, isl_dim_out, 0, dim->n_out, ids);
+ dim = set_ids(dim, isl_dim_in, 0, dim->n_in, ids + dim->n_out);
+ free(ids);
+ }
+
+ return dim;
+error:
+ free(ids);
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
+ enum isl_dim_type type, unsigned first, unsigned num)
+{
+ int i;
+
+ if (!dim)
+ return NULL;
+
+ if (num == 0)
+ return isl_space_reset(dim, type);
+
+ if (!valid_dim_type(type))
+ isl_die(dim->ctx, isl_error_invalid,
+ "cannot drop dimensions of specified type", goto error);
+
+ if (first + num > n(dim, type) || first + num < first)
+ isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+ "index out of bounds", return isl_space_free(dim));
+ dim = isl_space_cow(dim);
+ if (!dim)
+ goto error;
+ if (dim->ids) {
+ dim = extend_ids(dim);
+ if (!dim)
+ goto error;
+ for (i = 0; i < num; ++i)
+ isl_id_free(get_id(dim, type, first + i));
+ for (i = first+num; i < n(dim, type); ++i)
+ set_id(dim, type, i - num, get_id(dim, type, i));
+ switch (type) {
+ case isl_dim_param:
+ get_ids(dim, isl_dim_in, 0, dim->n_in,
+ dim->ids + offset(dim, isl_dim_in) - num);
+ case isl_dim_in:
+ get_ids(dim, isl_dim_out, 0, dim->n_out,
+ dim->ids + offset(dim, isl_dim_out) - num);
+ default:
+ ;
+ }
+ dim->n_id -= num;
+ }
+ switch (type) {
+ case isl_dim_param: dim->nparam -= num; break;
+ case isl_dim_in: dim->n_in -= num; break;
+ case isl_dim_out: dim->n_out -= num; break;
+ default: ;
+ }
+ dim = isl_space_reset(dim, type);
+ if (type == isl_dim_param) {
+ if (dim && dim->nested[0] &&
+ !(dim->nested[0] = isl_space_drop_dims(dim->nested[0],
+ isl_dim_param, first, num)))
+ goto error;
+ if (dim && dim->nested[1] &&
+ !(dim->nested[1] = isl_space_drop_dims(dim->nested[1],
+ isl_dim_param, first, num)))
+ goto error;
+ }
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
+ unsigned first, unsigned n)
+{
+ if (!dim)
+ return NULL;
+ return isl_space_drop_dims(dim, isl_dim_in, first, n);
+}
+
+__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
+ unsigned first, unsigned n)
+{
+ if (!dim)
+ return NULL;
+ return isl_space_drop_dims(dim, isl_dim_out, first, n);
+}
+
+__isl_give isl_space *isl_space_domain(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ dim = isl_space_drop_outputs(dim, 0, dim->n_out);
+ dim = isl_space_reverse(dim);
+ dim = mark_as_set(dim);
+ return dim;
+}
+
+__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!isl_space_is_set(dim))
+ isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+ "not a set space", goto error);
+ dim = isl_space_reverse(dim);
+ dim = isl_space_reset(dim, isl_dim_out);
+ return dim;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_range(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ dim = isl_space_drop_inputs(dim, 0, dim->n_in);
+ dim = mark_as_set(dim);
+ return dim;
+}
+
+__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!isl_space_is_set(dim))
+ isl_die(isl_space_get_ctx(dim), isl_error_invalid,
+ "not a set space", goto error);
+ return isl_space_reset(dim, isl_dim_in);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Given a map space A -> B, return the map space [A -> B] -> A.
+ */
+__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space)
+{
+ isl_space *domain;
+
+ domain = isl_space_from_range(isl_space_domain(isl_space_copy(space)));
+ space = isl_space_from_domain(isl_space_wrap(space));
+ space = isl_space_join(space, domain);
+
+ return space;
+}
+
+/* Given a map space A -> B, return the map space [A -> B] -> B.
+ */
+__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space)
+{
+ isl_space *range;
+
+ range = isl_space_from_range(isl_space_range(isl_space_copy(space)));
+ space = isl_space_from_domain(isl_space_wrap(space));
+ space = isl_space_join(space, range);
+
+ return space;
+}
+
+__isl_give isl_space *isl_space_params(__isl_take isl_space *space)
+{
+ if (isl_space_is_params(space))
+ return space;
+ space = isl_space_drop_dims(space,
+ isl_dim_in, 0, isl_space_dim(space, isl_dim_in));
+ space = isl_space_drop_dims(space,
+ isl_dim_out, 0, isl_space_dim(space, isl_dim_out));
+ space = mark_as_params(space);
+ return space;
+}
+
+__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+ if (!isl_space_is_params(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "not a parameter space", goto error);
+ return isl_space_reset(space, isl_dim_set);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_as_set_space(__isl_take isl_space *dim)
+{
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+
+ dim->n_out += dim->n_in;
+ dim->n_in = 0;
+ dim = isl_space_reset(dim, isl_dim_in);
+ dim = isl_space_reset(dim, isl_dim_out);
+
+ return dim;
+}
+
+__isl_give isl_space *isl_space_underlying(__isl_take isl_space *dim,
+ unsigned n_div)
+{
+ int i;
+
+ if (!dim)
+ return NULL;
+ if (n_div == 0 &&
+ dim->nparam == 0 && dim->n_in == 0 && dim->n_id == 0)
+ return isl_space_reset(isl_space_reset(dim, isl_dim_in), isl_dim_out);
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+ dim->n_out += dim->nparam + dim->n_in + n_div;
+ dim->nparam = 0;
+ dim->n_in = 0;
+
+ for (i = 0; i < dim->n_id; ++i)
+ isl_id_free(get_id(dim, isl_dim_out, i));
+ dim->n_id = 0;
+ dim = isl_space_reset(dim, isl_dim_in);
+ dim = isl_space_reset(dim, isl_dim_out);
+
+ return dim;
+}
+
+/* Are the two spaces the same, including positions and names of parameters?
+ */
+int isl_space_is_equal(__isl_keep isl_space *dim1, __isl_keep isl_space *dim2)
+{
+ if (!dim1 || !dim2)
+ return -1;
+ if (dim1 == dim2)
+ return 1;
+ return match(dim1, isl_dim_param, dim2, isl_dim_param) &&
+ isl_space_tuple_is_equal(dim1, isl_dim_in, dim2, isl_dim_in) &&
+ isl_space_tuple_is_equal(dim1, isl_dim_out, dim2, isl_dim_out);
+}
+
+/* Is space1 equal to the domain of space2?
+ *
+ * In the internal version we also allow space2 to be the space of a set,
+ * provided space1 is a parameter space.
+ */
+int isl_space_is_domain_internal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2)
+{
+ if (!space1 || !space2)
+ return -1;
+ if (!isl_space_is_set(space1))
+ return 0;
+ return match(space1, isl_dim_param, space2, isl_dim_param) &&
+ isl_space_tuple_is_equal(space1, isl_dim_set,
+ space2, isl_dim_in);
+}
+
+/* Is space1 equal to the domain of space2?
+ */
+int isl_space_is_domain(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2)
+{
+ if (!space2)
+ return -1;
+ if (!isl_space_is_map(space2))
+ return 0;
+ return isl_space_is_domain_internal(space1, space2);
+}
+
+/* Is space1 equal to the range of space2?
+ *
+ * In the internal version, space2 is allowed to be the space of a set,
+ * in which case it should be equal to space1.
+ */
+int isl_space_is_range_internal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2)
+{
+ if (!space1 || !space2)
+ return -1;
+ if (!isl_space_is_set(space1))
+ return 0;
+ return match(space1, isl_dim_param, space2, isl_dim_param) &&
+ isl_space_tuple_is_equal(space1, isl_dim_set,
+ space2, isl_dim_out);
+}
+
+/* Is space1 equal to the range of space2?
+ */
+int isl_space_is_range(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2)
+{
+ if (!space2)
+ return -1;
+ if (!isl_space_is_map(space2))
+ return 0;
+ return isl_space_is_range_internal(space1, space2);
+}
+
+int isl_space_compatible(__isl_keep isl_space *dim1,
+ __isl_keep isl_space *dim2)
+{
+ return dim1->nparam == dim2->nparam &&
+ 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)
+{
+ int i;
+ isl_id *id;
+
+ if (!dim)
+ 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);
+
+ for (i = 0; i < dim->nparam; ++i) {
+ id = get_id(dim, isl_dim_param, i);
+ hash = isl_hash_id(hash, id);
+ }
+
+ id = tuple_id(dim, isl_dim_in);
+ hash = isl_hash_id(hash, id);
+ id = tuple_id(dim, isl_dim_out);
+ hash = isl_hash_id(hash, id);
+
+ hash = isl_hash_dim(hash, dim->nested[0]);
+ hash = isl_hash_dim(hash, dim->nested[1]);
+
+ return hash;
+}
+
+uint32_t isl_space_get_hash(__isl_keep isl_space *dim)
+{
+ uint32_t hash;
+
+ if (!dim)
+ return 0;
+
+ hash = isl_hash_init();
+ hash = isl_hash_dim(hash, dim);
+
+ return hash;
+}
+
+int isl_space_is_wrapping(__isl_keep isl_space *dim)
+{
+ if (!dim)
+ return -1;
+
+ if (!isl_space_is_set(dim))
+ return 0;
+
+ return dim->nested[1] != NULL;
+}
+
+/* Is "space" the space of a map where the domain is a wrapped map space?
+ */
+int isl_space_domain_is_wrapping(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+
+ if (isl_space_is_set(space))
+ return 0;
+
+ return space->nested[0] != NULL;
+}
+
+/* Is "space" the space of a map where the range is a wrapped map space?
+ */
+int isl_space_range_is_wrapping(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+
+ if (isl_space_is_set(space))
+ return 0;
+
+ return space->nested[1] != NULL;
+}
+
+__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim)
+{
+ isl_space *wrap;
+
+ if (!dim)
+ return NULL;
+
+ wrap = isl_space_set_alloc(dim->ctx,
+ dim->nparam, dim->n_in + dim->n_out);
+
+ wrap = copy_ids(wrap, isl_dim_param, 0, dim, isl_dim_param);
+ wrap = copy_ids(wrap, isl_dim_set, 0, dim, isl_dim_in);
+ wrap = copy_ids(wrap, isl_dim_set, dim->n_in, dim, isl_dim_out);
+
+ if (!wrap)
+ goto error;
+
+ wrap->nested[1] = dim;
+
+ return wrap;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim)
+{
+ isl_space *unwrap;
+
+ if (!dim)
+ return NULL;
+
+ if (!isl_space_is_wrapping(dim))
+ isl_die(dim->ctx, isl_error_invalid, "not a wrapping space",
+ goto error);
+
+ unwrap = isl_space_copy(dim->nested[1]);
+ isl_space_free(dim);
+
+ return unwrap;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+int isl_space_is_named_or_nested(__isl_keep isl_space *dim, enum isl_dim_type type)
+{
+ if (type != isl_dim_in && type != isl_dim_out)
+ return 0;
+ if (!dim)
+ return -1;
+ if (dim->tuple_id[type - isl_dim_in])
+ return 1;
+ if (dim->nested[type - isl_dim_in])
+ return 1;
+ return 0;
+}
+
+int isl_space_may_be_set(__isl_keep isl_space *dim)
+{
+ if (!dim)
+ return -1;
+ if (isl_space_is_set(dim))
+ return 1;
+ if (isl_space_dim(dim, isl_dim_in) != 0)
+ return 0;
+ if (isl_space_is_named_or_nested(dim, isl_dim_in))
+ return 0;
+ return 1;
+}
+
+__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
+ enum isl_dim_type type)
+{
+ if (!isl_space_is_named_or_nested(dim, type))
+ return dim;
+
+ dim = isl_space_cow(dim);
+ if (!dim)
+ return NULL;
+
+ isl_id_free(dim->tuple_id[type - isl_dim_in]);
+ dim->tuple_id[type - isl_dim_in] = NULL;
+ isl_space_free(dim->nested[type - isl_dim_in]);
+ dim->nested[type - isl_dim_in] = NULL;
+
+ return dim;
+}
+
+__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!dim->nested[0] && !dim->nested[1])
+ return dim;
+
+ if (dim->nested[0])
+ dim = isl_space_reset(dim, isl_dim_in);
+ if (dim && dim->nested[1])
+ dim = isl_space_reset(dim, isl_dim_out);
+
+ return dim;
+}
+
+__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!dim->nested[0])
+ return dim;
+
+ return isl_space_reset(dim, isl_dim_in);
+}
+
+__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim)
+{
+ if (!dim)
+ return NULL;
+ if (!dim->nested[1])
+ return dim;
+
+ return isl_space_reset(dim, isl_dim_out);
+}
+
+/* Replace the dimensions of the given type of dst by those of src.
+ */
+__isl_give isl_space *isl_space_replace(__isl_take isl_space *dst,
+ enum isl_dim_type type, __isl_keep isl_space *src)
+{
+ dst = isl_space_cow(dst);
+
+ if (!dst || !src)
+ goto error;
+
+ dst = isl_space_drop_dims(dst, type, 0, isl_space_dim(dst, type));
+ dst = isl_space_add_dims(dst, type, isl_space_dim(src, type));
+ dst = copy_ids(dst, type, 0, src, type);
+
+ if (dst && type == isl_dim_param) {
+ int i;
+ for (i = 0; i <= 1; ++i) {
+ if (!dst->nested[i])
+ continue;
+ dst->nested[i] = isl_space_replace(dst->nested[i],
+ type, src);
+ if (!dst->nested[i])
+ goto error;
+ }
+ }
+
+ return dst;
+error:
+ isl_space_free(dst);
+ return NULL;
+}
+
+/* Given a dimension specification "dim" of a set, create a dimension
+ * specification for the lift of the set. In particular, the result
+ * is of the form [dim -> local[..]], with n_local variables in the
+ * range of the wrapped map.
+ */
+__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local)
+{
+ isl_space *local_dim;
+
+ if (!dim)
+ return NULL;
+
+ local_dim = isl_space_dup(dim);
+ local_dim = isl_space_drop_dims(local_dim, isl_dim_set, 0, dim->n_out);
+ local_dim = isl_space_add_dims(local_dim, isl_dim_set, n_local);
+ local_dim = isl_space_set_tuple_name(local_dim, isl_dim_set, "local");
+ dim = isl_space_join(isl_space_from_domain(dim),
+ isl_space_from_range(local_dim));
+ dim = isl_space_wrap(dim);
+ dim = isl_space_set_tuple_name(dim, isl_dim_set, "lifted");
+
+ return dim;
+}
+
+int isl_space_can_zip(__isl_keep isl_space *dim)
+{
+ if (!dim)
+ return -1;
+
+ return dim->nested[0] && dim->nested[1];
+}
+
+__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim)
+{
+ isl_space *dom, *ran;
+ isl_space *dom_dom, *dom_ran, *ran_dom, *ran_ran;
+
+ if (!isl_space_can_zip(dim))
+ isl_die(dim->ctx, isl_error_invalid, "dim cannot be zipped",
+ goto error);
+
+ if (!dim)
+ return NULL;
+ dom = isl_space_unwrap(isl_space_domain(isl_space_copy(dim)));
+ ran = isl_space_unwrap(isl_space_range(dim));
+ dom_dom = isl_space_domain(isl_space_copy(dom));
+ dom_ran = isl_space_range(dom);
+ ran_dom = isl_space_domain(isl_space_copy(ran));
+ ran_ran = isl_space_range(ran);
+ dom = isl_space_join(isl_space_from_domain(dom_dom),
+ isl_space_from_range(ran_dom));
+ ran = isl_space_join(isl_space_from_domain(dom_ran),
+ isl_space_from_range(ran_ran));
+ return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
+ isl_space_from_range(isl_space_wrap(ran)));
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Can we apply isl_space_curry to "space"?
+ * That is, does it have a nested relation in its domain?
+ */
+int isl_space_can_curry(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+
+ return !!space->nested[0];
+}
+
+/* Given a space (A -> B) -> C, return the corresponding space
+ * A -> (B -> C).
+ */
+__isl_give isl_space *isl_space_curry(__isl_take isl_space *space)
+{
+ isl_space *dom, *ran;
+ isl_space *dom_dom, *dom_ran;
+
+ if (!space)
+ return NULL;
+
+ if (!isl_space_can_curry(space))
+ isl_die(space->ctx, isl_error_invalid,
+ "space cannot be curried", goto error);
+
+ dom = isl_space_unwrap(isl_space_domain(isl_space_copy(space)));
+ ran = isl_space_range(space);
+ dom_dom = isl_space_domain(isl_space_copy(dom));
+ dom_ran = isl_space_range(dom);
+ ran = isl_space_join(isl_space_from_domain(dom_ran),
+ isl_space_from_range(ran));
+ return isl_space_join(isl_space_from_domain(dom_dom),
+ isl_space_from_range(isl_space_wrap(ran)));
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Can we apply isl_space_uncurry to "space"?
+ * That is, does it have a nested relation in its range?
+ */
+int isl_space_can_uncurry(__isl_keep isl_space *space)
+{
+ if (!space)
+ return -1;
+
+ return !!space->nested[1];
+}
+
+/* Given a space A -> (B -> C), return the corresponding space
+ * (A -> B) -> C.
+ */
+__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space)
+{
+ isl_space *dom, *ran;
+ isl_space *ran_dom, *ran_ran;
+
+ if (!space)
+ return NULL;
+
+ if (!isl_space_can_uncurry(space))
+ isl_die(space->ctx, isl_error_invalid,
+ "space cannot be uncurried",
+ return isl_space_free(space));
+
+ dom = isl_space_domain(isl_space_copy(space));
+ ran = isl_space_unwrap(isl_space_range(space));
+ ran_dom = isl_space_domain(isl_space_copy(ran));
+ ran_ran = isl_space_range(ran);
+ dom = isl_space_join(isl_space_from_domain(dom),
+ isl_space_from_range(ran_dom));
+ return isl_space_join(isl_space_from_domain(isl_space_wrap(dom)),
+ isl_space_from_range(ran_ran));
+}
+
+int isl_space_has_named_params(__isl_keep isl_space *dim)
+{
+ int i;
+ unsigned off;
+
+ if (!dim)
+ return -1;
+ if (dim->nparam == 0)
+ return 1;
+ off = isl_space_offset(dim, isl_dim_param);
+ if (off + dim->nparam > dim->n_id)
+ return 0;
+ for (i = 0; i < dim->nparam; ++i)
+ if (!dim->ids[off + i])
+ return 0;
+ return 1;
+}
+
+/* Align the initial parameters of dim1 to match the order in dim2.
+ */
+__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
+ __isl_take isl_space *dim2)
+{
+ isl_reordering *exp;
+
+ if (!isl_space_has_named_params(dim1) || !isl_space_has_named_params(dim2))
+ isl_die(isl_space_get_ctx(dim1), isl_error_invalid,
+ "parameter alignment requires named parameters",
+ goto error);
+
+ dim2 = isl_space_params(dim2);
+ exp = isl_parameter_alignment_reordering(dim1, dim2);
+ exp = isl_reordering_extend_space(exp, dim1);
+ isl_space_free(dim2);
+ if (!exp)
+ return NULL;
+ dim1 = isl_space_copy(exp->dim);
+ isl_reordering_free(exp);
+ return dim1;
+error:
+ isl_space_free(dim1);
+ isl_space_free(dim2);
+ return NULL;
+}
+
+/* Given the space of set (domain), construct a space for a map
+ * with as domain the given space and as range the range of "model".
+ */
+__isl_give isl_space *isl_space_extend_domain_with_range(
+ __isl_take isl_space *space, __isl_take isl_space *model)
+{
+ if (!model)
+ goto error;
+
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out,
+ isl_space_dim(model, isl_dim_out));
+ if (isl_space_has_tuple_id(model, isl_dim_out))
+ space = isl_space_set_tuple_id(space, isl_dim_out,
+ isl_space_get_tuple_id(model, isl_dim_out));
+ if (!space)
+ goto error;
+ if (model->nested[1]) {
+ isl_space *nested = isl_space_copy(model->nested[1]);
+ int n_nested, n_space;
+ nested = isl_space_align_params(nested, isl_space_copy(space));
+ n_nested = isl_space_dim(nested, isl_dim_param);
+ n_space = isl_space_dim(space, isl_dim_param);
+ if (n_nested > n_space)
+ nested = isl_space_drop_dims(nested, isl_dim_param,
+ n_space, n_nested - n_space);
+ if (!nested)
+ goto error;
+ space->nested[1] = nested;
+ }
+ isl_space_free(model);
+ return space;
+error:
+ isl_space_free(model);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Compare the "type" dimensions of two isl_spaces.
+ *
+ * The order is fairly arbitrary.
+ */
+static int isl_space_cmp_type(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2, enum isl_dim_type type)
+{
+ int cmp;
+ isl_space *nested1, *nested2;
+
+ if (isl_space_dim(space1, type) != isl_space_dim(space2, type))
+ return isl_space_dim(space1, type) -
+ isl_space_dim(space2, type);
+
+ cmp = isl_id_cmp(tuple_id(space1, type), tuple_id(space2, type));
+ if (cmp != 0)
+ return cmp;
+
+ nested1 = nested(space1, type);
+ nested2 = nested(space2, type);
+ if (!nested1 != !nested2)
+ return !nested1 - !nested2;
+
+ if (nested1)
+ return isl_space_cmp(nested1, nested2);
+
+ return 0;
+}
+
+/* Compare two isl_spaces.
+ *
+ * The order is fairly arbitrary.
+ */
+int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2)
+{
+ int i;
+ int cmp;
+
+ if (space1 == space2)
+ return 0;
+ if (!space1)
+ return -1;
+ if (!space2)
+ return 1;
+
+ cmp = isl_space_cmp_type(space1, space2, isl_dim_param);
+ if (cmp != 0)
+ return cmp;
+ cmp = isl_space_cmp_type(space1, space2, isl_dim_in);
+ if (cmp != 0)
+ return cmp;
+ cmp = isl_space_cmp_type(space1, space2, isl_dim_out);
+ if (cmp != 0)
+ return cmp;
+
+ if (!space1->ids && !space2->ids)
+ return 0;
+
+ for (i = 0; i < n(space1, isl_dim_param); ++i) {
+ cmp = isl_id_cmp(get_id(space1, isl_dim_param, i),
+ get_id(space2, isl_dim_param, i));
+ if (cmp != 0)
+ return cmp;
+ }
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/isl_space_private.h b/polly/lib/External/isl/isl_space_private.h
new file mode 100644
index 00000000000..3c892a4986a
--- /dev/null
+++ b/polly/lib/External/isl/isl_space_private.h
@@ -0,0 +1,60 @@
+#ifndef ISL_SPACE_PRIVATE
+#define ISL_SPACE_PRIVATE
+
+#include <isl/space.h>
+#include <isl/hash.h>
+#include <isl/id.h>
+
+struct isl_name;
+struct isl_space {
+ int ref;
+
+ struct isl_ctx *ctx;
+
+ unsigned nparam;
+ unsigned n_in; /* zero for sets */
+ unsigned n_out; /* dim for sets */
+
+ isl_id *tuple_id[2];
+ isl_space *nested[2];
+
+ unsigned n_id;
+ isl_id **ids;
+};
+
+__isl_give isl_space *isl_space_cow(__isl_take isl_space *dim);
+
+__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);
+
+int isl_space_is_domain_internal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+int isl_space_is_range_internal(__isl_keep isl_space *space1,
+ __isl_keep isl_space *space2);
+
+__isl_give isl_space *isl_space_as_set_space(__isl_take isl_space *dim);
+
+unsigned isl_space_offset(__isl_keep isl_space *dim, enum isl_dim_type type);
+
+int isl_space_may_be_set(__isl_keep isl_space *dim);
+int isl_space_is_named_or_nested(__isl_keep isl_space *dim, enum isl_dim_type type);
+int isl_space_has_named_params(__isl_keep isl_space *dim);
+__isl_give isl_space *isl_space_reset(__isl_take isl_space *dim,
+ enum isl_dim_type type);
+__isl_give isl_space *isl_space_flatten(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_flatten_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_flatten_range(__isl_take isl_space *dim);
+
+__isl_give isl_space *isl_space_replace(__isl_take isl_space *dst,
+ enum isl_dim_type type, __isl_keep isl_space *src);
+
+__isl_give isl_space *isl_space_lift(__isl_take isl_space *dim, unsigned n_local);
+
+__isl_give isl_space *isl_space_extend_domain_with_range(
+ __isl_take isl_space *domain, __isl_take isl_space *model);
+
+int isl_space_cmp(__isl_keep isl_space *space1, __isl_keep isl_space *space2);
+
+#endif
diff --git a/polly/lib/External/isl/isl_stream.c b/polly/lib/External/isl/isl_stream.c
new file mode 100644
index 00000000000..c5b15115668
--- /dev/null
+++ b/polly/lib/External/isl/isl_stream.c
@@ -0,0 +1,778 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <isl/ctx.h>
+#include <isl_stream_private.h>
+#include <isl/map.h>
+#include <isl/aff.h>
+#include <isl_val_private.h>
+
+struct isl_keyword {
+ char *name;
+ enum isl_token_type type;
+};
+
+static int same_name(const void *entry, const void *val)
+{
+ const struct isl_keyword *keyword = (const struct isl_keyword *)entry;
+
+ return !strcmp(keyword->name, val);
+}
+
+enum isl_token_type isl_stream_register_keyword(struct isl_stream *s,
+ const char *name)
+{
+ struct isl_hash_table_entry *entry;
+ struct isl_keyword *keyword;
+ uint32_t name_hash;
+
+ if (!s->keywords) {
+ s->keywords = isl_hash_table_alloc(s->ctx, 10);
+ if (!s->keywords)
+ return ISL_TOKEN_ERROR;
+ s->next_type = ISL_TOKEN_LAST;
+ }
+
+ name_hash = isl_hash_string(isl_hash_init(), name);
+
+ entry = isl_hash_table_find(s->ctx, s->keywords, name_hash,
+ same_name, name, 1);
+ if (!entry)
+ return ISL_TOKEN_ERROR;
+ if (entry->data) {
+ keyword = entry->data;
+ return keyword->type;
+ }
+
+ keyword = isl_calloc_type(s->ctx, struct isl_keyword);
+ if (!keyword)
+ return ISL_TOKEN_ERROR;
+ keyword->type = s->next_type++;
+ keyword->name = strdup(name);
+ if (!keyword->name) {
+ free(keyword);
+ return ISL_TOKEN_ERROR;
+ }
+ entry->data = keyword;
+
+ return keyword->type;
+}
+
+struct isl_token *isl_token_new(isl_ctx *ctx,
+ int line, int col, unsigned on_new_line)
+{
+ struct isl_token *tok = isl_alloc_type(ctx, struct isl_token);
+ if (!tok)
+ return NULL;
+ tok->line = line;
+ tok->col = col;
+ tok->on_new_line = on_new_line;
+ tok->is_keyword = 0;
+ tok->u.s = NULL;
+ return tok;
+}
+
+/* Return the type of "tok".
+ */
+int isl_token_get_type(struct isl_token *tok)
+{
+ return tok ? tok->type : ISL_TOKEN_ERROR;
+}
+
+/* Given a token of type ISL_TOKEN_VALUE, return the value it represents.
+ */
+__isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok)
+{
+ if (!tok)
+ return NULL;
+ if (tok->type != ISL_TOKEN_VALUE)
+ isl_die(ctx, isl_error_invalid, "not a value token",
+ return NULL);
+
+ return isl_val_int_from_isl_int(ctx, tok->u.v);
+}
+
+/* Given a token of type ISL_TOKEN_STRING, return the string it represents.
+ */
+__isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok)
+{
+ if (!tok)
+ return NULL;
+ if (tok->type != ISL_TOKEN_STRING)
+ isl_die(ctx, isl_error_invalid, "not a string token",
+ return NULL);
+
+ return strdup(tok->u.s);
+}
+
+void isl_token_free(struct isl_token *tok)
+{
+ if (!tok)
+ return;
+ if (tok->type == ISL_TOKEN_VALUE)
+ isl_int_clear(tok->u.v);
+ else if (tok->type == ISL_TOKEN_MAP)
+ isl_map_free(tok->u.map);
+ else if (tok->type == ISL_TOKEN_AFF)
+ isl_pw_aff_free(tok->u.pwaff);
+ else
+ free(tok->u.s);
+ free(tok);
+}
+
+void isl_stream_error(struct isl_stream *s, struct isl_token *tok, char *msg)
+{
+ int line = tok ? tok->line : s->line;
+ int col = tok ? tok->col : s->col;
+ fprintf(stderr, "syntax error (%d, %d): %s\n", line, col, msg);
+ if (tok) {
+ if (tok->type < 256)
+ fprintf(stderr, "got '%c'\n", tok->type);
+ else if (tok->type == ISL_TOKEN_IDENT)
+ fprintf(stderr, "got ident '%s'\n", tok->u.s);
+ else if (tok->is_keyword)
+ fprintf(stderr, "got keyword '%s'\n", tok->u.s);
+ else if (tok->type == ISL_TOKEN_VALUE) {
+ fprintf(stderr, "got value '");
+ isl_int_print(stderr, tok->u.v, 0);
+ fprintf(stderr, "'\n");
+ } else if (tok->type == ISL_TOKEN_MAP) {
+ isl_printer *p;
+ fprintf(stderr, "got map '");
+ p = isl_printer_to_file(s->ctx, stderr);
+ p = isl_printer_print_map(p, tok->u.map);
+ isl_printer_free(p);
+ fprintf(stderr, "'\n");
+ } else if (tok->type == ISL_TOKEN_AFF) {
+ isl_printer *p;
+ fprintf(stderr, "got affine expression '");
+ p = isl_printer_to_file(s->ctx, stderr);
+ p = isl_printer_print_pw_aff(p, tok->u.pwaff);
+ isl_printer_free(p);
+ fprintf(stderr, "'\n");
+ } else if (tok->u.s)
+ fprintf(stderr, "got token '%s'\n", tok->u.s);
+ else
+ fprintf(stderr, "got token type %d\n", tok->type);
+ }
+}
+
+static struct isl_stream* isl_stream_new(struct isl_ctx *ctx)
+{
+ int i;
+ struct isl_stream *s = isl_alloc_type(ctx, struct isl_stream);
+ if (!s)
+ return NULL;
+ s->ctx = ctx;
+ isl_ctx_ref(s->ctx);
+ s->file = NULL;
+ s->str = NULL;
+ s->len = 0;
+ s->line = 1;
+ s->col = 0;
+ s->eof = 0;
+ s->c = -1;
+ s->n_un = 0;
+ for (i = 0; i < 5; ++i)
+ s->tokens[i] = NULL;
+ s->n_token = 0;
+ s->keywords = NULL;
+ s->size = 256;
+ s->buffer = isl_alloc_array(ctx, char, s->size);
+ if (!s->buffer)
+ goto error;
+ return s;
+error:
+ isl_stream_free(s);
+ return NULL;
+}
+
+struct isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
+{
+ struct isl_stream *s = isl_stream_new(ctx);
+ if (!s)
+ return NULL;
+ s->file = file;
+ return s;
+}
+
+struct isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str)
+{
+ struct isl_stream *s;
+ if (!str)
+ return NULL;
+ s = isl_stream_new(ctx);
+ if (!s)
+ return NULL;
+ s->str = str;
+ return s;
+}
+
+static int stream_getc(struct isl_stream *s)
+{
+ int c;
+ if (s->eof)
+ return -1;
+ if (s->n_un)
+ return s->c = s->un[--s->n_un];
+ if (s->file)
+ c = fgetc(s->file);
+ else {
+ c = *s->str++;
+ if (c == '\0')
+ c = -1;
+ }
+ if (c == -1)
+ s->eof = 1;
+ if (!s->eof) {
+ if (s->c == '\n') {
+ s->line++;
+ s->col = 0;
+ } else
+ s->col++;
+ }
+ s->c = c;
+ return c;
+}
+
+static void isl_stream_ungetc(struct isl_stream *s, int c)
+{
+ isl_assert(s->ctx, s->n_un < 5, return);
+ s->un[s->n_un++] = c;
+ s->c = -1;
+}
+
+static int isl_stream_getc(struct isl_stream *s)
+{
+ int c;
+
+ do {
+ c = stream_getc(s);
+ if (c != '\\')
+ return c;
+ c = stream_getc(s);
+ } while (c == '\n');
+
+ isl_stream_ungetc(s, c);
+
+ return '\\';
+}
+
+static int isl_stream_push_char(struct isl_stream *s, int c)
+{
+ if (s->len >= s->size) {
+ char *buffer;
+ s->size = (3*s->size)/2;
+ buffer = isl_realloc_array(s->ctx, s->buffer, char, s->size);
+ if (!buffer)
+ return -1;
+ s->buffer = buffer;
+ }
+ s->buffer[s->len++] = c;
+ return 0;
+}
+
+void isl_stream_push_token(struct isl_stream *s, struct isl_token *tok)
+{
+ isl_assert(s->ctx, s->n_token < 5, return);
+ s->tokens[s->n_token++] = tok;
+}
+
+static enum isl_token_type check_keywords(struct isl_stream *s)
+{
+ struct isl_hash_table_entry *entry;
+ struct isl_keyword *keyword;
+ uint32_t name_hash;
+
+ if (!strcasecmp(s->buffer, "exists"))
+ return ISL_TOKEN_EXISTS;
+ if (!strcasecmp(s->buffer, "and"))
+ return ISL_TOKEN_AND;
+ if (!strcasecmp(s->buffer, "or"))
+ return ISL_TOKEN_OR;
+ if (!strcasecmp(s->buffer, "implies"))
+ return ISL_TOKEN_IMPLIES;
+ if (!strcasecmp(s->buffer, "not"))
+ return ISL_TOKEN_NOT;
+ if (!strcasecmp(s->buffer, "infty"))
+ return ISL_TOKEN_INFTY;
+ if (!strcasecmp(s->buffer, "infinity"))
+ return ISL_TOKEN_INFTY;
+ if (!strcasecmp(s->buffer, "NaN"))
+ return ISL_TOKEN_NAN;
+ if (!strcasecmp(s->buffer, "min"))
+ return ISL_TOKEN_MIN;
+ if (!strcasecmp(s->buffer, "max"))
+ return ISL_TOKEN_MAX;
+ if (!strcasecmp(s->buffer, "rat"))
+ return ISL_TOKEN_RAT;
+ if (!strcasecmp(s->buffer, "true"))
+ return ISL_TOKEN_TRUE;
+ if (!strcasecmp(s->buffer, "false"))
+ return ISL_TOKEN_FALSE;
+ if (!strcasecmp(s->buffer, "ceild"))
+ return ISL_TOKEN_CEILD;
+ if (!strcasecmp(s->buffer, "floord"))
+ return ISL_TOKEN_FLOORD;
+ if (!strcasecmp(s->buffer, "mod"))
+ return ISL_TOKEN_MOD;
+ if (!strcasecmp(s->buffer, "ceil"))
+ return ISL_TOKEN_CEIL;
+ if (!strcasecmp(s->buffer, "floor"))
+ return ISL_TOKEN_FLOOR;
+
+ if (!s->keywords)
+ return ISL_TOKEN_IDENT;
+
+ name_hash = isl_hash_string(isl_hash_init(), s->buffer);
+ entry = isl_hash_table_find(s->ctx, s->keywords, name_hash, same_name,
+ s->buffer, 0);
+ if (entry) {
+ keyword = entry->data;
+ return keyword->type;
+ }
+
+ return ISL_TOKEN_IDENT;
+}
+
+int isl_stream_skip_line(struct isl_stream *s)
+{
+ int c;
+
+ while ((c = isl_stream_getc(s)) != -1 && c != '\n')
+ /* nothing */
+ ;
+
+ return c == -1 ? -1 : 0;
+}
+
+static struct isl_token *next_token(struct isl_stream *s, int same_line)
+{
+ int c;
+ struct isl_token *tok = NULL;
+ int line, col;
+ int old_line = s->line;
+
+ if (s->n_token) {
+ if (same_line && s->tokens[s->n_token - 1]->on_new_line)
+ return NULL;
+ return s->tokens[--s->n_token];
+ }
+
+ if (same_line && s->c == '\n')
+ return NULL;
+
+ s->len = 0;
+
+ /* skip spaces and comment lines */
+ while ((c = isl_stream_getc(s)) != -1) {
+ if (c == '#') {
+ if (isl_stream_skip_line(s) < 0)
+ break;
+ c = '\n';
+ if (same_line)
+ break;
+ } else if (!isspace(c) || (same_line && c == '\n'))
+ break;
+ }
+
+ line = s->line;
+ col = s->col;
+
+ if (c == -1 || (same_line && c == '\n'))
+ return NULL;
+ if (c == '(' ||
+ c == ')' ||
+ c == '+' ||
+ c == '*' ||
+ c == '%' ||
+ c == '?' ||
+ c == '^' ||
+ c == '@' ||
+ c == '$' ||
+ c == ',' ||
+ c == '.' ||
+ c == ';' ||
+ c == '[' ||
+ c == ']' ||
+ c == '{' ||
+ c == '}') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = (enum isl_token_type)c;
+ return tok;
+ }
+ if (c == '-') {
+ int c;
+ if ((c = isl_stream_getc(s)) == '>') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->u.s = strdup("->");
+ tok->type = ISL_TOKEN_TO;
+ return tok;
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ if (!isdigit(c)) {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = (enum isl_token_type) '-';
+ return tok;
+ }
+ }
+ if (c == '-' || isdigit(c)) {
+ int minus = c == '-';
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = ISL_TOKEN_VALUE;
+ isl_int_init(tok->u.v);
+ if (isl_stream_push_char(s, c))
+ goto error;
+ while ((c = isl_stream_getc(s)) != -1 && isdigit(c))
+ if (isl_stream_push_char(s, c))
+ goto error;
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ isl_stream_push_char(s, '\0');
+ isl_int_read(tok->u.v, s->buffer);
+ if (minus && isl_int_is_zero(tok->u.v)) {
+ tok->col++;
+ tok->on_new_line = 0;
+ isl_stream_push_token(s, tok);
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = (enum isl_token_type) '-';
+ }
+ return tok;
+ }
+ if (isalpha(c) || c == '_') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ isl_stream_push_char(s, c);
+ while ((c = isl_stream_getc(s)) != -1 &&
+ (isalnum(c) || c == '_'))
+ isl_stream_push_char(s, c);
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ while ((c = isl_stream_getc(s)) != -1 && c == '\'')
+ isl_stream_push_char(s, c);
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ isl_stream_push_char(s, '\0');
+ tok->type = check_keywords(s);
+ if (tok->type != ISL_TOKEN_IDENT)
+ tok->is_keyword = 1;
+ tok->u.s = strdup(s->buffer);
+ if (!tok->u.s)
+ goto error;
+ return tok;
+ }
+ if (c == '"') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = ISL_TOKEN_STRING;
+ tok->u.s = NULL;
+ while ((c = isl_stream_getc(s)) != -1 && c != '"' && c != '\n')
+ isl_stream_push_char(s, c);
+ if (c != '"') {
+ isl_stream_error(s, NULL, "unterminated string");
+ goto error;
+ }
+ isl_stream_push_char(s, '\0');
+ tok->u.s = strdup(s->buffer);
+ return tok;
+ }
+ if (c == '=') {
+ int c;
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup("==");
+ tok->type = ISL_TOKEN_EQ_EQ;
+ return tok;
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ tok->type = (enum isl_token_type) '=';
+ return tok;
+ }
+ if (c == ':') {
+ int c;
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup(":=");
+ tok->type = ISL_TOKEN_DEF;
+ return tok;
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ tok->type = (enum isl_token_type) ':';
+ return tok;
+ }
+ if (c == '>') {
+ int c;
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup(">=");
+ tok->type = ISL_TOKEN_GE;
+ return tok;
+ } else if (c == '>') {
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup(">>=");
+ tok->type = ISL_TOKEN_LEX_GE;
+ return tok;
+ }
+ tok->u.s = strdup(">>");
+ tok->type = ISL_TOKEN_LEX_GT;
+ } else {
+ tok->u.s = strdup(">");
+ tok->type = ISL_TOKEN_GT;
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ return tok;
+ }
+ if (c == '<') {
+ int c;
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup("<=");
+ tok->type = ISL_TOKEN_LE;
+ return tok;
+ } else if (c == '<') {
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup("<<=");
+ tok->type = ISL_TOKEN_LEX_LE;
+ return tok;
+ }
+ tok->u.s = strdup("<<");
+ tok->type = ISL_TOKEN_LEX_LT;
+ } else {
+ tok->u.s = strdup("<");
+ tok->type = ISL_TOKEN_LT;
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ return tok;
+ }
+ if (c == '&') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = ISL_TOKEN_AND;
+ if ((c = isl_stream_getc(s)) != '&' && c != -1) {
+ tok->u.s = strdup("&");
+ isl_stream_ungetc(s, c);
+ } else
+ tok->u.s = strdup("&&");
+ return tok;
+ }
+ if (c == '|') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = ISL_TOKEN_OR;
+ if ((c = isl_stream_getc(s)) != '|' && c != -1) {
+ tok->u.s = strdup("|");
+ isl_stream_ungetc(s, c);
+ } else
+ tok->u.s = strdup("||");
+ return tok;
+ }
+ if (c == '/') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) != '\\' && c != -1) {
+ tok->type = (enum isl_token_type) '/';
+ isl_stream_ungetc(s, c);
+ } else {
+ tok->u.s = strdup("/\\");
+ tok->type = ISL_TOKEN_AND;
+ }
+ return tok;
+ }
+ if (c == '\\') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) != '/' && c != -1) {
+ tok->type = (enum isl_token_type) '\\';
+ isl_stream_ungetc(s, c);
+ } else {
+ tok->u.s = strdup("\\/");
+ tok->type = ISL_TOKEN_OR;
+ }
+ return tok;
+ }
+ if (c == '!') {
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ if ((c = isl_stream_getc(s)) == '=') {
+ tok->u.s = strdup("!=");
+ tok->type = ISL_TOKEN_NE;
+ return tok;
+ } else {
+ tok->type = ISL_TOKEN_NOT;
+ tok->u.s = strdup("!");
+ }
+ if (c != -1)
+ isl_stream_ungetc(s, c);
+ return tok;
+ }
+
+ tok = isl_token_new(s->ctx, line, col, old_line != line);
+ if (!tok)
+ return NULL;
+ tok->type = ISL_TOKEN_UNKNOWN;
+ return tok;
+error:
+ isl_token_free(tok);
+ return NULL;
+}
+
+struct isl_token *isl_stream_next_token(struct isl_stream *s)
+{
+ return next_token(s, 0);
+}
+
+struct isl_token *isl_stream_next_token_on_same_line(struct isl_stream *s)
+{
+ return next_token(s, 1);
+}
+
+int isl_stream_eat_if_available(struct isl_stream *s, int type)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type == type) {
+ isl_token_free(tok);
+ return 1;
+ }
+ isl_stream_push_token(s, tok);
+ return 0;
+}
+
+int isl_stream_next_token_is(struct isl_stream *s, int type)
+{
+ struct isl_token *tok;
+ int r;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ r = tok->type == type;
+ isl_stream_push_token(s, tok);
+ return r;
+}
+
+char *isl_stream_read_ident_if_available(struct isl_stream *s)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return NULL;
+ if (tok->type == ISL_TOKEN_IDENT) {
+ char *ident = strdup(tok->u.s);
+ isl_token_free(tok);
+ return ident;
+ }
+ isl_stream_push_token(s, tok);
+ return NULL;
+}
+
+int isl_stream_eat(struct isl_stream *s, int type)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return -1;
+ if (tok->type == type) {
+ isl_token_free(tok);
+ return 0;
+ }
+ isl_stream_error(s, tok, "expecting other token");
+ isl_stream_push_token(s, tok);
+ return -1;
+}
+
+int isl_stream_is_empty(struct isl_stream *s)
+{
+ struct isl_token *tok;
+
+ tok = isl_stream_next_token(s);
+
+ if (!tok)
+ return 1;
+
+ isl_stream_push_token(s, tok);
+ return 0;
+}
+
+static int free_keyword(void **p, void *user)
+{
+ struct isl_keyword *keyword = *p;
+
+ free(keyword->name);
+ free(keyword);
+
+ return 0;
+}
+
+void isl_stream_flush_tokens(struct isl_stream *s)
+{
+ int i;
+
+ if (!s)
+ return;
+ for (i = 0; i < s->n_token; ++i)
+ isl_token_free(s->tokens[i]);
+ s->n_token = 0;
+}
+
+void isl_stream_free(struct isl_stream *s)
+{
+ if (!s)
+ return;
+ free(s->buffer);
+ if (s->n_token != 0) {
+ struct isl_token *tok = isl_stream_next_token(s);
+ isl_stream_error(s, tok, "unexpected token");
+ isl_token_free(tok);
+ }
+ if (s->keywords) {
+ isl_hash_table_foreach(s->ctx, s->keywords, &free_keyword, NULL);
+ isl_hash_table_free(s->ctx, s->keywords);
+ }
+ isl_ctx_deref(s->ctx);
+ free(s);
+}
diff --git a/polly/lib/External/isl/isl_stream_private.h b/polly/lib/External/isl/isl_stream_private.h
new file mode 100644
index 00000000000..d5d4422127f
--- /dev/null
+++ b/polly/lib/External/isl/isl_stream_private.h
@@ -0,0 +1,21 @@
+#include <isl_int.h>
+#include <isl/stream.h>
+
+struct isl_token {
+ int type;
+
+ unsigned int on_new_line : 1;
+ unsigned is_keyword : 1;
+ int line;
+ int col;
+
+ union {
+ isl_int v;
+ char *s;
+ isl_map *map;
+ isl_pw_aff *pwaff;
+ } u;
+};
+
+struct isl_token *isl_token_new(isl_ctx *ctx,
+ int line, int col, unsigned on_new_line);
diff --git a/polly/lib/External/isl/isl_tab.c b/polly/lib/External/isl/isl_tab.c
new file mode 100644
index 00000000000..915521036a6
--- /dev/null
+++ b/polly/lib/External/isl/isl_tab.c
@@ -0,0 +1,3509 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include "isl_map_private.h"
+#include "isl_tab.h"
+#include <isl_seq.h>
+#include <isl_config.h>
+
+/*
+ * The implementation of tableaus in this file was inspired by Section 8
+ * of David Detlefs, Greg Nelson and James B. Saxe, "Simplify: a theorem
+ * prover for program checking".
+ */
+
+struct isl_tab *isl_tab_alloc(struct isl_ctx *ctx,
+ unsigned n_row, unsigned n_var, unsigned M)
+{
+ int i;
+ struct isl_tab *tab;
+ unsigned off = 2 + M;
+
+ tab = isl_calloc_type(ctx, struct isl_tab);
+ if (!tab)
+ return NULL;
+ tab->mat = isl_mat_alloc(ctx, n_row, off + n_var);
+ if (!tab->mat)
+ goto error;
+ tab->var = isl_alloc_array(ctx, struct isl_tab_var, n_var);
+ if (n_var && !tab->var)
+ goto error;
+ tab->con = isl_alloc_array(ctx, struct isl_tab_var, n_row);
+ if (n_row && !tab->con)
+ goto error;
+ tab->col_var = isl_alloc_array(ctx, int, n_var);
+ if (n_var && !tab->col_var)
+ goto error;
+ tab->row_var = isl_alloc_array(ctx, int, n_row);
+ if (n_row && !tab->row_var)
+ goto error;
+ for (i = 0; i < n_var; ++i) {
+ tab->var[i].index = i;
+ tab->var[i].is_row = 0;
+ tab->var[i].is_nonneg = 0;
+ tab->var[i].is_zero = 0;
+ tab->var[i].is_redundant = 0;
+ tab->var[i].frozen = 0;
+ tab->var[i].negated = 0;
+ tab->col_var[i] = i;
+ }
+ tab->n_row = 0;
+ tab->n_con = 0;
+ tab->n_eq = 0;
+ tab->max_con = n_row;
+ tab->n_col = n_var;
+ tab->n_var = n_var;
+ tab->max_var = n_var;
+ tab->n_param = 0;
+ tab->n_div = 0;
+ tab->n_dead = 0;
+ tab->n_redundant = 0;
+ tab->strict_redundant = 0;
+ tab->need_undo = 0;
+ tab->rational = 0;
+ tab->empty = 0;
+ tab->in_undo = 0;
+ tab->M = M;
+ tab->cone = 0;
+ tab->bottom.type = isl_tab_undo_bottom;
+ tab->bottom.next = NULL;
+ tab->top = &tab->bottom;
+
+ tab->n_zero = 0;
+ tab->n_unbounded = 0;
+ tab->basis = NULL;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+isl_ctx *isl_tab_get_ctx(struct isl_tab *tab)
+{
+ return tab ? isl_mat_get_ctx(tab->mat) : NULL;
+}
+
+int isl_tab_extend_cons(struct isl_tab *tab, unsigned n_new)
+{
+ unsigned off;
+
+ if (!tab)
+ return -1;
+
+ off = 2 + tab->M;
+
+ if (tab->max_con < tab->n_con + n_new) {
+ struct isl_tab_var *con;
+
+ con = isl_realloc_array(tab->mat->ctx, tab->con,
+ struct isl_tab_var, tab->max_con + n_new);
+ if (!con)
+ return -1;
+ tab->con = con;
+ tab->max_con += n_new;
+ }
+ if (tab->mat->n_row < tab->n_row + n_new) {
+ int *row_var;
+
+ tab->mat = isl_mat_extend(tab->mat,
+ tab->n_row + n_new, off + tab->n_col);
+ if (!tab->mat)
+ return -1;
+ row_var = isl_realloc_array(tab->mat->ctx, tab->row_var,
+ int, tab->mat->n_row);
+ if (!row_var)
+ return -1;
+ tab->row_var = row_var;
+ if (tab->row_sign) {
+ enum isl_tab_row_sign *s;
+ s = isl_realloc_array(tab->mat->ctx, tab->row_sign,
+ enum isl_tab_row_sign, tab->mat->n_row);
+ if (!s)
+ return -1;
+ tab->row_sign = s;
+ }
+ }
+ return 0;
+}
+
+/* Make room for at least n_new extra variables.
+ * Return -1 if anything went wrong.
+ */
+int isl_tab_extend_vars(struct isl_tab *tab, unsigned n_new)
+{
+ struct isl_tab_var *var;
+ unsigned off = 2 + tab->M;
+
+ if (tab->max_var < tab->n_var + n_new) {
+ var = isl_realloc_array(tab->mat->ctx, tab->var,
+ struct isl_tab_var, tab->n_var + n_new);
+ if (!var)
+ return -1;
+ tab->var = var;
+ tab->max_var += n_new;
+ }
+
+ if (tab->mat->n_col < off + tab->n_col + n_new) {
+ int *p;
+
+ tab->mat = isl_mat_extend(tab->mat,
+ tab->mat->n_row, off + tab->n_col + n_new);
+ if (!tab->mat)
+ return -1;
+ p = isl_realloc_array(tab->mat->ctx, tab->col_var,
+ int, tab->n_col + n_new);
+ if (!p)
+ return -1;
+ tab->col_var = p;
+ }
+
+ return 0;
+}
+
+static void free_undo_record(struct isl_tab_undo *undo)
+{
+ switch (undo->type) {
+ case isl_tab_undo_saved_basis:
+ free(undo->u.col_var);
+ break;
+ default:;
+ }
+ free(undo);
+}
+
+static void free_undo(struct isl_tab *tab)
+{
+ struct isl_tab_undo *undo, *next;
+
+ for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
+ next = undo->next;
+ free_undo_record(undo);
+ }
+ tab->top = undo;
+}
+
+void isl_tab_free(struct isl_tab *tab)
+{
+ if (!tab)
+ return;
+ free_undo(tab);
+ isl_mat_free(tab->mat);
+ isl_vec_free(tab->dual);
+ isl_basic_map_free(tab->bmap);
+ free(tab->var);
+ free(tab->con);
+ free(tab->row_var);
+ free(tab->col_var);
+ free(tab->row_sign);
+ isl_mat_free(tab->samples);
+ free(tab->sample_index);
+ isl_mat_free(tab->basis);
+ free(tab);
+}
+
+struct isl_tab *isl_tab_dup(struct isl_tab *tab)
+{
+ int i;
+ struct isl_tab *dup;
+ unsigned off;
+
+ if (!tab)
+ return NULL;
+
+ off = 2 + tab->M;
+ dup = isl_calloc_type(tab->mat->ctx, struct isl_tab);
+ if (!dup)
+ return NULL;
+ dup->mat = isl_mat_dup(tab->mat);
+ if (!dup->mat)
+ goto error;
+ dup->var = isl_alloc_array(tab->mat->ctx, struct isl_tab_var, tab->max_var);
+ if (tab->max_var && !dup->var)
+ goto error;
+ for (i = 0; i < tab->n_var; ++i)
+ dup->var[i] = tab->var[i];
+ dup->con = isl_alloc_array(tab->mat->ctx, struct isl_tab_var, tab->max_con);
+ if (tab->max_con && !dup->con)
+ goto error;
+ for (i = 0; i < tab->n_con; ++i)
+ dup->con[i] = tab->con[i];
+ dup->col_var = isl_alloc_array(tab->mat->ctx, int, tab->mat->n_col - off);
+ if ((tab->mat->n_col - off) && !dup->col_var)
+ goto error;
+ for (i = 0; i < tab->n_col; ++i)
+ dup->col_var[i] = tab->col_var[i];
+ dup->row_var = isl_alloc_array(tab->mat->ctx, int, tab->mat->n_row);
+ if (tab->mat->n_row && !dup->row_var)
+ goto error;
+ for (i = 0; i < tab->n_row; ++i)
+ dup->row_var[i] = tab->row_var[i];
+ if (tab->row_sign) {
+ dup->row_sign = isl_alloc_array(tab->mat->ctx, enum isl_tab_row_sign,
+ tab->mat->n_row);
+ if (tab->mat->n_row && !dup->row_sign)
+ goto error;
+ for (i = 0; i < tab->n_row; ++i)
+ dup->row_sign[i] = tab->row_sign[i];
+ }
+ if (tab->samples) {
+ dup->samples = isl_mat_dup(tab->samples);
+ if (!dup->samples)
+ goto error;
+ dup->sample_index = isl_alloc_array(tab->mat->ctx, int,
+ tab->samples->n_row);
+ if (tab->samples->n_row && !dup->sample_index)
+ goto error;
+ dup->n_sample = tab->n_sample;
+ dup->n_outside = tab->n_outside;
+ }
+ dup->n_row = tab->n_row;
+ dup->n_con = tab->n_con;
+ dup->n_eq = tab->n_eq;
+ dup->max_con = tab->max_con;
+ dup->n_col = tab->n_col;
+ dup->n_var = tab->n_var;
+ dup->max_var = tab->max_var;
+ dup->n_param = tab->n_param;
+ dup->n_div = tab->n_div;
+ dup->n_dead = tab->n_dead;
+ dup->n_redundant = tab->n_redundant;
+ dup->rational = tab->rational;
+ dup->empty = tab->empty;
+ dup->strict_redundant = 0;
+ dup->need_undo = 0;
+ dup->in_undo = 0;
+ dup->M = tab->M;
+ tab->cone = tab->cone;
+ dup->bottom.type = isl_tab_undo_bottom;
+ dup->bottom.next = NULL;
+ dup->top = &dup->bottom;
+
+ dup->n_zero = tab->n_zero;
+ dup->n_unbounded = tab->n_unbounded;
+ dup->basis = isl_mat_dup(tab->basis);
+
+ return dup;
+error:
+ isl_tab_free(dup);
+ return NULL;
+}
+
+/* Construct the coefficient matrix of the product tableau
+ * of two tableaus.
+ * mat{1,2} is the coefficient matrix of tableau {1,2}
+ * row{1,2} is the number of rows in tableau {1,2}
+ * col{1,2} is the number of columns in tableau {1,2}
+ * off is the offset to the coefficient column (skipping the
+ * denominator, the constant term and the big parameter if any)
+ * r{1,2} is the number of redundant rows in tableau {1,2}
+ * d{1,2} is the number of dead columns in tableau {1,2}
+ *
+ * The order of the rows and columns in the result is as explained
+ * in isl_tab_product.
+ */
+static struct isl_mat *tab_mat_product(struct isl_mat *mat1,
+ struct isl_mat *mat2, unsigned row1, unsigned row2,
+ unsigned col1, unsigned col2,
+ unsigned off, unsigned r1, unsigned r2, unsigned d1, unsigned d2)
+{
+ int i;
+ struct isl_mat *prod;
+ unsigned n;
+
+ prod = isl_mat_alloc(mat1->ctx, mat1->n_row + mat2->n_row,
+ off + col1 + col2);
+ if (!prod)
+ return NULL;
+
+ n = 0;
+ for (i = 0; i < r1; ++i) {
+ isl_seq_cpy(prod->row[n + i], mat1->row[i], off + d1);
+ isl_seq_clr(prod->row[n + i] + off + d1, d2);
+ isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
+ mat1->row[i] + off + d1, col1 - d1);
+ isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
+ }
+
+ n += r1;
+ for (i = 0; i < r2; ++i) {
+ isl_seq_cpy(prod->row[n + i], mat2->row[i], off);
+ isl_seq_clr(prod->row[n + i] + off, d1);
+ isl_seq_cpy(prod->row[n + i] + off + d1,
+ mat2->row[i] + off, d2);
+ isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
+ isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
+ mat2->row[i] + off + d2, col2 - d2);
+ }
+
+ n += r2;
+ for (i = 0; i < row1 - r1; ++i) {
+ isl_seq_cpy(prod->row[n + i], mat1->row[r1 + i], off + d1);
+ isl_seq_clr(prod->row[n + i] + off + d1, d2);
+ isl_seq_cpy(prod->row[n + i] + off + d1 + d2,
+ mat1->row[r1 + i] + off + d1, col1 - d1);
+ isl_seq_clr(prod->row[n + i] + off + col1 + d1, col2 - d2);
+ }
+
+ n += row1 - r1;
+ for (i = 0; i < row2 - r2; ++i) {
+ isl_seq_cpy(prod->row[n + i], mat2->row[r2 + i], off);
+ isl_seq_clr(prod->row[n + i] + off, d1);
+ isl_seq_cpy(prod->row[n + i] + off + d1,
+ mat2->row[r2 + i] + off, d2);
+ isl_seq_clr(prod->row[n + i] + off + d1 + d2, col1 - d1);
+ isl_seq_cpy(prod->row[n + i] + off + col1 + d1,
+ mat2->row[r2 + i] + off + d2, col2 - d2);
+ }
+
+ return prod;
+}
+
+/* Update the row or column index of a variable that corresponds
+ * to a variable in the first input tableau.
+ */
+static void update_index1(struct isl_tab_var *var,
+ unsigned r1, unsigned r2, unsigned d1, unsigned d2)
+{
+ if (var->index == -1)
+ return;
+ if (var->is_row && var->index >= r1)
+ var->index += r2;
+ if (!var->is_row && var->index >= d1)
+ var->index += d2;
+}
+
+/* Update the row or column index of a variable that corresponds
+ * to a variable in the second input tableau.
+ */
+static void update_index2(struct isl_tab_var *var,
+ unsigned row1, unsigned col1,
+ unsigned r1, unsigned r2, unsigned d1, unsigned d2)
+{
+ if (var->index == -1)
+ return;
+ if (var->is_row) {
+ if (var->index < r2)
+ var->index += r1;
+ else
+ var->index += row1;
+ } else {
+ if (var->index < d2)
+ var->index += d1;
+ else
+ var->index += col1;
+ }
+}
+
+/* Create a tableau that represents the Cartesian product of the sets
+ * represented by tableaus tab1 and tab2.
+ * The order of the rows in the product is
+ * - redundant rows of tab1
+ * - redundant rows of tab2
+ * - non-redundant rows of tab1
+ * - non-redundant rows of tab2
+ * The order of the columns is
+ * - denominator
+ * - constant term
+ * - coefficient of big parameter, if any
+ * - dead columns of tab1
+ * - dead columns of tab2
+ * - live columns of tab1
+ * - live columns of tab2
+ * The order of the variables and the constraints is a concatenation
+ * of order in the two input tableaus.
+ */
+struct isl_tab *isl_tab_product(struct isl_tab *tab1, struct isl_tab *tab2)
+{
+ int i;
+ struct isl_tab *prod;
+ unsigned off;
+ unsigned r1, r2, d1, d2;
+
+ if (!tab1 || !tab2)
+ return NULL;
+
+ isl_assert(tab1->mat->ctx, tab1->M == tab2->M, return NULL);
+ isl_assert(tab1->mat->ctx, tab1->rational == tab2->rational, return NULL);
+ isl_assert(tab1->mat->ctx, tab1->cone == tab2->cone, return NULL);
+ isl_assert(tab1->mat->ctx, !tab1->row_sign, return NULL);
+ isl_assert(tab1->mat->ctx, !tab2->row_sign, return NULL);
+ isl_assert(tab1->mat->ctx, tab1->n_param == 0, return NULL);
+ isl_assert(tab1->mat->ctx, tab2->n_param == 0, return NULL);
+ isl_assert(tab1->mat->ctx, tab1->n_div == 0, return NULL);
+ isl_assert(tab1->mat->ctx, tab2->n_div == 0, return NULL);
+
+ off = 2 + tab1->M;
+ r1 = tab1->n_redundant;
+ r2 = tab2->n_redundant;
+ d1 = tab1->n_dead;
+ d2 = tab2->n_dead;
+ prod = isl_calloc_type(tab1->mat->ctx, struct isl_tab);
+ if (!prod)
+ return NULL;
+ prod->mat = tab_mat_product(tab1->mat, tab2->mat,
+ tab1->n_row, tab2->n_row,
+ tab1->n_col, tab2->n_col, off, r1, r2, d1, d2);
+ if (!prod->mat)
+ goto error;
+ prod->var = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
+ tab1->max_var + tab2->max_var);
+ if ((tab1->max_var + tab2->max_var) && !prod->var)
+ goto error;
+ for (i = 0; i < tab1->n_var; ++i) {
+ prod->var[i] = tab1->var[i];
+ update_index1(&prod->var[i], r1, r2, d1, d2);
+ }
+ for (i = 0; i < tab2->n_var; ++i) {
+ prod->var[tab1->n_var + i] = tab2->var[i];
+ update_index2(&prod->var[tab1->n_var + i],
+ tab1->n_row, tab1->n_col,
+ r1, r2, d1, d2);
+ }
+ prod->con = isl_alloc_array(tab1->mat->ctx, struct isl_tab_var,
+ tab1->max_con + tab2->max_con);
+ if ((tab1->max_con + tab2->max_con) && !prod->con)
+ goto error;
+ for (i = 0; i < tab1->n_con; ++i) {
+ prod->con[i] = tab1->con[i];
+ update_index1(&prod->con[i], r1, r2, d1, d2);
+ }
+ for (i = 0; i < tab2->n_con; ++i) {
+ prod->con[tab1->n_con + i] = tab2->con[i];
+ update_index2(&prod->con[tab1->n_con + i],
+ tab1->n_row, tab1->n_col,
+ r1, r2, d1, d2);
+ }
+ prod->col_var = isl_alloc_array(tab1->mat->ctx, int,
+ tab1->n_col + tab2->n_col);
+ if ((tab1->n_col + tab2->n_col) && !prod->col_var)
+ goto error;
+ for (i = 0; i < tab1->n_col; ++i) {
+ int pos = i < d1 ? i : i + d2;
+ prod->col_var[pos] = tab1->col_var[i];
+ }
+ for (i = 0; i < tab2->n_col; ++i) {
+ int pos = i < d2 ? d1 + i : tab1->n_col + i;
+ int t = tab2->col_var[i];
+ if (t >= 0)
+ t += tab1->n_var;
+ else
+ t -= tab1->n_con;
+ prod->col_var[pos] = t;
+ }
+ prod->row_var = isl_alloc_array(tab1->mat->ctx, int,
+ tab1->mat->n_row + tab2->mat->n_row);
+ if ((tab1->mat->n_row + tab2->mat->n_row) && !prod->row_var)
+ goto error;
+ for (i = 0; i < tab1->n_row; ++i) {
+ int pos = i < r1 ? i : i + r2;
+ prod->row_var[pos] = tab1->row_var[i];
+ }
+ for (i = 0; i < tab2->n_row; ++i) {
+ int pos = i < r2 ? r1 + i : tab1->n_row + i;
+ int t = tab2->row_var[i];
+ if (t >= 0)
+ t += tab1->n_var;
+ else
+ t -= tab1->n_con;
+ prod->row_var[pos] = t;
+ }
+ prod->samples = NULL;
+ prod->sample_index = NULL;
+ prod->n_row = tab1->n_row + tab2->n_row;
+ prod->n_con = tab1->n_con + tab2->n_con;
+ prod->n_eq = 0;
+ prod->max_con = tab1->max_con + tab2->max_con;
+ prod->n_col = tab1->n_col + tab2->n_col;
+ prod->n_var = tab1->n_var + tab2->n_var;
+ prod->max_var = tab1->max_var + tab2->max_var;
+ prod->n_param = 0;
+ prod->n_div = 0;
+ prod->n_dead = tab1->n_dead + tab2->n_dead;
+ prod->n_redundant = tab1->n_redundant + tab2->n_redundant;
+ prod->rational = tab1->rational;
+ prod->empty = tab1->empty || tab2->empty;
+ prod->strict_redundant = tab1->strict_redundant || tab2->strict_redundant;
+ prod->need_undo = 0;
+ prod->in_undo = 0;
+ prod->M = tab1->M;
+ prod->cone = tab1->cone;
+ prod->bottom.type = isl_tab_undo_bottom;
+ prod->bottom.next = NULL;
+ prod->top = &prod->bottom;
+
+ prod->n_zero = 0;
+ prod->n_unbounded = 0;
+ prod->basis = NULL;
+
+ return prod;
+error:
+ isl_tab_free(prod);
+ return NULL;
+}
+
+static struct isl_tab_var *var_from_index(struct isl_tab *tab, int i)
+{
+ if (i >= 0)
+ return &tab->var[i];
+ else
+ return &tab->con[~i];
+}
+
+struct isl_tab_var *isl_tab_var_from_row(struct isl_tab *tab, int i)
+{
+ return var_from_index(tab, tab->row_var[i]);
+}
+
+static struct isl_tab_var *var_from_col(struct isl_tab *tab, int i)
+{
+ return var_from_index(tab, tab->col_var[i]);
+}
+
+/* Check if there are any upper bounds on column variable "var",
+ * i.e., non-negative rows where var appears with a negative coefficient.
+ * Return 1 if there are no such bounds.
+ */
+static int max_is_manifestly_unbounded(struct isl_tab *tab,
+ struct isl_tab_var *var)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ if (var->is_row)
+ return 0;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ if (!isl_int_is_neg(tab->mat->row[i][off + var->index]))
+ continue;
+ if (isl_tab_var_from_row(tab, i)->is_nonneg)
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if there are any lower bounds on column variable "var",
+ * i.e., non-negative rows where var appears with a positive coefficient.
+ * Return 1 if there are no such bounds.
+ */
+static int min_is_manifestly_unbounded(struct isl_tab *tab,
+ struct isl_tab_var *var)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ if (var->is_row)
+ return 0;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ if (!isl_int_is_pos(tab->mat->row[i][off + var->index]))
+ continue;
+ if (isl_tab_var_from_row(tab, i)->is_nonneg)
+ return 0;
+ }
+ return 1;
+}
+
+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);
+ 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);
+}
+
+/* Given the index of a column "c", return the index of a row
+ * that can be used to pivot the column in, with either an increase
+ * (sgn > 0) or a decrease (sgn < 0) of the corresponding variable.
+ * If "var" is not NULL, then the row returned will be different from
+ * the one associated with "var".
+ *
+ * Each row in the tableau is of the form
+ *
+ * x_r = a_r0 + \sum_i a_ri x_i
+ *
+ * Only rows with x_r >= 0 and with the sign of a_ri opposite to "sgn"
+ * impose any limit on the increase or decrease in the value of x_c
+ * and this bound is equal to a_r0 / |a_rc|. We are therefore looking
+ * for the row with the smallest (most stringent) such bound.
+ * Note that the common denominator of each row drops out of the fraction.
+ * To check if row j has a smaller bound than row r, i.e.,
+ * a_j0 / |a_jc| < a_r0 / |a_rc| or a_j0 |a_rc| < a_r0 |a_jc|,
+ * we check if -sign(a_jc) (a_j0 a_rc - a_r0 a_jc) < 0,
+ * where -sign(a_jc) is equal to "sgn".
+ */
+static int pivot_row(struct isl_tab *tab,
+ struct isl_tab_var *var, int sgn, int c)
+{
+ int j, r, tsgn;
+ isl_int t;
+ unsigned off = 2 + tab->M;
+
+ isl_int_init(t);
+ r = -1;
+ for (j = tab->n_redundant; j < tab->n_row; ++j) {
+ if (var && j == var->index)
+ continue;
+ if (!isl_tab_var_from_row(tab, j)->is_nonneg)
+ continue;
+ if (sgn * isl_int_sgn(tab->mat->row[j][off + c]) >= 0)
+ continue;
+ if (r < 0) {
+ r = j;
+ continue;
+ }
+ tsgn = sgn * row_cmp(tab, r, j, c, t);
+ if (tsgn < 0 || (tsgn == 0 &&
+ tab->row_var[j] < tab->row_var[r]))
+ r = j;
+ }
+ isl_int_clear(t);
+ return r;
+}
+
+/* Find a pivot (row and col) that will increase (sgn > 0) or decrease
+ * (sgn < 0) the value of row variable var.
+ * If not NULL, then skip_var is a row variable that should be ignored
+ * while looking for a pivot row. It is usually equal to var.
+ *
+ * As the given row in the tableau is of the form
+ *
+ * x_r = a_r0 + \sum_i a_ri x_i
+ *
+ * we need to find a column such that the sign of a_ri is equal to "sgn"
+ * (such that an increase in x_i will have the desired effect) or a
+ * column with a variable that may attain negative values.
+ * If a_ri is positive, then we need to move x_i in the same direction
+ * to obtain the desired effect. Otherwise, x_i has to move in the
+ * opposite direction.
+ */
+static void find_pivot(struct isl_tab *tab,
+ struct isl_tab_var *var, struct isl_tab_var *skip_var,
+ int sgn, int *row, int *col)
+{
+ int j, r, c;
+ isl_int *tr;
+
+ *row = *col = -1;
+
+ isl_assert(tab->mat->ctx, var->is_row, return);
+ tr = tab->mat->row[var->index] + 2 + tab->M;
+
+ c = -1;
+ for (j = tab->n_dead; j < tab->n_col; ++j) {
+ if (isl_int_is_zero(tr[j]))
+ continue;
+ if (isl_int_sgn(tr[j]) != sgn &&
+ var_from_col(tab, j)->is_nonneg)
+ continue;
+ if (c < 0 || tab->col_var[j] < tab->col_var[c])
+ c = j;
+ }
+ if (c < 0)
+ return;
+
+ sgn *= isl_int_sgn(tr[c]);
+ r = pivot_row(tab, skip_var, sgn, c);
+ *row = r < 0 ? var->index : r;
+ *col = c;
+}
+
+/* Return 1 if row "row" represents an obviously redundant inequality.
+ * This means
+ * - it represents an inequality or a variable
+ * - that is the sum of a non-negative sample value and a positive
+ * combination of zero or more non-negative constraints.
+ */
+int isl_tab_row_is_redundant(struct isl_tab *tab, int row)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ if (tab->row_var[row] < 0 && !isl_tab_var_from_row(tab, row)->is_nonneg)
+ return 0;
+
+ if (isl_int_is_neg(tab->mat->row[row][1]))
+ return 0;
+ if (tab->strict_redundant && isl_int_is_zero(tab->mat->row[row][1]))
+ return 0;
+ if (tab->M && isl_int_is_neg(tab->mat->row[row][2]))
+ return 0;
+
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ if (isl_int_is_zero(tab->mat->row[row][off + i]))
+ continue;
+ if (tab->col_var[i] >= 0)
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][off + i]))
+ return 0;
+ if (!var_from_col(tab, i)->is_nonneg)
+ return 0;
+ }
+ return 1;
+}
+
+static void swap_rows(struct isl_tab *tab, int row1, int row2)
+{
+ int t;
+ enum isl_tab_row_sign s;
+
+ t = tab->row_var[row1];
+ tab->row_var[row1] = tab->row_var[row2];
+ tab->row_var[row2] = t;
+ isl_tab_var_from_row(tab, row1)->index = row1;
+ isl_tab_var_from_row(tab, row2)->index = row2;
+ tab->mat = isl_mat_swap_rows(tab->mat, row1, row2);
+
+ if (!tab->row_sign)
+ return;
+ s = tab->row_sign[row1];
+ tab->row_sign[row1] = tab->row_sign[row2];
+ tab->row_sign[row2] = s;
+}
+
+static int push_union(struct isl_tab *tab,
+ enum isl_tab_undo_type type, union isl_tab_undo_val u) WARN_UNUSED;
+static int push_union(struct isl_tab *tab,
+ enum isl_tab_undo_type type, union isl_tab_undo_val u)
+{
+ struct isl_tab_undo *undo;
+
+ if (!tab)
+ return -1;
+ if (!tab->need_undo)
+ return 0;
+
+ undo = isl_alloc_type(tab->mat->ctx, struct isl_tab_undo);
+ if (!undo)
+ return -1;
+ undo->type = type;
+ undo->u = u;
+ undo->next = tab->top;
+ tab->top = undo;
+
+ return 0;
+}
+
+int isl_tab_push_var(struct isl_tab *tab,
+ enum isl_tab_undo_type type, struct isl_tab_var *var)
+{
+ union isl_tab_undo_val u;
+ if (var->is_row)
+ u.var_index = tab->row_var[var->index];
+ else
+ u.var_index = tab->col_var[var->index];
+ return push_union(tab, type, u);
+}
+
+int isl_tab_push(struct isl_tab *tab, enum isl_tab_undo_type type)
+{
+ union isl_tab_undo_val u = { 0 };
+ return push_union(tab, type, u);
+}
+
+/* Push a record on the undo stack describing the current basic
+ * variables, so that the this state can be restored during rollback.
+ */
+int isl_tab_push_basis(struct isl_tab *tab)
+{
+ int i;
+ union isl_tab_undo_val u;
+
+ u.col_var = isl_alloc_array(tab->mat->ctx, int, tab->n_col);
+ if (tab->n_col && !u.col_var)
+ return -1;
+ for (i = 0; i < tab->n_col; ++i)
+ u.col_var[i] = tab->col_var[i];
+ return push_union(tab, isl_tab_undo_saved_basis, u);
+}
+
+int isl_tab_push_callback(struct isl_tab *tab, struct isl_tab_callback *callback)
+{
+ union isl_tab_undo_val u;
+ u.callback = callback;
+ return push_union(tab, isl_tab_undo_callback, u);
+}
+
+struct isl_tab *isl_tab_init_samples(struct isl_tab *tab)
+{
+ if (!tab)
+ return NULL;
+
+ tab->n_sample = 0;
+ tab->n_outside = 0;
+ tab->samples = isl_mat_alloc(tab->mat->ctx, 1, 1 + tab->n_var);
+ if (!tab->samples)
+ goto error;
+ tab->sample_index = isl_alloc_array(tab->mat->ctx, int, 1);
+ if (!tab->sample_index)
+ goto error;
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+int isl_tab_add_sample(struct isl_tab *tab, __isl_take isl_vec *sample)
+{
+ if (!tab || !sample)
+ goto error;
+
+ if (tab->n_sample + 1 > tab->samples->n_row) {
+ int *t = isl_realloc_array(tab->mat->ctx,
+ tab->sample_index, int, tab->n_sample + 1);
+ if (!t)
+ goto error;
+ tab->sample_index = t;
+ }
+
+ tab->samples = isl_mat_extend(tab->samples,
+ tab->n_sample + 1, tab->samples->n_col);
+ if (!tab->samples)
+ goto error;
+
+ isl_seq_cpy(tab->samples->row[tab->n_sample], sample->el, sample->size);
+ isl_vec_free(sample);
+ tab->sample_index[tab->n_sample] = tab->n_sample;
+ tab->n_sample++;
+
+ return 0;
+error:
+ isl_vec_free(sample);
+ return -1;
+}
+
+struct isl_tab *isl_tab_drop_sample(struct isl_tab *tab, int s)
+{
+ if (s != tab->n_outside) {
+ int t = tab->sample_index[tab->n_outside];
+ tab->sample_index[tab->n_outside] = tab->sample_index[s];
+ tab->sample_index[s] = t;
+ isl_mat_swap_rows(tab->samples, tab->n_outside, s);
+ }
+ tab->n_outside++;
+ if (isl_tab_push(tab, isl_tab_undo_drop_sample) < 0) {
+ isl_tab_free(tab);
+ return NULL;
+ }
+
+ return tab;
+}
+
+/* Record the current number of samples so that we can remove newer
+ * samples during a rollback.
+ */
+int isl_tab_save_samples(struct isl_tab *tab)
+{
+ union isl_tab_undo_val u;
+
+ if (!tab)
+ return -1;
+
+ u.n = tab->n_sample;
+ return push_union(tab, isl_tab_undo_saved_samples, u);
+}
+
+/* Mark row with index "row" as being redundant.
+ * If we may need to undo the operation or if the row represents
+ * a variable of the original problem, the row is kept,
+ * but no longer considered when looking for a pivot row.
+ * Otherwise, the row is simply removed.
+ *
+ * The row may be interchanged with some other row. If it
+ * is interchanged with a later row, return 1. Otherwise return 0.
+ * If the rows are checked in order in the calling function,
+ * then a return value of 1 means that the row with the given
+ * row number may now contain a different row that hasn't been checked yet.
+ */
+int isl_tab_mark_redundant(struct isl_tab *tab, int row)
+{
+ struct isl_tab_var *var = isl_tab_var_from_row(tab, row);
+ var->is_redundant = 1;
+ isl_assert(tab->mat->ctx, row >= tab->n_redundant, return -1);
+ if (tab->preserve || tab->need_undo || tab->row_var[row] >= 0) {
+ if (tab->row_var[row] >= 0 && !var->is_nonneg) {
+ var->is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, var) < 0)
+ return -1;
+ }
+ if (row != tab->n_redundant)
+ swap_rows(tab, row, tab->n_redundant);
+ tab->n_redundant++;
+ return isl_tab_push_var(tab, isl_tab_undo_redundant, var);
+ } else {
+ if (row != tab->n_row - 1)
+ swap_rows(tab, row, tab->n_row - 1);
+ isl_tab_var_from_row(tab, tab->n_row - 1)->index = -1;
+ tab->n_row--;
+ return 1;
+ }
+}
+
+int isl_tab_mark_empty(struct isl_tab *tab)
+{
+ if (!tab)
+ return -1;
+ if (!tab->empty && tab->need_undo)
+ if (isl_tab_push(tab, isl_tab_undo_empty) < 0)
+ return -1;
+ tab->empty = 1;
+ return 0;
+}
+
+int isl_tab_freeze_constraint(struct isl_tab *tab, int con)
+{
+ struct isl_tab_var *var;
+
+ if (!tab)
+ return -1;
+
+ var = &tab->con[con];
+ if (var->frozen)
+ return 0;
+ if (var->index < 0)
+ return 0;
+ var->frozen = 1;
+
+ if (tab->need_undo)
+ return isl_tab_push_var(tab, isl_tab_undo_freeze, var);
+
+ return 0;
+}
+
+/* Update the rows signs after a pivot of "row" and "col", with "row_sgn"
+ * the original sign of the pivot element.
+ * We only keep track of row signs during PILP solving and in this case
+ * we only pivot a row with negative sign (meaning the value is always
+ * non-positive) using a positive pivot element.
+ *
+ * For each row j, the new value of the parametric constant is equal to
+ *
+ * a_j0 - a_jc a_r0/a_rc
+ *
+ * where a_j0 is the original parametric constant, a_rc is the pivot element,
+ * a_r0 is the parametric constant of the pivot row and a_jc is the
+ * pivot column entry of the row j.
+ * Since a_r0 is non-positive and a_rc is positive, the sign of row j
+ * remains the same if a_jc has the same sign as the row j or if
+ * a_jc is zero. In all other cases, we reset the sign to "unknown".
+ */
+static void update_row_sign(struct isl_tab *tab, int row, int col, int row_sgn)
+{
+ int i;
+ struct isl_mat *mat = tab->mat;
+ unsigned off = 2 + tab->M;
+
+ if (!tab->row_sign)
+ return;
+
+ if (tab->row_sign[row] == 0)
+ return;
+ isl_assert(mat->ctx, row_sgn > 0, return);
+ isl_assert(mat->ctx, tab->row_sign[row] == isl_tab_row_neg, return);
+ tab->row_sign[row] = isl_tab_row_pos;
+ for (i = 0; i < tab->n_row; ++i) {
+ int s;
+ if (i == row)
+ continue;
+ s = isl_int_sgn(mat->row[i][off + col]);
+ if (!s)
+ continue;
+ if (!tab->row_sign[i])
+ continue;
+ if (s < 0 && tab->row_sign[i] == isl_tab_row_neg)
+ continue;
+ if (s > 0 && tab->row_sign[i] == isl_tab_row_pos)
+ continue;
+ tab->row_sign[i] = isl_tab_row_unknown;
+ }
+}
+
+/* Given a row number "row" and a column number "col", pivot the tableau
+ * such that the associated variables are interchanged.
+ * The given row in the tableau expresses
+ *
+ * x_r = a_r0 + \sum_i a_ri x_i
+ *
+ * or
+ *
+ * x_c = 1/a_rc x_r - a_r0/a_rc + sum_{i \ne r} -a_ri/a_rc
+ *
+ * Substituting this equality into the other rows
+ *
+ * x_j = a_j0 + \sum_i a_ji x_i
+ *
+ * with a_jc \ne 0, we obtain
+ *
+ * x_j = a_jc/a_rc x_r + a_j0 - a_jc a_r0/a_rc + sum a_ji - a_jc a_ri/a_rc
+ *
+ * The tableau
+ *
+ * n_rc/d_r n_ri/d_r
+ * n_jc/d_j n_ji/d_j
+ *
+ * where i is any other column and j is any other row,
+ * is therefore transformed into
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * s(n_rc)d_r n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
+ *
+ * The transformation is performed along the following steps
+ *
+ * d_r/n_rc n_ri/n_rc
+ * n_jc/d_j n_ji/d_j
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * n_jc/d_j n_ji/d_j
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * n_jc/(|n_rc| d_j) n_ji/(|n_rc| d_j)
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * n_jc/(|n_rc| d_j) (n_ji |n_rc|)/(|n_rc| d_j)
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
+ *
+ * s(n_rc)d_r/|n_rc| -s(n_rc)n_ri/|n_rc|
+ * s(n_rc)d_r n_jc/(|n_rc| d_j) (n_ji |n_rc| - s(n_rc)n_jc n_ri)/(|n_rc| d_j)
+ *
+ */
+int isl_tab_pivot(struct isl_tab *tab, int row, int col)
+{
+ int i, j;
+ int sgn;
+ int t;
+ isl_ctx *ctx;
+ struct isl_mat *mat = tab->mat;
+ struct isl_tab_var *var;
+ unsigned off = 2 + tab->M;
+
+ ctx = isl_tab_get_ctx(tab);
+ if (isl_ctx_next_operation(ctx) < 0)
+ return -1;
+
+ isl_int_swap(mat->row[row][0], mat->row[row][off + col]);
+ sgn = isl_int_sgn(mat->row[row][0]);
+ if (sgn < 0) {
+ isl_int_neg(mat->row[row][0], mat->row[row][0]);
+ isl_int_neg(mat->row[row][off + col], mat->row[row][off + col]);
+ } else
+ for (j = 0; j < off - 1 + tab->n_col; ++j) {
+ if (j == off - 1 + col)
+ continue;
+ isl_int_neg(mat->row[row][1 + j], mat->row[row][1 + j]);
+ }
+ if (!isl_int_is_one(mat->row[row][0]))
+ isl_seq_normalize(mat->ctx, mat->row[row], off + tab->n_col);
+ for (i = 0; i < tab->n_row; ++i) {
+ if (i == row)
+ continue;
+ if (isl_int_is_zero(mat->row[i][off + col]))
+ continue;
+ isl_int_mul(mat->row[i][0], mat->row[i][0], mat->row[row][0]);
+ for (j = 0; j < off - 1 + tab->n_col; ++j) {
+ if (j == off - 1 + col)
+ continue;
+ isl_int_mul(mat->row[i][1 + j],
+ mat->row[i][1 + j], mat->row[row][0]);
+ isl_int_addmul(mat->row[i][1 + j],
+ mat->row[i][off + col], mat->row[row][1 + j]);
+ }
+ isl_int_mul(mat->row[i][off + col],
+ mat->row[i][off + col], mat->row[row][off + col]);
+ if (!isl_int_is_one(mat->row[i][0]))
+ isl_seq_normalize(mat->ctx, mat->row[i], off + tab->n_col);
+ }
+ t = tab->row_var[row];
+ tab->row_var[row] = tab->col_var[col];
+ tab->col_var[col] = t;
+ var = isl_tab_var_from_row(tab, row);
+ var->is_row = 1;
+ var->index = row;
+ var = var_from_col(tab, col);
+ var->is_row = 0;
+ var->index = col;
+ update_row_sign(tab, row, col, sgn);
+ if (tab->in_undo)
+ return 0;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ if (isl_int_is_zero(mat->row[i][off + col]))
+ continue;
+ if (!isl_tab_var_from_row(tab, i)->frozen &&
+ isl_tab_row_is_redundant(tab, i)) {
+ int redo = isl_tab_mark_redundant(tab, i);
+ if (redo < 0)
+ return -1;
+ if (redo)
+ --i;
+ }
+ }
+ return 0;
+}
+
+/* If "var" represents a column variable, then pivot is up (sgn > 0)
+ * or down (sgn < 0) to a row. The variable is assumed not to be
+ * unbounded in the specified direction.
+ * If sgn = 0, then the variable is unbounded in both directions,
+ * and we pivot with any row we can find.
+ */
+static int to_row(struct isl_tab *tab, struct isl_tab_var *var, int sign) WARN_UNUSED;
+static int to_row(struct isl_tab *tab, struct isl_tab_var *var, int sign)
+{
+ int r;
+ unsigned off = 2 + tab->M;
+
+ if (var->is_row)
+ return 0;
+
+ if (sign == 0) {
+ for (r = tab->n_redundant; r < tab->n_row; ++r)
+ if (!isl_int_is_zero(tab->mat->row[r][off+var->index]))
+ break;
+ isl_assert(tab->mat->ctx, r < tab->n_row, return -1);
+ } else {
+ r = pivot_row(tab, NULL, sign, var->index);
+ isl_assert(tab->mat->ctx, r >= 0, return -1);
+ }
+
+ return isl_tab_pivot(tab, r, var->index);
+}
+
+/* Check whether all variables that are marked as non-negative
+ * also have a non-negative sample value. This function is not
+ * called from the current code but is useful during debugging.
+ */
+static void check_table(struct isl_tab *tab) __attribute__ ((unused));
+static void check_table(struct isl_tab *tab)
+{
+ int i;
+
+ if (tab->empty)
+ return;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ struct isl_tab_var *var;
+ var = isl_tab_var_from_row(tab, i);
+ if (!var->is_nonneg)
+ continue;
+ if (tab->M) {
+ isl_assert(tab->mat->ctx,
+ !isl_int_is_neg(tab->mat->row[i][2]), abort());
+ if (isl_int_is_pos(tab->mat->row[i][2]))
+ continue;
+ }
+ isl_assert(tab->mat->ctx, !isl_int_is_neg(tab->mat->row[i][1]),
+ abort());
+ }
+}
+
+/* Return the sign of the maximal value of "var".
+ * If the sign is not negative, then on return from this function,
+ * the sample value will also be non-negative.
+ *
+ * If "var" is manifestly unbounded wrt positive values, we are done.
+ * Otherwise, we pivot the variable up to a row if needed
+ * Then we continue pivoting down until either
+ * - no more down pivots can be performed
+ * - the sample value is positive
+ * - the variable is pivoted into a manifestly unbounded column
+ */
+static int sign_of_max(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+
+ if (max_is_manifestly_unbounded(tab, var))
+ return 1;
+ if (to_row(tab, var, 1) < 0)
+ return -2;
+ while (!isl_int_is_pos(tab->mat->row[var->index][1])) {
+ find_pivot(tab, var, var, 1, &row, &col);
+ if (row == -1)
+ return isl_int_sgn(tab->mat->row[var->index][1]);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ if (!var->is_row) /* manifestly unbounded */
+ return 1;
+ }
+ return 1;
+}
+
+int isl_tab_sign_of_max(struct isl_tab *tab, int con)
+{
+ struct isl_tab_var *var;
+
+ if (!tab)
+ return -2;
+
+ var = &tab->con[con];
+ isl_assert(tab->mat->ctx, !var->is_redundant, return -2);
+ isl_assert(tab->mat->ctx, !var->is_zero, return -2);
+
+ return sign_of_max(tab, var);
+}
+
+static int row_is_neg(struct isl_tab *tab, int row)
+{
+ if (!tab->M)
+ return isl_int_is_neg(tab->mat->row[row][1]);
+ if (isl_int_is_pos(tab->mat->row[row][2]))
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][2]))
+ return 1;
+ return isl_int_is_neg(tab->mat->row[row][1]);
+}
+
+static int row_sgn(struct isl_tab *tab, int row)
+{
+ if (!tab->M)
+ return isl_int_sgn(tab->mat->row[row][1]);
+ if (!isl_int_is_zero(tab->mat->row[row][2]))
+ return isl_int_sgn(tab->mat->row[row][2]);
+ else
+ return isl_int_sgn(tab->mat->row[row][1]);
+}
+
+/* Perform pivots until the row variable "var" has a non-negative
+ * sample value or until no more upward pivots can be performed.
+ * Return the sign of the sample value after the pivots have been
+ * performed.
+ */
+static int restore_row(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+
+ while (row_is_neg(tab, var->index)) {
+ find_pivot(tab, var, var, 1, &row, &col);
+ if (row == -1)
+ break;
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ if (!var->is_row) /* manifestly unbounded */
+ return 1;
+ }
+ return row_sgn(tab, var->index);
+}
+
+/* Perform pivots until we are sure that the row variable "var"
+ * can attain non-negative values. After return from this
+ * function, "var" is still a row variable, but its sample
+ * value may not be non-negative, even if the function returns 1.
+ */
+static int at_least_zero(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+
+ while (isl_int_is_neg(tab->mat->row[var->index][1])) {
+ find_pivot(tab, var, var, 1, &row, &col);
+ if (row == -1)
+ break;
+ if (row == var->index) /* manifestly unbounded */
+ return 1;
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ }
+ return !isl_int_is_neg(tab->mat->row[var->index][1]);
+}
+
+/* Return a negative value if "var" can attain negative values.
+ * Return a non-negative value otherwise.
+ *
+ * If "var" is manifestly unbounded wrt negative values, we are done.
+ * Otherwise, if var is in a column, we can pivot it down to a row.
+ * Then we continue pivoting down until either
+ * - the pivot would result in a manifestly unbounded column
+ * => we don't perform the pivot, but simply return -1
+ * - no more down pivots can be performed
+ * - the sample value is negative
+ * If the sample value becomes negative and the variable is supposed
+ * to be nonnegative, then we undo the last pivot.
+ * However, if the last pivot has made the pivoting variable
+ * obviously redundant, then it may have moved to another row.
+ * In that case we look for upward pivots until we reach a non-negative
+ * value again.
+ */
+static int sign_of_min(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+ struct isl_tab_var *pivot_var = NULL;
+
+ if (min_is_manifestly_unbounded(tab, var))
+ return -1;
+ if (!var->is_row) {
+ col = var->index;
+ row = pivot_row(tab, NULL, -1, col);
+ pivot_var = var_from_col(tab, col);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ if (var->is_redundant)
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[var->index][1])) {
+ if (var->is_nonneg) {
+ if (!pivot_var->is_redundant &&
+ pivot_var->index == row) {
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ } else
+ if (restore_row(tab, var) < -1)
+ return -2;
+ }
+ return -1;
+ }
+ }
+ if (var->is_redundant)
+ return 0;
+ while (!isl_int_is_neg(tab->mat->row[var->index][1])) {
+ find_pivot(tab, var, var, -1, &row, &col);
+ if (row == var->index)
+ return -1;
+ if (row == -1)
+ return isl_int_sgn(tab->mat->row[var->index][1]);
+ pivot_var = var_from_col(tab, col);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ if (var->is_redundant)
+ return 0;
+ }
+ if (pivot_var && var->is_nonneg) {
+ /* pivot back to non-negative value */
+ if (!pivot_var->is_redundant && pivot_var->index == row) {
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -2;
+ } else
+ if (restore_row(tab, var) < -1)
+ return -2;
+ }
+ return -1;
+}
+
+static int row_at_most_neg_one(struct isl_tab *tab, int row)
+{
+ if (tab->M) {
+ if (isl_int_is_pos(tab->mat->row[row][2]))
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][2]))
+ return 1;
+ }
+ return isl_int_is_neg(tab->mat->row[row][1]) &&
+ isl_int_abs_ge(tab->mat->row[row][1],
+ tab->mat->row[row][0]);
+}
+
+/* Return 1 if "var" can attain values <= -1.
+ * Return 0 otherwise.
+ *
+ * The sample value of "var" is assumed to be non-negative when the
+ * the function is called. If 1 is returned then the constraint
+ * is not redundant and the sample value is made non-negative again before
+ * the function returns.
+ */
+int isl_tab_min_at_most_neg_one(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+ struct isl_tab_var *pivot_var;
+
+ if (min_is_manifestly_unbounded(tab, var))
+ return 1;
+ if (!var->is_row) {
+ col = var->index;
+ row = pivot_row(tab, NULL, -1, col);
+ pivot_var = var_from_col(tab, col);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ if (var->is_redundant)
+ return 0;
+ if (row_at_most_neg_one(tab, var->index)) {
+ if (var->is_nonneg) {
+ if (!pivot_var->is_redundant &&
+ pivot_var->index == row) {
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ } else
+ if (restore_row(tab, var) < -1)
+ return -1;
+ }
+ return 1;
+ }
+ }
+ if (var->is_redundant)
+ return 0;
+ do {
+ find_pivot(tab, var, var, -1, &row, &col);
+ if (row == var->index) {
+ if (restore_row(tab, var) < -1)
+ return -1;
+ return 1;
+ }
+ if (row == -1)
+ return 0;
+ pivot_var = var_from_col(tab, col);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ if (var->is_redundant)
+ return 0;
+ } while (!row_at_most_neg_one(tab, var->index));
+ if (var->is_nonneg) {
+ /* pivot back to non-negative value */
+ if (!pivot_var->is_redundant && pivot_var->index == row)
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ if (restore_row(tab, var) < -1)
+ return -1;
+ }
+ return 1;
+}
+
+/* Return 1 if "var" can attain values >= 1.
+ * Return 0 otherwise.
+ */
+static int at_least_one(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int row, col;
+ isl_int *r;
+
+ if (max_is_manifestly_unbounded(tab, var))
+ return 1;
+ if (to_row(tab, var, 1) < 0)
+ return -1;
+ r = tab->mat->row[var->index];
+ while (isl_int_lt(r[1], r[0])) {
+ find_pivot(tab, var, var, 1, &row, &col);
+ if (row == -1)
+ return isl_int_ge(r[1], r[0]);
+ if (row == var->index) /* manifestly unbounded */
+ return 1;
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ }
+ return 1;
+}
+
+static void swap_cols(struct isl_tab *tab, int col1, int col2)
+{
+ int t;
+ unsigned off = 2 + tab->M;
+ t = tab->col_var[col1];
+ tab->col_var[col1] = tab->col_var[col2];
+ tab->col_var[col2] = t;
+ var_from_col(tab, col1)->index = col1;
+ var_from_col(tab, col2)->index = col2;
+ tab->mat = isl_mat_swap_cols(tab->mat, off + col1, off + col2);
+}
+
+/* Mark column with index "col" as representing a zero variable.
+ * If we may need to undo the operation the column is kept,
+ * but no longer considered.
+ * Otherwise, the column is simply removed.
+ *
+ * The column may be interchanged with some other column. If it
+ * is interchanged with a later column, return 1. Otherwise return 0.
+ * If the columns are checked in order in the calling function,
+ * then a return value of 1 means that the column with the given
+ * column number may now contain a different column that
+ * hasn't been checked yet.
+ */
+int isl_tab_kill_col(struct isl_tab *tab, int col)
+{
+ var_from_col(tab, col)->is_zero = 1;
+ if (tab->need_undo) {
+ if (isl_tab_push_var(tab, isl_tab_undo_zero,
+ var_from_col(tab, col)) < 0)
+ return -1;
+ if (col != tab->n_dead)
+ swap_cols(tab, col, tab->n_dead);
+ tab->n_dead++;
+ return 0;
+ } else {
+ if (col != tab->n_col - 1)
+ swap_cols(tab, col, tab->n_col - 1);
+ var_from_col(tab, tab->n_col - 1)->index = -1;
+ tab->n_col--;
+ return 1;
+ }
+}
+
+static int row_is_manifestly_non_integral(struct isl_tab *tab, int row)
+{
+ unsigned off = 2 + tab->M;
+
+ if (tab->M && !isl_int_eq(tab->mat->row[row][2],
+ tab->mat->row[row][0]))
+ return 0;
+ if (isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+ tab->n_col - tab->n_dead) != -1)
+ return 0;
+
+ return !isl_int_is_divisible_by(tab->mat->row[row][1],
+ tab->mat->row[row][0]);
+}
+
+/* For integer tableaus, check if any of the coordinates are stuck
+ * at a non-integral value.
+ */
+static int tab_is_manifestly_empty(struct isl_tab *tab)
+{
+ int i;
+
+ if (tab->empty)
+ return 1;
+ if (tab->rational)
+ return 0;
+
+ for (i = 0; i < tab->n_var; ++i) {
+ if (!tab->var[i].is_row)
+ continue;
+ if (row_is_manifestly_non_integral(tab, tab->var[i].index))
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Row variable "var" is non-negative and cannot attain any values
+ * larger than zero. This means that the coefficients of the unrestricted
+ * column variables are zero and that the coefficients of the non-negative
+ * column variables are zero or negative.
+ * Each of the non-negative variables with a negative coefficient can
+ * then also be written as the negative sum of non-negative variables
+ * and must therefore also be zero.
+ */
+static int close_row(struct isl_tab *tab, struct isl_tab_var *var) WARN_UNUSED;
+static int close_row(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int j;
+ struct isl_mat *mat = tab->mat;
+ unsigned off = 2 + tab->M;
+
+ isl_assert(tab->mat->ctx, var->is_nonneg, return -1);
+ var->is_zero = 1;
+ if (tab->need_undo)
+ if (isl_tab_push_var(tab, isl_tab_undo_zero, var) < 0)
+ return -1;
+ for (j = tab->n_dead; j < tab->n_col; ++j) {
+ int recheck;
+ if (isl_int_is_zero(mat->row[var->index][off + j]))
+ continue;
+ isl_assert(tab->mat->ctx,
+ isl_int_is_neg(mat->row[var->index][off + j]), return -1);
+ recheck = isl_tab_kill_col(tab, j);
+ if (recheck < 0)
+ return -1;
+ if (recheck)
+ --j;
+ }
+ if (isl_tab_mark_redundant(tab, var->index) < 0)
+ return -1;
+ if (tab_is_manifestly_empty(tab) && isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+}
+
+/* Add a constraint to the tableau and allocate a row for it.
+ * Return the index into the constraint array "con".
+ */
+int isl_tab_allocate_con(struct isl_tab *tab)
+{
+ int r;
+
+ isl_assert(tab->mat->ctx, tab->n_row < tab->mat->n_row, return -1);
+ isl_assert(tab->mat->ctx, tab->n_con < tab->max_con, return -1);
+
+ r = tab->n_con;
+ tab->con[r].index = tab->n_row;
+ tab->con[r].is_row = 1;
+ tab->con[r].is_nonneg = 0;
+ tab->con[r].is_zero = 0;
+ tab->con[r].is_redundant = 0;
+ tab->con[r].frozen = 0;
+ tab->con[r].negated = 0;
+ tab->row_var[tab->n_row] = ~r;
+
+ tab->n_row++;
+ tab->n_con++;
+ if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->con[r]) < 0)
+ return -1;
+
+ return r;
+}
+
+/* Add a variable to the tableau and allocate a column for it.
+ * Return the index into the variable array "var".
+ */
+int isl_tab_allocate_var(struct isl_tab *tab)
+{
+ int r;
+ int i;
+ unsigned off = 2 + tab->M;
+
+ isl_assert(tab->mat->ctx, tab->n_col < tab->mat->n_col, return -1);
+ isl_assert(tab->mat->ctx, tab->n_var < tab->max_var, return -1);
+
+ r = tab->n_var;
+ tab->var[r].index = tab->n_col;
+ tab->var[r].is_row = 0;
+ tab->var[r].is_nonneg = 0;
+ tab->var[r].is_zero = 0;
+ tab->var[r].is_redundant = 0;
+ tab->var[r].frozen = 0;
+ tab->var[r].negated = 0;
+ tab->col_var[tab->n_col] = r;
+
+ for (i = 0; i < tab->n_row; ++i)
+ isl_int_set_si(tab->mat->row[i][off + tab->n_col], 0);
+
+ tab->n_var++;
+ tab->n_col++;
+ if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->var[r]) < 0)
+ return -1;
+
+ return r;
+}
+
+/* Add a row to the tableau. The row is given as an affine combination
+ * of the original variables and needs to be expressed in terms of the
+ * column variables.
+ *
+ * We add each term in turn.
+ * If r = n/d_r is the current sum and we need to add k x, then
+ * if x is a column variable, we increase the numerator of
+ * this column by k d_r
+ * if x = f/d_x is a row variable, then the new representation of r is
+ *
+ * n k f d_x/g n + d_r/g k f m/d_r n + m/d_g k f
+ * --- + --- = ------------------- = -------------------
+ * d_r d_r d_r d_x/g m
+ *
+ * with g the gcd of d_r and d_x and m the lcm of d_r and d_x.
+ *
+ * If tab->M is set, then, internally, each variable x is represented
+ * as x' - M. We then also need no subtract k d_r from the coefficient of M.
+ */
+int isl_tab_add_row(struct isl_tab *tab, isl_int *line)
+{
+ int i;
+ int r;
+ isl_int *row;
+ isl_int a, b;
+ unsigned off = 2 + tab->M;
+
+ r = isl_tab_allocate_con(tab);
+ if (r < 0)
+ return -1;
+
+ isl_int_init(a);
+ isl_int_init(b);
+ row = tab->mat->row[tab->con[r].index];
+ isl_int_set_si(row[0], 1);
+ isl_int_set(row[1], line[0]);
+ isl_seq_clr(row + 2, tab->M + tab->n_col);
+ for (i = 0; i < tab->n_var; ++i) {
+ if (tab->var[i].is_zero)
+ continue;
+ if (tab->var[i].is_row) {
+ isl_int_lcm(a,
+ row[0], tab->mat->row[tab->var[i].index][0]);
+ isl_int_swap(a, row[0]);
+ isl_int_divexact(a, row[0], a);
+ isl_int_divexact(b,
+ row[0], tab->mat->row[tab->var[i].index][0]);
+ isl_int_mul(b, b, line[1 + i]);
+ isl_seq_combine(row + 1, a, row + 1,
+ b, tab->mat->row[tab->var[i].index] + 1,
+ 1 + tab->M + tab->n_col);
+ } else
+ isl_int_addmul(row[off + tab->var[i].index],
+ line[1 + i], row[0]);
+ if (tab->M && i >= tab->n_param && i < tab->n_var - tab->n_div)
+ isl_int_submul(row[2], line[1 + i], row[0]);
+ }
+ isl_seq_normalize(tab->mat->ctx, row, off + tab->n_col);
+ isl_int_clear(a);
+ isl_int_clear(b);
+
+ if (tab->row_sign)
+ tab->row_sign[tab->con[r].index] = isl_tab_row_unknown;
+
+ return r;
+}
+
+static int drop_row(struct isl_tab *tab, int row)
+{
+ isl_assert(tab->mat->ctx, ~tab->row_var[row] == tab->n_con - 1, return -1);
+ if (row != tab->n_row - 1)
+ swap_rows(tab, row, tab->n_row - 1);
+ tab->n_row--;
+ tab->n_con--;
+ return 0;
+}
+
+static int drop_col(struct isl_tab *tab, int col)
+{
+ isl_assert(tab->mat->ctx, tab->col_var[col] == tab->n_var - 1, return -1);
+ if (col != tab->n_col - 1)
+ swap_cols(tab, col, tab->n_col - 1);
+ tab->n_col--;
+ tab->n_var--;
+ return 0;
+}
+
+/* Add inequality "ineq" and check if it conflicts with the
+ * previously added constraints or if it is obviously redundant.
+ */
+int isl_tab_add_ineq(struct isl_tab *tab, isl_int *ineq)
+{
+ int r;
+ int sgn;
+ isl_int cst;
+
+ if (!tab)
+ return -1;
+ if (tab->bmap) {
+ struct isl_basic_map *bmap = tab->bmap;
+
+ isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq, return -1);
+ isl_assert(tab->mat->ctx,
+ tab->n_con == bmap->n_eq + bmap->n_ineq, return -1);
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ return -1;
+ if (!tab->bmap)
+ return -1;
+ }
+ if (tab->cone) {
+ isl_int_init(cst);
+ isl_int_swap(ineq[0], cst);
+ }
+ r = isl_tab_add_row(tab, ineq);
+ if (tab->cone) {
+ isl_int_swap(ineq[0], cst);
+ isl_int_clear(cst);
+ }
+ if (r < 0)
+ return -1;
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ return -1;
+ if (isl_tab_row_is_redundant(tab, tab->con[r].index)) {
+ if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+ return -1;
+ return 0;
+ }
+
+ sgn = restore_row(tab, &tab->con[r]);
+ if (sgn < -1)
+ return -1;
+ if (sgn < 0)
+ return isl_tab_mark_empty(tab);
+ if (tab->con[r].is_row && isl_tab_row_is_redundant(tab, tab->con[r].index))
+ if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+ return -1;
+ return 0;
+}
+
+/* Pivot a non-negative variable down until it reaches the value zero
+ * and then pivot the variable into a column position.
+ */
+static int to_col(struct isl_tab *tab, struct isl_tab_var *var) WARN_UNUSED;
+static int to_col(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ int i;
+ int row, col;
+ unsigned off = 2 + tab->M;
+
+ if (!var->is_row)
+ return 0;
+
+ while (isl_int_is_pos(tab->mat->row[var->index][1])) {
+ find_pivot(tab, var, NULL, -1, &row, &col);
+ isl_assert(tab->mat->ctx, row != -1, return -1);
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ if (!var->is_row)
+ return 0;
+ }
+
+ for (i = tab->n_dead; i < tab->n_col; ++i)
+ if (!isl_int_is_zero(tab->mat->row[var->index][off + i]))
+ break;
+
+ isl_assert(tab->mat->ctx, i < tab->n_col, return -1);
+ if (isl_tab_pivot(tab, var->index, i) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* We assume Gaussian elimination has been performed on the equalities.
+ * The equalities can therefore never conflict.
+ * Adding the equalities is currently only really useful for a later call
+ * to isl_tab_ineq_type.
+ */
+static struct isl_tab *add_eq(struct isl_tab *tab, isl_int *eq)
+{
+ int i;
+ int r;
+
+ if (!tab)
+ return NULL;
+ r = isl_tab_add_row(tab, eq);
+ if (r < 0)
+ goto error;
+
+ r = tab->con[r].index;
+ i = isl_seq_first_non_zero(tab->mat->row[r] + 2 + tab->M + tab->n_dead,
+ tab->n_col - tab->n_dead);
+ isl_assert(tab->mat->ctx, i >= 0, goto error);
+ i += tab->n_dead;
+ if (isl_tab_pivot(tab, r, i) < 0)
+ goto error;
+ if (isl_tab_kill_col(tab, i) < 0)
+ goto error;
+ tab->n_eq++;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+static int row_is_manifestly_zero(struct isl_tab *tab, int row)
+{
+ unsigned off = 2 + tab->M;
+
+ if (!isl_int_is_zero(tab->mat->row[row][1]))
+ return 0;
+ if (tab->M && !isl_int_is_zero(tab->mat->row[row][2]))
+ return 0;
+ return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+ tab->n_col - tab->n_dead) == -1;
+}
+
+/* Add an equality that is known to be valid for the given tableau.
+ */
+int isl_tab_add_valid_eq(struct isl_tab *tab, isl_int *eq)
+{
+ struct isl_tab_var *var;
+ int r;
+
+ if (!tab)
+ return -1;
+ r = isl_tab_add_row(tab, eq);
+ if (r < 0)
+ return -1;
+
+ var = &tab->con[r];
+ r = var->index;
+ if (row_is_manifestly_zero(tab, r)) {
+ var->is_zero = 1;
+ if (isl_tab_mark_redundant(tab, r) < 0)
+ return -1;
+ return 0;
+ }
+
+ if (isl_int_is_neg(tab->mat->row[r][1])) {
+ isl_seq_neg(tab->mat->row[r] + 1, tab->mat->row[r] + 1,
+ 1 + tab->n_col);
+ var->negated = 1;
+ }
+ var->is_nonneg = 1;
+ if (to_col(tab, var) < 0)
+ return -1;
+ var->is_nonneg = 0;
+ if (isl_tab_kill_col(tab, var->index) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int add_zero_row(struct isl_tab *tab)
+{
+ int r;
+ isl_int *row;
+
+ r = isl_tab_allocate_con(tab);
+ if (r < 0)
+ return -1;
+
+ row = tab->mat->row[tab->con[r].index];
+ isl_seq_clr(row + 1, 1 + tab->M + tab->n_col);
+ isl_int_set_si(row[0], 1);
+
+ return r;
+}
+
+/* Add equality "eq" and check if it conflicts with the
+ * previously added constraints or if it is obviously redundant.
+ */
+int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq)
+{
+ struct isl_tab_undo *snap = NULL;
+ struct isl_tab_var *var;
+ int r;
+ int row;
+ int sgn;
+ isl_int cst;
+
+ if (!tab)
+ return -1;
+ isl_assert(tab->mat->ctx, !tab->M, return -1);
+
+ if (tab->need_undo)
+ snap = isl_tab_snap(tab);
+
+ if (tab->cone) {
+ isl_int_init(cst);
+ isl_int_swap(eq[0], cst);
+ }
+ r = isl_tab_add_row(tab, eq);
+ if (tab->cone) {
+ isl_int_swap(eq[0], cst);
+ isl_int_clear(cst);
+ }
+ if (r < 0)
+ return -1;
+
+ var = &tab->con[r];
+ row = var->index;
+ if (row_is_manifestly_zero(tab, row)) {
+ if (snap) {
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ } else
+ drop_row(tab, row);
+ return 0;
+ }
+
+ if (tab->bmap) {
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ return -1;
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ return -1;
+ if (!tab->bmap)
+ return -1;
+ if (add_zero_row(tab) < 0)
+ return -1;
+ }
+
+ sgn = isl_int_sgn(tab->mat->row[row][1]);
+
+ if (sgn > 0) {
+ isl_seq_neg(tab->mat->row[row] + 1, tab->mat->row[row] + 1,
+ 1 + tab->n_col);
+ var->negated = 1;
+ sgn = -1;
+ }
+
+ if (sgn < 0) {
+ sgn = sign_of_max(tab, var);
+ if (sgn < -1)
+ return -1;
+ if (sgn < 0) {
+ if (isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+ }
+ }
+
+ var->is_nonneg = 1;
+ if (to_col(tab, var) < 0)
+ return -1;
+ var->is_nonneg = 0;
+ if (isl_tab_kill_col(tab, var->index) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Construct and return an inequality that expresses an upper bound
+ * on the given div.
+ * In particular, if the div is given by
+ *
+ * d = floor(e/m)
+ *
+ * then the inequality expresses
+ *
+ * m d <= e
+ */
+static struct isl_vec *ineq_for_div(struct isl_basic_map *bmap, unsigned div)
+{
+ unsigned total;
+ unsigned div_pos;
+ struct isl_vec *ineq;
+
+ if (!bmap)
+ return NULL;
+
+ total = isl_basic_map_total_dim(bmap);
+ div_pos = 1 + total - bmap->n_div + div;
+
+ ineq = isl_vec_alloc(bmap->ctx, 1 + total);
+ if (!ineq)
+ return NULL;
+
+ isl_seq_cpy(ineq->el, bmap->div[div] + 1, 1 + total);
+ isl_int_neg(ineq->el[div_pos], bmap->div[div][0]);
+ return ineq;
+}
+
+/* For a div d = floor(f/m), add the constraints
+ *
+ * f - m d >= 0
+ * -(f-(m-1)) + m d >= 0
+ *
+ * Note that the second constraint is the negation of
+ *
+ * f - m d >= m
+ *
+ * If add_ineq is not NULL, then this function is used
+ * instead of isl_tab_add_ineq to effectively add the inequalities.
+ */
+static int add_div_constraints(struct isl_tab *tab, unsigned div,
+ int (*add_ineq)(void *user, isl_int *), void *user)
+{
+ unsigned total;
+ unsigned div_pos;
+ struct isl_vec *ineq;
+
+ total = isl_basic_map_total_dim(tab->bmap);
+ div_pos = 1 + total - tab->bmap->n_div + div;
+
+ ineq = ineq_for_div(tab->bmap, div);
+ if (!ineq)
+ goto error;
+
+ if (add_ineq) {
+ if (add_ineq(user, ineq->el) < 0)
+ goto error;
+ } else {
+ if (isl_tab_add_ineq(tab, ineq->el) < 0)
+ goto error;
+ }
+
+ isl_seq_neg(ineq->el, tab->bmap->div[div] + 1, 1 + total);
+ isl_int_set(ineq->el[div_pos], tab->bmap->div[div][0]);
+ isl_int_add(ineq->el[0], ineq->el[0], ineq->el[div_pos]);
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+ if (add_ineq) {
+ if (add_ineq(user, ineq->el) < 0)
+ goto error;
+ } else {
+ if (isl_tab_add_ineq(tab, ineq->el) < 0)
+ goto error;
+ }
+
+ isl_vec_free(ineq);
+
+ return 0;
+error:
+ isl_vec_free(ineq);
+ return -1;
+}
+
+/* Check whether the div described by "div" is obviously non-negative.
+ * If we are using a big parameter, then we will encode the div
+ * as div' = M + div, which is always non-negative.
+ * Otherwise, we check whether div is a non-negative affine combination
+ * of non-negative variables.
+ */
+static int div_is_nonneg(struct isl_tab *tab, __isl_keep isl_vec *div)
+{
+ int i;
+
+ if (tab->M)
+ return 1;
+
+ if (isl_int_is_neg(div->el[1]))
+ return 0;
+
+ for (i = 0; i < tab->n_var; ++i) {
+ if (isl_int_is_neg(div->el[2 + i]))
+ return 0;
+ if (isl_int_is_zero(div->el[2 + i]))
+ continue;
+ if (!tab->var[i].is_nonneg)
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Add an extra div, prescribed by "div" to the tableau and
+ * the associated bmap (which is assumed to be non-NULL).
+ *
+ * If add_ineq is not NULL, then this function is used instead
+ * of isl_tab_add_ineq to add the div constraints.
+ * This complication is needed because the code in isl_tab_pip
+ * wants to perform some extra processing when an inequality
+ * is added to the tableau.
+ */
+int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
+ int (*add_ineq)(void *user, isl_int *), void *user)
+{
+ int r;
+ int k;
+ int nonneg;
+
+ if (!tab || !div)
+ return -1;
+
+ isl_assert(tab->mat->ctx, tab->bmap, return -1);
+
+ nonneg = div_is_nonneg(tab, div);
+
+ if (isl_tab_extend_cons(tab, 3) < 0)
+ return -1;
+ if (isl_tab_extend_vars(tab, 1) < 0)
+ return -1;
+ r = isl_tab_allocate_var(tab);
+ if (r < 0)
+ return -1;
+
+ if (nonneg)
+ tab->var[r].is_nonneg = 1;
+
+ tab->bmap = isl_basic_map_extend_space(tab->bmap,
+ isl_basic_map_get_space(tab->bmap), 1, 0, 2);
+ k = isl_basic_map_alloc_div(tab->bmap);
+ if (k < 0)
+ return -1;
+ isl_seq_cpy(tab->bmap->div[k], div->el, div->size);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_div) < 0)
+ return -1;
+
+ if (add_div_constraints(tab, k, add_ineq, user) < 0)
+ return -1;
+
+ return r;
+}
+
+/* If "track" is set, then we want to keep track of all constraints in tab
+ * in its bmap field. This field is initialized from a copy of "bmap",
+ * so we need to make sure that all constraints in "bmap" also appear
+ * in the constructed tab.
+ */
+__isl_give struct isl_tab *isl_tab_from_basic_map(
+ __isl_keep isl_basic_map *bmap, int track)
+{
+ int i;
+ struct isl_tab *tab;
+
+ if (!bmap)
+ return NULL;
+ tab = isl_tab_alloc(bmap->ctx,
+ isl_basic_map_total_dim(bmap) + bmap->n_ineq + 1,
+ isl_basic_map_total_dim(bmap), 0);
+ if (!tab)
+ return NULL;
+ tab->preserve = track;
+ tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) {
+ if (isl_tab_mark_empty(tab) < 0)
+ goto error;
+ goto done;
+ }
+ for (i = 0; i < bmap->n_eq; ++i) {
+ tab = add_eq(tab, bmap->eq[i]);
+ if (!tab)
+ return tab;
+ }
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (isl_tab_add_ineq(tab, bmap->ineq[i]) < 0)
+ goto error;
+ if (tab->empty)
+ goto done;
+ }
+done:
+ if (track && isl_tab_track_bmap(tab, isl_basic_map_copy(bmap)) < 0)
+ goto error;
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+__isl_give struct isl_tab *isl_tab_from_basic_set(
+ __isl_keep isl_basic_set *bset, int track)
+{
+ return isl_tab_from_basic_map(bset, track);
+}
+
+/* Construct a tableau corresponding to the recession cone of "bset".
+ */
+struct isl_tab *isl_tab_from_recession_cone(__isl_keep isl_basic_set *bset,
+ int parametric)
+{
+ isl_int cst;
+ int i;
+ struct isl_tab *tab;
+ unsigned offset = 0;
+
+ if (!bset)
+ return NULL;
+ if (parametric)
+ offset = isl_basic_set_dim(bset, isl_dim_param);
+ tab = isl_tab_alloc(bset->ctx, bset->n_eq + bset->n_ineq,
+ isl_basic_set_total_dim(bset) - offset, 0);
+ if (!tab)
+ return NULL;
+ tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
+ tab->cone = 1;
+
+ isl_int_init(cst);
+ for (i = 0; i < bset->n_eq; ++i) {
+ isl_int_swap(bset->eq[i][offset], cst);
+ if (offset > 0) {
+ if (isl_tab_add_eq(tab, bset->eq[i] + offset) < 0)
+ goto error;
+ } else
+ tab = add_eq(tab, bset->eq[i]);
+ isl_int_swap(bset->eq[i][offset], cst);
+ if (!tab)
+ goto done;
+ }
+ for (i = 0; i < bset->n_ineq; ++i) {
+ int r;
+ isl_int_swap(bset->ineq[i][offset], cst);
+ r = isl_tab_add_row(tab, bset->ineq[i] + offset);
+ isl_int_swap(bset->ineq[i][offset], cst);
+ if (r < 0)
+ goto error;
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ goto error;
+ }
+done:
+ isl_int_clear(cst);
+ return tab;
+error:
+ isl_int_clear(cst);
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Assuming "tab" is the tableau of a cone, check if the cone is
+ * bounded, i.e., if it is empty or only contains the origin.
+ */
+int isl_tab_cone_is_bounded(struct isl_tab *tab)
+{
+ int i;
+
+ if (!tab)
+ return -1;
+ if (tab->empty)
+ return 1;
+ if (tab->n_dead == tab->n_col)
+ return 1;
+
+ for (;;) {
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ struct isl_tab_var *var;
+ int sgn;
+ var = isl_tab_var_from_row(tab, i);
+ if (!var->is_nonneg)
+ continue;
+ sgn = sign_of_max(tab, var);
+ if (sgn < -1)
+ return -1;
+ if (sgn != 0)
+ return 0;
+ if (close_row(tab, var) < 0)
+ return -1;
+ break;
+ }
+ if (tab->n_dead == tab->n_col)
+ return 1;
+ if (i == tab->n_row)
+ return 0;
+ }
+}
+
+int isl_tab_sample_is_integer(struct isl_tab *tab)
+{
+ int i;
+
+ if (!tab)
+ return -1;
+
+ for (i = 0; i < tab->n_var; ++i) {
+ int row;
+ if (!tab->var[i].is_row)
+ continue;
+ row = tab->var[i].index;
+ if (!isl_int_is_divisible_by(tab->mat->row[row][1],
+ tab->mat->row[row][0]))
+ return 0;
+ }
+ return 1;
+}
+
+static struct isl_vec *extract_integer_sample(struct isl_tab *tab)
+{
+ int i;
+ struct isl_vec *vec;
+
+ vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+ if (!vec)
+ return NULL;
+
+ isl_int_set_si(vec->block.data[0], 1);
+ for (i = 0; i < tab->n_var; ++i) {
+ if (!tab->var[i].is_row)
+ isl_int_set_si(vec->block.data[1 + i], 0);
+ else {
+ int row = tab->var[i].index;
+ isl_int_divexact(vec->block.data[1 + i],
+ tab->mat->row[row][1], tab->mat->row[row][0]);
+ }
+ }
+
+ return vec;
+}
+
+struct isl_vec *isl_tab_get_sample_value(struct isl_tab *tab)
+{
+ int i;
+ struct isl_vec *vec;
+ isl_int m;
+
+ if (!tab)
+ return NULL;
+
+ vec = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+ if (!vec)
+ return NULL;
+
+ isl_int_init(m);
+
+ isl_int_set_si(vec->block.data[0], 1);
+ for (i = 0; i < tab->n_var; ++i) {
+ int row;
+ if (!tab->var[i].is_row) {
+ isl_int_set_si(vec->block.data[1 + i], 0);
+ continue;
+ }
+ row = tab->var[i].index;
+ isl_int_gcd(m, vec->block.data[0], tab->mat->row[row][0]);
+ isl_int_divexact(m, tab->mat->row[row][0], m);
+ isl_seq_scale(vec->block.data, vec->block.data, m, 1 + i);
+ isl_int_divexact(m, vec->block.data[0], tab->mat->row[row][0]);
+ isl_int_mul(vec->block.data[1 + i], m, tab->mat->row[row][1]);
+ }
+ vec = isl_vec_normalize(vec);
+
+ isl_int_clear(m);
+ return vec;
+}
+
+/* Update "bmap" based on the results of the tableau "tab".
+ * In particular, implicit equalities are made explicit, redundant constraints
+ * are removed and if the sample value happens to be integer, it is stored
+ * in "bmap" (unless "bmap" already had an integer sample).
+ *
+ * The tableau is assumed to have been created from "bmap" using
+ * isl_tab_from_basic_map.
+ */
+struct isl_basic_map *isl_basic_map_update_from_tab(struct isl_basic_map *bmap,
+ struct isl_tab *tab)
+{
+ int i;
+ unsigned n_eq;
+
+ if (!bmap)
+ return NULL;
+ if (!tab)
+ return bmap;
+
+ n_eq = tab->n_eq;
+ if (tab->empty)
+ bmap = isl_basic_map_set_to_empty(bmap);
+ else
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ if (isl_tab_is_equality(tab, n_eq + i))
+ isl_basic_map_inequality_to_equality(bmap, i);
+ else if (isl_tab_is_redundant(tab, n_eq + i))
+ isl_basic_map_drop_inequality(bmap, i);
+ }
+ if (bmap->n_eq != n_eq)
+ isl_basic_map_gauss(bmap, NULL);
+ if (!tab->rational &&
+ !bmap->sample && isl_tab_sample_is_integer(tab))
+ bmap->sample = extract_integer_sample(tab);
+ return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_update_from_tab(struct isl_basic_set *bset,
+ struct isl_tab *tab)
+{
+ return (struct isl_basic_set *)isl_basic_map_update_from_tab(
+ (struct isl_basic_map *)bset, tab);
+}
+
+/* Given a non-negative variable "var", add a new non-negative variable
+ * that is the opposite of "var", ensuring that var can only attain the
+ * value zero.
+ * If var = n/d is a row variable, then the new variable = -n/d.
+ * If var is a column variables, then the new variable = -var.
+ * If the new variable cannot attain non-negative values, then
+ * the resulting tableau is empty.
+ * Otherwise, we know the value will be zero and we close the row.
+ */
+static int cut_to_hyperplane(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ unsigned r;
+ isl_int *row;
+ int sgn;
+ unsigned off = 2 + tab->M;
+
+ if (var->is_zero)
+ return 0;
+ isl_assert(tab->mat->ctx, !var->is_redundant, return -1);
+ isl_assert(tab->mat->ctx, var->is_nonneg, return -1);
+
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ return -1;
+
+ r = tab->n_con;
+ tab->con[r].index = tab->n_row;
+ tab->con[r].is_row = 1;
+ tab->con[r].is_nonneg = 0;
+ tab->con[r].is_zero = 0;
+ tab->con[r].is_redundant = 0;
+ tab->con[r].frozen = 0;
+ tab->con[r].negated = 0;
+ tab->row_var[tab->n_row] = ~r;
+ row = tab->mat->row[tab->n_row];
+
+ if (var->is_row) {
+ isl_int_set(row[0], tab->mat->row[var->index][0]);
+ isl_seq_neg(row + 1,
+ tab->mat->row[var->index] + 1, 1 + tab->n_col);
+ } else {
+ isl_int_set_si(row[0], 1);
+ isl_seq_clr(row + 1, 1 + tab->n_col);
+ isl_int_set_si(row[off + var->index], -1);
+ }
+
+ tab->n_row++;
+ tab->n_con++;
+ if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->con[r]) < 0)
+ return -1;
+
+ sgn = sign_of_max(tab, &tab->con[r]);
+ if (sgn < -1)
+ return -1;
+ if (sgn < 0) {
+ if (isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+ }
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ return -1;
+ /* sgn == 0 */
+ if (close_row(tab, &tab->con[r]) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Given a tableau "tab" and an inequality constraint "con" of the tableau,
+ * relax the inequality by one. That is, the inequality r >= 0 is replaced
+ * by r' = r + 1 >= 0.
+ * If r is a row variable, we simply increase the constant term by one
+ * (taking into account the denominator).
+ * If r is a column variable, then we need to modify each row that
+ * refers to r = r' - 1 by substituting this equality, effectively
+ * subtracting the coefficient of the column from the constant.
+ * We should only do this if the minimum is manifestly unbounded,
+ * however. Otherwise, we may end up with negative sample values
+ * for non-negative variables.
+ * So, if r is a column variable with a minimum that is not
+ * manifestly unbounded, then we need to move it to a row.
+ * However, the sample value of this row may be negative,
+ * even after the relaxation, so we need to restore it.
+ * We therefore prefer to pivot a column up to a row, if possible.
+ */
+struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con)
+{
+ struct isl_tab_var *var;
+ unsigned off = 2 + tab->M;
+
+ if (!tab)
+ return NULL;
+
+ var = &tab->con[con];
+
+ if (var->is_row && (var->index < 0 || var->index < tab->n_redundant))
+ isl_die(tab->mat->ctx, isl_error_invalid,
+ "cannot relax redundant constraint", goto error);
+ if (!var->is_row && (var->index < 0 || var->index < tab->n_dead))
+ isl_die(tab->mat->ctx, isl_error_invalid,
+ "cannot relax dead constraint", goto error);
+
+ if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
+ if (to_row(tab, var, 1) < 0)
+ goto error;
+ if (!var->is_row && !min_is_manifestly_unbounded(tab, var))
+ if (to_row(tab, var, -1) < 0)
+ goto error;
+
+ if (var->is_row) {
+ isl_int_add(tab->mat->row[var->index][1],
+ tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
+ if (restore_row(tab, var) < 0)
+ goto error;
+ } else {
+ int i;
+
+ for (i = 0; i < tab->n_row; ++i) {
+ if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
+ continue;
+ isl_int_sub(tab->mat->row[i][1], tab->mat->row[i][1],
+ tab->mat->row[i][off + var->index]);
+ }
+
+ }
+
+ if (isl_tab_push_var(tab, isl_tab_undo_relax, var) < 0)
+ goto error;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Remove the sign constraint from constraint "con".
+ *
+ * If the constraint variable was originally marked non-negative,
+ * then we make sure we mark it non-negative again during rollback.
+ */
+int isl_tab_unrestrict(struct isl_tab *tab, int con)
+{
+ struct isl_tab_var *var;
+
+ if (!tab)
+ return -1;
+
+ var = &tab->con[con];
+ if (!var->is_nonneg)
+ return 0;
+
+ var->is_nonneg = 0;
+ if (isl_tab_push_var(tab, isl_tab_undo_unrestrict, var) < 0)
+ return -1;
+
+ return 0;
+}
+
+int isl_tab_select_facet(struct isl_tab *tab, int con)
+{
+ if (!tab)
+ return -1;
+
+ return cut_to_hyperplane(tab, &tab->con[con]);
+}
+
+static int may_be_equality(struct isl_tab *tab, int row)
+{
+ return tab->rational ? isl_int_is_zero(tab->mat->row[row][1])
+ : isl_int_lt(tab->mat->row[row][1],
+ tab->mat->row[row][0]);
+}
+
+/* Check for (near) equalities among the constraints.
+ * A constraint is an equality if it is non-negative and if
+ * its maximal value is either
+ * - zero (in case of rational tableaus), or
+ * - strictly less than 1 (in case of integer tableaus)
+ *
+ * We first mark all non-redundant and non-dead variables that
+ * are not frozen and not obviously not an equality.
+ * Then we iterate over all marked variables if they can attain
+ * any values larger than zero or at least one.
+ * If the maximal value is zero, we mark any column variables
+ * that appear in the row as being zero and mark the row as being redundant.
+ * Otherwise, if the maximal value is strictly less than one (and the
+ * tableau is integer), then we restrict the value to being zero
+ * by adding an opposite non-negative variable.
+ */
+int isl_tab_detect_implicit_equalities(struct isl_tab *tab)
+{
+ int i;
+ unsigned n_marked;
+
+ if (!tab)
+ return -1;
+ if (tab->empty)
+ return 0;
+ if (tab->n_dead == tab->n_col)
+ return 0;
+
+ n_marked = 0;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
+ var->marked = !var->frozen && var->is_nonneg &&
+ may_be_equality(tab, i);
+ if (var->marked)
+ n_marked++;
+ }
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ struct isl_tab_var *var = var_from_col(tab, i);
+ var->marked = !var->frozen && var->is_nonneg;
+ if (var->marked)
+ n_marked++;
+ }
+ while (n_marked) {
+ struct isl_tab_var *var;
+ int sgn;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ var = isl_tab_var_from_row(tab, i);
+ if (var->marked)
+ break;
+ }
+ if (i == tab->n_row) {
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ var = var_from_col(tab, i);
+ if (var->marked)
+ break;
+ }
+ if (i == tab->n_col)
+ break;
+ }
+ var->marked = 0;
+ n_marked--;
+ sgn = sign_of_max(tab, var);
+ if (sgn < 0)
+ return -1;
+ if (sgn == 0) {
+ if (close_row(tab, var) < 0)
+ return -1;
+ } else if (!tab->rational && !at_least_one(tab, var)) {
+ if (cut_to_hyperplane(tab, var) < 0)
+ return -1;
+ return isl_tab_detect_implicit_equalities(tab);
+ }
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ var = isl_tab_var_from_row(tab, i);
+ if (!var->marked)
+ continue;
+ if (may_be_equality(tab, i))
+ continue;
+ var->marked = 0;
+ n_marked--;
+ }
+ }
+
+ return 0;
+}
+
+/* Update the element of row_var or col_var that corresponds to
+ * constraint tab->con[i] to a move from position "old" to position "i".
+ */
+static int update_con_after_move(struct isl_tab *tab, int i, int old)
+{
+ int *p;
+ int index;
+
+ index = tab->con[i].index;
+ if (index == -1)
+ return 0;
+ p = tab->con[i].is_row ? tab->row_var : tab->col_var;
+ if (p[index] != ~old)
+ isl_die(tab->mat->ctx, isl_error_internal,
+ "broken internal state", return -1);
+ p[index] = ~i;
+
+ return 0;
+}
+
+/* Rotate the "n" constraints starting at "first" to the right,
+ * putting the last constraint in the position of the first constraint.
+ */
+static int rotate_constraints(struct isl_tab *tab, int first, int n)
+{
+ int i, last;
+ struct isl_tab_var var;
+
+ if (n <= 1)
+ return 0;
+
+ last = first + n - 1;
+ var = tab->con[last];
+ for (i = last; i > first; --i) {
+ tab->con[i] = tab->con[i - 1];
+ if (update_con_after_move(tab, i, i - 1) < 0)
+ return -1;
+ }
+ tab->con[first] = var;
+ if (update_con_after_move(tab, first, last) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Make the equalities that are implicit in "bmap" but that have been
+ * detected in the corresponding "tab" explicit in "bmap" and update
+ * "tab" to reflect the new order of the constraints.
+ *
+ * In particular, if inequality i is an implicit equality then
+ * isl_basic_map_inequality_to_equality will move the inequality
+ * in front of the other equality and it will move the last inequality
+ * in the position of inequality i.
+ * In the tableau, the inequalities of "bmap" are stored after the equalities
+ * and so the original order
+ *
+ * E E E E E A A A I B B B B L
+ *
+ * is changed into
+ *
+ * I E E E E E A A A L B B B B
+ *
+ * where I is the implicit equality, the E are equalities,
+ * the A inequalities before I, the B inequalities after I and
+ * L the last inequality.
+ * We therefore need to rotate to the right two sets of constraints,
+ * those up to and including I and those after I.
+ *
+ * If "tab" contains any constraints that are not in "bmap" then they
+ * appear after those in "bmap" and they should be left untouched.
+ *
+ * Note that this function leaves "bmap" in a temporary state
+ * as it does not call isl_basic_map_gauss. Calling this function
+ * is the responsibility of the caller.
+ */
+__isl_give isl_basic_map *isl_tab_make_equalities_explicit(struct isl_tab *tab,
+ __isl_take isl_basic_map *bmap)
+{
+ int i;
+
+ if (!tab || !bmap)
+ return isl_basic_map_free(bmap);
+ if (tab->empty)
+ return bmap;
+
+ for (i = bmap->n_ineq - 1; i >= 0; --i) {
+ if (!isl_tab_is_equality(tab, bmap->n_eq + i))
+ continue;
+ isl_basic_map_inequality_to_equality(bmap, i);
+ if (rotate_constraints(tab, 0, tab->n_eq + i + 1) < 0)
+ return isl_basic_map_free(bmap);
+ if (rotate_constraints(tab, tab->n_eq + i + 1,
+ bmap->n_ineq - i) < 0)
+ return isl_basic_map_free(bmap);
+ tab->n_eq++;
+ }
+
+ return bmap;
+}
+
+static int con_is_redundant(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ if (!tab)
+ return -1;
+ if (tab->rational) {
+ int sgn = sign_of_min(tab, var);
+ if (sgn < -1)
+ return -1;
+ return sgn >= 0;
+ } else {
+ int irred = isl_tab_min_at_most_neg_one(tab, var);
+ if (irred < 0)
+ return -1;
+ return !irred;
+ }
+}
+
+/* Check for (near) redundant constraints.
+ * A constraint is redundant if it is non-negative and if
+ * its minimal value (temporarily ignoring the non-negativity) is either
+ * - zero (in case of rational tableaus), or
+ * - strictly larger than -1 (in case of integer tableaus)
+ *
+ * We first mark all non-redundant and non-dead variables that
+ * are not frozen and not obviously negatively unbounded.
+ * Then we iterate over all marked variables if they can attain
+ * any values smaller than zero or at most negative one.
+ * If not, we mark the row as being redundant (assuming it hasn't
+ * been detected as being obviously redundant in the mean time).
+ */
+int isl_tab_detect_redundant(struct isl_tab *tab)
+{
+ int i;
+ unsigned n_marked;
+
+ if (!tab)
+ return -1;
+ if (tab->empty)
+ return 0;
+ if (tab->n_redundant == tab->n_row)
+ return 0;
+
+ n_marked = 0;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ struct isl_tab_var *var = isl_tab_var_from_row(tab, i);
+ var->marked = !var->frozen && var->is_nonneg;
+ if (var->marked)
+ n_marked++;
+ }
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ struct isl_tab_var *var = var_from_col(tab, i);
+ var->marked = !var->frozen && var->is_nonneg &&
+ !min_is_manifestly_unbounded(tab, var);
+ if (var->marked)
+ n_marked++;
+ }
+ while (n_marked) {
+ struct isl_tab_var *var;
+ int red;
+ for (i = tab->n_redundant; i < tab->n_row; ++i) {
+ var = isl_tab_var_from_row(tab, i);
+ if (var->marked)
+ break;
+ }
+ if (i == tab->n_row) {
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ var = var_from_col(tab, i);
+ if (var->marked)
+ break;
+ }
+ if (i == tab->n_col)
+ break;
+ }
+ var->marked = 0;
+ n_marked--;
+ red = con_is_redundant(tab, var);
+ if (red < 0)
+ return -1;
+ if (red && !var->is_redundant)
+ if (isl_tab_mark_redundant(tab, var->index) < 0)
+ return -1;
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ var = var_from_col(tab, i);
+ if (!var->marked)
+ continue;
+ if (!min_is_manifestly_unbounded(tab, var))
+ continue;
+ var->marked = 0;
+ n_marked--;
+ }
+ }
+
+ return 0;
+}
+
+int isl_tab_is_equality(struct isl_tab *tab, int con)
+{
+ int row;
+ unsigned off;
+
+ if (!tab)
+ return -1;
+ if (tab->con[con].is_zero)
+ return 1;
+ if (tab->con[con].is_redundant)
+ return 0;
+ if (!tab->con[con].is_row)
+ return tab->con[con].index < tab->n_dead;
+
+ row = tab->con[con].index;
+
+ off = 2 + tab->M;
+ return isl_int_is_zero(tab->mat->row[row][1]) &&
+ (!tab->M || isl_int_is_zero(tab->mat->row[row][2])) &&
+ isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+ tab->n_col - tab->n_dead) == -1;
+}
+
+/* Return the minimal value of the affine expression "f" with denominator
+ * "denom" in *opt, *opt_denom, assuming the tableau is not empty and
+ * the expression cannot attain arbitrarily small values.
+ * If opt_denom is NULL, then *opt is rounded up to the nearest integer.
+ * The return value reflects the nature of the result (empty, unbounded,
+ * minimal value returned in *opt).
+ */
+enum isl_lp_result isl_tab_min(struct isl_tab *tab,
+ isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ unsigned flags)
+{
+ int r;
+ enum isl_lp_result res = isl_lp_ok;
+ struct isl_tab_var *var;
+ struct isl_tab_undo *snap;
+
+ if (!tab)
+ return isl_lp_error;
+
+ if (tab->empty)
+ return isl_lp_empty;
+
+ snap = isl_tab_snap(tab);
+ r = isl_tab_add_row(tab, f);
+ if (r < 0)
+ return isl_lp_error;
+ var = &tab->con[r];
+ for (;;) {
+ int row, col;
+ find_pivot(tab, var, var, -1, &row, &col);
+ if (row == var->index) {
+ res = isl_lp_unbounded;
+ break;
+ }
+ if (row == -1)
+ break;
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return isl_lp_error;
+ }
+ isl_int_mul(tab->mat->row[var->index][0],
+ tab->mat->row[var->index][0], denom);
+ if (ISL_FL_ISSET(flags, ISL_TAB_SAVE_DUAL)) {
+ int i;
+
+ isl_vec_free(tab->dual);
+ tab->dual = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_con);
+ if (!tab->dual)
+ return isl_lp_error;
+ isl_int_set(tab->dual->el[0], tab->mat->row[var->index][0]);
+ for (i = 0; i < tab->n_con; ++i) {
+ int pos;
+ if (tab->con[i].is_row) {
+ isl_int_set_si(tab->dual->el[1 + i], 0);
+ continue;
+ }
+ pos = 2 + tab->M + tab->con[i].index;
+ if (tab->con[i].negated)
+ isl_int_neg(tab->dual->el[1 + i],
+ tab->mat->row[var->index][pos]);
+ else
+ isl_int_set(tab->dual->el[1 + i],
+ tab->mat->row[var->index][pos]);
+ }
+ }
+ if (opt && res == isl_lp_ok) {
+ if (opt_denom) {
+ isl_int_set(*opt, tab->mat->row[var->index][1]);
+ isl_int_set(*opt_denom, tab->mat->row[var->index][0]);
+ } else
+ isl_int_cdiv_q(*opt, tab->mat->row[var->index][1],
+ tab->mat->row[var->index][0]);
+ }
+ if (isl_tab_rollback(tab, snap) < 0)
+ return isl_lp_error;
+ return res;
+}
+
+int isl_tab_is_redundant(struct isl_tab *tab, int con)
+{
+ if (!tab)
+ return -1;
+ if (tab->con[con].is_zero)
+ return 0;
+ if (tab->con[con].is_redundant)
+ return 1;
+ return tab->con[con].is_row && tab->con[con].index < tab->n_redundant;
+}
+
+/* Take a snapshot of the tableau that can be restored by s call to
+ * isl_tab_rollback.
+ */
+struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab)
+{
+ if (!tab)
+ return NULL;
+ tab->need_undo = 1;
+ return tab->top;
+}
+
+/* Undo the operation performed by isl_tab_relax.
+ */
+static int unrelax(struct isl_tab *tab, struct isl_tab_var *var) WARN_UNUSED;
+static int unrelax(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ unsigned off = 2 + tab->M;
+
+ if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
+ if (to_row(tab, var, 1) < 0)
+ return -1;
+
+ if (var->is_row) {
+ isl_int_sub(tab->mat->row[var->index][1],
+ tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
+ if (var->is_nonneg) {
+ int sgn = restore_row(tab, var);
+ isl_assert(tab->mat->ctx, sgn >= 0, return -1);
+ }
+ } else {
+ int i;
+
+ for (i = 0; i < tab->n_row; ++i) {
+ if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
+ continue;
+ isl_int_add(tab->mat->row[i][1], tab->mat->row[i][1],
+ tab->mat->row[i][off + var->index]);
+ }
+
+ }
+
+ return 0;
+}
+
+/* Undo the operation performed by isl_tab_unrestrict.
+ *
+ * In particular, mark the variable as being non-negative and make
+ * sure the sample value respects this constraint.
+ */
+static int ununrestrict(struct isl_tab *tab, struct isl_tab_var *var)
+{
+ var->is_nonneg = 1;
+
+ if (var->is_row && restore_row(tab, var) < -1)
+ return -1;
+
+ return 0;
+}
+
+static int perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo) WARN_UNUSED;
+static int perform_undo_var(struct isl_tab *tab, struct isl_tab_undo *undo)
+{
+ struct isl_tab_var *var = var_from_index(tab, undo->u.var_index);
+ switch (undo->type) {
+ case isl_tab_undo_nonneg:
+ var->is_nonneg = 0;
+ break;
+ case isl_tab_undo_redundant:
+ var->is_redundant = 0;
+ tab->n_redundant--;
+ restore_row(tab, isl_tab_var_from_row(tab, tab->n_redundant));
+ break;
+ case isl_tab_undo_freeze:
+ var->frozen = 0;
+ break;
+ case isl_tab_undo_zero:
+ var->is_zero = 0;
+ if (!var->is_row)
+ tab->n_dead--;
+ break;
+ case isl_tab_undo_allocate:
+ if (undo->u.var_index >= 0) {
+ isl_assert(tab->mat->ctx, !var->is_row, return -1);
+ drop_col(tab, var->index);
+ break;
+ }
+ if (!var->is_row) {
+ if (!max_is_manifestly_unbounded(tab, var)) {
+ if (to_row(tab, var, 1) < 0)
+ return -1;
+ } else if (!min_is_manifestly_unbounded(tab, var)) {
+ if (to_row(tab, var, -1) < 0)
+ return -1;
+ } else
+ if (to_row(tab, var, 0) < 0)
+ return -1;
+ }
+ drop_row(tab, var->index);
+ break;
+ case isl_tab_undo_relax:
+ return unrelax(tab, var);
+ case isl_tab_undo_unrestrict:
+ return ununrestrict(tab, var);
+ default:
+ isl_die(tab->mat->ctx, isl_error_internal,
+ "perform_undo_var called on invalid undo record",
+ return -1);
+ }
+
+ return 0;
+}
+
+/* Restore the tableau to the state where the basic variables
+ * are those in "col_var".
+ * We first construct a list of variables that are currently in
+ * the basis, but shouldn't. Then we iterate over all variables
+ * that should be in the basis and for each one that is currently
+ * not in the basis, we exchange it with one of the elements of the
+ * list constructed before.
+ * We can always find an appropriate variable to pivot with because
+ * the current basis is mapped to the old basis by a non-singular
+ * matrix and so we can never end up with a zero row.
+ */
+static int restore_basis(struct isl_tab *tab, int *col_var)
+{
+ int i, j;
+ int n_extra = 0;
+ int *extra = NULL; /* current columns that contain bad stuff */
+ unsigned off = 2 + tab->M;
+
+ extra = isl_alloc_array(tab->mat->ctx, int, tab->n_col);
+ if (tab->n_col && !extra)
+ goto error;
+ for (i = 0; i < tab->n_col; ++i) {
+ for (j = 0; j < tab->n_col; ++j)
+ if (tab->col_var[i] == col_var[j])
+ break;
+ if (j < tab->n_col)
+ continue;
+ extra[n_extra++] = i;
+ }
+ for (i = 0; i < tab->n_col && n_extra > 0; ++i) {
+ struct isl_tab_var *var;
+ int row;
+
+ for (j = 0; j < tab->n_col; ++j)
+ if (col_var[i] == tab->col_var[j])
+ break;
+ if (j < tab->n_col)
+ continue;
+ var = var_from_index(tab, col_var[i]);
+ row = var->index;
+ for (j = 0; j < n_extra; ++j)
+ if (!isl_int_is_zero(tab->mat->row[row][off+extra[j]]))
+ break;
+ isl_assert(tab->mat->ctx, j < n_extra, goto error);
+ if (isl_tab_pivot(tab, row, extra[j]) < 0)
+ goto error;
+ extra[j] = extra[--n_extra];
+ }
+
+ free(extra);
+ return 0;
+error:
+ free(extra);
+ return -1;
+}
+
+/* Remove all samples with index n or greater, i.e., those samples
+ * that were added since we saved this number of samples in
+ * isl_tab_save_samples.
+ */
+static void drop_samples_since(struct isl_tab *tab, int n)
+{
+ int i;
+
+ for (i = tab->n_sample - 1; i >= 0 && tab->n_sample > n; --i) {
+ if (tab->sample_index[i] < n)
+ continue;
+
+ if (i != tab->n_sample - 1) {
+ int t = tab->sample_index[tab->n_sample-1];
+ tab->sample_index[tab->n_sample-1] = tab->sample_index[i];
+ tab->sample_index[i] = t;
+ isl_mat_swap_rows(tab->samples, tab->n_sample-1, i);
+ }
+ tab->n_sample--;
+ }
+}
+
+static int perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo) WARN_UNUSED;
+static int perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
+{
+ switch (undo->type) {
+ case isl_tab_undo_empty:
+ tab->empty = 0;
+ break;
+ case isl_tab_undo_nonneg:
+ case isl_tab_undo_redundant:
+ case isl_tab_undo_freeze:
+ case isl_tab_undo_zero:
+ case isl_tab_undo_allocate:
+ case isl_tab_undo_relax:
+ case isl_tab_undo_unrestrict:
+ return perform_undo_var(tab, undo);
+ case isl_tab_undo_bmap_eq:
+ return isl_basic_map_free_equality(tab->bmap, 1);
+ case isl_tab_undo_bmap_ineq:
+ return isl_basic_map_free_inequality(tab->bmap, 1);
+ case isl_tab_undo_bmap_div:
+ if (isl_basic_map_free_div(tab->bmap, 1) < 0)
+ return -1;
+ if (tab->samples)
+ tab->samples->n_col--;
+ break;
+ case isl_tab_undo_saved_basis:
+ if (restore_basis(tab, undo->u.col_var) < 0)
+ return -1;
+ break;
+ case isl_tab_undo_drop_sample:
+ tab->n_outside--;
+ break;
+ case isl_tab_undo_saved_samples:
+ drop_samples_since(tab, undo->u.n);
+ break;
+ case isl_tab_undo_callback:
+ return undo->u.callback->run(undo->u.callback);
+ default:
+ isl_assert(tab->mat->ctx, 0, return -1);
+ }
+ return 0;
+}
+
+/* Return the tableau to the state it was in when the snapshot "snap"
+ * was taken.
+ */
+int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap)
+{
+ struct isl_tab_undo *undo, *next;
+
+ if (!tab)
+ return -1;
+
+ tab->in_undo = 1;
+ for (undo = tab->top; undo && undo != &tab->bottom; undo = next) {
+ next = undo->next;
+ if (undo == snap)
+ break;
+ if (perform_undo(tab, undo) < 0) {
+ tab->top = undo;
+ free_undo(tab);
+ tab->in_undo = 0;
+ return -1;
+ }
+ free_undo_record(undo);
+ }
+ tab->in_undo = 0;
+ tab->top = undo;
+ if (!undo)
+ return -1;
+ return 0;
+}
+
+/* The given row "row" represents an inequality violated by all
+ * points in the tableau. Check for some special cases of such
+ * separating constraints.
+ * In particular, if the row has been reduced to the constant -1,
+ * then we know the inequality is adjacent (but opposite) to
+ * an equality in the tableau.
+ * If the row has been reduced to r = c*(-1 -r'), with r' an inequality
+ * of the tableau and c a positive constant, then the inequality
+ * is adjacent (but opposite) to the inequality r'.
+ */
+static enum isl_ineq_type separation_type(struct isl_tab *tab, unsigned row)
+{
+ int pos;
+ unsigned off = 2 + tab->M;
+
+ if (tab->rational)
+ return isl_ineq_separate;
+
+ if (!isl_int_is_one(tab->mat->row[row][0]))
+ return isl_ineq_separate;
+
+ pos = isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+ tab->n_col - tab->n_dead);
+ if (pos == -1) {
+ if (isl_int_is_negone(tab->mat->row[row][1]))
+ return isl_ineq_adj_eq;
+ else
+ return isl_ineq_separate;
+ }
+
+ if (!isl_int_eq(tab->mat->row[row][1],
+ tab->mat->row[row][off + tab->n_dead + pos]))
+ return isl_ineq_separate;
+
+ pos = isl_seq_first_non_zero(
+ tab->mat->row[row] + off + tab->n_dead + pos + 1,
+ tab->n_col - tab->n_dead - pos - 1);
+
+ return pos == -1 ? isl_ineq_adj_ineq : isl_ineq_separate;
+}
+
+/* Check the effect of inequality "ineq" on the tableau "tab".
+ * The result may be
+ * isl_ineq_redundant: satisfied by all points in the tableau
+ * isl_ineq_separate: satisfied by no point in the tableau
+ * isl_ineq_cut: satisfied by some by not all points
+ * isl_ineq_adj_eq: adjacent to an equality
+ * isl_ineq_adj_ineq: adjacent to an inequality.
+ */
+enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq)
+{
+ enum isl_ineq_type type = isl_ineq_error;
+ struct isl_tab_undo *snap = NULL;
+ int con;
+ int row;
+
+ if (!tab)
+ return isl_ineq_error;
+
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ return isl_ineq_error;
+
+ snap = isl_tab_snap(tab);
+
+ con = isl_tab_add_row(tab, ineq);
+ if (con < 0)
+ goto error;
+
+ row = tab->con[con].index;
+ if (isl_tab_row_is_redundant(tab, row))
+ type = isl_ineq_redundant;
+ else if (isl_int_is_neg(tab->mat->row[row][1]) &&
+ (tab->rational ||
+ isl_int_abs_ge(tab->mat->row[row][1],
+ tab->mat->row[row][0]))) {
+ int nonneg = at_least_zero(tab, &tab->con[con]);
+ if (nonneg < 0)
+ goto error;
+ if (nonneg)
+ type = isl_ineq_cut;
+ else
+ type = separation_type(tab, row);
+ } else {
+ int red = con_is_redundant(tab, &tab->con[con]);
+ if (red < 0)
+ goto error;
+ if (!red)
+ type = isl_ineq_cut;
+ else
+ type = isl_ineq_redundant;
+ }
+
+ if (isl_tab_rollback(tab, snap))
+ return isl_ineq_error;
+ return type;
+error:
+ return isl_ineq_error;
+}
+
+int isl_tab_track_bmap(struct isl_tab *tab, __isl_take isl_basic_map *bmap)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (!tab || !bmap)
+ goto error;
+
+ if (tab->empty) {
+ bmap = isl_basic_map_set_to_empty(bmap);
+ if (!bmap)
+ goto error;
+ tab->bmap = bmap;
+ return 0;
+ }
+
+ isl_assert(tab->mat->ctx, tab->n_eq == bmap->n_eq, goto error);
+ isl_assert(tab->mat->ctx,
+ tab->n_con == bmap->n_eq + bmap->n_ineq, goto error);
+
+ tab->bmap = bmap;
+
+ return 0;
+error:
+ isl_basic_map_free(bmap);
+ return -1;
+}
+
+int isl_tab_track_bset(struct isl_tab *tab, __isl_take isl_basic_set *bset)
+{
+ return isl_tab_track_bmap(tab, (isl_basic_map *)bset);
+}
+
+__isl_keep isl_basic_set *isl_tab_peek_bset(struct isl_tab *tab)
+{
+ if (!tab)
+ return NULL;
+
+ return (isl_basic_set *)tab->bmap;
+}
+
+static void isl_tab_print_internal(__isl_keep struct isl_tab *tab,
+ FILE *out, int indent)
+{
+ unsigned r, c;
+ int i;
+
+ if (!tab) {
+ fprintf(out, "%*snull tab\n", indent, "");
+ return;
+ }
+ fprintf(out, "%*sn_redundant: %d, n_dead: %d", indent, "",
+ tab->n_redundant, tab->n_dead);
+ if (tab->rational)
+ fprintf(out, ", rational");
+ if (tab->empty)
+ fprintf(out, ", empty");
+ fprintf(out, "\n");
+ fprintf(out, "%*s[", indent, "");
+ for (i = 0; i < tab->n_var; ++i) {
+ if (i)
+ fprintf(out, (i == tab->n_param ||
+ i == tab->n_var - tab->n_div) ? "; "
+ : ", ");
+ fprintf(out, "%c%d%s", tab->var[i].is_row ? 'r' : 'c',
+ tab->var[i].index,
+ tab->var[i].is_zero ? " [=0]" :
+ tab->var[i].is_redundant ? " [R]" : "");
+ }
+ fprintf(out, "]\n");
+ fprintf(out, "%*s[", indent, "");
+ for (i = 0; i < tab->n_con; ++i) {
+ if (i)
+ fprintf(out, ", ");
+ fprintf(out, "%c%d%s", tab->con[i].is_row ? 'r' : 'c',
+ tab->con[i].index,
+ tab->con[i].is_zero ? " [=0]" :
+ tab->con[i].is_redundant ? " [R]" : "");
+ }
+ fprintf(out, "]\n");
+ fprintf(out, "%*s[", indent, "");
+ for (i = 0; i < tab->n_row; ++i) {
+ const char *sign = "";
+ if (i)
+ fprintf(out, ", ");
+ if (tab->row_sign) {
+ if (tab->row_sign[i] == isl_tab_row_unknown)
+ sign = "?";
+ else if (tab->row_sign[i] == isl_tab_row_neg)
+ sign = "-";
+ else if (tab->row_sign[i] == isl_tab_row_pos)
+ sign = "+";
+ else
+ sign = "+-";
+ }
+ fprintf(out, "r%d: %d%s%s", i, tab->row_var[i],
+ isl_tab_var_from_row(tab, i)->is_nonneg ? " [>=0]" : "", sign);
+ }
+ fprintf(out, "]\n");
+ fprintf(out, "%*s[", indent, "");
+ for (i = 0; i < tab->n_col; ++i) {
+ if (i)
+ fprintf(out, ", ");
+ fprintf(out, "c%d: %d%s", i, tab->col_var[i],
+ var_from_col(tab, i)->is_nonneg ? " [>=0]" : "");
+ }
+ fprintf(out, "]\n");
+ r = tab->mat->n_row;
+ tab->mat->n_row = tab->n_row;
+ c = tab->mat->n_col;
+ tab->mat->n_col = 2 + tab->M + tab->n_col;
+ isl_mat_print_internal(tab->mat, out, indent);
+ tab->mat->n_row = r;
+ tab->mat->n_col = c;
+ if (tab->bmap)
+ isl_basic_map_print_internal(tab->bmap, out, indent);
+}
+
+void isl_tab_dump(__isl_keep struct isl_tab *tab)
+{
+ isl_tab_print_internal(tab, stderr, 0);
+}
diff --git a/polly/lib/External/isl/isl_tab.h b/polly/lib/External/isl/isl_tab.h
new file mode 100644
index 00000000000..cfae0c919f8
--- /dev/null
+++ b/polly/lib/External/isl/isl_tab.h
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#ifndef ISL_TAB_H
+#define ISL_TAB_H
+
+#include <isl/lp.h>
+#include <isl/map.h>
+#include <isl/mat.h>
+#include <isl/set.h>
+#include <isl_config.h>
+
+struct isl_tab_var {
+ int index;
+ unsigned is_row : 1;
+ unsigned is_nonneg : 1;
+ unsigned is_zero : 1;
+ unsigned is_redundant : 1;
+ unsigned marked : 1;
+ unsigned frozen : 1;
+ unsigned negated : 1;
+};
+
+enum isl_tab_undo_type {
+ isl_tab_undo_bottom,
+ isl_tab_undo_empty,
+ isl_tab_undo_nonneg,
+ isl_tab_undo_redundant,
+ isl_tab_undo_freeze,
+ isl_tab_undo_zero,
+ isl_tab_undo_allocate,
+ isl_tab_undo_relax,
+ isl_tab_undo_unrestrict,
+ isl_tab_undo_bmap_ineq,
+ isl_tab_undo_bmap_eq,
+ isl_tab_undo_bmap_div,
+ isl_tab_undo_saved_basis,
+ isl_tab_undo_drop_sample,
+ isl_tab_undo_saved_samples,
+ isl_tab_undo_callback,
+};
+
+struct isl_tab_callback {
+ int (*run)(struct isl_tab_callback *cb);
+};
+
+union isl_tab_undo_val {
+ int var_index;
+ int *col_var;
+ int n;
+ struct isl_tab_callback *callback;
+};
+
+struct isl_tab_undo {
+ enum isl_tab_undo_type type;
+ union isl_tab_undo_val u;
+ struct isl_tab_undo *next;
+};
+
+/* The tableau maintains equality relations.
+ * Each column and each row is associated to a variable or a constraint.
+ * The "value" of an inequality constraint is the value of the corresponding
+ * slack variable.
+ * The "row_var" and "col_var" arrays map column and row indices
+ * to indices in the "var" and "con" arrays. The elements of these
+ * arrays maintain extra information about the variables and the constraints.
+ * Each row expresses the corresponding row variable as an affine expression
+ * of the column variables.
+ * The first two columns in the matrix contain the common denominator of
+ * the row and the numerator of the constant term.
+ * If "M" is set, then the third column represents the "big parameter".
+ * The third (M = 0) or fourth (M = 1) column
+ * in the matrix is called column 0 with respect to the col_var array.
+ * The sample value of the tableau is the value that assigns zero
+ * to all the column variables and the constant term of each affine
+ * expression to the corresponding row variable.
+ * The operations on the tableau maintain the property that the sample
+ * value satisfies the non-negativity constraints (usually on the slack
+ * variables).
+ *
+ * The big parameter represents an arbitrarily big (and divisible)
+ * positive number. If present, then the sign of a row is determined
+ * lexicographically, with the sign of the big parameter coefficient
+ * considered first. The big parameter is only used while
+ * solving PILP problems.
+ *
+ * The first n_dead column variables have their values fixed to zero.
+ * The corresponding tab_vars are flagged "is_zero".
+ * Some of the rows that have have zero coefficients in all but
+ * the dead columns are also flagged "is_zero".
+ *
+ * The first n_redundant rows correspond to inequality constraints
+ * that are always satisfied for any value satisfying the non-redundant
+ * rows. The corresponding tab_vars are flagged "is_redundant".
+ * A row variable that is flagged "is_zero" is also flagged "is_redundant"
+ * since the constraint has been reduced to 0 = 0 and is therefore always
+ * satisfied.
+ *
+ * There are "n_var" variables in total. The first "n_param" of these
+ * are called parameters and the last "n_div" of these are called divs.
+ * The basic tableau operations makes no distinction between different
+ * kinds of variables. These special variables are only used while
+ * solving PILP problems.
+ *
+ * Dead columns and redundant rows are detected on the fly.
+ * However, the basic operations do not ensure that all dead columns
+ * or all redundant rows are detected.
+ * isl_tab_detect_implicit_equalities and isl_tab_detect_redundant can be used
+ * to perform and exhaustive search for dead columns and redundant rows.
+ *
+ * The samples matrix contains "n_sample" integer points that have at some
+ * point been elements satisfying the tableau. The first "n_outside"
+ * of them no longer satisfy the tableau. They are kept because they
+ * can be reinstated during rollback when the constraint that cut them
+ * out is removed. These samples are only maintained for the context
+ * tableau while solving PILP problems.
+ *
+ * If "preserve" is set, then we want to keep all constraints in the
+ * tableau, even if they turn out to be redundant.
+ */
+enum isl_tab_row_sign {
+ isl_tab_row_unknown = 0,
+ isl_tab_row_pos,
+ isl_tab_row_neg,
+ isl_tab_row_any,
+};
+struct isl_tab {
+ struct isl_mat *mat;
+
+ unsigned n_row;
+ unsigned n_col;
+ unsigned n_dead;
+ unsigned n_redundant;
+
+ unsigned n_var;
+ unsigned n_param;
+ unsigned n_div;
+ unsigned max_var;
+ unsigned n_con;
+ unsigned n_eq;
+ unsigned max_con;
+ struct isl_tab_var *var;
+ struct isl_tab_var *con;
+ int *row_var; /* v >= 0 -> var v; v < 0 -> con ~v */
+ int *col_var; /* v >= 0 -> var v; v < 0 -> con ~v */
+ enum isl_tab_row_sign *row_sign;
+
+ struct isl_tab_undo bottom;
+ struct isl_tab_undo *top;
+
+ struct isl_vec *dual;
+ struct isl_basic_map *bmap;
+
+ unsigned n_sample;
+ unsigned n_outside;
+ int *sample_index;
+ struct isl_mat *samples;
+
+ int n_zero;
+ int n_unbounded;
+ struct isl_mat *basis;
+
+ int (*conflict)(int con, void *user);
+ void *conflict_user;
+
+ unsigned strict_redundant : 1;
+ unsigned need_undo : 1;
+ unsigned preserve : 1;
+ unsigned rational : 1;
+ unsigned empty : 1;
+ unsigned in_undo : 1;
+ unsigned M : 1;
+ unsigned cone : 1;
+};
+
+struct isl_tab *isl_tab_alloc(struct isl_ctx *ctx,
+ unsigned n_row, unsigned n_var, unsigned M);
+void isl_tab_free(struct isl_tab *tab);
+
+isl_ctx *isl_tab_get_ctx(struct isl_tab *tab);
+
+__isl_give struct isl_tab *isl_tab_from_basic_map(
+ __isl_keep isl_basic_map *bmap, int track);
+__isl_give struct isl_tab *isl_tab_from_basic_set(
+ __isl_keep isl_basic_set *bset, int track);
+struct isl_tab *isl_tab_from_recession_cone(struct isl_basic_set *bset,
+ int parametric);
+int isl_tab_cone_is_bounded(struct isl_tab *tab);
+struct isl_basic_map *isl_basic_map_update_from_tab(struct isl_basic_map *bmap,
+ struct isl_tab *tab);
+struct isl_basic_set *isl_basic_set_update_from_tab(struct isl_basic_set *bset,
+ struct isl_tab *tab);
+int isl_tab_detect_implicit_equalities(struct isl_tab *tab) WARN_UNUSED;
+__isl_give isl_basic_map *isl_tab_make_equalities_explicit(struct isl_tab *tab,
+ __isl_take isl_basic_map *bmap);
+int isl_tab_detect_redundant(struct isl_tab *tab) WARN_UNUSED;
+#define ISL_TAB_SAVE_DUAL (1 << 0)
+enum isl_lp_result isl_tab_min(struct isl_tab *tab,
+ isl_int *f, isl_int denom, isl_int *opt, isl_int *opt_denom,
+ unsigned flags) WARN_UNUSED;
+
+int isl_tab_add_ineq(struct isl_tab *tab, isl_int *ineq) WARN_UNUSED;
+int isl_tab_add_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
+int isl_tab_add_valid_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
+
+int isl_tab_freeze_constraint(struct isl_tab *tab, int con) WARN_UNUSED;
+
+int isl_tab_track_bmap(struct isl_tab *tab, __isl_take isl_basic_map *bmap) WARN_UNUSED;
+int isl_tab_track_bset(struct isl_tab *tab, __isl_take isl_basic_set *bset) WARN_UNUSED;
+__isl_keep isl_basic_set *isl_tab_peek_bset(struct isl_tab *tab);
+
+int isl_tab_is_equality(struct isl_tab *tab, int con);
+int isl_tab_is_redundant(struct isl_tab *tab, int con);
+
+int isl_tab_sample_is_integer(struct isl_tab *tab);
+struct isl_vec *isl_tab_get_sample_value(struct isl_tab *tab);
+
+enum isl_ineq_type {
+ isl_ineq_error = -1,
+ isl_ineq_redundant,
+ isl_ineq_separate,
+ isl_ineq_cut,
+ isl_ineq_adj_eq,
+ isl_ineq_adj_ineq,
+};
+
+enum isl_ineq_type isl_tab_ineq_type(struct isl_tab *tab, isl_int *ineq);
+
+struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab);
+int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap) WARN_UNUSED;
+
+struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con) WARN_UNUSED;
+int isl_tab_select_facet(struct isl_tab *tab, int con) WARN_UNUSED;
+int isl_tab_unrestrict(struct isl_tab *tab, int con) WARN_UNUSED;
+
+void isl_tab_dump(__isl_keep struct isl_tab *tab);
+
+struct isl_map *isl_tab_basic_map_partial_lexopt(
+ struct isl_basic_map *bmap, struct isl_basic_set *dom,
+ struct isl_set **empty, int max);
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexopt_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max);
+
+/* An isl_region represents a sequence of consecutive variables.
+ * pos is the location (starting at 0) of the first variable in the sequence.
+ */
+struct isl_region {
+ int pos;
+ int len;
+};
+
+__isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
+ __isl_take isl_basic_set *bset, int n_op, int n_region,
+ struct isl_region *region,
+ int (*conflict)(int con, void *user), void *user);
+__isl_give isl_vec *isl_tab_basic_set_non_neg_lexmin(
+ __isl_take isl_basic_set *bset);
+
+/* private */
+
+struct isl_tab_var *isl_tab_var_from_row(struct isl_tab *tab, int i);
+int isl_tab_mark_redundant(struct isl_tab *tab, int row) WARN_UNUSED;
+int isl_tab_mark_empty(struct isl_tab *tab) WARN_UNUSED;
+struct isl_tab *isl_tab_dup(struct isl_tab *tab);
+struct isl_tab *isl_tab_product(struct isl_tab *tab1, struct isl_tab *tab2);
+int isl_tab_extend_cons(struct isl_tab *tab, unsigned n_new) WARN_UNUSED;
+int isl_tab_allocate_con(struct isl_tab *tab) WARN_UNUSED;
+int isl_tab_extend_vars(struct isl_tab *tab, unsigned n_new) WARN_UNUSED;
+int isl_tab_allocate_var(struct isl_tab *tab) WARN_UNUSED;
+int isl_tab_pivot(struct isl_tab *tab, int row, int col) WARN_UNUSED;
+int isl_tab_add_row(struct isl_tab *tab, isl_int *line) WARN_UNUSED;
+int isl_tab_row_is_redundant(struct isl_tab *tab, int row);
+int isl_tab_min_at_most_neg_one(struct isl_tab *tab, struct isl_tab_var *var);
+int isl_tab_sign_of_max(struct isl_tab *tab, int con);
+int isl_tab_kill_col(struct isl_tab *tab, int col) WARN_UNUSED;
+
+int isl_tab_push(struct isl_tab *tab, enum isl_tab_undo_type type) WARN_UNUSED;
+int isl_tab_push_var(struct isl_tab *tab,
+ enum isl_tab_undo_type type, struct isl_tab_var *var) WARN_UNUSED;
+int isl_tab_push_basis(struct isl_tab *tab) WARN_UNUSED;
+
+struct isl_tab *isl_tab_init_samples(struct isl_tab *tab) WARN_UNUSED;
+int isl_tab_add_sample(struct isl_tab *tab,
+ __isl_take isl_vec *sample) WARN_UNUSED;
+struct isl_tab *isl_tab_drop_sample(struct isl_tab *tab, int s);
+int isl_tab_save_samples(struct isl_tab *tab) WARN_UNUSED;
+
+struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
+ struct isl_tab *tab_cone) WARN_UNUSED;
+
+int isl_tab_push_callback(struct isl_tab *tab,
+ struct isl_tab_callback *callback) WARN_UNUSED;
+
+int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
+ int (*add_ineq)(void *user, isl_int *), void *user);
+
+#endif
diff --git a/polly/lib/External/isl/isl_tab_pip.c b/polly/lib/External/isl/isl_tab_pip.c
new file mode 100644
index 00000000000..2a4a4f731fd
--- /dev/null
+++ b/polly/lib/External/isl/isl_tab_pip.c
@@ -0,0 +1,5681 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_ctx_private.h>
+#include "isl_map_private.h"
+#include <isl_seq.h>
+#include "isl_tab.h"
+#include "isl_sample.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_aff_private.h>
+#include <isl_options_private.h>
+#include <isl_config.h>
+
+/*
+ * The implementation of parametric integer linear programming in this file
+ * was inspired by the paper "Parametric Integer Programming" and the
+ * report "Solving systems of affine (in)equalities" by Paul Feautrier
+ * (and others).
+ *
+ * The strategy used for obtaining a feasible solution is different
+ * from the one used in isl_tab.c. In particular, in isl_tab.c,
+ * upon finding a constraint that is not yet satisfied, we pivot
+ * in a row that increases the constant term of the row holding the
+ * constraint, making sure the sample solution remains feasible
+ * for all the constraints it already satisfied.
+ * Here, we always pivot in the row holding the constraint,
+ * choosing a column that induces the lexicographically smallest
+ * increment to the sample solution.
+ *
+ * By starting out from a sample value that is lexicographically
+ * smaller than any integer point in the problem space, the first
+ * feasible integer sample point we find will also be the lexicographically
+ * smallest. If all variables can be assumed to be non-negative,
+ * then the initial sample value may be chosen equal to zero.
+ * However, we will not make this assumption. Instead, we apply
+ * the "big parameter" trick. Any variable x is then not directly
+ * used in the tableau, but instead it is represented by another
+ * variable x' = M + x, where M is an arbitrarily large (positive)
+ * value. x' is therefore always non-negative, whatever the value of x.
+ * Taking as initial sample value x' = 0 corresponds to x = -M,
+ * which is always smaller than any possible value of x.
+ *
+ * The big parameter trick is used in the main tableau and
+ * also in the context tableau if isl_context_lex is used.
+ * In this case, each tableaus has its own big parameter.
+ * Before doing any real work, we check if all the parameters
+ * happen to be non-negative. If so, we drop the column corresponding
+ * to M from the initial context tableau.
+ * If isl_context_gbr is used, then the big parameter trick is only
+ * used in the main tableau.
+ */
+
+struct isl_context;
+struct isl_context_op {
+ /* detect nonnegative parameters in context and mark them in tab */
+ struct isl_tab *(*detect_nonnegative_parameters)(
+ struct isl_context *context, struct isl_tab *tab);
+ /* return temporary reference to basic set representation of context */
+ struct isl_basic_set *(*peek_basic_set)(struct isl_context *context);
+ /* return temporary reference to tableau representation of context */
+ struct isl_tab *(*peek_tab)(struct isl_context *context);
+ /* add equality; check is 1 if eq may not be valid;
+ * update is 1 if we may want to call ineq_sign on context later.
+ */
+ void (*add_eq)(struct isl_context *context, isl_int *eq,
+ int check, int update);
+ /* add inequality; check is 1 if ineq may not be valid;
+ * update is 1 if we may want to call ineq_sign on context later.
+ */
+ void (*add_ineq)(struct isl_context *context, isl_int *ineq,
+ int check, int update);
+ /* check sign of ineq based on previous information.
+ * strict is 1 if saturation should be treated as a positive sign.
+ */
+ enum isl_tab_row_sign (*ineq_sign)(struct isl_context *context,
+ isl_int *ineq, int strict);
+ /* check if inequality maintains feasibility */
+ int (*test_ineq)(struct isl_context *context, isl_int *ineq);
+ /* return index of a div that corresponds to "div" */
+ int (*get_div)(struct isl_context *context, struct isl_tab *tab,
+ struct isl_vec *div);
+ /* add div "div" to context and return non-negativity */
+ int (*add_div)(struct isl_context *context, struct isl_vec *div);
+ int (*detect_equalities)(struct isl_context *context,
+ struct isl_tab *tab);
+ /* return row index of "best" split */
+ int (*best_split)(struct isl_context *context, struct isl_tab *tab);
+ /* check if context has already been determined to be empty */
+ int (*is_empty)(struct isl_context *context);
+ /* check if context is still usable */
+ int (*is_ok)(struct isl_context *context);
+ /* save a copy/snapshot of context */
+ void *(*save)(struct isl_context *context);
+ /* restore saved context */
+ void (*restore)(struct isl_context *context, void *);
+ /* discard saved context */
+ void (*discard)(void *);
+ /* invalidate context */
+ void (*invalidate)(struct isl_context *context);
+ /* free context */
+ void (*free)(struct isl_context *context);
+};
+
+struct isl_context {
+ struct isl_context_op *op;
+};
+
+struct isl_context_lex {
+ struct isl_context context;
+ struct isl_tab *tab;
+};
+
+/* A stack (linked list) of solutions of subtrees of the search space.
+ *
+ * "M" describes the solution in terms of the dimensions of "dom".
+ * The number of columns of "M" is one more than the total number
+ * of dimensions of "dom".
+ *
+ * If "M" is NULL, then there is no solution on "dom".
+ */
+struct isl_partial_sol {
+ int level;
+ struct isl_basic_set *dom;
+ struct isl_mat *M;
+
+ struct isl_partial_sol *next;
+};
+
+struct isl_sol;
+struct isl_sol_callback {
+ struct isl_tab_callback callback;
+ struct isl_sol *sol;
+};
+
+/* isl_sol is an interface for constructing a solution to
+ * a parametric integer linear programming problem.
+ * Every time the algorithm reaches a state where a solution
+ * can be read off from the tableau (including cases where the tableau
+ * is empty), the function "add" is called on the isl_sol passed
+ * to find_solutions_main.
+ *
+ * The context tableau is owned by isl_sol and is updated incrementally.
+ *
+ * There are currently two implementations of this interface,
+ * isl_sol_map, which simply collects the solutions in an isl_map
+ * and (optionally) the parts of the context where there is no solution
+ * in an isl_set, and
+ * isl_sol_for, which calls a user-defined function for each part of
+ * the solution.
+ */
+struct isl_sol {
+ int error;
+ int rational;
+ int level;
+ int max;
+ int n_out;
+ struct isl_context *context;
+ struct isl_partial_sol *partial;
+ void (*add)(struct isl_sol *sol,
+ struct isl_basic_set *dom, struct isl_mat *M);
+ void (*add_empty)(struct isl_sol *sol, struct isl_basic_set *bset);
+ void (*free)(struct isl_sol *sol);
+ struct isl_sol_callback dec_level;
+};
+
+static void sol_free(struct isl_sol *sol)
+{
+ struct isl_partial_sol *partial, *next;
+ if (!sol)
+ return;
+ for (partial = sol->partial; partial; partial = next) {
+ next = partial->next;
+ isl_basic_set_free(partial->dom);
+ isl_mat_free(partial->M);
+ free(partial);
+ }
+ sol->free(sol);
+}
+
+/* Push a partial solution represented by a domain and mapping M
+ * onto the stack of partial solutions.
+ */
+static void sol_push_sol(struct isl_sol *sol,
+ struct isl_basic_set *dom, struct isl_mat *M)
+{
+ struct isl_partial_sol *partial;
+
+ if (sol->error || !dom)
+ goto error;
+
+ partial = isl_alloc_type(dom->ctx, struct isl_partial_sol);
+ if (!partial)
+ goto error;
+
+ partial->level = sol->level;
+ partial->dom = dom;
+ partial->M = M;
+ partial->next = sol->partial;
+
+ sol->partial = partial;
+
+ return;
+error:
+ isl_basic_set_free(dom);
+ isl_mat_free(M);
+ sol->error = 1;
+}
+
+/* Pop one partial solution from the partial solution stack and
+ * pass it on to sol->add or sol->add_empty.
+ */
+static void sol_pop_one(struct isl_sol *sol)
+{
+ struct isl_partial_sol *partial;
+
+ partial = sol->partial;
+ sol->partial = partial->next;
+
+ if (partial->M)
+ sol->add(sol, partial->dom, partial->M);
+ else
+ sol->add_empty(sol, partial->dom);
+ free(partial);
+}
+
+/* Return a fresh copy of the domain represented by the context tableau.
+ */
+static struct isl_basic_set *sol_domain(struct isl_sol *sol)
+{
+ struct isl_basic_set *bset;
+
+ if (sol->error)
+ return NULL;
+
+ bset = isl_basic_set_dup(sol->context->op->peek_basic_set(sol->context));
+ bset = isl_basic_set_update_from_tab(bset,
+ sol->context->op->peek_tab(sol->context));
+
+ return bset;
+}
+
+/* Check whether two partial solutions have the same mapping, where n_div
+ * is the number of divs that the two partial solutions have in common.
+ */
+static int same_solution(struct isl_partial_sol *s1, struct isl_partial_sol *s2,
+ unsigned n_div)
+{
+ int i;
+ unsigned dim;
+
+ if (!s1->M != !s2->M)
+ return 0;
+ if (!s1->M)
+ return 1;
+
+ dim = isl_basic_set_total_dim(s1->dom) - s1->dom->n_div;
+
+ for (i = 0; i < s1->M->n_row; ++i) {
+ if (isl_seq_first_non_zero(s1->M->row[i]+1+dim+n_div,
+ s1->M->n_col-1-dim-n_div) != -1)
+ return 0;
+ if (isl_seq_first_non_zero(s2->M->row[i]+1+dim+n_div,
+ s2->M->n_col-1-dim-n_div) != -1)
+ return 0;
+ if (!isl_seq_eq(s1->M->row[i], s2->M->row[i], 1+dim+n_div))
+ return 0;
+ }
+ return 1;
+}
+
+/* Pop all solutions from the partial solution stack that were pushed onto
+ * the stack at levels that are deeper than the current level.
+ * If the two topmost elements on the stack have the same level
+ * and represent the same solution, then their domains are combined.
+ * This combined domain is the same as the current context domain
+ * as sol_pop is called each time we move back to a higher level.
+ */
+static void sol_pop(struct isl_sol *sol)
+{
+ struct isl_partial_sol *partial;
+ unsigned n_div;
+
+ if (sol->error)
+ return;
+
+ if (sol->level == 0) {
+ for (partial = sol->partial; partial; partial = sol->partial)
+ sol_pop_one(sol);
+ return;
+ }
+
+ partial = sol->partial;
+ if (!partial)
+ return;
+
+ if (partial->level <= sol->level)
+ return;
+
+ if (partial->next && partial->next->level == partial->level) {
+ n_div = isl_basic_set_dim(
+ sol->context->op->peek_basic_set(sol->context),
+ isl_dim_div);
+
+ if (!same_solution(partial, partial->next, n_div)) {
+ sol_pop_one(sol);
+ sol_pop_one(sol);
+ } else {
+ struct isl_basic_set *bset;
+ isl_mat *M;
+ unsigned n;
+
+ n = isl_basic_set_dim(partial->next->dom, isl_dim_div);
+ n -= n_div;
+ bset = sol_domain(sol);
+ isl_basic_set_free(partial->next->dom);
+ partial->next->dom = bset;
+ M = partial->next->M;
+ if (M) {
+ M = isl_mat_drop_cols(M, M->n_col - n, n);
+ partial->next->M = M;
+ if (!M)
+ goto error;
+ }
+ partial->next->level = sol->level;
+
+ if (!bset)
+ goto error;
+
+ sol->partial = partial->next;
+ isl_basic_set_free(partial->dom);
+ isl_mat_free(partial->M);
+ free(partial);
+ }
+ } else
+ sol_pop_one(sol);
+
+ if (0)
+error: sol->error = 1;
+}
+
+static void sol_dec_level(struct isl_sol *sol)
+{
+ if (sol->error)
+ return;
+
+ sol->level--;
+
+ sol_pop(sol);
+}
+
+static int sol_dec_level_wrap(struct isl_tab_callback *cb)
+{
+ struct isl_sol_callback *callback = (struct isl_sol_callback *)cb;
+
+ sol_dec_level(callback->sol);
+
+ return callback->sol->error ? -1 : 0;
+}
+
+/* Move down to next level and push callback onto context tableau
+ * to decrease the level again when it gets rolled back across
+ * the current state. That is, dec_level will be called with
+ * the context tableau in the same state as it is when inc_level
+ * is called.
+ */
+static void sol_inc_level(struct isl_sol *sol)
+{
+ struct isl_tab *tab;
+
+ if (sol->error)
+ return;
+
+ sol->level++;
+ tab = sol->context->op->peek_tab(sol->context);
+ if (isl_tab_push_callback(tab, &sol->dec_level.callback) < 0)
+ sol->error = 1;
+}
+
+static void scale_rows(struct isl_mat *mat, isl_int m, int n_row)
+{
+ int i;
+
+ if (isl_int_is_one(m))
+ return;
+
+ for (i = 0; i < n_row; ++i)
+ isl_seq_scale(mat->row[i], mat->row[i], m, mat->n_col);
+}
+
+/* Add the solution identified by the tableau and the context tableau.
+ *
+ * The layout of the variables is as follows.
+ * tab->n_var is equal to the total number of variables in the input
+ * map (including divs that were copied from the context)
+ * + the number of extra divs constructed
+ * Of these, the first tab->n_param and the last tab->n_div variables
+ * correspond to the variables in the context, i.e.,
+ * tab->n_param + tab->n_div = context_tab->n_var
+ * tab->n_param is equal to the number of parameters and input
+ * dimensions in the input map
+ * tab->n_div is equal to the number of divs in the context
+ *
+ * If there is no solution, then call add_empty with a basic set
+ * that corresponds to the context tableau. (If add_empty is NULL,
+ * then do nothing).
+ *
+ * If there is a solution, then first construct a matrix that maps
+ * all dimensions of the context to the output variables, i.e.,
+ * the output dimensions in the input map.
+ * The divs in the input map (if any) that do not correspond to any
+ * div in the context do not appear in the solution.
+ * The algorithm will make sure that they have an integer value,
+ * but these values themselves are of no interest.
+ * We have to be careful not to drop or rearrange any divs in the
+ * context because that would change the meaning of the matrix.
+ *
+ * To extract the value of the output variables, it should be noted
+ * that we always use a big parameter M in the main tableau and so
+ * the variable stored in this tableau is not an output variable x itself, but
+ * x' = M + x (in case of minimization)
+ * or
+ * x' = M - x (in case of maximization)
+ * If x' appears in a column, then its optimal value is zero,
+ * which means that the optimal value of x is an unbounded number
+ * (-M for minimization and M for maximization).
+ * We currently assume that the output dimensions in the original map
+ * are bounded, so this cannot occur.
+ * Similarly, when x' appears in a row, then the coefficient of M in that
+ * row is necessarily 1.
+ * If the row in the tableau represents
+ * d x' = c + d M + e(y)
+ * then, in case of minimization, the corresponding row in the matrix
+ * will be
+ * a c + a e(y)
+ * with a d = m, the (updated) common denominator of the matrix.
+ * In case of maximization, the row will be
+ * -a c - a e(y)
+ */
+static void sol_add(struct isl_sol *sol, struct isl_tab *tab)
+{
+ struct isl_basic_set *bset = NULL;
+ struct isl_mat *mat = NULL;
+ unsigned off;
+ int row;
+ isl_int m;
+
+ if (sol->error || !tab)
+ goto error;
+
+ if (tab->empty && !sol->add_empty)
+ return;
+ if (sol->context->op->is_empty(sol->context))
+ return;
+
+ bset = sol_domain(sol);
+
+ if (tab->empty) {
+ sol_push_sol(sol, bset, NULL);
+ return;
+ }
+
+ off = 2 + tab->M;
+
+ mat = isl_mat_alloc(tab->mat->ctx, 1 + sol->n_out,
+ 1 + tab->n_param + tab->n_div);
+ if (!mat)
+ goto error;
+
+ isl_int_init(m);
+
+ isl_seq_clr(mat->row[0] + 1, mat->n_col - 1);
+ isl_int_set_si(mat->row[0][0], 1);
+ for (row = 0; row < sol->n_out; ++row) {
+ int i = tab->n_param + row;
+ int r, j;
+
+ isl_seq_clr(mat->row[1 + row], mat->n_col);
+ if (!tab->var[i].is_row) {
+ if (tab->M)
+ isl_die(mat->ctx, isl_error_invalid,
+ "unbounded optimum", goto error2);
+ continue;
+ }
+
+ r = tab->var[i].index;
+ if (tab->M &&
+ isl_int_ne(tab->mat->row[r][2], tab->mat->row[r][0]))
+ isl_die(mat->ctx, isl_error_invalid,
+ "unbounded optimum", goto error2);
+ isl_int_gcd(m, mat->row[0][0], tab->mat->row[r][0]);
+ isl_int_divexact(m, tab->mat->row[r][0], m);
+ scale_rows(mat, m, 1 + row);
+ isl_int_divexact(m, mat->row[0][0], tab->mat->row[r][0]);
+ isl_int_mul(mat->row[1 + row][0], m, tab->mat->row[r][1]);
+ for (j = 0; j < tab->n_param; ++j) {
+ int col;
+ if (tab->var[j].is_row)
+ continue;
+ col = tab->var[j].index;
+ isl_int_mul(mat->row[1 + row][1 + j], m,
+ tab->mat->row[r][off + col]);
+ }
+ for (j = 0; j < tab->n_div; ++j) {
+ int col;
+ if (tab->var[tab->n_var - tab->n_div+j].is_row)
+ continue;
+ col = tab->var[tab->n_var - tab->n_div+j].index;
+ isl_int_mul(mat->row[1 + row][1 + tab->n_param + j], m,
+ tab->mat->row[r][off + col]);
+ }
+ if (sol->max)
+ isl_seq_neg(mat->row[1 + row], mat->row[1 + row],
+ mat->n_col);
+ }
+
+ isl_int_clear(m);
+
+ sol_push_sol(sol, bset, mat);
+ return;
+error2:
+ isl_int_clear(m);
+error:
+ isl_basic_set_free(bset);
+ isl_mat_free(mat);
+ sol->error = 1;
+}
+
+struct isl_sol_map {
+ struct isl_sol sol;
+ struct isl_map *map;
+ struct isl_set *empty;
+};
+
+static void sol_map_free(struct isl_sol_map *sol_map)
+{
+ if (!sol_map)
+ return;
+ if (sol_map->sol.context)
+ sol_map->sol.context->op->free(sol_map->sol.context);
+ isl_map_free(sol_map->map);
+ isl_set_free(sol_map->empty);
+ free(sol_map);
+}
+
+static void sol_map_free_wrap(struct isl_sol *sol)
+{
+ sol_map_free((struct isl_sol_map *)sol);
+}
+
+/* This function is called for parts of the context where there is
+ * no solution, with "bset" corresponding to the context tableau.
+ * Simply add the basic set to the set "empty".
+ */
+static void sol_map_add_empty(struct isl_sol_map *sol,
+ struct isl_basic_set *bset)
+{
+ if (!bset)
+ goto error;
+ isl_assert(bset->ctx, sol->empty, goto error);
+
+ sol->empty = isl_set_grow(sol->empty, 1);
+ bset = isl_basic_set_simplify(bset);
+ bset = isl_basic_set_finalize(bset);
+ sol->empty = isl_set_add_basic_set(sol->empty, isl_basic_set_copy(bset));
+ if (!sol->empty)
+ goto error;
+ isl_basic_set_free(bset);
+ return;
+error:
+ isl_basic_set_free(bset);
+ sol->sol.error = 1;
+}
+
+static void sol_map_add_empty_wrap(struct isl_sol *sol,
+ struct isl_basic_set *bset)
+{
+ sol_map_add_empty((struct isl_sol_map *)sol, bset);
+}
+
+/* Given a basic map "dom" that represents the context and an affine
+ * matrix "M" that maps the dimensions of the context to the
+ * output variables, construct a basic map with the same parameters
+ * and divs as the context, the dimensions of the context as input
+ * dimensions and a number of output dimensions that is equal to
+ * the number of output dimensions in the input map.
+ *
+ * The constraints and divs of the context are simply copied
+ * from "dom". For each row
+ * x = c + e(y)
+ * an equality
+ * c + e(y) - d x = 0
+ * is added, with d the common denominator of M.
+ */
+static void sol_map_add(struct isl_sol_map *sol,
+ struct isl_basic_set *dom, struct isl_mat *M)
+{
+ int i;
+ struct isl_basic_map *bmap = NULL;
+ unsigned n_eq;
+ unsigned n_ineq;
+ unsigned nparam;
+ unsigned total;
+ unsigned n_div;
+ unsigned n_out;
+
+ if (sol->sol.error || !dom || !M)
+ goto error;
+
+ n_out = sol->sol.n_out;
+ n_eq = dom->n_eq + n_out;
+ n_ineq = dom->n_ineq;
+ n_div = dom->n_div;
+ nparam = isl_basic_set_total_dim(dom) - n_div;
+ total = isl_map_dim(sol->map, isl_dim_all);
+ bmap = isl_basic_map_alloc_space(isl_map_get_space(sol->map),
+ n_div, n_eq, 2 * n_div + n_ineq);
+ if (!bmap)
+ goto error;
+ if (sol->sol.rational)
+ ISL_F_SET(bmap, ISL_BASIC_MAP_RATIONAL);
+ for (i = 0; i < dom->n_div; ++i) {
+ int k = isl_basic_map_alloc_div(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->div[k], dom->div[i], 1 + 1 + nparam);
+ isl_seq_clr(bmap->div[k] + 1 + 1 + nparam, total - nparam);
+ isl_seq_cpy(bmap->div[k] + 1 + 1 + total,
+ dom->div[i] + 1 + 1 + nparam, i);
+ }
+ for (i = 0; i < dom->n_eq; ++i) {
+ int k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->eq[k], dom->eq[i], 1 + nparam);
+ isl_seq_clr(bmap->eq[k] + 1 + nparam, total - nparam);
+ isl_seq_cpy(bmap->eq[k] + 1 + total,
+ dom->eq[i] + 1 + nparam, n_div);
+ }
+ for (i = 0; i < dom->n_ineq; ++i) {
+ int k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->ineq[k], dom->ineq[i], 1 + nparam);
+ isl_seq_clr(bmap->ineq[k] + 1 + nparam, total - nparam);
+ isl_seq_cpy(bmap->ineq[k] + 1 + total,
+ dom->ineq[i] + 1 + nparam, n_div);
+ }
+ for (i = 0; i < M->n_row - 1; ++i) {
+ int k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bmap->eq[k], M->row[1 + i], 1 + nparam);
+ isl_seq_clr(bmap->eq[k] + 1 + nparam, n_out);
+ isl_int_neg(bmap->eq[k][1 + nparam + i], M->row[0][0]);
+ isl_seq_cpy(bmap->eq[k] + 1 + nparam + n_out,
+ M->row[1 + i] + 1 + nparam, n_div);
+ }
+ bmap = isl_basic_map_simplify(bmap);
+ bmap = isl_basic_map_finalize(bmap);
+ sol->map = isl_map_grow(sol->map, 1);
+ sol->map = isl_map_add_basic_map(sol->map, bmap);
+ isl_basic_set_free(dom);
+ isl_mat_free(M);
+ if (!sol->map)
+ sol->sol.error = 1;
+ return;
+error:
+ isl_basic_set_free(dom);
+ isl_mat_free(M);
+ isl_basic_map_free(bmap);
+ sol->sol.error = 1;
+}
+
+static void sol_map_add_wrap(struct isl_sol *sol,
+ struct isl_basic_set *dom, struct isl_mat *M)
+{
+ sol_map_add((struct isl_sol_map *)sol, dom, M);
+}
+
+
+/* Store the "parametric constant" of row "row" of tableau "tab" in "line",
+ * i.e., the constant term and the coefficients of all variables that
+ * appear in the context tableau.
+ * Note that the coefficient of the big parameter M is NOT copied.
+ * The context tableau may not have a big parameter and even when it
+ * does, it is a different big parameter.
+ */
+static void get_row_parameter_line(struct isl_tab *tab, int row, isl_int *line)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ isl_int_set(line[0], tab->mat->row[row][1]);
+ for (i = 0; i < tab->n_param; ++i) {
+ if (tab->var[i].is_row)
+ isl_int_set_si(line[1 + i], 0);
+ else {
+ int col = tab->var[i].index;
+ isl_int_set(line[1 + i], tab->mat->row[row][off + col]);
+ }
+ }
+ for (i = 0; i < tab->n_div; ++i) {
+ if (tab->var[tab->n_var - tab->n_div + i].is_row)
+ isl_int_set_si(line[1 + tab->n_param + i], 0);
+ else {
+ int col = tab->var[tab->n_var - tab->n_div + i].index;
+ isl_int_set(line[1 + tab->n_param + i],
+ tab->mat->row[row][off + col]);
+ }
+ }
+}
+
+/* Check if rows "row1" and "row2" have identical "parametric constants",
+ * as explained above.
+ * In this case, we also insist that the coefficients of the big parameter
+ * be the same as the values of the constants will only be the same
+ * if these coefficients are also the same.
+ */
+static int identical_parameter_line(struct isl_tab *tab, int row1, int row2)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ if (isl_int_ne(tab->mat->row[row1][1], tab->mat->row[row2][1]))
+ return 0;
+
+ if (tab->M && isl_int_ne(tab->mat->row[row1][2],
+ tab->mat->row[row2][2]))
+ return 0;
+
+ for (i = 0; i < tab->n_param + tab->n_div; ++i) {
+ int pos = i < tab->n_param ? i :
+ tab->n_var - tab->n_div + i - tab->n_param;
+ int col;
+
+ if (tab->var[pos].is_row)
+ continue;
+ col = tab->var[pos].index;
+ if (isl_int_ne(tab->mat->row[row1][off + col],
+ tab->mat->row[row2][off + col]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Return an inequality that expresses that the "parametric constant"
+ * should be non-negative.
+ * This function is only called when the coefficient of the big parameter
+ * is equal to zero.
+ */
+static struct isl_vec *get_row_parameter_ineq(struct isl_tab *tab, int row)
+{
+ struct isl_vec *ineq;
+
+ ineq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_param + tab->n_div);
+ if (!ineq)
+ return NULL;
+
+ get_row_parameter_line(tab, row, ineq->el);
+ if (ineq)
+ ineq = isl_vec_normalize(ineq);
+
+ return ineq;
+}
+
+/* Normalize a div expression of the form
+ *
+ * [(g*f(x) + c)/(g * m)]
+ *
+ * with c the constant term and f(x) the remaining coefficients, to
+ *
+ * [(f(x) + [c/g])/m]
+ */
+static void normalize_div(__isl_keep isl_vec *div)
+{
+ isl_ctx *ctx = isl_vec_get_ctx(div);
+ int len = div->size - 2;
+
+ isl_seq_gcd(div->el + 2, len, &ctx->normalize_gcd);
+ isl_int_gcd(ctx->normalize_gcd, ctx->normalize_gcd, div->el[0]);
+
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return;
+
+ isl_int_divexact(div->el[0], div->el[0], ctx->normalize_gcd);
+ isl_int_fdiv_q(div->el[1], div->el[1], ctx->normalize_gcd);
+ isl_seq_scale_down(div->el + 2, div->el + 2, ctx->normalize_gcd, len);
+}
+
+/* Return a integer division for use in a parametric cut based on the given row.
+ * In particular, let the parametric constant of the row be
+ *
+ * \sum_i a_i y_i
+ *
+ * where y_0 = 1, but none of the y_i corresponds to the big parameter M.
+ * The div returned is equal to
+ *
+ * floor(\sum_i {-a_i} y_i) = floor((\sum_i (-a_i mod d) y_i)/d)
+ */
+static struct isl_vec *get_row_parameter_div(struct isl_tab *tab, int row)
+{
+ struct isl_vec *div;
+
+ div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div);
+ if (!div)
+ return NULL;
+
+ isl_int_set(div->el[0], tab->mat->row[row][0]);
+ get_row_parameter_line(tab, row, div->el + 1);
+ isl_seq_neg(div->el + 1, div->el + 1, div->size - 1);
+ normalize_div(div);
+ isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1);
+
+ return div;
+}
+
+/* Return a integer division for use in transferring an integrality constraint
+ * to the context.
+ * In particular, let the parametric constant of the row be
+ *
+ * \sum_i a_i y_i
+ *
+ * where y_0 = 1, but none of the y_i corresponds to the big parameter M.
+ * The the returned div is equal to
+ *
+ * floor(\sum_i {a_i} y_i) = floor((\sum_i (a_i mod d) y_i)/d)
+ */
+static struct isl_vec *get_row_split_div(struct isl_tab *tab, int row)
+{
+ struct isl_vec *div;
+
+ div = isl_vec_alloc(tab->mat->ctx, 1 + 1 + tab->n_param + tab->n_div);
+ if (!div)
+ return NULL;
+
+ isl_int_set(div->el[0], tab->mat->row[row][0]);
+ get_row_parameter_line(tab, row, div->el + 1);
+ normalize_div(div);
+ isl_seq_fdiv_r(div->el + 1, div->el + 1, div->el[0], div->size - 1);
+
+ return div;
+}
+
+/* Construct and return an inequality that expresses an upper bound
+ * on the given div.
+ * In particular, if the div is given by
+ *
+ * d = floor(e/m)
+ *
+ * then the inequality expresses
+ *
+ * m d <= e
+ */
+static struct isl_vec *ineq_for_div(struct isl_basic_set *bset, unsigned div)
+{
+ unsigned total;
+ unsigned div_pos;
+ struct isl_vec *ineq;
+
+ if (!bset)
+ return NULL;
+
+ total = isl_basic_set_total_dim(bset);
+ div_pos = 1 + total - bset->n_div + div;
+
+ ineq = isl_vec_alloc(bset->ctx, 1 + total);
+ if (!ineq)
+ return NULL;
+
+ isl_seq_cpy(ineq->el, bset->div[div] + 1, 1 + total);
+ isl_int_neg(ineq->el[div_pos], bset->div[div][0]);
+ return ineq;
+}
+
+/* Given a row in the tableau and a div that was created
+ * using get_row_split_div and that has been constrained to equality, i.e.,
+ *
+ * d = floor(\sum_i {a_i} y_i) = \sum_i {a_i} y_i
+ *
+ * replace the expression "\sum_i {a_i} y_i" in the row by d,
+ * i.e., we subtract "\sum_i {a_i} y_i" and add 1 d.
+ * The coefficients of the non-parameters in the tableau have been
+ * verified to be integral. We can therefore simply replace coefficient b
+ * by floor(b). For the coefficients of the parameters we have
+ * floor(a_i) = a_i - {a_i}, while for the other coefficients, we have
+ * floor(b) = b.
+ */
+static struct isl_tab *set_row_cst_to_div(struct isl_tab *tab, int row, int div)
+{
+ isl_seq_fdiv_q(tab->mat->row[row] + 1, tab->mat->row[row] + 1,
+ tab->mat->row[row][0], 1 + tab->M + tab->n_col);
+
+ isl_int_set_si(tab->mat->row[row][0], 1);
+
+ if (tab->var[tab->n_var - tab->n_div + div].is_row) {
+ int drow = tab->var[tab->n_var - tab->n_div + div].index;
+
+ isl_assert(tab->mat->ctx,
+ isl_int_is_one(tab->mat->row[drow][0]), goto error);
+ isl_seq_combine(tab->mat->row[row] + 1,
+ tab->mat->ctx->one, tab->mat->row[row] + 1,
+ tab->mat->ctx->one, tab->mat->row[drow] + 1,
+ 1 + tab->M + tab->n_col);
+ } else {
+ int dcol = tab->var[tab->n_var - tab->n_div + div].index;
+
+ isl_int_add_ui(tab->mat->row[row][2 + tab->M + dcol],
+ tab->mat->row[row][2 + tab->M + dcol], 1);
+ }
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check if the (parametric) constant of the given row is obviously
+ * negative, meaning that we don't need to consult the context tableau.
+ * If there is a big parameter and its coefficient is non-zero,
+ * then this coefficient determines the outcome.
+ * Otherwise, we check whether the constant is negative and
+ * all non-zero coefficients of parameters are negative and
+ * belong to non-negative parameters.
+ */
+static int is_obviously_neg(struct isl_tab *tab, int row)
+{
+ int i;
+ int col;
+ unsigned off = 2 + tab->M;
+
+ if (tab->M) {
+ if (isl_int_is_pos(tab->mat->row[row][2]))
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][2]))
+ return 1;
+ }
+
+ if (isl_int_is_nonneg(tab->mat->row[row][1]))
+ return 0;
+ for (i = 0; i < tab->n_param; ++i) {
+ /* Eliminated parameter */
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (!tab->var[i].is_nonneg)
+ return 0;
+ if (isl_int_is_pos(tab->mat->row[row][off + col]))
+ return 0;
+ }
+ for (i = 0; i < tab->n_div; ++i) {
+ if (tab->var[tab->n_var - tab->n_div + i].is_row)
+ continue;
+ col = tab->var[tab->n_var - tab->n_div + i].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg)
+ return 0;
+ if (isl_int_is_pos(tab->mat->row[row][off + col]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if the (parametric) constant of the given row is obviously
+ * non-negative, meaning that we don't need to consult the context tableau.
+ * If there is a big parameter and its coefficient is non-zero,
+ * then this coefficient determines the outcome.
+ * Otherwise, we check whether the constant is non-negative and
+ * all non-zero coefficients of parameters are positive and
+ * belong to non-negative parameters.
+ */
+static int is_obviously_nonneg(struct isl_tab *tab, int row)
+{
+ int i;
+ int col;
+ unsigned off = 2 + tab->M;
+
+ if (tab->M) {
+ if (isl_int_is_pos(tab->mat->row[row][2]))
+ return 1;
+ if (isl_int_is_neg(tab->mat->row[row][2]))
+ return 0;
+ }
+
+ if (isl_int_is_neg(tab->mat->row[row][1]))
+ return 0;
+ for (i = 0; i < tab->n_param; ++i) {
+ /* Eliminated parameter */
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (!tab->var[i].is_nonneg)
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][off + col]))
+ return 0;
+ }
+ for (i = 0; i < tab->n_div; ++i) {
+ if (tab->var[tab->n_var - tab->n_div + i].is_row)
+ continue;
+ col = tab->var[tab->n_var - tab->n_div + i].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (!tab->var[tab->n_var - tab->n_div + i].is_nonneg)
+ return 0;
+ if (isl_int_is_neg(tab->mat->row[row][off + col]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Given a row r and two columns, return the column that would
+ * lead to the lexicographically smallest increment in the sample
+ * solution when leaving the basis in favor of the row.
+ * Pivoting with column c will increment the sample value by a non-negative
+ * constant times a_{V,c}/a_{r,c}, with a_{V,c} the elements of column c
+ * corresponding to the non-parametric variables.
+ * If variable v appears in a column c_v, the a_{v,c} = 1 iff c = c_v,
+ * with all other entries in this virtual row equal to zero.
+ * If variable v appears in a row, then a_{v,c} is the element in column c
+ * of that row.
+ *
+ * Let v be the first variable with a_{v,c1}/a_{r,c1} != a_{v,c2}/a_{r,c2}.
+ * Then if a_{v,c1}/a_{r,c1} < a_{v,c2}/a_{r,c2}, i.e.,
+ * a_{v,c2} a_{r,c1} - a_{v,c1} a_{r,c2} > 0, c1 results in the minimal
+ * increment. Otherwise, it's c2.
+ */
+static int lexmin_col_pair(struct isl_tab *tab,
+ int row, int col1, int col2, isl_int tmp)
+{
+ int i;
+ isl_int *tr;
+
+ tr = tab->mat->row[row] + 2 + tab->M;
+
+ for (i = tab->n_param; i < tab->n_var - tab->n_div; ++i) {
+ int s1, s2;
+ isl_int *r;
+
+ if (!tab->var[i].is_row) {
+ if (tab->var[i].index == col1)
+ return col2;
+ if (tab->var[i].index == col2)
+ return col1;
+ continue;
+ }
+
+ if (tab->var[i].index == row)
+ continue;
+
+ r = tab->mat->row[tab->var[i].index] + 2 + tab->M;
+ s1 = isl_int_sgn(r[col1]);
+ s2 = isl_int_sgn(r[col2]);
+ if (s1 == 0 && s2 == 0)
+ continue;
+ if (s1 < s2)
+ return col1;
+ if (s2 < s1)
+ return col2;
+
+ isl_int_mul(tmp, r[col2], tr[col1]);
+ isl_int_submul(tmp, r[col1], tr[col2]);
+ if (isl_int_is_pos(tmp))
+ return col1;
+ if (isl_int_is_neg(tmp))
+ return col2;
+ }
+ return -1;
+}
+
+/* Given a row in the tableau, find and return the column that would
+ * result in the lexicographically smallest, but positive, increment
+ * in the sample point.
+ * If there is no such column, then return tab->n_col.
+ * If anything goes wrong, return -1.
+ */
+static int lexmin_pivot_col(struct isl_tab *tab, int row)
+{
+ int j;
+ int col = tab->n_col;
+ isl_int *tr;
+ isl_int tmp;
+
+ tr = tab->mat->row[row] + 2 + tab->M;
+
+ isl_int_init(tmp);
+
+ for (j = tab->n_dead; j < tab->n_col; ++j) {
+ if (tab->col_var[j] >= 0 &&
+ (tab->col_var[j] < tab->n_param ||
+ tab->col_var[j] >= tab->n_var - tab->n_div))
+ continue;
+
+ if (!isl_int_is_pos(tr[j]))
+ continue;
+
+ if (col == tab->n_col)
+ col = j;
+ else
+ col = lexmin_col_pair(tab, row, col, j, tmp);
+ isl_assert(tab->mat->ctx, col >= 0, goto error);
+ }
+
+ isl_int_clear(tmp);
+ return col;
+error:
+ isl_int_clear(tmp);
+ return -1;
+}
+
+/* Return the first known violated constraint, i.e., a non-negative
+ * constraint that currently has an either obviously negative value
+ * or a previously determined to be negative value.
+ *
+ * If any constraint has a negative coefficient for the big parameter,
+ * if any, then we return one of these first.
+ */
+static int first_neg(struct isl_tab *tab)
+{
+ int row;
+
+ if (tab->M)
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+ continue;
+ if (!isl_int_is_neg(tab->mat->row[row][2]))
+ continue;
+ if (tab->row_sign)
+ tab->row_sign[row] = isl_tab_row_neg;
+ return row;
+ }
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+ continue;
+ if (tab->row_sign) {
+ if (tab->row_sign[row] == 0 &&
+ is_obviously_neg(tab, row))
+ tab->row_sign[row] = isl_tab_row_neg;
+ if (tab->row_sign[row] != isl_tab_row_neg)
+ continue;
+ } else if (!is_obviously_neg(tab, row))
+ continue;
+ return row;
+ }
+ return -1;
+}
+
+/* Check whether the invariant that all columns are lexico-positive
+ * is satisfied. This function is not called from the current code
+ * but is useful during debugging.
+ */
+static void check_lexpos(struct isl_tab *tab) __attribute__ ((unused));
+static void check_lexpos(struct isl_tab *tab)
+{
+ unsigned off = 2 + tab->M;
+ int col;
+ int var;
+ int row;
+
+ for (col = tab->n_dead; col < tab->n_col; ++col) {
+ if (tab->col_var[col] >= 0 &&
+ (tab->col_var[col] < tab->n_param ||
+ tab->col_var[col] >= tab->n_var - tab->n_div))
+ continue;
+ for (var = tab->n_param; var < tab->n_var - tab->n_div; ++var) {
+ if (!tab->var[var].is_row) {
+ if (tab->var[var].index == col)
+ break;
+ else
+ continue;
+ }
+ row = tab->var[var].index;
+ if (isl_int_is_zero(tab->mat->row[row][off + col]))
+ continue;
+ if (isl_int_is_pos(tab->mat->row[row][off + col]))
+ break;
+ fprintf(stderr, "lexneg column %d (row %d)\n",
+ col, row);
+ }
+ if (var >= tab->n_var - tab->n_div)
+ fprintf(stderr, "zero column %d\n", col);
+ }
+}
+
+/* Report to the caller that the given constraint is part of an encountered
+ * conflict.
+ */
+static int report_conflicting_constraint(struct isl_tab *tab, int con)
+{
+ return tab->conflict(con, tab->conflict_user);
+}
+
+/* Given a conflicting row in the tableau, report all constraints
+ * involved in the row to the caller. That is, the row itself
+ * (if it represents a constraint) and all constraint columns with
+ * non-zero (and therefore negative) coefficients.
+ */
+static int report_conflict(struct isl_tab *tab, int row)
+{
+ int j;
+ isl_int *tr;
+
+ if (!tab->conflict)
+ return 0;
+
+ if (tab->row_var[row] < 0 &&
+ report_conflicting_constraint(tab, ~tab->row_var[row]) < 0)
+ return -1;
+
+ tr = tab->mat->row[row] + 2 + tab->M;
+
+ for (j = tab->n_dead; j < tab->n_col; ++j) {
+ if (tab->col_var[j] >= 0 &&
+ (tab->col_var[j] < tab->n_param ||
+ tab->col_var[j] >= tab->n_var - tab->n_div))
+ continue;
+
+ if (!isl_int_is_neg(tr[j]))
+ continue;
+
+ if (tab->col_var[j] < 0 &&
+ report_conflicting_constraint(tab, ~tab->col_var[j]) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Resolve all known or obviously violated constraints through pivoting.
+ * In particular, as long as we can find any violated constraint, we
+ * look for a pivoting column that would result in the lexicographically
+ * smallest increment in the sample point. If there is no such column
+ * then the tableau is infeasible.
+ */
+static int restore_lexmin(struct isl_tab *tab) WARN_UNUSED;
+static int restore_lexmin(struct isl_tab *tab)
+{
+ int row, col;
+
+ if (!tab)
+ return -1;
+ if (tab->empty)
+ return 0;
+ while ((row = first_neg(tab)) != -1) {
+ col = lexmin_pivot_col(tab, row);
+ if (col >= tab->n_col) {
+ if (report_conflict(tab, row) < 0)
+ return -1;
+ if (isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+ }
+ if (col < 0)
+ return -1;
+ if (isl_tab_pivot(tab, row, col) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+/* Given a row that represents an equality, look for an appropriate
+ * pivoting column.
+ * In particular, if there are any non-zero coefficients among
+ * the non-parameter variables, then we take the last of these
+ * variables. Eliminating this variable in terms of the other
+ * variables and/or parameters does not influence the property
+ * that all column in the initial tableau are lexicographically
+ * positive. The row corresponding to the eliminated variable
+ * will only have non-zero entries below the diagonal of the
+ * initial tableau. That is, we transform
+ *
+ * I I
+ * 1 into a
+ * I I
+ *
+ * If there is no such non-parameter variable, then we are dealing with
+ * pure parameter equality and we pick any parameter with coefficient 1 or -1
+ * for elimination. This will ensure that the eliminated parameter
+ * always has an integer value whenever all the other parameters are integral.
+ * If there is no such parameter then we return -1.
+ */
+static int last_var_col_or_int_par_col(struct isl_tab *tab, int row)
+{
+ unsigned off = 2 + tab->M;
+ int i;
+
+ for (i = tab->n_var - tab->n_div - 1; i >= 0 && i >= tab->n_param; --i) {
+ int col;
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ if (col <= tab->n_dead)
+ continue;
+ if (!isl_int_is_zero(tab->mat->row[row][off + col]))
+ return col;
+ }
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ if (isl_int_is_one(tab->mat->row[row][off + i]))
+ return i;
+ if (isl_int_is_negone(tab->mat->row[row][off + i]))
+ return i;
+ }
+ return -1;
+}
+
+/* Add an equality that is known to be valid to the tableau.
+ * We first check if we can eliminate a variable or a parameter.
+ * If not, we add the equality as two inequalities.
+ * In this case, the equality was a pure parameter equality and there
+ * is no need to resolve any constraint violations.
+ */
+static struct isl_tab *add_lexmin_valid_eq(struct isl_tab *tab, isl_int *eq)
+{
+ int i;
+ int r;
+
+ if (!tab)
+ return NULL;
+ r = isl_tab_add_row(tab, eq);
+ if (r < 0)
+ goto error;
+
+ r = tab->con[r].index;
+ i = last_var_col_or_int_par_col(tab, r);
+ if (i < 0) {
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ goto error;
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+ r = isl_tab_add_row(tab, eq);
+ if (r < 0)
+ goto error;
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ goto error;
+ } else {
+ if (isl_tab_pivot(tab, r, i) < 0)
+ goto error;
+ if (isl_tab_kill_col(tab, i) < 0)
+ goto error;
+ tab->n_eq++;
+ }
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check if the given row is a pure constant.
+ */
+static int is_constant(struct isl_tab *tab, int row)
+{
+ unsigned off = 2 + tab->M;
+
+ return isl_seq_first_non_zero(tab->mat->row[row] + off + tab->n_dead,
+ tab->n_col - tab->n_dead) == -1;
+}
+
+/* Add an equality that may or may not be valid to the tableau.
+ * If the resulting row is a pure constant, then it must be zero.
+ * Otherwise, the resulting tableau is empty.
+ *
+ * If the row is not a pure constant, then we add two inequalities,
+ * each time checking that they can be satisfied.
+ * In the end we try to use one of the two constraints to eliminate
+ * a column.
+ */
+static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq) WARN_UNUSED;
+static int add_lexmin_eq(struct isl_tab *tab, isl_int *eq)
+{
+ int r1, r2;
+ int row;
+ struct isl_tab_undo *snap;
+
+ if (!tab)
+ return -1;
+ snap = isl_tab_snap(tab);
+ r1 = isl_tab_add_row(tab, eq);
+ if (r1 < 0)
+ return -1;
+ tab->con[r1].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r1]) < 0)
+ return -1;
+
+ row = tab->con[r1].index;
+ if (is_constant(tab, row)) {
+ if (!isl_int_is_zero(tab->mat->row[row][1]) ||
+ (tab->M && !isl_int_is_zero(tab->mat->row[row][2]))) {
+ if (isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+ }
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ return 0;
+ }
+
+ if (restore_lexmin(tab) < 0)
+ return -1;
+ if (tab->empty)
+ return 0;
+
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+
+ r2 = isl_tab_add_row(tab, eq);
+ if (r2 < 0)
+ return -1;
+ tab->con[r2].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r2]) < 0)
+ return -1;
+
+ if (restore_lexmin(tab) < 0)
+ return -1;
+ if (tab->empty)
+ return 0;
+
+ if (!tab->con[r1].is_row) {
+ if (isl_tab_kill_col(tab, tab->con[r1].index) < 0)
+ return -1;
+ } else if (!tab->con[r2].is_row) {
+ if (isl_tab_kill_col(tab, tab->con[r2].index) < 0)
+ return -1;
+ }
+
+ if (tab->bmap) {
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ return -1;
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, eq);
+ isl_seq_neg(eq, eq, 1 + tab->n_var);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ return -1;
+ if (!tab->bmap)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Add an inequality to the tableau, resolving violations using
+ * restore_lexmin.
+ */
+static struct isl_tab *add_lexmin_ineq(struct isl_tab *tab, isl_int *ineq)
+{
+ int r;
+
+ if (!tab)
+ return NULL;
+ if (tab->bmap) {
+ tab->bmap = isl_basic_map_add_ineq(tab->bmap, ineq);
+ if (isl_tab_push(tab, isl_tab_undo_bmap_ineq) < 0)
+ goto error;
+ if (!tab->bmap)
+ goto error;
+ }
+ r = isl_tab_add_row(tab, ineq);
+ if (r < 0)
+ goto error;
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ goto error;
+ if (isl_tab_row_is_redundant(tab, tab->con[r].index)) {
+ if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+ goto error;
+ return tab;
+ }
+
+ if (restore_lexmin(tab) < 0)
+ goto error;
+ if (!tab->empty && tab->con[r].is_row &&
+ isl_tab_row_is_redundant(tab, tab->con[r].index))
+ if (isl_tab_mark_redundant(tab, tab->con[r].index) < 0)
+ goto error;
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check if the coefficients of the parameters are all integral.
+ */
+static int integer_parameter(struct isl_tab *tab, int row)
+{
+ int i;
+ int col;
+ unsigned off = 2 + tab->M;
+
+ for (i = 0; i < tab->n_param; ++i) {
+ /* Eliminated parameter */
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ if (!isl_int_is_divisible_by(tab->mat->row[row][off + col],
+ tab->mat->row[row][0]))
+ return 0;
+ }
+ for (i = 0; i < tab->n_div; ++i) {
+ if (tab->var[tab->n_var - tab->n_div + i].is_row)
+ continue;
+ col = tab->var[tab->n_var - tab->n_div + i].index;
+ if (!isl_int_is_divisible_by(tab->mat->row[row][off + col],
+ tab->mat->row[row][0]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if the coefficients of the non-parameter variables are all integral.
+ */
+static int integer_variable(struct isl_tab *tab, int row)
+{
+ int i;
+ unsigned off = 2 + tab->M;
+
+ for (i = tab->n_dead; i < tab->n_col; ++i) {
+ if (tab->col_var[i] >= 0 &&
+ (tab->col_var[i] < tab->n_param ||
+ tab->col_var[i] >= tab->n_var - tab->n_div))
+ continue;
+ if (!isl_int_is_divisible_by(tab->mat->row[row][off + i],
+ tab->mat->row[row][0]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if the constant term is integral.
+ */
+static int integer_constant(struct isl_tab *tab, int row)
+{
+ return isl_int_is_divisible_by(tab->mat->row[row][1],
+ tab->mat->row[row][0]);
+}
+
+#define I_CST 1 << 0
+#define I_PAR 1 << 1
+#define I_VAR 1 << 2
+
+/* Check for next (non-parameter) variable after "var" (first if var == -1)
+ * that is non-integer and therefore requires a cut and return
+ * the index of the variable.
+ * For parametric tableaus, there are three parts in a row,
+ * the constant, the coefficients of the parameters and the rest.
+ * For each part, we check whether the coefficients in that part
+ * are all integral and if so, set the corresponding flag in *f.
+ * If the constant and the parameter part are integral, then the
+ * current sample value is integral and no cut is required
+ * (irrespective of whether the variable part is integral).
+ */
+static int next_non_integer_var(struct isl_tab *tab, int var, int *f)
+{
+ var = var < 0 ? tab->n_param : var + 1;
+
+ for (; var < tab->n_var - tab->n_div; ++var) {
+ int flags = 0;
+ int row;
+ if (!tab->var[var].is_row)
+ continue;
+ row = tab->var[var].index;
+ if (integer_constant(tab, row))
+ ISL_FL_SET(flags, I_CST);
+ if (integer_parameter(tab, row))
+ ISL_FL_SET(flags, I_PAR);
+ if (ISL_FL_ISSET(flags, I_CST) && ISL_FL_ISSET(flags, I_PAR))
+ continue;
+ if (integer_variable(tab, row))
+ ISL_FL_SET(flags, I_VAR);
+ *f = flags;
+ return var;
+ }
+ return -1;
+}
+
+/* Check for first (non-parameter) variable that is non-integer and
+ * therefore requires a cut and return the corresponding row.
+ * For parametric tableaus, there are three parts in a row,
+ * the constant, the coefficients of the parameters and the rest.
+ * For each part, we check whether the coefficients in that part
+ * are all integral and if so, set the corresponding flag in *f.
+ * If the constant and the parameter part are integral, then the
+ * current sample value is integral and no cut is required
+ * (irrespective of whether the variable part is integral).
+ */
+static int first_non_integer_row(struct isl_tab *tab, int *f)
+{
+ int var = next_non_integer_var(tab, -1, f);
+
+ return var < 0 ? -1 : tab->var[var].index;
+}
+
+/* Add a (non-parametric) cut to cut away the non-integral sample
+ * value of the given row.
+ *
+ * If the row is given by
+ *
+ * m r = f + \sum_i a_i y_i
+ *
+ * then the cut is
+ *
+ * c = - {-f/m} + \sum_i {a_i/m} y_i >= 0
+ *
+ * The big parameter, if any, is ignored, since it is assumed to be big
+ * enough to be divisible by any integer.
+ * If the tableau is actually a parametric tableau, then this function
+ * is only called when all coefficients of the parameters are integral.
+ * The cut therefore has zero coefficients for the parameters.
+ *
+ * The current value is known to be negative, so row_sign, if it
+ * exists, is set accordingly.
+ *
+ * Return the row of the cut or -1.
+ */
+static int add_cut(struct isl_tab *tab, int row)
+{
+ int i;
+ int r;
+ isl_int *r_row;
+ unsigned off = 2 + tab->M;
+
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ return -1;
+ r = isl_tab_allocate_con(tab);
+ if (r < 0)
+ return -1;
+
+ r_row = tab->mat->row[tab->con[r].index];
+ isl_int_set(r_row[0], tab->mat->row[row][0]);
+ isl_int_neg(r_row[1], tab->mat->row[row][1]);
+ isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]);
+ isl_int_neg(r_row[1], r_row[1]);
+ if (tab->M)
+ isl_int_set_si(r_row[2], 0);
+ for (i = 0; i < tab->n_col; ++i)
+ isl_int_fdiv_r(r_row[off + i],
+ tab->mat->row[row][off + i], tab->mat->row[row][0]);
+
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ return -1;
+ if (tab->row_sign)
+ tab->row_sign[tab->con[r].index] = isl_tab_row_neg;
+
+ return tab->con[r].index;
+}
+
+#define CUT_ALL 1
+#define CUT_ONE 0
+
+/* Given a non-parametric tableau, add cuts until an integer
+ * sample point is obtained or until the tableau is determined
+ * to be integer infeasible.
+ * As long as there is any non-integer value in the sample point,
+ * we add appropriate cuts, if possible, for each of these
+ * non-integer values and then resolve the violated
+ * cut constraints using restore_lexmin.
+ * If one of the corresponding rows is equal to an integral
+ * combination of variables/constraints plus a non-integral constant,
+ * then there is no way to obtain an integer point and we return
+ * a tableau that is marked empty.
+ * The parameter cutting_strategy controls the strategy used when adding cuts
+ * to remove non-integer points. CUT_ALL adds all possible cuts
+ * before continuing the search. CUT_ONE adds only one cut at a time.
+ */
+static struct isl_tab *cut_to_integer_lexmin(struct isl_tab *tab,
+ int cutting_strategy)
+{
+ int var;
+ int row;
+ int flags;
+
+ if (!tab)
+ return NULL;
+ if (tab->empty)
+ return tab;
+
+ while ((var = next_non_integer_var(tab, -1, &flags)) != -1) {
+ do {
+ if (ISL_FL_ISSET(flags, I_VAR)) {
+ if (isl_tab_mark_empty(tab) < 0)
+ goto error;
+ return tab;
+ }
+ row = tab->var[var].index;
+ row = add_cut(tab, row);
+ if (row < 0)
+ goto error;
+ if (cutting_strategy == CUT_ONE)
+ break;
+ } while ((var = next_non_integer_var(tab, var, &flags)) != -1);
+ if (restore_lexmin(tab) < 0)
+ goto error;
+ if (tab->empty)
+ break;
+ }
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check whether all the currently active samples also satisfy the inequality
+ * "ineq" (treated as an equality if eq is set).
+ * Remove those samples that do not.
+ */
+static struct isl_tab *check_samples(struct isl_tab *tab, isl_int *ineq, int eq)
+{
+ int i;
+ isl_int v;
+
+ if (!tab)
+ return NULL;
+
+ isl_assert(tab->mat->ctx, tab->bmap, goto error);
+ isl_assert(tab->mat->ctx, tab->samples, goto error);
+ isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, goto error);
+
+ isl_int_init(v);
+ for (i = tab->n_outside; i < tab->n_sample; ++i) {
+ int sgn;
+ isl_seq_inner_product(ineq, tab->samples->row[i],
+ 1 + tab->n_var, &v);
+ sgn = isl_int_sgn(v);
+ if (eq ? (sgn == 0) : (sgn >= 0))
+ continue;
+ tab = isl_tab_drop_sample(tab, i);
+ if (!tab)
+ break;
+ }
+ isl_int_clear(v);
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check whether the sample value of the tableau is finite,
+ * i.e., either the tableau does not use a big parameter, or
+ * all values of the variables are equal to the big parameter plus
+ * some constant. This constant is the actual sample value.
+ */
+static int sample_is_finite(struct isl_tab *tab)
+{
+ int i;
+
+ if (!tab->M)
+ return 1;
+
+ for (i = 0; i < tab->n_var; ++i) {
+ int row;
+ if (!tab->var[i].is_row)
+ return 0;
+ row = tab->var[i].index;
+ if (isl_int_ne(tab->mat->row[row][0], tab->mat->row[row][2]))
+ return 0;
+ }
+ return 1;
+}
+
+/* Check if the context tableau of sol has any integer points.
+ * Leave tab in empty state if no integer point can be found.
+ * If an integer point can be found and if moreover it is finite,
+ * then it is added to the list of sample values.
+ *
+ * This function is only called when none of the currently active sample
+ * values satisfies the most recently added constraint.
+ */
+static struct isl_tab *check_integer_feasible(struct isl_tab *tab)
+{
+ struct isl_tab_undo *snap;
+
+ if (!tab)
+ return NULL;
+
+ snap = isl_tab_snap(tab);
+ if (isl_tab_push_basis(tab) < 0)
+ goto error;
+
+ tab = cut_to_integer_lexmin(tab, CUT_ALL);
+ if (!tab)
+ goto error;
+
+ if (!tab->empty && sample_is_finite(tab)) {
+ struct isl_vec *sample;
+
+ sample = isl_tab_get_sample_value(tab);
+
+ if (isl_tab_add_sample(tab, sample) < 0)
+ goto error;
+ }
+
+ if (!tab->empty && isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Check if any of the currently active sample values satisfies
+ * the inequality "ineq" (an equality if eq is set).
+ */
+static int tab_has_valid_sample(struct isl_tab *tab, isl_int *ineq, int eq)
+{
+ int i;
+ isl_int v;
+
+ if (!tab)
+ return -1;
+
+ isl_assert(tab->mat->ctx, tab->bmap, return -1);
+ isl_assert(tab->mat->ctx, tab->samples, return -1);
+ isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, return -1);
+
+ isl_int_init(v);
+ for (i = tab->n_outside; i < tab->n_sample; ++i) {
+ int sgn;
+ isl_seq_inner_product(ineq, tab->samples->row[i],
+ 1 + tab->n_var, &v);
+ sgn = isl_int_sgn(v);
+ if (eq ? (sgn == 0) : (sgn >= 0))
+ break;
+ }
+ isl_int_clear(v);
+
+ return i < tab->n_sample;
+}
+
+/* Add a div specified by "div" to the tableau "tab" and return
+ * 1 if the div is obviously non-negative.
+ */
+static int context_tab_add_div(struct isl_tab *tab, struct isl_vec *div,
+ int (*add_ineq)(void *user, isl_int *), void *user)
+{
+ int i;
+ int r;
+ struct isl_mat *samples;
+ int nonneg;
+
+ r = isl_tab_add_div(tab, div, add_ineq, user);
+ if (r < 0)
+ return -1;
+ nonneg = tab->var[r].is_nonneg;
+ tab->var[r].frozen = 1;
+
+ samples = isl_mat_extend(tab->samples,
+ tab->n_sample, 1 + tab->n_var);
+ tab->samples = samples;
+ if (!samples)
+ return -1;
+ for (i = tab->n_outside; i < samples->n_row; ++i) {
+ isl_seq_inner_product(div->el + 1, samples->row[i],
+ div->size - 1, &samples->row[i][samples->n_col - 1]);
+ isl_int_fdiv_q(samples->row[i][samples->n_col - 1],
+ samples->row[i][samples->n_col - 1], div->el[0]);
+ }
+
+ return nonneg;
+}
+
+/* Add a div specified by "div" to both the main tableau and
+ * the context tableau. In case of the main tableau, we only
+ * need to add an extra div. In the context tableau, we also
+ * need to express the meaning of the div.
+ * Return the index of the div or -1 if anything went wrong.
+ */
+static int add_div(struct isl_tab *tab, struct isl_context *context,
+ struct isl_vec *div)
+{
+ int r;
+ int nonneg;
+
+ if ((nonneg = context->op->add_div(context, div)) < 0)
+ goto error;
+
+ if (!context->op->is_ok(context))
+ goto error;
+
+ if (isl_tab_extend_vars(tab, 1) < 0)
+ goto error;
+ r = isl_tab_allocate_var(tab);
+ if (r < 0)
+ goto error;
+ if (nonneg)
+ tab->var[r].is_nonneg = 1;
+ tab->var[r].frozen = 1;
+ tab->n_div++;
+
+ return tab->n_div - 1;
+error:
+ context->op->invalidate(context);
+ return -1;
+}
+
+static int find_div(struct isl_tab *tab, isl_int *div, isl_int denom)
+{
+ int i;
+ unsigned total = isl_basic_map_total_dim(tab->bmap);
+
+ for (i = 0; i < tab->bmap->n_div; ++i) {
+ if (isl_int_ne(tab->bmap->div[i][0], denom))
+ continue;
+ if (!isl_seq_eq(tab->bmap->div[i] + 1, div, 1 + total))
+ continue;
+ return i;
+ }
+ return -1;
+}
+
+/* Return the index of a div that corresponds to "div".
+ * We first check if we already have such a div and if not, we create one.
+ */
+static int get_div(struct isl_tab *tab, struct isl_context *context,
+ struct isl_vec *div)
+{
+ int d;
+ struct isl_tab *context_tab = context->op->peek_tab(context);
+
+ if (!context_tab)
+ return -1;
+
+ d = find_div(context_tab, div->el + 1, div->el[0]);
+ if (d != -1)
+ return d;
+
+ return add_div(tab, context, div);
+}
+
+/* Add a parametric cut to cut away the non-integral sample value
+ * of the give row.
+ * Let a_i be the coefficients of the constant term and the parameters
+ * and let b_i be the coefficients of the variables or constraints
+ * in basis of the tableau.
+ * Let q be the div q = floor(\sum_i {-a_i} y_i).
+ *
+ * The cut is expressed as
+ *
+ * c = \sum_i -{-a_i} y_i + \sum_i {b_i} x_i + q >= 0
+ *
+ * If q did not already exist in the context tableau, then it is added first.
+ * If q is in a column of the main tableau then the "+ q" can be accomplished
+ * by setting the corresponding entry to the denominator of the constraint.
+ * If q happens to be in a row of the main tableau, then the corresponding
+ * row needs to be added instead (taking care of the denominators).
+ * Note that this is very unlikely, but perhaps not entirely impossible.
+ *
+ * The current value of the cut is known to be negative (or at least
+ * non-positive), so row_sign is set accordingly.
+ *
+ * Return the row of the cut or -1.
+ */
+static int add_parametric_cut(struct isl_tab *tab, int row,
+ struct isl_context *context)
+{
+ struct isl_vec *div;
+ int d;
+ int i;
+ int r;
+ isl_int *r_row;
+ int col;
+ int n;
+ unsigned off = 2 + tab->M;
+
+ if (!context)
+ return -1;
+
+ div = get_row_parameter_div(tab, row);
+ if (!div)
+ return -1;
+
+ n = tab->n_div;
+ d = context->op->get_div(context, tab, div);
+ isl_vec_free(div);
+ if (d < 0)
+ return -1;
+
+ if (isl_tab_extend_cons(tab, 1) < 0)
+ return -1;
+ r = isl_tab_allocate_con(tab);
+ if (r < 0)
+ return -1;
+
+ r_row = tab->mat->row[tab->con[r].index];
+ isl_int_set(r_row[0], tab->mat->row[row][0]);
+ isl_int_neg(r_row[1], tab->mat->row[row][1]);
+ isl_int_fdiv_r(r_row[1], r_row[1], tab->mat->row[row][0]);
+ isl_int_neg(r_row[1], r_row[1]);
+ if (tab->M)
+ isl_int_set_si(r_row[2], 0);
+ for (i = 0; i < tab->n_param; ++i) {
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]);
+ isl_int_fdiv_r(r_row[off + col], r_row[off + col],
+ tab->mat->row[row][0]);
+ isl_int_neg(r_row[off + col], r_row[off + col]);
+ }
+ for (i = 0; i < tab->n_div; ++i) {
+ if (tab->var[tab->n_var - tab->n_div + i].is_row)
+ continue;
+ col = tab->var[tab->n_var - tab->n_div + i].index;
+ isl_int_neg(r_row[off + col], tab->mat->row[row][off + col]);
+ isl_int_fdiv_r(r_row[off + col], r_row[off + col],
+ tab->mat->row[row][0]);
+ isl_int_neg(r_row[off + col], r_row[off + col]);
+ }
+ for (i = 0; i < tab->n_col; ++i) {
+ if (tab->col_var[i] >= 0 &&
+ (tab->col_var[i] < tab->n_param ||
+ tab->col_var[i] >= tab->n_var - tab->n_div))
+ continue;
+ isl_int_fdiv_r(r_row[off + i],
+ tab->mat->row[row][off + i], tab->mat->row[row][0]);
+ }
+ if (tab->var[tab->n_var - tab->n_div + d].is_row) {
+ isl_int gcd;
+ int d_row = tab->var[tab->n_var - tab->n_div + d].index;
+ isl_int_init(gcd);
+ isl_int_gcd(gcd, tab->mat->row[d_row][0], r_row[0]);
+ isl_int_divexact(r_row[0], r_row[0], gcd);
+ isl_int_divexact(gcd, tab->mat->row[d_row][0], gcd);
+ isl_seq_combine(r_row + 1, gcd, r_row + 1,
+ r_row[0], tab->mat->row[d_row] + 1,
+ off - 1 + tab->n_col);
+ isl_int_mul(r_row[0], r_row[0], tab->mat->row[d_row][0]);
+ isl_int_clear(gcd);
+ } else {
+ col = tab->var[tab->n_var - tab->n_div + d].index;
+ isl_int_set(r_row[off + col], tab->mat->row[row][0]);
+ }
+
+ tab->con[r].is_nonneg = 1;
+ if (isl_tab_push_var(tab, isl_tab_undo_nonneg, &tab->con[r]) < 0)
+ return -1;
+ if (tab->row_sign)
+ tab->row_sign[tab->con[r].index] = isl_tab_row_neg;
+
+ row = tab->con[r].index;
+
+ if (d >= n && context->op->detect_equalities(context, tab) < 0)
+ return -1;
+
+ return row;
+}
+
+/* Construct a tableau for bmap that can be used for computing
+ * the lexicographic minimum (or maximum) of bmap.
+ * If not NULL, then dom is the domain where the minimum
+ * should be computed. In this case, we set up a parametric
+ * tableau with row signs (initialized to "unknown").
+ * If M is set, then the tableau will use a big parameter.
+ * If max is set, then a maximum should be computed instead of a minimum.
+ * This means that for each variable x, the tableau will contain the variable
+ * x' = M - x, rather than x' = M + x. This in turn means that the coefficient
+ * of the variables in all constraints are negated prior to adding them
+ * to the tableau.
+ */
+static struct isl_tab *tab_for_lexmin(struct isl_basic_map *bmap,
+ struct isl_basic_set *dom, unsigned M, int max)
+{
+ int i;
+ struct isl_tab *tab;
+ unsigned n_var;
+ unsigned o_var;
+
+ tab = isl_tab_alloc(bmap->ctx, 2 * bmap->n_eq + bmap->n_ineq + 1,
+ isl_basic_map_total_dim(bmap), M);
+ if (!tab)
+ return NULL;
+
+ tab->rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+ if (dom) {
+ tab->n_param = isl_basic_set_total_dim(dom) - dom->n_div;
+ tab->n_div = dom->n_div;
+ tab->row_sign = isl_calloc_array(bmap->ctx,
+ enum isl_tab_row_sign, tab->mat->n_row);
+ if (tab->mat->n_row && !tab->row_sign)
+ goto error;
+ }
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY)) {
+ if (isl_tab_mark_empty(tab) < 0)
+ goto error;
+ return tab;
+ }
+
+ for (i = tab->n_param; i < tab->n_var - tab->n_div; ++i) {
+ tab->var[i].is_nonneg = 1;
+ tab->var[i].frozen = 1;
+ }
+ o_var = 1 + tab->n_param;
+ n_var = tab->n_var - tab->n_param - tab->n_div;
+ for (i = 0; i < bmap->n_eq; ++i) {
+ if (max)
+ isl_seq_neg(bmap->eq[i] + o_var,
+ bmap->eq[i] + o_var, n_var);
+ tab = add_lexmin_valid_eq(tab, bmap->eq[i]);
+ if (max)
+ isl_seq_neg(bmap->eq[i] + o_var,
+ bmap->eq[i] + o_var, n_var);
+ if (!tab || tab->empty)
+ return tab;
+ }
+ if (bmap->n_eq && restore_lexmin(tab) < 0)
+ goto error;
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (max)
+ isl_seq_neg(bmap->ineq[i] + o_var,
+ bmap->ineq[i] + o_var, n_var);
+ tab = add_lexmin_ineq(tab, bmap->ineq[i]);
+ if (max)
+ isl_seq_neg(bmap->ineq[i] + o_var,
+ bmap->ineq[i] + o_var, n_var);
+ if (!tab || tab->empty)
+ return tab;
+ }
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Given a main tableau where more than one row requires a split,
+ * determine and return the "best" row to split on.
+ *
+ * Given two rows in the main tableau, if the inequality corresponding
+ * to the first row is redundant with respect to that of the second row
+ * in the current tableau, then it is better to split on the second row,
+ * since in the positive part, both row will be positive.
+ * (In the negative part a pivot will have to be performed and just about
+ * anything can happen to the sign of the other row.)
+ *
+ * As a simple heuristic, we therefore select the row that makes the most
+ * of the other rows redundant.
+ *
+ * Perhaps it would also be useful to look at the number of constraints
+ * that conflict with any given constraint.
+ *
+ * best is the best row so far (-1 when we have not found any row yet).
+ * best_r is the number of other rows made redundant by row best.
+ * When best is still -1, bset_r is meaningless, but it is initialized
+ * to some arbitrary value (0) anyway. Without this redundant initialization
+ * valgrind may warn about uninitialized memory accesses when isl
+ * is compiled with some versions of gcc.
+ */
+static int best_split(struct isl_tab *tab, struct isl_tab *context_tab)
+{
+ struct isl_tab_undo *snap;
+ int split;
+ int row;
+ int best = -1;
+ int best_r = 0;
+
+ if (isl_tab_extend_cons(context_tab, 2) < 0)
+ return -1;
+
+ snap = isl_tab_snap(context_tab);
+
+ for (split = tab->n_redundant; split < tab->n_row; ++split) {
+ struct isl_tab_undo *snap2;
+ struct isl_vec *ineq = NULL;
+ int r = 0;
+ int ok;
+
+ if (!isl_tab_var_from_row(tab, split)->is_nonneg)
+ continue;
+ if (tab->row_sign[split] != isl_tab_row_any)
+ continue;
+
+ ineq = get_row_parameter_ineq(tab, split);
+ if (!ineq)
+ return -1;
+ ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0;
+ isl_vec_free(ineq);
+ if (!ok)
+ return -1;
+
+ snap2 = isl_tab_snap(context_tab);
+
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ struct isl_tab_var *var;
+
+ if (row == split)
+ continue;
+ if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+ continue;
+ if (tab->row_sign[row] != isl_tab_row_any)
+ continue;
+
+ ineq = get_row_parameter_ineq(tab, row);
+ if (!ineq)
+ return -1;
+ ok = isl_tab_add_ineq(context_tab, ineq->el) >= 0;
+ isl_vec_free(ineq);
+ if (!ok)
+ return -1;
+ var = &context_tab->con[context_tab->n_con - 1];
+ if (!context_tab->empty &&
+ !isl_tab_min_at_most_neg_one(context_tab, var))
+ r++;
+ if (isl_tab_rollback(context_tab, snap2) < 0)
+ return -1;
+ }
+ if (best == -1 || r > best_r) {
+ best = split;
+ best_r = r;
+ }
+ if (isl_tab_rollback(context_tab, snap) < 0)
+ return -1;
+ }
+
+ return best;
+}
+
+static struct isl_basic_set *context_lex_peek_basic_set(
+ struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ if (!clex->tab)
+ return NULL;
+ return isl_tab_peek_bset(clex->tab);
+}
+
+static struct isl_tab *context_lex_peek_tab(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ return clex->tab;
+}
+
+static void context_lex_add_eq(struct isl_context *context, isl_int *eq,
+ int check, int update)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ if (isl_tab_extend_cons(clex->tab, 2) < 0)
+ goto error;
+ if (add_lexmin_eq(clex->tab, eq) < 0)
+ goto error;
+ if (check) {
+ int v = tab_has_valid_sample(clex->tab, eq, 1);
+ if (v < 0)
+ goto error;
+ if (!v)
+ clex->tab = check_integer_feasible(clex->tab);
+ }
+ if (update)
+ clex->tab = check_samples(clex->tab, eq, 1);
+ return;
+error:
+ isl_tab_free(clex->tab);
+ clex->tab = NULL;
+}
+
+static void context_lex_add_ineq(struct isl_context *context, isl_int *ineq,
+ int check, int update)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ if (isl_tab_extend_cons(clex->tab, 1) < 0)
+ goto error;
+ clex->tab = add_lexmin_ineq(clex->tab, ineq);
+ if (check) {
+ int v = tab_has_valid_sample(clex->tab, ineq, 0);
+ if (v < 0)
+ goto error;
+ if (!v)
+ clex->tab = check_integer_feasible(clex->tab);
+ }
+ if (update)
+ clex->tab = check_samples(clex->tab, ineq, 0);
+ return;
+error:
+ isl_tab_free(clex->tab);
+ clex->tab = NULL;
+}
+
+static int context_lex_add_ineq_wrap(void *user, isl_int *ineq)
+{
+ struct isl_context *context = (struct isl_context *)user;
+ context_lex_add_ineq(context, ineq, 0, 0);
+ return context->op->is_ok(context) ? 0 : -1;
+}
+
+/* Check which signs can be obtained by "ineq" on all the currently
+ * active sample values. See row_sign for more information.
+ */
+static enum isl_tab_row_sign tab_ineq_sign(struct isl_tab *tab, isl_int *ineq,
+ int strict)
+{
+ int i;
+ int sgn;
+ isl_int tmp;
+ enum isl_tab_row_sign res = isl_tab_row_unknown;
+
+ isl_assert(tab->mat->ctx, tab->samples, return isl_tab_row_unknown);
+ isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var,
+ return isl_tab_row_unknown);
+
+ isl_int_init(tmp);
+ for (i = tab->n_outside; i < tab->n_sample; ++i) {
+ isl_seq_inner_product(tab->samples->row[i], ineq,
+ 1 + tab->n_var, &tmp);
+ sgn = isl_int_sgn(tmp);
+ if (sgn > 0 || (sgn == 0 && strict)) {
+ if (res == isl_tab_row_unknown)
+ res = isl_tab_row_pos;
+ if (res == isl_tab_row_neg)
+ res = isl_tab_row_any;
+ }
+ if (sgn < 0) {
+ if (res == isl_tab_row_unknown)
+ res = isl_tab_row_neg;
+ if (res == isl_tab_row_pos)
+ res = isl_tab_row_any;
+ }
+ if (res == isl_tab_row_any)
+ break;
+ }
+ isl_int_clear(tmp);
+
+ return res;
+}
+
+static enum isl_tab_row_sign context_lex_ineq_sign(struct isl_context *context,
+ isl_int *ineq, int strict)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ return tab_ineq_sign(clex->tab, ineq, strict);
+}
+
+/* Check whether "ineq" can be added to the tableau without rendering
+ * it infeasible.
+ */
+static int context_lex_test_ineq(struct isl_context *context, isl_int *ineq)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ struct isl_tab_undo *snap;
+ int feasible;
+
+ if (!clex->tab)
+ return -1;
+
+ if (isl_tab_extend_cons(clex->tab, 1) < 0)
+ return -1;
+
+ snap = isl_tab_snap(clex->tab);
+ if (isl_tab_push_basis(clex->tab) < 0)
+ return -1;
+ clex->tab = add_lexmin_ineq(clex->tab, ineq);
+ clex->tab = check_integer_feasible(clex->tab);
+ if (!clex->tab)
+ return -1;
+ feasible = !clex->tab->empty;
+ if (isl_tab_rollback(clex->tab, snap) < 0)
+ return -1;
+
+ return feasible;
+}
+
+static int context_lex_get_div(struct isl_context *context, struct isl_tab *tab,
+ struct isl_vec *div)
+{
+ return get_div(tab, context, div);
+}
+
+/* Add a div specified by "div" to the context tableau and return
+ * 1 if the div is obviously non-negative.
+ * context_tab_add_div will always return 1, because all variables
+ * in a isl_context_lex tableau are non-negative.
+ * However, if we are using a big parameter in the context, then this only
+ * reflects the non-negativity of the variable used to _encode_ the
+ * div, i.e., div' = M + div, so we can't draw any conclusions.
+ */
+static int context_lex_add_div(struct isl_context *context, struct isl_vec *div)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ int nonneg;
+ nonneg = context_tab_add_div(clex->tab, div,
+ context_lex_add_ineq_wrap, context);
+ if (nonneg < 0)
+ return -1;
+ if (clex->tab->M)
+ return 0;
+ return nonneg;
+}
+
+static int context_lex_detect_equalities(struct isl_context *context,
+ struct isl_tab *tab)
+{
+ return 0;
+}
+
+static int context_lex_best_split(struct isl_context *context,
+ struct isl_tab *tab)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ struct isl_tab_undo *snap;
+ int r;
+
+ snap = isl_tab_snap(clex->tab);
+ if (isl_tab_push_basis(clex->tab) < 0)
+ return -1;
+ r = best_split(tab, clex->tab);
+
+ if (r >= 0 && isl_tab_rollback(clex->tab, snap) < 0)
+ return -1;
+
+ return r;
+}
+
+static int context_lex_is_empty(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ if (!clex->tab)
+ return -1;
+ return clex->tab->empty;
+}
+
+static void *context_lex_save(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ struct isl_tab_undo *snap;
+
+ snap = isl_tab_snap(clex->tab);
+ if (isl_tab_push_basis(clex->tab) < 0)
+ return NULL;
+ if (isl_tab_save_samples(clex->tab) < 0)
+ return NULL;
+
+ return snap;
+}
+
+static void context_lex_restore(struct isl_context *context, void *save)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ if (isl_tab_rollback(clex->tab, (struct isl_tab_undo *)save) < 0) {
+ isl_tab_free(clex->tab);
+ clex->tab = NULL;
+ }
+}
+
+static void context_lex_discard(void *save)
+{
+}
+
+static int context_lex_is_ok(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ return !!clex->tab;
+}
+
+/* For each variable in the context tableau, check if the variable can
+ * only attain non-negative values. If so, mark the parameter as non-negative
+ * in the main tableau. This allows for a more direct identification of some
+ * cases of violated constraints.
+ */
+static struct isl_tab *tab_detect_nonnegative_parameters(struct isl_tab *tab,
+ struct isl_tab *context_tab)
+{
+ int i;
+ struct isl_tab_undo *snap;
+ struct isl_vec *ineq = NULL;
+ struct isl_tab_var *var;
+ int n;
+
+ if (context_tab->n_var == 0)
+ return tab;
+
+ ineq = isl_vec_alloc(tab->mat->ctx, 1 + context_tab->n_var);
+ if (!ineq)
+ goto error;
+
+ if (isl_tab_extend_cons(context_tab, 1) < 0)
+ goto error;
+
+ snap = isl_tab_snap(context_tab);
+
+ n = 0;
+ isl_seq_clr(ineq->el, ineq->size);
+ for (i = 0; i < context_tab->n_var; ++i) {
+ isl_int_set_si(ineq->el[1 + i], 1);
+ if (isl_tab_add_ineq(context_tab, ineq->el) < 0)
+ goto error;
+ var = &context_tab->con[context_tab->n_con - 1];
+ if (!context_tab->empty &&
+ !isl_tab_min_at_most_neg_one(context_tab, var)) {
+ int j = i;
+ if (i >= tab->n_param)
+ j = i - tab->n_param + tab->n_var - tab->n_div;
+ tab->var[j].is_nonneg = 1;
+ n++;
+ }
+ isl_int_set_si(ineq->el[1 + i], 0);
+ if (isl_tab_rollback(context_tab, snap) < 0)
+ goto error;
+ }
+
+ if (context_tab->M && n == context_tab->n_var) {
+ context_tab->mat = isl_mat_drop_cols(context_tab->mat, 2, 1);
+ context_tab->M = 0;
+ }
+
+ isl_vec_free(ineq);
+ return tab;
+error:
+ isl_vec_free(ineq);
+ isl_tab_free(tab);
+ return NULL;
+}
+
+static struct isl_tab *context_lex_detect_nonnegative_parameters(
+ struct isl_context *context, struct isl_tab *tab)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ struct isl_tab_undo *snap;
+
+ if (!tab)
+ return NULL;
+
+ snap = isl_tab_snap(clex->tab);
+ if (isl_tab_push_basis(clex->tab) < 0)
+ goto error;
+
+ tab = tab_detect_nonnegative_parameters(tab, clex->tab);
+
+ if (isl_tab_rollback(clex->tab, snap) < 0)
+ goto error;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+static void context_lex_invalidate(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ isl_tab_free(clex->tab);
+ clex->tab = NULL;
+}
+
+static void context_lex_free(struct isl_context *context)
+{
+ struct isl_context_lex *clex = (struct isl_context_lex *)context;
+ isl_tab_free(clex->tab);
+ free(clex);
+}
+
+struct isl_context_op isl_context_lex_op = {
+ context_lex_detect_nonnegative_parameters,
+ context_lex_peek_basic_set,
+ context_lex_peek_tab,
+ context_lex_add_eq,
+ context_lex_add_ineq,
+ context_lex_ineq_sign,
+ context_lex_test_ineq,
+ context_lex_get_div,
+ context_lex_add_div,
+ context_lex_detect_equalities,
+ context_lex_best_split,
+ context_lex_is_empty,
+ context_lex_is_ok,
+ context_lex_save,
+ context_lex_restore,
+ context_lex_discard,
+ context_lex_invalidate,
+ context_lex_free,
+};
+
+static struct isl_tab *context_tab_for_lexmin(struct isl_basic_set *bset)
+{
+ struct isl_tab *tab;
+
+ if (!bset)
+ return NULL;
+ tab = tab_for_lexmin((struct isl_basic_map *)bset, NULL, 1, 0);
+ if (!tab)
+ goto error;
+ if (isl_tab_track_bset(tab, bset) < 0)
+ goto error;
+ tab = isl_tab_init_samples(tab);
+ return tab;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static struct isl_context *isl_context_lex_alloc(struct isl_basic_set *dom)
+{
+ struct isl_context_lex *clex;
+
+ if (!dom)
+ return NULL;
+
+ clex = isl_alloc_type(dom->ctx, struct isl_context_lex);
+ if (!clex)
+ return NULL;
+
+ clex->context.op = &isl_context_lex_op;
+
+ clex->tab = context_tab_for_lexmin(isl_basic_set_copy(dom));
+ if (restore_lexmin(clex->tab) < 0)
+ goto error;
+ clex->tab = check_integer_feasible(clex->tab);
+ if (!clex->tab)
+ goto error;
+
+ return &clex->context;
+error:
+ clex->context.op->free(&clex->context);
+ return NULL;
+}
+
+/* Representation of the context when using generalized basis reduction.
+ *
+ * "shifted" contains the offsets of the unit hypercubes that lie inside the
+ * context. Any rational point in "shifted" can therefore be rounded
+ * up to an integer point in the context.
+ * If the context is constrained by any equality, then "shifted" is not used
+ * as it would be empty.
+ */
+struct isl_context_gbr {
+ struct isl_context context;
+ struct isl_tab *tab;
+ struct isl_tab *shifted;
+ struct isl_tab *cone;
+};
+
+static struct isl_tab *context_gbr_detect_nonnegative_parameters(
+ struct isl_context *context, struct isl_tab *tab)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ if (!tab)
+ return NULL;
+ return tab_detect_nonnegative_parameters(tab, cgbr->tab);
+}
+
+static struct isl_basic_set *context_gbr_peek_basic_set(
+ struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ if (!cgbr->tab)
+ return NULL;
+ return isl_tab_peek_bset(cgbr->tab);
+}
+
+static struct isl_tab *context_gbr_peek_tab(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ return cgbr->tab;
+}
+
+/* Initialize the "shifted" tableau of the context, which
+ * contains the constraints of the original tableau shifted
+ * by the sum of all negative coefficients. This ensures
+ * that any rational point in the shifted tableau can
+ * be rounded up to yield an integer point in the original tableau.
+ */
+static void gbr_init_shifted(struct isl_context_gbr *cgbr)
+{
+ int i, j;
+ struct isl_vec *cst;
+ struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab);
+ unsigned dim = isl_basic_set_total_dim(bset);
+
+ cst = isl_vec_alloc(cgbr->tab->mat->ctx, bset->n_ineq);
+ if (!cst)
+ return;
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ isl_int_set(cst->el[i], bset->ineq[i][0]);
+ for (j = 0; j < dim; ++j) {
+ if (!isl_int_is_neg(bset->ineq[i][1 + j]))
+ continue;
+ isl_int_add(bset->ineq[i][0], bset->ineq[i][0],
+ bset->ineq[i][1 + j]);
+ }
+ }
+
+ cgbr->shifted = isl_tab_from_basic_set(bset, 0);
+
+ for (i = 0; i < bset->n_ineq; ++i)
+ isl_int_set(bset->ineq[i][0], cst->el[i]);
+
+ isl_vec_free(cst);
+}
+
+/* Check if the shifted tableau is non-empty, and if so
+ * use the sample point to construct an integer point
+ * of the context tableau.
+ */
+static struct isl_vec *gbr_get_shifted_sample(struct isl_context_gbr *cgbr)
+{
+ struct isl_vec *sample;
+
+ if (!cgbr->shifted)
+ gbr_init_shifted(cgbr);
+ if (!cgbr->shifted)
+ return NULL;
+ if (cgbr->shifted->empty)
+ return isl_vec_alloc(cgbr->tab->mat->ctx, 0);
+
+ sample = isl_tab_get_sample_value(cgbr->shifted);
+ sample = isl_vec_ceil(sample);
+
+ return sample;
+}
+
+static struct isl_basic_set *drop_constant_terms(struct isl_basic_set *bset)
+{
+ int i;
+
+ if (!bset)
+ return NULL;
+
+ for (i = 0; i < bset->n_eq; ++i)
+ isl_int_set_si(bset->eq[i][0], 0);
+
+ for (i = 0; i < bset->n_ineq; ++i)
+ isl_int_set_si(bset->ineq[i][0], 0);
+
+ return bset;
+}
+
+static int use_shifted(struct isl_context_gbr *cgbr)
+{
+ if (!cgbr->tab)
+ return 0;
+ return cgbr->tab->bmap->n_eq == 0 && cgbr->tab->bmap->n_div == 0;
+}
+
+static struct isl_vec *gbr_get_sample(struct isl_context_gbr *cgbr)
+{
+ struct isl_basic_set *bset;
+ struct isl_basic_set *cone;
+
+ if (isl_tab_sample_is_integer(cgbr->tab))
+ return isl_tab_get_sample_value(cgbr->tab);
+
+ if (use_shifted(cgbr)) {
+ struct isl_vec *sample;
+
+ sample = gbr_get_shifted_sample(cgbr);
+ if (!sample || sample->size > 0)
+ return sample;
+
+ isl_vec_free(sample);
+ }
+
+ if (!cgbr->cone) {
+ bset = isl_tab_peek_bset(cgbr->tab);
+ cgbr->cone = isl_tab_from_recession_cone(bset, 0);
+ if (!cgbr->cone)
+ return NULL;
+ if (isl_tab_track_bset(cgbr->cone,
+ isl_basic_set_copy(bset)) < 0)
+ return NULL;
+ }
+ if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0)
+ return NULL;
+
+ if (cgbr->cone->n_dead == cgbr->cone->n_col) {
+ struct isl_vec *sample;
+ struct isl_tab_undo *snap;
+
+ if (cgbr->tab->basis) {
+ if (cgbr->tab->basis->n_col != 1 + cgbr->tab->n_var) {
+ isl_mat_free(cgbr->tab->basis);
+ cgbr->tab->basis = NULL;
+ }
+ cgbr->tab->n_zero = 0;
+ cgbr->tab->n_unbounded = 0;
+ }
+
+ snap = isl_tab_snap(cgbr->tab);
+
+ sample = isl_tab_sample(cgbr->tab);
+
+ if (isl_tab_rollback(cgbr->tab, snap) < 0) {
+ isl_vec_free(sample);
+ return NULL;
+ }
+
+ return sample;
+ }
+
+ cone = isl_basic_set_dup(isl_tab_peek_bset(cgbr->cone));
+ cone = drop_constant_terms(cone);
+ cone = isl_basic_set_update_from_tab(cone, cgbr->cone);
+ cone = isl_basic_set_underlying_set(cone);
+ cone = isl_basic_set_gauss(cone, NULL);
+
+ bset = isl_basic_set_dup(isl_tab_peek_bset(cgbr->tab));
+ bset = isl_basic_set_update_from_tab(bset, cgbr->tab);
+ bset = isl_basic_set_underlying_set(bset);
+ bset = isl_basic_set_gauss(bset, NULL);
+
+ return isl_basic_set_sample_with_cone(bset, cone);
+}
+
+static void check_gbr_integer_feasible(struct isl_context_gbr *cgbr)
+{
+ struct isl_vec *sample;
+
+ if (!cgbr->tab)
+ return;
+
+ if (cgbr->tab->empty)
+ return;
+
+ sample = gbr_get_sample(cgbr);
+ if (!sample)
+ goto error;
+
+ if (sample->size == 0) {
+ isl_vec_free(sample);
+ if (isl_tab_mark_empty(cgbr->tab) < 0)
+ goto error;
+ return;
+ }
+
+ if (isl_tab_add_sample(cgbr->tab, sample) < 0)
+ goto error;
+
+ return;
+error:
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static struct isl_tab *add_gbr_eq(struct isl_tab *tab, isl_int *eq)
+{
+ if (!tab)
+ return NULL;
+
+ if (isl_tab_extend_cons(tab, 2) < 0)
+ goto error;
+
+ if (isl_tab_add_eq(tab, eq) < 0)
+ goto error;
+
+ return tab;
+error:
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Add the equality described by "eq" to the context.
+ * If "check" is set, then we check if the context is empty after
+ * adding the equality.
+ * If "update" is set, then we check if the samples are still valid.
+ *
+ * We do not explicitly add shifted copies of the equality to
+ * cgbr->shifted since they would conflict with each other.
+ * Instead, we directly mark cgbr->shifted empty.
+ */
+static void context_gbr_add_eq(struct isl_context *context, isl_int *eq,
+ int check, int update)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+
+ cgbr->tab = add_gbr_eq(cgbr->tab, eq);
+
+ if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
+ if (isl_tab_mark_empty(cgbr->shifted) < 0)
+ goto error;
+ }
+
+ if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead) {
+ if (isl_tab_extend_cons(cgbr->cone, 2) < 0)
+ goto error;
+ if (isl_tab_add_eq(cgbr->cone, eq) < 0)
+ goto error;
+ }
+
+ if (check) {
+ int v = tab_has_valid_sample(cgbr->tab, eq, 1);
+ if (v < 0)
+ goto error;
+ if (!v)
+ check_gbr_integer_feasible(cgbr);
+ }
+ if (update)
+ cgbr->tab = check_samples(cgbr->tab, eq, 1);
+ return;
+error:
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static void add_gbr_ineq(struct isl_context_gbr *cgbr, isl_int *ineq)
+{
+ if (!cgbr->tab)
+ return;
+
+ if (isl_tab_extend_cons(cgbr->tab, 1) < 0)
+ goto error;
+
+ if (isl_tab_add_ineq(cgbr->tab, ineq) < 0)
+ goto error;
+
+ if (cgbr->shifted && !cgbr->shifted->empty && use_shifted(cgbr)) {
+ int i;
+ unsigned dim;
+ dim = isl_basic_map_total_dim(cgbr->tab->bmap);
+
+ if (isl_tab_extend_cons(cgbr->shifted, 1) < 0)
+ goto error;
+
+ for (i = 0; i < dim; ++i) {
+ if (!isl_int_is_neg(ineq[1 + i]))
+ continue;
+ isl_int_add(ineq[0], ineq[0], ineq[1 + i]);
+ }
+
+ if (isl_tab_add_ineq(cgbr->shifted, ineq) < 0)
+ goto error;
+
+ for (i = 0; i < dim; ++i) {
+ if (!isl_int_is_neg(ineq[1 + i]))
+ continue;
+ isl_int_sub(ineq[0], ineq[0], ineq[1 + i]);
+ }
+ }
+
+ if (cgbr->cone && cgbr->cone->n_col != cgbr->cone->n_dead) {
+ if (isl_tab_extend_cons(cgbr->cone, 1) < 0)
+ goto error;
+ if (isl_tab_add_ineq(cgbr->cone, ineq) < 0)
+ goto error;
+ }
+
+ return;
+error:
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static void context_gbr_add_ineq(struct isl_context *context, isl_int *ineq,
+ int check, int update)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+
+ add_gbr_ineq(cgbr, ineq);
+ if (!cgbr->tab)
+ return;
+
+ if (check) {
+ int v = tab_has_valid_sample(cgbr->tab, ineq, 0);
+ if (v < 0)
+ goto error;
+ if (!v)
+ check_gbr_integer_feasible(cgbr);
+ }
+ if (update)
+ cgbr->tab = check_samples(cgbr->tab, ineq, 0);
+ return;
+error:
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static int context_gbr_add_ineq_wrap(void *user, isl_int *ineq)
+{
+ struct isl_context *context = (struct isl_context *)user;
+ context_gbr_add_ineq(context, ineq, 0, 0);
+ return context->op->is_ok(context) ? 0 : -1;
+}
+
+static enum isl_tab_row_sign context_gbr_ineq_sign(struct isl_context *context,
+ isl_int *ineq, int strict)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ return tab_ineq_sign(cgbr->tab, ineq, strict);
+}
+
+/* Check whether "ineq" can be added to the tableau without rendering
+ * it infeasible.
+ */
+static int context_gbr_test_ineq(struct isl_context *context, isl_int *ineq)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ struct isl_tab_undo *snap;
+ struct isl_tab_undo *shifted_snap = NULL;
+ struct isl_tab_undo *cone_snap = NULL;
+ int feasible;
+
+ if (!cgbr->tab)
+ return -1;
+
+ if (isl_tab_extend_cons(cgbr->tab, 1) < 0)
+ return -1;
+
+ snap = isl_tab_snap(cgbr->tab);
+ if (cgbr->shifted)
+ shifted_snap = isl_tab_snap(cgbr->shifted);
+ if (cgbr->cone)
+ cone_snap = isl_tab_snap(cgbr->cone);
+ add_gbr_ineq(cgbr, ineq);
+ check_gbr_integer_feasible(cgbr);
+ if (!cgbr->tab)
+ return -1;
+ feasible = !cgbr->tab->empty;
+ if (isl_tab_rollback(cgbr->tab, snap) < 0)
+ return -1;
+ if (shifted_snap) {
+ if (isl_tab_rollback(cgbr->shifted, shifted_snap))
+ return -1;
+ } else if (cgbr->shifted) {
+ isl_tab_free(cgbr->shifted);
+ cgbr->shifted = NULL;
+ }
+ if (cone_snap) {
+ if (isl_tab_rollback(cgbr->cone, cone_snap))
+ return -1;
+ } else if (cgbr->cone) {
+ isl_tab_free(cgbr->cone);
+ cgbr->cone = NULL;
+ }
+
+ return feasible;
+}
+
+/* Return the column of the last of the variables associated to
+ * a column that has a non-zero coefficient.
+ * This function is called in a context where only coefficients
+ * of parameters or divs can be non-zero.
+ */
+static int last_non_zero_var_col(struct isl_tab *tab, isl_int *p)
+{
+ int i;
+ int col;
+
+ if (tab->n_var == 0)
+ return -1;
+
+ for (i = tab->n_var - 1; i >= 0; --i) {
+ if (i >= tab->n_param && i < tab->n_var - tab->n_div)
+ continue;
+ if (tab->var[i].is_row)
+ continue;
+ col = tab->var[i].index;
+ if (!isl_int_is_zero(p[col]))
+ return col;
+ }
+
+ return -1;
+}
+
+/* Look through all the recently added equalities in the context
+ * to see if we can propagate any of them to the main tableau.
+ *
+ * The newly added equalities in the context are encoded as pairs
+ * of inequalities starting at inequality "first".
+ *
+ * We tentatively add each of these equalities to the main tableau
+ * and if this happens to result in a row with a final coefficient
+ * that is one or negative one, we use it to kill a column
+ * in the main tableau. Otherwise, we discard the tentatively
+ * added row.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+static int propagate_equalities(struct isl_context_gbr *cgbr,
+ struct isl_tab *tab, unsigned first)
+{
+ int i;
+ struct isl_vec *eq = NULL;
+
+ eq = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+ if (!eq)
+ goto error;
+
+ if (isl_tab_extend_cons(tab, (cgbr->tab->bmap->n_ineq - first)/2) < 0)
+ goto error;
+
+ isl_seq_clr(eq->el + 1 + tab->n_param,
+ tab->n_var - tab->n_param - tab->n_div);
+ for (i = first; i < cgbr->tab->bmap->n_ineq; i += 2) {
+ int j;
+ int r;
+ struct isl_tab_undo *snap;
+ snap = isl_tab_snap(tab);
+
+ isl_seq_cpy(eq->el, cgbr->tab->bmap->ineq[i], 1 + tab->n_param);
+ isl_seq_cpy(eq->el + 1 + tab->n_var - tab->n_div,
+ cgbr->tab->bmap->ineq[i] + 1 + tab->n_param,
+ tab->n_div);
+
+ r = isl_tab_add_row(tab, eq->el);
+ if (r < 0)
+ goto error;
+ r = tab->con[r].index;
+ j = last_non_zero_var_col(tab, tab->mat->row[r] + 2 + tab->M);
+ if (j < 0 || j < tab->n_dead ||
+ !isl_int_is_one(tab->mat->row[r][0]) ||
+ (!isl_int_is_one(tab->mat->row[r][2 + tab->M + j]) &&
+ !isl_int_is_negone(tab->mat->row[r][2 + tab->M + j]))) {
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+ continue;
+ }
+ if (isl_tab_pivot(tab, r, j) < 0)
+ goto error;
+ if (isl_tab_kill_col(tab, j) < 0)
+ goto error;
+
+ if (restore_lexmin(tab) < 0)
+ goto error;
+ }
+
+ isl_vec_free(eq);
+
+ return 0;
+error:
+ isl_vec_free(eq);
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+ return -1;
+}
+
+static int context_gbr_detect_equalities(struct isl_context *context,
+ struct isl_tab *tab)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ struct isl_ctx *ctx;
+ unsigned n_ineq;
+
+ ctx = cgbr->tab->mat->ctx;
+
+ if (!cgbr->cone) {
+ struct isl_basic_set *bset = isl_tab_peek_bset(cgbr->tab);
+ cgbr->cone = isl_tab_from_recession_cone(bset, 0);
+ if (!cgbr->cone)
+ goto error;
+ if (isl_tab_track_bset(cgbr->cone,
+ isl_basic_set_copy(bset)) < 0)
+ goto error;
+ }
+ if (isl_tab_detect_implicit_equalities(cgbr->cone) < 0)
+ goto error;
+
+ n_ineq = cgbr->tab->bmap->n_ineq;
+ cgbr->tab = isl_tab_detect_equalities(cgbr->tab, cgbr->cone);
+ if (!cgbr->tab)
+ return -1;
+ if (cgbr->tab->bmap->n_ineq > n_ineq &&
+ propagate_equalities(cgbr, tab, n_ineq) < 0)
+ return -1;
+
+ return 0;
+error:
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+ return -1;
+}
+
+static int context_gbr_get_div(struct isl_context *context, struct isl_tab *tab,
+ struct isl_vec *div)
+{
+ return get_div(tab, context, div);
+}
+
+static int context_gbr_add_div(struct isl_context *context, struct isl_vec *div)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ if (cgbr->cone) {
+ int k;
+
+ if (isl_tab_extend_cons(cgbr->cone, 3) < 0)
+ return -1;
+ if (isl_tab_extend_vars(cgbr->cone, 1) < 0)
+ return -1;
+ if (isl_tab_allocate_var(cgbr->cone) <0)
+ return -1;
+
+ cgbr->cone->bmap = isl_basic_map_extend_space(cgbr->cone->bmap,
+ isl_basic_map_get_space(cgbr->cone->bmap), 1, 0, 2);
+ k = isl_basic_map_alloc_div(cgbr->cone->bmap);
+ if (k < 0)
+ return -1;
+ isl_seq_cpy(cgbr->cone->bmap->div[k], div->el, div->size);
+ if (isl_tab_push(cgbr->cone, isl_tab_undo_bmap_div) < 0)
+ return -1;
+ }
+ return context_tab_add_div(cgbr->tab, div,
+ context_gbr_add_ineq_wrap, context);
+}
+
+static int context_gbr_best_split(struct isl_context *context,
+ struct isl_tab *tab)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ struct isl_tab_undo *snap;
+ int r;
+
+ snap = isl_tab_snap(cgbr->tab);
+ r = best_split(tab, cgbr->tab);
+
+ if (r >= 0 && isl_tab_rollback(cgbr->tab, snap) < 0)
+ return -1;
+
+ return r;
+}
+
+static int context_gbr_is_empty(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ if (!cgbr->tab)
+ return -1;
+ return cgbr->tab->empty;
+}
+
+struct isl_gbr_tab_undo {
+ struct isl_tab_undo *tab_snap;
+ struct isl_tab_undo *shifted_snap;
+ struct isl_tab_undo *cone_snap;
+};
+
+static void *context_gbr_save(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ struct isl_gbr_tab_undo *snap;
+
+ if (!cgbr->tab)
+ return NULL;
+
+ snap = isl_alloc_type(cgbr->tab->mat->ctx, struct isl_gbr_tab_undo);
+ if (!snap)
+ return NULL;
+
+ snap->tab_snap = isl_tab_snap(cgbr->tab);
+ if (isl_tab_save_samples(cgbr->tab) < 0)
+ goto error;
+
+ if (cgbr->shifted)
+ snap->shifted_snap = isl_tab_snap(cgbr->shifted);
+ else
+ snap->shifted_snap = NULL;
+
+ if (cgbr->cone)
+ snap->cone_snap = isl_tab_snap(cgbr->cone);
+ else
+ snap->cone_snap = NULL;
+
+ return snap;
+error:
+ free(snap);
+ return NULL;
+}
+
+static void context_gbr_restore(struct isl_context *context, void *save)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save;
+ if (!snap)
+ goto error;
+ if (isl_tab_rollback(cgbr->tab, snap->tab_snap) < 0) {
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+ }
+
+ if (snap->shifted_snap) {
+ if (isl_tab_rollback(cgbr->shifted, snap->shifted_snap) < 0)
+ goto error;
+ } else if (cgbr->shifted) {
+ isl_tab_free(cgbr->shifted);
+ cgbr->shifted = NULL;
+ }
+
+ if (snap->cone_snap) {
+ if (isl_tab_rollback(cgbr->cone, snap->cone_snap) < 0)
+ goto error;
+ } else if (cgbr->cone) {
+ isl_tab_free(cgbr->cone);
+ cgbr->cone = NULL;
+ }
+
+ free(snap);
+
+ return;
+error:
+ free(snap);
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static void context_gbr_discard(void *save)
+{
+ struct isl_gbr_tab_undo *snap = (struct isl_gbr_tab_undo *)save;
+ free(snap);
+}
+
+static int context_gbr_is_ok(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ return !!cgbr->tab;
+}
+
+static void context_gbr_invalidate(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ isl_tab_free(cgbr->tab);
+ cgbr->tab = NULL;
+}
+
+static void context_gbr_free(struct isl_context *context)
+{
+ struct isl_context_gbr *cgbr = (struct isl_context_gbr *)context;
+ isl_tab_free(cgbr->tab);
+ isl_tab_free(cgbr->shifted);
+ isl_tab_free(cgbr->cone);
+ free(cgbr);
+}
+
+struct isl_context_op isl_context_gbr_op = {
+ context_gbr_detect_nonnegative_parameters,
+ context_gbr_peek_basic_set,
+ context_gbr_peek_tab,
+ context_gbr_add_eq,
+ context_gbr_add_ineq,
+ context_gbr_ineq_sign,
+ context_gbr_test_ineq,
+ context_gbr_get_div,
+ context_gbr_add_div,
+ context_gbr_detect_equalities,
+ context_gbr_best_split,
+ context_gbr_is_empty,
+ context_gbr_is_ok,
+ context_gbr_save,
+ context_gbr_restore,
+ context_gbr_discard,
+ context_gbr_invalidate,
+ context_gbr_free,
+};
+
+static struct isl_context *isl_context_gbr_alloc(struct isl_basic_set *dom)
+{
+ struct isl_context_gbr *cgbr;
+
+ if (!dom)
+ return NULL;
+
+ cgbr = isl_calloc_type(dom->ctx, struct isl_context_gbr);
+ if (!cgbr)
+ return NULL;
+
+ cgbr->context.op = &isl_context_gbr_op;
+
+ cgbr->shifted = NULL;
+ cgbr->cone = NULL;
+ cgbr->tab = isl_tab_from_basic_set(dom, 1);
+ cgbr->tab = isl_tab_init_samples(cgbr->tab);
+ if (!cgbr->tab)
+ goto error;
+ check_gbr_integer_feasible(cgbr);
+
+ return &cgbr->context;
+error:
+ cgbr->context.op->free(&cgbr->context);
+ return NULL;
+}
+
+static struct isl_context *isl_context_alloc(struct isl_basic_set *dom)
+{
+ if (!dom)
+ return NULL;
+
+ if (dom->ctx->opt->context == ISL_CONTEXT_LEXMIN)
+ return isl_context_lex_alloc(dom);
+ else
+ return isl_context_gbr_alloc(dom);
+}
+
+/* Construct an isl_sol_map structure for accumulating the solution.
+ * If track_empty is set, then we also keep track of the parts
+ * of the context where there is no solution.
+ * If max is set, then we are solving a maximization, rather than
+ * a minimization problem, which means that the variables in the
+ * tableau have value "M - x" rather than "M + x".
+ */
+static struct isl_sol *sol_map_init(struct isl_basic_map *bmap,
+ struct isl_basic_set *dom, int track_empty, int max)
+{
+ struct isl_sol_map *sol_map = NULL;
+
+ if (!bmap)
+ goto error;
+
+ sol_map = isl_calloc_type(bmap->ctx, struct isl_sol_map);
+ if (!sol_map)
+ goto error;
+
+ sol_map->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+ sol_map->sol.dec_level.callback.run = &sol_dec_level_wrap;
+ sol_map->sol.dec_level.sol = &sol_map->sol;
+ sol_map->sol.max = max;
+ sol_map->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ sol_map->sol.add = &sol_map_add_wrap;
+ sol_map->sol.add_empty = track_empty ? &sol_map_add_empty_wrap : NULL;
+ sol_map->sol.free = &sol_map_free_wrap;
+ sol_map->map = isl_map_alloc_space(isl_basic_map_get_space(bmap), 1,
+ ISL_MAP_DISJOINT);
+ if (!sol_map->map)
+ goto error;
+
+ sol_map->sol.context = isl_context_alloc(dom);
+ if (!sol_map->sol.context)
+ goto error;
+
+ if (track_empty) {
+ sol_map->empty = isl_set_alloc_space(isl_basic_set_get_space(dom),
+ 1, ISL_SET_DISJOINT);
+ if (!sol_map->empty)
+ goto error;
+ }
+
+ isl_basic_set_free(dom);
+ return &sol_map->sol;
+error:
+ isl_basic_set_free(dom);
+ sol_map_free(sol_map);
+ return NULL;
+}
+
+/* Check whether all coefficients of (non-parameter) variables
+ * are non-positive, meaning that no pivots can be performed on the row.
+ */
+static int is_critical(struct isl_tab *tab, int row)
+{
+ int j;
+ unsigned off = 2 + tab->M;
+
+ for (j = tab->n_dead; j < tab->n_col; ++j) {
+ if (tab->col_var[j] >= 0 &&
+ (tab->col_var[j] < tab->n_param ||
+ tab->col_var[j] >= tab->n_var - tab->n_div))
+ continue;
+
+ if (isl_int_is_pos(tab->mat->row[row][off + j]))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Check whether the inequality represented by vec is strict over the integers,
+ * i.e., there are no integer values satisfying the constraint with
+ * equality. This happens if the gcd of the coefficients is not a divisor
+ * of the constant term. If so, scale the constraint down by the gcd
+ * of the coefficients.
+ */
+static int is_strict(struct isl_vec *vec)
+{
+ isl_int gcd;
+ int strict = 0;
+
+ isl_int_init(gcd);
+ isl_seq_gcd(vec->el + 1, vec->size - 1, &gcd);
+ if (!isl_int_is_one(gcd)) {
+ strict = !isl_int_is_divisible_by(vec->el[0], gcd);
+ isl_int_fdiv_q(vec->el[0], vec->el[0], gcd);
+ isl_seq_scale_down(vec->el + 1, vec->el + 1, gcd, vec->size-1);
+ }
+ isl_int_clear(gcd);
+
+ return strict;
+}
+
+/* Determine the sign of the given row of the main tableau.
+ * The result is one of
+ * isl_tab_row_pos: always non-negative; no pivot needed
+ * isl_tab_row_neg: always non-positive; pivot
+ * isl_tab_row_any: can be both positive and negative; split
+ *
+ * We first handle some simple cases
+ * - the row sign may be known already
+ * - the row may be obviously non-negative
+ * - the parametric constant may be equal to that of another row
+ * for which we know the sign. This sign will be either "pos" or
+ * "any". If it had been "neg" then we would have pivoted before.
+ *
+ * If none of these cases hold, we check the value of the row for each
+ * of the currently active samples. Based on the signs of these values
+ * we make an initial determination of the sign of the row.
+ *
+ * all zero -> unk(nown)
+ * all non-negative -> pos
+ * all non-positive -> neg
+ * both negative and positive -> all
+ *
+ * If we end up with "all", we are done.
+ * Otherwise, we perform a check for positive and/or negative
+ * values as follows.
+ *
+ * samples neg unk pos
+ * <0 ? Y N Y N
+ * pos any pos
+ * >0 ? Y N Y N
+ * any neg any neg
+ *
+ * There is no special sign for "zero", because we can usually treat zero
+ * as either non-negative or non-positive, whatever works out best.
+ * However, if the row is "critical", meaning that pivoting is impossible
+ * then we don't want to limp zero with the non-positive case, because
+ * then we we would lose the solution for those values of the parameters
+ * where the value of the row is zero. Instead, we treat 0 as non-negative
+ * ensuring a split if the row can attain both zero and negative values.
+ * The same happens when the original constraint was one that could not
+ * be satisfied with equality by any integer values of the parameters.
+ * In this case, we normalize the constraint, but then a value of zero
+ * for the normalized constraint is actually a positive value for the
+ * original constraint, so again we need to treat zero as non-negative.
+ * In both these cases, we have the following decision tree instead:
+ *
+ * all non-negative -> pos
+ * all negative -> neg
+ * both negative and non-negative -> all
+ *
+ * samples neg pos
+ * <0 ? Y N
+ * any pos
+ * >=0 ? Y N
+ * any neg
+ */
+static enum isl_tab_row_sign row_sign(struct isl_tab *tab,
+ struct isl_sol *sol, int row)
+{
+ struct isl_vec *ineq = NULL;
+ enum isl_tab_row_sign res = isl_tab_row_unknown;
+ int critical;
+ int strict;
+ int row2;
+
+ if (tab->row_sign[row] != isl_tab_row_unknown)
+ return tab->row_sign[row];
+ if (is_obviously_nonneg(tab, row))
+ return isl_tab_row_pos;
+ for (row2 = tab->n_redundant; row2 < tab->n_row; ++row2) {
+ if (tab->row_sign[row2] == isl_tab_row_unknown)
+ continue;
+ if (identical_parameter_line(tab, row, row2))
+ return tab->row_sign[row2];
+ }
+
+ critical = is_critical(tab, row);
+
+ ineq = get_row_parameter_ineq(tab, row);
+ if (!ineq)
+ goto error;
+
+ strict = is_strict(ineq);
+
+ res = sol->context->op->ineq_sign(sol->context, ineq->el,
+ critical || strict);
+
+ if (res == isl_tab_row_unknown || res == isl_tab_row_pos) {
+ /* test for negative values */
+ int feasible;
+ isl_seq_neg(ineq->el, ineq->el, ineq->size);
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+ feasible = sol->context->op->test_ineq(sol->context, ineq->el);
+ if (feasible < 0)
+ goto error;
+ if (!feasible)
+ res = isl_tab_row_pos;
+ else
+ res = (res == isl_tab_row_unknown) ? isl_tab_row_neg
+ : isl_tab_row_any;
+ if (res == isl_tab_row_neg) {
+ isl_seq_neg(ineq->el, ineq->el, ineq->size);
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+ }
+ }
+
+ if (res == isl_tab_row_neg) {
+ /* test for positive values */
+ int feasible;
+ if (!critical && !strict)
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+ feasible = sol->context->op->test_ineq(sol->context, ineq->el);
+ if (feasible < 0)
+ goto error;
+ if (feasible)
+ res = isl_tab_row_any;
+ }
+
+ isl_vec_free(ineq);
+ return res;
+error:
+ isl_vec_free(ineq);
+ return isl_tab_row_unknown;
+}
+
+static void find_solutions(struct isl_sol *sol, struct isl_tab *tab);
+
+/* Find solutions for values of the parameters that satisfy the given
+ * inequality.
+ *
+ * We currently take a snapshot of the context tableau that is reset
+ * when we return from this function, while we make a copy of the main
+ * tableau, leaving the original main tableau untouched.
+ * These are fairly arbitrary choices. Making a copy also of the context
+ * tableau would obviate the need to undo any changes made to it later,
+ * while taking a snapshot of the main tableau could reduce memory usage.
+ * If we were to switch to taking a snapshot of the main tableau,
+ * we would have to keep in mind that we need to save the row signs
+ * and that we need to do this before saving the current basis
+ * such that the basis has been restore before we restore the row signs.
+ */
+static void find_in_pos(struct isl_sol *sol, struct isl_tab *tab, isl_int *ineq)
+{
+ void *saved;
+
+ if (!sol->context)
+ goto error;
+ saved = sol->context->op->save(sol->context);
+
+ tab = isl_tab_dup(tab);
+ if (!tab)
+ goto error;
+
+ sol->context->op->add_ineq(sol->context, ineq, 0, 1);
+
+ find_solutions(sol, tab);
+
+ if (!sol->error)
+ sol->context->op->restore(sol->context, saved);
+ else
+ sol->context->op->discard(saved);
+ return;
+error:
+ sol->error = 1;
+}
+
+/* Record the absence of solutions for those values of the parameters
+ * that do not satisfy the given inequality with equality.
+ */
+static void no_sol_in_strict(struct isl_sol *sol,
+ struct isl_tab *tab, struct isl_vec *ineq)
+{
+ int empty;
+ void *saved;
+
+ if (!sol->context || sol->error)
+ goto error;
+ saved = sol->context->op->save(sol->context);
+
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+
+ sol->context->op->add_ineq(sol->context, ineq->el, 1, 0);
+ if (!sol->context)
+ goto error;
+
+ empty = tab->empty;
+ tab->empty = 1;
+ sol_add(sol, tab);
+ tab->empty = empty;
+
+ isl_int_add_ui(ineq->el[0], ineq->el[0], 1);
+
+ sol->context->op->restore(sol->context, saved);
+ return;
+error:
+ sol->error = 1;
+}
+
+/* Compute the lexicographic minimum of the set represented by the main
+ * tableau "tab" within the context "sol->context_tab".
+ * On entry the sample value of the main tableau is lexicographically
+ * less than or equal to this lexicographic minimum.
+ * Pivots are performed until a feasible point is found, which is then
+ * necessarily equal to the minimum, or until the tableau is found to
+ * be infeasible. Some pivots may need to be performed for only some
+ * feasible values of the context tableau. If so, the context tableau
+ * is split into a part where the pivot is needed and a part where it is not.
+ *
+ * Whenever we enter the main loop, the main tableau is such that no
+ * "obvious" pivots need to be performed on it, where "obvious" means
+ * that the given row can be seen to be negative without looking at
+ * the context tableau. In particular, for non-parametric problems,
+ * no pivots need to be performed on the main tableau.
+ * The caller of find_solutions is responsible for making this property
+ * hold prior to the first iteration of the loop, while restore_lexmin
+ * is called before every other iteration.
+ *
+ * Inside the main loop, we first examine the signs of the rows of
+ * the main tableau within the context of the context tableau.
+ * If we find a row that is always non-positive for all values of
+ * the parameters satisfying the context tableau and negative for at
+ * least one value of the parameters, we perform the appropriate pivot
+ * and start over. An exception is the case where no pivot can be
+ * performed on the row. In this case, we require that the sign of
+ * the row is negative for all values of the parameters (rather than just
+ * non-positive). This special case is handled inside row_sign, which
+ * will say that the row can have any sign if it determines that it can
+ * attain both negative and zero values.
+ *
+ * If we can't find a row that always requires a pivot, but we can find
+ * one or more rows that require a pivot for some values of the parameters
+ * (i.e., the row can attain both positive and negative signs), then we split
+ * the context tableau into two parts, one where we force the sign to be
+ * non-negative and one where we force is to be negative.
+ * The non-negative part is handled by a recursive call (through find_in_pos).
+ * Upon returning from this call, we continue with the negative part and
+ * perform the required pivot.
+ *
+ * If no such rows can be found, all rows are non-negative and we have
+ * found a (rational) feasible point. If we only wanted a rational point
+ * then we are done.
+ * Otherwise, we check if all values of the sample point of the tableau
+ * are integral for the variables. If so, we have found the minimal
+ * integral point and we are done.
+ * If the sample point is not integral, then we need to make a distinction
+ * based on whether the constant term is non-integral or the coefficients
+ * of the parameters. Furthermore, in order to decide how to handle
+ * the non-integrality, we also need to know whether the coefficients
+ * of the other columns in the tableau are integral. This leads
+ * to the following table. The first two rows do not correspond
+ * to a non-integral sample point and are only mentioned for completeness.
+ *
+ * constant parameters other
+ *
+ * int int int |
+ * int int rat | -> no problem
+ *
+ * rat int int -> fail
+ *
+ * rat int rat -> cut
+ *
+ * int rat rat |
+ * rat rat rat | -> parametric cut
+ *
+ * int rat int |
+ * rat rat int | -> split context
+ *
+ * If the parametric constant is completely integral, then there is nothing
+ * to be done. If the constant term is non-integral, but all the other
+ * coefficient are integral, then there is nothing that can be done
+ * and the tableau has no integral solution.
+ * If, on the other hand, one or more of the other columns have rational
+ * coefficients, but the parameter coefficients are all integral, then
+ * we can perform a regular (non-parametric) cut.
+ * Finally, if there is any parameter coefficient that is non-integral,
+ * then we need to involve the context tableau. There are two cases here.
+ * If at least one other column has a rational coefficient, then we
+ * can perform a parametric cut in the main tableau by adding a new
+ * integer division in the context tableau.
+ * If all other columns have integral coefficients, then we need to
+ * enforce that the rational combination of parameters (c + \sum a_i y_i)/m
+ * is always integral. We do this by introducing an integer division
+ * q = floor((c + \sum a_i y_i)/m) and stipulating that its argument should
+ * always be integral in the context tableau, i.e., m q = c + \sum a_i y_i.
+ * Since q is expressed in the tableau as
+ * c + \sum a_i y_i - m q >= 0
+ * -c - \sum a_i y_i + m q + m - 1 >= 0
+ * it is sufficient to add the inequality
+ * -c - \sum a_i y_i + m q >= 0
+ * In the part of the context where this inequality does not hold, the
+ * main tableau is marked as being empty.
+ */
+static void find_solutions(struct isl_sol *sol, struct isl_tab *tab)
+{
+ struct isl_context *context;
+ int r;
+
+ if (!tab || sol->error)
+ goto error;
+
+ context = sol->context;
+
+ if (tab->empty)
+ goto done;
+ if (context->op->is_empty(context))
+ goto done;
+
+ for (r = 0; r >= 0 && tab && !tab->empty; r = restore_lexmin(tab)) {
+ int flags;
+ int row;
+ enum isl_tab_row_sign sgn;
+ int split = -1;
+ int n_split = 0;
+
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+ continue;
+ sgn = row_sign(tab, sol, row);
+ if (!sgn)
+ goto error;
+ tab->row_sign[row] = sgn;
+ if (sgn == isl_tab_row_any)
+ n_split++;
+ if (sgn == isl_tab_row_any && split == -1)
+ split = row;
+ if (sgn == isl_tab_row_neg)
+ break;
+ }
+ if (row < tab->n_row)
+ continue;
+ if (split != -1) {
+ struct isl_vec *ineq;
+ if (n_split != 1)
+ split = context->op->best_split(context, tab);
+ if (split < 0)
+ goto error;
+ ineq = get_row_parameter_ineq(tab, split);
+ if (!ineq)
+ goto error;
+ is_strict(ineq);
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ if (!isl_tab_var_from_row(tab, row)->is_nonneg)
+ continue;
+ if (tab->row_sign[row] == isl_tab_row_any)
+ tab->row_sign[row] = isl_tab_row_unknown;
+ }
+ tab->row_sign[split] = isl_tab_row_pos;
+ sol_inc_level(sol);
+ find_in_pos(sol, tab, ineq->el);
+ tab->row_sign[split] = isl_tab_row_neg;
+ row = split;
+ isl_seq_neg(ineq->el, ineq->el, ineq->size);
+ isl_int_sub_ui(ineq->el[0], ineq->el[0], 1);
+ if (!sol->error)
+ context->op->add_ineq(context, ineq->el, 0, 1);
+ isl_vec_free(ineq);
+ if (sol->error)
+ goto error;
+ continue;
+ }
+ if (tab->rational)
+ break;
+ row = first_non_integer_row(tab, &flags);
+ if (row < 0)
+ break;
+ if (ISL_FL_ISSET(flags, I_PAR)) {
+ if (ISL_FL_ISSET(flags, I_VAR)) {
+ if (isl_tab_mark_empty(tab) < 0)
+ goto error;
+ break;
+ }
+ row = add_cut(tab, row);
+ } else if (ISL_FL_ISSET(flags, I_VAR)) {
+ struct isl_vec *div;
+ struct isl_vec *ineq;
+ int d;
+ div = get_row_split_div(tab, row);
+ if (!div)
+ goto error;
+ d = context->op->get_div(context, tab, div);
+ isl_vec_free(div);
+ if (d < 0)
+ goto error;
+ ineq = ineq_for_div(context->op->peek_basic_set(context), d);
+ if (!ineq)
+ goto error;
+ sol_inc_level(sol);
+ no_sol_in_strict(sol, tab, ineq);
+ isl_seq_neg(ineq->el, ineq->el, ineq->size);
+ context->op->add_ineq(context, ineq->el, 1, 1);
+ isl_vec_free(ineq);
+ if (sol->error || !context->op->is_ok(context))
+ goto error;
+ tab = set_row_cst_to_div(tab, row, d);
+ if (context->op->is_empty(context))
+ break;
+ } else
+ row = add_parametric_cut(tab, row, context);
+ if (row < 0)
+ goto error;
+ }
+ if (r < 0)
+ goto error;
+done:
+ sol_add(sol, tab);
+ isl_tab_free(tab);
+ return;
+error:
+ isl_tab_free(tab);
+ sol->error = 1;
+}
+
+/* Does "sol" contain a pair of partial solutions that could potentially
+ * be merged?
+ *
+ * We currently only check that "sol" is not in an error state
+ * and that there are at least two partial solutions of which the final two
+ * are defined at the same level.
+ */
+static int sol_has_mergeable_solutions(struct isl_sol *sol)
+{
+ if (sol->error)
+ return 0;
+ if (!sol->partial)
+ return 0;
+ if (!sol->partial->next)
+ return 0;
+ return sol->partial->level == sol->partial->next->level;
+}
+
+/* Compute the lexicographic minimum of the set represented by the main
+ * tableau "tab" within the context "sol->context_tab".
+ *
+ * As a preprocessing step, we first transfer all the purely parametric
+ * equalities from the main tableau to the context tableau, i.e.,
+ * parameters that have been pivoted to a row.
+ * These equalities are ignored by the main algorithm, because the
+ * corresponding rows may not be marked as being non-negative.
+ * In parts of the context where the added equality does not hold,
+ * the main tableau is marked as being empty.
+ *
+ * Before we embark on the actual computation, we save a copy
+ * of the context. When we return, we check if there are any
+ * partial solutions that can potentially be merged. If so,
+ * we perform a rollback to the initial state of the context.
+ * The merging of partial solutions happens inside calls to
+ * sol_dec_level that are pushed onto the undo stack of the context.
+ * If there are no partial solutions that can potentially be merged
+ * then the rollback is skipped as it would just be wasted effort.
+ */
+static void find_solutions_main(struct isl_sol *sol, struct isl_tab *tab)
+{
+ int row;
+ void *saved;
+
+ if (!tab)
+ goto error;
+
+ sol->level = 0;
+
+ for (row = tab->n_redundant; row < tab->n_row; ++row) {
+ int p;
+ struct isl_vec *eq;
+
+ if (tab->row_var[row] < 0)
+ continue;
+ if (tab->row_var[row] >= tab->n_param &&
+ tab->row_var[row] < tab->n_var - tab->n_div)
+ continue;
+ if (tab->row_var[row] < tab->n_param)
+ p = tab->row_var[row];
+ else
+ p = tab->row_var[row]
+ + tab->n_param - (tab->n_var - tab->n_div);
+
+ eq = isl_vec_alloc(tab->mat->ctx, 1+tab->n_param+tab->n_div);
+ if (!eq)
+ goto error;
+ get_row_parameter_line(tab, row, eq->el);
+ isl_int_neg(eq->el[1 + p], tab->mat->row[row][0]);
+ eq = isl_vec_normalize(eq);
+
+ sol_inc_level(sol);
+ no_sol_in_strict(sol, tab, eq);
+
+ isl_seq_neg(eq->el, eq->el, eq->size);
+ sol_inc_level(sol);
+ no_sol_in_strict(sol, tab, eq);
+ isl_seq_neg(eq->el, eq->el, eq->size);
+
+ sol->context->op->add_eq(sol->context, eq->el, 1, 1);
+
+ isl_vec_free(eq);
+
+ if (isl_tab_mark_redundant(tab, row) < 0)
+ goto error;
+
+ if (sol->context->op->is_empty(sol->context))
+ break;
+
+ row = tab->n_redundant - 1;
+ }
+
+ saved = sol->context->op->save(sol->context);
+
+ find_solutions(sol, tab);
+
+ if (sol_has_mergeable_solutions(sol))
+ sol->context->op->restore(sol->context, saved);
+ else
+ sol->context->op->discard(saved);
+
+ sol->level = 0;
+ sol_pop(sol);
+
+ return;
+error:
+ isl_tab_free(tab);
+ sol->error = 1;
+}
+
+/* Check if integer division "div" of "dom" also occurs in "bmap".
+ * If so, return its position within the divs.
+ * If not, return -1.
+ */
+static int find_context_div(struct isl_basic_map *bmap,
+ struct isl_basic_set *dom, unsigned div)
+{
+ int i;
+ unsigned b_dim = isl_space_dim(bmap->dim, isl_dim_all);
+ unsigned d_dim = isl_space_dim(dom->dim, isl_dim_all);
+
+ if (isl_int_is_zero(dom->div[div][0]))
+ return -1;
+ if (isl_seq_first_non_zero(dom->div[div] + 2 + d_dim, dom->n_div) != -1)
+ return -1;
+
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (isl_seq_first_non_zero(bmap->div[i] + 2 + d_dim,
+ (b_dim - d_dim) + bmap->n_div) != -1)
+ continue;
+ if (isl_seq_eq(bmap->div[i], dom->div[div], 2 + d_dim))
+ return i;
+ }
+ return -1;
+}
+
+/* The correspondence between the variables in the main tableau,
+ * the context tableau, and the input map and domain is as follows.
+ * The first n_param and the last n_div variables of the main tableau
+ * form the variables of the context tableau.
+ * In the basic map, these n_param variables correspond to the
+ * parameters and the input dimensions. In the domain, they correspond
+ * to the parameters and the set dimensions.
+ * The n_div variables correspond to the integer divisions in the domain.
+ * To ensure that everything lines up, we may need to copy some of the
+ * integer divisions of the domain to the map. These have to be placed
+ * in the same order as those in the context and they have to be placed
+ * after any other integer divisions that the map may have.
+ * This function performs the required reordering.
+ */
+static struct isl_basic_map *align_context_divs(struct isl_basic_map *bmap,
+ struct isl_basic_set *dom)
+{
+ int i;
+ int common = 0;
+ int other;
+
+ for (i = 0; i < dom->n_div; ++i)
+ if (find_context_div(bmap, dom, i) != -1)
+ common++;
+ other = bmap->n_div - common;
+ if (dom->n_div - common > 0) {
+ bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+ dom->n_div - common, 0, 0);
+ if (!bmap)
+ return NULL;
+ }
+ for (i = 0; i < dom->n_div; ++i) {
+ int pos = find_context_div(bmap, dom, i);
+ if (pos < 0) {
+ pos = isl_basic_map_alloc_div(bmap);
+ if (pos < 0)
+ goto error;
+ isl_int_set_si(bmap->div[pos][0], 0);
+ }
+ if (pos != other + i)
+ isl_basic_map_swap_div(bmap, pos, other + i);
+ }
+ return bmap;
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We make sure the divs in the domain are properly ordered,
+ * because they will be added one by one in the given order
+ * during the construction of the solution map.
+ */
+static struct isl_sol *basic_map_partial_lexopt_base(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max,
+ struct isl_sol *(*init)(__isl_keep isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom, int track_empty, int max))
+{
+ struct isl_tab *tab;
+ struct isl_sol *sol = NULL;
+ struct isl_context *context;
+
+ if (dom->n_div) {
+ dom = isl_basic_set_order_divs(dom);
+ bmap = align_context_divs(bmap, dom);
+ }
+ sol = init(bmap, dom, !!empty, max);
+ if (!sol)
+ goto error;
+
+ context = sol->context;
+ if (isl_basic_set_plain_is_empty(context->op->peek_basic_set(context)))
+ /* nothing */;
+ else if (isl_basic_map_plain_is_empty(bmap)) {
+ if (sol->add_empty)
+ sol->add_empty(sol,
+ isl_basic_set_copy(context->op->peek_basic_set(context)));
+ } else {
+ tab = tab_for_lexmin(bmap,
+ context->op->peek_basic_set(context), 1, max);
+ tab = context->op->detect_nonnegative_parameters(context, tab);
+ find_solutions_main(sol, tab);
+ }
+ if (sol->error)
+ goto error;
+
+ isl_basic_map_free(bmap);
+ return sol;
+error:
+ sol_free(sol);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We call basic_map_partial_lexopt_base and extract the results.
+ */
+static __isl_give isl_map *basic_map_partial_lexopt_base_map(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ isl_map *result = NULL;
+ struct isl_sol *sol;
+ struct isl_sol_map *sol_map;
+
+ sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
+ &sol_map_init);
+ if (!sol)
+ return NULL;
+ sol_map = (struct isl_sol_map *) sol;
+
+ result = isl_map_copy(sol_map->map);
+ if (empty)
+ *empty = isl_set_copy(sol_map->empty);
+ sol_free(&sol_map->sol);
+ return result;
+}
+
+/* Structure used during detection of parallel constraints.
+ * n_in: number of "input" variables: isl_dim_param + isl_dim_in
+ * n_out: number of "output" variables: isl_dim_out + isl_dim_div
+ * val: the coefficients of the output variables
+ */
+struct isl_constraint_equal_info {
+ isl_basic_map *bmap;
+ unsigned n_in;
+ unsigned n_out;
+ isl_int *val;
+};
+
+/* Check whether the coefficients of the output variables
+ * of the constraint in "entry" are equal to info->val.
+ */
+static int constraint_equal(const void *entry, const void *val)
+{
+ isl_int **row = (isl_int **)entry;
+ const struct isl_constraint_equal_info *info = val;
+
+ return isl_seq_eq((*row) + 1 + info->n_in, info->val, info->n_out);
+}
+
+/* Check whether "bmap" has a pair of constraints that have
+ * the same coefficients for the output variables.
+ * Note that the coefficients of the existentially quantified
+ * variables need to be zero since the existentially quantified
+ * of the result are usually not the same as those of the input.
+ * the isl_dim_out and isl_dim_div dimensions.
+ * If so, return 1 and return the row indices of the two constraints
+ * in *first and *second.
+ */
+static int parallel_constraints(__isl_keep isl_basic_map *bmap,
+ int *first, int *second)
+{
+ int i;
+ isl_ctx *ctx = isl_basic_map_get_ctx(bmap);
+ struct isl_hash_table *table = NULL;
+ struct isl_hash_table_entry *entry;
+ struct isl_constraint_equal_info info;
+ unsigned n_out;
+ unsigned n_div;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ table = isl_hash_table_alloc(ctx, bmap->n_ineq);
+ if (!table)
+ goto error;
+
+ info.n_in = isl_basic_map_dim(bmap, isl_dim_param) +
+ isl_basic_map_dim(bmap, isl_dim_in);
+ info.bmap = bmap;
+ n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ info.n_out = n_out + n_div;
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ uint32_t hash;
+
+ info.val = bmap->ineq[i] + 1 + info.n_in;
+ if (isl_seq_first_non_zero(info.val, n_out) < 0)
+ continue;
+ if (isl_seq_first_non_zero(info.val + n_out, n_div) >= 0)
+ continue;
+ hash = isl_seq_get_hash(info.val, info.n_out);
+ entry = isl_hash_table_find(ctx, table, hash,
+ constraint_equal, &info, 1);
+ if (!entry)
+ goto error;
+ if (entry->data)
+ break;
+ entry->data = &bmap->ineq[i];
+ }
+
+ if (i < bmap->n_ineq) {
+ *first = ((isl_int **)entry->data) - bmap->ineq;
+ *second = i;
+ }
+
+ isl_hash_table_free(ctx, table);
+
+ return i < bmap->n_ineq;
+error:
+ isl_hash_table_free(ctx, table);
+ return -1;
+}
+
+/* Given a set of upper bounds in "var", add constraints to "bset"
+ * that make the i-th bound smallest.
+ *
+ * In particular, if there are n bounds b_i, then add the constraints
+ *
+ * b_i <= b_j for j > i
+ * b_i < b_j for j < i
+ */
+static __isl_give isl_basic_set *select_minimum(__isl_take isl_basic_set *bset,
+ __isl_keep isl_mat *var, int i)
+{
+ isl_ctx *ctx;
+ int j, k;
+
+ ctx = isl_mat_get_ctx(var);
+
+ for (j = 0; j < var->n_row; ++j) {
+ if (j == i)
+ continue;
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_combine(bset->ineq[k], ctx->one, var->row[j],
+ ctx->negone, var->row[i], var->n_col);
+ isl_int_set_si(bset->ineq[k][var->n_col], 0);
+ if (j < i)
+ isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+ }
+
+ bset = isl_basic_set_finalize(bset);
+
+ return bset;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+/* Given a set of upper bounds on the last "input" variable m,
+ * construct a set that assigns the minimal upper bound to m, i.e.,
+ * construct a set that divides the space into cells where one
+ * of the upper bounds is smaller than all the others and assign
+ * this upper bound to m.
+ *
+ * In particular, if there are n bounds b_i, then the result
+ * consists of n basic sets, each one of the form
+ *
+ * m = b_i
+ * b_i <= b_j for j > i
+ * b_i < b_j for j < i
+ */
+static __isl_give isl_set *set_minimum(__isl_take isl_space *dim,
+ __isl_take isl_mat *var)
+{
+ int i, k;
+ isl_basic_set *bset = NULL;
+ isl_ctx *ctx;
+ isl_set *set = NULL;
+
+ if (!dim || !var)
+ goto error;
+
+ ctx = isl_space_get_ctx(dim);
+ set = isl_set_alloc_space(isl_space_copy(dim),
+ var->n_row, ISL_SET_DISJOINT);
+
+ for (i = 0; i < var->n_row; ++i) {
+ bset = isl_basic_set_alloc_space(isl_space_copy(dim), 0,
+ 1, var->n_row - 1);
+ k = isl_basic_set_alloc_equality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(bset->eq[k], var->row[i], var->n_col);
+ isl_int_set_si(bset->eq[k][var->n_col], -1);
+ bset = select_minimum(bset, var, i);
+ set = isl_set_add_basic_set(set, bset);
+ }
+
+ isl_space_free(dim);
+ isl_mat_free(var);
+ return set;
+error:
+ isl_basic_set_free(bset);
+ isl_set_free(set);
+ isl_space_free(dim);
+ isl_mat_free(var);
+ return NULL;
+}
+
+/* Given that the last input variable of "bmap" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ *
+ * A split is needed when the minimum appears in an integer division
+ * or in an equality. Otherwise, it is only needed if it appears in
+ * an upper bound that is different from the upper bounds on which it
+ * is defined.
+ */
+static int need_split_basic_map(__isl_keep isl_basic_map *bmap,
+ __isl_keep isl_mat *cst)
+{
+ int i, j;
+ unsigned total;
+ unsigned pos;
+
+ pos = cst->n_col - 1;
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+
+ for (i = 0; i < bmap->n_div; ++i)
+ if (!isl_int_is_zero(bmap->div[i][2 + pos]))
+ return 1;
+
+ for (i = 0; i < bmap->n_eq; ++i)
+ if (!isl_int_is_zero(bmap->eq[i][1 + pos]))
+ return 1;
+
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (isl_int_is_nonneg(bmap->ineq[i][1 + pos]))
+ continue;
+ if (!isl_int_is_negone(bmap->ineq[i][1 + pos]))
+ return 1;
+ if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + pos + 1,
+ total - pos - 1) >= 0)
+ return 1;
+
+ for (j = 0; j < cst->n_row; ++j)
+ if (isl_seq_eq(bmap->ineq[i], cst->row[j], cst->n_col))
+ break;
+ if (j >= cst->n_row)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Given that the last set variable of "bset" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ *
+ * We simply call need_split_basic_map here. This is safe because
+ * the position of the minimum is computed from "cst" and not
+ * from "bmap".
+ */
+static int need_split_basic_set(__isl_keep isl_basic_set *bset,
+ __isl_keep isl_mat *cst)
+{
+ return need_split_basic_map((isl_basic_map *)bset, cst);
+}
+
+/* Given that the last set variable of "set" represents the minimum
+ * of the bounds in "cst", check whether we need to split the domain
+ * based on which bound attains the minimum.
+ */
+static int need_split_set(__isl_keep isl_set *set, __isl_keep isl_mat *cst)
+{
+ int i;
+
+ for (i = 0; i < set->n; ++i)
+ if (need_split_basic_set(set->p[i], cst))
+ return 1;
+
+ return 0;
+}
+
+/* Given a set of which the last set variable is the minimum
+ * of the bounds in "cst", split each basic set in the set
+ * in pieces where one of the bounds is (strictly) smaller than the others.
+ * This subdivision is given in "min_expr".
+ * The variable is subsequently projected out.
+ *
+ * We only do the split when it is needed.
+ * For example if the last input variable m = min(a,b) and the only
+ * constraints in the given basic set are lower bounds on m,
+ * i.e., l <= m = min(a,b), then we can simply project out m
+ * to obtain l <= a and l <= b, without having to split on whether
+ * m is equal to a or b.
+ */
+static __isl_give isl_set *split(__isl_take isl_set *empty,
+ __isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+ int n_in;
+ int i;
+ isl_space *dim;
+ isl_set *res;
+
+ if (!empty || !min_expr || !cst)
+ goto error;
+
+ n_in = isl_set_dim(empty, isl_dim_set);
+ dim = isl_set_get_space(empty);
+ dim = isl_space_drop_dims(dim, isl_dim_set, n_in - 1, 1);
+ res = isl_set_empty(dim);
+
+ for (i = 0; i < empty->n; ++i) {
+ isl_set *set;
+
+ set = isl_set_from_basic_set(isl_basic_set_copy(empty->p[i]));
+ if (need_split_basic_set(empty->p[i], cst))
+ set = isl_set_intersect(set, isl_set_copy(min_expr));
+ set = isl_set_remove_dims(set, isl_dim_set, n_in - 1, 1);
+
+ res = isl_set_union_disjoint(res, set);
+ }
+
+ isl_set_free(empty);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return res;
+error:
+ isl_set_free(empty);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return NULL;
+}
+
+/* Given a map of which the last input variable is the minimum
+ * of the bounds in "cst", split each basic set in the set
+ * in pieces where one of the bounds is (strictly) smaller than the others.
+ * This subdivision is given in "min_expr".
+ * The variable is subsequently projected out.
+ *
+ * The implementation is essentially the same as that of "split".
+ */
+static __isl_give isl_map *split_domain(__isl_take isl_map *opt,
+ __isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+ int n_in;
+ int i;
+ isl_space *dim;
+ isl_map *res;
+
+ if (!opt || !min_expr || !cst)
+ goto error;
+
+ n_in = isl_map_dim(opt, isl_dim_in);
+ dim = isl_map_get_space(opt);
+ dim = isl_space_drop_dims(dim, isl_dim_in, n_in - 1, 1);
+ res = isl_map_empty(dim);
+
+ for (i = 0; i < opt->n; ++i) {
+ isl_map *map;
+
+ map = isl_map_from_basic_map(isl_basic_map_copy(opt->p[i]));
+ if (need_split_basic_map(opt->p[i], cst))
+ map = isl_map_intersect_domain(map,
+ isl_set_copy(min_expr));
+ map = isl_map_remove_dims(map, isl_dim_in, n_in - 1, 1);
+
+ res = isl_map_union_disjoint(res, map);
+ }
+
+ isl_map_free(opt);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return res;
+error:
+ isl_map_free(opt);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return NULL;
+}
+
+static __isl_give isl_map *basic_map_partial_lexopt(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max);
+
+union isl_lex_res {
+ void *p;
+ isl_map *map;
+ isl_pw_multi_aff *pma;
+};
+
+/* This function is called from basic_map_partial_lexopt_symm.
+ * The last variable of "bmap" and "dom" corresponds to the minimum
+ * of the bounds in "cst". "map_space" is the space of the original
+ * input relation (of basic_map_partial_lexopt_symm) and "set_space"
+ * is the space of the original domain.
+ *
+ * We recursively call basic_map_partial_lexopt and then plug in
+ * the definition of the minimum in the result.
+ */
+static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_map_core(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
+ __isl_take isl_space *map_space, __isl_take isl_space *set_space)
+{
+ isl_map *opt;
+ isl_set *min_expr;
+ union isl_lex_res res;
+
+ min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
+
+ opt = basic_map_partial_lexopt(bmap, dom, empty, max);
+
+ if (empty) {
+ *empty = split(*empty,
+ isl_set_copy(min_expr), isl_mat_copy(cst));
+ *empty = isl_set_reset_space(*empty, set_space);
+ }
+
+ opt = split_domain(opt, min_expr, cst);
+ opt = isl_map_reset_space(opt, map_space);
+
+ res.map = opt;
+ return res;
+}
+
+/* Given a basic map with at least two parallel constraints (as found
+ * by the function parallel_constraints), first look for more constraints
+ * parallel to the two constraint and replace the found list of parallel
+ * constraints by a single constraint with as "input" part the minimum
+ * of the input parts of the list of constraints. Then, recursively call
+ * basic_map_partial_lexopt (possibly finding more parallel constraints)
+ * and plug in the definition of the minimum in the result.
+ *
+ * More specifically, given a set of constraints
+ *
+ * a x + b_i(p) >= 0
+ *
+ * Replace this set by a single constraint
+ *
+ * a x + u >= 0
+ *
+ * with u a new parameter with constraints
+ *
+ * u <= b_i(p)
+ *
+ * Any solution to the new system is also a solution for the original system
+ * since
+ *
+ * a x >= -u >= -b_i(p)
+ *
+ * Moreover, m = min_i(b_i(p)) satisfies the constraints on u and can
+ * therefore be plugged into the solution.
+ */
+static union isl_lex_res basic_map_partial_lexopt_symm(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max, int first, int second,
+ __isl_give union isl_lex_res (*core)(__isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty,
+ int max, __isl_take isl_mat *cst,
+ __isl_take isl_space *map_space,
+ __isl_take isl_space *set_space))
+{
+ int i, n, k;
+ int *list = NULL;
+ unsigned n_in, n_out, n_div;
+ isl_ctx *ctx;
+ isl_vec *var = NULL;
+ isl_mat *cst = NULL;
+ isl_space *map_space, *set_space;
+ union isl_lex_res res;
+
+ map_space = isl_basic_map_get_space(bmap);
+ set_space = empty ? isl_basic_set_get_space(dom) : NULL;
+
+ n_in = isl_basic_map_dim(bmap, isl_dim_param) +
+ isl_basic_map_dim(bmap, isl_dim_in);
+ n_out = isl_basic_map_dim(bmap, isl_dim_all) - n_in;
+
+ ctx = isl_basic_map_get_ctx(bmap);
+ list = isl_alloc_array(ctx, int, bmap->n_ineq);
+ var = isl_vec_alloc(ctx, n_out);
+ if ((bmap->n_ineq && !list) || (n_out && !var))
+ goto error;
+
+ list[0] = first;
+ list[1] = second;
+ isl_seq_cpy(var->el, bmap->ineq[first] + 1 + n_in, n_out);
+ for (i = second + 1, n = 2; i < bmap->n_ineq; ++i) {
+ if (isl_seq_eq(var->el, bmap->ineq[i] + 1 + n_in, n_out))
+ list[n++] = i;
+ }
+
+ cst = isl_mat_alloc(ctx, n, 1 + n_in);
+ if (!cst)
+ goto error;
+
+ for (i = 0; i < n; ++i)
+ isl_seq_cpy(cst->row[i], bmap->ineq[list[i]], 1 + n_in);
+
+ bmap = isl_basic_map_cow(bmap);
+ if (!bmap)
+ goto error;
+ for (i = n - 1; i >= 0; --i)
+ if (isl_basic_map_drop_inequality(bmap, list[i]) < 0)
+ goto error;
+
+ bmap = isl_basic_map_add(bmap, isl_dim_in, 1);
+ bmap = isl_basic_map_extend_constraints(bmap, 0, 1);
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k], 1 + n_in);
+ isl_int_set_si(bmap->ineq[k][1 + n_in], 1);
+ isl_seq_cpy(bmap->ineq[k] + 1 + n_in + 1, var->el, n_out);
+ bmap = isl_basic_map_finalize(bmap);
+
+ n_div = isl_basic_set_dim(dom, isl_dim_div);
+ dom = isl_basic_set_add_dims(dom, isl_dim_set, 1);
+ dom = isl_basic_set_extend_constraints(dom, 0, n);
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_set_alloc_inequality(dom);
+ if (k < 0)
+ goto error;
+ isl_seq_cpy(dom->ineq[k], cst->row[i], 1 + n_in);
+ isl_int_set_si(dom->ineq[k][1 + n_in], -1);
+ isl_seq_clr(dom->ineq[k] + 1 + n_in + 1, n_div);
+ }
+
+ isl_vec_free(var);
+ free(list);
+
+ return core(bmap, dom, empty, max, cst, map_space, set_space);
+error:
+ isl_space_free(map_space);
+ isl_space_free(set_space);
+ isl_mat_free(cst);
+ isl_vec_free(var);
+ free(list);
+ isl_basic_set_free(dom);
+ isl_basic_map_free(bmap);
+ res.p = NULL;
+ return res;
+}
+
+static __isl_give isl_map *basic_map_partial_lexopt_symm_map(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max, int first, int second)
+{
+ return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
+ first, second, &basic_map_partial_lexopt_symm_map_core).map;
+}
+
+/* Recursive part of isl_tab_basic_map_partial_lexopt, after detecting
+ * equalities and removing redundant constraints.
+ *
+ * We first check if there are any parallel constraints (left).
+ * If not, we are in the base case.
+ * If there are parallel constraints, we replace them by a single
+ * constraint in basic_map_partial_lexopt_symm and then call
+ * this function recursively to look for more parallel constraints.
+ */
+static __isl_give isl_map *basic_map_partial_lexopt(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ int par = 0;
+ int first, second;
+
+ if (!bmap)
+ goto error;
+
+ if (bmap->ctx->opt->pip_symmetry)
+ par = parallel_constraints(bmap, &first, &second);
+ if (par < 0)
+ goto error;
+ if (!par)
+ return basic_map_partial_lexopt_base_map(bmap, dom, empty, max);
+
+ return basic_map_partial_lexopt_symm_map(bmap, dom, empty, max,
+ first, second);
+error:
+ isl_basic_set_free(dom);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over the domain "dom" and return the result as a map.
+ * If "empty" is not NULL, then *empty is assigned a set that
+ * contains those parts of the domain where there is no solution.
+ * If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
+ * then we compute the rational optimum. Otherwise, we compute
+ * the integral optimum.
+ *
+ * We perform some preprocessing. As the PILP solver does not
+ * handle implicit equalities very well, we first make sure all
+ * the equalities are explicitly available.
+ *
+ * We also add context constraints to the basic map and remove
+ * redundant constraints. This is only needed because of the
+ * way we handle simple symmetries. In particular, we currently look
+ * for symmetries on the constraints, before we set up the main tableau.
+ * It is then no good to look for symmetries on possibly redundant constraints.
+ */
+struct isl_map *isl_tab_basic_map_partial_lexopt(
+ struct isl_basic_map *bmap, struct isl_basic_set *dom,
+ struct isl_set **empty, int max)
+{
+ if (empty)
+ *empty = NULL;
+ if (!bmap || !dom)
+ goto error;
+
+ isl_assert(bmap->ctx,
+ isl_basic_map_compatible_domain(bmap, dom), goto error);
+
+ if (isl_basic_set_dim(dom, isl_dim_all) == 0)
+ return basic_map_partial_lexopt(bmap, dom, empty, max);
+
+ bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
+ bmap = isl_basic_map_detect_equalities(bmap);
+ bmap = isl_basic_map_remove_redundancies(bmap);
+
+ return basic_map_partial_lexopt(bmap, dom, empty, max);
+error:
+ isl_basic_set_free(dom);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+struct isl_sol_for {
+ struct isl_sol sol;
+ int (*fn)(__isl_take isl_basic_set *dom,
+ __isl_take isl_aff_list *list, void *user);
+ void *user;
+};
+
+static void sol_for_free(struct isl_sol_for *sol_for)
+{
+ if (!sol_for)
+ return;
+ if (sol_for->sol.context)
+ sol_for->sol.context->op->free(sol_for->sol.context);
+ free(sol_for);
+}
+
+static void sol_for_free_wrap(struct isl_sol *sol)
+{
+ sol_for_free((struct isl_sol_for *)sol);
+}
+
+/* Add the solution identified by the tableau and the context tableau.
+ *
+ * See documentation of sol_add for more details.
+ *
+ * Instead of constructing a basic map, this function calls a user
+ * defined function with the current context as a basic set and
+ * a list of affine expressions representing the relation between
+ * the input and output. The space over which the affine expressions
+ * are defined is the same as that of the domain. The number of
+ * affine expressions in the list is equal to the number of output variables.
+ */
+static void sol_for_add(struct isl_sol_for *sol,
+ struct isl_basic_set *dom, struct isl_mat *M)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_local_space *ls;
+ isl_aff *aff;
+ isl_aff_list *list;
+
+ if (sol->sol.error || !dom || !M)
+ goto error;
+
+ ctx = isl_basic_set_get_ctx(dom);
+ ls = isl_basic_set_get_local_space(dom);
+ list = isl_aff_list_alloc(ctx, M->n_row - 1);
+ for (i = 1; i < M->n_row; ++i) {
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ if (aff) {
+ isl_int_set(aff->v->el[0], M->row[0][0]);
+ isl_seq_cpy(aff->v->el + 1, M->row[i], M->n_col);
+ }
+ aff = isl_aff_normalize(aff);
+ list = isl_aff_list_add(list, aff);
+ }
+ isl_local_space_free(ls);
+
+ dom = isl_basic_set_finalize(dom);
+
+ if (sol->fn(isl_basic_set_copy(dom), list, sol->user) < 0)
+ goto error;
+
+ isl_basic_set_free(dom);
+ isl_mat_free(M);
+ return;
+error:
+ isl_basic_set_free(dom);
+ isl_mat_free(M);
+ sol->sol.error = 1;
+}
+
+static void sol_for_add_wrap(struct isl_sol *sol,
+ struct isl_basic_set *dom, struct isl_mat *M)
+{
+ sol_for_add((struct isl_sol_for *)sol, dom, M);
+}
+
+static struct isl_sol_for *sol_for_init(struct isl_basic_map *bmap, int max,
+ int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+ void *user),
+ void *user)
+{
+ struct isl_sol_for *sol_for = NULL;
+ isl_space *dom_dim;
+ struct isl_basic_set *dom = NULL;
+
+ sol_for = isl_calloc_type(bmap->ctx, struct isl_sol_for);
+ if (!sol_for)
+ goto error;
+
+ dom_dim = isl_space_domain(isl_space_copy(bmap->dim));
+ dom = isl_basic_set_universe(dom_dim);
+
+ sol_for->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+ sol_for->sol.dec_level.callback.run = &sol_dec_level_wrap;
+ sol_for->sol.dec_level.sol = &sol_for->sol;
+ sol_for->fn = fn;
+ sol_for->user = user;
+ sol_for->sol.max = max;
+ sol_for->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ sol_for->sol.add = &sol_for_add_wrap;
+ sol_for->sol.add_empty = NULL;
+ sol_for->sol.free = &sol_for_free_wrap;
+
+ sol_for->sol.context = isl_context_alloc(dom);
+ if (!sol_for->sol.context)
+ goto error;
+
+ isl_basic_set_free(dom);
+ return sol_for;
+error:
+ isl_basic_set_free(dom);
+ sol_for_free(sol_for);
+ return NULL;
+}
+
+static void sol_for_find_solutions(struct isl_sol_for *sol_for,
+ struct isl_tab *tab)
+{
+ find_solutions_main(&sol_for->sol, tab);
+}
+
+int isl_basic_map_foreach_lexopt(__isl_keep isl_basic_map *bmap, int max,
+ int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+ void *user),
+ void *user)
+{
+ struct isl_sol_for *sol_for = NULL;
+
+ bmap = isl_basic_map_copy(bmap);
+ bmap = isl_basic_map_detect_equalities(bmap);
+ if (!bmap)
+ return -1;
+
+ sol_for = sol_for_init(bmap, max, fn, user);
+ if (!sol_for)
+ goto error;
+
+ if (isl_basic_map_plain_is_empty(bmap))
+ /* nothing */;
+ else {
+ struct isl_tab *tab;
+ struct isl_context *context = sol_for->sol.context;
+ tab = tab_for_lexmin(bmap,
+ context->op->peek_basic_set(context), 1, max);
+ tab = context->op->detect_nonnegative_parameters(context, tab);
+ sol_for_find_solutions(sol_for, tab);
+ if (sol_for->sol.error)
+ goto error;
+ }
+
+ sol_free(&sol_for->sol);
+ isl_basic_map_free(bmap);
+ return 0;
+error:
+ sol_free(&sol_for->sol);
+ isl_basic_map_free(bmap);
+ return -1;
+}
+
+int isl_basic_set_foreach_lexopt(__isl_keep isl_basic_set *bset, int max,
+ int (*fn)(__isl_take isl_basic_set *dom, __isl_take isl_aff_list *list,
+ void *user),
+ void *user)
+{
+ return isl_basic_map_foreach_lexopt(bset, max, fn, user);
+}
+
+/* Check if the given sequence of len variables starting at pos
+ * represents a trivial (i.e., zero) solution.
+ * The variables are assumed to be non-negative and to come in pairs,
+ * with each pair representing a variable of unrestricted sign.
+ * The solution is trivial if each such pair in the sequence consists
+ * of two identical values, meaning that the variable being represented
+ * has value zero.
+ */
+static int region_is_trivial(struct isl_tab *tab, int pos, int len)
+{
+ int i;
+
+ if (len == 0)
+ return 0;
+
+ for (i = 0; i < len; i += 2) {
+ int neg_row;
+ int pos_row;
+
+ neg_row = tab->var[pos + i].is_row ?
+ tab->var[pos + i].index : -1;
+ pos_row = tab->var[pos + i + 1].is_row ?
+ tab->var[pos + i + 1].index : -1;
+
+ if ((neg_row < 0 ||
+ isl_int_is_zero(tab->mat->row[neg_row][1])) &&
+ (pos_row < 0 ||
+ isl_int_is_zero(tab->mat->row[pos_row][1])))
+ continue;
+
+ if (neg_row < 0 || pos_row < 0)
+ return 0;
+ if (isl_int_ne(tab->mat->row[neg_row][1],
+ tab->mat->row[pos_row][1]))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return the index of the first trivial region or -1 if all regions
+ * are non-trivial.
+ */
+static int first_trivial_region(struct isl_tab *tab,
+ int n_region, struct isl_region *region)
+{
+ int i;
+
+ for (i = 0; i < n_region; ++i) {
+ if (region_is_trivial(tab, region[i].pos, region[i].len))
+ return i;
+ }
+
+ return -1;
+}
+
+/* Check if the solution is optimal, i.e., whether the first
+ * n_op entries are zero.
+ */
+static int is_optimal(__isl_keep isl_vec *sol, int n_op)
+{
+ int i;
+
+ for (i = 0; i < n_op; ++i)
+ if (!isl_int_is_zero(sol->el[1 + i]))
+ return 0;
+ return 1;
+}
+
+/* Add constraints to "tab" that ensure that any solution is significantly
+ * better that that represented by "sol". That is, find the first
+ * relevant (within first n_op) non-zero coefficient and force it (along
+ * with all previous coefficients) to be zero.
+ * If the solution is already optimal (all relevant coefficients are zero),
+ * then just mark the table as empty.
+ */
+static int force_better_solution(struct isl_tab *tab,
+ __isl_keep isl_vec *sol, int n_op)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_vec *v = NULL;
+
+ if (!sol)
+ return -1;
+
+ for (i = 0; i < n_op; ++i)
+ if (!isl_int_is_zero(sol->el[1 + i]))
+ break;
+
+ if (i == n_op) {
+ if (isl_tab_mark_empty(tab) < 0)
+ return -1;
+ return 0;
+ }
+
+ ctx = isl_vec_get_ctx(sol);
+ v = isl_vec_alloc(ctx, 1 + tab->n_var);
+ if (!v)
+ return -1;
+
+ for (; i >= 0; --i) {
+ v = isl_vec_clr(v);
+ isl_int_set_si(v->el[1 + i], -1);
+ if (add_lexmin_eq(tab, v->el) < 0)
+ goto error;
+ }
+
+ isl_vec_free(v);
+ return 0;
+error:
+ isl_vec_free(v);
+ return -1;
+}
+
+struct isl_trivial {
+ int update;
+ int region;
+ int side;
+ struct isl_tab_undo *snap;
+};
+
+/* Return the lexicographically smallest non-trivial solution of the
+ * given ILP problem.
+ *
+ * All variables are assumed to be non-negative.
+ *
+ * n_op is the number of initial coordinates to optimize.
+ * That is, once a solution has been found, we will only continue looking
+ * for solution that result in significantly better values for those
+ * initial coordinates. That is, we only continue looking for solutions
+ * that increase the number of initial zeros in this sequence.
+ *
+ * A solution is non-trivial, if it is non-trivial on each of the
+ * specified regions. Each region represents a sequence of pairs
+ * of variables. A solution is non-trivial on such a region if
+ * at least one of these pairs consists of different values, i.e.,
+ * such that the non-negative variable represented by the pair is non-zero.
+ *
+ * Whenever a conflict is encountered, all constraints involved are
+ * reported to the caller through a call to "conflict".
+ *
+ * We perform a simple branch-and-bound backtracking search.
+ * Each level in the search represents initially trivial region that is forced
+ * to be non-trivial.
+ * At each level we consider n cases, where n is the length of the region.
+ * In terms of the n/2 variables of unrestricted signs being encoded by
+ * the region, we consider the cases
+ * x_0 >= 1
+ * x_0 <= -1
+ * x_0 = 0 and x_1 >= 1
+ * x_0 = 0 and x_1 <= -1
+ * x_0 = 0 and x_1 = 0 and x_2 >= 1
+ * x_0 = 0 and x_1 = 0 and x_2 <= -1
+ * ...
+ * The cases are considered in this order, assuming that each pair
+ * x_i_a x_i_b represents the value x_i_b - x_i_a.
+ * That is, x_0 >= 1 is enforced by adding the constraint
+ * x_0_b - x_0_a >= 1
+ */
+__isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
+ __isl_take isl_basic_set *bset, int n_op, int n_region,
+ struct isl_region *region,
+ int (*conflict)(int con, void *user), void *user)
+{
+ int i, j;
+ int r;
+ isl_ctx *ctx;
+ isl_vec *v = NULL;
+ isl_vec *sol = NULL;
+ struct isl_tab *tab;
+ struct isl_trivial *triv = NULL;
+ int level, init;
+
+ if (!bset)
+ return NULL;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ sol = isl_vec_alloc(ctx, 0);
+
+ tab = tab_for_lexmin(bset, NULL, 0, 0);
+ if (!tab)
+ goto error;
+ tab->conflict = conflict;
+ tab->conflict_user = user;
+
+ v = isl_vec_alloc(ctx, 1 + tab->n_var);
+ triv = isl_calloc_array(ctx, struct isl_trivial, n_region);
+ if (!v || (n_region && !triv))
+ goto error;
+
+ level = 0;
+ init = 1;
+
+ while (level >= 0) {
+ int side, base;
+
+ if (init) {
+ tab = cut_to_integer_lexmin(tab, CUT_ONE);
+ if (!tab)
+ goto error;
+ if (tab->empty)
+ goto backtrack;
+ r = first_trivial_region(tab, n_region, region);
+ if (r < 0) {
+ for (i = 0; i < level; ++i)
+ triv[i].update = 1;
+ isl_vec_free(sol);
+ sol = isl_tab_get_sample_value(tab);
+ if (!sol)
+ goto error;
+ if (is_optimal(sol, n_op))
+ break;
+ goto backtrack;
+ }
+ if (level >= n_region)
+ isl_die(ctx, isl_error_internal,
+ "nesting level too deep", goto error);
+ if (isl_tab_extend_cons(tab,
+ 2 * region[r].len + 2 * n_op) < 0)
+ goto error;
+ triv[level].region = r;
+ triv[level].side = 0;
+ }
+
+ r = triv[level].region;
+ side = triv[level].side;
+ base = 2 * (side/2);
+
+ if (side >= region[r].len) {
+backtrack:
+ level--;
+ init = 0;
+ if (level >= 0)
+ if (isl_tab_rollback(tab, triv[level].snap) < 0)
+ goto error;
+ continue;
+ }
+
+ if (triv[level].update) {
+ if (force_better_solution(tab, sol, n_op) < 0)
+ goto error;
+ triv[level].update = 0;
+ }
+
+ if (side == base && base >= 2) {
+ for (j = base - 2; j < base; ++j) {
+ v = isl_vec_clr(v);
+ isl_int_set_si(v->el[1 + region[r].pos + j], 1);
+ if (add_lexmin_eq(tab, v->el) < 0)
+ goto error;
+ }
+ }
+
+ triv[level].snap = isl_tab_snap(tab);
+ if (isl_tab_push_basis(tab) < 0)
+ goto error;
+
+ v = isl_vec_clr(v);
+ isl_int_set_si(v->el[0], -1);
+ isl_int_set_si(v->el[1 + region[r].pos + side], -1);
+ isl_int_set_si(v->el[1 + region[r].pos + (side ^ 1)], 1);
+ tab = add_lexmin_ineq(tab, v->el);
+
+ triv[level].side++;
+ level++;
+ init = 1;
+ }
+
+ free(triv);
+ isl_vec_free(v);
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+
+ return sol;
+error:
+ free(triv);
+ isl_vec_free(v);
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+ isl_vec_free(sol);
+ return NULL;
+}
+
+/* Return the lexicographically smallest rational point in "bset",
+ * assuming that all variables are non-negative.
+ * If "bset" is empty, then return a zero-length vector.
+ */
+__isl_give isl_vec *isl_tab_basic_set_non_neg_lexmin(
+ __isl_take isl_basic_set *bset)
+{
+ struct isl_tab *tab;
+ isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+ isl_vec *sol;
+
+ if (!bset)
+ return NULL;
+
+ tab = tab_for_lexmin(bset, NULL, 0, 0);
+ if (!tab)
+ goto error;
+ if (tab->empty)
+ sol = isl_vec_alloc(ctx, 0);
+ else
+ sol = isl_tab_get_sample_value(tab);
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+ return sol;
+error:
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_sol_pma {
+ struct isl_sol sol;
+ isl_pw_multi_aff *pma;
+ isl_set *empty;
+};
+
+static void sol_pma_free(struct isl_sol_pma *sol_pma)
+{
+ if (!sol_pma)
+ return;
+ if (sol_pma->sol.context)
+ sol_pma->sol.context->op->free(sol_pma->sol.context);
+ isl_pw_multi_aff_free(sol_pma->pma);
+ isl_set_free(sol_pma->empty);
+ free(sol_pma);
+}
+
+/* This function is called for parts of the context where there is
+ * no solution, with "bset" corresponding to the context tableau.
+ * Simply add the basic set to the set "empty".
+ */
+static void sol_pma_add_empty(struct isl_sol_pma *sol,
+ __isl_take isl_basic_set *bset)
+{
+ if (!bset)
+ goto error;
+ isl_assert(bset->ctx, sol->empty, goto error);
+
+ sol->empty = isl_set_grow(sol->empty, 1);
+ bset = isl_basic_set_simplify(bset);
+ bset = isl_basic_set_finalize(bset);
+ sol->empty = isl_set_add_basic_set(sol->empty, bset);
+ if (!sol->empty)
+ sol->sol.error = 1;
+ return;
+error:
+ isl_basic_set_free(bset);
+ sol->sol.error = 1;
+}
+
+/* Given a basic map "dom" that represents the context and an affine
+ * matrix "M" that maps the dimensions of the context to the
+ * output variables, construct an isl_pw_multi_aff with a single
+ * cell corresponding to "dom" and affine expressions copied from "M".
+ */
+static void sol_pma_add(struct isl_sol_pma *sol,
+ __isl_take isl_basic_set *dom, __isl_take isl_mat *M)
+{
+ int i;
+ isl_local_space *ls;
+ isl_aff *aff;
+ isl_multi_aff *maff;
+ isl_pw_multi_aff *pma;
+
+ maff = isl_multi_aff_alloc(isl_pw_multi_aff_get_space(sol->pma));
+ ls = isl_basic_set_get_local_space(dom);
+ for (i = 1; i < M->n_row; ++i) {
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ if (aff) {
+ isl_int_set(aff->v->el[0], M->row[0][0]);
+ isl_seq_cpy(aff->v->el + 1, M->row[i], M->n_col);
+ }
+ aff = isl_aff_normalize(aff);
+ maff = isl_multi_aff_set_aff(maff, i - 1, aff);
+ }
+ isl_local_space_free(ls);
+ isl_mat_free(M);
+ dom = isl_basic_set_simplify(dom);
+ dom = isl_basic_set_finalize(dom);
+ pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(dom), maff);
+ sol->pma = isl_pw_multi_aff_add_disjoint(sol->pma, pma);
+ if (!sol->pma)
+ sol->sol.error = 1;
+}
+
+static void sol_pma_free_wrap(struct isl_sol *sol)
+{
+ sol_pma_free((struct isl_sol_pma *)sol);
+}
+
+static void sol_pma_add_empty_wrap(struct isl_sol *sol,
+ __isl_take isl_basic_set *bset)
+{
+ sol_pma_add_empty((struct isl_sol_pma *)sol, bset);
+}
+
+static void sol_pma_add_wrap(struct isl_sol *sol,
+ __isl_take isl_basic_set *dom, __isl_take isl_mat *M)
+{
+ sol_pma_add((struct isl_sol_pma *)sol, dom, M);
+}
+
+/* Construct an isl_sol_pma structure for accumulating the solution.
+ * If track_empty is set, then we also keep track of the parts
+ * of the context where there is no solution.
+ * If max is set, then we are solving a maximization, rather than
+ * a minimization problem, which means that the variables in the
+ * tableau have value "M - x" rather than "M + x".
+ */
+static struct isl_sol *sol_pma_init(__isl_keep isl_basic_map *bmap,
+ __isl_take isl_basic_set *dom, int track_empty, int max)
+{
+ struct isl_sol_pma *sol_pma = NULL;
+
+ if (!bmap)
+ goto error;
+
+ sol_pma = isl_calloc_type(bmap->ctx, struct isl_sol_pma);
+ if (!sol_pma)
+ goto error;
+
+ sol_pma->sol.rational = ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL);
+ sol_pma->sol.dec_level.callback.run = &sol_dec_level_wrap;
+ sol_pma->sol.dec_level.sol = &sol_pma->sol;
+ sol_pma->sol.max = max;
+ sol_pma->sol.n_out = isl_basic_map_dim(bmap, isl_dim_out);
+ sol_pma->sol.add = &sol_pma_add_wrap;
+ sol_pma->sol.add_empty = track_empty ? &sol_pma_add_empty_wrap : NULL;
+ sol_pma->sol.free = &sol_pma_free_wrap;
+ sol_pma->pma = isl_pw_multi_aff_empty(isl_basic_map_get_space(bmap));
+ if (!sol_pma->pma)
+ goto error;
+
+ sol_pma->sol.context = isl_context_alloc(dom);
+ if (!sol_pma->sol.context)
+ goto error;
+
+ if (track_empty) {
+ sol_pma->empty = isl_set_alloc_space(isl_basic_set_get_space(dom),
+ 1, ISL_SET_DISJOINT);
+ if (!sol_pma->empty)
+ goto error;
+ }
+
+ isl_basic_set_free(dom);
+ return &sol_pma->sol;
+error:
+ isl_basic_set_free(dom);
+ sol_pma_free(sol_pma);
+ return NULL;
+}
+
+/* Base case of isl_tab_basic_map_partial_lexopt, after removing
+ * some obvious symmetries.
+ *
+ * We call basic_map_partial_lexopt_base and extract the results.
+ */
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_base_pma(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ isl_pw_multi_aff *result = NULL;
+ struct isl_sol *sol;
+ struct isl_sol_pma *sol_pma;
+
+ sol = basic_map_partial_lexopt_base(bmap, dom, empty, max,
+ &sol_pma_init);
+ if (!sol)
+ return NULL;
+ sol_pma = (struct isl_sol_pma *) sol;
+
+ result = isl_pw_multi_aff_copy(sol_pma->pma);
+ if (empty)
+ *empty = isl_set_copy(sol_pma->empty);
+ sol_free(&sol_pma->sol);
+ return result;
+}
+
+/* Given that the last input variable of "maff" represents the minimum
+ * of some bounds, check whether we need to plug in the expression
+ * of the minimum.
+ *
+ * In particular, check if the last input variable appears in any
+ * of the expressions in "maff".
+ */
+static int need_substitution(__isl_keep isl_multi_aff *maff)
+{
+ int i;
+ unsigned pos;
+
+ pos = isl_multi_aff_dim(maff, isl_dim_in) - 1;
+
+ for (i = 0; i < maff->n; ++i)
+ if (isl_aff_involves_dims(maff->p[i], isl_dim_in, pos, 1))
+ return 1;
+
+ return 0;
+}
+
+/* Given a set of upper bounds on the last "input" variable m,
+ * construct a piecewise affine expression that selects
+ * the minimal upper bound to m, i.e.,
+ * divide the space into cells where one
+ * of the upper bounds is smaller than all the others and select
+ * this upper bound on that cell.
+ *
+ * In particular, if there are n bounds b_i, then the result
+ * consists of n cell, each one of the form
+ *
+ * b_i <= b_j for j > i
+ * b_i < b_j for j < i
+ *
+ * The affine expression on this cell is
+ *
+ * b_i
+ */
+static __isl_give isl_pw_aff *set_minimum_pa(__isl_take isl_space *space,
+ __isl_take isl_mat *var)
+{
+ int i;
+ isl_aff *aff = NULL;
+ isl_basic_set *bset = NULL;
+ isl_ctx *ctx;
+ isl_pw_aff *paff = NULL;
+ isl_space *pw_space;
+ isl_local_space *ls = NULL;
+
+ if (!space || !var)
+ goto error;
+
+ ctx = isl_space_get_ctx(space);
+ ls = isl_local_space_from_space(isl_space_copy(space));
+ pw_space = isl_space_copy(space);
+ pw_space = isl_space_from_domain(pw_space);
+ pw_space = isl_space_add_dims(pw_space, isl_dim_out, 1);
+ paff = isl_pw_aff_alloc_size(pw_space, var->n_row);
+
+ for (i = 0; i < var->n_row; ++i) {
+ isl_pw_aff *paff_i;
+
+ aff = isl_aff_alloc(isl_local_space_copy(ls));
+ bset = isl_basic_set_alloc_space(isl_space_copy(space), 0,
+ 0, var->n_row - 1);
+ if (!aff || !bset)
+ goto error;
+ isl_int_set_si(aff->v->el[0], 1);
+ isl_seq_cpy(aff->v->el + 1, var->row[i], var->n_col);
+ isl_int_set_si(aff->v->el[1 + var->n_col], 0);
+ bset = select_minimum(bset, var, i);
+ paff_i = isl_pw_aff_alloc(isl_set_from_basic_set(bset), aff);
+ paff = isl_pw_aff_add_disjoint(paff, paff_i);
+ }
+
+ isl_local_space_free(ls);
+ isl_space_free(space);
+ isl_mat_free(var);
+ return paff;
+error:
+ isl_aff_free(aff);
+ isl_basic_set_free(bset);
+ isl_pw_aff_free(paff);
+ isl_local_space_free(ls);
+ isl_space_free(space);
+ isl_mat_free(var);
+ return NULL;
+}
+
+/* Given a piecewise multi-affine expression of which the last input variable
+ * is the minimum of the bounds in "cst", plug in the value of the minimum.
+ * This minimum expression is given in "min_expr_pa".
+ * The set "min_expr" contains the same information, but in the form of a set.
+ * The variable is subsequently projected out.
+ *
+ * The implementation is similar to those of "split" and "split_domain".
+ * If the variable appears in a given expression, then minimum expression
+ * is plugged in. Otherwise, if the variable appears in the constraints
+ * and a split is required, then the domain is split. Otherwise, no split
+ * is performed.
+ */
+static __isl_give isl_pw_multi_aff *split_domain_pma(
+ __isl_take isl_pw_multi_aff *opt, __isl_take isl_pw_aff *min_expr_pa,
+ __isl_take isl_set *min_expr, __isl_take isl_mat *cst)
+{
+ int n_in;
+ int i;
+ isl_space *space;
+ isl_pw_multi_aff *res;
+
+ if (!opt || !min_expr || !cst)
+ goto error;
+
+ n_in = isl_pw_multi_aff_dim(opt, isl_dim_in);
+ space = isl_pw_multi_aff_get_space(opt);
+ space = isl_space_drop_dims(space, isl_dim_in, n_in - 1, 1);
+ res = isl_pw_multi_aff_empty(space);
+
+ for (i = 0; i < opt->n; ++i) {
+ isl_pw_multi_aff *pma;
+
+ pma = isl_pw_multi_aff_alloc(isl_set_copy(opt->p[i].set),
+ isl_multi_aff_copy(opt->p[i].maff));
+ if (need_substitution(opt->p[i].maff))
+ pma = isl_pw_multi_aff_substitute(pma,
+ isl_dim_in, n_in - 1, min_expr_pa);
+ else if (need_split_set(opt->p[i].set, cst))
+ pma = isl_pw_multi_aff_intersect_domain(pma,
+ isl_set_copy(min_expr));
+ pma = isl_pw_multi_aff_project_out(pma,
+ isl_dim_in, n_in - 1, 1);
+
+ res = isl_pw_multi_aff_add_disjoint(res, pma);
+ }
+
+ isl_pw_multi_aff_free(opt);
+ isl_pw_aff_free(min_expr_pa);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return res;
+error:
+ isl_pw_multi_aff_free(opt);
+ isl_pw_aff_free(min_expr_pa);
+ isl_set_free(min_expr);
+ isl_mat_free(cst);
+ return NULL;
+}
+
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max);
+
+/* This function is called from basic_map_partial_lexopt_symm.
+ * The last variable of "bmap" and "dom" corresponds to the minimum
+ * of the bounds in "cst". "map_space" is the space of the original
+ * input relation (of basic_map_partial_lexopt_symm) and "set_space"
+ * is the space of the original domain.
+ *
+ * We recursively call basic_map_partial_lexopt and then plug in
+ * the definition of the minimum in the result.
+ */
+static __isl_give union isl_lex_res basic_map_partial_lexopt_symm_pma_core(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max, __isl_take isl_mat *cst,
+ __isl_take isl_space *map_space, __isl_take isl_space *set_space)
+{
+ isl_pw_multi_aff *opt;
+ isl_pw_aff *min_expr_pa;
+ isl_set *min_expr;
+ union isl_lex_res res;
+
+ min_expr = set_minimum(isl_basic_set_get_space(dom), isl_mat_copy(cst));
+ min_expr_pa = set_minimum_pa(isl_basic_set_get_space(dom),
+ isl_mat_copy(cst));
+
+ opt = basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+
+ if (empty) {
+ *empty = split(*empty,
+ isl_set_copy(min_expr), isl_mat_copy(cst));
+ *empty = isl_set_reset_space(*empty, set_space);
+ }
+
+ opt = split_domain_pma(opt, min_expr_pa, min_expr, cst);
+ opt = isl_pw_multi_aff_reset_space(opt, map_space);
+
+ res.pma = opt;
+ return res;
+}
+
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_symm_pma(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max, int first, int second)
+{
+ return basic_map_partial_lexopt_symm(bmap, dom, empty, max,
+ first, second, &basic_map_partial_lexopt_symm_pma_core).pma;
+}
+
+/* Recursive part of isl_basic_map_partial_lexopt_pw_multi_aff, after detecting
+ * equalities and removing redundant constraints.
+ *
+ * We first check if there are any parallel constraints (left).
+ * If not, we are in the base case.
+ * If there are parallel constraints, we replace them by a single
+ * constraint in basic_map_partial_lexopt_symm_pma and then call
+ * this function recursively to look for more parallel constraints.
+ */
+static __isl_give isl_pw_multi_aff *basic_map_partial_lexopt_pma(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ int par = 0;
+ int first, second;
+
+ if (!bmap)
+ goto error;
+
+ if (bmap->ctx->opt->pip_symmetry)
+ par = parallel_constraints(bmap, &first, &second);
+ if (par < 0)
+ goto error;
+ if (!par)
+ return basic_map_partial_lexopt_base_pma(bmap, dom, empty, max);
+
+ return basic_map_partial_lexopt_symm_pma(bmap, dom, empty, max,
+ first, second);
+error:
+ isl_basic_set_free(dom);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Compute the lexicographic minimum (or maximum if "max" is set)
+ * of "bmap" over the domain "dom" and return the result as a piecewise
+ * multi-affine expression.
+ * If "empty" is not NULL, then *empty is assigned a set that
+ * contains those parts of the domain where there is no solution.
+ * If "bmap" is marked as rational (ISL_BASIC_MAP_RATIONAL),
+ * then we compute the rational optimum. Otherwise, we compute
+ * the integral optimum.
+ *
+ * We perform some preprocessing. As the PILP solver does not
+ * handle implicit equalities very well, we first make sure all
+ * the equalities are explicitly available.
+ *
+ * We also add context constraints to the basic map and remove
+ * redundant constraints. This is only needed because of the
+ * way we handle simple symmetries. In particular, we currently look
+ * for symmetries on the constraints, before we set up the main tableau.
+ * It is then no good to look for symmetries on possibly redundant constraints.
+ */
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexopt_pw_multi_aff(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+ __isl_give isl_set **empty, int max)
+{
+ if (empty)
+ *empty = NULL;
+ if (!bmap || !dom)
+ goto error;
+
+ isl_assert(bmap->ctx,
+ isl_basic_map_compatible_domain(bmap, dom), goto error);
+
+ if (isl_basic_set_dim(dom, isl_dim_all) == 0)
+ return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+
+ bmap = isl_basic_map_intersect_domain(bmap, isl_basic_set_copy(dom));
+ bmap = isl_basic_map_detect_equalities(bmap);
+ bmap = isl_basic_map_remove_redundancies(bmap);
+
+ return basic_map_partial_lexopt_pma(bmap, dom, empty, max);
+error:
+ isl_basic_set_free(dom);
+ isl_basic_map_free(bmap);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_tarjan.c b/polly/lib/External/isl/isl_tarjan.c
new file mode 100644
index 00000000000..61e6b6e2f0d
--- /dev/null
+++ b/polly/lib/External/isl/isl_tarjan.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2012 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 <stdlib.h>
+#include <isl/ctx.h>
+#include <isl_tarjan.h>
+
+void isl_tarjan_graph_free(struct isl_tarjan_graph *g)
+{
+ if (!g)
+ return;
+ free(g->node);
+ free(g->stack);
+ free(g->order);
+ free(g);
+}
+
+static struct isl_tarjan_graph *isl_tarjan_graph_alloc(isl_ctx *ctx, int len)
+{
+ struct isl_tarjan_graph *g;
+ int i;
+
+ g = isl_calloc_type(ctx, struct isl_tarjan_graph);
+ if (!g)
+ return NULL;
+ g->len = len;
+ g->node = isl_alloc_array(ctx, struct isl_tarjan_node, len);
+ if (len && !g->node)
+ goto error;
+ for (i = 0; i < len; ++i)
+ g->node[i].index = -1;
+ g->stack = isl_alloc_array(ctx, int, len);
+ if (len && !g->stack)
+ goto error;
+ g->order = isl_alloc_array(ctx, int, 2 * len);
+ if (len && !g->order)
+ goto error;
+
+ g->sp = 0;
+ g->index = 0;
+ g->op = 0;
+
+ return g;
+error:
+ isl_tarjan_graph_free(g);
+ return NULL;
+}
+
+/* Perform Tarjan's algorithm for computing the strongly connected components
+ * in the graph with g->len nodes and with edges defined by "follows".
+ */
+static int isl_tarjan_components(struct isl_tarjan_graph *g, int i,
+ int (*follows)(int i, int j, void *user), void *user)
+{
+ int j;
+
+ g->node[i].index = g->index;
+ g->node[i].min_index = g->index;
+ g->node[i].on_stack = 1;
+ g->index++;
+ g->stack[g->sp++] = i;
+
+ for (j = g->len - 1; j >= 0; --j) {
+ int f;
+
+ if (j == i)
+ continue;
+ if (g->node[j].index >= 0 &&
+ (!g->node[j].on_stack ||
+ g->node[j].index > g->node[i].min_index))
+ continue;
+
+ f = follows(i, j, user);
+ if (f < 0)
+ return -1;
+ if (!f)
+ continue;
+
+ if (g->node[j].index < 0) {
+ isl_tarjan_components(g, j, follows, user);
+ if (g->node[j].min_index < g->node[i].min_index)
+ g->node[i].min_index = g->node[j].min_index;
+ } else if (g->node[j].index < g->node[i].min_index)
+ g->node[i].min_index = g->node[j].index;
+ }
+
+ if (g->node[i].index != g->node[i].min_index)
+ return 0;
+
+ do {
+ j = g->stack[--g->sp];
+ g->node[j].on_stack = 0;
+ g->order[g->op++] = j;
+ } while (j != i);
+ g->order[g->op++] = -1;
+
+ return 0;
+}
+
+/* Decompose the graph with "len" nodes and edges defined by "follows"
+ * into strongly connected components (SCCs).
+ * follows(i, j, user) should return 1 if "i" follows "j" and 0 otherwise.
+ * It should return -1 on error.
+ *
+ * If SCC a contains a node i that follows a node j in another SCC b
+ * (i.e., follows(i, j, user) returns 1), then SCC a will appear after SCC b
+ * in the result.
+ */
+struct isl_tarjan_graph *isl_tarjan_graph_init(isl_ctx *ctx, int len,
+ int (*follows)(int i, int j, void *user), void *user)
+{
+ int i;
+ struct isl_tarjan_graph *g = NULL;
+
+ g = isl_tarjan_graph_alloc(ctx, len);
+ if (!g)
+ return NULL;
+ for (i = len - 1; i >= 0; --i) {
+ if (g->node[i].index >= 0)
+ continue;
+ if (isl_tarjan_components(g, i, follows, user) < 0)
+ goto error;
+ }
+
+ return g;
+error:
+ isl_tarjan_graph_free(g);
+ return NULL;
+}
diff --git a/polly/lib/External/isl/isl_tarjan.h b/polly/lib/External/isl/isl_tarjan.h
new file mode 100644
index 00000000000..0767d0916de
--- /dev/null
+++ b/polly/lib/External/isl/isl_tarjan.h
@@ -0,0 +1,40 @@
+#ifndef ISL_TARJAN_H
+#define ISL_TARJAN_H
+
+/* Structure for representing the nodes in the graph being traversed
+ * using Tarjan's algorithm.
+ * index represents the order in which nodes are visited.
+ * min_index is the index of the root of a (sub)component.
+ * on_stack indicates whether the node is currently on the stack.
+ */
+struct isl_tarjan_node {
+ int index;
+ int min_index;
+ int on_stack;
+};
+
+/* Structure for representing the graph being traversed
+ * using Tarjan's algorithm.
+ * len is the number of nodes
+ * node is an array of nodes
+ * stack contains the nodes on the path from the root to the current node
+ * sp is the stack pointer
+ * index is the index of the last node visited
+ * order contains the elements of the components separated by -1
+ * op represents the current position in order
+ */
+struct isl_tarjan_graph {
+ int len;
+ struct isl_tarjan_node *node;
+ int *stack;
+ int sp;
+ int index;
+ int *order;
+ int op;
+};
+
+struct isl_tarjan_graph *isl_tarjan_graph_init(isl_ctx *ctx, int len,
+ int (*follows)(int i, int j, void *user), void *user);
+void isl_tarjan_graph_free(struct isl_tarjan_graph *g);
+
+#endif
diff --git a/polly/lib/External/isl/isl_test.c b/polly/lib/External/isl/isl_test.c
new file mode 100644
index 00000000000..cb9075ad94b
--- /dev/null
+++ b/polly/lib/External/isl/isl_test.c
@@ -0,0 +1,5176 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010 INRIA Saclay
+ * Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and 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 - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <limits.h>
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_aff_private.h>
+#include <isl/set.h>
+#include <isl/flow.h>
+#include <isl_constraint_private.h>
+#include <isl/polynomial.h>
+#include <isl/union_map.h>
+#include <isl_factorization.h>
+#include <isl/schedule.h>
+#include <isl_options_private.h>
+#include <isl/vertices.h>
+#include <isl/ast_build.h>
+#include <isl/val.h>
+#include <isl/ilp.h>
+#include <isl_ast_build_expr.h>
+#include <isl/options.h>
+
+#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
+
+static char *srcdir;
+
+static char *get_filename(isl_ctx *ctx, const char *name, const char *suffix) {
+ char *filename;
+ int length;
+ char *pattern = "%s/test_inputs/%s.%s";
+
+ length = strlen(pattern) - 6 + strlen(srcdir) + strlen(name)
+ + strlen(suffix) + 1;
+ filename = isl_alloc_array(ctx, char, length);
+
+ if (!filename)
+ return NULL;
+
+ sprintf(filename, pattern, srcdir, name, suffix);
+
+ return filename;
+}
+
+void test_parse_map(isl_ctx *ctx, const char *str)
+{
+ isl_map *map;
+
+ map = isl_map_read_from_str(ctx, str);
+ assert(map);
+ isl_map_free(map);
+}
+
+int test_parse_map_equal(isl_ctx *ctx, const char *str, const char *str2)
+{
+ isl_map *map, *map2;
+ int equal;
+
+ map = isl_map_read_from_str(ctx, str);
+ map2 = isl_map_read_from_str(ctx, str2);
+ equal = isl_map_is_equal(map, map2);
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "maps not equal",
+ return -1);
+
+ return 0;
+}
+
+void test_parse_pwqp(isl_ctx *ctx, const char *str)
+{
+ isl_pw_qpolynomial *pwqp;
+
+ pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+ assert(pwqp);
+ isl_pw_qpolynomial_free(pwqp);
+}
+
+static void test_parse_pwaff(isl_ctx *ctx, const char *str)
+{
+ isl_pw_aff *pwaff;
+
+ pwaff = isl_pw_aff_read_from_str(ctx, str);
+ assert(pwaff);
+ isl_pw_aff_free(pwaff);
+}
+
+int test_parse(struct isl_ctx *ctx)
+{
+ isl_map *map, *map2;
+ const char *str, *str2;
+
+ str = "{ [i] -> [-i] }";
+ map = isl_map_read_from_str(ctx, str);
+ assert(map);
+ isl_map_free(map);
+
+ str = "{ A[i] -> L[([i/3])] }";
+ map = isl_map_read_from_str(ctx, str);
+ assert(map);
+ isl_map_free(map);
+
+ test_parse_map(ctx, "{[[s] -> A[i]] -> [[s+1] -> A[i]]}");
+ 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;
+
+ str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
+ map = isl_map_read_from_str(ctx, str);
+ str = "{ [new, old] -> [o0, o1] : "
+ "exists (e0 = [(-1 - new + o0)/2], e1 = [(-1 - old + o1)/2]: "
+ "2e0 = -1 - new + o0 and 2e1 = -1 - old + o1 and o0 >= 0 and "
+ "o0 <= 1 and o1 >= 0 and o1 <= 1) }";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{[new,old] -> [new+1-2*[(new+1)/2],old+1-2*[(old+1)/2]]}";
+ map = isl_map_read_from_str(ctx, str);
+ str = "{[new,old] -> [(new+1)%2,(old+1)%2]}";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ 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;
+}
+
+void test_read(struct isl_ctx *ctx)
+{
+ char *filename;
+ FILE *input;
+ struct isl_basic_set *bset1, *bset2;
+ const char *str = "{[y]: Exists ( alpha : 2alpha = y)}";
+
+ filename = get_filename(ctx, "set", "omega");
+ assert(filename);
+ input = fopen(filename, "r");
+ assert(input);
+
+ bset1 = isl_basic_set_read_from_file(ctx, input);
+ bset2 = isl_basic_set_read_from_str(ctx, str);
+
+ assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ free(filename);
+
+ fclose(input);
+}
+
+void test_bounded(struct isl_ctx *ctx)
+{
+ isl_set *set;
+ int bounded;
+
+ set = isl_set_read_from_str(ctx, "[n] -> {[i] : 0 <= i <= n }");
+ bounded = isl_set_is_bounded(set);
+ assert(bounded);
+ isl_set_free(set);
+
+ set = isl_set_read_from_str(ctx, "{[n, i] : 0 <= i <= n }");
+ bounded = isl_set_is_bounded(set);
+ assert(!bounded);
+ isl_set_free(set);
+
+ set = isl_set_read_from_str(ctx, "[n] -> {[i] : i <= n }");
+ bounded = isl_set_is_bounded(set);
+ assert(!bounded);
+ isl_set_free(set);
+}
+
+/* Construct the basic set { [i] : 5 <= i <= N } */
+void test_construction(struct isl_ctx *ctx)
+{
+ isl_int v;
+ isl_space *dim;
+ isl_local_space *ls;
+ struct isl_basic_set *bset;
+ struct isl_constraint *c;
+
+ isl_int_init(v);
+
+ dim = isl_space_set_alloc(ctx, 1, 1);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_inequality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_param, 0, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_inequality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -5);
+ isl_constraint_set_constant(c, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ isl_int_clear(v);
+}
+
+void test_dim(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map1, *map2;
+
+ map1 = isl_map_read_from_str(ctx,
+ "[n] -> { [i] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
+ map1 = isl_map_add_dims(map1, isl_dim_in, 1);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [i,k] -> [j] : exists (a = [i/10] : i - 10a <= n ) }");
+ assert(isl_map_is_equal(map1, map2));
+ isl_map_free(map2);
+
+ map1 = isl_map_project_out(map1, isl_dim_in, 0, 1);
+ map2 = isl_map_read_from_str(ctx, "[n] -> { [i] -> [j] : n >= 0 }");
+ assert(isl_map_is_equal(map1, map2));
+
+ isl_map_free(map1);
+ isl_map_free(map2);
+
+ str = "[n] -> { [i] -> [] : exists a : 0 <= i <= n and i = 2 a }";
+ map1 = isl_map_read_from_str(ctx, str);
+ str = "{ [i] -> [j] : exists a : 0 <= i <= j and i = 2 a }";
+ map2 = isl_map_read_from_str(ctx, str);
+ map1 = isl_map_move_dims(map1, isl_dim_out, 0, isl_dim_param, 0, 1);
+ assert(isl_map_is_equal(map1, map2));
+
+ isl_map_free(map1);
+ isl_map_free(map2);
+}
+
+struct {
+ __isl_give isl_val *(*op)(__isl_take isl_val *v);
+ const char *arg;
+ const char *res;
+} val_un_tests[] = {
+ { &isl_val_neg, "0", "0" },
+ { &isl_val_abs, "0", "0" },
+ { &isl_val_2exp, "0", "1" },
+ { &isl_val_floor, "0", "0" },
+ { &isl_val_ceil, "0", "0" },
+ { &isl_val_neg, "1", "-1" },
+ { &isl_val_neg, "-1", "1" },
+ { &isl_val_neg, "1/2", "-1/2" },
+ { &isl_val_neg, "-1/2", "1/2" },
+ { &isl_val_neg, "infty", "-infty" },
+ { &isl_val_neg, "-infty", "infty" },
+ { &isl_val_neg, "NaN", "NaN" },
+ { &isl_val_abs, "1", "1" },
+ { &isl_val_abs, "-1", "1" },
+ { &isl_val_abs, "1/2", "1/2" },
+ { &isl_val_abs, "-1/2", "1/2" },
+ { &isl_val_abs, "infty", "infty" },
+ { &isl_val_abs, "-infty", "infty" },
+ { &isl_val_abs, "NaN", "NaN" },
+ { &isl_val_floor, "1", "1" },
+ { &isl_val_floor, "-1", "-1" },
+ { &isl_val_floor, "1/2", "0" },
+ { &isl_val_floor, "-1/2", "-1" },
+ { &isl_val_floor, "infty", "infty" },
+ { &isl_val_floor, "-infty", "-infty" },
+ { &isl_val_floor, "NaN", "NaN" },
+ { &isl_val_ceil, "1", "1" },
+ { &isl_val_ceil, "-1", "-1" },
+ { &isl_val_ceil, "1/2", "1" },
+ { &isl_val_ceil, "-1/2", "0" },
+ { &isl_val_ceil, "infty", "infty" },
+ { &isl_val_ceil, "-infty", "-infty" },
+ { &isl_val_ceil, "NaN", "NaN" },
+ { &isl_val_2exp, "-3", "1/8" },
+ { &isl_val_2exp, "-1", "1/2" },
+ { &isl_val_2exp, "1", "2" },
+ { &isl_val_2exp, "2", "4" },
+ { &isl_val_2exp, "3", "8" },
+ { &isl_val_inv, "1", "1" },
+ { &isl_val_inv, "2", "1/2" },
+ { &isl_val_inv, "1/2", "2" },
+ { &isl_val_inv, "-2", "-1/2" },
+ { &isl_val_inv, "-1/2", "-2" },
+ { &isl_val_inv, "0", "NaN" },
+ { &isl_val_inv, "NaN", "NaN" },
+ { &isl_val_inv, "infty", "0" },
+ { &isl_val_inv, "-infty", "0" },
+};
+
+/* Perform some basic tests of unary operations on isl_val objects.
+ */
+static int test_un_val(isl_ctx *ctx)
+{
+ int i;
+ isl_val *v, *res;
+ __isl_give isl_val *(*fn)(__isl_take isl_val *v);
+ int ok;
+
+ for (i = 0; i < ARRAY_SIZE(val_un_tests); ++i) {
+ v = isl_val_read_from_str(ctx, val_un_tests[i].arg);
+ res = isl_val_read_from_str(ctx, val_un_tests[i].res);
+ fn = val_un_tests[i].op;
+ v = fn(v);
+ if (isl_val_is_nan(res))
+ ok = isl_val_is_nan(v);
+ else
+ ok = isl_val_eq(v, res);
+ isl_val_free(v);
+ isl_val_free(res);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ return 0;
+}
+
+struct {
+ __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+} val_bin_op[] = {
+ ['+'] = { &isl_val_add },
+ ['-'] = { &isl_val_sub },
+ ['*'] = { &isl_val_mul },
+ ['/'] = { &isl_val_div },
+ ['g'] = { &isl_val_gcd },
+ ['m'] = { &isl_val_min },
+ ['M'] = { &isl_val_max },
+};
+
+struct {
+ const char *arg1;
+ unsigned char op;
+ const char *arg2;
+ const char *res;
+} val_bin_tests[] = {
+ { "0", '+', "0", "0" },
+ { "1", '+', "0", "1" },
+ { "1", '+', "1", "2" },
+ { "1", '-', "1", "0" },
+ { "1", '*', "1", "1" },
+ { "1", '/', "1", "1" },
+ { "2", '*', "3", "6" },
+ { "2", '*', "1/2", "1" },
+ { "2", '*', "1/3", "2/3" },
+ { "2/3", '*', "3/5", "2/5" },
+ { "2/3", '*', "7/5", "14/15" },
+ { "2", '/', "1/2", "4" },
+ { "-2", '/', "-1/2", "4" },
+ { "-2", '/', "1/2", "-4" },
+ { "2", '/', "-1/2", "-4" },
+ { "2", '/', "2", "1" },
+ { "2", '/', "3", "2/3" },
+ { "2/3", '/', "5/3", "2/5" },
+ { "2/3", '/', "5/7", "14/15" },
+ { "0", '/', "0", "NaN" },
+ { "42", '/', "0", "NaN" },
+ { "-42", '/', "0", "NaN" },
+ { "infty", '/', "0", "NaN" },
+ { "-infty", '/', "0", "NaN" },
+ { "NaN", '/', "0", "NaN" },
+ { "0", '/', "NaN", "NaN" },
+ { "42", '/', "NaN", "NaN" },
+ { "-42", '/', "NaN", "NaN" },
+ { "infty", '/', "NaN", "NaN" },
+ { "-infty", '/', "NaN", "NaN" },
+ { "NaN", '/', "NaN", "NaN" },
+ { "0", '/', "infty", "0" },
+ { "42", '/', "infty", "0" },
+ { "-42", '/', "infty", "0" },
+ { "infty", '/', "infty", "NaN" },
+ { "-infty", '/', "infty", "NaN" },
+ { "NaN", '/', "infty", "NaN" },
+ { "0", '/', "-infty", "0" },
+ { "42", '/', "-infty", "0" },
+ { "-42", '/', "-infty", "0" },
+ { "infty", '/', "-infty", "NaN" },
+ { "-infty", '/', "-infty", "NaN" },
+ { "NaN", '/', "-infty", "NaN" },
+ { "1", '-', "1/3", "2/3" },
+ { "1/3", '+', "1/2", "5/6" },
+ { "1/2", '+', "1/2", "1" },
+ { "3/4", '-', "1/4", "1/2" },
+ { "1/2", '-', "1/3", "1/6" },
+ { "infty", '+', "42", "infty" },
+ { "infty", '+', "infty", "infty" },
+ { "42", '+', "infty", "infty" },
+ { "infty", '-', "infty", "NaN" },
+ { "infty", '*', "infty", "infty" },
+ { "infty", '*', "-infty", "-infty" },
+ { "-infty", '*', "infty", "-infty" },
+ { "-infty", '*', "-infty", "infty" },
+ { "0", '*', "infty", "NaN" },
+ { "1", '*', "infty", "infty" },
+ { "infty", '*', "0", "NaN" },
+ { "infty", '*', "42", "infty" },
+ { "42", '-', "infty", "-infty" },
+ { "infty", '+', "-infty", "NaN" },
+ { "4", 'g', "6", "2" },
+ { "5", 'g', "6", "1" },
+ { "42", 'm', "3", "3" },
+ { "42", 'M', "3", "42" },
+ { "3", 'm', "42", "3" },
+ { "3", 'M', "42", "42" },
+ { "42", 'm', "infty", "42" },
+ { "42", 'M', "infty", "infty" },
+ { "42", 'm', "-infty", "-infty" },
+ { "42", 'M', "-infty", "42" },
+ { "42", 'm', "NaN", "NaN" },
+ { "42", 'M', "NaN", "NaN" },
+ { "infty", 'm', "-infty", "-infty" },
+ { "infty", 'M', "-infty", "infty" },
+};
+
+/* Perform some basic tests of binary operations on isl_val objects.
+ */
+static int test_bin_val(isl_ctx *ctx)
+{
+ int i;
+ isl_val *v1, *v2, *res;
+ __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+ int ok;
+
+ for (i = 0; i < ARRAY_SIZE(val_bin_tests); ++i) {
+ v1 = isl_val_read_from_str(ctx, val_bin_tests[i].arg1);
+ v2 = isl_val_read_from_str(ctx, val_bin_tests[i].arg2);
+ res = isl_val_read_from_str(ctx, val_bin_tests[i].res);
+ fn = val_bin_op[val_bin_tests[i].op].fn;
+ v1 = fn(v1, v2);
+ if (isl_val_is_nan(res))
+ ok = isl_val_is_nan(v1);
+ else
+ ok = isl_val_eq(v1, res);
+ isl_val_free(v1);
+ isl_val_free(res);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ return 0;
+}
+
+/* Perform some basic tests on isl_val objects.
+ */
+static int test_val(isl_ctx *ctx)
+{
+ if (test_un_val(ctx) < 0)
+ return -1;
+ if (test_bin_val(ctx) < 0)
+ return -1;
+ return 0;
+}
+
+static int test_div(isl_ctx *ctx)
+{
+ unsigned n;
+ const char *str;
+ int empty;
+ isl_int v;
+ isl_space *dim;
+ isl_set *set;
+ isl_local_space *ls;
+ struct isl_basic_set *bset;
+ struct isl_constraint *c;
+
+ isl_int_init(v);
+
+ /* test 1 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+ assert(bset && bset->n_div == 1);
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 2 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+ assert(bset && bset->n_div == 1);
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 3 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -3);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 4);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+ assert(bset && bset->n_div == 1);
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 4 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 2);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_constant(c, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 6);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 1, 2);
+
+ assert(isl_basic_set_is_empty(bset));
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 5 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+ assert(bset && bset->n_div == 0);
+ isl_basic_set_free(bset);
+ isl_local_space_free(ls);
+
+ /* test 6 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 6);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+ assert(bset && bset->n_div == 1);
+ isl_basic_set_free(bset);
+ isl_local_space_free(ls);
+
+ /* test 7 */
+ /* This test is a bit tricky. We set up an equality
+ * a + 3b + 3c = 6 e0
+ * Normalization of divs creates _two_ divs
+ * a = 3 e0
+ * c - b - e0 = 2 e1
+ * Afterwards e0 is removed again because it has coefficient -1
+ * and we end up with the original equality and div again.
+ * Perhaps we can avoid the introduction of this temporary div.
+ */
+ dim = isl_space_set_alloc(ctx, 0, 4);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ isl_int_set_si(v, 6);
+ isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
+
+ /* Test disabled for now */
+ /*
+ assert(bset && bset->n_div == 1);
+ */
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 8 */
+ dim = isl_space_set_alloc(ctx, 0, 5);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ isl_int_set_si(v, -3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+ isl_int_set_si(v, 6);
+ isl_constraint_set_coefficient(c, isl_dim_set, 4, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ isl_int_set_si(v, 1);
+ isl_constraint_set_constant(c, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 4, 1);
+
+ /* Test disabled for now */
+ /*
+ assert(bset && bset->n_div == 1);
+ */
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 9 */
+ dim = isl_space_set_alloc(ctx, 0, 4);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 1, v);
+ isl_int_set_si(v, -2);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, 3);
+ isl_constraint_set_coefficient(c, isl_dim_set, 3, v);
+ isl_int_set_si(v, 2);
+ isl_constraint_set_constant(c, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 2);
+
+ bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
+
+ assert(!isl_basic_set_is_empty(bset));
+
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ /* test 10 */
+ dim = isl_space_set_alloc(ctx, 0, 3);
+ bset = isl_basic_set_universe(isl_space_copy(dim));
+ ls = isl_local_space_from_space(dim);
+
+ c = isl_equality_alloc(isl_local_space_copy(ls));
+ isl_int_set_si(v, 1);
+ isl_constraint_set_coefficient(c, isl_dim_set, 0, v);
+ isl_int_set_si(v, -2);
+ isl_constraint_set_coefficient(c, isl_dim_set, 2, v);
+ bset = isl_basic_set_add_constraint(bset, c);
+
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 2, 1);
+
+ bset = isl_basic_set_fix_si(bset, isl_dim_set, 0, 2);
+
+ isl_local_space_free(ls);
+ isl_basic_set_free(bset);
+
+ isl_int_clear(v);
+
+ str = "{ [i] : exists (e0, e1: 3e1 >= 1 + 2e0 and "
+ "8e1 <= -1 + 5i - 5e0 and 2e1 >= 1 + 2i - 5e0) }";
+ set = isl_set_read_from_str(ctx, str);
+ set = isl_set_compute_divs(set);
+ isl_set_free(set);
+ if (!set)
+ return -1;
+
+ str = "{ [i,j] : 2*[i/2] + 3 * [j/4] <= 10 and 2 i = j }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ n = isl_basic_set_dim(bset, isl_dim_div);
+ isl_basic_set_free(bset);
+ if (!bset)
+ return -1;
+ if (n != 0)
+ isl_die(ctx, isl_error_unknown,
+ "expecting no existentials", return -1);
+
+ str = "{ [i,j,k] : 3 + i + 2j >= 0 and 2 * [(i+2j)/4] <= k }";
+ set = isl_set_read_from_str(ctx, str);
+ set = isl_set_remove_divs_involving_dims(set, isl_dim_set, 0, 2);
+ set = isl_set_fix_si(set, isl_dim_set, 2, -3);
+ empty = isl_set_is_empty(set);
+ isl_set_free(set);
+ if (empty < 0)
+ return -1;
+ if (!empty)
+ isl_die(ctx, isl_error_unknown,
+ "result not as accurate as expected", return -1);
+
+ return 0;
+}
+
+void test_application_case(struct isl_ctx *ctx, const char *name)
+{
+ char *filename;
+ FILE *input;
+ struct isl_basic_set *bset1, *bset2;
+ struct isl_basic_map *bmap;
+
+ filename = get_filename(ctx, name, "omega");
+ assert(filename);
+ input = fopen(filename, "r");
+ assert(input);
+
+ bset1 = isl_basic_set_read_from_file(ctx, input);
+ bmap = isl_basic_map_read_from_file(ctx, input);
+
+ bset1 = isl_basic_set_apply(bset1, bmap);
+
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ free(filename);
+
+ fclose(input);
+}
+
+void test_application(struct isl_ctx *ctx)
+{
+ test_application_case(ctx, "application");
+ test_application_case(ctx, "application2");
+}
+
+void test_affine_hull_case(struct isl_ctx *ctx, const char *name)
+{
+ char *filename;
+ FILE *input;
+ struct isl_basic_set *bset1, *bset2;
+
+ filename = get_filename(ctx, name, "polylib");
+ assert(filename);
+ input = fopen(filename, "r");
+ assert(input);
+
+ bset1 = isl_basic_set_read_from_file(ctx, input);
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ bset1 = isl_basic_set_affine_hull(bset1);
+
+ assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ free(filename);
+
+ fclose(input);
+}
+
+int test_affine_hull(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_basic_set *bset, *bset2;
+ int n;
+ int subset;
+
+ test_affine_hull_case(ctx, "affine2");
+ test_affine_hull_case(ctx, "affine");
+ test_affine_hull_case(ctx, "affine3");
+
+ str = "[m] -> { [i0] : exists (e0, e1: e1 <= 1 + i0 and "
+ "m >= 3 and 4i0 <= 2 + m and e1 >= i0 and "
+ "e1 >= 0 and e1 <= 2 and e1 >= 1 + 2e0 and "
+ "2e1 <= 1 + m + 4e0 and 2e1 >= 2 - m + 4i0 - 4e0) }";
+ set = isl_set_read_from_str(ctx, str);
+ bset = isl_set_affine_hull(set);
+ n = isl_basic_set_dim(bset, isl_dim_div);
+ isl_basic_set_free(bset);
+ if (n != 0)
+ isl_die(ctx, isl_error_unknown, "not expecting any divs",
+ return -1);
+
+ /* Check that isl_map_affine_hull is not confused by
+ * the reordering of divs in isl_map_align_divs.
+ */
+ str = "{ [a, b, c, 0] : exists (e0 = [(b)/32], e1 = [(c)/32]: "
+ "32e0 = b and 32e1 = c); "
+ "[a, 0, c, 0] : exists (e0 = [(c)/32]: 32e0 = c) }";
+ set = isl_set_read_from_str(ctx, str);
+ bset = isl_set_affine_hull(set);
+ isl_basic_set_free(bset);
+ if (!bset)
+ return -1;
+
+ str = "{ [a] : exists e0, e1, e2: 32e1 = 31 + 31a + 31e0 and "
+ "32e2 = 31 + 31e0 }";
+ set = isl_set_read_from_str(ctx, str);
+ bset = isl_set_affine_hull(set);
+ str = "{ [a] : exists e : a = 32 e }";
+ bset2 = isl_basic_set_read_from_str(ctx, str);
+ subset = isl_basic_set_is_subset(bset, bset2);
+ isl_basic_set_free(bset);
+ isl_basic_set_free(bset2);
+ if (subset < 0)
+ return -1;
+ if (!subset)
+ isl_die(ctx, isl_error_unknown, "not as accurate as expected",
+ return -1);
+
+ return 0;
+}
+
+void test_convex_hull_case(struct isl_ctx *ctx, const char *name)
+{
+ char *filename;
+ FILE *input;
+ struct isl_basic_set *bset1, *bset2;
+ struct isl_set *set;
+
+ filename = get_filename(ctx, name, "polylib");
+ assert(filename);
+ input = fopen(filename, "r");
+ assert(input);
+
+ bset1 = isl_basic_set_read_from_file(ctx, input);
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ set = isl_basic_set_union(bset1, bset2);
+ bset1 = isl_set_convex_hull(set);
+
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ free(filename);
+
+ fclose(input);
+}
+
+struct {
+ const char *set;
+ const char *hull;
+} convex_hull_tests[] = {
+ { "{ [i0, i1, i2] : (i2 = 1 and i0 = 0 and i1 >= 0) or "
+ "(i0 = 1 and i1 = 0 and i2 = 1) or "
+ "(i0 = 0 and i1 = 0 and i2 = 0) }",
+ "{ [i0, i1, i2] : i0 >= 0 and i2 >= i0 and i2 <= 1 and i1 >= 0 }" },
+ { "[n] -> { [i0, i1, i0] : i0 <= -4 + n; "
+ "[i0, i0, i2] : n = 6 and i0 >= 0 and i2 <= 7 - i0 and "
+ "i2 <= 5 and i2 >= 4; "
+ "[3, i1, 3] : n = 5 and i1 <= 2 and i1 >= 0 }",
+ "[n] -> { [i0, i1, i2] : i2 <= -1 + n and 2i2 <= -6 + 3n - i0 and "
+ "i2 <= 5 + i0 and i2 >= i0 }" },
+ { "{ [x, y] : 3y <= 2x and y >= -2 + 2x and 2y >= 2 - x }",
+ "{ [x, y] : 1 = 0 }" },
+};
+
+void test_convex_hull_algo(struct isl_ctx *ctx, int convex)
+{
+ int i;
+ int orig_convex = ctx->opt->convex;
+ ctx->opt->convex = convex;
+
+ test_convex_hull_case(ctx, "convex0");
+ test_convex_hull_case(ctx, "convex1");
+ test_convex_hull_case(ctx, "convex2");
+ test_convex_hull_case(ctx, "convex3");
+ test_convex_hull_case(ctx, "convex4");
+ test_convex_hull_case(ctx, "convex5");
+ test_convex_hull_case(ctx, "convex6");
+ test_convex_hull_case(ctx, "convex7");
+ test_convex_hull_case(ctx, "convex8");
+ test_convex_hull_case(ctx, "convex9");
+ test_convex_hull_case(ctx, "convex10");
+ test_convex_hull_case(ctx, "convex11");
+ test_convex_hull_case(ctx, "convex12");
+ test_convex_hull_case(ctx, "convex13");
+ test_convex_hull_case(ctx, "convex14");
+ test_convex_hull_case(ctx, "convex15");
+
+ for (i = 0; i < ARRAY_SIZE(convex_hull_tests); ++i) {
+ isl_set *set1, *set2;
+
+ set1 = isl_set_read_from_str(ctx, convex_hull_tests[i].set);
+ set2 = isl_set_read_from_str(ctx, convex_hull_tests[i].hull);
+ set1 = isl_set_from_basic_set(isl_set_convex_hull(set1));
+ assert(isl_set_is_equal(set1, set2));
+ isl_set_free(set1);
+ isl_set_free(set2);
+ }
+
+ ctx->opt->convex = orig_convex;
+}
+
+void test_convex_hull(struct isl_ctx *ctx)
+{
+ test_convex_hull_algo(ctx, ISL_CONVEX_HULL_FM);
+ test_convex_hull_algo(ctx, ISL_CONVEX_HULL_WRAP);
+}
+
+void test_gist_case(struct isl_ctx *ctx, const char *name)
+{
+ char *filename;
+ FILE *input;
+ struct isl_basic_set *bset1, *bset2;
+
+ filename = get_filename(ctx, name, "polylib");
+ assert(filename);
+ input = fopen(filename, "r");
+ assert(input);
+
+ bset1 = isl_basic_set_read_from_file(ctx, input);
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ bset1 = isl_basic_set_gist(bset1, bset2);
+
+ bset2 = isl_basic_set_read_from_file(ctx, input);
+
+ assert(isl_basic_set_is_equal(bset1, bset2) == 1);
+
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ free(filename);
+
+ fclose(input);
+}
+
+struct {
+ const char *set;
+ const char *context;
+ const char *gist;
+} gist_tests[] = {
+ { "{ [a, b, c] : a <= 15 and a >= 1 }",
+ "{ [a, b, c] : exists (e0 = floor((-1 + a)/16): a >= 1 and "
+ "c <= 30 and 32e0 >= -62 + 2a + 2b - c and b >= 0) }",
+ "{ [a, b, c] : a <= 15 }" },
+ { "{ : }", "{ : 1 = 0 }", "{ : }" },
+ { "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
+ { "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
+ "[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
+};
+
+static int test_gist(struct isl_ctx *ctx)
+{
+ int i;
+ const char *str;
+ isl_basic_set *bset1, *bset2;
+ isl_map *map1, *map2;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
+ int equal_input;
+ isl_basic_set *copy;
+
+ bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
+ bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].context);
+ copy = isl_basic_set_copy(bset1);
+ bset1 = isl_basic_set_gist(bset1, bset2);
+ bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].gist);
+ equal = isl_basic_set_is_equal(bset1, bset2);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
+ equal_input = isl_basic_set_is_equal(bset1, copy);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(copy);
+ if (equal < 0 || equal_input < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect gist result", return -1);
+ if (!equal_input)
+ isl_die(ctx, isl_error_unknown,
+ "gist modified input", return -1);
+ }
+
+ test_gist_case(ctx, "gist1");
+
+ str = "[p0, p2, p3, p5, p6, p10] -> { [] : "
+ "exists (e0 = [(15 + p0 + 15p6 + 15p10)/16], e1 = [(p5)/8], "
+ "e2 = [(p6)/128], e3 = [(8p2 - p5)/128], "
+ "e4 = [(128p3 - p6)/4096]: 8e1 = p5 and 128e2 = p6 and "
+ "128e3 = 8p2 - p5 and 4096e4 = 128p3 - p6 and p2 >= 0 and "
+ "16e0 >= 16 + 16p6 + 15p10 and p2 <= 15 and p3 >= 0 and "
+ "p3 <= 31 and p6 >= 128p3 and p5 >= 8p2 and p10 >= 0 and "
+ "16e0 <= 15 + p0 + 15p6 + 15p10 and 16e0 >= p0 + 15p6 + 15p10 and "
+ "p10 <= 15 and p10 <= -1 + p0 - p6) }";
+ bset1 = isl_basic_set_read_from_str(ctx, str);
+ str = "[p0, p2, p3, p5, p6, p10] -> { [] : exists (e0 = [(p5)/8], "
+ "e1 = [(p6)/128], e2 = [(8p2 - p5)/128], "
+ "e3 = [(128p3 - p6)/4096]: 8e0 = p5 and 128e1 = p6 and "
+ "128e2 = 8p2 - p5 and 4096e3 = 128p3 - p6 and p5 >= -7 and "
+ "p2 >= 0 and 8p2 <= -1 + p0 and p2 <= 15 and p3 >= 0 and "
+ "p3 <= 31 and 128p3 <= -1 + p0 and p6 >= -127 and "
+ "p5 <= -1 + p0 and p6 <= -1 + p0 and p6 >= 128p3 and "
+ "p0 >= 1 and p5 >= 8p2 and p10 >= 0 and p10 <= 15 ) }";
+ bset2 = isl_basic_set_read_from_str(ctx, str);
+ bset1 = isl_basic_set_gist(bset1, bset2);
+ assert(bset1 && bset1->n_div == 0);
+ isl_basic_set_free(bset1);
+
+ /* Check that the integer divisions of the second disjunct
+ * do not spread to the first disjunct.
+ */
+ str = "[t1] -> { S_0[] -> A[o0] : (exists (e0 = [(-t1 + o0)/16]: "
+ "16e0 = -t1 + o0 and o0 >= 0 and o0 <= 15 and t1 >= 0)) or "
+ "(exists (e0 = [(-1 + t1)/16], "
+ "e1 = [(-16 + t1 - 16e0)/4294967296]: "
+ "4294967296e1 = -16 + t1 - o0 - 16e0 and "
+ "16e0 <= -1 + t1 and 16e0 >= -16 + t1 and o0 >= 0 and "
+ "o0 <= 4294967295 and t1 <= -1)) }";
+ map1 = isl_map_read_from_str(ctx, str);
+ str = "[t1] -> { S_0[] -> A[o0] : t1 >= 0 and t1 <= 4294967295 }";
+ map2 = isl_map_read_from_str(ctx, str);
+ map1 = isl_map_gist(map1, map2);
+ if (!map1)
+ return -1;
+ if (map1->n != 1)
+ isl_die(ctx, isl_error_unknown, "expecting single disjunct",
+ isl_map_free(map1); return -1);
+ if (isl_basic_map_dim(map1->p[0], isl_dim_div) != 1)
+ isl_die(ctx, isl_error_unknown, "expecting single div",
+ isl_map_free(map1); return -1);
+ isl_map_free(map1);
+
+ return 0;
+}
+
+int test_coalesce_set(isl_ctx *ctx, const char *str, int check_one)
+{
+ isl_set *set, *set2;
+ int equal;
+ int one;
+
+ set = isl_set_read_from_str(ctx, str);
+ set = isl_set_coalesce(set);
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set, set2);
+ one = set && set->n == 1;
+ isl_set_free(set);
+ isl_set_free(set2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "coalesced set not equal to input", return -1);
+ if (check_one && !one)
+ isl_die(ctx, isl_error_unknown,
+ "coalesced set should not be a union", return -1);
+
+ return 0;
+}
+
+int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
+{
+ int r = 0;
+ int bounded;
+
+ bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
+ isl_options_set_coalesce_bounded_wrapping(ctx, 0);
+
+ if (test_coalesce_set(ctx,
+ "{[x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
+ "-x - y + 1 >= 0 and -3 <= z <= 3;"
+ "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
+ "x-z + 20 >= 0 and x+z + 20 >= 0 and "
+ "-10 <= y <= 0}", 1) < 0)
+ goto error;
+ if (test_coalesce_set(ctx,
+ "{[x,y] : 0 <= x,y <= 10; [5,y]: 4 <=y <= 11}", 1) < 0)
+ goto error;
+ if (test_coalesce_set(ctx,
+ "{[x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }", 1) < 0)
+ goto error;
+
+ if (0) {
+error:
+ r = -1;
+ }
+
+ isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
+
+ return r;
+}
+
+/* Inputs for coalescing tests.
+ * "str" is a string representation of the input set.
+ * "single_disjunct" is set if we expect the result to consist of
+ * a single disjunct.
+ */
+struct {
+ int single_disjunct;
+ const char *str;
+} coalesce_tests[] = {
+ { 1, "{[x,y]: x >= 0 & x <= 10 & y >= 0 & y <= 10 or "
+ "y >= x & x >= 2 & 5 >= y }" },
+ { 1, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
+ "x + y >= 10 & y <= x & x + y <= 20 & y >= 0}" },
+ { 0, "{[x,y]: y >= 0 & 2x + y <= 30 & y <= 10 & x >= 0 or "
+ "x + y >= 10 & y <= x & x + y <= 19 & y >= 0}" },
+ { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+ "y >= 0 & x >= 6 & x <= 10 & y <= x}" },
+ { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+ "y >= 0 & x >= 7 & x <= 10 & y <= x}" },
+ { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or "
+ "y >= 0 & x >= 6 & x <= 10 & y + 1 <= x}" },
+ { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 6}" },
+ { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 7 & y <= 6}" },
+ { 1, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 5}" },
+ { 0, "{[x,y]: y >= 0 & x <= 5 & y <= x or y >= 0 & x = 6 & y <= 7}" },
+ { 1, "[n] -> { [i] : i = 1 and n >= 2 or 2 <= i and i <= n }" },
+ { 0, "{[x,y] : x >= 0 and y >= 0 or 0 <= y and y <= 5 and x = -1}" },
+ { 1, "[n] -> { [i] : 1 <= i and i <= n - 1 or 2 <= i and i <= n }" },
+ { 0, "[n] -> { [[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
+ "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
+ "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
+ "4e4 = -2 + o0 and i0 >= 8 + 2n and o0 >= 2 + i0 and "
+ "o0 <= 56 + 2n and o0 <= -12 + 4n and i0 <= 57 + 2n and "
+ "i0 <= -11 + 4n and o0 >= 6 + 2n and 4e0 <= i0 and "
+ "4e0 >= -3 + i0 and 4e1 <= o0 and 4e1 >= -3 + o0 and "
+ "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0);"
+ "[[i0] -> [o0]] : exists (e0 = [(i0)/4], e1 = [(o0)/4], "
+ "e2 = [(n)/2], e3 = [(-2 + i0)/4], e4 = [(-2 + o0)/4], "
+ "e5 = [(-2n + i0)/4]: 2e2 = n and 4e3 = -2 + i0 and "
+ "4e4 = -2 + o0 and 2e0 >= 3 + n and e0 <= -4 + n and "
+ "2e0 <= 27 + n and e1 <= -4 + n and 2e1 <= 27 + n and "
+ "2e1 >= 2 + n and e1 >= 1 + e0 and i0 >= 7 + 2n and "
+ "i0 <= -11 + 4n and i0 <= 57 + 2n and 4e0 <= -2 + i0 and "
+ "4e0 >= -3 + i0 and o0 >= 6 + 2n and o0 <= -11 + 4n and "
+ "o0 <= 57 + 2n and 4e1 <= -2 + o0 and 4e1 >= -3 + o0 and "
+ "4e5 <= -2n + i0 and 4e5 >= -3 - 2n + i0 ) }" },
+ { 0, "[n, m] -> { [o0, o2, o3] : (o3 = 1 and o0 >= 1 + m and "
+ "o0 <= n + m and o2 <= m and o0 >= 2 + n and o2 >= 3) or "
+ "(o0 >= 2 + n and o0 >= 1 + m and o0 <= n + m and n >= 1 and "
+ "o3 <= -1 + o2 and o3 >= 1 - m + o2 and o3 >= 2 and o3 <= n) }" },
+ { 0, "[M, N] -> { [[i0, i1, i2, i3, i4, i5, i6] -> "
+ "[o0, o1, o2, o3, o4, o5, o6]] : "
+ "(o6 <= -4 + 2M - 2N + i0 + i1 - i2 + i6 - o0 - o1 + o2 and "
+ "o3 <= -2 + i3 and o6 >= 2 + i0 + i3 + i6 - o0 - o3 and "
+ "o6 >= 2 - M + N + i3 + i4 + i6 - o3 - o4 and o0 <= -1 + i0 and "
+ "o4 >= 4 - 3M + 3N - i0 - i1 + i2 + 2i3 + i4 + o0 + o1 - o2 - 2o3 "
+ "and o6 <= -3 + 2M - 2N + i3 + i4 - i5 + i6 - o3 - o4 + o5 and "
+ "2o6 <= -5 + 5M - 5N + 2i0 + i1 - i2 - i5 + 2i6 - 2o0 - o1 + o2 + o5 "
+ "and o6 >= 2i0 + i1 + i6 - 2o0 - o1 and "
+ "3o6 <= -5 + 4M - 4N + 2i0 + i1 - i2 + 2i3 + i4 - i5 + 3i6 "
+ "- 2o0 - o1 + o2 - 2o3 - o4 + o5) or "
+ "(N >= 2 and o3 <= -1 + i3 and o0 <= -1 + i0 and "
+ "o6 >= i3 + i6 - o3 and M >= 0 and "
+ "2o6 >= 1 + i0 + i3 + 2i6 - o0 - o3 and "
+ "o6 >= 1 - M + i0 + i6 - o0 and N >= 2M and o6 >= i0 + i6 - o0) }" },
+ { 0, "[M, N] -> { [o0] : (o0 = 0 and M >= 1 and N >= 2) or "
+ "(o0 = 0 and M >= 1 and N >= 2M and N >= 2 + M) or "
+ "(o0 = 0 and M >= 2 and N >= 3) or "
+ "(M = 0 and o0 = 0 and N >= 3) }" },
+ { 0, "{ [i0, i1, i2, i3] : (i1 = 10i0 and i0 >= 1 and 10i0 <= 100 and "
+ "i3 <= 9 + 10 i2 and i3 >= 1 + 10i2 and i3 >= 0) or "
+ "(i1 <= 9 + 10i0 and i1 >= 1 + 10i0 and i2 >= 0 and "
+ "i0 >= 0 and i1 <= 100 and i3 <= 9 + 10i2 and i3 >= 1 + 10i2) }" },
+ { 0, "[M] -> { [i1] : (i1 >= 2 and i1 <= M) or (i1 = M and M >= 1) }" },
+ { 0, "{[x,y] : x,y >= 0; [x,y] : 10 <= x <= 20 and y >= -1 }" },
+ { 1, "{ [x, y] : (x >= 1 and y >= 1 and x <= 2 and y <= 2) or "
+ "(y = 3 and x = 1) }" },
+ { 1, "[M] -> { [i0, i1, i2, i3, i4] : (i1 >= 3 and i4 >= 2 + i2 and "
+ "i2 >= 2 and i0 >= 2 and i3 >= 1 + i2 and i0 <= M and "
+ "i1 <= M and i3 <= M and i4 <= M) or "
+ "(i1 >= 2 and i4 >= 1 + i2 and i2 >= 2 and i0 >= 2 and "
+ "i3 >= 1 + i2 and i0 <= M and i1 <= -1 + M and i3 <= M and "
+ "i4 <= -1 + M) }" },
+ { 1, "{ [x, y] : (x >= 0 and y >= 0 and x <= 10 and y <= 10) or "
+ "(x >= 1 and y >= 1 and x <= 11 and y <= 11) }" },
+ { 0, "{[x,0] : x >= 0; [x,1] : x <= 20}" },
+ { 1, "{ [x, 1 - x] : 0 <= x <= 1; [0,0] }" },
+ { 1, "{ [0,0]; [i,i] : 1 <= i <= 10 }" },
+ { 0, "{ [0,0]; [i,j] : 1 <= i,j <= 10 }" },
+ { 1, "{ [0,0]; [i,2i] : 1 <= i <= 10 }" },
+ { 0, "{ [0,0]; [i,2i] : 2 <= i <= 10 }" },
+ { 0, "{ [1,0]; [i,2i] : 1 <= i <= 10 }" },
+ { 0, "{ [0,1]; [i,2i] : 1 <= i <= 10 }" },
+ { 0, "{ [a, b] : exists e : 2e = a and "
+ "a >= 0 and (a <= 3 or (b <= 0 and b >= -4 + a)) }" },
+ { 0, "{ [i, j, i', j'] : i <= 2 and j <= 2 and "
+ "j' >= -1 + 2i + j - 2i' and i' <= -1 + i and "
+ "j >= 1 and j' <= i + j - i' and i >= 1; "
+ "[1, 1, 1, 1] }" },
+ { 1, "{ [i,j] : exists a,b : i = 2a and j = 3b; "
+ "[i,j] : exists a : j = 3a }" },
+ { 1, "{ [a, b, c] : (c <= 7 - b and b <= 1 and b >= 0 and "
+ "c >= 3 + b and b <= 3 + 8a and b >= -26 + 8a and "
+ "a >= 3) or "
+ "(b <= 1 and c <= 7 and b >= 0 and c >= 4 + b and "
+ "b <= 3 + 8a and b >= -26 + 8a and a >= 3) }" },
+ { 1, "{ [a, 0, c] : c >= 1 and c <= 29 and c >= -1 + 8a and "
+ "c <= 6 + 8a and a >= 3; "
+ "[a, -1, c] : c >= 1 and c <= 30 and c >= 8a and "
+ "c <= 7 + 8a and a >= 3 and a <= 4 }" },
+ { 1, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
+ "[x,0] : 3 <= x <= 4 }" },
+ { 1, "{ [x,y] : 0 <= x <= 3 and y >= 0 and x + 3y <= 6; "
+ "[x,0] : 4 <= x <= 5 }" },
+ { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + 2y <= 4; "
+ "[x,0] : 3 <= x <= 5 }" },
+ { 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
+ "[x,0] : 3 <= x <= 4 }" },
+ { 1 , "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
+ "i1 <= 0; "
+ "[i0, 0] : i0 >= 123 and i0 <= 124 }" },
+};
+
+/* Test the functionality of isl_set_coalesce.
+ * That is, check that the output is always equal to the input
+ * and in some cases that the result consists of a single disjunct.
+ */
+static int test_coalesce(struct isl_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coalesce_tests); ++i) {
+ const char *str = coalesce_tests[i].str;
+ int check_one = coalesce_tests[i].single_disjunct;
+ if (test_coalesce_set(ctx, str, check_one) < 0)
+ return -1;
+ }
+
+ if (test_coalesce_unbounded_wrapping(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
+void test_closure(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *dom;
+ isl_map *up, *right;
+ isl_map *map, *map2;
+ int exact;
+
+ /* COCOA example 1 */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
+ "1 <= i and i < n and 1 <= j and j < n or "
+ "i2 = i + 1 and j2 = j - 1 and "
+ "1 <= i and i < n and 2 <= j and j <= n }");
+ map = isl_map_power(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ /* COCOA example 1 */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 1 and j2 = j + 1 and "
+ "1 <= i and i < n and 1 <= j and j < n or "
+ "i2 = i + 1 and j2 = j - 1 and "
+ "1 <= i and i < n and 2 <= j and j <= n }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
+ "1 <= i and i < n and 1 <= j and j <= n and "
+ "2 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
+ "i2 = i + k1 + k2 and j2 = j + k1 - k2 and "
+ "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1 )}");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map2);
+ isl_map_free(map);
+
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [x] -> [y] : y = x + 1 and 0 <= x and x <= n and "
+ " 0 <= y and y <= n }");
+ map = isl_map_transitive_closure(map, &exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [x] -> [y] : y > x and 0 <= x and x <= n and "
+ " 0 <= y and y <= n }");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map2);
+ isl_map_free(map);
+
+ /* COCOA example 2 */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j + 2 and "
+ "1 <= i and i < n - 1 and 1 <= j and j < n - 1 or "
+ "i2 = i + 2 and j2 = j - 2 and "
+ "1 <= i and i < n - 1 and 3 <= j and j <= n }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k : "
+ "1 <= i and i < n - 1 and 1 <= j and j <= n and "
+ "3 <= i2 and i2 <= n and 1 <= j2 and j2 <= n and "
+ "i2 = i + 2 k1 + 2 k2 and j2 = j + 2 k1 - 2 k2 and "
+ "k1 >= 0 and k2 >= 0 and k1 + k2 = k and k >= 1) }");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ /* COCOA Fig.2 left */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 2 and j2 = j and "
+ "i <= 2 j - 3 and i <= n - 2 and j <= 2 i - 1 and "
+ "j <= n or "
+ "i2 = i and j2 = j + 2 and i <= 2 j - 1 and i <= n and "
+ "j <= 2 i - 3 and j <= n - 2 or "
+ "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+ "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ /* COCOA Fig.2 right */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
+ "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
+ "j <= n or "
+ "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
+ "j <= 2 i - 4 and j <= n - 3 or "
+ "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+ "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+ map = isl_map_power(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ /* COCOA Fig.2 right */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i + 3 and j2 = j and "
+ "i <= 2 j - 4 and i <= n - 3 and j <= 2 i - 1 and "
+ "j <= n or "
+ "i2 = i and j2 = j + 3 and i <= 2 j - 1 and i <= n and "
+ "j <= 2 i - 4 and j <= n - 3 or "
+ "i2 = i + 1 and j2 = j + 1 and i <= 2 j - 1 and "
+ "i <= n - 1 and j <= 2 i - 1 and j <= n - 1 }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : exists (k1,k2,k3,k : "
+ "i <= 2 j - 1 and i <= n and j <= 2 i - 1 and "
+ "j <= n and 3 + i + 2 j <= 3 n and "
+ "3 + 2 i + j <= 3n and i2 <= 2 j2 -1 and i2 <= n and "
+ "i2 <= 3 j2 - 4 and j2 <= 2 i2 -1 and j2 <= n and "
+ "13 + 4 j2 <= 11 i2 and i2 = i + 3 k1 + k3 and "
+ "j2 = j + 3 k2 + k3 and k1 >= 0 and k2 >= 0 and "
+ "k3 >= 0 and k1 + k2 + k3 = k and k > 0) }");
+ assert(isl_map_is_equal(map, map2));
+ 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 = 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] }");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map2);
+ isl_map_free(map);
+
+ /* 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 "
+ "i2 = 1 and j2 = j or "
+ "i = 0 and j = 0 and i2 = 0 and j2 = 1 }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ map = isl_map_read_from_str(ctx,
+ "[m,n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 2 and "
+ "1 <= i,i2 <= n and 1 <= j,j2 <= m or "
+ "i2 = i + 1 and 3 <= j2 - j <= 4 and "
+ "1 <= i,i2 <= n and 1 <= j,j2 <= m }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ /* Kelly et al 1996, fig 12 */
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : i2 = i and j2 = j + 1 and "
+ "1 <= i,j,j+1 <= n or "
+ "j = n and j2 = 1 and i2 = i + 1 and "
+ "1 <= i,i+1 <= n }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [i,j] -> [i2,j2] : 1 <= j < j2 <= n and "
+ "1 <= i <= n and i = i2 or "
+ "1 <= i < i2 <= n and 1 <= j <= n and "
+ "1 <= j2 <= n }");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map2);
+ isl_map_free(map);
+
+ /* Omega's closure4 */
+ map = isl_map_read_from_str(ctx,
+ "[m,n] -> { [x,y] -> [x2,y2] : x2 = x and y2 = y + 1 and "
+ "1 <= x,y <= 10 or "
+ "x2 = x + 1 and y2 = y and "
+ "1 <= x <= 20 && 5 <= y <= 15 }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ isl_map_free(map);
+
+ map = isl_map_read_from_str(ctx,
+ "[n] -> { [x] -> [y]: 1 <= n <= y - x <= 10 }");
+ map = isl_map_transitive_closure(map, &exact);
+ assert(!exact);
+ map2 = isl_map_read_from_str(ctx,
+ "[n] -> { [x] -> [y] : 1 <= n <= 10 and y >= n + x }");
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "[n, m] -> { [i0, i1, i2, i3] -> [o0, o1, o2, o3] : "
+ "i3 = 1 and o0 = i0 and o1 = -1 + i1 and o2 = -1 + i2 and "
+ "o3 = -2 + i2 and i1 <= -1 + i0 and i1 >= 1 - m + i0 and "
+ "i1 >= 2 and i1 <= n and i2 >= 3 and i2 <= 1 + n and i2 <= m }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{[0] -> [1]; [2] -> [3]}";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_transitive_closure(map, &exact);
+ assert(exact);
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "[n] -> { [[i0, i1, 1, 0, i0] -> [i5, 1]] -> "
+ "[[i0, -1 + i1, 2, 0, i0] -> [-1 + i5, 2]] : "
+ "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 2 and "
+ "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+ "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+ "[[i0, i1, 2, 0, i0] -> [i5, 1]] -> "
+ "[[i0, i1, 1, 0, i0] -> [-1 + i5, 2]] : "
+ "exists (e0 = [(3 - n)/3]: i5 >= 2 and i1 >= 1 and "
+ "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+ "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+ "[[i0, i1, 1, 0, i0] -> [i5, 2]] -> "
+ "[[i0, -1 + i1, 2, 0, i0] -> [i5, 1]] : "
+ "exists (e0 = [(3 - n)/3]: i1 >= 2 and i5 >= 1 and "
+ "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+ "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n); "
+ "[[i0, i1, 2, 0, i0] -> [i5, 2]] -> "
+ "[[i0, i1, 1, 0, i0] -> [i5, 1]] : "
+ "exists (e0 = [(3 - n)/3]: i5 >= 1 and i1 >= 1 and "
+ "3i0 <= -1 + n and i1 <= -1 + n and i5 <= -1 + n and "
+ "3e0 >= 1 - n and 3e0 <= 2 - n and 3i0 >= -2 + n) }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_transitive_closure(map, NULL);
+ assert(map);
+ isl_map_free(map);
+}
+
+void test_lex(struct isl_ctx *ctx)
+{
+ isl_space *dim;
+ isl_map *map;
+
+ dim = isl_space_set_alloc(ctx, 0, 0);
+ map = isl_map_lex_le(dim);
+ assert(!isl_map_is_empty(map));
+ isl_map_free(map);
+}
+
+static int test_lexmin(struct isl_ctx *ctx)
+{
+ int equal;
+ const char *str;
+ isl_basic_map *bmap;
+ isl_map *map, *map2;
+ isl_set *set;
+ isl_set *set2;
+ isl_pw_multi_aff *pma;
+
+ str = "[p0, p1] -> { [] -> [] : "
+ "exists (e0 = [(2p1)/3], e1, e2, e3 = [(3 - p1 + 3e0)/3], "
+ "e4 = [(p1)/3], e5 = [(p1 + 3e4)/3]: "
+ "3e0 >= -2 + 2p1 and 3e0 >= p1 and 3e3 >= 1 - p1 + 3e0 and "
+ "3e0 <= 2p1 and 3e3 >= -2 + p1 and 3e3 <= -1 + p1 and p1 >= 3 and "
+ "3e5 >= -2 + 2p1 and 3e5 >= p1 and 3e5 <= -1 + p1 + 3e4 and "
+ "3e4 <= p1 and 3e4 >= -2 + p1 and e3 <= -1 + e0 and "
+ "3e4 >= 6 - p1 + 3e1 and 3e1 >= p1 and 3e5 >= -2 + p1 + 3e4 and "
+ "2e4 >= 3 - p1 + 2e1 and e4 <= e1 and 3e3 <= 2 - p1 + 3e0 and "
+ "e5 >= 1 + e1 and 3e4 >= 6 - 2p1 + 3e1 and "
+ "p0 >= 2 and p1 >= p0 and 3e2 >= p1 and 3e4 >= 6 - p1 + 3e2 and "
+ "e2 <= e1 and e3 >= 1 and e4 <= e2) }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_lexmin(map);
+ isl_map_free(map);
+
+ str = "[C] -> { [obj,a,b,c] : obj <= 38 a + 7 b + 10 c and "
+ "a + b <= 1 and c <= 10 b and c <= C and a,b,c,C >= 0 }";
+ set = isl_set_read_from_str(ctx, str);
+ set = isl_set_lexmax(set);
+ str = "[C] -> { [obj,a,b,c] : C = 8 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ set = isl_set_intersect(set, set2);
+ assert(!isl_set_is_empty(set));
+ isl_set_free(set);
+
+ str = "{ [x] -> [y] : x <= y <= 10; [x] -> [5] : -8 <= x <= 8 }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_lexmin(map);
+ str = "{ [x] -> [5] : 6 <= x <= 8; "
+ "[x] -> [x] : x <= 5 or (9 <= x <= 10) }";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{ [x] -> [y] : 4y = x or 4y = -1 + x or 4y = -2 + x }";
+ map = isl_map_read_from_str(ctx, str);
+ map2 = isl_map_copy(map);
+ map = isl_map_lexmin(map);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{ [x] -> [y] : x = 4y; [x] -> [y] : x = 2y }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_lexmin(map);
+ str = "{ [x] -> [y] : (4y = x and x >= 0) or "
+ "(exists (e0 = [(x)/4], e1 = [(-2 + x)/4]: 2y = x and "
+ "4e1 = -2 + x and 4e0 <= -1 + x and 4e0 >= -3 + x)) or "
+ "(exists (e0 = [(x)/4]: 2y = x and 4e0 = x and x <= -4)) }";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{ [i] -> [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
+ " 8i' <= i and 8i' >= -7 + i }";
+ bmap = isl_basic_map_read_from_str(ctx, str);
+ pma = isl_basic_map_lexmin_pw_multi_aff(isl_basic_map_copy(bmap));
+ map2 = isl_map_from_pw_multi_aff(pma);
+ map = isl_map_from_basic_map(bmap);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "{ T[a] -> S[b, c] : a = 4b-2c and c >= b }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_lexmin(map);
+ str = "{ T[a] -> S[b, c] : 2b = a and 2c = a }";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ /* Check that empty pieces are properly combined. */
+ str = "[K, N] -> { [x, y] -> [a, b] : K+2<=N<=K+4 and x>=4 and "
+ "2N-6<=x<K+N and N-1<=a<=K+N-1 and N+b-6<=a<=2N-4 and "
+ "b<=2N-3K+a and 3b<=4N-K+1 and b>=N and a>=x+1 }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_lexmin(map);
+ str = "[K, N] -> { [x, y] -> [1 + x, N] : x >= -6 + 2N and "
+ "x <= -5 + 2N and x >= -1 + 3K - N and x <= -2 + K + N and "
+ "x >= 4 }";
+ map2 = isl_map_read_from_str(ctx, str);
+ assert(isl_map_is_equal(map, map2));
+ isl_map_free(map);
+ isl_map_free(map2);
+
+ str = "[i] -> { [i', j] : j = i - 8i' and i' >= 0 and i' <= 7 and "
+ " 8i' <= i and 8i' >= -7 + i }";
+ set = isl_set_read_from_str(ctx, str);
+ pma = isl_set_lexmin_pw_multi_aff(isl_set_copy(set));
+ set2 = isl_set_from_pw_multi_aff(pma);
+ equal = isl_set_is_equal(set, set2);
+ isl_set_free(set);
+ isl_set_free(set2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected difference between set and "
+ "piecewise affine expression", return -1);
+
+ return 0;
+}
+
+/* Check that isl_set_min_val and isl_set_max_val compute the correct
+ * result on non-convex inputs.
+ */
+static int test_min(struct isl_ctx *ctx)
+{
+ isl_set *set;
+ isl_aff *aff;
+ isl_val *val;
+ int min_ok, max_ok;
+
+ set = isl_set_read_from_str(ctx, "{ [-1]; [1] }");
+ aff = isl_aff_read_from_str(ctx, "{ [x] -> [x] }");
+ val = isl_set_min_val(set, aff);
+ min_ok = isl_val_is_negone(val);
+ isl_val_free(val);
+ val = isl_set_max_val(set, aff);
+ max_ok = isl_val_is_one(val);
+ isl_val_free(val);
+ isl_aff_free(aff);
+ isl_set_free(set);
+
+ if (min_ok < 0 || max_ok < 0)
+ return -1;
+ if (!min_ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected minimum", return -1);
+ if (!max_ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected maximum", return -1);
+
+ return 0;
+}
+
+struct must_may {
+ isl_map *must;
+ isl_map *may;
+};
+
+static int collect_must_may(__isl_take isl_map *dep, int must,
+ void *dep_user, void *user)
+{
+ struct must_may *mm = (struct must_may *)user;
+
+ if (must)
+ mm->must = isl_map_union(mm->must, dep);
+ else
+ mm->may = isl_map_union(mm->may, dep);
+
+ return 0;
+}
+
+static int common_space(void *first, void *second)
+{
+ int depth = *(int *)first;
+ return 2 * depth;
+}
+
+static int map_is_equal(__isl_keep isl_map *map, const char *str)
+{
+ isl_map *map2;
+ int equal;
+
+ if (!map)
+ return -1;
+
+ map2 = isl_map_read_from_str(map->ctx, str);
+ equal = isl_map_is_equal(map, map2);
+ isl_map_free(map2);
+
+ return equal;
+}
+
+static int map_check_equal(__isl_keep isl_map *map, const char *str)
+{
+ int equal;
+
+ equal = map_is_equal(map, str);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(isl_map_get_ctx(map), isl_error_unknown,
+ "result not as expected", return -1);
+ return 0;
+}
+
+void test_dep(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_space *dim;
+ isl_map *map;
+ isl_access_info *ai;
+ isl_flow *flow;
+ int depth;
+ struct must_may mm;
+
+ depth = 3;
+
+ str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+ str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+ str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 3, 3);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10); "
+ " [1,10,0] -> [2,5,0] }";
+ assert(map_is_equal(mm.must, str));
+ str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+ assert(map_is_equal(mm.may, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+
+
+ str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+ str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+ str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 3, 3);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0] -> [2,i,0] : (0 <= i <= 4) or (6 <= i <= 10) }";
+ assert(map_is_equal(mm.must, str));
+ str = "{ [0,5,0] -> [2,5,0]; [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
+ assert(map_is_equal(mm.may, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+
+
+ str = "{ [2,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+ str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ str = "{ [1,i,0] -> [5] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 3, 3);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0] -> [2,i,0] : 0 <= i <= 10; "
+ " [1,i,0] -> [2,5,0] : 0 <= i <= 10 }";
+ assert(map_is_equal(mm.may, str));
+ str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+ assert(map_is_equal(mm.must, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+
+
+ str = "{ [0,i,2] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+ str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ str = "{ [0,i,1] -> [5] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 3, 3);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0] -> [0,i,2] : 0 <= i <= 10; "
+ " [0,i,1] -> [0,5,2] : 0 <= i <= 5 }";
+ assert(map_is_equal(mm.may, str));
+ str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+ assert(map_is_equal(mm.must, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+
+
+ str = "{ [0,i,1] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 2);
+
+ str = "{ [0,i,0] -> [i] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ str = "{ [0,i,2] -> [5] : 0 <= i <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 0, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 3, 3);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0] -> [0,i,1] : 0 <= i <= 10; "
+ " [0,i,2] -> [0,5,1] : 0 <= i <= 4 }";
+ assert(map_is_equal(mm.may, str));
+ str = "{ [i,j,k] -> [l,m,n] : 1 = 0 }";
+ assert(map_is_equal(mm.must, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+
+
+ depth = 5;
+
+ str = "{ [1,i,0,0,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_alloc(map, &depth, &common_space, 1);
+
+ str = "{ [0,i,0,j,0] -> [i,j] : 0 <= i <= 10 and 0 <= j <= 10 }";
+ map = isl_map_read_from_str(ctx, str);
+ ai = isl_access_info_add_source(ai, map, 1, &depth);
+
+ flow = isl_access_info_compute_flow(ai);
+ dim = isl_space_alloc(ctx, 0, 5, 5);
+ mm.must = isl_map_empty(isl_space_copy(dim));
+ mm.may = isl_map_empty(dim);
+
+ isl_flow_foreach(flow, collect_must_may, &mm);
+
+ str = "{ [0,i,0,j,0] -> [1,i,0,0,0] : 0 <= i,j <= 10 }";
+ assert(map_is_equal(mm.must, str));
+ str = "{ [0,0,0,0,0] -> [0,0,0,0,0] : 1 = 0 }";
+ assert(map_is_equal(mm.may, str));
+
+ isl_map_free(mm.must);
+ isl_map_free(mm.may);
+ isl_flow_free(flow);
+}
+
+/* Check that the dependence analysis proceeds without errors.
+ * Earlier versions of isl would break down during the analysis
+ * due to the use of the wrong spaces.
+ */
+static int test_flow(isl_ctx *ctx)
+{
+ const char *str;
+ isl_union_map *access, *schedule;
+ isl_union_map *must_dep, *may_dep;
+ int r;
+
+ str = "{ S0[j] -> i[]; S1[j,i] -> i[]; S2[] -> i[]; S3[] -> i[] }";
+ access = isl_union_map_read_from_str(ctx, str);
+ str = "{ S0[j] -> [0,j,0,0] : 0 <= j < 10; "
+ "S1[j,i] -> [0,j,1,i] : 0 <= j < i < 10; "
+ "S2[] -> [1,0,0,0]; "
+ "S3[] -> [-1,0,0,0] }";
+ schedule = isl_union_map_read_from_str(ctx, str);
+ r = isl_union_map_compute_flow(access, isl_union_map_copy(access),
+ isl_union_map_copy(access), schedule,
+ &must_dep, &may_dep, NULL, NULL);
+ isl_union_map_free(may_dep);
+ isl_union_map_free(must_dep);
+
+ return r;
+}
+
+struct {
+ const char *map;
+ int sv;
+} sv_tests[] = {
+ { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 9 }", 1 },
+ { "[N] -> { [i] -> [f] : 0 <= i <= N and 0 <= i - 10 f <= 10 }", 0 },
+ { "{ [i] -> [3*floor(i/2) + 5*floor(i/3)] }", 1 },
+ { "{ S1[i] -> [i] : 0 <= i <= 9; S2[i] -> [i] : 0 <= i <= 9 }", 1 },
+ { "{ [i] -> S1[i] : 0 <= i <= 9; [i] -> S2[i] : 0 <= i <= 9 }", 0 },
+ { "{ A[i] -> [i]; B[i] -> [i]; B[i] -> [i + 1] }", 0 },
+ { "{ A[i] -> [i]; B[i] -> [i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
+ { "{ A[i] -> [i]; B[i] -> A[i] : i < 0; B[i] -> [i + 1] : i > 0 }", 1 },
+ { "{ A[i] -> [i]; B[i] -> [j] : i - 1 <= j <= i }", 0 },
+};
+
+int test_sv(isl_ctx *ctx)
+{
+ isl_union_map *umap;
+ int i;
+ int sv;
+
+ for (i = 0; i < ARRAY_SIZE(sv_tests); ++i) {
+ umap = isl_union_map_read_from_str(ctx, sv_tests[i].map);
+ sv = isl_union_map_is_single_valued(umap);
+ isl_union_map_free(umap);
+ if (sv < 0)
+ return -1;
+ if (sv_tests[i].sv && !sv)
+ isl_die(ctx, isl_error_internal,
+ "map not detected as single valued", return -1);
+ if (!sv_tests[i].sv && sv)
+ isl_die(ctx, isl_error_internal,
+ "map detected as single valued", return -1);
+ }
+
+ return 0;
+}
+
+void test_bijective_case(struct isl_ctx *ctx, const char *str, int bijective)
+{
+ isl_map *map;
+
+ map = isl_map_read_from_str(ctx, str);
+ if (bijective)
+ assert(isl_map_is_bijective(map));
+ else
+ assert(!isl_map_is_bijective(map));
+ isl_map_free(map);
+}
+
+void test_bijective(struct isl_ctx *ctx)
+{
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i]}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=i}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=0}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i] : j=N}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [j,i]}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i+j]}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> []}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,j,N]}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i]}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [i,i]}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,i]}", 0);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [2i,j]}", 1);
+ test_bijective_case(ctx, "[N,M]->{[i,j] -> [x,y] : 2x=i & y =j}", 1);
+}
+
+/* Inputs for isl_pw_qpolynomial_gist tests.
+ * "pwqp" is the input, "set" is the context and "gist" is the expected result.
+ */
+struct {
+ const char *pwqp;
+ const char *set;
+ const char *gist;
+} pwqp_gist_tests[] = {
+ { "{ [i] -> i }", "{ [k] : exists a : k = 2a }", "{ [i] -> i }" },
+ { "{ [i] -> i + [ (i + [i/3])/2 ] }", "{ [10] }", "{ [i] -> 16 }" },
+ { "{ [i] -> ([(i)/2]) }", "{ [k] : exists a : k = 2a+1 }",
+ "{ [i] -> -1/2 + 1/2 * i }" },
+ { "{ [i] -> i^2 : i != 0 }", "{ [i] : i != 0 }", "{ [i] -> i^2 }" },
+};
+
+static int test_pwqp(struct isl_ctx *ctx)
+{
+ int i;
+ const char *str;
+ isl_set *set;
+ isl_pw_qpolynomial *pwqp1, *pwqp2;
+ int equal;
+
+ str = "{ [i,j,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+ pwqp1 = isl_pw_qpolynomial_move_dims(pwqp1, isl_dim_param, 0,
+ isl_dim_in, 1, 1);
+
+ str = "[j] -> { [i,k] -> 1 + 9 * [i/5] + 7 * [j/11] + 4 * [k/13] }";
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+ pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+ assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+ isl_pw_qpolynomial_free(pwqp1);
+
+ for (i = 0; i < ARRAY_SIZE(pwqp_gist_tests); ++i) {
+ str = pwqp_gist_tests[i].pwqp;
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ str = pwqp_gist_tests[i].set;
+ set = isl_set_read_from_str(ctx, str);
+ pwqp1 = isl_pw_qpolynomial_gist(pwqp1, set);
+ str = pwqp_gist_tests[i].gist;
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+ equal = isl_pw_qpolynomial_is_zero(pwqp1);
+ isl_pw_qpolynomial_free(pwqp1);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ str = "{ [i] -> ([([i/2] + [i/2])/5]) }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ str = "{ [i] -> ([(2 * [i/2])/5]) }";
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+ pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+ assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+ isl_pw_qpolynomial_free(pwqp1);
+
+ str = "{ [x] -> ([x/2] + [(x+1)/2]) }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ str = "{ [x] -> x }";
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+ pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+
+ assert(isl_pw_qpolynomial_is_zero(pwqp1));
+
+ isl_pw_qpolynomial_free(pwqp1);
+
+ str = "{ [i] -> ([i/2]) : i >= 0; [i] -> ([i/3]) : i < 0 }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwqp1 = isl_pw_qpolynomial_coalesce(pwqp1);
+ pwqp1 = isl_pw_qpolynomial_sub(pwqp1, pwqp2);
+ assert(isl_pw_qpolynomial_is_zero(pwqp1));
+ isl_pw_qpolynomial_free(pwqp1);
+
+ str = "{ [a,b,a] -> (([(2*[a/3]+b)/5]) * ([(2*[a/3]+b)/5])) }";
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ set = isl_set_read_from_str(ctx, "{ [a,b,a] }");
+ pwqp1 = isl_pw_qpolynomial_intersect_domain(pwqp1, set);
+ equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
+ isl_pw_qpolynomial_free(pwqp1);
+ isl_pw_qpolynomial_free(pwqp2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ str = "{ [a,b,c] -> (([(2*[a/3]+1)/5]) * ([(2*[c/3]+1)/5])) : b = 1 }";
+ pwqp2 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ str = "{ [a,b,c] -> (([(2*[a/3]+b)/5]) * ([(2*[c/3]+b)/5])) }";
+ pwqp1 = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwqp1 = isl_pw_qpolynomial_fix_val(pwqp1, isl_dim_set, 1,
+ isl_val_one(ctx));
+ equal = isl_pw_qpolynomial_plain_is_equal(pwqp1, pwqp2);
+ isl_pw_qpolynomial_free(pwqp1);
+ isl_pw_qpolynomial_free(pwqp2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+void test_split_periods(isl_ctx *ctx)
+{
+ const char *str;
+ isl_pw_qpolynomial *pwqp;
+
+ str = "{ [U,V] -> 1/3 * U + 2/3 * V - [(U + 2V)/3] + [U/2] : "
+ "U + 2V + 3 >= 0 and - U -2V >= 0 and - U + 10 >= 0 and "
+ "U >= 0; [U,V] -> U^2 : U >= 100 }";
+ pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+
+ pwqp = isl_pw_qpolynomial_split_periods(pwqp, 2);
+ assert(pwqp);
+
+ isl_pw_qpolynomial_free(pwqp);
+}
+
+void test_union(isl_ctx *ctx)
+{
+ const char *str;
+ isl_union_set *uset1, *uset2;
+ isl_union_map *umap1, *umap2;
+
+ str = "{ [i] : 0 <= i <= 1 }";
+ uset1 = isl_union_set_read_from_str(ctx, str);
+ str = "{ [1] -> [0] }";
+ umap1 = isl_union_map_read_from_str(ctx, str);
+
+ umap2 = isl_union_set_lex_gt_union_set(isl_union_set_copy(uset1), uset1);
+ assert(isl_union_map_is_equal(umap1, umap2));
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+
+ str = "{ A[i] -> B[i]; B[i] -> C[i]; A[0] -> C[1] }";
+ umap1 = isl_union_map_read_from_str(ctx, str);
+ str = "{ A[i]; B[i] }";
+ uset1 = isl_union_set_read_from_str(ctx, str);
+
+ uset2 = isl_union_map_domain(umap1);
+
+ assert(isl_union_set_is_equal(uset1, uset2));
+
+ isl_union_set_free(uset1);
+ isl_union_set_free(uset2);
+}
+
+void test_bound(isl_ctx *ctx)
+{
+ const char *str;
+ isl_pw_qpolynomial *pwqp;
+ isl_pw_qpolynomial_fold *pwf;
+
+ str = "{ [[a, b, c, d] -> [e]] -> 0 }";
+ pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
+ assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 4);
+ isl_pw_qpolynomial_fold_free(pwf);
+
+ str = "{ [[x]->[x]] -> 1 : exists a : x = 2 a }";
+ pwqp = isl_pw_qpolynomial_read_from_str(ctx, str);
+ pwf = isl_pw_qpolynomial_bound(pwqp, isl_fold_max, NULL);
+ assert(isl_pw_qpolynomial_fold_dim(pwf, isl_dim_in) == 1);
+ isl_pw_qpolynomial_fold_free(pwf);
+}
+
+void test_lift(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_map *bmap;
+ isl_basic_set *bset;
+
+ str = "{ [i0] : exists e0 : i0 = 4e0 }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ bset = isl_basic_set_lift(bset);
+ bmap = isl_basic_map_from_range(bset);
+ bset = isl_basic_map_domain(bmap);
+ isl_basic_set_free(bset);
+}
+
+struct {
+ const char *set1;
+ const char *set2;
+ int subset;
+} subset_tests[] = {
+ { "{ [112, 0] }",
+ "{ [i0, i1] : exists (e0 = [(i0 - i1)/16], e1: "
+ "16e0 <= i0 - i1 and 16e0 >= -15 + i0 - i1 and "
+ "16e1 <= i1 and 16e0 >= -i1 and 16e1 >= -i0 + i1) }", 1 },
+ { "{ [65] }",
+ "{ [i] : exists (e0 = [(255i)/256], e1 = [(127i + 65e0)/191], "
+ "e2 = [(3i + 61e1)/65], e3 = [(52i + 12e2)/61], "
+ "e4 = [(2i + e3)/3], e5 = [(4i + e3)/4], e6 = [(8i + e3)/12]: "
+ "3e4 = 2i + e3 and 4e5 = 4i + e3 and 12e6 = 8i + e3 and "
+ "i <= 255 and 64e3 >= -45 + 67i and i >= 0 and "
+ "256e0 <= 255i and 256e0 >= -255 + 255i and "
+ "191e1 <= 127i + 65e0 and 191e1 >= -190 + 127i + 65e0 and "
+ "65e2 <= 3i + 61e1 and 65e2 >= -64 + 3i + 61e1 and "
+ "61e3 <= 52i + 12e2 and 61e3 >= -60 + 52i + 12e2) }", 1 },
+ { "{ [i] : 0 <= i <= 10 }", "{ rat: [i] : 0 <= i <= 10 }", 1 },
+ { "{ rat: [i] : 0 <= i <= 10 }", "{ [i] : 0 <= i <= 10 }", 0 },
+ { "{ rat: [0] }", "{ [i] : 0 <= i <= 10 }", 1 },
+ { "{ rat: [(1)/2] }", "{ [i] : 0 <= i <= 10 }", 0 },
+ { "{ [t, i] : (exists (e0 = [(2 + t)/4]: 4e0 <= 2 + t and "
+ "4e0 >= -1 + t and i >= 57 and i <= 62 and "
+ "4e0 <= 62 + t - i and 4e0 >= -61 + t + i and "
+ "t >= 0 and t <= 511 and 4e0 <= -57 + t + i and "
+ "4e0 >= 58 + t - i and i >= 58 + t and i >= 62 - t)) }",
+ "{ [i0, i1] : (exists (e0 = [(4 + i0)/4]: 4e0 <= 62 + i0 - i1 and "
+ "4e0 >= 1 + i0 and i0 >= 0 and i0 <= 511 and "
+ "4e0 <= -57 + i0 + i1)) or "
+ "(exists (e0 = [(2 + i0)/4]: 4e0 <= i0 and "
+ "4e0 >= 58 + i0 - i1 and i0 >= 2 and i0 <= 511 and "
+ "4e0 >= -61 + i0 + i1)) or "
+ "(i1 <= 66 - i0 and i0 >= 2 and i1 >= 59 + i0) }", 1 },
+};
+
+static int test_subset(isl_ctx *ctx)
+{
+ int i;
+ isl_set *set1, *set2;
+ int subset;
+
+ for (i = 0; i < ARRAY_SIZE(subset_tests); ++i) {
+ set1 = isl_set_read_from_str(ctx, subset_tests[i].set1);
+ set2 = isl_set_read_from_str(ctx, subset_tests[i].set2);
+ subset = isl_set_is_subset(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+ if (subset < 0)
+ return -1;
+ if (subset != subset_tests[i].subset)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect subset result", return -1);
+ }
+
+ return 0;
+}
+
+struct {
+ const char *minuend;
+ const char *subtrahend;
+ const char *difference;
+} subtract_domain_tests[] = {
+ { "{ A[i] -> B[i] }", "{ A[i] }", "{ }" },
+ { "{ A[i] -> B[i] }", "{ B[i] }", "{ A[i] -> B[i] }" },
+ { "{ A[i] -> B[i] }", "{ A[i] : i > 0 }", "{ A[i] -> B[i] : i <= 0 }" },
+};
+
+static int test_subtract(isl_ctx *ctx)
+{
+ int i;
+ isl_union_map *umap1, *umap2;
+ isl_union_set *uset;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
+ umap1 = isl_union_map_read_from_str(ctx,
+ subtract_domain_tests[i].minuend);
+ uset = isl_union_set_read_from_str(ctx,
+ subtract_domain_tests[i].subtrahend);
+ umap2 = isl_union_map_read_from_str(ctx,
+ subtract_domain_tests[i].difference);
+ umap1 = isl_union_map_subtract_domain(umap1, uset);
+ equal = isl_union_map_is_equal(umap1, umap2);
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect subtract domain result", return -1);
+ }
+
+ return 0;
+}
+
+int test_factorize(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_set *bset;
+ isl_factorizer *f;
+
+ str = "{ [i0, i1, i2, i3, i4, i5, i6, i7] : 3i5 <= 2 - 2i0 and "
+ "i0 >= -2 and i6 >= 1 + i3 and i7 >= 0 and 3i5 >= -2i0 and "
+ "2i4 <= i2 and i6 >= 1 + 2i0 + 3i1 and i4 <= -1 and "
+ "i6 >= 1 + 2i0 + 3i5 and i6 <= 2 + 2i0 + 3i5 and "
+ "3i5 <= 2 - 2i0 - i2 + 3i4 and i6 <= 2 + 2i0 + 3i1 and "
+ "i0 <= -1 and i7 <= i2 + i3 - 3i4 - i6 and "
+ "3i5 >= -2i0 - i2 + 3i4 }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ f = isl_basic_set_factorizer(bset);
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+ if (!f)
+ isl_die(ctx, isl_error_unknown,
+ "failed to construct factorizer", return -1);
+
+ str = "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
+ "i12 <= 2 + i0 - i11 and 2i8 >= -i4 and i11 >= i1 and "
+ "3i5 <= -i2 and 2i11 >= -i4 - 2i7 and i11 <= 3 + i0 + 3i9 and "
+ "i11 <= -i4 - 2i7 and i12 >= -i10 and i2 >= -2 and "
+ "i11 >= i1 + 3i10 and i11 >= 1 + i0 + 3i9 and "
+ "i11 <= 1 - i4 - 2i8 and 6i6 <= 6 - i2 and 3i6 >= 1 - i2 and "
+ "i11 <= 2 + i1 and i12 <= i4 + i11 and i12 >= i0 - i11 and "
+ "3i5 >= -2 - i2 and i12 >= -1 + i4 + i11 and 3i3 <= 3 - i2 and "
+ "9i6 <= 11 - i2 + 6i5 and 3i3 >= 1 - i2 and "
+ "9i6 <= 5 - i2 + 6i3 and i12 <= -1 and i2 <= 0 }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ f = isl_basic_set_factorizer(bset);
+ isl_basic_set_free(bset);
+ isl_factorizer_free(f);
+ if (!f)
+ isl_die(ctx, isl_error_unknown,
+ "failed to construct factorizer", return -1);
+
+ return 0;
+}
+
+static int check_injective(__isl_take isl_map *map, void *user)
+{
+ int *injective = user;
+
+ *injective = isl_map_is_injective(map);
+ isl_map_free(map);
+
+ if (*injective < 0 || !*injective)
+ return -1;
+
+ return 0;
+}
+
+int test_one_schedule(isl_ctx *ctx, const char *d, const char *w,
+ const char *r, const char *s, int tilable, int parallel)
+{
+ int i;
+ isl_union_set *D;
+ isl_union_map *W, *R, *S;
+ isl_union_map *empty;
+ isl_union_map *dep_raw, *dep_war, *dep_waw, *dep;
+ isl_union_map *validity, *proximity, *coincidence;
+ isl_union_map *schedule;
+ isl_union_map *test;
+ isl_union_set *delta;
+ isl_union_set *domain;
+ isl_set *delta_set;
+ isl_set *slice;
+ isl_set *origin;
+ isl_schedule_constraints *sc;
+ isl_schedule *sched;
+ int is_nonneg, is_parallel, is_tilable, is_injection, is_complete;
+
+ D = isl_union_set_read_from_str(ctx, d);
+ W = isl_union_map_read_from_str(ctx, w);
+ R = isl_union_map_read_from_str(ctx, r);
+ S = isl_union_map_read_from_str(ctx, s);
+
+ W = isl_union_map_intersect_domain(W, isl_union_set_copy(D));
+ R = isl_union_map_intersect_domain(R, isl_union_set_copy(D));
+
+ empty = isl_union_map_empty(isl_union_map_get_space(S));
+ isl_union_map_compute_flow(isl_union_map_copy(R),
+ isl_union_map_copy(W), empty,
+ isl_union_map_copy(S),
+ &dep_raw, NULL, NULL, NULL);
+ isl_union_map_compute_flow(isl_union_map_copy(W),
+ isl_union_map_copy(W),
+ isl_union_map_copy(R),
+ isl_union_map_copy(S),
+ &dep_waw, &dep_war, NULL, NULL);
+
+ dep = isl_union_map_union(dep_waw, dep_war);
+ dep = isl_union_map_union(dep, dep_raw);
+ validity = isl_union_map_copy(dep);
+ coincidence = isl_union_map_copy(dep);
+ proximity = isl_union_map_copy(dep);
+
+ sc = isl_schedule_constraints_on_domain(isl_union_set_copy(D));
+ sc = isl_schedule_constraints_set_validity(sc, validity);
+ sc = isl_schedule_constraints_set_coincidence(sc, coincidence);
+ sc = isl_schedule_constraints_set_proximity(sc, proximity);
+ sched = isl_schedule_constraints_compute_schedule(sc);
+ schedule = isl_schedule_get_map(sched);
+ isl_schedule_free(sched);
+ isl_union_map_free(W);
+ isl_union_map_free(R);
+ isl_union_map_free(S);
+
+ is_injection = 1;
+ isl_union_map_foreach_map(schedule, &check_injective, &is_injection);
+
+ domain = isl_union_map_domain(isl_union_map_copy(schedule));
+ is_complete = isl_union_set_is_subset(D, domain);
+ isl_union_set_free(D);
+ isl_union_set_free(domain);
+
+ test = isl_union_map_reverse(isl_union_map_copy(schedule));
+ test = isl_union_map_apply_range(test, dep);
+ test = isl_union_map_apply_range(test, schedule);
+
+ delta = isl_union_map_deltas(test);
+ if (isl_union_set_n_set(delta) == 0) {
+ is_tilable = 1;
+ is_parallel = 1;
+ is_nonneg = 1;
+ isl_union_set_free(delta);
+ } else {
+ delta_set = isl_set_from_union_set(delta);
+
+ slice = isl_set_universe(isl_set_get_space(delta_set));
+ for (i = 0; i < tilable; ++i)
+ slice = isl_set_lower_bound_si(slice, isl_dim_set, i, 0);
+ is_tilable = isl_set_is_subset(delta_set, slice);
+ isl_set_free(slice);
+
+ slice = isl_set_universe(isl_set_get_space(delta_set));
+ for (i = 0; i < parallel; ++i)
+ slice = isl_set_fix_si(slice, isl_dim_set, i, 0);
+ is_parallel = isl_set_is_subset(delta_set, slice);
+ isl_set_free(slice);
+
+ origin = isl_set_universe(isl_set_get_space(delta_set));
+ for (i = 0; i < isl_set_dim(origin, isl_dim_set); ++i)
+ origin = isl_set_fix_si(origin, isl_dim_set, i, 0);
+
+ delta_set = isl_set_union(delta_set, isl_set_copy(origin));
+ delta_set = isl_set_lexmin(delta_set);
+
+ is_nonneg = isl_set_is_equal(delta_set, origin);
+
+ isl_set_free(origin);
+ isl_set_free(delta_set);
+ }
+
+ if (is_nonneg < 0 || is_parallel < 0 || is_tilable < 0 ||
+ is_injection < 0 || is_complete < 0)
+ return -1;
+ if (!is_complete)
+ isl_die(ctx, isl_error_unknown,
+ "generated schedule incomplete", return -1);
+ if (!is_injection)
+ isl_die(ctx, isl_error_unknown,
+ "generated schedule not injective on each statement",
+ return -1);
+ if (!is_nonneg)
+ isl_die(ctx, isl_error_unknown,
+ "negative dependences in generated schedule",
+ return -1);
+ if (!is_tilable)
+ isl_die(ctx, isl_error_unknown,
+ "generated schedule not as tilable as expected",
+ return -1);
+ if (!is_parallel)
+ isl_die(ctx, isl_error_unknown,
+ "generated schedule not as parallel as expected",
+ return -1);
+
+ return 0;
+}
+
+static __isl_give isl_union_map *compute_schedule(isl_ctx *ctx,
+ const char *domain, const char *validity, const char *proximity)
+{
+ isl_union_set *dom;
+ isl_union_map *dep;
+ isl_union_map *prox;
+ isl_schedule_constraints *sc;
+ isl_schedule *schedule;
+ isl_union_map *sched;
+
+ dom = isl_union_set_read_from_str(ctx, domain);
+ dep = isl_union_map_read_from_str(ctx, validity);
+ prox = isl_union_map_read_from_str(ctx, proximity);
+ sc = isl_schedule_constraints_on_domain(dom);
+ sc = isl_schedule_constraints_set_validity(sc, dep);
+ sc = isl_schedule_constraints_set_proximity(sc, prox);
+ schedule = isl_schedule_constraints_compute_schedule(sc);
+ sched = isl_schedule_get_map(schedule);
+ isl_schedule_free(schedule);
+
+ return sched;
+}
+
+/* Check that a schedule can be constructed on the given domain
+ * with the given validity and proximity constraints.
+ */
+static int test_has_schedule(isl_ctx *ctx, const char *domain,
+ const char *validity, const char *proximity)
+{
+ isl_union_map *sched;
+
+ sched = compute_schedule(ctx, domain, validity, proximity);
+ if (!sched)
+ return -1;
+
+ isl_union_map_free(sched);
+ return 0;
+}
+
+int test_special_schedule(isl_ctx *ctx, const char *domain,
+ const char *validity, const char *proximity, const char *expected_sched)
+{
+ isl_union_map *sched1, *sched2;
+ int equal;
+
+ sched1 = compute_schedule(ctx, domain, validity, proximity);
+ sched2 = isl_union_map_read_from_str(ctx, expected_sched);
+
+ equal = isl_union_map_is_equal(sched1, sched2);
+ isl_union_map_free(sched1);
+ isl_union_map_free(sched2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected schedule",
+ return -1);
+
+ return 0;
+}
+
+/* Check that the schedule map is properly padded, even after being
+ * reconstructed from the band forest.
+ */
+static int test_padded_schedule(isl_ctx *ctx)
+{
+ const char *str;
+ isl_union_set *D;
+ isl_union_map *validity, *proximity;
+ isl_schedule_constraints *sc;
+ isl_schedule *sched;
+ isl_union_map *map1, *map2;
+ isl_band_list *list;
+ int equal;
+
+ str = "[N] -> { S0[i] : 0 <= i <= N; S1[i, j] : 0 <= i, j <= N }";
+ D = isl_union_set_read_from_str(ctx, str);
+ validity = isl_union_map_empty(isl_union_set_get_space(D));
+ proximity = isl_union_map_copy(validity);
+ sc = isl_schedule_constraints_on_domain(D);
+ sc = isl_schedule_constraints_set_validity(sc, validity);
+ sc = isl_schedule_constraints_set_proximity(sc, proximity);
+ sched = isl_schedule_constraints_compute_schedule(sc);
+ map1 = isl_schedule_get_map(sched);
+ list = isl_schedule_get_band_forest(sched);
+ isl_band_list_free(list);
+ map2 = isl_schedule_get_map(sched);
+ isl_schedule_free(sched);
+ equal = isl_union_map_is_equal(map1, map2);
+ isl_union_map_free(map1);
+ isl_union_map_free(map2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "reconstructed schedule map not the same as original",
+ return -1);
+
+ return 0;
+}
+
+/* Input for testing of schedule construction based on
+ * conditional constraints.
+ *
+ * domain is the iteration domain
+ * flow are the flow dependences, which determine the validity and
+ * proximity constraints
+ * condition are the conditions on the conditional validity constraints
+ * conditional_validity are the conditional validity constraints
+ * outer_band_n is the expected number of members in the outer band
+ */
+struct {
+ const char *domain;
+ const char *flow;
+ const char *condition;
+ const char *conditional_validity;
+ int outer_band_n;
+} live_range_tests[] = {
+ /* Contrived example that illustrates that we need to keep
+ * track of tagged condition dependences and
+ * tagged conditional validity dependences
+ * in isl_sched_edge separately.
+ * In particular, the conditional validity constraints on A
+ * cannot be satisfied,
+ * but they can be ignored because there are no corresponding
+ * condition constraints. However, we do have an additional
+ * conditional validity constraint that maps to the same
+ * dependence relation
+ * as the condition constraint on B. If we did not make a distinction
+ * between tagged condition and tagged conditional validity
+ * dependences, then we
+ * could end up treating this shared dependence as an condition
+ * constraint on A, forcing a localization of the conditions,
+ * which is impossible.
+ */
+ { "{ S[i] : 0 <= 1 < 100; T[i] : 0 <= 1 < 100 }",
+ "{ S[i] -> S[i+1] : 0 <= i < 99 }",
+ "{ [S[i] -> B[]] -> [S[i+1] -> B[]] : 0 <= i < 99 }",
+ "{ [S[i] -> A[]] -> [T[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
+ "[T[i] -> A[]] -> [S[i'] -> A[]] : 0 <= i', i < 100 and i != i';"
+ "[S[i] -> A[]] -> [S[i+1] -> A[]] : 0 <= i < 99 }",
+ 1
+ },
+ /* TACO 2013 Fig. 7 */
+ { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
+ "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+ "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+ "[n] -> { [S1[i,j] -> t[]] -> [S2[i,j] -> t[]] : 0 <= i,j < n;"
+ "[S2[i,j] -> x1[]] -> [S2[i,j+1] -> x1[]] : "
+ "0 <= i < n and 0 <= j < n - 1 }",
+ "[n] -> { [S2[i,j] -> t[]] -> [S1[i,j'] -> t[]] : "
+ "0 <= i < n and 0 <= j < j' < n;"
+ "[S2[i,j] -> t[]] -> [S1[i',j'] -> t[]] : "
+ "0 <= i < i' < n and 0 <= j,j' < n;"
+ "[S2[i,j] -> x1[]] -> [S2[i,j'] -> x1[]] : "
+ "0 <= i,j,j' < n and j < j' }",
+ 2
+ },
+ /* TACO 2013 Fig. 7, without tags */
+ { "[n] -> { S1[i,j] : 0 <= i,j < n; S2[i,j] : 0 <= i,j < n }",
+ "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+ "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+ "[n] -> { S1[i,j] -> S2[i,j] : 0 <= i,j < n;"
+ "S2[i,j] -> S2[i,j+1] : 0 <= i < n and 0 <= j < n - 1 }",
+ "[n] -> { S2[i,j] -> S1[i,j'] : 0 <= i < n and 0 <= j < j' < n;"
+ "S2[i,j] -> S1[i',j'] : 0 <= i < i' < n and 0 <= j,j' < n;"
+ "S2[i,j] -> S2[i,j'] : 0 <= i,j,j' < n and j < j' }",
+ 1
+ },
+ /* TACO 2013 Fig. 12 */
+ { "{ S1[i,0] : 0 <= i <= 1; S2[i,j] : 0 <= i <= 1 and 1 <= j <= 2;"
+ "S3[i,3] : 0 <= i <= 1 }",
+ "{ S1[i,0] -> S2[i,1] : 0 <= i <= 1;"
+ "S2[i,1] -> S2[i,2] : 0 <= i <= 1;"
+ "S2[i,2] -> S3[i,3] : 0 <= i <= 1 }",
+ "{ [S1[i,0]->t[]] -> [S2[i,1]->t[]] : 0 <= i <= 1;"
+ "[S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
+ "[S2[i,2]->t[]] -> [S3[i,3]->t[]] : 0 <= i <= 1 }",
+ "{ [S2[i,1]->t[]] -> [S2[i,2]->t[]] : 0 <= i <= 1;"
+ "[S2[0,j]->t[]] -> [S2[1,j']->t[]] : 1 <= j,j' <= 2;"
+ "[S2[0,j]->t[]] -> [S1[1,0]->t[]] : 1 <= j <= 2;"
+ "[S3[0,3]->t[]] -> [S2[1,j]->t[]] : 1 <= j <= 2;"
+ "[S3[0,3]->t[]] -> [S1[1,0]->t[]] }",
+ 1
+ }
+};
+
+/* Test schedule construction based on conditional constraints.
+ * In particular, check the number of members in the outer band
+ * as an indication of whether tiling is possible or not.
+ */
+static int test_conditional_schedule_constraints(isl_ctx *ctx)
+{
+ int i;
+ isl_union_set *domain;
+ isl_union_map *condition;
+ isl_union_map *flow;
+ isl_union_map *validity;
+ isl_schedule_constraints *sc;
+ isl_schedule *schedule;
+ isl_band_list *list;
+ isl_band *band;
+ int n_member;
+
+ for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
+ domain = isl_union_set_read_from_str(ctx,
+ live_range_tests[i].domain);
+ flow = isl_union_map_read_from_str(ctx,
+ live_range_tests[i].flow);
+ condition = isl_union_map_read_from_str(ctx,
+ live_range_tests[i].condition);
+ validity = isl_union_map_read_from_str(ctx,
+ live_range_tests[i].conditional_validity);
+ sc = isl_schedule_constraints_on_domain(domain);
+ sc = isl_schedule_constraints_set_validity(sc,
+ isl_union_map_copy(flow));
+ sc = isl_schedule_constraints_set_proximity(sc, flow);
+ sc = isl_schedule_constraints_set_conditional_validity(sc,
+ condition, validity);
+ schedule = isl_schedule_constraints_compute_schedule(sc);
+ list = isl_schedule_get_band_forest(schedule);
+ band = isl_band_list_get_band(list, 0);
+ n_member = isl_band_n_member(band);
+ isl_band_free(band);
+ isl_band_list_free(list);
+ isl_schedule_free(schedule);
+
+ if (!schedule)
+ return -1;
+ if (n_member != live_range_tests[i].outer_band_n)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected number of members in outer band",
+ return -1);
+ }
+ return 0;
+}
+
+int test_schedule(isl_ctx *ctx)
+{
+ const char *D, *W, *R, *V, *P, *S;
+
+ /* Handle resulting schedule with zero bands. */
+ if (test_one_schedule(ctx, "{[]}", "{}", "{}", "{[] -> []}", 0, 0) < 0)
+ return -1;
+
+ /* Jacobi */
+ D = "[T,N] -> { S1[t,i] : 1 <= t <= T and 2 <= i <= N - 1 }";
+ W = "{ S1[t,i] -> a[t,i] }";
+ R = "{ S1[t,i] -> a[t-1,i]; S1[t,i] -> a[t-1,i-1]; "
+ "S1[t,i] -> a[t-1,i+1] }";
+ S = "{ S1[t,i] -> [t,i] }";
+ if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+ return -1;
+
+ /* Fig. 5 of CC2008 */
+ D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and j >= 2 and "
+ "j <= -1 + N }";
+ W = "[N] -> { S_0[i, j] -> a[i, j] : i >= 0 and i <= -1 + N and "
+ "j >= 2 and j <= -1 + N }";
+ R = "[N] -> { S_0[i, j] -> a[j, i] : i >= 0 and i <= -1 + N and "
+ "j >= 2 and j <= -1 + N; "
+ "S_0[i, j] -> a[i, -1 + j] : i >= 0 and i <= -1 + N and "
+ "j >= 2 and j <= -1 + N }";
+ S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+ return -1;
+
+ D = "{ S1[i] : 0 <= i <= 10; S2[i] : 0 <= i <= 9 }";
+ W = "{ S1[i] -> a[i] }";
+ R = "{ S2[i] -> a[i+1] }";
+ S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+ if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+ return -1;
+
+ D = "{ S1[i] : 0 <= i < 10; S2[i] : 0 <= i < 10 }";
+ W = "{ S1[i] -> a[i] }";
+ R = "{ S2[i] -> a[9-i] }";
+ S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+ if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+ return -1;
+
+ D = "[N] -> { S1[i] : 0 <= i < N; S2[i] : 0 <= i < N }";
+ W = "{ S1[i] -> a[i] }";
+ R = "[N] -> { S2[i] -> a[N-1-i] }";
+ S = "{ S1[i] -> [0,i]; S2[i] -> [1,i] }";
+ if (test_one_schedule(ctx, D, W, R, S, 1, 1) < 0)
+ return -1;
+
+ D = "{ S1[i] : 0 < i < 10; S2[i] : 0 <= i < 10 }";
+ W = "{ S1[i] -> a[i]; S2[i] -> b[i] }";
+ R = "{ S2[i] -> a[i]; S1[i] -> b[i-1] }";
+ S = "{ S1[i] -> [i,0]; S2[i] -> [i,1] }";
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+
+ D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
+ W = "{ S1[i] -> a[0,i]; S2[i,j] -> a[i,j] }";
+ R = "{ S2[i,j] -> a[i-1,j] }";
+ S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
+ if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+ return -1;
+
+ D = "[N] -> { S1[i] : 1 <= i <= N; S2[i,j] : 1 <= i,j <= N }";
+ W = "{ S1[i] -> a[i,0]; S2[i,j] -> a[i,j] }";
+ R = "{ S2[i,j] -> a[i,j-1] }";
+ S = "{ S1[i] -> [0,i,0]; S2[i,j] -> [1,i,j] }";
+ if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+ return -1;
+
+ D = "[N] -> { S_0[]; S_1[i] : i >= 0 and i <= -1 + N; S_2[] }";
+ W = "[N] -> { S_0[] -> a[0]; S_2[] -> b[0]; "
+ "S_1[i] -> a[1 + i] : i >= 0 and i <= -1 + N }";
+ R = "[N] -> { S_2[] -> a[N]; S_1[i] -> a[i] : i >= 0 and i <= -1 + N }";
+ S = "[N] -> { S_1[i] -> [1, i, 0]; S_2[] -> [2, 0, 1]; "
+ "S_0[] -> [0, 0, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 1, 0) < 0)
+ return -1;
+ ctx->opt->schedule_parametric = 0;
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+ ctx->opt->schedule_parametric = 1;
+
+ D = "[N] -> { S1[i] : 1 <= i <= N; S2[i] : 1 <= i <= N; "
+ "S3[i,j] : 1 <= i,j <= N; S4[i] : 1 <= i <= N }";
+ W = "{ S1[i] -> a[i,0]; S2[i] -> a[0,i]; S3[i,j] -> a[i,j] }";
+ R = "[N] -> { S3[i,j] -> a[i-1,j]; S3[i,j] -> a[i,j-1]; "
+ "S4[i] -> a[i,N] }";
+ S = "{ S1[i] -> [0,i,0]; S2[i] -> [1,i,0]; S3[i,j] -> [2,i,j]; "
+ "S4[i] -> [4,i,0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 2, 0) < 0)
+ return -1;
+
+ D = "[N] -> { S_0[i, j] : i >= 1 and i <= N and j >= 1 and j <= N }";
+ W = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
+ "j <= N }";
+ R = "[N] -> { S_0[i, j] -> s[0] : i >= 1 and i <= N and j >= 1 and "
+ "j <= N; "
+ "S_0[i, j] -> a[i, j] : i >= 1 and i <= N and j >= 1 and "
+ "j <= N }";
+ S = "[N] -> { S_0[i, j] -> [0, i, 0, j, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+
+ D = "[N] -> { S_0[t] : t >= 0 and t <= -1 + N; "
+ " S_2[t] : t >= 0 and t <= -1 + N; "
+ " S_1[t, i] : t >= 0 and t <= -1 + N and i >= 0 and "
+ "i <= -1 + N }";
+ W = "[N] -> { S_0[t] -> a[t, 0] : t >= 0 and t <= -1 + N; "
+ " S_2[t] -> b[t] : t >= 0 and t <= -1 + N; "
+ " S_1[t, i] -> a[t, 1 + i] : t >= 0 and t <= -1 + N and "
+ "i >= 0 and i <= -1 + N }";
+ R = "[N] -> { S_1[t, i] -> a[t, i] : t >= 0 and t <= -1 + N and "
+ "i >= 0 and i <= -1 + N; "
+ " S_2[t] -> a[t, N] : t >= 0 and t <= -1 + N }";
+ S = "[N] -> { S_2[t] -> [0, t, 2]; S_1[t, i] -> [0, t, 1, i, 0]; "
+ " S_0[t] -> [0, t, 0] }";
+
+ if (test_one_schedule(ctx, D, W, R, S, 2, 1) < 0)
+ return -1;
+ ctx->opt->schedule_parametric = 0;
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+ ctx->opt->schedule_parametric = 1;
+
+ D = "[N] -> { S1[i,j] : 0 <= i,j < N; S2[i,j] : 0 <= i,j < N }";
+ S = "{ S1[i,j] -> [0,i,j]; S2[i,j] -> [1,i,j] }";
+ if (test_one_schedule(ctx, D, "{}", "{}", S, 2, 2) < 0)
+ return -1;
+
+ D = "[M, N] -> { S_1[i] : i >= 0 and i <= -1 + M; "
+ "S_0[i, j] : i >= 0 and i <= -1 + M and j >= 0 and j <= -1 + N }";
+ W = "[M, N] -> { S_0[i, j] -> a[j] : i >= 0 and i <= -1 + M and "
+ "j >= 0 and j <= -1 + N; "
+ "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
+ R = "[M, N] -> { S_0[i, j] -> a[0] : i >= 0 and i <= -1 + M and "
+ "j >= 0 and j <= -1 + N; "
+ "S_1[i] -> b[0] : i >= 0 and i <= -1 + M }";
+ S = "[M, N] -> { S_1[i] -> [1, i, 0]; S_0[i, j] -> [0, i, 0, j, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+
+ D = "{ S_0[i] : i >= 0 }";
+ W = "{ S_0[i] -> a[i] : i >= 0 }";
+ R = "{ S_0[i] -> a[0] : i >= 0 }";
+ S = "{ S_0[i] -> [0, i, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+
+ D = "{ S_0[i] : i >= 0; S_1[i] : i >= 0 }";
+ W = "{ S_0[i] -> a[i] : i >= 0; S_1[i] -> b[i] : i >= 0 }";
+ R = "{ S_0[i] -> b[0] : i >= 0; S_1[i] -> a[i] : i >= 0 }";
+ S = "{ S_1[i] -> [0, i, 1]; S_0[i] -> [0, i, 0] }";
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+
+ D = "[n] -> { S_0[j, k] : j <= -1 + n and j >= 0 and "
+ "k <= -1 + n and k >= 0 }";
+ W = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and " "k <= -1 + n and k >= 0 }";
+ R = "[n] -> { S_0[j, k] -> B[j] : j <= -1 + n and j >= 0 and "
+ "k <= -1 + n and k >= 0; "
+ "S_0[j, k] -> B[k] : j <= -1 + n and j >= 0 and "
+ "k <= -1 + n and k >= 0; "
+ "S_0[j, k] -> A[k] : j <= -1 + n and j >= 0 and "
+ "k <= -1 + n and k >= 0 }";
+ S = "[n] -> { S_0[j, k] -> [2, j, k] }";
+ ctx->opt->schedule_outer_coincidence = 1;
+ if (test_one_schedule(ctx, D, W, R, S, 0, 0) < 0)
+ return -1;
+ ctx->opt->schedule_outer_coincidence = 0;
+
+ D = "{Stmt_for_body24[i0, i1, i2, i3]:"
+ "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 6 and i2 >= 2 and "
+ "i2 <= 6 - i1 and i3 >= 0 and i3 <= -1 + i2;"
+ "Stmt_for_body24[i0, i1, 1, 0]:"
+ "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 5;"
+ "Stmt_for_body7[i0, i1, i2]:"
+ "i0 >= 0 and i0 <= 1 and i1 >= 0 and i1 <= 7 and i2 >= 0 and "
+ "i2 <= 7 }";
+
+ V = "{Stmt_for_body24[0, i1, i2, i3] -> "
+ "Stmt_for_body24[1, i1, i2, i3]:"
+ "i3 >= 0 and i3 <= -1 + i2 and i1 >= 0 and i2 <= 6 - i1 and "
+ "i2 >= 1;"
+ "Stmt_for_body24[0, i1, i2, i3] -> "
+ "Stmt_for_body7[1, 1 + i1 + i3, 1 + i1 + i2]:"
+ "i3 <= -1 + i2 and i2 <= 6 - i1 and i2 >= 1 and i1 >= 0 and "
+ "i3 >= 0;"
+ "Stmt_for_body24[0, i1, i2, i3] ->"
+ "Stmt_for_body7[1, i1, 1 + i1 + i3]:"
+ "i3 >= 0 and i2 <= 6 - i1 and i1 >= 0 and i3 <= -1 + i2;"
+ "Stmt_for_body7[0, i1, i2] -> Stmt_for_body7[1, i1, i2]:"
+ "(i2 >= 1 + i1 and i2 <= 6 and i1 >= 0 and i1 <= 4) or "
+ "(i2 >= 3 and i2 <= 7 and i1 >= 1 and i2 >= 1 + i1) or "
+ "(i2 >= 0 and i2 <= i1 and i2 >= -7 + i1 and i1 <= 7);"
+ "Stmt_for_body7[0, i1, 1 + i1] -> Stmt_for_body7[1, i1, 1 + i1]:"
+ "i1 <= 6 and i1 >= 0;"
+ "Stmt_for_body7[0, 0, 7] -> Stmt_for_body7[1, 0, 7];"
+ "Stmt_for_body7[i0, i1, i2] -> "
+ "Stmt_for_body24[i0, o1, -1 + i2 - o1, -1 + i1 - o1]:"
+ "i0 >= 0 and i0 <= 1 and o1 >= 0 and i2 >= 1 + i1 and "
+ "o1 <= -2 + i2 and i2 <= 7 and o1 <= -1 + i1;"
+ "Stmt_for_body7[i0, i1, i2] -> "
+ "Stmt_for_body24[i0, i1, o2, -1 - i1 + i2]:"
+ "i0 >= 0 and i0 <= 1 and i1 >= 0 and o2 >= -i1 + i2 and "
+ "o2 >= 1 and o2 <= 6 - i1 and i2 >= 1 + i1 }";
+ P = V;
+ S = "{ Stmt_for_body24[i0, i1, i2, i3] -> "
+ "[i0, 5i0 + i1, 6i0 + i1 + i2, 1 + 6i0 + i1 + i2 + i3, 1];"
+ "Stmt_for_body7[i0, i1, i2] -> [0, 5i0, 6i0 + i1, 6i0 + i2, 0] }";
+
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+
+ D = "{ S_0[i, j] : i >= 1 and i <= 10 and j >= 1 and j <= 8 }";
+ V = "{ S_0[i, j] -> S_0[i, 1 + j] : i >= 1 and i <= 10 and "
+ "j >= 1 and j <= 7;"
+ "S_0[i, j] -> S_0[1 + i, j] : i >= 1 and i <= 9 and "
+ "j >= 1 and j <= 8 }";
+ P = "{ }";
+ S = "{ S_0[i, j] -> [i + j, j] }";
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+ /* Fig. 1 from Feautrier's "Some Efficient Solutions..." pt. 2, 1992 */
+ D = "[N] -> { S_0[i, j] : i >= 0 and i <= -1 + N and "
+ "j >= 0 and j <= -1 + i }";
+ V = "[N] -> { S_0[i, j] -> S_0[i, 1 + j] : j <= -2 + i and "
+ "i <= -1 + N and j >= 0;"
+ "S_0[i, -1 + i] -> S_0[1 + i, 0] : i >= 1 and "
+ "i <= -2 + N }";
+ P = "{ }";
+ S = "{ S_0[i, j] -> [i, j] }";
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+ /* Test both algorithms on a case with only proximity dependences. */
+ D = "{ S[i,j] : 0 <= i <= 10 }";
+ V = "{ }";
+ P = "{ S[i,j] -> S[i+1,j] : 0 <= i,j <= 10 }";
+ S = "{ S[i, j] -> [j, i] }";
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+ if (test_special_schedule(ctx, D, V, P, S) < 0)
+ return -1;
+
+ D = "{ A[a]; B[] }";
+ V = "{}";
+ P = "{ A[a] -> B[] }";
+ if (test_has_schedule(ctx, D, V, P) < 0)
+ return -1;
+
+ if (test_padded_schedule(ctx) < 0)
+ return -1;
+
+ /* Check that check for progress is not confused by rational
+ * solution.
+ */
+ D = "[N] -> { S0[i, j] : i >= 0 and i <= N and j >= 0 and j <= N }";
+ V = "[N] -> { S0[i0, -1 + N] -> S0[2 + i0, 0] : i0 >= 0 and "
+ "i0 <= -2 + N; "
+ "S0[i0, i1] -> S0[i0, 1 + i1] : i0 >= 0 and "
+ "i0 <= N and i1 >= 0 and i1 <= -1 + N }";
+ P = "{}";
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+ if (test_has_schedule(ctx, D, V, P) < 0)
+ return -1;
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+ /* Check that we allow schedule rows that are only non-trivial
+ * on some full-dimensional domains.
+ */
+ D = "{ S1[j] : 0 <= j <= 1; S0[]; S2[k] : 0 <= k <= 1 }";
+ V = "{ S0[] -> S1[j] : 0 <= j <= 1; S2[0] -> S0[];"
+ "S1[j] -> S2[1] : 0 <= j <= 1 }";
+ P = "{}";
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_FEAUTRIER;
+ if (test_has_schedule(ctx, D, V, P) < 0)
+ return -1;
+ ctx->opt->schedule_algorithm = ISL_SCHEDULE_ALGORITHM_ISL;
+
+ if (test_conditional_schedule_constraints(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
+int test_plain_injective(isl_ctx *ctx, const char *str, int injective)
+{
+ isl_union_map *umap;
+ int test;
+
+ umap = isl_union_map_read_from_str(ctx, str);
+ test = isl_union_map_plain_is_injective(umap);
+ isl_union_map_free(umap);
+ if (test < 0)
+ return -1;
+ if (test == injective)
+ return 0;
+ if (injective)
+ isl_die(ctx, isl_error_unknown,
+ "map not detected as injective", return -1);
+ else
+ isl_die(ctx, isl_error_unknown,
+ "map detected as injective", return -1);
+}
+
+int test_injective(isl_ctx *ctx)
+{
+ const char *str;
+
+ if (test_plain_injective(ctx, "{S[i,j] -> A[0]; T[i,j] -> B[1]}", 0))
+ return -1;
+ if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> B[0]}", 1))
+ return -1;
+ if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[1]}", 1))
+ return -1;
+ if (test_plain_injective(ctx, "{S[] -> A[0]; T[] -> A[0]}", 0))
+ return -1;
+ if (test_plain_injective(ctx, "{S[i] -> A[i,0]; T[i] -> A[i,1]}", 1))
+ return -1;
+ if (test_plain_injective(ctx, "{S[i] -> A[i]; T[i] -> A[i]}", 0))
+ return -1;
+ if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[0,1]}", 1))
+ return -1;
+ if (test_plain_injective(ctx, "{S[] -> A[0,0]; T[] -> A[1,0]}", 1))
+ return -1;
+
+ str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[1,0]}";
+ if (test_plain_injective(ctx, str, 1))
+ return -1;
+ str = "{S[] -> A[0,0]; T[] -> A[0,1]; U[] -> A[0,0]}";
+ if (test_plain_injective(ctx, str, 0))
+ return -1;
+
+ return 0;
+}
+
+static int aff_plain_is_equal(__isl_keep isl_aff *aff, const char *str)
+{
+ isl_aff *aff2;
+ int equal;
+
+ if (!aff)
+ return -1;
+
+ aff2 = isl_aff_read_from_str(isl_aff_get_ctx(aff), str);
+ equal = isl_aff_plain_is_equal(aff, aff2);
+ isl_aff_free(aff2);
+
+ return equal;
+}
+
+static int aff_check_plain_equal(__isl_keep isl_aff *aff, const char *str)
+{
+ int equal;
+
+ equal = aff_plain_is_equal(aff, str);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(isl_aff_get_ctx(aff), isl_error_unknown,
+ "result not as expected", return -1);
+ return 0;
+}
+
+struct {
+ __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+} aff_bin_op[] = {
+ ['+'] = { &isl_aff_add },
+ ['-'] = { &isl_aff_sub },
+ ['*'] = { &isl_aff_mul },
+ ['/'] = { &isl_aff_div },
+};
+
+struct {
+ const char *arg1;
+ unsigned char op;
+ const char *arg2;
+ const char *res;
+} aff_bin_tests[] = {
+ { "{ [i] -> [i] }", '+', "{ [i] -> [i] }",
+ "{ [i] -> [2i] }" },
+ { "{ [i] -> [i] }", '-', "{ [i] -> [i] }",
+ "{ [i] -> [0] }" },
+ { "{ [i] -> [i] }", '*', "{ [i] -> [2] }",
+ "{ [i] -> [2i] }" },
+ { "{ [i] -> [2] }", '*', "{ [i] -> [i] }",
+ "{ [i] -> [2i] }" },
+ { "{ [i] -> [i] }", '/', "{ [i] -> [2] }",
+ "{ [i] -> [i/2] }" },
+ { "{ [i] -> [2i] }", '/', "{ [i] -> [2] }",
+ "{ [i] -> [i] }" },
+ { "{ [i] -> [i] }", '+', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [i] }", '-', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [i] }", '*', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [2] }", '*', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [i] }", '/', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [2] }", '/', "{ [i] -> [NaN] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '+', "{ [i] -> [i] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '-', "{ [i] -> [i] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '*', "{ [i] -> [2] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '*', "{ [i] -> [i] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '/', "{ [i] -> [2] }",
+ "{ [i] -> [NaN] }" },
+ { "{ [i] -> [NaN] }", '/', "{ [i] -> [i] }",
+ "{ [i] -> [NaN] }" },
+};
+
+/* Perform some basic tests of binary operations on isl_aff objects.
+ */
+static int test_bin_aff(isl_ctx *ctx)
+{
+ int i;
+ isl_aff *aff1, *aff2, *res;
+ __isl_give isl_aff *(*fn)(__isl_take isl_aff *aff1,
+ __isl_take isl_aff *aff2);
+ int ok;
+
+ for (i = 0; i < ARRAY_SIZE(aff_bin_tests); ++i) {
+ aff1 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg1);
+ aff2 = isl_aff_read_from_str(ctx, aff_bin_tests[i].arg2);
+ res = isl_aff_read_from_str(ctx, aff_bin_tests[i].res);
+ fn = aff_bin_op[aff_bin_tests[i].op].fn;
+ aff1 = fn(aff1, aff2);
+ if (isl_aff_is_nan(res))
+ ok = isl_aff_is_nan(aff1);
+ else
+ ok = isl_aff_plain_is_equal(aff1, res);
+ isl_aff_free(aff1);
+ isl_aff_free(res);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ 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;
+ const char *res;
+} upma_bin_tests[] = {
+ { &isl_union_pw_multi_aff_add, "{ A[] -> [0]; B[0] -> [1] }",
+ "{ B[x] -> [2] : x >= 0 }", "{ B[0] -> [3] }" },
+ { &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 }" },
+};
+
+/* Perform some basic tests of binary operations on
+ * isl_union_pw_multi_aff objects.
+ */
+static int test_bin_upma(isl_ctx *ctx)
+{
+ int i;
+ isl_union_pw_multi_aff *upma1, *upma2, *res;
+ int ok;
+
+ for (i = 0; i < ARRAY_SIZE(upma_bin_tests); ++i) {
+ upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_tests[i].arg1);
+ upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_tests[i].arg2);
+ res = isl_union_pw_multi_aff_read_from_str(ctx,
+ upma_bin_tests[i].res);
+ upma1 = upma_bin_tests[i].fn(upma1, upma2);
+ ok = isl_union_pw_multi_aff_plain_is_equal(upma1, res);
+ isl_union_pw_multi_aff_free(upma1);
+ isl_union_pw_multi_aff_free(res);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ return 0;
+}
+
+int test_aff(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_space *space;
+ isl_local_space *ls;
+ isl_aff *aff;
+ int zero, equal;
+
+ if (test_bin_aff(ctx) < 0)
+ return -1;
+ if (test_bin_upma(ctx) < 0)
+ return -1;
+
+ space = isl_space_set_alloc(ctx, 0, 1);
+ ls = isl_local_space_from_space(space);
+ aff = isl_aff_zero_on_domain(ls);
+
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+ aff = isl_aff_scale_down_ui(aff, 3);
+ aff = isl_aff_floor(aff);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+ aff = isl_aff_scale_down_ui(aff, 2);
+ aff = isl_aff_floor(aff);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, 0, 1);
+
+ str = "{ [10] }";
+ set = isl_set_read_from_str(ctx, str);
+ aff = isl_aff_gist(aff, set);
+
+ aff = isl_aff_add_constant_si(aff, -16);
+ zero = isl_aff_plain_is_zero(aff);
+ isl_aff_free(aff);
+
+ if (zero < 0)
+ return -1;
+ if (!zero)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ aff = isl_aff_read_from_str(ctx, "{ [-1] }");
+ aff = isl_aff_scale_down_ui(aff, 64);
+ aff = isl_aff_floor(aff);
+ equal = aff_check_plain_equal(aff, "{ [-1] }");
+ isl_aff_free(aff);
+ if (equal < 0)
+ return -1;
+
+ return 0;
+}
+
+int test_dim_max(isl_ctx *ctx)
+{
+ int equal;
+ const char *str;
+ isl_set *set1, *set2;
+ isl_set *set;
+ isl_map *map;
+ isl_pw_aff *pwaff;
+
+ str = "[N] -> { [i] : 0 <= i <= min(N,10) }";
+ set = isl_set_read_from_str(ctx, str);
+ pwaff = isl_set_dim_max(set, 0);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[N] -> { [10] : N >= 10; [N] : N <= 9 and N >= 0 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ str = "[N] -> { [i] : 0 <= i <= max(2N,N+6) }";
+ set = isl_set_read_from_str(ctx, str);
+ pwaff = isl_set_dim_max(set, 0);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ str = "[N] -> { [i] : 0 <= i <= 2N or 0 <= i <= N+6 }";
+ set = isl_set_read_from_str(ctx, str);
+ pwaff = isl_set_dim_max(set, 0);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[N] -> { [6 + N] : -6 <= N <= 5; [2N] : N >= 6 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ str = "[N,M] -> { [i,j] -> [([i/16]), i%16, ([j/16]), j%16] : "
+ "0 <= i < N and 0 <= j < M }";
+ map = isl_map_read_from_str(ctx, str);
+ set = isl_map_range(map);
+
+ pwaff = isl_set_dim_max(isl_set_copy(set), 0);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[N,M] -> { [([(N-1)/16])] : M,N > 0 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+
+ pwaff = isl_set_dim_max(isl_set_copy(set), 3);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[N,M] -> { [t] : t = min(M-1,15) and M,N > 0 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ if (equal >= 0 && equal)
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+
+ isl_set_free(set);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ /* Check that solutions are properly merged. */
+ str = "[n] -> { [a, b, c] : c >= -4a - 2b and "
+ "c <= -1 + n - 4a - 2b and c >= -2b and "
+ "4a >= -4 + n and c >= 0 }";
+ set = isl_set_read_from_str(ctx, str);
+ pwaff = isl_set_dim_min(set, 2);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[n] -> { [(0)] : n >= 1 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ /* Check that empty solution lie in the right space. */
+ str = "[n] -> { [t,a] : 1 = 0 }";
+ set = isl_set_read_from_str(ctx, str);
+ pwaff = isl_set_dim_max(set, 0);
+ set1 = isl_set_from_pw_aff(pwaff);
+ str = "[n] -> { [t] : 1 = 0 }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+/* Is "pma" obviously equal to the isl_pw_multi_aff represented by "str"?
+ */
+static int pw_multi_aff_plain_is_equal(__isl_keep isl_pw_multi_aff *pma,
+ const char *str)
+{
+ isl_ctx *ctx;
+ isl_pw_multi_aff *pma2;
+ int equal;
+
+ if (!pma)
+ return -1;
+
+ ctx = isl_pw_multi_aff_get_ctx(pma);
+ pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+ equal = isl_pw_multi_aff_plain_is_equal(pma, pma2);
+ isl_pw_multi_aff_free(pma2);
+
+ return equal;
+}
+
+/* Check that "pma" is obviously equal to the isl_pw_multi_aff
+ * represented by "str".
+ */
+static int pw_multi_aff_check_plain_equal(__isl_keep isl_pw_multi_aff *pma,
+ const char *str)
+{
+ int equal;
+
+ equal = pw_multi_aff_plain_is_equal(pma, str);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_unknown,
+ "result not as expected", return -1);
+ return 0;
+}
+
+/* Basic test for isl_pw_multi_aff_product.
+ *
+ * Check that multiple pieces are properly handled.
+ */
+static int test_product_pma(isl_ctx *ctx)
+{
+ int equal;
+ const char *str;
+ isl_pw_multi_aff *pma1, *pma2;
+
+ str = "{ A[i] -> B[1] : i < 0; A[i] -> B[2] : i >= 0 }";
+ pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
+ str = "{ C[] -> D[] }";
+ pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+ pma1 = isl_pw_multi_aff_product(pma1, pma2);
+ str = "{ [A[i] -> C[]] -> [B[(1)] -> D[]] : i < 0;"
+ "[A[i] -> C[]] -> [B[(2)] -> D[]] : i >= 0 }";
+ equal = pw_multi_aff_check_plain_equal(pma1, str);
+ isl_pw_multi_aff_free(pma1);
+ if (equal < 0)
+ return -1;
+
+ return 0;
+}
+
+int test_product(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_set *uset1, *uset2;
+ int ok;
+
+ str = "{ A[i] }";
+ set = isl_set_read_from_str(ctx, str);
+ set = isl_set_product(set, isl_set_copy(set));
+ ok = isl_set_is_wrapping(set);
+ isl_set_free(set);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ str = "{ [] }";
+ uset1 = isl_union_set_read_from_str(ctx, str);
+ uset1 = isl_union_set_product(uset1, isl_union_set_copy(uset1));
+ str = "{ [[] -> []] }";
+ uset2 = isl_union_set_read_from_str(ctx, str);
+ ok = isl_union_set_is_equal(uset1, uset2);
+ isl_union_set_free(uset1);
+ isl_union_set_free(uset2);
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ if (test_product_pma(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check that two sets are not considered disjoint just because
+ * they have a different set of (named) parameters.
+ */
+static int test_disjoint(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set, *set2;
+ int disjoint;
+
+ str = "[n] -> { [[]->[]] }";
+ set = isl_set_read_from_str(ctx, str);
+ str = "{ [[]->[]] }";
+ set2 = isl_set_read_from_str(ctx, str);
+ disjoint = isl_set_is_disjoint(set, set2);
+ isl_set_free(set);
+ isl_set_free(set2);
+ if (disjoint < 0)
+ return -1;
+ if (disjoint)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+int test_equal(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set, *set2;
+ int equal;
+
+ str = "{ S_6[i] }";
+ set = isl_set_read_from_str(ctx, str);
+ str = "{ S_7[i] }";
+ set2 = isl_set_read_from_str(ctx, str);
+ equal = isl_set_is_equal(set, set2);
+ isl_set_free(set);
+ isl_set_free(set2);
+ if (equal < 0)
+ return -1;
+ if (equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+static int test_plain_fixed(isl_ctx *ctx, __isl_take isl_map *map,
+ enum isl_dim_type type, unsigned pos, int fixed)
+{
+ int test;
+
+ test = isl_map_plain_is_fixed(map, type, pos, NULL);
+ isl_map_free(map);
+ if (test < 0)
+ return -1;
+ if (test == fixed)
+ return 0;
+ if (fixed)
+ isl_die(ctx, isl_error_unknown,
+ "map not detected as fixed", return -1);
+ else
+ isl_die(ctx, isl_error_unknown,
+ "map detected as fixed", return -1);
+}
+
+int test_fixed(isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map;
+
+ str = "{ [i] -> [i] }";
+ map = isl_map_read_from_str(ctx, str);
+ if (test_plain_fixed(ctx, map, isl_dim_out, 0, 0))
+ return -1;
+ str = "{ [i] -> [1] }";
+ map = isl_map_read_from_str(ctx, str);
+ if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+ return -1;
+ str = "{ S_1[p1] -> [o0] : o0 = -2 and p1 >= 1 and p1 <= 7 }";
+ map = isl_map_read_from_str(ctx, str);
+ if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+ return -1;
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_neg(map);
+ if (test_plain_fixed(ctx, map, isl_dim_out, 0, 1))
+ return -1;
+
+ return 0;
+}
+
+struct isl_vertices_test_data {
+ const char *set;
+ int n;
+ const char *vertex[2];
+} vertices_tests[] = {
+ { "{ A[t, i] : t = 12 and i >= 4 and i <= 12 }",
+ 2, { "{ A[12, 4] }", "{ A[12, 12] }" } },
+ { "{ A[t, i] : t = 14 and i = 1 }",
+ 1, { "{ A[14, 1] }" } },
+};
+
+/* Check that "vertex" corresponds to one of the vertices in data->vertex.
+ */
+static int find_vertex(__isl_take isl_vertex *vertex, void *user)
+{
+ struct isl_vertices_test_data *data = user;
+ isl_ctx *ctx;
+ isl_multi_aff *ma;
+ isl_basic_set *bset;
+ isl_pw_multi_aff *pma;
+ int i;
+ int equal;
+
+ ctx = isl_vertex_get_ctx(vertex);
+ bset = isl_vertex_get_domain(vertex);
+ ma = isl_vertex_get_expr(vertex);
+ pma = isl_pw_multi_aff_alloc(isl_set_from_basic_set(bset), ma);
+
+ for (i = 0; i < data->n; ++i) {
+ isl_pw_multi_aff *pma_i;
+
+ pma_i = isl_pw_multi_aff_read_from_str(ctx, data->vertex[i]);
+ equal = isl_pw_multi_aff_plain_is_equal(pma, pma_i);
+ isl_pw_multi_aff_free(pma_i);
+
+ if (equal < 0 || equal)
+ break;
+ }
+
+ isl_pw_multi_aff_free(pma);
+ isl_vertex_free(vertex);
+
+ if (equal < 0)
+ return -1;
+
+ return equal ? 0 : - 1;
+}
+
+int test_vertices(isl_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(vertices_tests); ++i) {
+ isl_basic_set *bset;
+ isl_vertices *vertices;
+ int ok = 1;
+ int n;
+
+ bset = isl_basic_set_read_from_str(ctx, vertices_tests[i].set);
+ vertices = isl_basic_set_compute_vertices(bset);
+ n = isl_vertices_get_n_vertices(vertices);
+ if (vertices_tests[i].n != n)
+ ok = 0;
+ if (isl_vertices_foreach_vertex(vertices, &find_vertex,
+ &vertices_tests[i]) < 0)
+ ok = 0;
+ isl_vertices_free(vertices);
+ isl_basic_set_free(bset);
+
+ if (!vertices)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown, "unexpected vertices",
+ return -1);
+ }
+
+ return 0;
+}
+
+int test_union_pw(isl_ctx *ctx)
+{
+ int equal;
+ const char *str;
+ isl_union_set *uset;
+ isl_union_pw_qpolynomial *upwqp1, *upwqp2;
+
+ str = "{ [x] -> x^2 }";
+ upwqp1 = isl_union_pw_qpolynomial_read_from_str(ctx, str);
+ upwqp2 = isl_union_pw_qpolynomial_copy(upwqp1);
+ uset = isl_union_pw_qpolynomial_domain(upwqp1);
+ upwqp1 = isl_union_pw_qpolynomial_copy(upwqp2);
+ upwqp1 = isl_union_pw_qpolynomial_intersect_domain(upwqp1, uset);
+ equal = isl_union_pw_qpolynomial_plain_is_equal(upwqp1, upwqp2);
+ isl_union_pw_qpolynomial_free(upwqp1);
+ isl_union_pw_qpolynomial_free(upwqp2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+int test_output(isl_ctx *ctx)
+{
+ char *s;
+ const char *str;
+ isl_pw_aff *pa;
+ isl_printer *p;
+ int equal;
+
+ str = "[x] -> { [1] : x % 4 <= 2; [2] : x = 3 }";
+ pa = isl_pw_aff_read_from_str(ctx, str);
+
+ p = isl_printer_to_str(ctx);
+ p = isl_printer_set_output_format(p, ISL_FORMAT_C);
+ p = isl_printer_print_pw_aff(p, pa);
+ s = isl_printer_get_str(p);
+ isl_printer_free(p);
+ isl_pw_aff_free(pa);
+ if (!s)
+ equal = -1;
+ else
+ equal = !strcmp(s, "4 * floord(x, 4) + 2 >= x ? 1 : 2");
+ free(s);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "unexpected result", return -1);
+
+ return 0;
+}
+
+int test_sample(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_set *bset1, *bset2;
+ int empty, subset;
+
+ str = "{ [a, b, c, d, e, f, g, h, i, j, k] : "
+ "3i >= 1073741823b - c - 1073741823e + f and c >= 0 and "
+ "3i >= -1 + 3221225466b + c + d - 3221225466e - f and "
+ "2e >= a - b and 3e <= 2a and 3k <= -a and f <= -1 + a and "
+ "3i <= 4 - a + 4b + 2c - e - 2f and 3k <= -a + c - f and "
+ "3h >= -2 + a and 3g >= -3 - a and 3k >= -2 - a and "
+ "3i >= -2 - a - 2c + 3e + 2f and 3h <= a + c - f and "
+ "3h >= a + 2147483646b + 2c - 2147483646e - 2f and "
+ "3g <= -1 - a and 3i <= 1 + c + d - f and a <= 1073741823 and "
+ "f >= 1 - a + 1073741822b + c + d - 1073741822e and "
+ "3i >= 1 + 2b - 2c + e + 2f + 3g and "
+ "1073741822f <= 1073741822 - a + 1073741821b + 1073741822c +"
+ "d - 1073741821e and "
+ "3j <= 3 - a + 3b and 3g <= -2 - 2b + c + d - e - f and "
+ "3j >= 1 - a + b + 2e and "
+ "3f >= -3 + a + 3221225462b + 3c + d - 3221225465e and "
+ "3i <= 4 - a + 4b - e and "
+ "f <= 1073741822 + 1073741822b - 1073741822e and 3h <= a and "
+ "f >= 0 and 2e <= 4 - a + 5b - d and 2e <= a - b + d and "
+ "c <= -1 + a and 3i >= -2 - a + 3e and "
+ "1073741822e <= 1073741823 - a + 1073741822b + c and "
+ "3g >= -4 + 3221225464b + 3c + d - 3221225467e - 3f and "
+ "3i >= -1 + 3221225466b + 3c + d - 3221225466e - 3f and "
+ "1073741823e >= 1 + 1073741823b - d and "
+ "3i >= 1073741823b + c - 1073741823e - f and "
+ "3i >= 1 + 2b + e + 3g }";
+ bset1 = isl_basic_set_read_from_str(ctx, str);
+ bset2 = isl_basic_set_sample(isl_basic_set_copy(bset1));
+ empty = isl_basic_set_is_empty(bset2);
+ subset = isl_basic_set_is_subset(bset2, bset1);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ if (empty < 0 || subset < 0)
+ return -1;
+ if (empty)
+ isl_die(ctx, isl_error_unknown, "point not found", return -1);
+ if (!subset)
+ isl_die(ctx, isl_error_unknown, "bad point found", return -1);
+
+ return 0;
+}
+
+int test_fixed_power(isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map;
+ isl_int exp;
+ int equal;
+
+ isl_int_init(exp);
+ str = "{ [i] -> [i + 1] }";
+ map = isl_map_read_from_str(ctx, str);
+ isl_int_set_si(exp, 23);
+ map = isl_map_fixed_power(map, exp);
+ equal = map_check_equal(map, "{ [i] -> [i + 23] }");
+ isl_int_clear(exp);
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ return 0;
+}
+
+int test_slice(isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map;
+ int equal;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_equate(map, isl_dim_in, 0, isl_dim_out, 0);
+ equal = map_check_equal(map, "{ [i] -> [i] }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_equate(map, isl_dim_in, 0, isl_dim_in, 0);
+ equal = map_check_equal(map, "{ [i] -> [j] }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_out, 0);
+ equal = map_check_equal(map, "{ [i] -> [-i] }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_oppose(map, isl_dim_in, 0, isl_dim_in, 0);
+ equal = map_check_equal(map, "{ [0] -> [j] }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_out, 0);
+ equal = map_check_equal(map, "{ [i] -> [j] : i > j }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ str = "{ [i] -> [j] }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_order_gt(map, isl_dim_in, 0, isl_dim_in, 0);
+ equal = map_check_equal(map, "{ [i] -> [j] : false }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ return 0;
+}
+
+int test_eliminate(isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map;
+ int equal;
+
+ str = "{ [i] -> [j] : i = 2j }";
+ map = isl_map_read_from_str(ctx, str);
+ map = isl_map_eliminate(map, isl_dim_out, 0, 1);
+ equal = map_check_equal(map, "{ [i] -> [j] : exists a : i = 2a }");
+ isl_map_free(map);
+ if (equal < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check that isl_set_dim_residue_class detects that the values of j
+ * in the set below are all odd and that it does not detect any spurious
+ * strides.
+ */
+static int test_residue_class(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_int m, r;
+ int res;
+
+ str = "{ [i,j] : j = 4 i + 1 and 0 <= i <= 100; "
+ "[i,j] : j = 4 i + 3 and 500 <= i <= 600 }";
+ set = isl_set_read_from_str(ctx, str);
+ isl_int_init(m);
+ isl_int_init(r);
+ res = isl_set_dim_residue_class(set, 1, &m, &r);
+ if (res >= 0 &&
+ (isl_int_cmp_si(m, 2) != 0 || isl_int_cmp_si(r, 1) != 0))
+ isl_die(ctx, isl_error_unknown, "incorrect residue class",
+ res = -1);
+ isl_int_clear(r);
+ isl_int_clear(m);
+ isl_set_free(set);
+
+ return res;
+}
+
+int test_align_parameters(isl_ctx *ctx)
+{
+ const char *str;
+ isl_space *space;
+ isl_multi_aff *ma1, *ma2;
+ int equal;
+
+ str = "{ A[B[] -> C[]] -> D[E[] -> F[]] }";
+ ma1 = isl_multi_aff_read_from_str(ctx, str);
+
+ space = isl_space_params_alloc(ctx, 1);
+ space = isl_space_set_dim_name(space, isl_dim_param, 0, "N");
+ ma1 = isl_multi_aff_align_params(ma1, space);
+
+ str = "[N] -> { A[B[] -> C[]] -> D[E[] -> F[]] }";
+ ma2 = isl_multi_aff_read_from_str(ctx, str);
+
+ equal = isl_multi_aff_plain_is_equal(ma1, ma2);
+
+ isl_multi_aff_free(ma1);
+ isl_multi_aff_free(ma2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "result not as expected", return -1);
+
+ return 0;
+}
+
+static int test_list(isl_ctx *ctx)
+{
+ isl_id *a, *b, *c, *d, *id;
+ isl_id_list *list;
+ int ok;
+
+ a = isl_id_alloc(ctx, "a", NULL);
+ b = isl_id_alloc(ctx, "b", NULL);
+ c = isl_id_alloc(ctx, "c", NULL);
+ d = isl_id_alloc(ctx, "d", NULL);
+
+ list = isl_id_list_alloc(ctx, 4);
+ list = isl_id_list_add(list, a);
+ list = isl_id_list_add(list, b);
+ list = isl_id_list_add(list, c);
+ list = isl_id_list_add(list, d);
+ list = isl_id_list_drop(list, 1, 1);
+
+ if (isl_id_list_n_id(list) != 3) {
+ isl_id_list_free(list);
+ isl_die(ctx, isl_error_unknown,
+ "unexpected number of elements in list", return -1);
+ }
+
+ id = isl_id_list_get_id(list, 0);
+ ok = id == a;
+ isl_id_free(id);
+ id = isl_id_list_get_id(list, 1);
+ ok = ok && id == c;
+ isl_id_free(id);
+ id = isl_id_list_get_id(list, 2);
+ ok = ok && id == d;
+ isl_id_free(id);
+
+ isl_id_list_free(list);
+
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected elements in list", return -1);
+
+ return 0;
+}
+
+const char *set_conversion_tests[] = {
+ "[N] -> { [i] : N - 1 <= 2 i <= N }",
+ "[N] -> { [i] : exists a : i = 4 a and N - 1 <= i <= N }",
+ "[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)] }",
+};
+
+/* Check that converting from isl_set to isl_pw_multi_aff and back
+ * to isl_set produces the original isl_set.
+ */
+static int test_set_conversion(isl_ctx *ctx)
+{
+ int i;
+ const char *str;
+ isl_set *set1, *set2;
+ isl_pw_multi_aff *pma;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(set_conversion_tests); ++i) {
+ str = set_conversion_tests[i];
+ set1 = isl_set_read_from_str(ctx, str);
+ pma = isl_pw_multi_aff_from_set(isl_set_copy(set1));
+ set2 = isl_set_from_pw_multi_aff(pma);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad conversion",
+ return -1);
+ }
+
+ return 0;
+}
+
+/* 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;
+ 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);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad conversion", return -1);
+
+ return 0;
+}
+
+static int test_conversion(isl_ctx *ctx)
+{
+ if (test_set_conversion(ctx) < 0)
+ return -1;
+ if (test_map_conversion(ctx) < 0)
+ return -1;
+ return 0;
+}
+
+/* Check that isl_basic_map_curry does not modify input.
+ */
+static int test_curry(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_map *bmap1, *bmap2;
+ int equal;
+
+ str = "{ [A[] -> B[]] -> C[] }";
+ bmap1 = isl_basic_map_read_from_str(ctx, str);
+ bmap2 = isl_basic_map_curry(isl_basic_map_copy(bmap1));
+ equal = isl_basic_map_is_equal(bmap1, bmap2);
+ isl_basic_map_free(bmap1);
+ isl_basic_map_free(bmap2);
+
+ if (equal < 0)
+ return -1;
+ if (equal)
+ isl_die(ctx, isl_error_unknown,
+ "curried map should not be equal to original",
+ return -1);
+
+ return 0;
+}
+
+struct {
+ const char *set;
+ const char *ma;
+ const char *res;
+} preimage_tests[] = {
+ { "{ B[i,j] : 0 <= i < 10 and 0 <= j < 100 }",
+ "{ A[j,i] -> B[i,j] }",
+ "{ A[j,i] : 0 <= i < 10 and 0 <= j < 100 }" },
+ { "{ rat: B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
+ "{ A[a,b] -> B[a/2,b/6] }",
+ "{ rat: A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 }" },
+ { "{ B[i,j] : 0 <= i, j and 3 i + 5 j <= 100 }",
+ "{ A[a,b] -> B[a/2,b/6] }",
+ "{ A[a,b] : 0 <= a, b and 9 a + 5 b <= 600 and "
+ "exists i,j : a = 2 i and b = 6 j }" },
+ { "[n] -> { S[i] : 0 <= i <= 100 }", "[n] -> { S[n] }",
+ "[n] -> { : 0 <= n <= 100 }" },
+ { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
+ "{ A[a] -> B[2a] }",
+ "{ A[a] : 0 <= a < 50 and exists b : a = 2 b }" },
+ { "{ B[i] : 0 <= i < 100 and exists a : i = 4 a }",
+ "{ A[a] -> B[([a/2])] }",
+ "{ A[a] : 0 <= a < 200 and exists b : [a/2] = 4 b }" },
+ { "{ B[i,j,k] : 0 <= i,j,k <= 100 }",
+ "{ A[a] -> B[a,a,a/3] }",
+ "{ A[a] : 0 <= a <= 100 and exists b : a = 3 b }" },
+ { "{ B[i,j] : j = [(i)/2] } ", "{ A[i,j] -> B[i/3,j] }",
+ "{ A[i,j] : j = [(i)/6] and exists a : i = 3 a }" },
+};
+
+static int test_preimage_basic_set(isl_ctx *ctx)
+{
+ int i;
+ isl_basic_set *bset1, *bset2;
+ isl_multi_aff *ma;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(preimage_tests); ++i) {
+ bset1 = isl_basic_set_read_from_str(ctx, preimage_tests[i].set);
+ ma = isl_multi_aff_read_from_str(ctx, preimage_tests[i].ma);
+ bset2 = isl_basic_set_read_from_str(ctx, preimage_tests[i].res);
+ bset1 = isl_basic_set_preimage_multi_aff(bset1, ma);
+ equal = isl_basic_set_is_equal(bset1, bset2);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad preimage",
+ return -1);
+ }
+
+ return 0;
+}
+
+struct {
+ const char *map;
+ const char *ma;
+ const char *res;
+} preimage_domain_tests[] = {
+ { "{ B[i,j] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }",
+ "{ A[j,i] -> B[i,j] }",
+ "{ A[j,i] -> C[2i + 3j] : 0 <= i < 10 and 0 <= j < 100 }" },
+ { "{ B[i] -> C[i]; D[i] -> E[i] }",
+ "{ A[i] -> B[i + 1] }",
+ "{ A[i] -> C[i + 1] }" },
+ { "{ B[i] -> C[i]; B[i] -> E[i] }",
+ "{ A[i] -> B[i + 1] }",
+ "{ A[i] -> C[i + 1]; A[i] -> E[i + 1] }" },
+ { "{ B[i] -> C[([i/2])] }",
+ "{ A[i] -> B[2i] }",
+ "{ A[i] -> C[i] }" },
+ { "{ B[i,j] -> C[([i/2]), ([(i+j)/3])] }",
+ "{ A[i] -> B[([i/5]), ([i/7])] }",
+ "{ A[i] -> C[([([i/5])/2]), ([(([i/5])+([i/7]))/3])] }" },
+ { "[N] -> { B[i] -> C[([N/2]), i, ([N/3])] }",
+ "[N] -> { A[] -> B[([N/5])] }",
+ "[N] -> { A[] -> C[([N/2]), ([N/5]), ([N/3])] }" },
+ { "{ B[i] -> C[i] : exists a : i = 5 a }",
+ "{ A[i] -> B[2i] }",
+ "{ A[i] -> C[2i] : exists a : 2i = 5 a }" },
+ { "{ B[i] -> C[i] : exists a : i = 2 a; "
+ "B[i] -> D[i] : exists a : i = 2 a + 1 }",
+ "{ A[i] -> B[2i] }",
+ "{ A[i] -> C[2i] }" },
+};
+
+static int test_preimage_union_map(isl_ctx *ctx)
+{
+ int i;
+ isl_union_map *umap1, *umap2;
+ isl_multi_aff *ma;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(preimage_domain_tests); ++i) {
+ umap1 = isl_union_map_read_from_str(ctx,
+ preimage_domain_tests[i].map);
+ ma = isl_multi_aff_read_from_str(ctx,
+ preimage_domain_tests[i].ma);
+ umap2 = isl_union_map_read_from_str(ctx,
+ preimage_domain_tests[i].res);
+ umap1 = isl_union_map_preimage_domain_multi_aff(umap1, ma);
+ equal = isl_union_map_is_equal(umap1, umap2);
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad preimage",
+ return -1);
+ }
+
+ return 0;
+}
+
+static int test_preimage(isl_ctx *ctx)
+{
+ if (test_preimage_basic_set(ctx) < 0)
+ return -1;
+ if (test_preimage_union_map(ctx) < 0)
+ return -1;
+
+ return 0;
+}
+
+struct {
+ const char *ma1;
+ const char *ma;
+ const char *res;
+} pullback_tests[] = {
+ { "{ B[i,j] -> C[i + 2j] }" , "{ A[a,b] -> B[b,a] }",
+ "{ A[a,b] -> C[b + 2a] }" },
+ { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/2] }", "{ A[a] -> C[a] }" },
+ { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[2a] }", "{ A[a] -> C[a] }" },
+ { "{ B[i] -> C[(i)/2] }", "{ A[a] -> B[(a)/3] }",
+ "{ A[a] -> C[(a)/6] }" },
+ { "{ B[i] -> C[2i] }", "{ A[a] -> B[5a] }", "{ A[a] -> C[10a] }" },
+ { "{ B[i] -> C[2i] }", "{ A[a] -> B[(a)/3] }",
+ "{ A[a] -> C[(2a)/3] }" },
+ { "{ B[i,j] -> C[i + j] }", "{ A[a] -> B[a,a] }", "{ A[a] -> C[2a] }"},
+ { "{ B[a] -> C[a,a] }", "{ A[i,j] -> B[i + j] }",
+ "{ A[i,j] -> C[i + j, i + j] }"},
+ { "{ B[i] -> C[([i/2])] }", "{ B[5] }", "{ C[2] }" },
+ { "[n] -> { B[i,j] -> C[([i/2]) + 2j] }",
+ "[n] -> { B[n,[n/3]] }", "[n] -> { C[([n/2]) + 2*[n/3]] }", },
+};
+
+static int test_pullback(isl_ctx *ctx)
+{
+ int i;
+ isl_multi_aff *ma1, *ma2;
+ isl_multi_aff *ma;
+ int equal;
+
+ for (i = 0; i < ARRAY_SIZE(pullback_tests); ++i) {
+ ma1 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma1);
+ ma = isl_multi_aff_read_from_str(ctx, pullback_tests[i].ma);
+ ma2 = isl_multi_aff_read_from_str(ctx, pullback_tests[i].res);
+ ma1 = isl_multi_aff_pullback_multi_aff(ma1, ma);
+ equal = isl_multi_aff_plain_is_equal(ma1, ma2);
+ isl_multi_aff_free(ma1);
+ isl_multi_aff_free(ma2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown, "bad pullback",
+ return -1);
+ }
+
+ return 0;
+}
+
+/* Check that negation is printed correctly.
+ */
+static int test_ast(isl_ctx *ctx)
+{
+ isl_ast_expr *expr, *expr1, *expr2, *expr3;
+ char *str;
+ int ok;
+
+ expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+ expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+ expr = isl_ast_expr_add(expr1, expr2);
+ expr = isl_ast_expr_neg(expr);
+ str = isl_ast_expr_to_str(expr);
+ ok = str ? !strcmp(str, "-(A + B)") : -1;
+ free(str);
+ isl_ast_expr_free(expr);
+
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "isl_ast_expr printed incorrectly", return -1);
+
+ expr1 = isl_ast_expr_from_id(isl_id_alloc(ctx, "A", NULL));
+ expr2 = isl_ast_expr_from_id(isl_id_alloc(ctx, "B", NULL));
+ expr = isl_ast_expr_add(expr1, expr2);
+ expr3 = isl_ast_expr_from_id(isl_id_alloc(ctx, "C", NULL));
+ expr = isl_ast_expr_sub(expr3, expr);
+ str = isl_ast_expr_to_str(expr);
+ ok = str ? !strcmp(str, "C - (A + B)") : -1;
+ free(str);
+ isl_ast_expr_free(expr);
+
+ if (ok < 0)
+ return -1;
+ if (!ok)
+ isl_die(ctx, isl_error_unknown,
+ "isl_ast_expr printed incorrectly", return -1);
+
+ return 0;
+}
+
+/* Check that isl_ast_build_expr_from_set returns a valid expression
+ * for an empty set. Note that isl_ast_build_expr_from_set getting
+ * called on an empty set probably indicates a bug in the caller.
+ */
+static int test_ast_build(isl_ctx *ctx)
+{
+ isl_set *set;
+ isl_ast_build *build;
+ isl_ast_expr *expr;
+
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+ build = isl_ast_build_from_context(set);
+
+ set = isl_set_empty(isl_space_params_alloc(ctx, 0));
+ expr = isl_ast_build_expr_from_set(build, set);
+
+ isl_ast_expr_free(expr);
+ isl_ast_build_free(build);
+
+ if (!expr)
+ return -1;
+
+ return 0;
+}
+
+/* Internal data structure for before_for and after_for callbacks.
+ *
+ * depth is the current depth
+ * before is the number of times before_for has been called
+ * after is the number of times after_for has been called
+ */
+struct isl_test_codegen_data {
+ int depth;
+ int before;
+ int after;
+};
+
+/* This function is called before each for loop in the AST generated
+ * from test_ast_gen1.
+ *
+ * Increment the number of calls and the depth.
+ * Check that the space returned by isl_ast_build_get_schedule_space
+ * matches the target space of the schedule returned by
+ * isl_ast_build_get_schedule.
+ * Return an isl_id that is checked by the corresponding call
+ * to after_for.
+ */
+static __isl_give isl_id *before_for(__isl_keep isl_ast_build *build,
+ void *user)
+{
+ struct isl_test_codegen_data *data = user;
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_union_map *schedule;
+ isl_union_set *uset;
+ isl_set *set;
+ int empty;
+ char name[] = "d0";
+
+ ctx = isl_ast_build_get_ctx(build);
+
+ if (data->before >= 3)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected number of for nodes", return NULL);
+ if (data->depth >= 2)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected depth", return NULL);
+
+ snprintf(name, sizeof(name), "d%d", data->depth);
+ data->before++;
+ data->depth++;
+
+ schedule = isl_ast_build_get_schedule(build);
+ uset = isl_union_map_range(schedule);
+ if (!uset)
+ return NULL;
+ if (isl_union_set_n_set(uset) != 1) {
+ isl_union_set_free(uset);
+ isl_die(ctx, isl_error_unknown,
+ "expecting single range space", return NULL);
+ }
+
+ space = isl_ast_build_get_schedule_space(build);
+ set = isl_union_set_extract_set(uset, space);
+ isl_union_set_free(uset);
+ empty = isl_set_is_empty(set);
+ isl_set_free(set);
+
+ if (empty < 0)
+ return NULL;
+ if (empty)
+ isl_die(ctx, isl_error_unknown,
+ "spaces don't match", return NULL);
+
+ return isl_id_alloc(ctx, name, NULL);
+}
+
+/* This function is called after each for loop in the AST generated
+ * from test_ast_gen1.
+ *
+ * Increment the number of calls and decrement the depth.
+ * Check that the annotation attached to the node matches
+ * the isl_id returned by the corresponding call to before_for.
+ */
+static __isl_give isl_ast_node *after_for(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user)
+{
+ struct isl_test_codegen_data *data = user;
+ isl_id *id;
+ const char *name;
+ int valid;
+
+ data->after++;
+ data->depth--;
+
+ if (data->after > data->before)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+ "mismatch in number of for nodes",
+ return isl_ast_node_free(node));
+
+ id = isl_ast_node_get_annotation(node);
+ if (!id)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+ "missing annotation", return isl_ast_node_free(node));
+
+ name = isl_id_get_name(id);
+ valid = name && atoi(name + 1) == data->depth;
+ isl_id_free(id);
+
+ if (!valid)
+ isl_die(isl_ast_node_get_ctx(node), isl_error_unknown,
+ "wrong annotation", return isl_ast_node_free(node));
+
+ return node;
+}
+
+/* Check that the before_each_for and after_each_for callbacks
+ * are called for each for loop in the generated code,
+ * that they are called in the right order and that the isl_id
+ * returned from the before_each_for callback is attached to
+ * the isl_ast_node passed to the corresponding after_each_for call.
+ */
+static int test_ast_gen1(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_map *schedule;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+ struct isl_test_codegen_data data;
+
+ str = "[N] -> { : N >= 10 }";
+ set = isl_set_read_from_str(ctx, str);
+ str = "[N] -> { A[i,j] -> S[8,i,3,j] : 0 <= i,j <= N; "
+ "B[i,j] -> S[8,j,9,i] : 0 <= i,j <= N }";
+ schedule = isl_union_map_read_from_str(ctx, str);
+
+ data.before = 0;
+ data.after = 0;
+ data.depth = 0;
+ build = isl_ast_build_from_context(set);
+ build = isl_ast_build_set_before_each_for(build,
+ &before_for, &data);
+ build = isl_ast_build_set_after_each_for(build,
+ &after_for, &data);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ if (!tree)
+ return -1;
+
+ isl_ast_node_free(tree);
+
+ if (data.before != 3 || data.after != 3)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected number of for nodes", return -1);
+
+ return 0;
+}
+
+/* Check that the AST generator handles domains that are integrally disjoint
+ * but not ratinoally disjoint.
+ */
+static int test_ast_gen2(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_map *schedule;
+ isl_union_map *options;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+
+ str = "{ A[i,j] -> [i,j] : 0 <= i,j <= 1 }";
+ schedule = isl_union_map_read_from_str(ctx, str);
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+ build = isl_ast_build_from_context(set);
+
+ str = "{ [i,j] -> atomic[1] : i + j = 1; [i,j] -> unroll[1] : i = j }";
+ options = isl_union_map_read_from_str(ctx, str);
+ build = isl_ast_build_set_options(build, options);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ if (!tree)
+ return -1;
+ isl_ast_node_free(tree);
+
+ return 0;
+}
+
+/* Increment *user on each call.
+ */
+static __isl_give isl_ast_node *count_domains(__isl_take isl_ast_node *node,
+ __isl_keep isl_ast_build *build, void *user)
+{
+ int *n = user;
+
+ (*n)++;
+
+ return node;
+}
+
+/* Test that unrolling tries to minimize the number of instances.
+ * In particular, for the schedule given below, make sure it generates
+ * 3 nodes (rather than 101).
+ */
+static int test_ast_gen3(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_map *schedule;
+ isl_union_map *options;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+ int n_domain = 0;
+
+ str = "[n] -> { A[i] -> [i] : 0 <= i <= 100 and n <= i <= n + 2 }";
+ schedule = isl_union_map_read_from_str(ctx, str);
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+
+ str = "{ [i] -> unroll[0] }";
+ options = isl_union_map_read_from_str(ctx, str);
+
+ build = isl_ast_build_from_context(set);
+ build = isl_ast_build_set_options(build, options);
+ build = isl_ast_build_set_at_each_domain(build,
+ &count_domains, &n_domain);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ if (!tree)
+ return -1;
+
+ isl_ast_node_free(tree);
+
+ if (n_domain != 3)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected number of for nodes", return -1);
+
+ return 0;
+}
+
+/* Check that if the ast_build_exploit_nested_bounds options is set,
+ * we do not get an outer if node in the generated AST,
+ * while we do get such an outer if node if the options is not set.
+ */
+static int test_ast_gen4(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_map *schedule;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+ enum isl_ast_node_type type;
+ int enb;
+
+ enb = isl_options_get_ast_build_exploit_nested_bounds(ctx);
+ str = "[N,M] -> { A[i,j] -> [i,j] : 0 <= i <= N and 0 <= j <= M }";
+
+ isl_options_set_ast_build_exploit_nested_bounds(ctx, 1);
+
+ schedule = isl_union_map_read_from_str(ctx, str);
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+ build = isl_ast_build_from_context(set);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ if (!tree)
+ return -1;
+
+ type = isl_ast_node_get_type(tree);
+ isl_ast_node_free(tree);
+
+ if (type == isl_ast_node_if)
+ isl_die(ctx, isl_error_unknown,
+ "not expecting if node", return -1);
+
+ isl_options_set_ast_build_exploit_nested_bounds(ctx, 0);
+
+ schedule = isl_union_map_read_from_str(ctx, str);
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+ build = isl_ast_build_from_context(set);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ if (!tree)
+ return -1;
+
+ type = isl_ast_node_get_type(tree);
+ isl_ast_node_free(tree);
+
+ if (type != isl_ast_node_if)
+ isl_die(ctx, isl_error_unknown,
+ "expecting if node", return -1);
+
+ isl_options_set_ast_build_exploit_nested_bounds(ctx, enb);
+
+ return 0;
+}
+
+/* This function is called for each leaf in the AST generated
+ * from test_ast_gen5.
+ *
+ * We finalize the AST generation by extending the outer schedule
+ * with a zero-dimensional schedule. If this results in any for loops,
+ * then this means that we did not pass along enough information
+ * about the outer schedule to the inner AST generation.
+ */
+static __isl_give isl_ast_node *create_leaf(__isl_take isl_ast_build *build,
+ void *user)
+{
+ isl_union_map *schedule, *extra;
+ isl_ast_node *tree;
+
+ schedule = isl_ast_build_get_schedule(build);
+ extra = isl_union_map_copy(schedule);
+ extra = isl_union_map_from_domain(isl_union_map_domain(extra));
+ schedule = isl_union_map_range_product(schedule, extra);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+
+ if (!tree)
+ return NULL;
+
+ if (isl_ast_node_get_type(tree) == isl_ast_node_for)
+ isl_die(isl_ast_node_get_ctx(tree), isl_error_unknown,
+ "code should not contain any for loop",
+ return isl_ast_node_free(tree));
+
+ return tree;
+}
+
+/* Check that we do not lose any information when going back and
+ * forth between internal and external schedule.
+ *
+ * In particular, we create an AST where we unroll the only
+ * non-constant dimension in the schedule. We therefore do
+ * not expect any for loops in the AST. However, older versions
+ * of isl would not pass along enough information about the outer
+ * schedule when performing an inner code generation from a create_leaf
+ * callback, resulting in the inner code generation producing a for loop.
+ */
+static int test_ast_gen5(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *set;
+ isl_union_map *schedule, *options;
+ isl_ast_build *build;
+ isl_ast_node *tree;
+
+ str = "{ A[] -> [1, 1, 2]; B[i] -> [1, i, 0] : i >= 1 and i <= 2 }";
+ schedule = isl_union_map_read_from_str(ctx, str);
+
+ str = "{ [a, b, c] -> unroll[1] : exists (e0 = [(a)/4]: "
+ "4e0 >= -1 + a - b and 4e0 <= -2 + a + b) }";
+ options = isl_union_map_read_from_str(ctx, str);
+
+ set = isl_set_universe(isl_space_params_alloc(ctx, 0));
+ build = isl_ast_build_from_context(set);
+ build = isl_ast_build_set_options(build, options);
+ build = isl_ast_build_set_create_leaf(build, &create_leaf, NULL);
+ tree = isl_ast_build_ast_from_schedule(build, schedule);
+ isl_ast_build_free(build);
+ isl_ast_node_free(tree);
+ if (!tree)
+ return -1;
+
+ return 0;
+}
+
+static int test_ast_gen(isl_ctx *ctx)
+{
+ if (test_ast_gen1(ctx) < 0)
+ return -1;
+ if (test_ast_gen2(ctx) < 0)
+ return -1;
+ if (test_ast_gen3(ctx) < 0)
+ return -1;
+ if (test_ast_gen4(ctx) < 0)
+ return -1;
+ if (test_ast_gen5(ctx) < 0)
+ return -1;
+ return 0;
+}
+
+/* Check if dropping output dimensions from an isl_pw_multi_aff
+ * works properly.
+ */
+static int test_pw_multi_aff(isl_ctx *ctx)
+{
+ const char *str;
+ isl_pw_multi_aff *pma1, *pma2;
+ int equal;
+
+ str = "{ [i,j] -> [i+j, 4i-j] }";
+ pma1 = isl_pw_multi_aff_read_from_str(ctx, str);
+ str = "{ [i,j] -> [4i-j] }";
+ pma2 = isl_pw_multi_aff_read_from_str(ctx, str);
+
+ pma1 = isl_pw_multi_aff_drop_dims(pma1, isl_dim_out, 0, 1);
+
+ equal = isl_pw_multi_aff_plain_is_equal(pma1, pma2);
+
+ isl_pw_multi_aff_free(pma1);
+ isl_pw_multi_aff_free(pma2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "expressions not equal", return -1);
+
+ return 0;
+}
+
+/* Check that we can properly parse multi piecewise affine expressions
+ * where the piecewise affine expressions have different domains.
+ */
+static int test_multi_pw_aff(isl_ctx *ctx)
+{
+ const char *str;
+ isl_set *dom, *dom2;
+ isl_multi_pw_aff *mpa1, *mpa2;
+ isl_pw_aff *pa;
+ int equal;
+ int equal_domain;
+
+ mpa1 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [i] }");
+ dom = isl_set_read_from_str(ctx, "{ [i] : i > 0 }");
+ mpa1 = isl_multi_pw_aff_intersect_domain(mpa1, dom);
+ mpa2 = isl_multi_pw_aff_read_from_str(ctx, "{ [i] -> [2i] }");
+ mpa2 = isl_multi_pw_aff_flat_range_product(mpa1, mpa2);
+ str = "{ [i] -> [(i : i > 0), 2i] }";
+ mpa1 = isl_multi_pw_aff_read_from_str(ctx, str);
+
+ equal = isl_multi_pw_aff_plain_is_equal(mpa1, mpa2);
+
+ pa = isl_multi_pw_aff_get_pw_aff(mpa1, 0);
+ dom = isl_pw_aff_domain(pa);
+ pa = isl_multi_pw_aff_get_pw_aff(mpa1, 1);
+ dom2 = isl_pw_aff_domain(pa);
+ equal_domain = isl_set_is_equal(dom, dom2);
+
+ isl_set_free(dom);
+ isl_set_free(dom2);
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa2);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "expressions not equal", return -1);
+
+ if (equal_domain < 0)
+ return -1;
+ if (equal_domain)
+ isl_die(ctx, isl_error_unknown,
+ "domains unexpectedly equal", return -1);
+
+ return 0;
+}
+
+/* This is a regression test for a bug where isl_basic_map_simplify
+ * would end up in an infinite loop. In particular, we construct
+ * an empty basic set that is not obviously empty.
+ * isl_basic_set_is_empty marks the basic set as empty.
+ * After projecting out i3, the variable can be dropped completely,
+ * but isl_basic_map_simplify refrains from doing so if the basic set
+ * is empty and would end up in an infinite loop if it didn't test
+ * explicitly for empty basic maps in the outer loop.
+ */
+static int test_simplify(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_set *bset;
+ int empty;
+
+ str = "{ [i0, i1, i2, i3] : i0 >= -2 and 6i2 <= 4 + i0 + 5i1 and "
+ "i2 <= 22 and 75i2 <= 111 + 13i0 + 60i1 and "
+ "25i2 >= 38 + 6i0 + 20i1 and i0 <= -1 and i2 >= 20 and "
+ "i3 >= i2 }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ empty = isl_basic_set_is_empty(bset);
+ bset = isl_basic_set_project_out(bset, isl_dim_set, 3, 1);
+ isl_basic_set_free(bset);
+ if (!bset)
+ return -1;
+ if (!empty)
+ isl_die(ctx, isl_error_unknown,
+ "basic set should be empty", return -1);
+
+ return 0;
+}
+
+/* This is a regression test for a bug where isl_tab_basic_map_partial_lexopt
+ * with gbr context would fail to disable the use of the shifted tableau
+ * when transferring equalities for the input to the context, resulting
+ * in invalid sample values.
+ */
+static int test_partial_lexmin(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_set *bset;
+ isl_basic_map *bmap;
+ isl_map *map;
+
+ str = "{ [1, b, c, 1 - c] -> [e] : 2e <= -c and 2e >= -3 + c }";
+ bmap = isl_basic_map_read_from_str(ctx, str);
+ str = "{ [a, b, c, d] : c <= 1 and 2d >= 6 - 4b - c }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ map = isl_basic_map_partial_lexmin(bmap, bset, NULL);
+ isl_map_free(map);
+
+ if (!map)
+ return -1;
+
+ return 0;
+}
+
+/* Check that the variable compression performed on the existentially
+ * quantified variables inside isl_basic_set_compute_divs is not confused
+ * by the implicit equalities among the parameters.
+ */
+static int test_compute_divs(isl_ctx *ctx)
+{
+ const char *str;
+ isl_basic_set *bset;
+ isl_set *set;
+
+ str = "[a, b, c, d, e] -> { [] : exists (e0: 2d = b and a <= 124 and "
+ "b <= 2046 and b >= 0 and b <= 60 + 64a and 2e >= b + 2c and "
+ "2e >= b and 2e <= 1 + b and 2e <= 1 + b + 2c and "
+ "32768e0 >= -124 + a and 2097152e0 <= 60 + 64a - b) }";
+ bset = isl_basic_set_read_from_str(ctx, str);
+ set = isl_basic_set_compute_divs(bset);
+ isl_set_free(set);
+ if (!set)
+ return -1;
+
+ return 0;
+}
+
+struct {
+ const char *set;
+ const char *dual;
+} coef_tests[] = {
+ { "{ rat: [i] : 0 <= i <= 10 }",
+ "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }" },
+ { "{ rat: [i] : FALSE }",
+ "{ rat: coefficients[[cst] -> [a]] }" },
+ { "{ rat: [i] : }",
+ "{ rat: coefficients[[cst] -> [0]] : cst >= 0 }" },
+};
+
+struct {
+ const char *set;
+ const char *dual;
+} sol_tests[] = {
+ { "{ rat: coefficients[[cst] -> [a]] : cst >= 0 and 10a + cst >= 0 }",
+ "{ rat: [i] : 0 <= i <= 10 }" },
+ { "{ rat: coefficients[[cst] -> [a]] : FALSE }",
+ "{ rat: [i] }" },
+ { "{ rat: coefficients[[cst] -> [a]] }",
+ "{ rat: [i] : FALSE }" },
+};
+
+/* Test the basic functionality of isl_basic_set_coefficients and
+ * isl_basic_set_solutions.
+ */
+static int test_dual(isl_ctx *ctx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coef_tests); ++i) {
+ int equal;
+ isl_basic_set *bset1, *bset2;
+
+ bset1 = isl_basic_set_read_from_str(ctx, coef_tests[i].set);
+ bset2 = isl_basic_set_read_from_str(ctx, coef_tests[i].dual);
+ bset1 = isl_basic_set_coefficients(bset1);
+ equal = isl_basic_set_is_equal(bset1, bset2);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect dual", return -1);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sol_tests); ++i) {
+ int equal;
+ isl_basic_set *bset1, *bset2;
+
+ bset1 = isl_basic_set_read_from_str(ctx, sol_tests[i].set);
+ bset2 = isl_basic_set_read_from_str(ctx, sol_tests[i].dual);
+ bset1 = isl_basic_set_solutions(bset1);
+ equal = isl_basic_set_is_equal(bset1, bset2);
+ isl_basic_set_free(bset1);
+ isl_basic_set_free(bset2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect dual", return -1);
+ }
+
+ return 0;
+}
+
+struct {
+ const char *name;
+ int (*fn)(isl_ctx *ctx);
+} tests [] = {
+ { "dual", &test_dual },
+ { "dependence analysis", &test_flow },
+ { "val", &test_val },
+ { "compute divs", &test_compute_divs },
+ { "partial lexmin", &test_partial_lexmin },
+ { "simplify", &test_simplify },
+ { "curry", &test_curry },
+ { "piecewise multi affine expressions", &test_pw_multi_aff },
+ { "multi piecewise affine expressions", &test_multi_pw_aff },
+ { "conversion", &test_conversion },
+ { "list", &test_list },
+ { "align parameters", &test_align_parameters },
+ { "preimage", &test_preimage },
+ { "pullback", &test_pullback },
+ { "AST", &test_ast },
+ { "AST build", &test_ast_build },
+ { "AST generation", &test_ast_gen },
+ { "eliminate", &test_eliminate },
+ { "residue class", &test_residue_class },
+ { "div", &test_div },
+ { "slice", &test_slice },
+ { "fixed power", &test_fixed_power },
+ { "sample", &test_sample },
+ { "output", &test_output },
+ { "vertices", &test_vertices },
+ { "fixed", &test_fixed },
+ { "equal", &test_equal },
+ { "disjoint", &test_disjoint },
+ { "product", &test_product },
+ { "dim_max", &test_dim_max },
+ { "affine", &test_aff },
+ { "injective", &test_injective },
+ { "schedule", &test_schedule },
+ { "union_pw", &test_union_pw },
+ { "parse", &test_parse },
+ { "single-valued", &test_sv },
+ { "affine hull", &test_affine_hull },
+ { "coalesce", &test_coalesce },
+ { "factorize", &test_factorize },
+ { "subset", &test_subset },
+ { "subtract", &test_subtract },
+ { "lexmin", &test_lexmin },
+ { "min", &test_min },
+ { "gist", &test_gist },
+ { "piecewise quasi-polynomials", &test_pwqp },
+};
+
+int main(int argc, char **argv)
+{
+ int i;
+ struct isl_ctx *ctx;
+ struct isl_options *options;
+
+ srcdir = getenv("srcdir");
+ assert(srcdir);
+
+ options = isl_options_new_with_defaults();
+ assert(options);
+ argc = isl_options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
+ for (i = 0; i < ARRAY_SIZE(tests); ++i) {
+ printf("%s\n", tests[i].name);
+ if (tests[i].fn(ctx) < 0)
+ goto error;
+ }
+ test_lift(ctx);
+ test_bound(ctx);
+ test_union(ctx);
+ test_split_periods(ctx);
+ test_lex(ctx);
+ test_bijective(ctx);
+ test_dep(ctx);
+ test_read(ctx);
+ test_bounded(ctx);
+ test_construction(ctx);
+ test_dim(ctx);
+ test_application(ctx);
+ test_convex_hull(ctx);
+ test_closure(ctx);
+ isl_ctx_free(ctx);
+ return 0;
+error:
+ isl_ctx_free(ctx);
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_transitive_closure.c b/polly/lib/External/isl/isl_transitive_closure.c
new file mode 100644
index 00000000000..d91a58f3787
--- /dev/null
+++ b/polly/lib/External/isl/isl_transitive_closure.c
@@ -0,0 +1,2981 @@
+/*
+ * 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_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/map.h>
+#include <isl_seq.h>
+#include <isl_space_private.h>
+#include <isl_lp_private.h>
+#include <isl/union_map.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+#include <isl_options_private.h>
+#include <isl_tarjan.h>
+
+int isl_map_is_transitively_closed(__isl_keep isl_map *map)
+{
+ isl_map *map2;
+ int closed;
+
+ map2 = isl_map_apply_range(isl_map_copy(map), isl_map_copy(map));
+ closed = isl_map_is_subset(map2, map);
+ isl_map_free(map2);
+
+ return closed;
+}
+
+int isl_union_map_is_transitively_closed(__isl_keep isl_union_map *umap)
+{
+ isl_union_map *umap2;
+ int closed;
+
+ umap2 = isl_union_map_apply_range(isl_union_map_copy(umap),
+ isl_union_map_copy(umap));
+ closed = isl_union_map_is_subset(umap2, umap);
+ isl_union_map_free(umap2);
+
+ return closed;
+}
+
+/* Given a map that represents a path with the length of the path
+ * encoded as the difference between the last output coordindate
+ * and the last input coordinate, set this length to either
+ * exactly "length" (if "exactly" is set) or at least "length"
+ * (if "exactly" is not set).
+ */
+static __isl_give isl_map *set_path_length(__isl_take isl_map *map,
+ int exactly, int length)
+{
+ isl_space *dim;
+ struct isl_basic_map *bmap;
+ unsigned d;
+ unsigned nparam;
+ int k;
+ isl_int *c;
+
+ if (!map)
+ return NULL;
+
+ dim = isl_map_get_space(map);
+ d = isl_space_dim(dim, isl_dim_in);
+ nparam = isl_space_dim(dim, isl_dim_param);
+ bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+ if (exactly) {
+ k = isl_basic_map_alloc_equality(bmap);
+ c = bmap->eq[k];
+ } else {
+ k = isl_basic_map_alloc_inequality(bmap);
+ c = bmap->ineq[k];
+ }
+ if (k < 0)
+ goto error;
+ isl_seq_clr(c, 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(c[0], -length);
+ isl_int_set_si(c[1 + nparam + d - 1], -1);
+ isl_int_set_si(c[1 + nparam + d + d - 1], 1);
+
+ bmap = isl_basic_map_finalize(bmap);
+ map = isl_map_intersect(map, isl_map_from_basic_map(bmap));
+
+ return map;
+error:
+ isl_basic_map_free(bmap);
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Check whether the overapproximation of the power of "map" is exactly
+ * the power of "map". Let R be "map" and A_k the overapproximation.
+ * The approximation is exact if
+ *
+ * A_1 = R
+ * A_k = A_{k-1} \circ R k >= 2
+ *
+ * Since A_k is known to be an overapproximation, we only need to check
+ *
+ * A_1 \subset R
+ * A_k \subset A_{k-1} \circ R k >= 2
+ *
+ * In practice, "app" has an extra input and output coordinate
+ * to encode the length of the path. So, we first need to add
+ * this coordinate to "map" and set the length of the path to
+ * one.
+ */
+static int check_power_exactness(__isl_take isl_map *map,
+ __isl_take isl_map *app)
+{
+ int exact;
+ isl_map *app_1;
+ isl_map *app_2;
+
+ map = isl_map_add_dims(map, isl_dim_in, 1);
+ map = isl_map_add_dims(map, isl_dim_out, 1);
+ map = set_path_length(map, 1, 1);
+
+ app_1 = set_path_length(isl_map_copy(app), 1, 1);
+
+ exact = isl_map_is_subset(app_1, map);
+ isl_map_free(app_1);
+
+ if (!exact || exact < 0) {
+ isl_map_free(app);
+ isl_map_free(map);
+ return exact;
+ }
+
+ app_1 = set_path_length(isl_map_copy(app), 0, 1);
+ app_2 = set_path_length(app, 0, 2);
+ app_1 = isl_map_apply_range(map, app_1);
+
+ exact = isl_map_is_subset(app_2, app_1);
+
+ isl_map_free(app_1);
+ isl_map_free(app_2);
+
+ return exact;
+}
+
+/* Check whether the overapproximation of the power of "map" is exactly
+ * the power of "map", possibly after projecting out the power (if "project"
+ * is set).
+ *
+ * If "project" is set and if "steps" can only result in acyclic paths,
+ * then we check
+ *
+ * A = R \cup (A \circ R)
+ *
+ * where A is the overapproximation with the power projected out, i.e.,
+ * an overapproximation of the transitive closure.
+ * More specifically, since A is known to be an overapproximation, we check
+ *
+ * A \subset R \cup (A \circ R)
+ *
+ * Otherwise, we check if the power is exact.
+ *
+ * Note that "app" has an extra input and output coordinate to encode
+ * the length of the part. If we are only interested in the transitive
+ * closure, then we can simply project out these coordinates first.
+ */
+static int check_exactness(__isl_take isl_map *map, __isl_take isl_map *app,
+ int project)
+{
+ isl_map *test;
+ int exact;
+ unsigned d;
+
+ if (!project)
+ return check_power_exactness(map, app);
+
+ d = isl_map_dim(map, isl_dim_in);
+ app = set_path_length(app, 0, 1);
+ app = isl_map_project_out(app, isl_dim_in, d, 1);
+ app = isl_map_project_out(app, isl_dim_out, d, 1);
+
+ app = isl_map_reset_space(app, isl_map_get_space(map));
+
+ test = isl_map_apply_range(isl_map_copy(map), isl_map_copy(app));
+ test = isl_map_union(test, isl_map_copy(map));
+
+ exact = isl_map_is_subset(app, test);
+
+ isl_map_free(app);
+ isl_map_free(test);
+
+ isl_map_free(map);
+
+ return exact;
+}
+
+/*
+ * The transitive closure implementation is based on the paper
+ * "Computing the Transitive Closure of a Union of Affine Integer
+ * Tuple Relations" by Anna Beletska, Denis Barthou, Wlodzimierz Bielecki and
+ * Albert Cohen.
+ */
+
+/* Given a set of n offsets v_i (the rows of "steps"), construct a relation
+ * of the given dimension specification (Z^{n+1} -> Z^{n+1})
+ * that maps an element x to any element that can be reached
+ * by taking a non-negative number of steps along any of
+ * the extended offsets v'_i = [v_i 1].
+ * That is, construct
+ *
+ * { [x] -> [y] : exists k_i >= 0, y = x + \sum_i k_i v'_i }
+ *
+ * For any element in this relation, the number of steps taken
+ * is equal to the difference in the final coordinates.
+ */
+static __isl_give isl_map *path_along_steps(__isl_take isl_space *dim,
+ __isl_keep isl_mat *steps)
+{
+ int i, j, k;
+ struct isl_basic_map *path = NULL;
+ unsigned d;
+ unsigned n;
+ unsigned nparam;
+
+ if (!dim || !steps)
+ goto error;
+
+ d = isl_space_dim(dim, isl_dim_in);
+ n = steps->n_row;
+ nparam = isl_space_dim(dim, isl_dim_param);
+
+ path = isl_basic_map_alloc_space(isl_space_copy(dim), n, d, n);
+
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_map_alloc_div(path);
+ if (k < 0)
+ goto error;
+ isl_assert(steps->ctx, i == k, goto error);
+ isl_int_set_si(path->div[k][0], 0);
+ }
+
+ for (i = 0; i < d; ++i) {
+ k = isl_basic_map_alloc_equality(path);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+ isl_int_set_si(path->eq[k][1 + nparam + i], 1);
+ isl_int_set_si(path->eq[k][1 + nparam + d + i], -1);
+ if (i == d - 1)
+ for (j = 0; j < n; ++j)
+ isl_int_set_si(path->eq[k][1 + nparam + 2 * d + j], 1);
+ else
+ for (j = 0; j < n; ++j)
+ isl_int_set(path->eq[k][1 + nparam + 2 * d + j],
+ steps->row[j][i]);
+ }
+
+ for (i = 0; i < n; ++i) {
+ k = isl_basic_map_alloc_inequality(path);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+ isl_int_set_si(path->ineq[k][1 + nparam + 2 * d + i], 1);
+ }
+
+ isl_space_free(dim);
+
+ path = isl_basic_map_simplify(path);
+ path = isl_basic_map_finalize(path);
+ return isl_map_from_basic_map(path);
+error:
+ isl_space_free(dim);
+ isl_basic_map_free(path);
+ return NULL;
+}
+
+#define IMPURE 0
+#define PURE_PARAM 1
+#define PURE_VAR 2
+#define MIXED 3
+
+/* Check whether the parametric constant term of constraint c is never
+ * positive in "bset".
+ */
+static int parametric_constant_never_positive(__isl_keep isl_basic_set *bset,
+ isl_int *c, int *div_purity)
+{
+ unsigned d;
+ unsigned n_div;
+ unsigned nparam;
+ int i;
+ int k;
+ int empty;
+
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+ d = isl_basic_set_dim(bset, isl_dim_set);
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_cow(bset);
+ bset = isl_basic_set_extend_constraints(bset, 0, 1);
+ k = isl_basic_set_alloc_inequality(bset);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bset->ineq[k], 1 + isl_basic_set_total_dim(bset));
+ isl_seq_cpy(bset->ineq[k], c, 1 + nparam);
+ for (i = 0; i < n_div; ++i) {
+ if (div_purity[i] != PURE_PARAM)
+ continue;
+ isl_int_set(bset->ineq[k][1 + nparam + d + i],
+ c[1 + nparam + d + i]);
+ }
+ isl_int_sub_ui(bset->ineq[k][0], bset->ineq[k][0], 1);
+ empty = isl_basic_set_is_empty(bset);
+ isl_basic_set_free(bset);
+
+ return empty;
+error:
+ isl_basic_set_free(bset);
+ return -1;
+}
+
+/* Return PURE_PARAM if only the coefficients of the parameters are non-zero.
+ * Return PURE_VAR if only the coefficients of the set variables are non-zero.
+ * Return MIXED if only the coefficients of the parameters and the set
+ * variables are non-zero and if moreover the parametric constant
+ * can never attain positive values.
+ * Return IMPURE otherwise.
+ */
+static int purity(__isl_keep isl_basic_set *bset, isl_int *c, int *div_purity,
+ int eq)
+{
+ unsigned d;
+ unsigned n_div;
+ unsigned nparam;
+ int empty;
+ int i;
+ int p = 0, v = 0;
+
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+ d = isl_basic_set_dim(bset, isl_dim_set);
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ for (i = 0; i < n_div; ++i) {
+ if (isl_int_is_zero(c[1 + nparam + d + i]))
+ continue;
+ switch (div_purity[i]) {
+ case PURE_PARAM: p = 1; break;
+ case PURE_VAR: v = 1; break;
+ default: return IMPURE;
+ }
+ }
+ if (!p && isl_seq_first_non_zero(c + 1, nparam) == -1)
+ return PURE_VAR;
+ if (!v && isl_seq_first_non_zero(c + 1 + nparam, d) == -1)
+ return PURE_PARAM;
+
+ empty = parametric_constant_never_positive(bset, c, div_purity);
+ if (eq && empty >= 0 && !empty) {
+ isl_seq_neg(c, c, 1 + nparam + d + n_div);
+ empty = parametric_constant_never_positive(bset, c, div_purity);
+ }
+
+ return empty < 0 ? -1 : empty ? MIXED : IMPURE;
+}
+
+/* Return an array of integers indicating the type of each div in bset.
+ * If the div is (recursively) defined in terms of only the parameters,
+ * then the type is PURE_PARAM.
+ * If the div is (recursively) defined in terms of only the set variables,
+ * then the type is PURE_VAR.
+ * Otherwise, the type is IMPURE.
+ */
+static __isl_give int *get_div_purity(__isl_keep isl_basic_set *bset)
+{
+ int i, j;
+ int *div_purity;
+ unsigned d;
+ unsigned n_div;
+ unsigned nparam;
+
+ if (!bset)
+ return NULL;
+
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+ d = isl_basic_set_dim(bset, isl_dim_set);
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ div_purity = isl_alloc_array(bset->ctx, int, n_div);
+ if (n_div && !div_purity)
+ return NULL;
+
+ for (i = 0; i < bset->n_div; ++i) {
+ int p = 0, v = 0;
+ if (isl_int_is_zero(bset->div[i][0])) {
+ div_purity[i] = IMPURE;
+ continue;
+ }
+ if (isl_seq_first_non_zero(bset->div[i] + 2, nparam) != -1)
+ p = 1;
+ if (isl_seq_first_non_zero(bset->div[i] + 2 + nparam, d) != -1)
+ v = 1;
+ for (j = 0; j < i; ++j) {
+ if (isl_int_is_zero(bset->div[i][2 + nparam + d + j]))
+ continue;
+ switch (div_purity[j]) {
+ case PURE_PARAM: p = 1; break;
+ case PURE_VAR: v = 1; break;
+ default: p = v = 1; break;
+ }
+ }
+ div_purity[i] = v ? p ? IMPURE : PURE_VAR : PURE_PARAM;
+ }
+
+ return div_purity;
+}
+
+/* Given a path with the as yet unconstrained length at position "pos",
+ * check if setting the length to zero results in only the identity
+ * mapping.
+ */
+static int empty_path_is_identity(__isl_keep isl_basic_map *path, unsigned pos)
+{
+ isl_basic_map *test = NULL;
+ isl_basic_map *id = NULL;
+ int k;
+ int is_id;
+
+ test = isl_basic_map_copy(path);
+ test = isl_basic_map_extend_constraints(test, 1, 0);
+ k = isl_basic_map_alloc_equality(test);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(test->eq[k], 1 + isl_basic_map_total_dim(test));
+ isl_int_set_si(test->eq[k][pos], 1);
+ id = isl_basic_map_identity(isl_basic_map_get_space(path));
+ is_id = isl_basic_map_is_equal(test, id);
+ isl_basic_map_free(test);
+ isl_basic_map_free(id);
+ return is_id;
+error:
+ isl_basic_map_free(test);
+ return -1;
+}
+
+/* If any of the constraints is found to be impure then this function
+ * sets *impurity to 1.
+ *
+ * If impurity is NULL then we are dealing with a non-parametric set
+ * and so the constraints are obviously PURE_VAR.
+ */
+static __isl_give isl_basic_map *add_delta_constraints(
+ __isl_take isl_basic_map *path,
+ __isl_keep isl_basic_set *delta, unsigned off, unsigned nparam,
+ unsigned d, int *div_purity, int eq, int *impurity)
+{
+ int i, k;
+ int n = eq ? delta->n_eq : delta->n_ineq;
+ isl_int **delta_c = eq ? delta->eq : delta->ineq;
+ unsigned n_div;
+
+ n_div = isl_basic_set_dim(delta, isl_dim_div);
+
+ for (i = 0; i < n; ++i) {
+ isl_int *path_c;
+ int p = PURE_VAR;
+ if (impurity)
+ p = purity(delta, delta_c[i], div_purity, eq);
+ if (p < 0)
+ goto error;
+ if (p != PURE_VAR && p != PURE_PARAM && !*impurity)
+ *impurity = 1;
+ if (p == IMPURE)
+ continue;
+ if (eq && p != MIXED) {
+ k = isl_basic_map_alloc_equality(path);
+ path_c = path->eq[k];
+ } else {
+ k = isl_basic_map_alloc_inequality(path);
+ path_c = path->ineq[k];
+ }
+ if (k < 0)
+ goto error;
+ isl_seq_clr(path_c, 1 + isl_basic_map_total_dim(path));
+ if (p == PURE_VAR) {
+ isl_seq_cpy(path_c + off,
+ delta_c[i] + 1 + nparam, d);
+ isl_int_set(path_c[off + d], delta_c[i][0]);
+ } else if (p == PURE_PARAM) {
+ isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
+ } else {
+ isl_seq_cpy(path_c + off,
+ delta_c[i] + 1 + nparam, d);
+ isl_seq_cpy(path_c, delta_c[i], 1 + nparam);
+ }
+ isl_seq_cpy(path_c + off - n_div,
+ delta_c[i] + 1 + nparam + d, n_div);
+ }
+
+ return path;
+error:
+ isl_basic_map_free(path);
+ return NULL;
+}
+
+/* Given a set of offsets "delta", construct a relation of the
+ * given dimension specification (Z^{n+1} -> Z^{n+1}) that
+ * is an overapproximation of the relations that
+ * maps an element x to any element that can be reached
+ * by taking a non-negative number of steps along any of
+ * the elements in "delta".
+ * That is, construct an approximation of
+ *
+ * { [x] -> [y] : exists f \in \delta, k \in Z :
+ * y = x + k [f, 1] and k >= 0 }
+ *
+ * For any element in this relation, the number of steps taken
+ * is equal to the difference in the final coordinates.
+ *
+ * In particular, let delta be defined as
+ *
+ * \delta = [p] -> { [x] : A x + a >= 0 and B p + b >= 0 and
+ * C x + C'p + c >= 0 and
+ * D x + D'p + d >= 0 }
+ *
+ * where the constraints C x + C'p + c >= 0 are such that the parametric
+ * constant term of each constraint j, "C_j x + C'_j p + c_j",
+ * can never attain positive values, then the relation is constructed as
+ *
+ * { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
+ * A f + k a >= 0 and B p + b >= 0 and
+ * C f + C'p + c >= 0 and k >= 1 }
+ * union { [x] -> [x] }
+ *
+ * If the zero-length paths happen to correspond exactly to the identity
+ * mapping, then we return
+ *
+ * { [x] -> [y] : exists [f, k] \in Z^{n+1} : y = x + f and
+ * A f + k a >= 0 and B p + b >= 0 and
+ * C f + C'p + c >= 0 and k >= 0 }
+ *
+ * instead.
+ *
+ * Existentially quantified variables in \delta are handled by
+ * classifying them as independent of the parameters, purely
+ * parameter dependent and others. Constraints containing
+ * any of the other existentially quantified variables are removed.
+ * This is safe, but leads to an additional overapproximation.
+ *
+ * If there are any impure constraints, then we also eliminate
+ * the parameters from \delta, resulting in a set
+ *
+ * \delta' = { [x] : E x + e >= 0 }
+ *
+ * and add the constraints
+ *
+ * E f + k e >= 0
+ *
+ * to the constructed relation.
+ */
+static __isl_give isl_map *path_along_delta(__isl_take isl_space *dim,
+ __isl_take isl_basic_set *delta)
+{
+ isl_basic_map *path = NULL;
+ unsigned d;
+ unsigned n_div;
+ unsigned nparam;
+ unsigned off;
+ int i, k;
+ int is_id;
+ int *div_purity = NULL;
+ int impurity = 0;
+
+ if (!delta)
+ goto error;
+ n_div = isl_basic_set_dim(delta, isl_dim_div);
+ d = isl_basic_set_dim(delta, isl_dim_set);
+ nparam = isl_basic_set_dim(delta, isl_dim_param);
+ path = isl_basic_map_alloc_space(isl_space_copy(dim), n_div + d + 1,
+ d + 1 + delta->n_eq, delta->n_eq + delta->n_ineq + 1);
+ off = 1 + nparam + 2 * (d + 1) + n_div;
+
+ for (i = 0; i < n_div + d + 1; ++i) {
+ k = isl_basic_map_alloc_div(path);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(path->div[k][0], 0);
+ }
+
+ for (i = 0; i < d + 1; ++i) {
+ k = isl_basic_map_alloc_equality(path);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(path->eq[k], 1 + isl_basic_map_total_dim(path));
+ isl_int_set_si(path->eq[k][1 + nparam + i], 1);
+ isl_int_set_si(path->eq[k][1 + nparam + d + 1 + i], -1);
+ isl_int_set_si(path->eq[k][off + i], 1);
+ }
+
+ div_purity = get_div_purity(delta);
+ if (n_div && !div_purity)
+ goto error;
+
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ div_purity, 1, &impurity);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ div_purity, 0, &impurity);
+ if (impurity) {
+ isl_space *dim = isl_basic_set_get_space(delta);
+ delta = isl_basic_set_project_out(delta,
+ isl_dim_param, 0, nparam);
+ delta = isl_basic_set_add_dims(delta, isl_dim_param, nparam);
+ delta = isl_basic_set_reset_space(delta, dim);
+ if (!delta)
+ goto error;
+ path = isl_basic_map_extend_constraints(path, delta->n_eq,
+ delta->n_ineq + 1);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ NULL, 1, NULL);
+ path = add_delta_constraints(path, delta, off, nparam, d,
+ NULL, 0, NULL);
+ path = isl_basic_map_gauss(path, NULL);
+ }
+
+ is_id = empty_path_is_identity(path, off + d);
+ if (is_id < 0)
+ goto error;
+
+ k = isl_basic_map_alloc_inequality(path);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(path->ineq[k], 1 + isl_basic_map_total_dim(path));
+ if (!is_id)
+ isl_int_set_si(path->ineq[k][0], -1);
+ isl_int_set_si(path->ineq[k][off + d], 1);
+
+ free(div_purity);
+ isl_basic_set_free(delta);
+ path = isl_basic_map_finalize(path);
+ if (is_id) {
+ isl_space_free(dim);
+ return isl_map_from_basic_map(path);
+ }
+ return isl_basic_map_union(path, isl_basic_map_identity(dim));
+error:
+ free(div_purity);
+ isl_space_free(dim);
+ isl_basic_set_free(delta);
+ isl_basic_map_free(path);
+ return NULL;
+}
+
+/* Given a dimension specification Z^{n+1} -> Z^{n+1} and a parameter "param",
+ * construct a map that equates the parameter to the difference
+ * in the final coordinates and imposes that this difference is positive.
+ * That is, construct
+ *
+ * { [x,x_s] -> [y,y_s] : k = y_s - x_s > 0 }
+ */
+static __isl_give isl_map *equate_parameter_to_length(__isl_take isl_space *dim,
+ unsigned param)
+{
+ struct isl_basic_map *bmap;
+ unsigned d;
+ unsigned nparam;
+ int k;
+
+ d = isl_space_dim(dim, isl_dim_in);
+ nparam = isl_space_dim(dim, isl_dim_param);
+ bmap = isl_basic_map_alloc_space(dim, 0, 1, 1);
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[k][1 + param], -1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + d - 1], -1);
+ isl_int_set_si(bmap->eq[k][1 + nparam + d + d - 1], 1);
+
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k], 1 + isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->ineq[k][1 + param], 1);
+ isl_int_set_si(bmap->ineq[k][0], -1);
+
+ bmap = isl_basic_map_finalize(bmap);
+ return isl_map_from_basic_map(bmap);
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Check whether "path" is acyclic, where the last coordinates of domain
+ * and range of path encode the number of steps taken.
+ * That is, check whether
+ *
+ * { d | d = y - x and (x,y) in path }
+ *
+ * does not contain any element with positive last coordinate (positive length)
+ * and zero remaining coordinates (cycle).
+ */
+static int is_acyclic(__isl_take isl_map *path)
+{
+ int i;
+ int acyclic;
+ unsigned dim;
+ struct isl_set *delta;
+
+ delta = isl_map_deltas(path);
+ dim = isl_set_dim(delta, isl_dim_set);
+ for (i = 0; i < dim; ++i) {
+ if (i == dim -1)
+ delta = isl_set_lower_bound_si(delta, isl_dim_set, i, 1);
+ else
+ delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
+ }
+
+ acyclic = isl_set_is_empty(delta);
+ isl_set_free(delta);
+
+ return acyclic;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the space D \times Z to another
+ * element from the same space, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * That is, let
+ *
+ * \Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = (\sum_i k_i \delta_i, \sum_i k_i) }
+ *
+ * The elements of the singleton \Delta_i's are collected as the
+ * rows of the steps matrix. For all these \Delta_i's together,
+ * a single path is constructed.
+ * For each of the other \Delta_i's, we compute an overapproximation
+ * of the paths along elements of \Delta_i.
+ * Since each of these paths performs an addition, composition is
+ * symmetric and we can simply compose all resulting paths in any order.
+ */
+static __isl_give isl_map *construct_extended_path(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *project)
+{
+ struct isl_mat *steps = NULL;
+ struct isl_map *path = NULL;
+ unsigned d;
+ int i, j, n;
+
+ d = isl_map_dim(map, isl_dim_in);
+
+ path = isl_map_identity(isl_space_copy(dim));
+
+ steps = isl_mat_alloc(map->ctx, map->n, d);
+ if (!steps)
+ goto error;
+
+ n = 0;
+ for (i = 0; i < map->n; ++i) {
+ struct isl_basic_set *delta;
+
+ delta = isl_basic_map_deltas(isl_basic_map_copy(map->p[i]));
+
+ for (j = 0; j < d; ++j) {
+ int fixed;
+
+ fixed = isl_basic_set_plain_dim_is_fixed(delta, j,
+ &steps->row[n][j]);
+ if (fixed < 0) {
+ isl_basic_set_free(delta);
+ goto error;
+ }
+ if (!fixed)
+ break;
+ }
+
+
+ if (j < d) {
+ path = isl_map_apply_range(path,
+ path_along_delta(isl_space_copy(dim), delta));
+ path = isl_map_coalesce(path);
+ } else {
+ isl_basic_set_free(delta);
+ ++n;
+ }
+ }
+
+ if (n > 0) {
+ steps->n_row = n;
+ path = isl_map_apply_range(path,
+ path_along_steps(isl_space_copy(dim), steps));
+ }
+
+ if (project && *project) {
+ *project = is_acyclic(isl_map_copy(path));
+ if (*project < 0)
+ goto error;
+ }
+
+ isl_space_free(dim);
+ isl_mat_free(steps);
+ return path;
+error:
+ isl_space_free(dim);
+ isl_mat_free(steps);
+ isl_map_free(path);
+ return NULL;
+}
+
+static int isl_set_overlaps(__isl_keep isl_set *set1, __isl_keep isl_set *set2)
+{
+ isl_set *i;
+ int no_overlap;
+
+ if (!isl_space_tuple_is_equal(set1->dim, isl_dim_set,
+ set2->dim, isl_dim_set))
+ return 0;
+
+ i = isl_set_intersect(isl_set_copy(set1), isl_set_copy(set2));
+ no_overlap = isl_set_is_empty(i);
+ isl_set_free(i);
+
+ return no_overlap < 0 ? -1 : !no_overlap;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the dom R \times Z to an
+ * element from ran R \times Z, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * That is, let
+ *
+ * \Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = (\sum_i k_i \delta_i, \sum_i k_i) and
+ * x in dom R and x + d in ran R and
+ * \sum_i k_i >= 1 }
+ */
+static __isl_give isl_map *construct_component(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project)
+{
+ struct isl_set *domain = NULL;
+ struct isl_set *range = NULL;
+ struct isl_map *app = NULL;
+ struct isl_map *path = NULL;
+
+ domain = isl_map_domain(isl_map_copy(map));
+ domain = isl_set_coalesce(domain);
+ range = isl_map_range(isl_map_copy(map));
+ range = isl_set_coalesce(range);
+ if (!isl_set_overlaps(domain, range)) {
+ isl_set_free(domain);
+ isl_set_free(range);
+ isl_space_free(dim);
+
+ map = isl_map_copy(map);
+ map = isl_map_add_dims(map, isl_dim_in, 1);
+ map = isl_map_add_dims(map, isl_dim_out, 1);
+ map = set_path_length(map, 1, 1);
+ return map;
+ }
+ app = isl_map_from_domain_and_range(domain, range);
+ app = isl_map_add_dims(app, isl_dim_in, 1);
+ app = isl_map_add_dims(app, isl_dim_out, 1);
+
+ path = construct_extended_path(isl_space_copy(dim), map,
+ exact && *exact ? &project : NULL);
+ app = isl_map_intersect(app, path);
+
+ if (exact && *exact &&
+ (*exact = check_exactness(isl_map_copy(map), isl_map_copy(app),
+ project)) < 0)
+ goto error;
+
+ isl_space_free(dim);
+ app = set_path_length(app, 0, 1);
+ return app;
+error:
+ isl_space_free(dim);
+ isl_map_free(app);
+ return NULL;
+}
+
+/* Call construct_component and, if "project" is set, project out
+ * the final coordinates.
+ */
+static __isl_give isl_map *construct_projected_component(
+ __isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project)
+{
+ isl_map *app;
+ unsigned d;
+
+ if (!dim)
+ return NULL;
+ d = isl_space_dim(dim, isl_dim_in);
+
+ app = construct_component(dim, map, exact, project);
+ if (project) {
+ app = isl_map_project_out(app, isl_dim_in, d - 1, 1);
+ app = isl_map_project_out(app, isl_dim_out, d - 1, 1);
+ }
+ return app;
+}
+
+/* Compute an extended version, i.e., with path lengths, of
+ * an overapproximation of the transitive closure of "bmap"
+ * with path lengths greater than or equal to zero and with
+ * domain and range equal to "dom".
+ */
+static __isl_give isl_map *q_closure(__isl_take isl_space *dim,
+ __isl_take isl_set *dom, __isl_keep isl_basic_map *bmap, int *exact)
+{
+ int project = 1;
+ isl_map *path;
+ isl_map *map;
+ isl_map *app;
+
+ dom = isl_set_add_dims(dom, isl_dim_set, 1);
+ app = isl_map_from_domain_and_range(dom, isl_set_copy(dom));
+ map = isl_map_from_basic_map(isl_basic_map_copy(bmap));
+ path = construct_extended_path(dim, map, &project);
+ app = isl_map_intersect(app, path);
+
+ if ((*exact = check_exactness(map, isl_map_copy(app), project)) < 0)
+ goto error;
+
+ return app;
+error:
+ isl_map_free(app);
+ return NULL;
+}
+
+/* Check whether qc has any elements of length at least one
+ * with domain and/or range outside of dom and ran.
+ */
+static int has_spurious_elements(__isl_keep isl_map *qc,
+ __isl_keep isl_set *dom, __isl_keep isl_set *ran)
+{
+ isl_set *s;
+ int subset;
+ unsigned d;
+
+ if (!qc || !dom || !ran)
+ return -1;
+
+ d = isl_map_dim(qc, isl_dim_in);
+
+ qc = isl_map_copy(qc);
+ qc = set_path_length(qc, 0, 1);
+ qc = isl_map_project_out(qc, isl_dim_in, d - 1, 1);
+ qc = isl_map_project_out(qc, isl_dim_out, d - 1, 1);
+
+ s = isl_map_domain(isl_map_copy(qc));
+ subset = isl_set_is_subset(s, dom);
+ isl_set_free(s);
+ if (subset < 0)
+ goto error;
+ if (!subset) {
+ isl_map_free(qc);
+ return 1;
+ }
+
+ s = isl_map_range(qc);
+ subset = isl_set_is_subset(s, ran);
+ isl_set_free(s);
+
+ return subset < 0 ? -1 : !subset;
+error:
+ isl_map_free(qc);
+ return -1;
+}
+
+#define LEFT 2
+#define RIGHT 1
+
+/* For each basic map in "map", except i, check whether it combines
+ * with the transitive closure that is reflexive on C combines
+ * to the left and to the right.
+ *
+ * In particular, if
+ *
+ * dom map_j \subseteq C
+ *
+ * then right[j] is set to 1. Otherwise, if
+ *
+ * ran map_i \cap dom map_j = \emptyset
+ *
+ * then right[j] is set to 0. Otherwise, composing to the right
+ * is impossible.
+ *
+ * Similar, for composing to the left, we have if
+ *
+ * ran map_j \subseteq C
+ *
+ * then left[j] is set to 1. Otherwise, if
+ *
+ * dom map_i \cap ran map_j = \emptyset
+ *
+ * then left[j] is set to 0. Otherwise, composing to the left
+ * is impossible.
+ *
+ * The return value is or'd with LEFT if composing to the left
+ * is possible and with RIGHT if composing to the right is possible.
+ */
+static int composability(__isl_keep isl_set *C, int i,
+ isl_set **dom, isl_set **ran, int *left, int *right,
+ __isl_keep isl_map *map)
+{
+ int j;
+ int ok;
+
+ ok = LEFT | RIGHT;
+ for (j = 0; j < map->n && ok; ++j) {
+ int overlaps, subset;
+ if (j == i)
+ continue;
+
+ if (ok & RIGHT) {
+ if (!dom[j])
+ dom[j] = isl_set_from_basic_set(
+ isl_basic_map_domain(
+ isl_basic_map_copy(map->p[j])));
+ if (!dom[j])
+ return -1;
+ overlaps = isl_set_overlaps(ran[i], dom[j]);
+ if (overlaps < 0)
+ return -1;
+ if (!overlaps)
+ right[j] = 0;
+ else {
+ subset = isl_set_is_subset(dom[j], C);
+ if (subset < 0)
+ return -1;
+ if (subset)
+ right[j] = 1;
+ else
+ ok &= ~RIGHT;
+ }
+ }
+
+ if (ok & LEFT) {
+ if (!ran[j])
+ ran[j] = isl_set_from_basic_set(
+ isl_basic_map_range(
+ isl_basic_map_copy(map->p[j])));
+ if (!ran[j])
+ return -1;
+ overlaps = isl_set_overlaps(dom[i], ran[j]);
+ if (overlaps < 0)
+ return -1;
+ if (!overlaps)
+ left[j] = 0;
+ else {
+ subset = isl_set_is_subset(ran[j], C);
+ if (subset < 0)
+ return -1;
+ if (subset)
+ left[j] = 1;
+ else
+ ok &= ~LEFT;
+ }
+ }
+ }
+
+ return ok;
+}
+
+static __isl_give isl_map *anonymize(__isl_take isl_map *map)
+{
+ map = isl_map_reset(map, isl_dim_in);
+ map = isl_map_reset(map, isl_dim_out);
+ return map;
+}
+
+/* Return a map that is a union of the basic maps in "map", except i,
+ * composed to left and right with qc based on the entries of "left"
+ * and "right".
+ */
+static __isl_give isl_map *compose(__isl_keep isl_map *map, int i,
+ __isl_take isl_map *qc, int *left, int *right)
+{
+ int j;
+ isl_map *comp;
+
+ comp = isl_map_empty(isl_map_get_space(map));
+ for (j = 0; j < map->n; ++j) {
+ isl_map *map_j;
+
+ if (j == i)
+ continue;
+
+ map_j = isl_map_from_basic_map(isl_basic_map_copy(map->p[j]));
+ map_j = anonymize(map_j);
+ if (left && left[j])
+ map_j = isl_map_apply_range(map_j, isl_map_copy(qc));
+ if (right && right[j])
+ map_j = isl_map_apply_range(isl_map_copy(qc), map_j);
+ comp = isl_map_union(comp, map_j);
+ }
+
+ comp = isl_map_compute_divs(comp);
+ comp = isl_map_coalesce(comp);
+
+ isl_map_free(qc);
+
+ return comp;
+}
+
+/* Compute the transitive closure of "map" incrementally by
+ * computing
+ *
+ * map_i^+ \cup qc^+
+ *
+ * or
+ *
+ * map_i^+ \cup ((id \cup map_i^) \circ qc^+)
+ *
+ * or
+ *
+ * map_i^+ \cup (qc^+ \circ (id \cup map_i^))
+ *
+ * depending on whether left or right are NULL.
+ */
+static __isl_give isl_map *compute_incremental(
+ __isl_take isl_space *dim, __isl_keep isl_map *map,
+ int i, __isl_take isl_map *qc, int *left, int *right, int *exact)
+{
+ isl_map *map_i;
+ isl_map *tc;
+ isl_map *rtc = NULL;
+
+ if (!map)
+ goto error;
+ isl_assert(map->ctx, left || right, goto error);
+
+ map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
+ tc = construct_projected_component(isl_space_copy(dim), map_i,
+ exact, 1);
+ isl_map_free(map_i);
+
+ if (*exact)
+ qc = isl_map_transitive_closure(qc, exact);
+
+ if (!*exact) {
+ isl_space_free(dim);
+ isl_map_free(tc);
+ isl_map_free(qc);
+ return isl_map_universe(isl_map_get_space(map));
+ }
+
+ if (!left || !right)
+ rtc = isl_map_union(isl_map_copy(tc),
+ isl_map_identity(isl_map_get_space(tc)));
+ if (!right)
+ qc = isl_map_apply_range(rtc, qc);
+ if (!left)
+ qc = isl_map_apply_range(qc, rtc);
+ qc = isl_map_union(tc, qc);
+
+ isl_space_free(dim);
+
+ return qc;
+error:
+ isl_space_free(dim);
+ isl_map_free(qc);
+ return NULL;
+}
+
+/* Given a map "map", try to find a basic map such that
+ * map^+ can be computed as
+ *
+ * map^+ = map_i^+ \cup
+ * \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
+ *
+ * with C the simple hull of the domain and range of the input map.
+ * map_i^ \cup Id_C is computed by allowing the path lengths to be zero
+ * and by intersecting domain and range with C.
+ * Of course, we need to check that this is actually equal to map_i^ \cup Id_C.
+ * Also, we only use the incremental computation if all the transitive
+ * closures are exact and if the number of basic maps in the union,
+ * after computing the integer divisions, is smaller than the number
+ * of basic maps in the input map.
+ */
+static int incemental_on_entire_domain(__isl_keep isl_space *dim,
+ __isl_keep isl_map *map,
+ isl_set **dom, isl_set **ran, int *left, int *right,
+ __isl_give isl_map **res)
+{
+ int i;
+ isl_set *C;
+ unsigned d;
+
+ *res = NULL;
+
+ C = isl_set_union(isl_map_domain(isl_map_copy(map)),
+ isl_map_range(isl_map_copy(map)));
+ C = isl_set_from_basic_set(isl_set_simple_hull(C));
+ if (!C)
+ return -1;
+ if (C->n != 1) {
+ isl_set_free(C);
+ return 0;
+ }
+
+ d = isl_map_dim(map, isl_dim_in);
+
+ for (i = 0; i < map->n; ++i) {
+ isl_map *qc;
+ int exact_i, spurious;
+ int j;
+ dom[i] = isl_set_from_basic_set(isl_basic_map_domain(
+ isl_basic_map_copy(map->p[i])));
+ ran[i] = isl_set_from_basic_set(isl_basic_map_range(
+ isl_basic_map_copy(map->p[i])));
+ qc = q_closure(isl_space_copy(dim), isl_set_copy(C),
+ map->p[i], &exact_i);
+ if (!qc)
+ goto error;
+ if (!exact_i) {
+ isl_map_free(qc);
+ continue;
+ }
+ spurious = has_spurious_elements(qc, dom[i], ran[i]);
+ if (spurious) {
+ isl_map_free(qc);
+ if (spurious < 0)
+ goto error;
+ continue;
+ }
+ qc = isl_map_project_out(qc, isl_dim_in, d, 1);
+ qc = isl_map_project_out(qc, isl_dim_out, d, 1);
+ qc = isl_map_compute_divs(qc);
+ for (j = 0; j < map->n; ++j)
+ left[j] = right[j] = 1;
+ qc = compose(map, i, qc, left, right);
+ if (!qc)
+ goto error;
+ if (qc->n >= map->n) {
+ isl_map_free(qc);
+ continue;
+ }
+ *res = compute_incremental(isl_space_copy(dim), map, i, qc,
+ left, right, &exact_i);
+ if (!*res)
+ goto error;
+ if (exact_i)
+ break;
+ isl_map_free(*res);
+ *res = NULL;
+ }
+
+ isl_set_free(C);
+
+ return *res != NULL;
+error:
+ isl_set_free(C);
+ return -1;
+}
+
+/* Try and compute the transitive closure of "map" as
+ *
+ * map^+ = map_i^+ \cup
+ * \bigcup_j ((map_i^+ \cup Id_C)^+ \circ map_j \circ (map_i^+ \cup Id_C))^+
+ *
+ * with C either the simple hull of the domain and range of the entire
+ * map or the simple hull of domain and range of map_i.
+ */
+static __isl_give isl_map *incremental_closure(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project)
+{
+ int i;
+ isl_set **dom = NULL;
+ isl_set **ran = NULL;
+ int *left = NULL;
+ int *right = NULL;
+ isl_set *C;
+ unsigned d;
+ isl_map *res = NULL;
+
+ if (!project)
+ return construct_projected_component(dim, map, exact, project);
+
+ if (!map)
+ goto error;
+ if (map->n <= 1)
+ return construct_projected_component(dim, map, exact, project);
+
+ d = isl_map_dim(map, isl_dim_in);
+
+ dom = isl_calloc_array(map->ctx, isl_set *, map->n);
+ ran = isl_calloc_array(map->ctx, isl_set *, map->n);
+ left = isl_calloc_array(map->ctx, int, map->n);
+ right = isl_calloc_array(map->ctx, int, map->n);
+ if (!ran || !dom || !left || !right)
+ goto error;
+
+ if (incemental_on_entire_domain(dim, map, dom, ran, left, right, &res) < 0)
+ goto error;
+
+ for (i = 0; !res && i < map->n; ++i) {
+ isl_map *qc;
+ int exact_i, spurious, comp;
+ if (!dom[i])
+ dom[i] = isl_set_from_basic_set(
+ isl_basic_map_domain(
+ isl_basic_map_copy(map->p[i])));
+ if (!dom[i])
+ goto error;
+ if (!ran[i])
+ ran[i] = isl_set_from_basic_set(
+ isl_basic_map_range(
+ isl_basic_map_copy(map->p[i])));
+ if (!ran[i])
+ goto error;
+ C = isl_set_union(isl_set_copy(dom[i]),
+ isl_set_copy(ran[i]));
+ C = isl_set_from_basic_set(isl_set_simple_hull(C));
+ if (!C)
+ goto error;
+ if (C->n != 1) {
+ isl_set_free(C);
+ continue;
+ }
+ comp = composability(C, i, dom, ran, left, right, map);
+ if (!comp || comp < 0) {
+ isl_set_free(C);
+ if (comp < 0)
+ goto error;
+ continue;
+ }
+ qc = q_closure(isl_space_copy(dim), C, map->p[i], &exact_i);
+ if (!qc)
+ goto error;
+ if (!exact_i) {
+ isl_map_free(qc);
+ continue;
+ }
+ spurious = has_spurious_elements(qc, dom[i], ran[i]);
+ if (spurious) {
+ isl_map_free(qc);
+ if (spurious < 0)
+ goto error;
+ continue;
+ }
+ qc = isl_map_project_out(qc, isl_dim_in, d, 1);
+ qc = isl_map_project_out(qc, isl_dim_out, d, 1);
+ qc = isl_map_compute_divs(qc);
+ qc = compose(map, i, qc, (comp & LEFT) ? left : NULL,
+ (comp & RIGHT) ? right : NULL);
+ if (!qc)
+ goto error;
+ if (qc->n >= map->n) {
+ isl_map_free(qc);
+ continue;
+ }
+ res = compute_incremental(isl_space_copy(dim), map, i, qc,
+ (comp & LEFT) ? left : NULL,
+ (comp & RIGHT) ? right : NULL, &exact_i);
+ if (!res)
+ goto error;
+ if (exact_i)
+ break;
+ isl_map_free(res);
+ res = NULL;
+ }
+
+ for (i = 0; i < map->n; ++i) {
+ isl_set_free(dom[i]);
+ isl_set_free(ran[i]);
+ }
+ free(dom);
+ free(ran);
+ free(left);
+ free(right);
+
+ if (res) {
+ isl_space_free(dim);
+ return res;
+ }
+
+ return construct_projected_component(dim, map, exact, project);
+error:
+ if (dom)
+ for (i = 0; i < map->n; ++i)
+ isl_set_free(dom[i]);
+ free(dom);
+ if (ran)
+ for (i = 0; i < map->n; ++i)
+ isl_set_free(ran[i]);
+ free(ran);
+ free(left);
+ free(right);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Given an array of sets "set", add "dom" at position "pos"
+ * and search for elements at earlier positions that overlap with "dom".
+ * If any can be found, then merge all of them, together with "dom", into
+ * a single set and assign the union to the first in the array,
+ * which becomes the new group leader for all groups involved in the merge.
+ * During the search, we only consider group leaders, i.e., those with
+ * group[i] = i, as the other sets have already been combined
+ * with one of the group leaders.
+ */
+static int merge(isl_set **set, int *group, __isl_take isl_set *dom, int pos)
+{
+ int i;
+
+ group[pos] = pos;
+ set[pos] = isl_set_copy(dom);
+
+ for (i = pos - 1; i >= 0; --i) {
+ int o;
+
+ if (group[i] != i)
+ continue;
+
+ o = isl_set_overlaps(set[i], dom);
+ if (o < 0)
+ goto error;
+ if (!o)
+ continue;
+
+ set[i] = isl_set_union(set[i], set[group[pos]]);
+ set[group[pos]] = NULL;
+ if (!set[i])
+ goto error;
+ group[group[pos]] = i;
+ group[pos] = i;
+ }
+
+ isl_set_free(dom);
+ return 0;
+error:
+ isl_set_free(dom);
+ return -1;
+}
+
+/* Replace each entry in the n by n grid of maps by the cross product
+ * with the relation { [i] -> [i + 1] }.
+ */
+static int add_length(__isl_keep isl_map *map, isl_map ***grid, int n)
+{
+ int i, j, k;
+ isl_space *dim;
+ isl_basic_map *bstep;
+ isl_map *step;
+ unsigned nparam;
+
+ if (!map)
+ return -1;
+
+ dim = isl_map_get_space(map);
+ nparam = isl_space_dim(dim, isl_dim_param);
+ dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
+ dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
+ dim = isl_space_add_dims(dim, isl_dim_in, 1);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ bstep = isl_basic_map_alloc_space(dim, 0, 1, 0);
+ k = isl_basic_map_alloc_equality(bstep);
+ if (k < 0) {
+ isl_basic_map_free(bstep);
+ return -1;
+ }
+ isl_seq_clr(bstep->eq[k], 1 + isl_basic_map_total_dim(bstep));
+ isl_int_set_si(bstep->eq[k][0], 1);
+ isl_int_set_si(bstep->eq[k][1 + nparam], 1);
+ isl_int_set_si(bstep->eq[k][1 + nparam + 1], -1);
+ bstep = isl_basic_map_finalize(bstep);
+ step = isl_map_from_basic_map(bstep);
+
+ for (i = 0; i < n; ++i)
+ for (j = 0; j < n; ++j)
+ grid[i][j] = isl_map_product(grid[i][j],
+ isl_map_copy(step));
+
+ isl_map_free(step);
+
+ return 0;
+}
+
+/* The core of the Floyd-Warshall algorithm.
+ * Updates the given n x x matrix of relations in place.
+ *
+ * The algorithm iterates over all vertices. In each step, the whole
+ * matrix is updated to include all paths that go to the current vertex,
+ * possibly stay there a while (including passing through earlier vertices)
+ * and then come back. At the start of each iteration, the diagonal
+ * element corresponding to the current vertex is replaced by its
+ * transitive closure to account for all indirect paths that stay
+ * in the current vertex.
+ */
+static void floyd_warshall_iterate(isl_map ***grid, int n, int *exact)
+{
+ int r, p, q;
+
+ for (r = 0; r < n; ++r) {
+ int r_exact;
+ grid[r][r] = isl_map_transitive_closure(grid[r][r],
+ (exact && *exact) ? &r_exact : NULL);
+ if (exact && *exact && !r_exact)
+ *exact = 0;
+
+ for (p = 0; p < n; ++p)
+ for (q = 0; q < n; ++q) {
+ isl_map *loop;
+ if (p == r && q == r)
+ continue;
+ loop = isl_map_apply_range(
+ isl_map_copy(grid[p][r]),
+ isl_map_copy(grid[r][q]));
+ grid[p][q] = isl_map_union(grid[p][q], loop);
+ loop = isl_map_apply_range(
+ isl_map_copy(grid[p][r]),
+ isl_map_apply_range(
+ isl_map_copy(grid[r][r]),
+ isl_map_copy(grid[r][q])));
+ grid[p][q] = isl_map_union(grid[p][q], loop);
+ grid[p][q] = isl_map_coalesce(grid[p][q]);
+ }
+ }
+}
+
+/* Given a partition of the domains and ranges of the basic maps in "map",
+ * apply the Floyd-Warshall algorithm with the elements in the partition
+ * as vertices.
+ *
+ * In particular, there are "n" elements in the partition and "group" is
+ * an array of length 2 * map->n with entries in [0,n-1].
+ *
+ * We first construct a matrix of relations based on the partition information,
+ * apply Floyd-Warshall on this matrix of relations and then take the
+ * union of all entries in the matrix as the final result.
+ *
+ * If we are actually computing the power instead of the transitive closure,
+ * i.e., when "project" is not set, then the result should have the
+ * path lengths encoded as the difference between an extra pair of
+ * coordinates. We therefore apply the nested transitive closures
+ * to relations that include these lengths. In particular, we replace
+ * the input relation by the cross product with the unit length relation
+ * { [i] -> [i + 1] }.
+ */
+static __isl_give isl_map *floyd_warshall_with_groups(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project, int *group, int n)
+{
+ int i, j, k;
+ isl_map ***grid = NULL;
+ isl_map *app;
+
+ if (!map)
+ goto error;
+
+ if (n == 1) {
+ free(group);
+ return incremental_closure(dim, map, exact, project);
+ }
+
+ grid = isl_calloc_array(map->ctx, isl_map **, n);
+ if (!grid)
+ goto error;
+ for (i = 0; i < n; ++i) {
+ grid[i] = isl_calloc_array(map->ctx, isl_map *, n);
+ if (!grid[i])
+ goto error;
+ for (j = 0; j < n; ++j)
+ grid[i][j] = isl_map_empty(isl_map_get_space(map));
+ }
+
+ for (k = 0; k < map->n; ++k) {
+ i = group[2 * k];
+ j = group[2 * k + 1];
+ grid[i][j] = isl_map_union(grid[i][j],
+ isl_map_from_basic_map(
+ isl_basic_map_copy(map->p[k])));
+ }
+
+ if (!project && add_length(map, grid, n) < 0)
+ goto error;
+
+ floyd_warshall_iterate(grid, n, exact);
+
+ app = isl_map_empty(isl_map_get_space(map));
+
+ for (i = 0; i < n; ++i) {
+ for (j = 0; j < n; ++j)
+ app = isl_map_union(app, grid[i][j]);
+ free(grid[i]);
+ }
+ free(grid);
+
+ free(group);
+ isl_space_free(dim);
+
+ return app;
+error:
+ if (grid)
+ for (i = 0; i < n; ++i) {
+ if (!grid[i])
+ continue;
+ for (j = 0; j < n; ++j)
+ isl_map_free(grid[i][j]);
+ free(grid[i]);
+ }
+ free(grid);
+ free(group);
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Partition the domains and ranges of the n basic relations in list
+ * into disjoint cells.
+ *
+ * To find the partition, we simply consider all of the domains
+ * and ranges in turn and combine those that overlap.
+ * "set" contains the partition elements and "group" indicates
+ * to which partition element a given domain or range belongs.
+ * The domain of basic map i corresponds to element 2 * i in these arrays,
+ * while the domain corresponds to element 2 * i + 1.
+ * During the construction group[k] is either equal to k,
+ * in which case set[k] contains the union of all the domains and
+ * ranges in the corresponding group, or is equal to some l < k,
+ * with l another domain or range in the same group.
+ */
+static int *setup_groups(isl_ctx *ctx, __isl_keep isl_basic_map **list, int n,
+ isl_set ***set, int *n_group)
+{
+ int i;
+ int *group = NULL;
+ int g;
+
+ *set = isl_calloc_array(ctx, isl_set *, 2 * n);
+ group = isl_alloc_array(ctx, int, 2 * n);
+
+ if (!*set || !group)
+ goto error;
+
+ for (i = 0; i < n; ++i) {
+ isl_set *dom;
+ dom = isl_set_from_basic_set(isl_basic_map_domain(
+ isl_basic_map_copy(list[i])));
+ if (merge(*set, group, dom, 2 * i) < 0)
+ goto error;
+ dom = isl_set_from_basic_set(isl_basic_map_range(
+ isl_basic_map_copy(list[i])));
+ if (merge(*set, group, dom, 2 * i + 1) < 0)
+ goto error;
+ }
+
+ g = 0;
+ for (i = 0; i < 2 * n; ++i)
+ if (group[i] == i) {
+ if (g != i) {
+ (*set)[g] = (*set)[i];
+ (*set)[i] = NULL;
+ }
+ group[i] = g++;
+ } else
+ group[i] = group[group[i]];
+
+ *n_group = g;
+
+ return group;
+error:
+ if (*set) {
+ for (i = 0; i < 2 * n; ++i)
+ isl_set_free((*set)[i]);
+ free(*set);
+ *set = NULL;
+ }
+ free(group);
+ return NULL;
+}
+
+/* Check if the domains and ranges of the basic maps in "map" can
+ * be partitioned, and if so, apply Floyd-Warshall on the elements
+ * of the partition. Note that we also apply this algorithm
+ * if we want to compute the power, i.e., when "project" is not set.
+ * However, the results are unlikely to be exact since the recursive
+ * calls inside the Floyd-Warshall algorithm typically result in
+ * non-linear path lengths quite quickly.
+ */
+static __isl_give isl_map *floyd_warshall(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project)
+{
+ int i;
+ isl_set **set = NULL;
+ int *group = NULL;
+ int n;
+
+ if (!map)
+ goto error;
+ if (map->n <= 1)
+ return incremental_closure(dim, map, exact, project);
+
+ group = setup_groups(map->ctx, map->p, map->n, &set, &n);
+ if (!group)
+ goto error;
+
+ for (i = 0; i < 2 * map->n; ++i)
+ isl_set_free(set[i]);
+
+ free(set);
+
+ return floyd_warshall_with_groups(dim, map, exact, project, group, n);
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+/* Structure for representing the nodes of the graph of which
+ * strongly connected components are being computed.
+ *
+ * list contains the actual nodes
+ * check_closed is set if we may have used the fact that
+ * a pair of basic maps can be interchanged
+ */
+struct isl_tc_follows_data {
+ isl_basic_map **list;
+ int check_closed;
+};
+
+/* Check whether in the computation of the transitive closure
+ * "list[i]" (R_1) should follow (or be part of the same component as)
+ * "list[j]" (R_2).
+ *
+ * That is check whether
+ *
+ * R_1 \circ R_2
+ *
+ * is a subset of
+ *
+ * R_2 \circ R_1
+ *
+ * If so, then there is no reason for R_1 to immediately follow R_2
+ * in any path.
+ *
+ * *check_closed is set if the subset relation holds while
+ * R_1 \circ R_2 is not empty.
+ */
+static int basic_map_follows(int i, int j, void *user)
+{
+ struct isl_tc_follows_data *data = user;
+ struct isl_map *map12 = NULL;
+ struct isl_map *map21 = NULL;
+ int subset;
+
+ if (!isl_space_tuple_is_equal(data->list[i]->dim, isl_dim_in,
+ data->list[j]->dim, isl_dim_out))
+ return 0;
+
+ map21 = isl_map_from_basic_map(
+ isl_basic_map_apply_range(
+ isl_basic_map_copy(data->list[j]),
+ isl_basic_map_copy(data->list[i])));
+ subset = isl_map_is_empty(map21);
+ if (subset < 0)
+ goto error;
+ if (subset) {
+ isl_map_free(map21);
+ return 0;
+ }
+
+ if (!isl_space_tuple_is_equal(data->list[i]->dim, isl_dim_in,
+ data->list[i]->dim, isl_dim_out) ||
+ !isl_space_tuple_is_equal(data->list[j]->dim, isl_dim_in,
+ data->list[j]->dim, isl_dim_out)) {
+ isl_map_free(map21);
+ return 1;
+ }
+
+ map12 = isl_map_from_basic_map(
+ isl_basic_map_apply_range(
+ isl_basic_map_copy(data->list[i]),
+ isl_basic_map_copy(data->list[j])));
+
+ subset = isl_map_is_subset(map21, map12);
+
+ isl_map_free(map12);
+ isl_map_free(map21);
+
+ if (subset)
+ data->check_closed = 1;
+
+ return subset < 0 ? -1 : !subset;
+error:
+ isl_map_free(map21);
+ return -1;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D
+ * and a dimension specification (Z^{n+1} -> Z^{n+1}),
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the dom R \times Z to an
+ * element from ran R \times Z, such that the first n coordinates of the
+ * difference between them is a sum of differences between images
+ * and pre-images in one of the R_i and such that the last coordinate
+ * is equal to the number of steps taken.
+ * If "project" is set, then these final coordinates are not included,
+ * i.e., a relation of type Z^n -> Z^n is returned.
+ * That is, let
+ *
+ * \Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = (\sum_i k_i \delta_i, \sum_i k_i) and
+ * x in dom R and x + d in ran R }
+ *
+ * or
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = (\sum_i k_i \delta_i) and
+ * x in dom R and x + d in ran R }
+ *
+ * if "project" is set.
+ *
+ * We first split the map into strongly connected components, perform
+ * the above on each component and then join the results in the correct
+ * order, at each join also taking in the union of both arguments
+ * to allow for paths that do not go through one of the two arguments.
+ */
+static __isl_give isl_map *construct_power_components(__isl_take isl_space *dim,
+ __isl_keep isl_map *map, int *exact, int project)
+{
+ int i, n, c;
+ struct isl_map *path = NULL;
+ struct isl_tc_follows_data data;
+ struct isl_tarjan_graph *g = NULL;
+ int *orig_exact;
+ int local_exact;
+
+ if (!map)
+ goto error;
+ if (map->n <= 1)
+ return floyd_warshall(dim, map, exact, project);
+
+ data.list = map->p;
+ data.check_closed = 0;
+ g = isl_tarjan_graph_init(map->ctx, map->n, &basic_map_follows, &data);
+ if (!g)
+ goto error;
+
+ orig_exact = exact;
+ if (data.check_closed && !exact)
+ exact = &local_exact;
+
+ c = 0;
+ i = 0;
+ n = map->n;
+ if (project)
+ path = isl_map_empty(isl_map_get_space(map));
+ else
+ path = isl_map_empty(isl_space_copy(dim));
+ path = anonymize(path);
+ while (n) {
+ struct isl_map *comp;
+ isl_map *path_comp, *path_comb;
+ comp = isl_map_alloc_space(isl_map_get_space(map), n, 0);
+ while (g->order[i] != -1) {
+ comp = isl_map_add_basic_map(comp,
+ isl_basic_map_copy(map->p[g->order[i]]));
+ --n;
+ ++i;
+ }
+ path_comp = floyd_warshall(isl_space_copy(dim),
+ comp, exact, project);
+ path_comp = anonymize(path_comp);
+ path_comb = isl_map_apply_range(isl_map_copy(path),
+ isl_map_copy(path_comp));
+ path = isl_map_union(path, path_comp);
+ path = isl_map_union(path, path_comb);
+ isl_map_free(comp);
+ ++i;
+ ++c;
+ }
+
+ if (c > 1 && data.check_closed && !*exact) {
+ int closed;
+
+ closed = isl_map_is_transitively_closed(path);
+ if (closed < 0)
+ goto error;
+ if (!closed) {
+ isl_tarjan_graph_free(g);
+ isl_map_free(path);
+ return floyd_warshall(dim, map, orig_exact, project);
+ }
+ }
+
+ isl_tarjan_graph_free(g);
+ isl_space_free(dim);
+
+ return path;
+error:
+ isl_tarjan_graph_free(g);
+ isl_space_free(dim);
+ isl_map_free(path);
+ return NULL;
+}
+
+/* Given a union of basic maps R = \cup_i R_i \subseteq D \times D,
+ * construct a map that is an overapproximation of the map
+ * that takes an element from the space D to another
+ * element from the same space, such that the difference between
+ * them is a strictly positive sum of differences between images
+ * and pre-images in one of the R_i.
+ * The number of differences in the sum is equated to parameter "param".
+ * That is, let
+ *
+ * \Delta_i = { y - x | (x, y) in R_i }
+ *
+ * then the constructed map is an overapproximation of
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = \sum_i k_i \delta_i and k = \sum_i k_i > 0 }
+ * or
+ *
+ * { (x) -> (x + d) | \exists k_i >= 0, \delta_i \in \Delta_i :
+ * d = \sum_i k_i \delta_i and \sum_i k_i > 0 }
+ *
+ * if "project" is set.
+ *
+ * If "project" is not set, then
+ * we construct an extended mapping with an extra coordinate
+ * that indicates the number of steps taken. In particular,
+ * the difference in the last coordinate is equal to the number
+ * of steps taken to move from a domain element to the corresponding
+ * image element(s).
+ */
+static __isl_give isl_map *construct_power(__isl_keep isl_map *map,
+ int *exact, int project)
+{
+ struct isl_map *app = NULL;
+ isl_space *dim = NULL;
+ unsigned d;
+
+ if (!map)
+ return NULL;
+
+ dim = isl_map_get_space(map);
+
+ d = isl_space_dim(dim, isl_dim_in);
+ dim = isl_space_add_dims(dim, isl_dim_in, 1);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+
+ app = construct_power_components(isl_space_copy(dim), map,
+ exact, project);
+
+ isl_space_free(dim);
+
+ return app;
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ *
+ * If project is set, then we are actually interested in the transitive
+ * closure, so we can use a more relaxed exactness check.
+ * The lengths of the paths are also projected out instead of being
+ * encoded as the difference between an extra pair of final coordinates.
+ */
+static __isl_give isl_map *map_power(__isl_take isl_map *map,
+ int *exact, int project)
+{
+ struct isl_map *app = NULL;
+
+ if (exact)
+ *exact = 1;
+
+ if (!map)
+ return NULL;
+
+ isl_assert(map->ctx,
+ isl_map_dim(map, isl_dim_in) == isl_map_dim(map, isl_dim_out),
+ goto error);
+
+ app = construct_power(map, exact, project);
+
+ isl_map_free(map);
+ return app;
+error:
+ isl_map_free(map);
+ isl_map_free(app);
+ return NULL;
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * The result maps the exponent to a nested copy of the corresponding power.
+ * If the result is exact, then *exact is set to 1.
+ * map_power constructs an extended relation with the path lengths
+ * encoded as the difference between the final coordinates.
+ * In the final step, this difference is equated to an extra parameter
+ * and made positive. The extra coordinates are subsequently projected out
+ * and the parameter is turned into the domain of the result.
+ */
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact)
+{
+ isl_space *target_dim;
+ isl_space *dim;
+ isl_map *diff;
+ unsigned d;
+ unsigned param;
+
+ if (!map)
+ return NULL;
+
+ d = isl_map_dim(map, isl_dim_in);
+ param = isl_map_dim(map, isl_dim_param);
+
+ map = isl_map_compute_divs(map);
+ map = isl_map_coalesce(map);
+
+ if (isl_map_plain_is_empty(map)) {
+ map = isl_map_from_range(isl_map_wrap(map));
+ map = isl_map_add_dims(map, isl_dim_in, 1);
+ map = isl_map_set_dim_name(map, isl_dim_in, 0, "k");
+ return map;
+ }
+
+ target_dim = isl_map_get_space(map);
+ target_dim = isl_space_from_range(isl_space_wrap(target_dim));
+ target_dim = isl_space_add_dims(target_dim, isl_dim_in, 1);
+ target_dim = isl_space_set_dim_name(target_dim, isl_dim_in, 0, "k");
+
+ map = map_power(map, exact, 0);
+
+ map = isl_map_add_dims(map, isl_dim_param, 1);
+ dim = isl_map_get_space(map);
+ diff = equate_parameter_to_length(dim, param);
+ map = isl_map_intersect(map, diff);
+ map = isl_map_project_out(map, isl_dim_in, d, 1);
+ map = isl_map_project_out(map, isl_dim_out, d, 1);
+ map = isl_map_from_range(isl_map_wrap(map));
+ map = isl_map_move_dims(map, isl_dim_in, 0, isl_dim_param, param, 1);
+
+ map = isl_map_reset_space(map, target_dim);
+
+ return map;
+}
+
+/* Compute a relation that maps each element in the range of the input
+ * relation to the lengths of all paths composed of edges in the input
+ * relation that end up in the given range element.
+ * The result may be an overapproximation, in which case *exact is set to 0.
+ * The resulting relation is very similar to the power relation.
+ * The difference are that the domain has been projected out, the
+ * range has become the domain and the exponent is the range instead
+ * of a parameter.
+ */
+__isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
+ int *exact)
+{
+ isl_space *dim;
+ isl_map *diff;
+ unsigned d;
+ unsigned param;
+
+ if (!map)
+ return NULL;
+
+ d = isl_map_dim(map, isl_dim_in);
+ param = isl_map_dim(map, isl_dim_param);
+
+ map = isl_map_compute_divs(map);
+ map = isl_map_coalesce(map);
+
+ if (isl_map_plain_is_empty(map)) {
+ if (exact)
+ *exact = 1;
+ map = isl_map_project_out(map, isl_dim_out, 0, d);
+ map = isl_map_add_dims(map, isl_dim_out, 1);
+ return map;
+ }
+
+ map = map_power(map, exact, 0);
+
+ map = isl_map_add_dims(map, isl_dim_param, 1);
+ dim = isl_map_get_space(map);
+ diff = equate_parameter_to_length(dim, param);
+ map = isl_map_intersect(map, diff);
+ map = isl_map_project_out(map, isl_dim_in, 0, d + 1);
+ map = isl_map_project_out(map, isl_dim_out, d, 1);
+ map = isl_map_reverse(map);
+ map = isl_map_move_dims(map, isl_dim_out, 0, isl_dim_param, param, 1);
+
+ return map;
+}
+
+/* Check whether equality i of bset is a pure stride constraint
+ * on a single dimensions, i.e., of the form
+ *
+ * v = k e
+ *
+ * with k a constant and e an existentially quantified variable.
+ */
+static int is_eq_stride(__isl_keep isl_basic_set *bset, int i)
+{
+ unsigned nparam;
+ unsigned d;
+ unsigned n_div;
+ int pos1;
+ int pos2;
+
+ if (!bset)
+ return -1;
+
+ if (!isl_int_is_zero(bset->eq[i][0]))
+ return 0;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ d = isl_basic_set_dim(bset, isl_dim_set);
+ n_div = isl_basic_set_dim(bset, isl_dim_div);
+
+ if (isl_seq_first_non_zero(bset->eq[i] + 1, nparam) != -1)
+ return 0;
+ pos1 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam, d);
+ if (pos1 == -1)
+ return 0;
+ if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + pos1 + 1,
+ d - pos1 - 1) != -1)
+ return 0;
+
+ pos2 = isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d, n_div);
+ if (pos2 == -1)
+ return 0;
+ if (isl_seq_first_non_zero(bset->eq[i] + 1 + nparam + d + pos2 + 1,
+ n_div - pos2 - 1) != -1)
+ return 0;
+ if (!isl_int_is_one(bset->eq[i][1 + nparam + pos1]) &&
+ !isl_int_is_negone(bset->eq[i][1 + nparam + pos1]))
+ return 0;
+
+ return 1;
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ * { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive closure of this map, i.e.,
+ *
+ * { i -> j : exists k > 0:
+ * k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * the given domain and range.
+ *
+ * If with_id is set, then try to include as much of the identity mapping
+ * as possible, by computing
+ *
+ * { i -> j : exists k >= 0:
+ * k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * instead (i.e., allow k = 0).
+ *
+ * In practice, we compute the difference set
+ *
+ * delta = { j - i | i -> j in map },
+ *
+ * look for stride constraint on the individual dimensions and compute
+ * (constant) lower and upper bounds for each individual dimension,
+ * adding a constraint for each bound not equal to infinity.
+ */
+static __isl_give isl_map *box_closure_on_domain(__isl_take isl_map *map,
+ __isl_take isl_set *dom, __isl_take isl_set *ran, int with_id)
+{
+ int i;
+ int k;
+ unsigned d;
+ unsigned nparam;
+ unsigned total;
+ isl_space *dim;
+ isl_set *delta;
+ isl_map *app = NULL;
+ isl_basic_set *aff = NULL;
+ isl_basic_map *bmap = NULL;
+ isl_vec *obj = NULL;
+ isl_int opt;
+
+ isl_int_init(opt);
+
+ delta = isl_map_deltas(isl_map_copy(map));
+
+ aff = isl_set_affine_hull(isl_set_copy(delta));
+ if (!aff)
+ goto error;
+ dim = isl_map_get_space(map);
+ d = isl_space_dim(dim, isl_dim_in);
+ nparam = isl_space_dim(dim, isl_dim_param);
+ total = isl_space_dim(dim, isl_dim_all);
+ bmap = isl_basic_map_alloc_space(dim,
+ aff->n_div + 1, aff->n_div, 2 * d + 1);
+ for (i = 0; i < aff->n_div + 1; ++i) {
+ k = isl_basic_map_alloc_div(bmap);
+ if (k < 0)
+ goto error;
+ isl_int_set_si(bmap->div[k][0], 0);
+ }
+ for (i = 0; i < aff->n_eq; ++i) {
+ if (!is_eq_stride(aff, i))
+ continue;
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], 1 + nparam);
+ isl_seq_cpy(bmap->eq[k] + 1 + nparam + d,
+ aff->eq[i] + 1 + nparam, d);
+ isl_seq_neg(bmap->eq[k] + 1 + nparam,
+ aff->eq[i] + 1 + nparam, d);
+ isl_seq_cpy(bmap->eq[k] + 1 + nparam + 2 * d,
+ aff->eq[i] + 1 + nparam + d, aff->n_div);
+ isl_int_set_si(bmap->eq[k][1 + total + aff->n_div], 0);
+ }
+ obj = isl_vec_alloc(map->ctx, 1 + nparam + d);
+ if (!obj)
+ goto error;
+ isl_seq_clr(obj->el, 1 + nparam + d);
+ for (i = 0; i < d; ++ i) {
+ enum isl_lp_result res;
+
+ isl_int_set_si(obj->el[1 + nparam + i], 1);
+
+ res = isl_set_solve_lp(delta, 0, obj->el, map->ctx->one, &opt,
+ NULL, NULL);
+ if (res == isl_lp_error)
+ goto error;
+ if (res == isl_lp_ok) {
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k],
+ 1 + nparam + 2 * d + bmap->n_div);
+ isl_int_set_si(bmap->ineq[k][1 + nparam + i], -1);
+ isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], 1);
+ isl_int_neg(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
+ }
+
+ res = isl_set_solve_lp(delta, 1, obj->el, map->ctx->one, &opt,
+ NULL, NULL);
+ if (res == isl_lp_error)
+ goto error;
+ if (res == isl_lp_ok) {
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k],
+ 1 + nparam + 2 * d + bmap->n_div);
+ isl_int_set_si(bmap->ineq[k][1 + nparam + i], 1);
+ isl_int_set_si(bmap->ineq[k][1 + nparam + d + i], -1);
+ isl_int_set(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], opt);
+ }
+
+ isl_int_set_si(obj->el[1 + nparam + i], 0);
+ }
+ k = isl_basic_map_alloc_inequality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->ineq[k],
+ 1 + nparam + 2 * d + bmap->n_div);
+ if (!with_id)
+ isl_int_set_si(bmap->ineq[k][0], -1);
+ isl_int_set_si(bmap->ineq[k][1 + nparam + 2 * d + aff->n_div], 1);
+
+ app = isl_map_from_domain_and_range(dom, ran);
+
+ isl_vec_free(obj);
+ isl_basic_set_free(aff);
+ isl_map_free(map);
+ bmap = isl_basic_map_finalize(bmap);
+ isl_set_free(delta);
+ isl_int_clear(opt);
+
+ map = isl_map_from_basic_map(bmap);
+ map = isl_map_intersect(map, app);
+
+ return map;
+error:
+ isl_vec_free(obj);
+ isl_basic_map_free(bmap);
+ isl_basic_set_free(aff);
+ isl_set_free(dom);
+ isl_set_free(ran);
+ isl_map_free(map);
+ isl_set_free(delta);
+ isl_int_clear(opt);
+ return NULL;
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ * { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive closure of this map, i.e.,
+ *
+ * { i -> j : exists k > 0:
+ * k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * domain and range of the original map.
+ */
+static __isl_give isl_map *box_closure(__isl_take isl_map *map)
+{
+ isl_set *domain;
+ isl_set *range;
+
+ domain = isl_map_domain(isl_map_copy(map));
+ domain = isl_set_coalesce(domain);
+ range = isl_map_range(isl_map_copy(map));
+ range = isl_set_coalesce(range);
+
+ return box_closure_on_domain(map, domain, range, 0);
+}
+
+/* Given a map, compute the smallest superset of this map that is of the form
+ *
+ * { i -> j : L <= j - i <= U and exists a_p: j_p - i_p = M_p a_p }
+ *
+ * (where p ranges over the (non-parametric) dimensions),
+ * compute the transitive and partially reflexive closure of this map, i.e.,
+ *
+ * { i -> j : exists k >= 0:
+ * k L <= j - i <= k U and exists a: j_p - i_p = M_p a_p }
+ *
+ * and intersect domain and range of this transitive closure with
+ * the given domain.
+ */
+static __isl_give isl_map *box_closure_with_identity(__isl_take isl_map *map,
+ __isl_take isl_set *dom)
+{
+ return box_closure_on_domain(map, dom, isl_set_copy(dom), 1);
+}
+
+/* Check whether app is the transitive closure of map.
+ * In particular, check that app is acyclic and, if so,
+ * check that
+ *
+ * app \subset (map \cup (map \circ app))
+ */
+static int check_exactness_omega(__isl_keep isl_map *map,
+ __isl_keep isl_map *app)
+{
+ isl_set *delta;
+ int i;
+ int is_empty, is_exact;
+ unsigned d;
+ isl_map *test;
+
+ delta = isl_map_deltas(isl_map_copy(app));
+ d = isl_set_dim(delta, isl_dim_set);
+ for (i = 0; i < d; ++i)
+ delta = isl_set_fix_si(delta, isl_dim_set, i, 0);
+ is_empty = isl_set_is_empty(delta);
+ isl_set_free(delta);
+ if (is_empty < 0)
+ return -1;
+ if (!is_empty)
+ return 0;
+
+ test = isl_map_apply_range(isl_map_copy(app), isl_map_copy(map));
+ test = isl_map_union(test, isl_map_copy(map));
+ is_exact = isl_map_is_subset(app, test);
+ isl_map_free(test);
+
+ return is_exact;
+}
+
+/* Check if basic map M_i can be combined with all the other
+ * basic maps such that
+ *
+ * (\cup_j M_j)^+
+ *
+ * can be computed as
+ *
+ * M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
+ *
+ * In particular, check if we can compute a compact representation
+ * of
+ *
+ * M_i^* \circ M_j \circ M_i^*
+ *
+ * for each j != i.
+ * Let M_i^? be an extension of M_i^+ that allows paths
+ * of length zero, i.e., the result of box_closure(., 1).
+ * The criterion, as proposed by Kelly et al., is that
+ * id = M_i^? - M_i^+ can be represented as a basic map
+ * and that
+ *
+ * id \circ M_j \circ id = M_j
+ *
+ * for each j != i.
+ *
+ * If this function returns 1, then tc and qc are set to
+ * M_i^+ and M_i^?, respectively.
+ */
+static int can_be_split_off(__isl_keep isl_map *map, int i,
+ __isl_give isl_map **tc, __isl_give isl_map **qc)
+{
+ isl_map *map_i, *id = NULL;
+ int j = -1;
+ isl_set *C;
+
+ *tc = NULL;
+ *qc = NULL;
+
+ C = isl_set_union(isl_map_domain(isl_map_copy(map)),
+ isl_map_range(isl_map_copy(map)));
+ C = isl_set_from_basic_set(isl_set_simple_hull(C));
+ if (!C)
+ goto error;
+
+ map_i = isl_map_from_basic_map(isl_basic_map_copy(map->p[i]));
+ *tc = box_closure(isl_map_copy(map_i));
+ *qc = box_closure_with_identity(map_i, C);
+ id = isl_map_subtract(isl_map_copy(*qc), isl_map_copy(*tc));
+
+ if (!id || !*qc)
+ goto error;
+ if (id->n != 1 || (*qc)->n != 1)
+ goto done;
+
+ for (j = 0; j < map->n; ++j) {
+ isl_map *map_j, *test;
+ int is_ok;
+
+ if (i == j)
+ continue;
+ map_j = isl_map_from_basic_map(
+ isl_basic_map_copy(map->p[j]));
+ test = isl_map_apply_range(isl_map_copy(id),
+ isl_map_copy(map_j));
+ test = isl_map_apply_range(test, isl_map_copy(id));
+ is_ok = isl_map_is_equal(test, map_j);
+ isl_map_free(map_j);
+ isl_map_free(test);
+ if (is_ok < 0)
+ goto error;
+ if (!is_ok)
+ break;
+ }
+
+done:
+ isl_map_free(id);
+ if (j == map->n)
+ return 1;
+
+ isl_map_free(*qc);
+ isl_map_free(*tc);
+ *qc = NULL;
+ *tc = NULL;
+
+ return 0;
+error:
+ isl_map_free(id);
+ isl_map_free(*qc);
+ isl_map_free(*tc);
+ *qc = NULL;
+ *tc = NULL;
+ return -1;
+}
+
+static __isl_give isl_map *box_closure_with_check(__isl_take isl_map *map,
+ int *exact)
+{
+ isl_map *app;
+
+ app = box_closure(isl_map_copy(map));
+ if (exact)
+ *exact = check_exactness_omega(map, app);
+
+ isl_map_free(map);
+ return app;
+}
+
+/* Compute an overapproximation of the transitive closure of "map"
+ * using a variation of the algorithm from
+ * "Transitive Closure of Infinite Graphs and its Applications"
+ * by Kelly et al.
+ *
+ * We first check whether we can can split of any basic map M_i and
+ * compute
+ *
+ * (\cup_j M_j)^+
+ *
+ * as
+ *
+ * M_i \cup (\cup_{j \ne i} M_i^* \circ M_j \circ M_i^*)^+
+ *
+ * using a recursive call on the remaining map.
+ *
+ * If not, we simply call box_closure on the whole map.
+ */
+static __isl_give isl_map *transitive_closure_omega(__isl_take isl_map *map,
+ int *exact)
+{
+ int i, j;
+ int exact_i;
+ isl_map *app;
+
+ if (!map)
+ return NULL;
+ if (map->n == 1)
+ return box_closure_with_check(map, exact);
+
+ for (i = 0; i < map->n; ++i) {
+ int ok;
+ isl_map *qc, *tc;
+ ok = can_be_split_off(map, i, &tc, &qc);
+ if (ok < 0)
+ goto error;
+ if (!ok)
+ continue;
+
+ app = isl_map_alloc_space(isl_map_get_space(map), map->n - 1, 0);
+
+ for (j = 0; j < map->n; ++j) {
+ if (j == i)
+ continue;
+ app = isl_map_add_basic_map(app,
+ isl_basic_map_copy(map->p[j]));
+ }
+
+ app = isl_map_apply_range(isl_map_copy(qc), app);
+ app = isl_map_apply_range(app, qc);
+
+ app = isl_map_union(tc, transitive_closure_omega(app, NULL));
+ exact_i = check_exactness_omega(map, app);
+ if (exact_i == 1) {
+ if (exact)
+ *exact = exact_i;
+ isl_map_free(map);
+ return app;
+ }
+ isl_map_free(app);
+ if (exact_i < 0)
+ goto error;
+ }
+
+ return box_closure_with_check(map, exact);
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+/* Compute the transitive closure of "map", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ * Simply use map_power to compute the powers of map, but tell
+ * it to project out the lengths of the paths instead of equating
+ * the length to a parameter.
+ */
+__isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
+ int *exact)
+{
+ isl_space *target_dim;
+ int closed;
+
+ if (!map)
+ goto error;
+
+ if (map->ctx->opt->closure == ISL_CLOSURE_BOX)
+ return transitive_closure_omega(map, exact);
+
+ map = isl_map_compute_divs(map);
+ map = isl_map_coalesce(map);
+ closed = isl_map_is_transitively_closed(map);
+ if (closed < 0)
+ goto error;
+ if (closed) {
+ if (exact)
+ *exact = 1;
+ return map;
+ }
+
+ target_dim = isl_map_get_space(map);
+ map = map_power(map, exact, 1);
+ map = isl_map_reset_space(map, target_dim);
+
+ return map;
+error:
+ isl_map_free(map);
+ return NULL;
+}
+
+static int inc_count(__isl_take isl_map *map, void *user)
+{
+ int *n = user;
+
+ *n += map->n;
+
+ isl_map_free(map);
+
+ return 0;
+}
+
+static int collect_basic_map(__isl_take isl_map *map, void *user)
+{
+ int i;
+ isl_basic_map ***next = user;
+
+ for (i = 0; i < map->n; ++i) {
+ **next = isl_basic_map_copy(map->p[i]);
+ if (!**next)
+ goto error;
+ (*next)++;
+ }
+
+ isl_map_free(map);
+ return 0;
+error:
+ isl_map_free(map);
+ return -1;
+}
+
+/* Perform Floyd-Warshall on the given list of basic relations.
+ * The basic relations may live in different dimensions,
+ * but basic relations that get assigned to the diagonal of the
+ * grid have domains and ranges of the same dimension and so
+ * the standard algorithm can be used because the nested transitive
+ * closures are only applied to diagonal elements and because all
+ * compositions are peformed on relations with compatible domains and ranges.
+ */
+static __isl_give isl_union_map *union_floyd_warshall_on_list(isl_ctx *ctx,
+ __isl_keep isl_basic_map **list, int n, int *exact)
+{
+ int i, j, k;
+ int n_group;
+ int *group = NULL;
+ isl_set **set = NULL;
+ isl_map ***grid = NULL;
+ isl_union_map *app;
+
+ group = setup_groups(ctx, list, n, &set, &n_group);
+ if (!group)
+ goto error;
+
+ grid = isl_calloc_array(ctx, isl_map **, n_group);
+ if (!grid)
+ goto error;
+ for (i = 0; i < n_group; ++i) {
+ grid[i] = isl_calloc_array(ctx, isl_map *, n_group);
+ if (!grid[i])
+ goto error;
+ for (j = 0; j < n_group; ++j) {
+ isl_space *dim1, *dim2, *dim;
+ dim1 = isl_space_reverse(isl_set_get_space(set[i]));
+ dim2 = isl_set_get_space(set[j]);
+ dim = isl_space_join(dim1, dim2);
+ grid[i][j] = isl_map_empty(dim);
+ }
+ }
+
+ for (k = 0; k < n; ++k) {
+ i = group[2 * k];
+ j = group[2 * k + 1];
+ grid[i][j] = isl_map_union(grid[i][j],
+ isl_map_from_basic_map(
+ isl_basic_map_copy(list[k])));
+ }
+
+ floyd_warshall_iterate(grid, n_group, exact);
+
+ app = isl_union_map_empty(isl_map_get_space(grid[0][0]));
+
+ for (i = 0; i < n_group; ++i) {
+ for (j = 0; j < n_group; ++j)
+ app = isl_union_map_add_map(app, grid[i][j]);
+ free(grid[i]);
+ }
+ free(grid);
+
+ for (i = 0; i < 2 * n; ++i)
+ isl_set_free(set[i]);
+ free(set);
+
+ free(group);
+ return app;
+error:
+ if (grid)
+ for (i = 0; i < n_group; ++i) {
+ if (!grid[i])
+ continue;
+ for (j = 0; j < n_group; ++j)
+ isl_map_free(grid[i][j]);
+ free(grid[i]);
+ }
+ free(grid);
+ if (set) {
+ for (i = 0; i < 2 * n; ++i)
+ isl_set_free(set[i]);
+ free(set);
+ }
+ free(group);
+ return NULL;
+}
+
+/* Perform Floyd-Warshall on the given union relation.
+ * The implementation is very similar to that for non-unions.
+ * The main difference is that it is applied unconditionally.
+ * We first extract a list of basic maps from the union map
+ * and then perform the algorithm on this list.
+ */
+static __isl_give isl_union_map *union_floyd_warshall(
+ __isl_take isl_union_map *umap, int *exact)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_basic_map **list = NULL;
+ isl_basic_map **next;
+ isl_union_map *res;
+
+ n = 0;
+ if (isl_union_map_foreach_map(umap, inc_count, &n) < 0)
+ goto error;
+
+ ctx = isl_union_map_get_ctx(umap);
+ list = isl_calloc_array(ctx, isl_basic_map *, n);
+ if (!list)
+ goto error;
+
+ next = list;
+ if (isl_union_map_foreach_map(umap, collect_basic_map, &next) < 0)
+ goto error;
+
+ res = union_floyd_warshall_on_list(ctx, list, n, exact);
+
+ if (list) {
+ for (i = 0; i < n; ++i)
+ isl_basic_map_free(list[i]);
+ free(list);
+ }
+
+ isl_union_map_free(umap);
+ return res;
+error:
+ if (list) {
+ for (i = 0; i < n; ++i)
+ isl_basic_map_free(list[i]);
+ free(list);
+ }
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+/* Decompose the give union relation into strongly connected components.
+ * The implementation is essentially the same as that of
+ * construct_power_components with the major difference that all
+ * operations are performed on union maps.
+ */
+static __isl_give isl_union_map *union_components(
+ __isl_take isl_union_map *umap, int *exact)
+{
+ int i;
+ int n;
+ isl_ctx *ctx;
+ isl_basic_map **list = NULL;
+ isl_basic_map **next;
+ isl_union_map *path = NULL;
+ struct isl_tc_follows_data data;
+ struct isl_tarjan_graph *g = NULL;
+ int c, l;
+ int recheck = 0;
+
+ n = 0;
+ if (isl_union_map_foreach_map(umap, inc_count, &n) < 0)
+ goto error;
+
+ if (n == 0)
+ return umap;
+ if (n <= 1)
+ return union_floyd_warshall(umap, exact);
+
+ ctx = isl_union_map_get_ctx(umap);
+ list = isl_calloc_array(ctx, isl_basic_map *, n);
+ if (!list)
+ goto error;
+
+ next = list;
+ if (isl_union_map_foreach_map(umap, collect_basic_map, &next) < 0)
+ goto error;
+
+ data.list = list;
+ data.check_closed = 0;
+ g = isl_tarjan_graph_init(ctx, n, &basic_map_follows, &data);
+ if (!g)
+ goto error;
+
+ c = 0;
+ i = 0;
+ l = n;
+ path = isl_union_map_empty(isl_union_map_get_space(umap));
+ while (l) {
+ isl_union_map *comp;
+ isl_union_map *path_comp, *path_comb;
+ comp = isl_union_map_empty(isl_union_map_get_space(umap));
+ while (g->order[i] != -1) {
+ comp = isl_union_map_add_map(comp,
+ isl_map_from_basic_map(
+ isl_basic_map_copy(list[g->order[i]])));
+ --l;
+ ++i;
+ }
+ path_comp = union_floyd_warshall(comp, exact);
+ path_comb = isl_union_map_apply_range(isl_union_map_copy(path),
+ isl_union_map_copy(path_comp));
+ path = isl_union_map_union(path, path_comp);
+ path = isl_union_map_union(path, path_comb);
+ ++i;
+ ++c;
+ }
+
+ if (c > 1 && data.check_closed && !*exact) {
+ int closed;
+
+ closed = isl_union_map_is_transitively_closed(path);
+ if (closed < 0)
+ goto error;
+ recheck = !closed;
+ }
+
+ isl_tarjan_graph_free(g);
+
+ for (i = 0; i < n; ++i)
+ isl_basic_map_free(list[i]);
+ free(list);
+
+ if (recheck) {
+ isl_union_map_free(path);
+ return union_floyd_warshall(umap, exact);
+ }
+
+ isl_union_map_free(umap);
+
+ return path;
+error:
+ isl_tarjan_graph_free(g);
+ if (list) {
+ for (i = 0; i < n; ++i)
+ isl_basic_map_free(list[i]);
+ free(list);
+ }
+ isl_union_map_free(umap);
+ isl_union_map_free(path);
+ return NULL;
+}
+
+/* Compute the transitive closure of "umap", or an overapproximation.
+ * If the result is exact, then *exact is set to 1.
+ */
+__isl_give isl_union_map *isl_union_map_transitive_closure(
+ __isl_take isl_union_map *umap, int *exact)
+{
+ int closed;
+
+ if (!umap)
+ return NULL;
+
+ if (exact)
+ *exact = 1;
+
+ umap = isl_union_map_compute_divs(umap);
+ umap = isl_union_map_coalesce(umap);
+ closed = isl_union_map_is_transitively_closed(umap);
+ if (closed < 0)
+ goto error;
+ if (closed)
+ return umap;
+ umap = union_components(umap, exact);
+ return umap;
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+struct isl_union_power {
+ isl_union_map *pow;
+ int *exact;
+};
+
+static int power(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_power *up = user;
+
+ map = isl_map_power(map, up->exact);
+ up->pow = isl_union_map_from_map(map);
+
+ return -1;
+}
+
+/* Construct a map [x] -> [x+1], with parameters prescribed by "dim".
+ */
+static __isl_give isl_union_map *increment(__isl_take isl_space *dim)
+{
+ int k;
+ isl_basic_map *bmap;
+
+ dim = isl_space_add_dims(dim, isl_dim_in, 1);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ bmap = isl_basic_map_alloc_space(dim, 0, 1, 0);
+ k = isl_basic_map_alloc_equality(bmap);
+ if (k < 0)
+ goto error;
+ isl_seq_clr(bmap->eq[k], isl_basic_map_total_dim(bmap));
+ isl_int_set_si(bmap->eq[k][0], 1);
+ isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_in)], 1);
+ isl_int_set_si(bmap->eq[k][isl_basic_map_offset(bmap, isl_dim_out)], -1);
+ return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+error:
+ isl_basic_map_free(bmap);
+ return NULL;
+}
+
+/* Construct a map [[x]->[y]] -> [y-x], with parameters prescribed by "dim".
+ */
+static __isl_give isl_union_map *deltas_map(__isl_take isl_space *dim)
+{
+ isl_basic_map *bmap;
+
+ dim = isl_space_add_dims(dim, isl_dim_in, 1);
+ dim = isl_space_add_dims(dim, isl_dim_out, 1);
+ bmap = isl_basic_map_universe(dim);
+ bmap = isl_basic_map_deltas_map(bmap);
+
+ return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+}
+
+/* Compute the positive powers of "map", or an overapproximation.
+ * The result maps the exponent to a nested copy of the corresponding power.
+ * If the result is exact, then *exact is set to 1.
+ */
+__isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
+ int *exact)
+{
+ int n;
+ isl_union_map *inc;
+ isl_union_map *dm;
+
+ if (!umap)
+ return NULL;
+ n = isl_union_map_n_map(umap);
+ if (n == 0)
+ return umap;
+ if (n == 1) {
+ struct isl_union_power up = { NULL, exact };
+ isl_union_map_foreach_map(umap, &power, &up);
+ isl_union_map_free(umap);
+ return up.pow;
+ }
+ inc = increment(isl_union_map_get_space(umap));
+ umap = isl_union_map_product(inc, umap);
+ umap = isl_union_map_transitive_closure(umap, exact);
+ umap = isl_union_map_zip(umap);
+ dm = deltas_map(isl_union_map_get_space(umap));
+ umap = isl_union_map_apply_domain(umap, dm);
+
+ return umap;
+}
+
+#undef TYPE
+#define TYPE isl_map
+#include "isl_power_templ.c"
+
+#undef TYPE
+#define TYPE isl_union_map
+#include "isl_power_templ.c"
diff --git a/polly/lib/External/isl/isl_union_map.c b/polly/lib/External/isl/isl_union_map.c
new file mode 100644
index 00000000000..be39088c8a9
--- /dev/null
+++ b/polly/lib/External/isl/isl_union_map.c
@@ -0,0 +1,3373 @@
+/*
+ * Copyright 2010-2011 INRIA Saclay
+ * Copyright 2013-2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA 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 Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
+ */
+
+#define ISL_DIM_H
+#include <isl_map_private.h>
+#include <isl/ctx.h>
+#include <isl/hash.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl/set.h>
+#include <isl_space_private.h>
+#include <isl_union_map_private.h>
+#include <isl/union_set.h>
+#include <isl/deprecated/union_map_int.h>
+
+/* Return the number of parameters of "umap", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type)
+{
+ if (!umap)
+ return 0;
+
+ if (type != isl_dim_param)
+ isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+ "can only reference parameters", return 0);
+
+ return isl_space_dim(umap->dim, type);
+}
+
+/* Return the number of parameters of "uset", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+ enum isl_dim_type type)
+{
+ return isl_union_map_dim(uset, type);
+}
+
+/* Return the id of the specified dimension.
+ */
+__isl_give isl_id *isl_union_map_get_dim_id(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned pos)
+{
+ if (!umap)
+ return NULL;
+
+ if (type != isl_dim_param)
+ isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+ "can only reference parameters", return NULL);
+
+ return isl_space_get_dim_id(umap->dim, type, pos);
+}
+
+/* Is this union set a parameter domain?
+ */
+int isl_union_set_is_params(__isl_keep isl_union_set *uset)
+{
+ isl_set *set;
+ int params;
+
+ if (!uset)
+ return -1;
+ if (uset->table.n != 1)
+ return 0;
+
+ set = isl_set_from_union_set(isl_union_set_copy(uset));
+ params = isl_set_is_params(set);
+ isl_set_free(set);
+ return params;
+}
+
+static __isl_give isl_union_map *isl_union_map_alloc(
+ __isl_take isl_space *space, int size)
+{
+ isl_union_map *umap;
+
+ space = isl_space_params(space);
+ if (!space)
+ return NULL;
+
+ umap = isl_calloc_type(space->ctx, isl_union_map);
+ if (!umap) {
+ isl_space_free(space);
+ return NULL;
+ }
+
+ umap->ref = 1;
+ umap->dim = space;
+ if (isl_hash_table_init(space->ctx, &umap->table, size) < 0)
+ return isl_union_map_free(umap);
+
+ return umap;
+}
+
+__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *dim)
+{
+ return isl_union_map_alloc(dim, 16);
+}
+
+__isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *dim)
+{
+ return isl_union_map_empty(dim);
+}
+
+isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap)
+{
+ return umap ? umap->dim->ctx : NULL;
+}
+
+isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset)
+{
+ return uset ? uset->dim->ctx : NULL;
+}
+
+__isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap)
+{
+ if (!umap)
+ return NULL;
+ return isl_space_copy(umap->dim);
+}
+
+/* Return the position of the parameter with the given name
+ * in "umap".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, const char *name)
+{
+ if (!umap)
+ return -1;
+ return isl_space_find_dim_by_name(umap->dim, type, name);
+}
+
+__isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset)
+{
+ return isl_union_map_get_space(uset);
+}
+
+static int free_umap_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_map_free(map);
+ return 0;
+}
+
+static int add_map(__isl_take isl_map *map, void *user)
+{
+ isl_union_map **umap = (isl_union_map **)user;
+
+ *umap = isl_union_map_add_map(*umap, map);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_dup(__isl_keep isl_union_map *umap)
+{
+ isl_union_map *dup;
+
+ if (!umap)
+ return NULL;
+
+ dup = isl_union_map_empty(isl_space_copy(umap->dim));
+ if (isl_union_map_foreach_map(umap, &add_map, &dup) < 0)
+ goto error;
+ return dup;
+error:
+ isl_union_map_free(dup);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_cow(__isl_take isl_union_map *umap)
+{
+ if (!umap)
+ return NULL;
+
+ if (umap->ref == 1)
+ return umap;
+ umap->ref--;
+ return isl_union_map_dup(umap);
+}
+
+struct isl_union_align {
+ isl_reordering *exp;
+ isl_union_map *res;
+};
+
+static int align_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_reordering *exp;
+ struct isl_union_align *data = user;
+
+ exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+ isl_map_get_space(map));
+
+ data->res = isl_union_map_add_map(data->res,
+ isl_map_realign(isl_map_copy(map), exp));
+
+ return 0;
+}
+
+/* Align the parameters of umap along those of model.
+ * The result has the parameters of model first, in the same order
+ * as they appear in model, followed by any remaining parameters of
+ * umap that do not appear in model.
+ */
+__isl_give isl_union_map *isl_union_map_align_params(
+ __isl_take isl_union_map *umap, __isl_take isl_space *model)
+{
+ struct isl_union_align data = { NULL, NULL };
+
+ if (!umap || !model)
+ goto error;
+
+ if (isl_space_match(umap->dim, isl_dim_param, model, isl_dim_param)) {
+ isl_space_free(model);
+ return umap;
+ }
+
+ model = isl_space_params(model);
+ data.exp = isl_parameter_alignment_reordering(umap->dim, model);
+ if (!data.exp)
+ goto error;
+
+ data.res = isl_union_map_alloc(isl_space_copy(data.exp->dim),
+ umap->table.n);
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &align_entry, &data) < 0)
+ goto error;
+
+ isl_reordering_free(data.exp);
+ isl_union_map_free(umap);
+ isl_space_free(model);
+ return data.res;
+error:
+ isl_reordering_free(data.exp);
+ isl_union_map_free(umap);
+ isl_union_map_free(data.res);
+ isl_space_free(model);
+ return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_align_params(
+ __isl_take isl_union_set *uset, __isl_take isl_space *model)
+{
+ return isl_union_map_align_params(uset, model);
+}
+
+__isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2)
+{
+ umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+ umap1 = isl_union_map_cow(umap1);
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ if (isl_union_map_foreach_map(umap2, &add_map, &umap1) < 0)
+ goto error;
+
+ isl_union_map_free(umap2);
+
+ return umap1;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2)
+{
+ return isl_union_map_union(uset1, uset2);
+}
+
+__isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap)
+{
+ if (!umap)
+ return NULL;
+
+ umap->ref++;
+ return umap;
+}
+
+__isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset)
+{
+ return isl_union_map_copy(uset);
+}
+
+__isl_null isl_union_map *isl_union_map_free(__isl_take isl_union_map *umap)
+{
+ if (!umap)
+ return NULL;
+
+ if (--umap->ref > 0)
+ return NULL;
+
+ isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &free_umap_entry, NULL);
+ isl_hash_table_clear(&umap->table);
+ isl_space_free(umap->dim);
+ free(umap);
+ return NULL;
+}
+
+__isl_null isl_union_set *isl_union_set_free(__isl_take isl_union_set *uset)
+{
+ return isl_union_map_free(uset);
+}
+
+static int has_dim(const void *entry, const void *val)
+{
+ isl_map *map = (isl_map *)entry;
+ isl_space *dim = (isl_space *)val;
+
+ return isl_space_is_equal(map->dim, dim);
+}
+
+__isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
+ __isl_take isl_map *map)
+{
+ uint32_t hash;
+ struct isl_hash_table_entry *entry;
+
+ if (!map || !umap)
+ goto error;
+
+ if (isl_map_plain_is_empty(map)) {
+ isl_map_free(map);
+ return umap;
+ }
+
+ if (!isl_space_match(map->dim, isl_dim_param, umap->dim, isl_dim_param)) {
+ umap = isl_union_map_align_params(umap, isl_map_get_space(map));
+ map = isl_map_align_params(map, isl_union_map_get_space(umap));
+ }
+
+ umap = isl_union_map_cow(umap);
+
+ if (!map || !umap)
+ goto error;
+
+ hash = isl_space_get_hash(map->dim);
+ entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+ &has_dim, map->dim, 1);
+ if (!entry)
+ goto error;
+
+ if (!entry->data)
+ entry->data = map;
+ else {
+ entry->data = isl_map_union(entry->data, isl_map_copy(map));
+ if (!entry->data)
+ goto error;
+ isl_map_free(map);
+ }
+
+ return umap;
+error:
+ isl_map_free(map);
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+__isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
+ __isl_take isl_set *set)
+{
+ return isl_union_map_add_map(uset, (isl_map *)set);
+}
+
+__isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map)
+{
+ isl_space *dim;
+ isl_union_map *umap;
+
+ if (!map)
+ return NULL;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_params(dim);
+ umap = isl_union_map_empty(dim);
+ umap = isl_union_map_add_map(umap, map);
+
+ return umap;
+}
+
+__isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set)
+{
+ return isl_union_map_from_map((isl_map *)set);
+}
+
+__isl_give isl_union_map *isl_union_map_from_basic_map(
+ __isl_take isl_basic_map *bmap)
+{
+ return isl_union_map_from_map(isl_map_from_basic_map(bmap));
+}
+
+__isl_give isl_union_set *isl_union_set_from_basic_set(
+ __isl_take isl_basic_set *bset)
+{
+ return isl_union_map_from_basic_map(bset);
+}
+
+struct isl_union_map_foreach_data
+{
+ int (*fn)(__isl_take isl_map *map, void *user);
+ void *user;
+};
+
+static int call_on_copy(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ struct isl_union_map_foreach_data *data;
+ data = (struct isl_union_map_foreach_data *)user;
+
+ return data->fn(isl_map_copy(map), data->user);
+}
+
+int isl_union_map_n_map(__isl_keep isl_union_map *umap)
+{
+ return umap ? umap->table.n : 0;
+}
+
+int isl_union_set_n_set(__isl_keep isl_union_set *uset)
+{
+ return uset ? uset->table.n : 0;
+}
+
+int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
+ int (*fn)(__isl_take isl_map *map, void *user), void *user)
+{
+ struct isl_union_map_foreach_data data = { fn, user };
+
+ if (!umap)
+ return -1;
+
+ return isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &call_on_copy, &data);
+}
+
+static int copy_map(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_map **map_p = user;
+
+ *map_p = isl_map_copy(map);
+
+ return -1;
+}
+
+__isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap)
+{
+ isl_ctx *ctx;
+ isl_map *map = NULL;
+
+ if (!umap)
+ return NULL;
+ ctx = isl_union_map_get_ctx(umap);
+ if (umap->table.n != 1)
+ isl_die(ctx, isl_error_invalid,
+ "union map needs to contain elements in exactly "
+ "one space", goto error);
+
+ isl_hash_table_foreach(ctx, &umap->table, &copy_map, &map);
+
+ isl_union_map_free(umap);
+
+ return map;
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+__isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset)
+{
+ return isl_map_from_union_map(uset);
+}
+
+/* Extract the map in "umap" that lives in the given space (ignoring
+ * parameters).
+ */
+__isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
+ __isl_take isl_space *space)
+{
+ uint32_t hash;
+ struct isl_hash_table_entry *entry;
+
+ space = isl_space_drop_dims(space, isl_dim_param,
+ 0, isl_space_dim(space, isl_dim_param));
+ space = isl_space_align_params(space, isl_union_map_get_space(umap));
+ if (!umap || !space)
+ goto error;
+
+ hash = isl_space_get_hash(space);
+ entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+ &has_dim, space, 0);
+ if (!entry)
+ return isl_map_empty(space);
+ isl_space_free(space);
+ return isl_map_copy(entry->data);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+__isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
+ __isl_take isl_space *dim)
+{
+ return (isl_set *)isl_union_map_extract_map(uset, dim);
+}
+
+/* Check if umap contains a map in the given space.
+ */
+__isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
+ __isl_keep isl_space *dim)
+{
+ uint32_t hash;
+ struct isl_hash_table_entry *entry;
+
+ if (!umap || !dim)
+ return -1;
+
+ hash = isl_space_get_hash(dim);
+ entry = isl_hash_table_find(umap->dim->ctx, &umap->table, hash,
+ &has_dim, dim, 0);
+ return !!entry;
+}
+
+__isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
+ __isl_keep isl_space *dim)
+{
+ return isl_union_map_contains(uset, dim);
+}
+
+int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
+ int (*fn)(__isl_take isl_set *set, void *user), void *user)
+{
+ return isl_union_map_foreach_map(uset,
+ (int(*)(__isl_take isl_map *, void*))fn, user);
+}
+
+struct isl_union_set_foreach_point_data {
+ int (*fn)(__isl_take isl_point *pnt, void *user);
+ void *user;
+};
+
+static int foreach_point(__isl_take isl_set *set, void *user)
+{
+ struct isl_union_set_foreach_point_data *data = user;
+ int r;
+
+ r = isl_set_foreach_point(set, data->fn, data->user);
+ isl_set_free(set);
+
+ return r;
+}
+
+int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
+ int (*fn)(__isl_take isl_point *pnt, void *user), void *user)
+{
+ struct isl_union_set_foreach_point_data data = { fn, user };
+ return isl_union_set_foreach_set(uset, &foreach_point, &data);
+}
+
+struct isl_union_map_gen_bin_data {
+ isl_union_map *umap2;
+ isl_union_map *res;
+};
+
+static int subtract_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_map *map = *entry;
+
+ hash = isl_space_get_hash(map->dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, map->dim, 0);
+ map = isl_map_copy(map);
+ if (entry2) {
+ int empty;
+ map = isl_map_subtract(map, isl_map_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+ }
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+static __isl_give isl_union_map *gen_bin_op(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2, int (*fn)(void **, void *))
+{
+ struct isl_union_map_gen_bin_data data = { NULL, NULL };
+
+ umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ data.umap2 = umap2;
+ data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+ umap1->table.n);
+ if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+ fn, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return data.res;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ isl_union_map_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_subtract(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return gen_bin_op(umap1, umap2, &subtract_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_subtract(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ return isl_union_map_subtract(uset1, uset2);
+}
+
+struct isl_union_map_gen_bin_set_data {
+ isl_set *set;
+ isl_union_map *res;
+};
+
+static int intersect_params_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_set_data *data = user;
+ isl_map *map = *entry;
+ int empty;
+
+ map = isl_map_copy(map);
+ map = isl_map_intersect_params(map, isl_set_copy(data->set));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+static __isl_give isl_union_map *gen_bin_set_op(__isl_take isl_union_map *umap,
+ __isl_take isl_set *set, int (*fn)(void **, void *))
+{
+ struct isl_union_map_gen_bin_set_data data = { NULL, NULL };
+
+ umap = isl_union_map_align_params(umap, isl_set_get_space(set));
+ set = isl_set_align_params(set, isl_union_map_get_space(umap));
+
+ if (!umap || !set)
+ goto error;
+
+ data.set = set;
+ data.res = isl_union_map_alloc(isl_space_copy(umap->dim),
+ umap->table.n);
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ fn, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap);
+ isl_set_free(set);
+ return data.res;
+error:
+ isl_union_map_free(umap);
+ isl_set_free(set);
+ isl_union_map_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+ return gen_bin_set_op(umap, set, &intersect_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_intersect_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+ return isl_union_map_intersect_params(uset, set);
+}
+
+static __isl_give isl_union_map *union_map_intersect_params(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return isl_union_map_intersect_params(umap,
+ isl_set_from_union_set(uset));
+}
+
+static __isl_give isl_union_map *union_map_gist_params(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return isl_union_map_gist_params(umap, isl_set_from_union_set(uset));
+}
+
+struct isl_union_map_match_bin_data {
+ isl_union_map *umap2;
+ isl_union_map *res;
+ __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*);
+};
+
+static int match_bin_entry(void **entry, void *user)
+{
+ struct isl_union_map_match_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_map *map = *entry;
+ int empty;
+
+ hash = isl_space_get_hash(map->dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, map->dim, 0);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = data->fn(map, isl_map_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+static __isl_give isl_union_map *match_bin_op(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2,
+ __isl_give isl_map *(*fn)(__isl_take isl_map*, __isl_take isl_map*))
+{
+ struct isl_union_map_match_bin_data data = { NULL, NULL, fn };
+
+ umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ data.umap2 = umap2;
+ data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+ umap1->table.n);
+ if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+ &match_bin_entry, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return data.res;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ isl_union_map_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return match_bin_op(umap1, umap2, &isl_map_intersect);
+}
+
+/* Compute the intersection of the two union_sets.
+ * As a special case, if exactly one of the two union_sets
+ * is a parameter domain, then intersect the parameter domain
+ * of the other one with this set.
+ */
+__isl_give isl_union_set *isl_union_set_intersect(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ int p1, p2;
+
+ p1 = isl_union_set_is_params(uset1);
+ p2 = isl_union_set_is_params(uset2);
+ if (p1 < 0 || p2 < 0)
+ goto error;
+ if (!p1 && p2)
+ return union_map_intersect_params(uset1, uset2);
+ if (p1 && !p2)
+ return union_map_intersect_params(uset2, uset1);
+ return isl_union_map_intersect(uset1, uset2);
+error:
+ isl_union_set_free(uset1);
+ isl_union_set_free(uset2);
+ return NULL;
+}
+
+static int gist_params_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_set_data *data = user;
+ isl_map *map = *entry;
+ int empty;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_params(map, isl_set_copy(data->set));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_gist_params(
+ __isl_take isl_union_map *umap, __isl_take isl_set *set)
+{
+ return gen_bin_set_op(umap, set, &gist_params_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_gist_params(
+ __isl_take isl_union_set *uset, __isl_take isl_set *set)
+{
+ return isl_union_map_gist_params(uset, set);
+}
+
+__isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
+ __isl_take isl_union_map *context)
+{
+ return match_bin_op(umap, context, &isl_map_gist);
+}
+
+__isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
+ __isl_take isl_union_set *context)
+{
+ if (isl_union_set_is_params(context))
+ return union_map_gist_params(uset, context);
+ return isl_union_map_gist(uset, context);
+}
+
+static __isl_give isl_map *lex_le_set(__isl_take isl_map *set1,
+ __isl_take isl_map *set2)
+{
+ return isl_set_lex_le_set((isl_set *)set1, (isl_set *)set2);
+}
+
+static __isl_give isl_map *lex_lt_set(__isl_take isl_map *set1,
+ __isl_take isl_map *set2)
+{
+ return isl_set_lex_lt_set((isl_set *)set1, (isl_set *)set2);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_lt_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ return match_bin_op(uset1, uset2, &lex_lt_set);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_le_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ return match_bin_op(uset1, uset2, &lex_le_set);
+}
+
+__isl_give isl_union_map *isl_union_set_lex_gt_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ return isl_union_map_reverse(isl_union_set_lex_lt_union_set(uset2, uset1));
+}
+
+__isl_give isl_union_map *isl_union_set_lex_ge_union_set(
+ __isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2)
+{
+ return isl_union_map_reverse(isl_union_set_lex_le_union_set(uset2, uset1));
+}
+
+__isl_give isl_union_map *isl_union_map_lex_gt_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return isl_union_map_reverse(isl_union_map_lex_lt_union_map(umap2, umap1));
+}
+
+__isl_give isl_union_map *isl_union_map_lex_ge_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return isl_union_map_reverse(isl_union_map_lex_le_union_map(umap2, umap1));
+}
+
+static int intersect_domain_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *dim;
+ isl_map *map = *entry;
+ int empty;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_domain(dim);
+ hash = isl_space_get_hash(dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, dim, 0);
+ isl_space_free(dim);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_intersect_domain(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Intersect the domain of "umap" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "umap" with this set.
+ */
+__isl_give isl_union_map *isl_union_map_intersect_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ if (isl_union_set_is_params(uset))
+ return union_map_intersect_params(umap, uset);
+ return gen_bin_op(umap, uset, &intersect_domain_entry);
+}
+
+/* Remove the elements of data->umap2 from the domain of *entry
+ * and add the result to data->res.
+ */
+static int subtract_domain_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *dim;
+ isl_map *map = *entry;
+ int empty;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_domain(dim);
+ hash = isl_space_get_hash(dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, dim, 0);
+ isl_space_free(dim);
+
+ map = isl_map_copy(map);
+
+ if (!entry2) {
+ data->res = isl_union_map_add_map(data->res, map);
+ return 0;
+ }
+
+ map = isl_map_subtract_domain(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Remove the elements of "uset" from the domain of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_subtract_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *dom)
+{
+ return gen_bin_op(umap, dom, &subtract_domain_entry);
+}
+
+/* Remove the elements of data->umap2 from the range of *entry
+ * and add the result to data->res.
+ */
+static int subtract_range_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *space;
+ isl_map *map = *entry;
+ int empty;
+
+ space = isl_map_get_space(map);
+ space = isl_space_range(space);
+ hash = isl_space_get_hash(space);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, space, 0);
+ isl_space_free(space);
+
+ map = isl_map_copy(map);
+
+ if (!entry2) {
+ data->res = isl_union_map_add_map(data->res, map);
+ return 0;
+ }
+
+ map = isl_map_subtract_range(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Remove the elements of "uset" from the range of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_subtract_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *dom)
+{
+ return gen_bin_op(umap, dom, &subtract_range_entry);
+}
+
+static int gist_domain_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *dim;
+ isl_map *map = *entry;
+ int empty;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_domain(dim);
+ hash = isl_space_get_hash(dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, dim, 0);
+ isl_space_free(dim);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_domain(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the gist of "umap" with respect to the domain "uset".
+ * If "uset" is a parameters domain, then compute the gist
+ * with respect to this parameter domain.
+ */
+__isl_give isl_union_map *isl_union_map_gist_domain(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ if (isl_union_set_is_params(uset))
+ return union_map_gist_params(umap, uset);
+ return gen_bin_op(umap, uset, &gist_domain_entry);
+}
+
+static int gist_range_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *space;
+ isl_map *map = *entry;
+ int empty;
+
+ space = isl_map_get_space(map);
+ space = isl_space_range(space);
+ hash = isl_space_get_hash(space);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, space, 0);
+ isl_space_free(space);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_gist_range(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the gist of "umap" with respect to the range "uset".
+ */
+__isl_give isl_union_map *isl_union_map_gist_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return gen_bin_op(umap, uset, &gist_range_entry);
+}
+
+static int intersect_range_entry(void **entry, void *user)
+{
+ struct isl_union_map_gen_bin_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_space *dim;
+ isl_map *map = *entry;
+ int empty;
+
+ dim = isl_map_get_space(map);
+ dim = isl_space_range(dim);
+ hash = isl_space_get_hash(dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, dim, 0);
+ isl_space_free(dim);
+ if (!entry2)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = isl_map_intersect_range(map, isl_set_copy(entry2->data));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0) {
+ isl_map_free(map);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_intersect_range(
+ __isl_take isl_union_map *umap, __isl_take isl_union_set *uset)
+{
+ return gen_bin_op(umap, uset, &intersect_range_entry);
+}
+
+struct isl_union_map_bin_data {
+ isl_union_map *umap2;
+ isl_union_map *res;
+ isl_map *map;
+ int (*fn)(void **entry, void *user);
+};
+
+static int apply_range_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+ int empty;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+ map2->dim, isl_dim_in))
+ return 0;
+
+ map2 = isl_map_apply_range(isl_map_copy(data->map), isl_map_copy(map2));
+
+ empty = isl_map_is_empty(map2);
+ if (empty < 0) {
+ isl_map_free(map2);
+ return -1;
+ }
+ if (empty) {
+ isl_map_free(map2);
+ return 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+static int bin_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map = *entry;
+
+ data->map = map;
+ if (isl_hash_table_foreach(data->umap2->dim->ctx, &data->umap2->table,
+ data->fn, data) < 0)
+ return -1;
+
+ return 0;
+}
+
+static __isl_give isl_union_map *bin_op(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2, int (*fn)(void **entry, void *user))
+{
+ struct isl_union_map_bin_data data = { NULL, NULL, NULL, fn };
+
+ umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ data.umap2 = umap2;
+ data.res = isl_union_map_alloc(isl_space_copy(umap1->dim),
+ umap1->table.n);
+ if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+ &bin_entry, &data) < 0)
+ goto error;
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return data.res;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ isl_union_map_free(data.res);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_apply_range(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &apply_range_entry);
+}
+
+__isl_give isl_union_map *isl_union_map_apply_domain(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ umap1 = isl_union_map_reverse(umap1);
+ umap1 = isl_union_map_apply_range(umap1, umap2);
+ return isl_union_map_reverse(umap1);
+}
+
+__isl_give isl_union_set *isl_union_set_apply(
+ __isl_take isl_union_set *uset, __isl_take isl_union_map *umap)
+{
+ return isl_union_map_apply_range(uset, umap);
+}
+
+static int map_lex_lt_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+ map2->dim, isl_dim_out))
+ return 0;
+
+ map2 = isl_map_lex_lt_map(isl_map_copy(data->map), isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_lex_lt_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &map_lex_lt_entry);
+}
+
+static int map_lex_le_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+ map2->dim, isl_dim_out))
+ return 0;
+
+ map2 = isl_map_lex_le_map(isl_map_copy(data->map), isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_lex_le_union_map(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &map_lex_le_entry);
+}
+
+static int product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ map2 = isl_map_product(isl_map_copy(data->map), isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &product_entry);
+}
+
+static int set_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_set *set2 = *entry;
+
+ set2 = isl_set_product(isl_set_copy(data->map), isl_set_copy(set2));
+
+ data->res = isl_union_set_add_set(data->res, set2);
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
+ __isl_take isl_union_set *uset2)
+{
+ return bin_op(uset1, uset2, &set_product_entry);
+}
+
+static int domain_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+ map2->dim, isl_dim_out))
+ return 0;
+
+ map2 = isl_map_domain_product(isl_map_copy(data->map),
+ isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+/* Given two maps A -> B and C -> D, construct a map [A -> C] -> (B * D)
+ */
+__isl_give isl_union_map *isl_union_map_domain_product(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &domain_product_entry);
+}
+
+static int range_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_in,
+ map2->dim, isl_dim_in))
+ return 0;
+
+ map2 = isl_map_range_product(isl_map_copy(data->map),
+ isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_range_product(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &range_product_entry);
+}
+
+static int flat_range_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_in,
+ map2->dim, isl_dim_in))
+ return 0;
+
+ map2 = isl_map_flat_range_product(isl_map_copy(data->map),
+ isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_flat_range_product(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &flat_range_product_entry);
+}
+
+static __isl_give isl_union_set *cond_un_op(__isl_take isl_union_map *umap,
+ int (*fn)(void **, void *))
+{
+ isl_union_set *res;
+
+ if (!umap)
+ return NULL;
+
+ res = isl_union_map_alloc(isl_space_copy(umap->dim), umap->table.n);
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, &res) < 0)
+ goto error;
+
+ isl_union_map_free(umap);
+ return res;
+error:
+ isl_union_map_free(umap);
+ isl_union_set_free(res);
+ return NULL;
+}
+
+static int from_range_entry(void **entry, void *user)
+{
+ isl_map *set = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_from_range(isl_set_copy(set)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_from_range(
+ __isl_take isl_union_set *uset)
+{
+ return cond_un_op(uset, &from_range_entry);
+}
+
+__isl_give isl_union_map *isl_union_map_from_domain(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_reverse(isl_union_map_from_range(uset));
+}
+
+__isl_give isl_union_map *isl_union_map_from_domain_and_range(
+ __isl_take isl_union_set *domain, __isl_take isl_union_set *range)
+{
+ return isl_union_map_apply_range(isl_union_map_from_domain(domain),
+ isl_union_map_from_range(range));
+}
+
+static __isl_give isl_union_map *un_op(__isl_take isl_union_map *umap,
+ int (*fn)(void **, void *))
+{
+ umap = isl_union_map_cow(umap);
+ if (!umap)
+ return NULL;
+
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table, fn, NULL) < 0)
+ goto error;
+
+ return umap;
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+static int affine_entry(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_from_basic_map(isl_map_affine_hull(*map));
+
+ return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_affine_hull(
+ __isl_take isl_union_map *umap)
+{
+ return un_op(umap, &affine_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_affine_hull(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_affine_hull(uset);
+}
+
+static int polyhedral_entry(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_from_basic_map(isl_map_polyhedral_hull(*map));
+
+ return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_polyhedral_hull(
+ __isl_take isl_union_map *umap)
+{
+ return un_op(umap, &polyhedral_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_polyhedral_hull(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_polyhedral_hull(uset);
+}
+
+static int simple_entry(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_from_basic_map(isl_map_simple_hull(*map));
+
+ return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_simple_hull(
+ __isl_take isl_union_map *umap)
+{
+ return un_op(umap, &simple_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_simple_hull(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_simple_hull(uset);
+}
+
+static int inplace_entry(void **entry, void *user)
+{
+ __isl_give isl_map *(*fn)(__isl_take isl_map *);
+ isl_map **map = (isl_map **)entry;
+ isl_map *copy;
+
+ fn = *(__isl_give isl_map *(**)(__isl_take isl_map *)) user;
+ copy = fn(isl_map_copy(*map));
+ if (!copy)
+ return -1;
+
+ isl_map_free(*map);
+ *map = copy;
+
+ return 0;
+}
+
+static __isl_give isl_union_map *inplace(__isl_take isl_union_map *umap,
+ __isl_give isl_map *(*fn)(__isl_take isl_map *))
+{
+ if (!umap)
+ return NULL;
+
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &inplace_entry, &fn) < 0)
+ goto error;
+
+ return umap;
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+__isl_give isl_union_map *isl_union_map_coalesce(
+ __isl_take isl_union_map *umap)
+{
+ return inplace(umap, &isl_map_coalesce);
+}
+
+__isl_give isl_union_set *isl_union_set_coalesce(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_coalesce(uset);
+}
+
+__isl_give isl_union_map *isl_union_map_detect_equalities(
+ __isl_take isl_union_map *umap)
+{
+ return inplace(umap, &isl_map_detect_equalities);
+}
+
+__isl_give isl_union_set *isl_union_set_detect_equalities(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_detect_equalities(uset);
+}
+
+__isl_give isl_union_map *isl_union_map_compute_divs(
+ __isl_take isl_union_map *umap)
+{
+ return inplace(umap, &isl_map_compute_divs);
+}
+
+__isl_give isl_union_set *isl_union_set_compute_divs(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_compute_divs(uset);
+}
+
+static int lexmin_entry(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_lexmin(*map);
+
+ return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_lexmin(
+ __isl_take isl_union_map *umap)
+{
+ return un_op(umap, &lexmin_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_lexmin(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_lexmin(uset);
+}
+
+static int lexmax_entry(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_lexmax(*map);
+
+ return *map ? 0 : -1;
+}
+
+__isl_give isl_union_map *isl_union_map_lexmax(
+ __isl_take isl_union_map *umap)
+{
+ return un_op(umap, &lexmax_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_lexmax(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_lexmax(uset);
+}
+
+static int universe_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ map = isl_map_universe(isl_map_get_space(map));
+ *res = isl_union_map_add_map(*res, map);
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_universe(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &universe_entry);
+}
+
+__isl_give isl_union_set *isl_union_set_universe(__isl_take isl_union_set *uset)
+{
+ return isl_union_map_universe(uset);
+}
+
+static int reverse_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ *res = isl_union_map_add_map(*res, isl_map_reverse(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &reverse_entry);
+}
+
+static int params_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_map_params(isl_map_copy(map)));
+
+ return 0;
+}
+
+/* Compute the parameter domain of the given union map.
+ */
+__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap)
+{
+ int empty;
+
+ empty = isl_union_map_is_empty(umap);
+ if (empty < 0)
+ goto error;
+ if (empty) {
+ isl_space *space;
+ space = isl_union_map_get_space(umap);
+ isl_union_map_free(umap);
+ return isl_set_empty(space);
+ }
+ return isl_set_from_union_set(cond_un_op(umap, &params_entry));
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+/* Compute the parameter domain of the given union set.
+ */
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset)
+{
+ return isl_union_map_params(uset);
+}
+
+static int domain_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_map_domain(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &domain_entry);
+}
+
+static int range_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_map_range(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &range_entry);
+}
+
+static int domain_map_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_domain_map(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_domain_map(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &domain_map_entry);
+}
+
+static int range_map_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_range_map(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_range_map(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &range_map_entry);
+}
+
+/* Check if "set" is of the form A[B -> C].
+ * If so, add A[B -> C] -> B to "res".
+ */
+static int wrapped_domain_map_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_set **res = user;
+ int wrapping;
+
+ wrapping = isl_set_is_wrapping(set);
+ if (wrapping < 0)
+ return -1;
+ if (!wrapping)
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_set_wrapped_domain_map(isl_set_copy(set)));
+
+ return 0;
+}
+
+/* Given a collection of wrapped maps of the form A[B -> C],
+ * return the collection of maps A[B -> C] -> B.
+ */
+__isl_give isl_union_map *isl_union_set_wrapped_domain_map(
+ __isl_take isl_union_set *uset)
+{
+ return cond_un_op(uset, &wrapped_domain_map_entry);
+}
+
+static int deltas_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ map->dim, isl_dim_out))
+ return 0;
+
+ *res = isl_union_set_add_set(*res, isl_map_deltas(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &deltas_entry);
+}
+
+static int deltas_map_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ map->dim, isl_dim_out))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_deltas_map(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_deltas_map(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &deltas_map_entry);
+}
+
+static int identity_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_map **res = user;
+
+ *res = isl_union_map_add_map(*res, isl_set_identity(isl_set_copy(set)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset)
+{
+ return cond_un_op(uset, &identity_entry);
+}
+
+/* If "map" is of the form [A -> B] -> C, then add A -> C to "res".
+ */
+static int domain_factor_domain_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_domain_is_wrapping(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_domain_factor_domain(isl_map_copy(map)));
+
+ return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> C,
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_domain_factor_domain(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &domain_factor_domain_entry);
+}
+
+/* If "map" is of the form [A -> B] -> C, then add B -> C to "res".
+ */
+static int domain_factor_range_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_domain_is_wrapping(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_domain_factor_range(isl_map_copy(map)));
+
+ return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> C,
+ * construct the map B -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_domain_factor_range(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &domain_factor_range_entry);
+}
+
+/* If "map" is of the form A -> [B -> C], then add A -> C to "res".
+ */
+static int range_factor_range_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_range_is_wrapping(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_range_factor_range(isl_map_copy(map)));
+
+ return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form A -> [B -> C],
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_range_factor_range(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &range_factor_range_entry);
+}
+
+/* If "map" is of the form [A -> B] -> [C -> D], then add A -> C to "res".
+ */
+static int factor_domain_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_domain_is_wrapping(map) || !isl_map_range_is_wrapping(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_factor_domain(isl_map_copy(map)));
+
+ return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> [C -> D],
+ * construct the map A -> C and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_factor_domain(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &factor_domain_entry);
+}
+
+/* If "map" is of the form [A -> B] -> [C -> D], then add B -> D to "res".
+ */
+static int factor_range_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_domain_is_wrapping(map) || !isl_map_range_is_wrapping(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res,
+ isl_map_factor_range(isl_map_copy(map)));
+
+ return *res ? 0 : -1;
+}
+
+/* For each map in "umap" of the form [A -> B] -> [C -> D],
+ * construct the map B -> D and collect the results.
+ */
+__isl_give isl_union_map *isl_union_map_factor_range(
+ __isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &factor_range_entry);
+}
+
+static int unwrap_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_set **res = user;
+
+ if (!isl_set_is_wrapping(set))
+ return 0;
+
+ *res = isl_union_map_add_map(*res, isl_set_unwrap(isl_set_copy(set)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset)
+{
+ return cond_un_op(uset, &unwrap_entry);
+}
+
+static int wrap_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_map_wrap(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &wrap_entry);
+}
+
+struct isl_union_map_is_subset_data {
+ isl_union_map *umap2;
+ int is_subset;
+};
+
+static int is_subset_entry(void **entry, void *user)
+{
+ struct isl_union_map_is_subset_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_map *map = *entry;
+
+ hash = isl_space_get_hash(map->dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, map->dim, 0);
+ if (!entry2) {
+ int empty = isl_map_is_empty(map);
+ if (empty < 0)
+ return -1;
+ if (empty)
+ return 0;
+ data->is_subset = 0;
+ return -1;
+ }
+
+ data->is_subset = isl_map_is_subset(map, entry2->data);
+ if (data->is_subset < 0 || !data->is_subset)
+ return -1;
+
+ return 0;
+}
+
+int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2)
+{
+ struct isl_union_map_is_subset_data data = { NULL, 1 };
+
+ umap1 = isl_union_map_copy(umap1);
+ umap2 = isl_union_map_copy(umap2);
+ umap1 = isl_union_map_align_params(umap1, isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2, isl_union_map_get_space(umap1));
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ data.umap2 = umap2;
+ if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+ &is_subset_entry, &data) < 0 &&
+ data.is_subset)
+ goto error;
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+
+ return data.is_subset;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return -1;
+}
+
+int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2)
+{
+ return isl_union_map_is_subset(uset1, uset2);
+}
+
+int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2)
+{
+ int is_subset;
+
+ if (!umap1 || !umap2)
+ return -1;
+ is_subset = isl_union_map_is_subset(umap1, umap2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_union_map_is_subset(umap2, umap1);
+ return is_subset;
+}
+
+int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2)
+{
+ return isl_union_map_is_equal(uset1, uset2);
+}
+
+int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2)
+{
+ int is_subset;
+
+ if (!umap1 || !umap2)
+ return -1;
+ is_subset = isl_union_map_is_subset(umap1, umap2);
+ if (is_subset != 1)
+ return is_subset;
+ is_subset = isl_union_map_is_subset(umap2, umap1);
+ if (is_subset == -1)
+ return is_subset;
+ return !is_subset;
+}
+
+int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2)
+{
+ return isl_union_map_is_strict_subset(uset1, uset2);
+}
+
+static int sample_entry(void **entry, void *user)
+{
+ isl_basic_map **sample = (isl_basic_map **)user;
+ isl_map *map = *entry;
+
+ *sample = isl_map_sample(isl_map_copy(map));
+ if (!*sample)
+ return -1;
+ if (!isl_basic_map_plain_is_empty(*sample))
+ return -1;
+ return 0;
+}
+
+__isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap)
+{
+ isl_basic_map *sample = NULL;
+
+ if (!umap)
+ return NULL;
+
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &sample_entry, &sample) < 0 &&
+ !sample)
+ goto error;
+
+ if (!sample)
+ sample = isl_basic_map_empty(isl_union_map_get_space(umap));
+
+ isl_union_map_free(umap);
+
+ return sample;
+error:
+ isl_union_map_free(umap);
+ return NULL;
+}
+
+__isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset)
+{
+ return (isl_basic_set *)isl_union_map_sample(uset);
+}
+
+struct isl_forall_data {
+ int res;
+ int (*fn)(__isl_keep isl_map *map);
+};
+
+static int forall_entry(void **entry, void *user)
+{
+ struct isl_forall_data *data = user;
+ isl_map *map = *entry;
+
+ data->res = data->fn(map);
+ if (data->res < 0)
+ return -1;
+
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+static int union_map_forall(__isl_keep isl_union_map *umap,
+ int (*fn)(__isl_keep isl_map *map))
+{
+ struct isl_forall_data data = { 1, fn };
+
+ if (!umap)
+ return -1;
+
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &forall_entry, &data) < 0 && data.res)
+ return -1;
+
+ return data.res;
+}
+
+struct isl_forall_user_data {
+ int res;
+ int (*fn)(__isl_keep isl_map *map, void *user);
+ void *user;
+};
+
+static int forall_user_entry(void **entry, void *user)
+{
+ struct isl_forall_user_data *data = user;
+ isl_map *map = *entry;
+
+ data->res = data->fn(map, data->user);
+ if (data->res < 0)
+ return -1;
+
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Check if fn(map, user) returns true for all maps "map" in umap.
+ */
+static int union_map_forall_user(__isl_keep isl_union_map *umap,
+ int (*fn)(__isl_keep isl_map *map, void *user), void *user)
+{
+ struct isl_forall_user_data data = { 1, fn, user };
+
+ if (!umap)
+ return -1;
+
+ if (isl_hash_table_foreach(umap->dim->ctx, &umap->table,
+ &forall_user_entry, &data) < 0 && data.res)
+ return -1;
+
+ return data.res;
+}
+
+int isl_union_map_is_empty(__isl_keep isl_union_map *umap)
+{
+ return union_map_forall(umap, &isl_map_is_empty);
+}
+
+int isl_union_set_is_empty(__isl_keep isl_union_set *uset)
+{
+ return isl_union_map_is_empty(uset);
+}
+
+static int is_subset_of_identity(__isl_keep isl_map *map)
+{
+ int is_subset;
+ isl_space *dim;
+ isl_map *id;
+
+ if (!map)
+ return -1;
+
+ if (!isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ map->dim, isl_dim_out))
+ return 0;
+
+ dim = isl_map_get_space(map);
+ id = isl_map_identity(dim);
+
+ is_subset = isl_map_is_subset(map, id);
+
+ isl_map_free(id);
+
+ return is_subset;
+}
+
+/* Given an isl_union_map that consists of a single map, check
+ * if it is single-valued.
+ */
+static int single_map_is_single_valued(__isl_keep isl_union_map *umap)
+{
+ isl_map *map;
+ int sv;
+
+ umap = isl_union_map_copy(umap);
+ map = isl_map_from_union_map(umap);
+ sv = isl_map_is_single_valued(map);
+ isl_map_free(map);
+
+ return sv;
+}
+
+/* Internal data structure for single_valued_on_domain.
+ *
+ * "umap" is the union map to be tested.
+ * "sv" is set to 1 as long as "umap" may still be single-valued.
+ */
+struct isl_union_map_is_sv_data {
+ isl_union_map *umap;
+ int sv;
+};
+
+/* Check if the data->umap is single-valued on "set".
+ *
+ * If data->umap consists of a single map on "set", then test it
+ * as an isl_map.
+ *
+ * Otherwise, compute
+ *
+ * M \circ M^-1
+ *
+ * check if the result is a subset of the identity mapping and
+ * store the result in data->sv.
+ *
+ * Terminate as soon as data->umap has been determined not to
+ * be single-valued.
+ */
+static int single_valued_on_domain(__isl_take isl_set *set, void *user)
+{
+ struct isl_union_map_is_sv_data *data = user;
+ isl_union_map *umap, *test;
+
+ umap = isl_union_map_copy(data->umap);
+ umap = isl_union_map_intersect_domain(umap,
+ isl_union_set_from_set(set));
+
+ if (isl_union_map_n_map(umap) == 1) {
+ data->sv = single_map_is_single_valued(umap);
+ isl_union_map_free(umap);
+ } else {
+ test = isl_union_map_reverse(isl_union_map_copy(umap));
+ test = isl_union_map_apply_range(test, umap);
+
+ data->sv = union_map_forall(test, &is_subset_of_identity);
+
+ isl_union_map_free(test);
+ }
+
+ if (data->sv < 0 || !data->sv)
+ return -1;
+ return 0;
+}
+
+/* Check if the given map is single-valued.
+ *
+ * If the union map consists of a single map, then test it as an isl_map.
+ * Otherwise, check if the union map is single-valued on each of its
+ * domain spaces.
+ */
+int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap)
+{
+ isl_union_map *universe;
+ isl_union_set *domain;
+ struct isl_union_map_is_sv_data data;
+
+ if (isl_union_map_n_map(umap) == 1)
+ return single_map_is_single_valued(umap);
+
+ universe = isl_union_map_universe(isl_union_map_copy(umap));
+ domain = isl_union_map_domain(universe);
+
+ data.sv = 1;
+ data.umap = umap;
+ if (isl_union_set_foreach_set(domain,
+ &single_valued_on_domain, &data) < 0 && data.sv)
+ data.sv = -1;
+ isl_union_set_free(domain);
+
+ return data.sv;
+}
+
+int isl_union_map_is_injective(__isl_keep isl_union_map *umap)
+{
+ int in;
+
+ umap = isl_union_map_copy(umap);
+ umap = isl_union_map_reverse(umap);
+ in = isl_union_map_is_single_valued(umap);
+ isl_union_map_free(umap);
+
+ return in;
+}
+
+/* Represents a map that has a fixed value (v) for one of its
+ * range dimensions.
+ * The map in this structure is not reference counted, so it
+ * is only valid while the isl_union_map from which it was
+ * obtained is still alive.
+ */
+struct isl_fixed_map {
+ isl_int v;
+ isl_map *map;
+};
+
+static struct isl_fixed_map *alloc_isl_fixed_map_array(isl_ctx *ctx,
+ int n)
+{
+ int i;
+ struct isl_fixed_map *v;
+
+ v = isl_calloc_array(ctx, struct isl_fixed_map, n);
+ if (!v)
+ return NULL;
+ for (i = 0; i < n; ++i)
+ isl_int_init(v[i].v);
+ return v;
+}
+
+static void free_isl_fixed_map_array(struct isl_fixed_map *v, int n)
+{
+ int i;
+
+ if (!v)
+ return;
+ for (i = 0; i < n; ++i)
+ isl_int_clear(v[i].v);
+ free(v);
+}
+
+/* Compare the "v" field of two isl_fixed_map structs.
+ */
+static int qsort_fixed_map_cmp(const void *p1, const void *p2)
+{
+ const struct isl_fixed_map *e1 = (const struct isl_fixed_map *) p1;
+ const struct isl_fixed_map *e2 = (const struct isl_fixed_map *) p2;
+
+ return isl_int_cmp(e1->v, e2->v);
+}
+
+/* Internal data structure used while checking whether all maps
+ * in a union_map have a fixed value for a given output dimension.
+ * v is the list of maps, with the fixed value for the dimension
+ * n is the number of maps considered so far
+ * pos is the output dimension under investigation
+ */
+struct isl_fixed_dim_data {
+ struct isl_fixed_map *v;
+ int n;
+ int pos;
+};
+
+static int fixed_at_pos(__isl_keep isl_map *map, void *user)
+{
+ struct isl_fixed_dim_data *data = user;
+
+ data->v[data->n].map = map;
+ return isl_map_plain_is_fixed(map, isl_dim_out, data->pos,
+ &data->v[data->n++].v);
+}
+
+static int plain_injective_on_range(__isl_take isl_union_map *umap,
+ int first, int n_range);
+
+/* Given a list of the maps, with their fixed values at output dimension "pos",
+ * check whether the ranges of the maps form an obvious partition.
+ *
+ * We first sort the maps according to their fixed values.
+ * If all maps have a different value, then we know the ranges form
+ * a partition.
+ * Otherwise, we collect the maps with the same fixed value and
+ * check whether each such collection is obviously injective
+ * based on later dimensions.
+ */
+static int separates(struct isl_fixed_map *v, int n,
+ __isl_take isl_space *dim, int pos, int n_range)
+{
+ int i;
+
+ if (!v)
+ goto error;
+
+ qsort(v, n, sizeof(*v), &qsort_fixed_map_cmp);
+
+ for (i = 0; i + 1 < n; ++i) {
+ int j, k;
+ isl_union_map *part;
+ int injective;
+
+ for (j = i + 1; j < n; ++j)
+ if (isl_int_ne(v[i].v, v[j].v))
+ break;
+
+ if (j == i + 1)
+ continue;
+
+ part = isl_union_map_alloc(isl_space_copy(dim), j - i);
+ for (k = i; k < j; ++k)
+ part = isl_union_map_add_map(part,
+ isl_map_copy(v[k].map));
+
+ injective = plain_injective_on_range(part, pos + 1, n_range);
+ if (injective < 0)
+ goto error;
+ if (!injective)
+ break;
+
+ i = j - 1;
+ }
+
+ isl_space_free(dim);
+ free_isl_fixed_map_array(v, n);
+ return i + 1 >= n;
+error:
+ isl_space_free(dim);
+ free_isl_fixed_map_array(v, n);
+ return -1;
+}
+
+/* Check whether the maps in umap have obviously distinct ranges.
+ * In particular, check for an output dimension in the range
+ * [first,n_range) for which all maps have a fixed value
+ * and then check if these values, possibly along with fixed values
+ * at later dimensions, entail distinct ranges.
+ */
+static int plain_injective_on_range(__isl_take isl_union_map *umap,
+ int first, int n_range)
+{
+ isl_ctx *ctx;
+ int n;
+ struct isl_fixed_dim_data data = { NULL };
+
+ ctx = isl_union_map_get_ctx(umap);
+
+ n = isl_union_map_n_map(umap);
+ if (!umap)
+ goto error;
+
+ if (n <= 1) {
+ isl_union_map_free(umap);
+ return 1;
+ }
+
+ if (first >= n_range) {
+ isl_union_map_free(umap);
+ return 0;
+ }
+
+ data.v = alloc_isl_fixed_map_array(ctx, n);
+ if (!data.v)
+ goto error;
+
+ for (data.pos = first; data.pos < n_range; ++data.pos) {
+ int fixed;
+ int injective;
+ isl_space *dim;
+
+ data.n = 0;
+ fixed = union_map_forall_user(umap, &fixed_at_pos, &data);
+ if (fixed < 0)
+ goto error;
+ if (!fixed)
+ continue;
+ dim = isl_union_map_get_space(umap);
+ injective = separates(data.v, n, dim, data.pos, n_range);
+ isl_union_map_free(umap);
+ return injective;
+ }
+
+ free_isl_fixed_map_array(data.v, n);
+ isl_union_map_free(umap);
+
+ return 0;
+error:
+ free_isl_fixed_map_array(data.v, n);
+ isl_union_map_free(umap);
+ return -1;
+}
+
+/* Check whether the maps in umap that map to subsets of "ran"
+ * have obviously distinct ranges.
+ */
+static int plain_injective_on_range_wrap(__isl_keep isl_set *ran, void *user)
+{
+ isl_union_map *umap = user;
+
+ umap = isl_union_map_copy(umap);
+ umap = isl_union_map_intersect_range(umap,
+ isl_union_set_from_set(isl_set_copy(ran)));
+ return plain_injective_on_range(umap, 0, isl_set_dim(ran, isl_dim_set));
+}
+
+/* Check if the given union_map is obviously injective.
+ *
+ * In particular, we first check if all individual maps are obviously
+ * injective and then check if all the ranges of these maps are
+ * obviously disjoint.
+ */
+int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap)
+{
+ int in;
+ isl_union_map *univ;
+ isl_union_set *ran;
+
+ in = union_map_forall(umap, &isl_map_plain_is_injective);
+ if (in < 0)
+ return -1;
+ if (!in)
+ return 0;
+
+ univ = isl_union_map_universe(isl_union_map_copy(umap));
+ ran = isl_union_map_range(univ);
+
+ in = union_map_forall_user(ran, &plain_injective_on_range_wrap, umap);
+
+ isl_union_set_free(ran);
+
+ return in;
+}
+
+int isl_union_map_is_bijective(__isl_keep isl_union_map *umap)
+{
+ int sv;
+
+ sv = isl_union_map_is_single_valued(umap);
+ if (sv < 0 || !sv)
+ return sv;
+
+ return isl_union_map_is_injective(umap);
+}
+
+static int zip_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_can_zip(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res, isl_map_zip(isl_map_copy(map)));
+
+ return 0;
+}
+
+__isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &zip_entry);
+}
+
+static int uncurry_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_can_uncurry(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res, isl_map_uncurry(isl_map_copy(map)));
+
+ return 0;
+}
+
+/* Given a union map, take the maps of the form A -> (B -> C) and
+ * return the union of the corresponding maps (A -> B) -> C.
+ */
+__isl_give isl_union_map *isl_union_map_uncurry(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &uncurry_entry);
+}
+
+static int curry_entry(void **entry, void *user)
+{
+ isl_map *map = *entry;
+ isl_union_map **res = user;
+
+ if (!isl_map_can_curry(map))
+ return 0;
+
+ *res = isl_union_map_add_map(*res, isl_map_curry(isl_map_copy(map)));
+
+ return 0;
+}
+
+/* Given a union map, take the maps of the form (A -> B) -> C and
+ * return the union of the corresponding maps A -> (B -> C).
+ */
+__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap)
+{
+ return cond_un_op(umap, &curry_entry);
+}
+
+static int lift_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_set **res = user;
+
+ *res = isl_union_set_add_set(*res, isl_set_lift(isl_set_copy(set)));
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset)
+{
+ return cond_un_op(uset, &lift_entry);
+}
+
+static int coefficients_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_set **res = user;
+
+ set = isl_set_copy(set);
+ set = isl_set_from_basic_set(isl_set_coefficients(set));
+ *res = isl_union_set_add_set(*res, set);
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_coefficients(
+ __isl_take isl_union_set *uset)
+{
+ isl_ctx *ctx;
+ isl_space *dim;
+ isl_union_set *res;
+
+ if (!uset)
+ return NULL;
+
+ ctx = isl_union_set_get_ctx(uset);
+ dim = isl_space_set_alloc(ctx, 0, 0);
+ res = isl_union_map_alloc(dim, uset->table.n);
+ if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
+ &coefficients_entry, &res) < 0)
+ goto error;
+
+ isl_union_set_free(uset);
+ return res;
+error:
+ isl_union_set_free(uset);
+ isl_union_set_free(res);
+ return NULL;
+}
+
+static int solutions_entry(void **entry, void *user)
+{
+ isl_set *set = *entry;
+ isl_union_set **res = user;
+
+ set = isl_set_copy(set);
+ set = isl_set_from_basic_set(isl_set_solutions(set));
+ if (!*res)
+ *res = isl_union_set_from_set(set);
+ else
+ *res = isl_union_set_add_set(*res, set);
+
+ if (!*res)
+ return -1;
+
+ return 0;
+}
+
+__isl_give isl_union_set *isl_union_set_solutions(
+ __isl_take isl_union_set *uset)
+{
+ isl_union_set *res = NULL;
+
+ if (!uset)
+ return NULL;
+
+ if (uset->table.n == 0) {
+ res = isl_union_set_empty(isl_union_set_get_space(uset));
+ isl_union_set_free(uset);
+ return res;
+ }
+
+ if (isl_hash_table_foreach(uset->dim->ctx, &uset->table,
+ &solutions_entry, &res) < 0)
+ goto error;
+
+ isl_union_set_free(uset);
+ return res;
+error:
+ isl_union_set_free(uset);
+ isl_union_set_free(res);
+ return NULL;
+}
+
+/* Is the domain space of "map" equal to "space"?
+ */
+static int domain_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+ return isl_space_tuple_is_equal(map->dim, isl_dim_in,
+ space, isl_dim_out);
+}
+
+/* Is the range space of "map" equal to "space"?
+ */
+static int range_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+ return isl_space_tuple_is_equal(map->dim, isl_dim_out,
+ space, isl_dim_out);
+}
+
+/* Is the set space of "map" equal to "space"?
+ */
+static int set_match(__isl_keep isl_map *map, __isl_keep isl_space *space)
+{
+ return isl_space_tuple_is_equal(map->dim, isl_dim_set,
+ space, isl_dim_out);
+}
+
+/* Internal data structure for preimage_pw_multi_aff.
+ *
+ * "pma" is the function under which the preimage should be taken.
+ * "space" is the space of "pma".
+ * "res" collects the results.
+ * "fn" computes the preimage for a given map.
+ * "match" returns true if "fn" can be called.
+ */
+struct isl_union_map_preimage_data {
+ isl_space *space;
+ isl_pw_multi_aff *pma;
+ isl_union_map *res;
+ int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space);
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map,
+ __isl_take isl_pw_multi_aff *pma);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of *entry
+ * under the function represented by data->pma, provided the domain/range
+ * space of *entry matches the target space of data->pma
+ * (as given by data->match), and add the result to data->res.
+ */
+static int preimage_entry(void **entry, void *user)
+{
+ int m;
+ isl_map *map = *entry;
+ struct isl_union_map_preimage_data *data = user;
+ int empty;
+
+ m = data->match(map, data->space);
+ if (m < 0)
+ return -1;
+ if (!m)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = data->fn(map, isl_pw_multi_aff_copy(data->pma));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0 || empty) {
+ isl_map_free(map);
+ return empty < 0 ? -1 : 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation on a map,
+ * while "match" determines to which maps the function should be applied.
+ */
+static __isl_give isl_union_map *preimage_pw_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma,
+ int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space),
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map,
+ __isl_take isl_pw_multi_aff *pma))
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ struct isl_union_map_preimage_data data;
+
+ umap = isl_union_map_align_params(umap,
+ isl_pw_multi_aff_get_space(pma));
+ pma = isl_pw_multi_aff_align_params(pma, isl_union_map_get_space(umap));
+
+ if (!umap || !pma)
+ goto error;
+
+ ctx = isl_union_map_get_ctx(umap);
+ space = isl_union_map_get_space(umap);
+ data.space = isl_pw_multi_aff_get_space(pma);
+ data.pma = pma;
+ data.res = isl_union_map_alloc(space, umap->table.n);
+ data.match = match;
+ data.fn = fn;
+ if (isl_hash_table_foreach(ctx, &umap->table, &preimage_entry,
+ &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_space_free(data.space);
+ isl_union_map_free(umap);
+ isl_pw_multi_aff_free(pma);
+ return data.res;
+error:
+ isl_union_map_free(umap);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "pma",
+ * except that the domain has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_pw_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma)
+{
+ return preimage_pw_multi_aff(umap, pma, &domain_match,
+ &isl_map_preimage_domain_pw_multi_aff);
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "pma".
+ * In other words, plug in "pma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to the target space of "pma",
+ * except that the range has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_pw_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma)
+{
+ return preimage_pw_multi_aff(umap, pma, &range_match,
+ &isl_map_preimage_range_pw_multi_aff);
+}
+
+/* Compute the preimage of "uset" under the function represented by "pma".
+ * In other words, plug in "pma" in "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to the target space of "pma",
+ * except that the space has been replaced by the domain space of "pma".
+ */
+__isl_give isl_union_set *isl_union_set_preimage_pw_multi_aff(
+ __isl_take isl_union_set *uset, __isl_take isl_pw_multi_aff *pma)
+{
+ return preimage_pw_multi_aff(uset, pma, &set_match,
+ &isl_set_preimage_pw_multi_aff);
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "ma",
+ * except that the domain has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma)
+{
+ return isl_union_map_preimage_domain_pw_multi_aff(umap,
+ isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "ma".
+ * In other words, plug in "ma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to the target space of "ma",
+ * except that the range has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_multi_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma)
+{
+ return isl_union_map_preimage_range_pw_multi_aff(umap,
+ isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Compute the preimage of "uset" under the function represented by "ma".
+ * In other words, plug in "ma" in "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to the target space of "ma",
+ * except that the space has been replaced by the domain space of "ma".
+ */
+__isl_give isl_union_map *isl_union_set_preimage_multi_aff(
+ __isl_take isl_union_set *uset, __isl_take isl_multi_aff *ma)
+{
+ return isl_union_set_preimage_pw_multi_aff(uset,
+ isl_pw_multi_aff_from_multi_aff(ma));
+}
+
+/* Internal data structure for preimage_multi_pw_aff.
+ *
+ * "mpa" is the function under which the preimage should be taken.
+ * "space" is the space of "mpa".
+ * "res" collects the results.
+ * "fn" computes the preimage for a given map.
+ * "match" returns true if "fn" can be called.
+ */
+struct isl_union_map_preimage_mpa_data {
+ isl_space *space;
+ isl_multi_pw_aff *mpa;
+ isl_union_map *res;
+ int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space);
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map,
+ __isl_take isl_multi_pw_aff *mpa);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of *entry
+ * under the function represented by data->mpa, provided the domain/range
+ * space of *entry matches the target space of data->mpa
+ * (as given by data->match), and add the result to data->res.
+ */
+static int preimage_mpa_entry(void **entry, void *user)
+{
+ int m;
+ isl_map *map = *entry;
+ struct isl_union_map_preimage_mpa_data *data = user;
+ int empty;
+
+ m = data->match(map, data->space);
+ if (m < 0)
+ return -1;
+ if (!m)
+ return 0;
+
+ map = isl_map_copy(map);
+ map = data->fn(map, isl_multi_pw_aff_copy(data->mpa));
+
+ empty = isl_map_is_empty(map);
+ if (empty < 0 || empty) {
+ isl_map_free(map);
+ return empty < 0 ? -1 : 0;
+ }
+
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "mpa".
+ * In other words, plug in "mpa" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation on a map,
+ * while "match" determines to which maps the function should be applied.
+ */
+static __isl_give isl_union_map *preimage_multi_pw_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa,
+ int (*match)(__isl_keep isl_map *map, __isl_keep isl_space *space),
+ __isl_give isl_map *(*fn)(__isl_take isl_map *map,
+ __isl_take isl_multi_pw_aff *mpa))
+{
+ isl_ctx *ctx;
+ isl_space *space;
+ struct isl_union_map_preimage_mpa_data data;
+
+ umap = isl_union_map_align_params(umap,
+ isl_multi_pw_aff_get_space(mpa));
+ mpa = isl_multi_pw_aff_align_params(mpa, isl_union_map_get_space(umap));
+
+ if (!umap || !mpa)
+ goto error;
+
+ ctx = isl_union_map_get_ctx(umap);
+ space = isl_union_map_get_space(umap);
+ data.space = isl_multi_pw_aff_get_space(mpa);
+ data.mpa = mpa;
+ data.res = isl_union_map_alloc(space, umap->table.n);
+ data.match = match;
+ data.fn = fn;
+ if (isl_hash_table_foreach(ctx, &umap->table, &preimage_mpa_entry,
+ &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_space_free(data.space);
+ isl_union_map_free(umap);
+ isl_multi_pw_aff_free(mpa);
+ return data.res;
+error:
+ isl_union_map_free(umap);
+ isl_multi_pw_aff_free(mpa);
+ return NULL;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "mpa".
+ * In other words, plug in "mpa" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to the target space of "mpa",
+ * except that the domain has been replaced by the domain space of "mpa".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_pw_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa)
+{
+ return preimage_multi_pw_aff(umap, mpa, &domain_match,
+ &isl_map_preimage_domain_multi_pw_aff);
+}
+
+/* Internal data structure for preimage_upma.
+ *
+ * "umap" is the map of which the preimage should be computed.
+ * "res" collects the results.
+ * "fn" computes the preimage for a given piecewise multi-affine function.
+ */
+struct isl_union_map_preimage_upma_data {
+ isl_union_map *umap;
+ isl_union_map *res;
+ __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap,
+ __isl_take isl_pw_multi_aff *pma);
+};
+
+/* Call data->fn to compute the preimage of the domain or range of data->umap
+ * under the function represented by pma and add the result to data->res.
+ */
+static int preimage_upma(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ struct isl_union_map_preimage_upma_data *data = user;
+ isl_union_map *umap;
+
+ umap = isl_union_map_copy(data->umap);
+ umap = data->fn(umap, pma);
+ data->res = isl_union_map_union(data->res, umap);
+
+ return data->res ? 0 : -1;
+}
+
+/* Compute the preimage of the domain or range of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the domain or range of "umap".
+ * The function "fn" performs the actual preimage computation
+ * on a piecewise multi-affine function.
+ */
+static __isl_give isl_union_map *preimage_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_give isl_union_map *(*fn)(__isl_take isl_union_map *umap,
+ __isl_take isl_pw_multi_aff *pma))
+{
+ struct isl_union_map_preimage_upma_data data;
+
+ data.umap = umap;
+ data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+ data.fn = fn;
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &preimage_upma, &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_union_map_free(umap);
+ isl_union_pw_multi_aff_free(upma);
+
+ return data.res;
+}
+
+/* Compute the preimage of the domain of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the domain of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with domain space equal to one of the target spaces of "upma",
+ * except that the domain has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_domain_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ return preimage_union_pw_multi_aff(umap, upma,
+ &isl_union_map_preimage_domain_pw_multi_aff);
+}
+
+/* Compute the preimage of the range of "umap" under the function
+ * represented by "upma".
+ * In other words, plug in "upma" in the range of "umap".
+ * The result contains maps that live in the same spaces as the maps of "umap"
+ * with range space equal to one of the target spaces of "upma",
+ * except that the range has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ return preimage_union_pw_multi_aff(umap, upma,
+ &isl_union_map_preimage_range_pw_multi_aff);
+}
+
+/* Compute the preimage of "uset" under the function represented by "upma".
+ * In other words, plug in "upma" in the range of "uset".
+ * The result contains sets that live in the same spaces as the sets of "uset"
+ * with space equal to one of the target spaces of "upma",
+ * except that the space has been replaced by one of the the domain spaces that
+ * corresponds to that target space of "upma".
+ */
+__isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff(
+ __isl_take isl_union_set *uset,
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ return preimage_union_pw_multi_aff(uset, upma,
+ &isl_union_set_preimage_pw_multi_aff);
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of *entry.
+ */
+static int reset_user(void **entry, void *user)
+{
+ isl_map **map = (isl_map **)entry;
+
+ *map = isl_map_reset_user(*map);
+
+ return *map ? 0 : -1;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the spaces of "umap".
+ */
+__isl_give isl_union_map *isl_union_map_reset_user(
+ __isl_take isl_union_map *umap)
+{
+ umap = isl_union_map_cow(umap);
+ if (!umap)
+ return NULL;
+ umap->dim = isl_space_reset_user(umap->dim);
+ if (!umap->dim)
+ return isl_union_map_free(umap);
+ umap = un_op(umap, &reset_user);
+
+ return umap;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the spaces of "uset".
+ */
+__isl_give isl_union_set *isl_union_set_reset_user(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_reset_user(uset);
+}
+
+/* Internal data structure for isl_union_map_project_out.
+ * "type", "first" and "n" are the arguments for the isl_map_project_out
+ * call.
+ * "res" collects the results.
+ */
+struct isl_union_map_project_out_data {
+ enum isl_dim_type type;
+ unsigned first;
+ unsigned n;
+
+ isl_union_map *res;
+};
+
+/* Turn the data->n dimensions of type data->type, starting at data->first
+ * into existentially quantified variables and add the result to data->res.
+ */
+static int project_out(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_map_project_out_data *data = user;
+
+ map = isl_map_project_out(map, data->type, data->first, data->n);
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return 0;
+}
+
+/* Turn the "n" dimensions of type "type", starting at "first"
+ * into existentially quantified variables.
+ * Since the space of an isl_union_map only contains parameters,
+ * type is required to be equal to isl_dim_param.
+ */
+__isl_give isl_union_map *isl_union_map_project_out(
+ __isl_take isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_space *space;
+ struct isl_union_map_project_out_data data = { type, first, n };
+
+ if (!umap)
+ return NULL;
+
+ if (type != isl_dim_param)
+ isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+ "can only project out parameters",
+ return isl_union_map_free(umap));
+
+ space = isl_union_map_get_space(umap);
+ space = isl_space_drop_dims(space, type, first, n);
+ data.res = isl_union_map_empty(space);
+ if (isl_union_map_foreach_map(umap, &project_out, &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_union_map_free(umap);
+
+ return data.res;
+}
+
+/* Internal data structure for isl_union_map_involves_dims.
+ * "first" and "n" are the arguments for the isl_map_involves_dims calls.
+ */
+struct isl_union_map_involves_dims_data {
+ unsigned first;
+ unsigned n;
+};
+
+/* Does "map" _not_ involve the data->n parameters starting at data->first?
+ */
+static int map_excludes(__isl_keep isl_map *map, void *user)
+{
+ struct isl_union_map_involves_dims_data *data = user;
+ int involves;
+
+ involves = isl_map_involves_dims(map,
+ isl_dim_param, data->first, data->n);
+ if (involves < 0)
+ return -1;
+ return !involves;
+}
+
+/* Does "umap" involve any of the n parameters starting at first?
+ * "type" is required to be set to isl_dim_param.
+ *
+ * "umap" involves any of those parameters if any of its maps
+ * involve the parameters. In other words, "umap" does not
+ * involve any of the parameters if all its maps to not
+ * involve the parameters.
+ */
+int isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ struct isl_union_map_involves_dims_data data = { first, n };
+ int excludes;
+
+ if (type != isl_dim_param)
+ isl_die(isl_union_map_get_ctx(umap), isl_error_invalid,
+ "can only reference parameters", return 0);
+
+ excludes = union_map_forall_user(umap, &map_excludes, &data);
+
+ if (excludes < 0)
+ return -1;
+
+ return !excludes;
+}
diff --git a/polly/lib/External/isl/isl_union_map_private.h b/polly/lib/External/isl/isl_union_map_private.h
new file mode 100644
index 00000000000..7a502e7bdd5
--- /dev/null
+++ b/polly/lib/External/isl/isl_union_map_private.h
@@ -0,0 +1,10 @@
+#define isl_union_set isl_union_map
+#include <isl/union_map.h>
+#include <isl/union_set.h>
+
+struct isl_union_map {
+ int ref;
+ isl_space *dim;
+
+ struct isl_hash_table table;
+};
diff --git a/polly/lib/External/isl/isl_union_templ.c b/polly/lib/External/isl/isl_union_templ.c
new file mode 100644
index 00000000000..4cd1d9dd183
--- /dev/null
+++ b/polly/lib/External/isl/isl_union_templ.c
@@ -0,0 +1,1107 @@
+/*
+ * 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
+ */
+
+#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)
+{
+ return u ? u->space->ctx : NULL;
+}
+
+__isl_give isl_space *FN(UNION,get_space)(__isl_keep UNION *u)
+{
+ if (!u)
+ return NULL;
+ return isl_space_copy(u->space);
+}
+
+/* Return the number of parameters of "u", where "type"
+ * is required to be set to isl_dim_param.
+ */
+unsigned FN(UNION,dim)(__isl_keep UNION *u, enum isl_dim_type type)
+{
+ if (!u)
+ return 0;
+
+ if (type != isl_dim_param)
+ isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+ "can only reference parameters", return 0);
+
+ return isl_space_dim(u->space, type);
+}
+
+/* Return the position of the parameter with the given name
+ * in "u".
+ * Return -1 if no such dimension can be found.
+ */
+int FN(UNION,find_dim_by_name)(__isl_keep UNION *u, enum isl_dim_type type,
+ const char *name)
+{
+ if (!u)
+ return -1;
+ return isl_space_find_dim_by_name(u->space, type, name);
+}
+
+#ifdef HAS_TYPE
+static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim,
+ enum isl_fold type, int size)
+#else
+static __isl_give UNION *FN(UNION,alloc)(__isl_take isl_space *dim, int size)
+#endif
+{
+ UNION *u;
+
+ dim = isl_space_params(dim);
+ if (!dim)
+ return NULL;
+
+ u = isl_calloc_type(dim->ctx, UNION);
+ if (!u)
+ goto error;
+
+ u->ref = 1;
+#ifdef HAS_TYPE
+ u->type = type;
+#endif
+ u->space = dim;
+ if (isl_hash_table_init(dim->ctx, &u->table, size) < 0)
+ return FN(UNION,free)(u);
+
+ return u;
+error:
+ isl_space_free(dim);
+ return NULL;
+}
+
+#ifdef HAS_TYPE
+__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim, enum isl_fold type)
+{
+ return FN(UNION,alloc)(dim, type, 16);
+}
+#else
+__isl_give UNION *FN(UNION,ZERO)(__isl_take isl_space *dim)
+{
+ return FN(UNION,alloc)(dim, 16);
+}
+#endif
+
+__isl_give UNION *FN(UNION,copy)(__isl_keep UNION *u)
+{
+ if (!u)
+ return NULL;
+
+ u->ref++;
+ return u;
+}
+
+S(UNION,foreach_data)
+{
+ int (*fn)(__isl_take PART *part, void *user);
+ void *user;
+};
+
+static int 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);
+}
+
+int FN(FN(UNION,foreach),PARTS)(__isl_keep UNION *u,
+ int (*fn)(__isl_take PART *part, void *user), void *user)
+{
+ S(UNION,foreach_data) data = { fn, user };
+
+ if (!u)
+ return -1;
+
+ return isl_hash_table_foreach(u->space->ctx, &u->table,
+ &call_on_copy, &data);
+}
+
+/* Is the space of "entry" equal to "space"?
+ */
+static int 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 has_domain_space(const void *entry, const void *val)
+ __attribute__ ((unused));
+
+/* Is the domain space of "entry" equal to "space"?
+ */
+static int 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 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
+ * living in "space".
+ */
+__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)
+ goto error;
+ if (!isl_space_match(u->space, isl_dim_param, space, isl_dim_param)) {
+ space = isl_space_drop_dims(space, isl_dim_param,
+ 0, isl_space_dim(space, isl_dim_param));
+ space = isl_space_align_params(space,
+ FN(UNION,get_space)(u));
+ if (!space)
+ goto error;
+ }
+
+ hash = isl_space_get_hash(space);
+ entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
+ &has_space, space, 0);
+ if (!entry)
+#ifdef HAS_TYPE
+ return FN(PART,ZERO)(space, u->type);
+#else
+ return FN(PART,ZERO)(space);
+#endif
+ isl_space_free(space);
+ return FN(PART,copy)(entry->data);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* 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".
+ * Otherwise, compute the union sum of "part" and the part in "u"
+ * defined on the same space.
+ */
+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)
+ goto error;
+
+ empty = FN(PART,IS_ZERO)(part);
+ if (empty < 0)
+ goto error;
+ if (empty) {
+ FN(PART,free)(part);
+ return u;
+ }
+
+ u = FN(UNION,align_params)(u, FN(PART,get_space)(part));
+ part = FN(PART,align_params)(part, FN(UNION,get_space)(u));
+
+ u = FN(UNION,cow)(u);
+
+ if (!u)
+ goto error;
+
+ hash = isl_space_get_hash(part->dim);
+ entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
+ &has_same_domain_space, 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);
+ entry->data = FN(PART,union_add_)(entry->data,
+ FN(PART,copy)(part));
+ if (!entry->data)
+ goto error;
+ 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);
+ }
+ FN(PART,free)(part);
+ }
+
+ return u;
+error:
+ FN(PART,free)(part);
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+/* Add "part" to "u", where "u" is assumed not to already have
+ * a part that is defined on the same space as "part".
+ */
+__isl_give UNION *FN(FN(UNION,add),PARTS)(__isl_take UNION *u,
+ __isl_take PART *part)
+{
+ return FN(UNION,add_part_generic)(u, part, 1);
+}
+
+static int add_part(__isl_take PART *part, void *user)
+{
+ UNION **u = (UNION **)user;
+
+ *u = FN(FN(UNION,add),PARTS)(*u, part);
+
+ return 0;
+}
+
+__isl_give UNION *FN(UNION,dup)(__isl_keep UNION *u)
+{
+ UNION *dup;
+
+ if (!u)
+ return NULL;
+
+#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, &add_part, &dup) < 0)
+ goto error;
+ return dup;
+error:
+ FN(UNION,free)(dup);
+ return NULL;
+}
+
+__isl_give UNION *FN(UNION,cow)(__isl_take UNION *u)
+{
+ if (!u)
+ return NULL;
+
+ if (u->ref == 1)
+ return u;
+ u->ref--;
+ return FN(UNION,dup)(u);
+}
+
+static int free_u_entry(void **entry, void *user)
+{
+ PART *part = *entry;
+ FN(PART,free)(part);
+ return 0;
+}
+
+__isl_null UNION *FN(UNION,free)(__isl_take UNION *u)
+{
+ if (!u)
+ return NULL;
+
+ if (--u->ref > 0)
+ return NULL;
+
+ isl_hash_table_foreach(u->space->ctx, &u->table, &free_u_entry, NULL);
+ isl_hash_table_clear(&u->table);
+ isl_space_free(u->space);
+ free(u);
+ return NULL;
+}
+
+S(UNION,align) {
+ isl_reordering *exp;
+ UNION *res;
+};
+
+#ifdef ALIGN_DOMAIN
+static int align_entry(__isl_take PART *part, void *user)
+{
+ isl_reordering *exp;
+ S(UNION,align) *data = user;
+
+ exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+ FN(PART,get_domain_space)(part));
+
+ data->res = FN(FN(UNION,add),PARTS)(data->res,
+ FN(PART,realign_domain)(part, exp));
+
+ return 0;
+}
+#else
+static int align_entry(__isl_take PART *part, void *user)
+{
+ isl_reordering *exp;
+ S(UNION,align) *data = user;
+
+ exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
+ FN(PART,get_space)(part));
+
+ data->res = FN(FN(UNION,add),PARTS)(data->res,
+ FN(PART,realign)(part, exp));
+
+ return 0;
+}
+#endif
+
+__isl_give UNION *FN(UNION,align_params)(__isl_take UNION *u,
+ __isl_take isl_space *model)
+{
+ S(UNION,align) data = { NULL, NULL };
+
+ if (!u || !model)
+ goto error;
+
+ if (isl_space_match(u->space, isl_dim_param, model, isl_dim_param)) {
+ isl_space_free(model);
+ return u;
+ }
+
+ model = isl_space_params(model);
+ data.exp = isl_parameter_alignment_reordering(u->space, model);
+ if (!data.exp)
+ goto error;
+
+#ifdef HAS_TYPE
+ data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim),
+ u->type, u->table.n);
+#else
+ data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim), u->table.n);
+#endif
+ if (FN(FN(UNION,foreach),PARTS)(u, &align_entry, &data) < 0)
+ goto error;
+
+ isl_reordering_free(data.exp);
+ FN(UNION,free)(u);
+ isl_space_free(model);
+ return data.res;
+error:
+ isl_reordering_free(data.exp);
+ FN(UNION,free)(u);
+ FN(UNION,free)(data.res);
+ isl_space_free(model);
+ return NULL;
+}
+
+/* Add "part" to *u, taking the union sum if "u" already has
+ * a part defined on the same space as "part".
+ */
+static int union_add_part(__isl_take PART *part, void *user)
+{
+ UNION **u = (UNION **)user;
+
+ *u = FN(UNION,add_part_generic)(*u, part, 0);
+
+ return 0;
+}
+
+/* Compute the sum of "u1" and "u2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ *
+ * This is an internal function that is exposed under different
+ * names depending on whether the base expressions have a zero default
+ * value.
+ * If they do, then this function is called "add".
+ * Otherwise, it is called "union_add".
+ */
+static __isl_give UNION *FN(UNION,union_add_)(__isl_take UNION *u1,
+ __isl_take UNION *u2)
+{
+ u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+ u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+
+ u1 = FN(UNION,cow)(u1);
+
+ if (!u1 || !u2)
+ goto error;
+
+ if (FN(FN(UNION,foreach),PARTS)(u2, &union_add_part, &u1) < 0)
+ goto error;
+
+ FN(UNION,free)(u2);
+
+ return u1;
+error:
+ FN(UNION,free)(u1);
+ FN(UNION,free)(u2);
+ return NULL;
+}
+
+__isl_give UNION *FN(FN(UNION,from),PARTS)(__isl_take PART *part)
+{
+ isl_space *dim;
+ UNION *u;
+
+ if (!part)
+ return NULL;
+
+ dim = FN(PART,get_space)(part);
+ dim = isl_space_drop_dims(dim, isl_dim_in, 0, isl_space_dim(dim, isl_dim_in));
+ dim = isl_space_drop_dims(dim, isl_dim_out, 0, isl_space_dim(dim, isl_dim_out));
+#ifdef HAS_TYPE
+ u = FN(UNION,ZERO)(dim, part->type);
+#else
+ u = FN(UNION,ZERO)(dim);
+#endif
+ u = FN(FN(UNION,add),PARTS)(u, part);
+
+ return u;
+}
+
+S(UNION,match_bin_data) {
+ UNION *u2;
+ UNION *res;
+ __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *);
+};
+
+/* Check if data->u2 has an element living in the same space as *entry.
+ * If so, call data->fn on the two elements and add the result to
+ * data->res.
+ */
+static int match_bin_entry(void **entry, 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, &has_same_domain_space, space, 0);
+ isl_space_free(space);
+ if (!entry2)
+ return 0;
+
+ 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 -1);
+
+ part = FN(PART, copy)(part);
+ part = data->fn(part, FN(PART, copy)(entry2->data));
+
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* This function is currently only used from isl_polynomial.c
+ * and not from isl_fold.c.
+ */
+static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+ __isl_take UNION *u2,
+ __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
+ __attribute__ ((unused));
+/* For each pair of elements in "u1" and "u2" living in the same space,
+ * call "fn" and collect the results.
+ */
+static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+ __isl_take UNION *u2,
+ __isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
+{
+ S(UNION,match_bin_data) data = { NULL, NULL, fn };
+
+ u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+ u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+
+ if (!u1 || !u2)
+ 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,
+ &match_bin_entry, &data) < 0)
+ goto error;
+
+ FN(UNION,free)(u1);
+ FN(UNION,free)(u2);
+ return data.res;
+error:
+ FN(UNION,free)(u1);
+ FN(UNION,free)(u2);
+ FN(UNION,free)(data.res);
+ return NULL;
+}
+
+/* Compute the sum of "u1" and "u2".
+ *
+ * If the base expressions have a default zero value, then the sum
+ * is computed on the union of the domains of "u1" and "u2".
+ * Otherwise, it is computed on their shared domains.
+ */
+__isl_give UNION *FN(UNION,add)(__isl_take UNION *u1, __isl_take UNION *u2)
+{
+#if DEFAULT_IS_ZERO
+ return FN(UNION,union_add_)(u1, u2);
+#else
+ return match_bin_op(u1, u2, &FN(PART,add));
+#endif
+}
+
+#ifndef NO_SUB
+/* Subtract "u2" from "u1" and return the result.
+ */
+__isl_give UNION *FN(UNION,sub)(__isl_take UNION *u1, __isl_take UNION *u2)
+{
+ return match_bin_op(u1, u2, &FN(PART,sub));
+}
+#endif
+
+S(UNION,any_set_data) {
+ isl_set *set;
+ UNION *res;
+ __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+};
+
+static int any_set_entry(void **entry, 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 -1;
+
+ return 0;
+}
+
+/* Update each element of "u" by calling "fn" on the element and "set".
+ */
+static __isl_give 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 };
+
+ u = FN(UNION,align_params)(u, isl_set_get_space(set));
+ set = isl_set_align_params(set, FN(UNION,get_space)(u));
+
+ if (!u || !set)
+ 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,
+ &any_set_entry, &data) < 0)
+ goto error;
+
+ FN(UNION,free)(u);
+ isl_set_free(set);
+ return data.res;
+error:
+ FN(UNION,free)(u);
+ isl_set_free(set);
+ FN(UNION,free)(data.res);
+ return NULL;
+}
+
+/* Intersect the domain of "u" with the parameter domain "context".
+ */
+__isl_give UNION *FN(UNION,intersect_params)(__isl_take UNION *u,
+ __isl_take isl_set *set)
+{
+ return any_set_op(u, set, &FN(PW,intersect_params));
+}
+
+/* Compute the gist of the domain of "u" with respect to
+ * the parameter domain "context".
+ */
+__isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u,
+ __isl_take isl_set *set)
+{
+ return any_set_op(u, set, &FN(PW,gist_params));
+}
+
+S(UNION,match_domain_data) {
+ isl_union_set *uset;
+ UNION *res;
+ __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
+};
+
+static int set_has_dim(const void *entry, const void *val)
+{
+ isl_set *set = (isl_set *)entry;
+ isl_space *dim = (isl_space *)val;
+
+ return isl_space_is_equal(set->dim, dim);
+}
+
+/* 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
+ * the result to data->res.
+ */
+static int match_domain_entry(void **entry, 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);
+ hash = isl_space_get_hash(space);
+ entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
+ hash, &set_has_dim, space, 0);
+ isl_space_free(space);
+ if (!entry2)
+ return 0;
+
+ pw = FN(PW,copy)(pw);
+ pw = data->fn(pw, isl_set_copy(entry2->data));
+
+ data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Apply fn to each pair of PW in u and set in uset such that
+ * the set lives in the same space as the domain of PW
+ * and collect the results.
+ */
+static __isl_give UNION *match_domain_op(__isl_take UNION *u,
+ __isl_take isl_union_set *uset,
+ __isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
+{
+ S(UNION,match_domain_data) data = { NULL, NULL, fn };
+
+ u = FN(UNION,align_params)(u, isl_union_set_get_space(uset));
+ uset = isl_union_set_align_params(uset, FN(UNION,get_space)(u));
+
+ 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 (isl_hash_table_foreach(u->space->ctx, &u->table,
+ &match_domain_entry, &data) < 0)
+ goto error;
+
+ FN(UNION,free)(u);
+ isl_union_set_free(uset);
+ return data.res;
+error:
+ FN(UNION,free)(u);
+ isl_union_set_free(uset);
+ FN(UNION,free)(data.res);
+ return NULL;
+}
+
+/* Intersect the domain of "u" with "uset".
+ * If "uset" is a parameters domain, then intersect the parameter
+ * domain of "u" with this set.
+ */
+__isl_give UNION *FN(UNION,intersect_domain)(__isl_take UNION *u,
+ __isl_take isl_union_set *uset)
+{
+ if (isl_union_set_is_params(uset))
+ return FN(UNION,intersect_params)(u,
+ isl_set_from_union_set(uset));
+ return match_domain_op(u, uset, &FN(PW,intersect_domain));
+}
+
+__isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
+ __isl_take isl_union_set *uset)
+{
+ if (isl_union_set_is_params(uset))
+ return FN(UNION,gist_params)(u, isl_set_from_union_set(uset));
+ return 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, &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
+
+static int coalesce_entry(void **entry, void *user)
+{
+ PW **pw = (PW **)entry;
+
+ *pw = FN(PW,coalesce)(*pw);
+ if (!*pw)
+ return -1;
+
+ return 0;
+}
+
+__isl_give UNION *FN(UNION,coalesce)(__isl_take UNION *u)
+{
+ if (!u)
+ return NULL;
+
+ if (isl_hash_table_foreach(u->space->ctx, &u->table,
+ &coalesce_entry, NULL) < 0)
+ goto error;
+
+ return u;
+error:
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+static int domain(__isl_take PART *part, void *user)
+{
+ isl_union_set **uset = (isl_union_set **)user;
+
+ *uset = isl_union_set_add_set(*uset, FN(PART,domain)(part));
+
+ return 0;
+}
+
+__isl_give isl_union_set *FN(UNION,domain)(__isl_take UNION *u)
+{
+ isl_union_set *uset;
+
+ uset = isl_union_set_empty(FN(UNION,get_space)(u));
+ if (FN(FN(UNION,foreach),PARTS)(u, &domain, &uset) < 0)
+ goto error;
+
+ FN(UNION,free)(u);
+
+ return uset;
+error:
+ isl_union_set_free(uset);
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+static int mul_isl_int(void **entry, void *user)
+{
+ PW **pw = (PW **)entry;
+ isl_int *v = user;
+
+ *pw = FN(PW,mul_isl_int)(*pw, *v);
+ if (!*pw)
+ return -1;
+
+ return 0;
+}
+
+__isl_give UNION *FN(UNION,mul_isl_int)(__isl_take UNION *u, isl_int v)
+{
+ if (isl_int_is_one(v))
+ return u;
+
+ if (DEFAULT_IS_ZERO && u && isl_int_is_zero(v)) {
+ UNION *zero;
+ isl_space *dim = FN(UNION,get_space)(u);
+#ifdef HAS_TYPE
+ zero = FN(UNION,ZERO)(dim, u->type);
+#else
+ zero = FN(UNION,ZERO)(dim);
+#endif
+ FN(UNION,free)(u);
+ return zero;
+ }
+
+ u = FN(UNION,cow)(u);
+ if (!u)
+ return NULL;
+
+#ifdef HAS_TYPE
+ 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,
+ &mul_isl_int, &v) < 0)
+ goto error;
+
+ return u;
+error:
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+/* Multiply *entry by the isl_val "user".
+ *
+ * Return 0 on success and -1 on error.
+ */
+static int scale_val(void **entry, void *user)
+{
+ PW **pw = (PW **)entry;
+ isl_val *v = user;
+
+ *pw = FN(PW,scale_val)(*pw, isl_val_copy(v));
+ if (!*pw)
+ return -1;
+
+ return 0;
+}
+
+/* Multiply "u" by "v" and return the result.
+ */
+__isl_give UNION *FN(UNION,scale_val)(__isl_take UNION *u,
+ __isl_take isl_val *v)
+{
+ if (!u || !v)
+ goto error;
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return u;
+ }
+
+ if (DEFAULT_IS_ZERO && u && isl_val_is_zero(v)) {
+ UNION *zero;
+ isl_space *space = FN(UNION,get_space)(u);
+#ifdef HAS_TYPE
+ zero = FN(UNION,ZERO)(space, u->type);
+#else
+ zero = FN(UNION,ZERO)(space);
+#endif
+ FN(UNION,free)(u);
+ isl_val_free(v);
+ return zero;
+ }
+
+ if (!isl_val_is_rat(v))
+ 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
+ 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, &scale_val, v) < 0)
+ goto error;
+
+ isl_val_free(v);
+ return u;
+error:
+ isl_val_free(v);
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+/* Divide *entry by the isl_val "user".
+ *
+ * Return 0 on success and -1 on error.
+ */
+static int FN(UNION,scale_down_val_entry)(void **entry, void *user)
+{
+ PW **pw = (PW **)entry;
+ isl_val *v = user;
+
+ *pw = FN(PW,scale_down_val)(*pw, isl_val_copy(v));
+ if (!*pw)
+ return -1;
+
+ return 0;
+}
+
+/* Divide "u" by "v" and return the result.
+ */
+__isl_give UNION *FN(UNION,scale_down_val)(__isl_take UNION *u,
+ __isl_take isl_val *v)
+{
+ if (!u || !v)
+ goto error;
+ if (isl_val_is_one(v)) {
+ isl_val_free(v);
+ return u;
+ }
+
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational factor", goto error);
+ if (isl_val_is_zero(v))
+ 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
+ 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;
+
+ isl_val_free(v);
+ return u;
+error:
+ isl_val_free(v);
+ FN(UNION,free)(u);
+ return NULL;
+}
+
+S(UNION,plain_is_equal_data)
+{
+ UNION *u2;
+ int is_equal;
+};
+
+static int 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, &has_same_domain_space, pw->dim, 0);
+ if (!entry2) {
+ data->is_equal = 0;
+ return -1;
+ }
+
+ data->is_equal = FN(PW,plain_is_equal)(pw, entry2->data);
+ if (data->is_equal < 0 || !data->is_equal)
+ return -1;
+
+ return 0;
+}
+
+int FN(UNION,plain_is_equal)(__isl_keep UNION *u1, __isl_keep UNION *u2)
+{
+ S(UNION,plain_is_equal_data) data = { NULL, 1 };
+
+ if (!u1 || !u2)
+ return -1;
+ if (u1 == u2)
+ return 1;
+ if (u1->table.n != u2->table.n)
+ return 0;
+
+ u1 = FN(UNION,copy)(u1);
+ u2 = FN(UNION,copy)(u2);
+ u1 = FN(UNION,align_params)(u1, FN(UNION,get_space)(u2));
+ u2 = FN(UNION,align_params)(u2, FN(UNION,get_space)(u1));
+ if (!u1 || !u2)
+ goto error;
+
+ data.u2 = u2;
+ if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
+ &plain_is_equal_entry, &data) < 0 &&
+ data.is_equal)
+ goto error;
+
+ FN(UNION,free)(u1);
+ FN(UNION,free)(u2);
+
+ return data.is_equal;
+error:
+ FN(UNION,free)(u1);
+ FN(UNION,free)(u2);
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_val.c b/polly/lib/External/isl/isl_val.c
new file mode 100644
index 00000000000..4938c4c3823
--- /dev/null
+++ b/polly/lib/External/isl/isl_val.c
@@ -0,0 +1,1624 @@
+/*
+ * 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_int.h>
+#include <isl_ctx_private.h>
+#include <isl_val_private.h>
+
+#undef BASE
+#define BASE val
+
+#include <isl_list_templ.c>
+
+/* Allocate an isl_val object with indeterminate value.
+ */
+__isl_give isl_val *isl_val_alloc(isl_ctx *ctx)
+{
+ isl_val *v;
+
+ v = isl_alloc_type(ctx, struct isl_val);
+ if (!v)
+ return NULL;
+
+ v->ctx = ctx;
+ isl_ctx_ref(ctx);
+ v->ref = 1;
+ isl_int_init(v->n);
+ isl_int_init(v->d);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing zero.
+ */
+__isl_give isl_val *isl_val_zero(isl_ctx *ctx)
+{
+ return isl_val_int_from_si(ctx, 0);
+}
+
+/* Return a reference to an isl_val representing one.
+ */
+__isl_give isl_val *isl_val_one(isl_ctx *ctx)
+{
+ return isl_val_int_from_si(ctx, 1);
+}
+
+/* Return a reference to an isl_val representing negative one.
+ */
+__isl_give isl_val *isl_val_negone(isl_ctx *ctx)
+{
+ return isl_val_int_from_si(ctx, -1);
+}
+
+/* Return a reference to an isl_val representing NaN.
+ */
+__isl_give isl_val *isl_val_nan(isl_ctx *ctx)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, 0);
+ isl_int_set_si(v->d, 0);
+
+ return v;
+}
+
+/* Change "v" into a NaN.
+ */
+__isl_give isl_val *isl_val_set_nan(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_nan(v))
+ return v;
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, 0);
+ isl_int_set_si(v->d, 0);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing +infinity.
+ */
+__isl_give isl_val *isl_val_infty(isl_ctx *ctx)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, 1);
+ isl_int_set_si(v->d, 0);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing -infinity.
+ */
+__isl_give isl_val *isl_val_neginfty(isl_ctx *ctx)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, -1);
+ isl_int_set_si(v->d, 0);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing the integer "i".
+ */
+__isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, i);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Change the value of "v" to be equal to the integer "i".
+ */
+__isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_int(v) && isl_int_cmp_si(v->n, i) == 0)
+ return v;
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+
+ isl_int_set_si(v->n, i);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Change the value of "v" to be equal to zero.
+ */
+__isl_give isl_val *isl_val_set_zero(__isl_take isl_val *v)
+{
+ return isl_val_set_si(v, 0);
+}
+
+/* Return a reference to an isl_val representing the unsigned integer "u".
+ */
+__isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set_ui(v->n, u);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing the integer "n".
+ */
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set(v->n, n);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing the rational value "n"/"d".
+ * Normalizing the isl_val (if needed) is left to the caller.
+ */
+__isl_give isl_val *isl_val_rat_from_isl_int(isl_ctx *ctx,
+ isl_int n, isl_int d)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set(v->n, n);
+ isl_int_set(v->d, d);
+
+ return v;
+}
+
+/* Return a new reference to "v".
+ */
+__isl_give isl_val *isl_val_copy(__isl_keep isl_val *v)
+{
+ if (!v)
+ return NULL;
+
+ v->ref++;
+ return v;
+}
+
+/* Return a fresh copy of "val".
+ */
+__isl_give isl_val *isl_val_dup(__isl_keep isl_val *val)
+{
+ isl_val *dup;
+
+ if (!val)
+ return NULL;
+
+ dup = isl_val_alloc(isl_val_get_ctx(val));
+ if (!dup)
+ return NULL;
+
+ isl_int_set(dup->n, val->n);
+ isl_int_set(dup->d, val->d);
+
+ return dup;
+}
+
+/* Return an isl_val that is equal to "val" and that has only
+ * a single reference.
+ */
+__isl_give isl_val *isl_val_cow(__isl_take isl_val *val)
+{
+ if (!val)
+ return NULL;
+
+ if (val->ref == 1)
+ return val;
+ val->ref--;
+ return isl_val_dup(val);
+}
+
+/* Free "v" and return NULL.
+ */
+__isl_null isl_val *isl_val_free(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+
+ if (--v->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(v->ctx);
+ isl_int_clear(v->n);
+ isl_int_clear(v->d);
+ free(v);
+ return NULL;
+}
+
+/* Extract the numerator of a rational value "v" as an integer.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+long isl_val_get_num_si(__isl_keep isl_val *v)
+{
+ 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);
+ if (!isl_int_fits_slong(v->n))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "numerator too large", return 0);
+ return isl_int_get_si(v->n);
+}
+
+/* Extract the numerator of a rational value "v" as an isl_int.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_num_isl_int(__isl_keep isl_val *v, isl_int *n)
+{
+ if (!v)
+ return -1;
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return -1);
+ isl_int_set(*n, v->n);
+ return 0;
+}
+
+/* Extract the denominator of a rational value "v" as an integer.
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+long isl_val_get_den_si(__isl_keep isl_val *v)
+{
+ 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);
+ if (!isl_int_fits_slong(v->d))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "denominator too large", return 0);
+ return isl_int_get_si(v->d);
+}
+
+/* Return an approximation of "v" as a double.
+ */
+double isl_val_get_d(__isl_keep isl_val *v)
+{
+ 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);
+ return isl_int_get_d(v->n) / isl_int_get_d(v->d);
+}
+
+/* Return the isl_ctx to which "val" belongs.
+ */
+isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val)
+{
+ return val ? val->ctx : NULL;
+}
+
+/* Normalize "v".
+ *
+ * In particular, make sure that the denominator of a rational value
+ * is positive and the numerator and denominator do not have any
+ * common divisors.
+ *
+ * This function should not be called by an external user
+ * since it will only be given normalized values.
+ */
+__isl_give isl_val *isl_val_normalize(__isl_take isl_val *v)
+{
+ isl_ctx *ctx;
+
+ if (!v)
+ return NULL;
+ if (isl_val_is_int(v))
+ return v;
+ if (!isl_val_is_rat(v))
+ return v;
+ if (isl_int_is_neg(v->d)) {
+ isl_int_neg(v->d, v->d);
+ isl_int_neg(v->n, v->n);
+ }
+ ctx = isl_val_get_ctx(v);
+ isl_int_gcd(ctx->normalize_gcd, v->n, v->d);
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return v;
+ isl_int_divexact(v->n, v->n, ctx->normalize_gcd);
+ isl_int_divexact(v->d, v->d, ctx->normalize_gcd);
+ return v;
+}
+
+/* Return the opposite of "v".
+ */
+__isl_give isl_val *isl_val_neg(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_nan(v))
+ return v;
+ if (isl_val_is_zero(v))
+ return v;
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ isl_int_neg(v->n, v->n);
+
+ return v;
+}
+
+/* Return the inverse of "v".
+ */
+__isl_give isl_val *isl_val_inv(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_nan(v))
+ return v;
+ if (isl_val_is_zero(v)) {
+ isl_ctx *ctx = isl_val_get_ctx(v);
+ isl_val_free(v);
+ return isl_val_nan(ctx);
+ }
+ if (isl_val_is_infty(v) || isl_val_is_neginfty(v)) {
+ isl_ctx *ctx = isl_val_get_ctx(v);
+ isl_val_free(v);
+ return isl_val_zero(ctx);
+ }
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ isl_int_swap(v->n, v->d);
+
+ return isl_val_normalize(v);
+}
+
+/* Return the absolute value of "v".
+ */
+__isl_give isl_val *isl_val_abs(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_nan(v))
+ return v;
+ if (isl_val_is_nonneg(v))
+ return v;
+ return isl_val_neg(v);
+}
+
+/* Return the "floor" (greatest integer part) of "v".
+ * That is, return the result of rounding towards -infinity.
+ */
+__isl_give isl_val *isl_val_floor(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_int(v))
+ return v;
+ if (!isl_val_is_rat(v))
+ return v;
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ isl_int_fdiv_q(v->n, v->n, v->d);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Return the "ceiling" of "v".
+ * That is, return the result of rounding towards +infinity.
+ */
+__isl_give isl_val *isl_val_ceil(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_int(v))
+ return v;
+ if (!isl_val_is_rat(v))
+ return v;
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ isl_int_cdiv_q(v->n, v->n, v->d);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Truncate "v".
+ * That is, return the result of rounding towards zero.
+ */
+__isl_give isl_val *isl_val_trunc(__isl_take isl_val *v)
+{
+ if (!v)
+ return NULL;
+ if (isl_val_is_int(v))
+ return v;
+ if (!isl_val_is_rat(v))
+ return v;
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ isl_int_tdiv_q(v->n, v->n, v->d);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Return 2^v, where v is an integer (that is not too large).
+ */
+__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v)
+{
+ unsigned long exp;
+ int neg;
+
+ v = isl_val_cow(v);
+ if (!v)
+ return NULL;
+ if (!isl_val_is_int(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "can only compute integer powers",
+ return isl_val_free(v));
+ neg = isl_val_is_neg(v);
+ if (neg)
+ isl_int_neg(v->n, v->n);
+ if (!isl_int_fits_ulong(v->n))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "exponent too large", return isl_val_free(v));
+ exp = isl_int_get_ui(v->n);
+ if (neg) {
+ isl_int_mul_2exp(v->d, v->d, exp);
+ isl_int_set_si(v->n, 1);
+ } else {
+ isl_int_mul_2exp(v->n, v->d, exp);
+ }
+
+ return v;
+}
+
+/* Return the minimum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_le(v1, v2)) {
+ isl_val_free(v2);
+ return v1;
+ } else {
+ isl_val_free(v1);
+ return v2;
+ }
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Return the maximum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_ge(v1, v2)) {
+ isl_val_free(v2);
+ return v1;
+ } else {
+ isl_val_free(v1);
+ return v2;
+ }
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Return the sum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if ((isl_val_is_infty(v1) && isl_val_is_neginfty(v2)) ||
+ (isl_val_is_neginfty(v1) && isl_val_is_infty(v2))) {
+ isl_val_free(v2);
+ return isl_val_set_nan(v1);
+ }
+ if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_is_zero(v1)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_is_zero(v2)) {
+ isl_val_free(v2);
+ return v1;
+ }
+
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ if (isl_val_is_int(v1) && isl_val_is_int(v2))
+ isl_int_add(v1->n, v1->n, v2->n);
+ else {
+ if (isl_int_eq(v1->d, v2->d))
+ isl_int_add(v1->n, v1->n, v2->n);
+ else {
+ isl_int_mul(v1->n, v1->n, v2->d);
+ isl_int_addmul(v1->n, v2->n, v1->d);
+ isl_int_mul(v1->d, v1->d, v2->d);
+ }
+ v1 = isl_val_normalize(v1);
+ }
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Return the sum of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+ if (!v1)
+ return NULL;
+ if (!isl_val_is_rat(v1))
+ return v1;
+ if (v2 == 0)
+ return v1;
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ return NULL;
+
+ isl_int_addmul_ui(v1->n, v1->d, v2);
+
+ return v1;
+}
+
+/* Subtract "v2" from "v1".
+ */
+__isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if ((isl_val_is_infty(v1) && isl_val_is_infty(v2)) ||
+ (isl_val_is_neginfty(v1) && isl_val_is_neginfty(v2))) {
+ isl_val_free(v2);
+ return isl_val_set_nan(v1);
+ }
+ if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+ isl_val_free(v1);
+ return isl_val_neg(v2);
+ }
+ if (isl_val_is_zero(v2)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_zero(v1)) {
+ isl_val_free(v1);
+ return isl_val_neg(v2);
+ }
+
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ if (isl_val_is_int(v1) && isl_val_is_int(v2))
+ isl_int_sub(v1->n, v1->n, v2->n);
+ else {
+ if (isl_int_eq(v1->d, v2->d))
+ isl_int_sub(v1->n, v1->n, v2->n);
+ else {
+ isl_int_mul(v1->n, v1->n, v2->d);
+ isl_int_submul(v1->n, v2->n, v1->d);
+ isl_int_mul(v1->d, v1->d, v2->d);
+ }
+ v1 = isl_val_normalize(v1);
+ }
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Subtract "v2" from "v1".
+ */
+__isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+ if (!v1)
+ return NULL;
+ if (!isl_val_is_rat(v1))
+ return v1;
+ if (v2 == 0)
+ return v1;
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ return NULL;
+
+ isl_int_submul_ui(v1->n, v1->d, v2);
+
+ return v1;
+}
+
+/* Return the product of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if ((!isl_val_is_rat(v1) && isl_val_is_zero(v2)) ||
+ (isl_val_is_zero(v1) && !isl_val_is_rat(v2))) {
+ isl_val_free(v2);
+ return isl_val_set_nan(v1);
+ }
+ if (isl_val_is_zero(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_zero(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+ if (isl_val_is_neg(v2))
+ v1 = isl_val_neg(v1);
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+ if (isl_val_is_neg(v1))
+ v2 = isl_val_neg(v2);
+ isl_val_free(v1);
+ return v2;
+ }
+
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ if (isl_val_is_int(v1) && isl_val_is_int(v2))
+ isl_int_mul(v1->n, v1->n, v2->n);
+ else {
+ isl_int_mul(v1->n, v1->n, v2->n);
+ isl_int_mul(v1->d, v1->d, v2->d);
+ v1 = isl_val_normalize(v1);
+ }
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Return the product of "v1" and "v2".
+ *
+ * This is a private copy of isl_val_mul for use in the generic
+ * isl_multi_*_scale_val instantiated for isl_val.
+ */
+__isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2)
+{
+ return isl_val_mul(v1, v2);
+}
+
+/* Return the product of "v1" and "v2".
+ */
+__isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2)
+{
+ if (!v1)
+ return NULL;
+ if (isl_val_is_nan(v1))
+ return v1;
+ if (!isl_val_is_rat(v1)) {
+ if (v2 == 0)
+ v1 = isl_val_set_nan(v1);
+ return v1;
+ }
+ if (v2 == 1)
+ return v1;
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ return NULL;
+
+ isl_int_mul_ui(v1->n, v1->n, v2);
+
+ return isl_val_normalize(v1);
+}
+
+/* Divide "v1" by "v2".
+ */
+__isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (isl_val_is_nan(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_nan(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ if (isl_val_is_zero(v2) ||
+ (!isl_val_is_rat(v1) && !isl_val_is_rat(v2))) {
+ isl_val_free(v2);
+ return isl_val_set_nan(v1);
+ }
+ if (isl_val_is_zero(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_infty(v1) || isl_val_is_neginfty(v1)) {
+ if (isl_val_is_neg(v2))
+ v1 = isl_val_neg(v1);
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_infty(v2) || isl_val_is_neginfty(v2)) {
+ isl_val_free(v2);
+ return isl_val_set_zero(v1);
+ }
+
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ if (isl_val_is_int(v2)) {
+ isl_int_mul(v1->d, v1->d, v2->n);
+ v1 = isl_val_normalize(v1);
+ } else {
+ isl_int_mul(v1->d, v1->d, v2->n);
+ isl_int_mul(v1->n, v1->n, v2->d);
+ v1 = isl_val_normalize(v1);
+ }
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Divide "v1" by "v2".
+ *
+ * This is a private copy of isl_val_div for use in the generic
+ * isl_multi_*_scale_down_val instantiated for isl_val.
+ */
+__isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2)
+{
+ return isl_val_div(v1, v2);
+}
+
+/* Given two integer values "v1" and "v2", check if "v1" is divisible by "v2".
+ */
+int isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ if (!v1 || !v2)
+ return -1;
+
+ if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+ isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+ "expecting two integers", return -1);
+
+ return isl_int_is_divisible_by(v1->n, v2->n);
+}
+
+/* Given two integer values "v1" and "v2", return the residue of "v1"
+ * modulo "v2".
+ */
+__isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+ isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+ "expecting two integers", goto error);
+ if (isl_val_is_nonneg(v1) && isl_val_lt(v1, v2)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ isl_int_fdiv_r(v1->n, v1->n, v2->n);
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* Given two integer values, return their greatest common divisor.
+ */
+__isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2)
+{
+ if (!v1 || !v2)
+ goto error;
+ if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+ isl_die(isl_val_get_ctx(v1), isl_error_invalid,
+ "expecting two integers", goto error);
+ if (isl_val_eq(v1, v2)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_one(v1)) {
+ isl_val_free(v2);
+ return v1;
+ }
+ if (isl_val_is_one(v2)) {
+ isl_val_free(v1);
+ return v2;
+ }
+ v1 = isl_val_cow(v1);
+ if (!v1)
+ goto error;
+ isl_int_gcd(v1->n, v1->n, v2->n);
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ return NULL;
+}
+
+/* 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,
+ isl_int a, isl_int b)
+{
+ isl_int d, tmp;
+ isl_int a_copy, b_copy;
+
+ isl_int_init(a_copy);
+ isl_int_init(b_copy);
+ isl_int_init(d);
+ 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(d, b_copy);
+ 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);
+ }
+ if (isl_int_is_zero(a_copy))
+ isl_int_set_si(x, 0);
+ else if (isl_int_is_neg(a_copy))
+ isl_int_neg(x, x);
+ if (isl_int_is_zero(b_copy))
+ 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_clear(d);
+ isl_int_clear(tmp);
+ isl_int_clear(a_copy);
+ isl_int_clear(b_copy);
+}
+
+/* Given two integer values v1 and v2, return their greatest common divisor g,
+ * as well as two integers x and y such that x * v1 + y * v2 = g.
+ */
+__isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
+ __isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y)
+{
+ isl_ctx *ctx;
+ isl_val *a = NULL, *b = NULL;
+
+ if (!x && !y)
+ return isl_val_gcd(v1, v2);
+
+ if (!v1 || !v2)
+ goto error;
+
+ ctx = isl_val_get_ctx(v1);
+ if (!isl_val_is_int(v1) || !isl_val_is_int(v2))
+ isl_die(ctx, isl_error_invalid,
+ "expecting two integers", goto error);
+
+ v1 = isl_val_cow(v1);
+ a = isl_val_alloc(ctx);
+ b = isl_val_alloc(ctx);
+ if (!v1 || !a || !b)
+ goto error;
+ isl_int_gcdext(v1->n, a->n, b->n, v1->n, v2->n);
+ if (x) {
+ isl_int_set_si(a->d, 1);
+ *x = a;
+ } else
+ isl_val_free(a);
+ if (y) {
+ isl_int_set_si(b->d, 1);
+ *y = b;
+ } else
+ isl_val_free(b);
+ isl_val_free(v2);
+ return v1;
+error:
+ isl_val_free(v1);
+ isl_val_free(v2);
+ isl_val_free(a);
+ isl_val_free(b);
+ if (x)
+ *x = NULL;
+ if (y)
+ *y = NULL;
+ return NULL;
+}
+
+/* Does "v" represent an integer value?
+ */
+int isl_val_is_int(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_one(v->d);
+}
+
+/* Does "v" represent a rational value?
+ */
+int isl_val_is_rat(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return !isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent NaN?
+ */
+int isl_val_is_nan(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_zero(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent +infinity?
+ */
+int isl_val_is_infty(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_pos(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent -infinity?
+ */
+int isl_val_is_neginfty(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_neg(v->n) && isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent the integer zero?
+ */
+int isl_val_is_zero(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_zero(v->n) && !isl_int_is_zero(v->d);
+}
+
+/* Does "v" represent the integer one?
+ */
+int isl_val_is_one(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_eq(v->n, v->d);
+}
+
+/* Does "v" represent the integer negative one?
+ */
+int isl_val_is_negone(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_neg(v->n) && isl_int_abs_eq(v->n, v->d);
+}
+
+/* Is "v" (strictly) positive?
+ */
+int isl_val_is_pos(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_pos(v->n);
+}
+
+/* Is "v" (strictly) negative?
+ */
+int isl_val_is_neg(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ return isl_int_is_neg(v->n);
+}
+
+/* Is "v" non-negative?
+ */
+int isl_val_is_nonneg(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ if (isl_val_is_nan(v))
+ return 0;
+
+ return isl_int_is_nonneg(v->n);
+}
+
+/* Is "v" non-positive?
+ */
+int isl_val_is_nonpos(__isl_keep isl_val *v)
+{
+ if (!v)
+ return -1;
+
+ if (isl_val_is_nan(v))
+ return 0;
+
+ return isl_int_is_nonpos(v->n);
+}
+
+/* Return the sign of "v".
+ *
+ * The sign of NaN is undefined.
+ */
+int isl_val_sgn(__isl_keep isl_val *v)
+{
+ if (!v)
+ return 0;
+ if (isl_val_is_zero(v))
+ return 0;
+ if (isl_val_is_pos(v))
+ return 1;
+ return -1;
+}
+
+/* Is "v1" (strictly) less than "v2"?
+ */
+int isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ isl_int t;
+ int lt;
+
+ if (!v1 || !v2)
+ return -1;
+ if (isl_val_is_int(v1) && isl_val_is_int(v2))
+ return isl_int_lt(v1->n, v2->n);
+ if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+ return 0;
+ if (isl_val_eq(v1, v2))
+ return 0;
+ if (isl_val_is_infty(v2))
+ return 1;
+ if (isl_val_is_infty(v1))
+ return 0;
+ if (isl_val_is_neginfty(v1))
+ return 1;
+ if (isl_val_is_neginfty(v2))
+ return 0;
+
+ isl_int_init(t);
+ isl_int_mul(t, v1->n, v2->d);
+ isl_int_submul(t, v2->n, v1->d);
+ lt = isl_int_is_neg(t);
+ isl_int_clear(t);
+
+ return lt;
+}
+
+/* Is "v1" (strictly) greater than "v2"?
+ */
+int isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ return isl_val_lt(v2, v1);
+}
+
+/* Is "v1" less than or equal to "v2"?
+ */
+int isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ isl_int t;
+ int le;
+
+ if (!v1 || !v2)
+ return -1;
+ if (isl_val_is_int(v1) && isl_val_is_int(v2))
+ return isl_int_le(v1->n, v2->n);
+ if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+ return 0;
+ if (isl_val_eq(v1, v2))
+ return 1;
+ if (isl_val_is_infty(v2))
+ return 1;
+ if (isl_val_is_infty(v1))
+ return 0;
+ if (isl_val_is_neginfty(v1))
+ return 1;
+ if (isl_val_is_neginfty(v2))
+ return 0;
+
+ isl_int_init(t);
+ isl_int_mul(t, v1->n, v2->d);
+ isl_int_submul(t, v2->n, v1->d);
+ le = isl_int_is_nonpos(t);
+ isl_int_clear(t);
+
+ return le;
+}
+
+/* Is "v1" greater than or equal to "v2"?
+ */
+int isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ return isl_val_le(v2, v1);
+}
+
+/* How does "v" compare to "i"?
+ *
+ * Return 1 if v is greater, -1 if v is smaller and 0 if v is equal to i.
+ *
+ * If v is NaN (or NULL), then the result is undefined.
+ */
+int isl_val_cmp_si(__isl_keep isl_val *v, long i)
+{
+ isl_int t;
+ int cmp;
+
+ if (!v)
+ return 0;
+ if (isl_val_is_int(v))
+ return isl_int_cmp_si(v->n, i);
+ if (isl_val_is_nan(v))
+ return 0;
+ if (isl_val_is_infty(v))
+ return 1;
+ if (isl_val_is_neginfty(v))
+ return -1;
+
+ isl_int_init(t);
+ isl_int_mul_si(t, v->d, i);
+ isl_int_sub(t, v->n, t);
+ cmp = isl_int_sgn(t);
+ isl_int_clear(t);
+
+ return cmp;
+}
+
+/* Is "v1" equal to "v2"?
+ */
+int isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ if (!v1 || !v2)
+ return -1;
+ if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+ return 0;
+
+ return isl_int_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+}
+
+/* Is "v1" equal to "v2" in absolute value?
+ */
+int isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ if (!v1 || !v2)
+ return -1;
+ if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+ return 0;
+
+ return isl_int_abs_eq(v1->n, v2->n) && isl_int_eq(v1->d, v2->d);
+}
+
+/* Is "v1" different from "v2"?
+ */
+int isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2)
+{
+ if (!v1 || !v2)
+ return -1;
+ if (isl_val_is_nan(v1) || isl_val_is_nan(v2))
+ return 0;
+
+ return isl_int_ne(v1->n, v2->n) || isl_int_ne(v1->d, v2->d);
+}
+
+/* Print a textual representation of "v" onto "p".
+ */
+__isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
+ __isl_keep isl_val *v)
+{
+ int neg;
+
+ if (!p || !v)
+ return isl_printer_free(p);
+
+ neg = isl_int_is_neg(v->n);
+ if (neg) {
+ p = isl_printer_print_str(p, "-");
+ isl_int_neg(v->n, v->n);
+ }
+ if (isl_int_is_zero(v->d)) {
+ int sgn = isl_int_sgn(v->n);
+ p = isl_printer_print_str(p, sgn < 0 ? "-infty" :
+ sgn == 0 ? "NaN" : "infty");
+ } else
+ p = isl_printer_print_isl_int(p, v->n);
+ if (neg)
+ isl_int_neg(v->n, v->n);
+ if (!isl_int_is_zero(v->d) && !isl_int_is_one(v->d)) {
+ p = isl_printer_print_str(p, "/");
+ p = isl_printer_print_isl_int(p, v->d);
+ }
+
+ return p;
+}
+
+/* Is "val1" (obviously) equal to "val2"?
+ *
+ * This is a private copy of isl_val_eq for use in the generic
+ * isl_multi_*_plain_is_equal instantiated for isl_val.
+ */
+int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2)
+{
+ return isl_val_eq(val1, val2);
+}
+
+/* Does "v" have any non-zero coefficients
+ * for any dimension in the given range?
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have any coefficients, this function
+ * always return 0.
+ */
+int isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type,
+ unsigned first, unsigned n)
+{
+ if (!v)
+ return -1;
+
+ return 0;
+}
+
+/* Insert "n" dimensions of type "type" at position "first".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return v;
+}
+
+/* Drop the the "n" first dimensions of type "type" at position "first".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return v;
+}
+
+/* Change the name of the dimension of type "type" at position "pos" to "s".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything.
+ */
+__isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ return v;
+}
+
+/* Return the space of "v".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. The conditions surrounding the call to this function make sure
+ * that this function will never actually get called. We return a valid
+ * space anyway, just in case.
+ */
+__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v)
+{
+ if (!v)
+ return NULL;
+
+ return isl_space_params_alloc(isl_val_get_ctx(v), 0);
+}
+
+/* Reset the domain space of "v" to "space".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
+ __isl_take isl_space *space)
+{
+ if (!space)
+ return isl_val_free(v);
+ isl_space_free(space);
+ return v;
+}
+
+/* Align the parameters of "v" to those of "space".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ * Note that the conditions surrounding the call to this function make sure
+ * that this function will never actually get called.
+ */
+__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
+ __isl_take isl_space *space)
+{
+ if (!space)
+ return isl_val_free(v);
+ isl_space_free(space);
+ return v;
+}
+
+/* Reorder the dimensions of the domain of "v" according
+ * to the given reordering.
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * does not do anything, apart from error handling and cleaning up memory.
+ */
+__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
+ __isl_take isl_reordering *r)
+{
+ if (!r)
+ return isl_val_free(v);
+ isl_reordering_free(r);
+ return v;
+}
+
+/* Return an isl_val that is zero on "ls".
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * simply returns a zero isl_val in the same context as "ls".
+ */
+__isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls)
+{
+ isl_ctx *ctx;
+
+ if (!ls)
+ return NULL;
+ ctx = isl_local_space_get_ctx(ls);
+ isl_local_space_free(ls);
+ return isl_val_zero(ctx);
+}
+
+/* Do the parameters of "v" match those of "space"?
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * simply returns 1, except if "v" or "space" are NULL.
+ */
+int isl_val_matching_params(__isl_keep isl_val *v, __isl_keep isl_space *space)
+{
+ if (!v || !space)
+ return -1;
+ return 1;
+}
+
+/* Check that the domain space of "v" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * This function is only meant to be used in the generic isl_multi_*
+ * functions which have to deal with base objects that have an associated
+ * space. Since an isl_val does not have an associated space, this function
+ * simply returns 0, except if "v" or "space" are NULL.
+ */
+int isl_val_check_match_domain_space(__isl_keep isl_val *v,
+ __isl_keep isl_space *space)
+{
+ if (!v || !space)
+ return -1;
+ return 0;
+}
+
+#undef BASE
+#define BASE val
+
+#define NO_DOMAIN
+#define NO_INTERSECT_DOMAIN
+#define NO_GIST
+#define NO_IDENTITY
+#define NO_FROM_BASE
+#define NO_MOVE_DIMS
+#include <isl_multi_templ.c>
+
+/* Apply "fn" to each of the elements of "mv" with as second argument "v".
+ */
+static __isl_give isl_multi_val *isl_multi_val_fn_val(
+ __isl_take isl_multi_val *mv,
+ __isl_give isl_val *(*fn)(__isl_take isl_val *v1,
+ __isl_take isl_val *v2),
+ __isl_take isl_val *v)
+{
+ int i;
+
+ mv = isl_multi_val_cow(mv);
+ if (!mv || !v)
+ goto error;
+
+ for (i = 0; i < mv->n; ++i) {
+ mv->p[i] = fn(mv->p[i], isl_val_copy(v));
+ if (!mv->p[i])
+ goto error;
+ }
+
+ isl_val_free(v);
+ return mv;
+error:
+ isl_val_free(v);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Add "v" to each of the elements of "mv".
+ */
+__isl_give isl_multi_val *isl_multi_val_add_val(__isl_take isl_multi_val *mv,
+ __isl_take isl_val *v)
+{
+ if (!v)
+ return isl_multi_val_free(mv);
+ if (isl_val_is_zero(v)) {
+ isl_val_free(v);
+ return mv;
+ }
+ return isl_multi_val_fn_val(mv, &isl_val_add, v);
+}
+
+/* Reduce the elements of "mv" modulo "v".
+ */
+__isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv,
+ __isl_take isl_val *v)
+{
+ return isl_multi_val_fn_val(mv, &isl_val_mod, v);
+}
diff --git a/polly/lib/External/isl/isl_val_gmp.c b/polly/lib/External/isl/isl_val_gmp.c
new file mode 100644
index 00000000000..42e8d444671
--- /dev/null
+++ b/polly/lib/External/isl/isl_val_gmp.c
@@ -0,0 +1,128 @@
+#include <string.h>
+#include <isl/val_gmp.h>
+#include <isl_val_private.h>
+
+/* Return a reference to an isl_val representing the integer "z".
+ */
+__isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx, mpz_t z)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set(v->n, z);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* Return a reference to an isl_val representing the rational value "n"/"d".
+ */
+__isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx, const mpz_t n, const mpz_t d)
+{
+ isl_val *v;
+
+ v = isl_val_alloc(ctx);
+ if (!v)
+ return NULL;
+
+ isl_int_set(v->n, n);
+ isl_int_set(v->d, d);
+
+ return isl_val_normalize(v);
+}
+
+/* Extract the numerator of a rational value "v" in "z".
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z)
+{
+ if (!v)
+ return -1;
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return -1);
+ mpz_set(z, v->n);
+ return 0;
+}
+
+/* Extract the denominator of a rational value "v" in "z".
+ *
+ * If "v" is not a rational value, then the result is undefined.
+ */
+int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z)
+{
+ if (!v)
+ return -1;
+ if (!isl_val_is_rat(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting rational value", return -1);
+ mpz_set(z, v->d);
+ return 0;
+}
+
+/* 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;
+
+ mpz_import(v->n, n, -1, size, 0, 0, chunks);
+ isl_int_set_si(v->d, 1);
+
+ return v;
+}
+
+/* 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 (mpz_sizeinbase(v->n, 2) + size - 1) / size;
+}
+
+/* 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 mpz_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)
+{
+ 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);
+
+ mpz_export(chunks, NULL, -1, size, 0, 0, v->n);
+ if (isl_val_is_zero(v))
+ memset(chunks, 0, size);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/isl_val_imath.c b/polly/lib/External/isl/isl_val_imath.c
new file mode 100644
index 00000000000..8f91700a895
--- /dev/null
+++ b/polly/lib/External/isl/isl_val_imath.c
@@ -0,0 +1,64 @@
+#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(v->n, n, -1, size, 0, 0, chunks);
+ 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)
+{
+ 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, v->n);
+ 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 (impz_sizeinbase(v->n, 2) + size - 1) / size;
+}
diff --git a/polly/lib/External/isl/isl_val_private.h b/polly/lib/External/isl/isl_val_private.h
new file mode 100644
index 00000000000..722fcf07639
--- /dev/null
+++ b/polly/lib/External/isl/isl_val_private.h
@@ -0,0 +1,70 @@
+#ifndef ISL_VAL_PRIVATE_H
+#define ISL_VAL_PRIVATE_H
+
+#include <isl_int.h>
+#include <isl/val.h>
+#include <isl/local_space.h>
+#include <isl_reordering.h>
+
+/* Represents a "value", which may be an integer value, a rational value,
+ * plus or minus infinity or "not a number".
+ *
+ * Internally, +infinity is represented as 1/0,
+ * -infinity as -1/0 and NaN as 0/0.
+ *
+ * A rational value is always normalized before it is passed to the user.
+ */
+struct isl_val {
+ int ref;
+ isl_ctx *ctx;
+
+ isl_int n;
+ isl_int d;
+};
+
+#undef EL
+#define EL isl_val
+
+#include <isl_list_templ.h>
+
+__isl_give isl_val *isl_val_alloc(isl_ctx *ctx);
+__isl_give isl_val *isl_val_normalize(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n);
+__isl_give isl_val *isl_val_rat_from_isl_int(isl_ctx *ctx,
+ isl_int n, isl_int d);
+__isl_give isl_val *isl_val_cow(__isl_take isl_val *val);
+
+int isl_val_involves_dims(__isl_keep isl_val *v, enum isl_dim_type type,
+ unsigned first, unsigned n);
+__isl_give isl_val *isl_val_insert_dims(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_val *isl_val_drop_dims(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_val *isl_val_set_dim_name(__isl_take isl_val *v,
+ enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_space *isl_val_get_space(__isl_keep isl_val *v);
+__isl_give isl_val *isl_val_reset_domain_space(__isl_take isl_val *v,
+ __isl_take isl_space *space);
+__isl_give isl_val *isl_val_align_params(__isl_take isl_val *v,
+ __isl_take isl_space *space);
+__isl_give isl_val *isl_val_realign_domain(__isl_take isl_val *v,
+ __isl_take isl_reordering *r);
+__isl_give isl_val *isl_val_zero_on_domain(__isl_take isl_local_space *ls);
+
+__isl_give isl_val *isl_val_scale_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
+
+int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2);
+
+int isl_val_matching_params(__isl_keep isl_val *v, __isl_keep isl_space *space);
+int isl_val_check_match_domain_space(__isl_keep isl_val *v,
+ __isl_keep isl_space *space);
+
+#undef BASE
+#define BASE val
+
+#include <isl_multi_templ.h>
+
+#endif
diff --git a/polly/lib/External/isl/isl_vec.c b/polly/lib/External/isl/isl_vec.c
new file mode 100644
index 00000000000..a8582be3996
--- /dev/null
+++ b/polly/lib/External/isl/isl_vec.c
@@ -0,0 +1,579 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ * and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_seq.h>
+#include <isl_val_private.h>
+#include <isl_vec_private.h>
+#include <isl/deprecated/vec_int.h>
+
+isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec)
+{
+ return vec ? vec->ctx : NULL;
+}
+
+struct isl_vec *isl_vec_alloc(struct isl_ctx *ctx, unsigned size)
+{
+ struct isl_vec *vec;
+
+ vec = isl_alloc_type(ctx, struct isl_vec);
+ if (!vec)
+ return NULL;
+
+ vec->block = isl_blk_alloc(ctx, size);
+ if (isl_blk_is_error(vec->block))
+ goto error;
+
+ vec->ctx = ctx;
+ isl_ctx_ref(ctx);
+ vec->ref = 1;
+ vec->size = size;
+ vec->el = vec->block.data;
+
+ return vec;
+error:
+ isl_blk_free(ctx, vec->block);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size)
+{
+ if (!vec)
+ return NULL;
+ if (size <= vec->size)
+ return vec;
+
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+
+ vec->block = isl_blk_extend(vec->ctx, vec->block, size);
+ if (!vec->block.data)
+ goto error;
+
+ vec->size = size;
+ vec->el = vec->block.data;
+
+ return vec;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size)
+{
+ int extra;
+
+ if (!vec)
+ return NULL;
+ if (size <= vec->size)
+ return vec;
+
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+
+ extra = size - vec->size;
+ vec = isl_vec_extend(vec, size);
+ if (!vec)
+ return NULL;
+
+ isl_seq_clr(vec->el + size - extra, extra);
+
+ return vec;
+}
+
+/* Return a vector containing the elements of "vec1" followed by
+ * those of "vec2".
+ */
+__isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
+ __isl_take isl_vec *vec2)
+{
+ if (!vec1 || !vec2)
+ goto error;
+
+ if (vec2->size == 0) {
+ isl_vec_free(vec2);
+ return vec1;
+ }
+
+ if (vec1->size == 0) {
+ isl_vec_free(vec1);
+ return vec2;
+ }
+
+ vec1 = isl_vec_extend(vec1, vec1->size + vec2->size);
+ if (!vec1)
+ goto error;
+
+ isl_seq_cpy(vec1->el + vec1->size - vec2->size, vec2->el, vec2->size);
+
+ isl_vec_free(vec2);
+ return vec1;
+error:
+ isl_vec_free(vec1);
+ isl_vec_free(vec2);
+ return NULL;
+}
+
+struct isl_vec *isl_vec_copy(struct isl_vec *vec)
+{
+ if (!vec)
+ return NULL;
+
+ vec->ref++;
+ return vec;
+}
+
+struct isl_vec *isl_vec_dup(struct isl_vec *vec)
+{
+ struct isl_vec *vec2;
+
+ if (!vec)
+ return NULL;
+ vec2 = isl_vec_alloc(vec->ctx, vec->size);
+ if (!vec2)
+ return NULL;
+ isl_seq_cpy(vec2->el, vec->el, vec->size);
+ return vec2;
+}
+
+struct isl_vec *isl_vec_cow(struct isl_vec *vec)
+{
+ struct isl_vec *vec2;
+ if (!vec)
+ return NULL;
+
+ if (vec->ref == 1)
+ return vec;
+
+ vec2 = isl_vec_dup(vec);
+ isl_vec_free(vec);
+ return vec2;
+}
+
+__isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec)
+{
+ if (!vec)
+ return NULL;
+
+ if (--vec->ref > 0)
+ return NULL;
+
+ isl_ctx_deref(vec->ctx);
+ isl_blk_free(vec->ctx, vec->block);
+ free(vec);
+
+ return NULL;
+}
+
+int isl_vec_size(__isl_keep isl_vec *vec)
+{
+ return vec ? vec->size : -1;
+}
+
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v)
+{
+ if (!vec)
+ return -1;
+
+ if (pos < 0 || pos >= vec->size)
+ isl_die(vec->ctx, isl_error_invalid, "position out of range",
+ return -1);
+ isl_int_set(*v, vec->el[pos]);
+ return 0;
+}
+
+/* Extract the element at position "pos" of "vec".
+ */
+__isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos)
+{
+ isl_ctx *ctx;
+
+ if (!vec)
+ return NULL;
+ ctx = isl_vec_get_ctx(vec);
+ if (pos < 0 || pos >= vec->size)
+ isl_die(ctx, isl_error_invalid, "position out of range",
+ return NULL);
+ return isl_val_int_from_isl_int(ctx, vec->el[pos]);
+}
+
+__isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
+ int pos, isl_int v)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ if (pos < 0 || pos >= vec->size)
+ isl_die(vec->ctx, isl_error_invalid, "position out of range",
+ goto error);
+ isl_int_set(vec->el[pos], v);
+ return vec;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
+ int pos, int v)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ if (pos < 0 || pos >= vec->size)
+ isl_die(vec->ctx, isl_error_invalid, "position out of range",
+ goto error);
+ isl_int_set_si(vec->el[pos], v);
+ return vec;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+/* Replace the element at position "pos" of "vec" by "v".
+ */
+__isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec,
+ int pos, __isl_take isl_val *v)
+{
+ if (!v)
+ return isl_vec_free(vec);
+ if (!isl_val_is_int(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting integer value", goto error);
+ vec = isl_vec_set_element(vec, pos, v->n);
+ isl_val_free(v);
+ return vec;
+error:
+ isl_val_free(v);
+ return isl_vec_free(vec);
+}
+
+/* Compare the elements of "vec1" and "vec2" at position "pos".
+ */
+int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2,
+ int pos)
+{
+ if (!vec1 || !vec2)
+ return 0;
+ if (pos < 0 || pos >= vec1->size || pos >= vec2->size)
+ isl_die(isl_vec_get_ctx(vec1), isl_error_invalid,
+ "position out of range", return 0);
+ return isl_int_cmp(vec1->el[pos], vec2->el[pos]);
+}
+
+int isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2)
+{
+ if (!vec1 || !vec2)
+ return -1;
+
+ if (vec1->size != vec2->size)
+ return 0;
+
+ return isl_seq_eq(vec1->el, vec2->el, vec1->size);
+}
+
+__isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
+ __isl_keep isl_vec *vec)
+{
+ int i;
+
+ if (!printer || !vec)
+ goto error;
+
+ printer = isl_printer_print_str(printer, "[");
+ for (i = 0; i < vec->size; ++i) {
+ if (i)
+ printer = isl_printer_print_str(printer, ",");
+ printer = isl_printer_print_isl_int(printer, vec->el[i]);
+ }
+ printer = isl_printer_print_str(printer, "]");
+
+ return printer;
+error:
+ isl_printer_free(printer);
+ return NULL;
+}
+
+void isl_vec_dump(struct isl_vec *vec)
+{
+ isl_printer *printer;
+
+ if (!vec)
+ return;
+
+ printer = isl_printer_to_file(vec->ctx, stderr);
+ printer = isl_printer_print_vec(printer, vec);
+ printer = isl_printer_end_line(printer);
+
+ isl_printer_free(printer);
+}
+
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ isl_seq_set(vec->el, v, vec->size);
+ return vec;
+}
+
+__isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ isl_seq_set_si(vec->el, v, vec->size);
+ return vec;
+}
+
+/* Replace all elements of "vec" by "v".
+ */
+__isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec,
+ __isl_take isl_val *v)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec || !v)
+ goto error;
+ if (!isl_val_is_int(v))
+ isl_die(isl_val_get_ctx(v), isl_error_invalid,
+ "expecting integer value", goto error);
+ isl_seq_set(vec->el, v->n, vec->size);
+ isl_val_free(v);
+ return vec;
+error:
+ isl_vec_free(vec);
+ isl_val_free(v);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ isl_seq_clr(vec->el, vec->size);
+ return vec;
+}
+
+void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm)
+{
+ isl_seq_lcm(vec->block.data, vec->size, lcm);
+}
+
+/* Given a rational vector, with the denominator in the first element
+ * of the vector, round up all coordinates.
+ */
+struct isl_vec *isl_vec_ceil(struct isl_vec *vec)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+
+ isl_seq_cdiv_q(vec->el + 1, vec->el + 1, vec->el[0], vec->size - 1);
+
+ isl_int_set_si(vec->el[0], 1);
+
+ return vec;
+}
+
+struct isl_vec *isl_vec_normalize(struct isl_vec *vec)
+{
+ if (!vec)
+ return NULL;
+ isl_seq_normalize(vec->ctx, vec->el, vec->size);
+ return vec;
+}
+
+__isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ isl_seq_neg(vec->el, vec->el, vec->size);
+ return vec;
+}
+
+__isl_give isl_vec *isl_vec_scale(__isl_take isl_vec *vec, isl_int m)
+{
+ if (isl_int_is_one(m))
+ return vec;
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+ isl_seq_scale(vec->el, vec->el, m, vec->size);
+ return vec;
+}
+
+/* Reduce the elements of "vec" modulo "m".
+ */
+__isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m)
+{
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+
+ isl_seq_fdiv_r(vec->el, vec->el, m, vec->size);
+
+ return vec;
+}
+
+__isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
+ __isl_take isl_vec *vec2)
+{
+ vec1 = isl_vec_cow(vec1);
+ if (!vec1 || !vec2)
+ goto error;
+
+ isl_assert(vec1->ctx, vec1->size == vec2->size, goto error);
+
+ isl_seq_combine(vec1->el, vec1->ctx->one, vec1->el,
+ vec1->ctx->one, vec2->el, vec1->size);
+
+ isl_vec_free(vec2);
+ return vec1;
+error:
+ isl_vec_free(vec1);
+ isl_vec_free(vec2);
+ return NULL;
+}
+
+static int qsort_int_cmp(const void *p1, const void *p2)
+{
+ const isl_int *i1 = (const isl_int *) p1;
+ const isl_int *i2 = (const isl_int *) p2;
+
+ return isl_int_cmp(*i1, *i2);
+}
+
+__isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec)
+{
+ if (!vec)
+ return NULL;
+
+ qsort(vec->el, vec->size, sizeof(*vec->el), &qsort_int_cmp);
+
+ return vec;
+}
+
+__isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n)
+{
+ if (n == 0)
+ return vec;
+ vec = isl_vec_cow(vec);
+ if (!vec)
+ return NULL;
+
+ if (pos + n > vec->size)
+ isl_die(vec->ctx, isl_error_invalid,
+ "range out of bounds", goto error);
+
+ if (pos + n != vec->size)
+ isl_seq_cpy(vec->el + pos, vec->el + pos + n,
+ vec->size - pos - n);
+
+ vec->size -= n;
+
+ return vec;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n)
+{
+ isl_vec *ext = NULL;
+
+ if (n == 0)
+ return vec;
+ if (!vec)
+ return NULL;
+
+ if (pos > vec->size)
+ isl_die(vec->ctx, isl_error_invalid,
+ "position out of bounds", goto error);
+
+ ext = isl_vec_alloc(vec->ctx, vec->size + n);
+ if (!ext)
+ goto error;
+
+ isl_seq_cpy(ext->el, vec->el, pos);
+ isl_seq_cpy(ext->el + pos + n, vec->el + pos, vec->size - pos);
+
+ isl_vec_free(vec);
+ return ext;
+error:
+ isl_vec_free(vec);
+ isl_vec_free(ext);
+ return NULL;
+}
+
+__isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
+ unsigned pos, unsigned n)
+{
+ vec = isl_vec_insert_els(vec, pos, n);
+ if (!vec)
+ return NULL;
+
+ isl_seq_clr(vec->el + pos, n);
+
+ return vec;
+}
+
+/* Move the "n" elements starting as "src_pos" of "vec"
+ * to "dst_pos". The elements originally at "dst_pos" are moved
+ * up or down depending on whether "dst_pos" is smaller or greater
+ * than "src_pos".
+ */
+__isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec,
+ unsigned dst_pos, unsigned src_pos, unsigned n)
+{
+ isl_vec *res;
+
+ if (!vec)
+ return NULL;
+
+ if (src_pos + n > vec->size)
+ isl_die(vec->ctx, isl_error_invalid,
+ "source range out of bounds", return isl_vec_free(vec));
+ if (dst_pos + n > vec->size)
+ isl_die(vec->ctx, isl_error_invalid,
+ "destination range out of bounds",
+ return isl_vec_free(vec));
+
+ if (n == 0 || dst_pos == src_pos)
+ return vec;
+
+ res = isl_vec_alloc(vec->ctx, vec->size);
+ if (!res)
+ return isl_vec_free(vec);
+
+ if (dst_pos < src_pos) {
+ isl_seq_cpy(res->el, vec->el, dst_pos);
+ isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
+ isl_seq_cpy(res->el + dst_pos + n,
+ vec->el + dst_pos, src_pos - dst_pos);
+ isl_seq_cpy(res->el + src_pos + n,
+ vec->el + src_pos + n, res->size - src_pos - n);
+ } else {
+ isl_seq_cpy(res->el, vec->el, src_pos);
+ isl_seq_cpy(res->el + src_pos,
+ vec->el + src_pos + n, dst_pos - src_pos);
+ isl_seq_cpy(res->el + dst_pos, vec->el + src_pos, n);
+ isl_seq_cpy(res->el + dst_pos + n,
+ vec->el + dst_pos + n, res->size - dst_pos - n);
+ }
+
+ isl_vec_free(vec);
+ return res;
+}
diff --git a/polly/lib/External/isl/isl_vec_private.h b/polly/lib/External/isl/isl_vec_private.h
new file mode 100644
index 00000000000..c3fcd9227a2
--- /dev/null
+++ b/polly/lib/External/isl/isl_vec_private.h
@@ -0,0 +1,24 @@
+#ifndef ISL_VEC_PRIVATE_H
+#define ISL_VEC_PRIVATE_H
+
+#include <isl_blk.h>
+#include <isl/vec.h>
+
+struct isl_vec {
+ int ref;
+
+ struct isl_ctx *ctx;
+
+ unsigned size;
+ isl_int *el;
+
+ struct isl_blk block;
+};
+
+__isl_give isl_vec *isl_vec_cow(__isl_take isl_vec *vec);
+
+void isl_vec_lcm(struct isl_vec *vec, isl_int *lcm);
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v);
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v);
+
+#endif
diff --git a/polly/lib/External/isl/isl_version.c b/polly/lib/External/isl/isl_version.c
new file mode 100644
index 00000000000..a7ddd9dc8f9
--- /dev/null
+++ b/polly/lib/External/isl/isl_version.c
@@ -0,0 +1,14 @@
+#include "isl_config.h"
+#include "gitversion.h"
+
+const char *isl_version(void)
+{
+ return GIT_HEAD_ID
+#ifdef USE_GMP_FOR_MP
+ "-GMP"
+#endif
+#ifdef USE_IMATH_FOR_MP
+ "-IMath"
+#endif
+ "\n";
+}
diff --git a/polly/lib/External/isl/isl_vertices.c b/polly/lib/External/isl/isl_vertices.c
new file mode 100644
index 00000000000..c17224d08bb
--- /dev/null
+++ b/polly/lib/External/isl/isl_vertices.c
@@ -0,0 +1,1578 @@
+/*
+ * 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_map_private.h>
+#include <isl_aff_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_tab.h>
+#include <isl_space_private.h>
+#include <isl_morph.h>
+#include <isl_vertices_private.h>
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+#define SELECTED 1
+#define DESELECTED -1
+#define UNSELECTED 0
+
+static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset,
+ __isl_take isl_vertices *vertices);
+
+__isl_give isl_vertices *isl_vertices_copy(__isl_keep isl_vertices *vertices)
+{
+ if (!vertices)
+ return NULL;
+
+ vertices->ref++;
+ return vertices;
+}
+
+void isl_vertices_free(__isl_take isl_vertices *vertices)
+{
+ int i;
+
+ if (!vertices)
+ return;
+
+ if (--vertices->ref > 0)
+ return;
+
+ for (i = 0; i < vertices->n_vertices; ++i) {
+ isl_basic_set_free(vertices->v[i].vertex);
+ isl_basic_set_free(vertices->v[i].dom);
+ }
+ free(vertices->v);
+
+ for (i = 0; i < vertices->n_chambers; ++i) {
+ free(vertices->c[i].vertices);
+ isl_basic_set_free(vertices->c[i].dom);
+ }
+ free(vertices->c);
+
+ isl_basic_set_free(vertices->bset);
+ free(vertices);
+}
+
+struct isl_vertex_list {
+ struct isl_vertex v;
+ struct isl_vertex_list *next;
+};
+
+static void free_vertex_list(struct isl_vertex_list *list)
+{
+ struct isl_vertex_list *next;
+
+ for (; list; list = next) {
+ next = list->next;
+ isl_basic_set_free(list->v.vertex);
+ isl_basic_set_free(list->v.dom);
+ free(list);
+ }
+}
+
+static __isl_give isl_vertices *vertices_from_list(__isl_keep isl_basic_set *bset,
+ int n_vertices, struct isl_vertex_list *list)
+{
+ int i;
+ struct isl_vertex_list *next;
+ isl_vertices *vertices;
+
+ vertices = isl_calloc_type(bset->ctx, isl_vertices);
+ if (!vertices)
+ goto error;
+ vertices->ref = 1;
+ vertices->bset = isl_basic_set_copy(bset);
+ vertices->v = isl_alloc_array(bset->ctx, struct isl_vertex, n_vertices);
+ if (n_vertices && !vertices->v)
+ goto error;
+ vertices->n_vertices = n_vertices;
+
+ for (i = 0; list; list = next, i++) {
+ next = list->next;
+ vertices->v[i] = list->v;
+ free(list);
+ }
+
+ return vertices;
+error:
+ isl_vertices_free(vertices);
+ free_vertex_list(list);
+ return NULL;
+}
+
+/* Prepend a vertex to the linked list "list" based on the equalities in "tab".
+ */
+static int add_vertex(struct isl_vertex_list **list,
+ __isl_keep isl_basic_set *bset, struct isl_tab *tab)
+{
+ unsigned nvar;
+ unsigned nparam;
+ struct isl_vertex_list *v = NULL;
+
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
+ return -1;
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ v = isl_calloc_type(tab->mat->ctx, struct isl_vertex_list);
+ if (!v)
+ goto error;
+
+ v->v.vertex = isl_basic_set_copy(bset);
+ v->v.vertex = isl_basic_set_cow(v->v.vertex);
+ v->v.vertex = isl_basic_set_update_from_tab(v->v.vertex, tab);
+ v->v.vertex = isl_basic_set_simplify(v->v.vertex);
+ v->v.vertex = isl_basic_set_finalize(v->v.vertex);
+ if (!v->v.vertex)
+ goto error;
+ isl_assert(bset->ctx, v->v.vertex->n_eq >= nvar, goto error);
+ v->v.dom = isl_basic_set_copy(v->v.vertex);
+ v->v.dom = isl_basic_set_params(v->v.dom);
+ if (!v->v.dom)
+ goto error;
+
+ v->next = *list;
+ *list = v;
+
+ return 0;
+error:
+ free_vertex_list(v);
+ return -1;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of an empty parametric polytope.
+ */
+static __isl_give isl_vertices *vertices_empty(__isl_keep isl_basic_set *bset)
+{
+ isl_vertices *vertices;
+ unsigned nparam;
+
+ if (!bset)
+ return NULL;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ vertices = isl_calloc_type(bset->ctx, isl_vertices);
+ if (!vertices)
+ return NULL;
+ vertices->bset = isl_basic_set_copy(bset);
+ vertices->ref = 1;
+
+ vertices->n_vertices = 0;
+ vertices->n_chambers = 0;
+
+ return vertices;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of the parametric polytope defined using the same constraints
+ * as "bset" in the 0D case.
+ * There is exactly one 0D vertex and a single chamber containing
+ * the vertex.
+ */
+static __isl_give isl_vertices *vertices_0D(__isl_keep isl_basic_set *bset)
+{
+ isl_vertices *vertices;
+ unsigned nparam;
+
+ if (!bset)
+ return NULL;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+
+ vertices = isl_calloc_type(bset->ctx, isl_vertices);
+ if (!vertices)
+ return NULL;
+ vertices->ref = 1;
+ vertices->bset = isl_basic_set_copy(bset);
+
+ vertices->v = isl_calloc_array(bset->ctx, struct isl_vertex, 1);
+ if (!vertices->v)
+ goto error;
+ vertices->n_vertices = 1;
+ vertices->v[0].vertex = isl_basic_set_copy(bset);
+ vertices->v[0].dom = isl_basic_set_params(isl_basic_set_copy(bset));
+ if (!vertices->v[0].vertex || !vertices->v[0].dom)
+ goto error;
+
+ vertices->c = isl_calloc_array(bset->ctx, struct isl_chamber, 1);
+ if (!vertices->c)
+ goto error;
+ vertices->n_chambers = 1;
+ vertices->c[0].n_vertices = 1;
+ vertices->c[0].vertices = isl_calloc_array(bset->ctx, int, 1);
+ if (!vertices->c[0].vertices)
+ goto error;
+ vertices->c[0].dom = isl_basic_set_copy(vertices->v[0].dom);
+ if (!vertices->c[0].dom)
+ goto error;
+
+ return vertices;
+error:
+ isl_vertices_free(vertices);
+ return NULL;
+}
+
+static int isl_mat_rank(__isl_keep isl_mat *mat)
+{
+ int row, col;
+ isl_mat *H;
+
+ H = isl_mat_left_hermite(isl_mat_copy(mat), 0, NULL, NULL);
+ if (!H)
+ return -1;
+
+ for (col = 0; col < H->n_col; ++col) {
+ for (row = 0; row < H->n_row; ++row)
+ if (!isl_int_is_zero(H->row[row][col]))
+ break;
+ if (row == H->n_row)
+ break;
+ }
+
+ isl_mat_free(H);
+
+ return col;
+}
+
+/* Is the row pointed to by "f" linearly independent of the "n" first
+ * rows in "facets"?
+ */
+static int is_independent(__isl_keep isl_mat *facets, int n, isl_int *f)
+{
+ int rank;
+
+ if (isl_seq_first_non_zero(f, facets->n_col) < 0)
+ return 0;
+
+ isl_seq_cpy(facets->row[n], f, facets->n_col);
+ facets->n_row = n + 1;
+ rank = isl_mat_rank(facets);
+ if (rank < 0)
+ return -1;
+
+ return rank == n + 1;
+}
+
+/* Check whether we can select constraint "level", given the current selection
+ * reflected by facets in "tab", the rows of "facets" and the earlier
+ * "selected" elements of "selection".
+ *
+ * If the constraint is (strictly) redundant in the tableau, selecting it would
+ * result in an empty tableau, so it can't be selected.
+ * If the set variable part of the constraint is not linearly indepedent
+ * of the set variable parts of the already selected constraints,
+ * the constraint cannot be selected.
+ * If selecting the constraint results in an empty tableau, the constraint
+ * cannot be selected.
+ * Finally, if selecting the constraint results in some explicitly
+ * deselected constraints turning into equalities, then the corresponding
+ * vertices have already been generated, so the constraint cannot be selected.
+ */
+static int can_select(__isl_keep isl_basic_set *bset, int level,
+ struct isl_tab *tab, __isl_keep isl_mat *facets, int selected,
+ int *selection)
+{
+ int i;
+ int indep;
+ unsigned ovar;
+ struct isl_tab_undo *snap;
+
+ if (isl_tab_is_redundant(tab, level))
+ return 0;
+
+ ovar = isl_space_offset(bset->dim, isl_dim_set);
+
+ indep = is_independent(facets, selected, bset->ineq[level] + 1 + ovar);
+ if (indep < 0)
+ return -1;
+ if (!indep)
+ return 0;
+
+ snap = isl_tab_snap(tab);
+ if (isl_tab_select_facet(tab, level) < 0)
+ return -1;
+
+ if (tab->empty) {
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ return 0;
+ }
+
+ for (i = 0; i < level; ++i) {
+ int sgn;
+
+ if (selection[i] != DESELECTED)
+ continue;
+
+ if (isl_tab_is_equality(tab, i))
+ sgn = 0;
+ else if (isl_tab_is_redundant(tab, i))
+ sgn = 1;
+ else
+ sgn = isl_tab_sign_of_max(tab, i);
+ if (sgn < -1)
+ return -1;
+ if (sgn <= 0) {
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of a parametric polytope that is not full-dimensional.
+ *
+ * Simply map the parametric polytope to a lower dimensional space
+ * and map the resulting vertices back.
+ */
+static __isl_give isl_vertices *lower_dim_vertices(
+ __isl_keep isl_basic_set *bset)
+{
+ isl_morph *morph;
+ isl_vertices *vertices;
+
+ bset = isl_basic_set_copy(bset);
+ morph = isl_basic_set_full_compression(bset);
+ bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+
+ vertices = isl_basic_set_compute_vertices(bset);
+ isl_basic_set_free(bset);
+
+ morph = isl_morph_inverse(morph);
+
+ vertices = isl_morph_vertices(morph, vertices);
+
+ return vertices;
+}
+
+/* Compute the parametric vertices and the chamber decomposition
+ * of the parametric polytope defined using the same constraints
+ * as "bset". "bset" is assumed to have no existentially quantified
+ * variables.
+ *
+ * The vertices themselves are computed in a fairly simplistic way.
+ * We simply run through all combinations of d constraints,
+ * with d the number of set variables, and check if those d constraints
+ * define a vertex. To avoid the generation of duplicate vertices,
+ * which we may happen if a vertex is defined by more that d constraints,
+ * we make sure we only generate the vertex for the d constraints with
+ * smallest index.
+ *
+ * We set up a tableau and keep track of which facets have been
+ * selected. The tableau is marked strict_redundant so that we can be
+ * sure that any constraint that is marked redundant (and that is not
+ * also marked zero) is not an equality.
+ * If a constraint is marked DESELECTED, it means the constraint was
+ * SELECTED before (in combination with the same selection of earlier
+ * constraints). If such a deselected constraint turns out to be an
+ * equality, then any vertex that may still be found with the current
+ * selection has already been generated when the constraint was selected.
+ * A constraint is marked UNSELECTED when there is no way selecting
+ * the constraint could lead to a vertex (in combination with the current
+ * selection of earlier constraints).
+ *
+ * The set variable coefficients of the selected constraints are stored
+ * in the facets matrix.
+ */
+__isl_give isl_vertices *isl_basic_set_compute_vertices(
+ __isl_keep isl_basic_set *bset)
+{
+ struct isl_tab *tab;
+ int level;
+ int init;
+ unsigned nvar;
+ int *selection = NULL;
+ int selected;
+ struct isl_tab_undo **snap = NULL;
+ isl_mat *facets = NULL;
+ struct isl_vertex_list *list = NULL;
+ int n_vertices = 0;
+ isl_vertices *vertices;
+
+ if (!bset)
+ return NULL;
+
+ if (isl_basic_set_plain_is_empty(bset))
+ return vertices_empty(bset);
+
+ if (bset->n_eq != 0)
+ return lower_dim_vertices(bset);
+
+ isl_assert(bset->ctx, isl_basic_set_dim(bset, isl_dim_div) == 0,
+ return NULL);
+
+ if (isl_basic_set_dim(bset, isl_dim_set) == 0)
+ return vertices_0D(bset);
+
+ nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+ bset = isl_basic_set_copy(bset);
+ bset = isl_basic_set_set_rational(bset);
+ if (!bset)
+ return NULL;
+
+ tab = isl_tab_from_basic_set(bset, 0);
+ if (!tab)
+ goto error;
+ tab->strict_redundant = 1;
+
+ if (tab->empty) {
+ vertices = vertices_empty(bset);
+ isl_basic_set_free(bset);
+ isl_tab_free(tab);
+ return vertices;
+ }
+
+ selection = isl_alloc_array(bset->ctx, int, bset->n_ineq);
+ snap = isl_alloc_array(bset->ctx, struct isl_tab_undo *, bset->n_ineq);
+ facets = isl_mat_alloc(bset->ctx, nvar, nvar);
+ if ((bset->n_ineq && (!selection || !snap)) || !facets)
+ goto error;
+
+ level = 0;
+ init = 1;
+ selected = 0;
+
+ while (level >= 0) {
+ if (level >= bset->n_ineq ||
+ (!init && selection[level] != SELECTED)) {
+ --level;
+ init = 0;
+ continue;
+ }
+ if (init) {
+ int ok;
+ snap[level] = isl_tab_snap(tab);
+ ok = can_select(bset, level, tab, facets, selected,
+ selection);
+ if (ok < 0)
+ goto error;
+ if (ok) {
+ selection[level] = SELECTED;
+ selected++;
+ } else
+ selection[level] = UNSELECTED;
+ } else {
+ selection[level] = DESELECTED;
+ selected--;
+ if (isl_tab_rollback(tab, snap[level]) < 0)
+ goto error;
+ }
+ if (selected == nvar) {
+ if (tab->n_dead == nvar) {
+ if (add_vertex(&list, bset, tab) < 0)
+ goto error;
+ n_vertices++;
+ }
+ init = 0;
+ continue;
+ }
+ ++level;
+ init = 1;
+ }
+
+ isl_mat_free(facets);
+ free(selection);
+ free(snap);
+
+ isl_tab_free(tab);
+
+ vertices = vertices_from_list(bset, n_vertices, list);
+
+ vertices = compute_chambers(bset, vertices);
+
+ return vertices;
+error:
+ free_vertex_list(list);
+ isl_mat_free(facets);
+ free(selection);
+ free(snap);
+ isl_tab_free(tab);
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+struct isl_chamber_list {
+ struct isl_chamber c;
+ struct isl_chamber_list *next;
+};
+
+static void free_chamber_list(struct isl_chamber_list *list)
+{
+ struct isl_chamber_list *next;
+
+ for (; list; list = next) {
+ next = list->next;
+ isl_basic_set_free(list->c.dom);
+ free(list->c.vertices);
+ free(list);
+ }
+}
+
+/* Check whether the basic set "bset" is a superset of the basic set described
+ * by "tab", i.e., check whether all constraints of "bset" are redundant.
+ */
+static int bset_covers_tab(__isl_keep isl_basic_set *bset, struct isl_tab *tab)
+{
+ int i;
+
+ if (!bset || !tab)
+ return -1;
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ enum isl_ineq_type type = isl_tab_ineq_type(tab, bset->ineq[i]);
+ switch (type) {
+ case isl_ineq_error: return -1;
+ case isl_ineq_redundant: continue;
+ default: return 0;
+ }
+ }
+
+ return 1;
+}
+
+static __isl_give isl_vertices *vertices_add_chambers(
+ __isl_take isl_vertices *vertices, int n_chambers,
+ struct isl_chamber_list *list)
+{
+ int i;
+ isl_ctx *ctx;
+ struct isl_chamber_list *next;
+
+ ctx = isl_vertices_get_ctx(vertices);
+ vertices->c = isl_alloc_array(ctx, struct isl_chamber, n_chambers);
+ if (!vertices->c)
+ goto error;
+ vertices->n_chambers = n_chambers;
+
+ for (i = 0; list; list = next, i++) {
+ next = list->next;
+ vertices->c[i] = list->c;
+ free(list);
+ }
+
+ return vertices;
+error:
+ isl_vertices_free(vertices);
+ free_chamber_list(list);
+ return NULL;
+}
+
+/* Can "tab" be intersected with "bset" without resulting in
+ * a lower-dimensional set.
+ */
+static int can_intersect(struct isl_tab *tab, __isl_keep isl_basic_set *bset)
+{
+ int i;
+ struct isl_tab_undo *snap;
+
+ if (isl_tab_extend_cons(tab, bset->n_ineq) < 0)
+ return -1;
+
+ snap = isl_tab_snap(tab);
+
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_tab_ineq_type(tab, bset->ineq[i]) == isl_ineq_redundant)
+ continue;
+ if (isl_tab_add_ineq(tab, bset->ineq[i]) < 0)
+ return -1;
+ }
+
+ if (isl_tab_detect_implicit_equalities(tab) < 0)
+ return -1;
+ if (tab->n_dead) {
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ return 0;
+ }
+
+ return 1;
+}
+
+static int add_chamber(struct isl_chamber_list **list,
+ __isl_keep isl_vertices *vertices, struct isl_tab *tab, int *selection)
+{
+ int n_frozen;
+ int i, j;
+ int n_vertices = 0;
+ struct isl_tab_undo *snap;
+ struct isl_chamber_list *c = NULL;
+
+ for (i = 0; i < vertices->n_vertices; ++i)
+ if (selection[i])
+ n_vertices++;
+
+ snap = isl_tab_snap(tab);
+
+ for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i)
+ tab->con[i].frozen = 0;
+ n_frozen = i;
+
+ if (isl_tab_detect_redundant(tab) < 0)
+ return -1;
+
+ c = isl_calloc_type(tab->mat->ctx, struct isl_chamber_list);
+ if (!c)
+ goto error;
+ c->c.vertices = isl_alloc_array(tab->mat->ctx, int, n_vertices);
+ if (n_vertices && !c->c.vertices)
+ goto error;
+ c->c.dom = isl_basic_set_from_basic_map(isl_basic_map_copy(tab->bmap));
+ c->c.dom = isl_basic_set_set_rational(c->c.dom);
+ c->c.dom = isl_basic_set_cow(c->c.dom);
+ c->c.dom = isl_basic_set_update_from_tab(c->c.dom, tab);
+ c->c.dom = isl_basic_set_simplify(c->c.dom);
+ c->c.dom = isl_basic_set_finalize(c->c.dom);
+ if (!c->c.dom)
+ goto error;
+
+ c->c.n_vertices = n_vertices;
+
+ for (i = 0, j = 0; i < vertices->n_vertices; ++i)
+ if (selection[i]) {
+ c->c.vertices[j] = i;
+ j++;
+ }
+
+ c->next = *list;
+ *list = c;
+
+ for (i = 0; i < n_frozen; ++i)
+ tab->con[i].frozen = 1;
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+
+ return 0;
+error:
+ free_chamber_list(c);
+ return -1;
+}
+
+struct isl_facet_todo {
+ struct isl_tab *tab; /* A tableau representation of the facet */
+ isl_basic_set *bset; /* A normalized basic set representation */
+ isl_vec *constraint; /* Constraint pointing to the other side */
+ struct isl_facet_todo *next;
+};
+
+static void free_todo(struct isl_facet_todo *todo)
+{
+ while (todo) {
+ struct isl_facet_todo *next = todo->next;
+
+ isl_tab_free(todo->tab);
+ isl_basic_set_free(todo->bset);
+ isl_vec_free(todo->constraint);
+ free(todo);
+
+ todo = next;
+ }
+}
+
+static struct isl_facet_todo *create_todo(struct isl_tab *tab, int con)
+{
+ int i;
+ int n_frozen;
+ struct isl_tab_undo *snap;
+ struct isl_facet_todo *todo;
+
+ snap = isl_tab_snap(tab);
+
+ for (i = 0; i < tab->n_con && tab->con[i].frozen; ++i)
+ tab->con[i].frozen = 0;
+ n_frozen = i;
+
+ if (isl_tab_detect_redundant(tab) < 0)
+ return NULL;
+
+ todo = isl_calloc_type(tab->mat->ctx, struct isl_facet_todo);
+ if (!todo)
+ return NULL;
+
+ todo->constraint = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+ if (!todo->constraint)
+ goto error;
+ isl_seq_neg(todo->constraint->el, tab->bmap->ineq[con], 1 + tab->n_var);
+ todo->bset = isl_basic_set_from_basic_map(isl_basic_map_copy(tab->bmap));
+ todo->bset = isl_basic_set_set_rational(todo->bset);
+ todo->bset = isl_basic_set_cow(todo->bset);
+ todo->bset = isl_basic_set_update_from_tab(todo->bset, tab);
+ todo->bset = isl_basic_set_simplify(todo->bset);
+ todo->bset = isl_basic_set_sort_constraints(todo->bset);
+ if (!todo->bset)
+ goto error;
+ ISL_F_SET(todo->bset, ISL_BASIC_SET_NORMALIZED);
+ todo->tab = isl_tab_dup(tab);
+ if (!todo->tab)
+ goto error;
+
+ for (i = 0; i < n_frozen; ++i)
+ tab->con[i].frozen = 1;
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ return todo;
+error:
+ free_todo(todo);
+ return NULL;
+}
+
+/* Create todo items for all interior facets of the chamber represented
+ * by "tab" and collect them in "next".
+ */
+static int init_todo(struct isl_facet_todo **next, struct isl_tab *tab)
+{
+ int i;
+ struct isl_tab_undo *snap;
+ struct isl_facet_todo *todo;
+
+ snap = isl_tab_snap(tab);
+
+ for (i = 0; i < tab->n_con; ++i) {
+ if (tab->con[i].frozen)
+ continue;
+ if (tab->con[i].is_redundant)
+ continue;
+
+ if (isl_tab_select_facet(tab, i) < 0)
+ return -1;
+
+ todo = create_todo(tab, i);
+ if (!todo)
+ return -1;
+
+ todo->next = *next;
+ *next = todo;
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Does the linked list contain a todo item that is the opposite of "todo".
+ * If so, return 1 and remove the opposite todo item.
+ */
+static int has_opposite(struct isl_facet_todo *todo,
+ struct isl_facet_todo **list)
+{
+ for (; *list; list = &(*list)->next) {
+ int eq;
+ eq = isl_basic_set_plain_is_equal(todo->bset, (*list)->bset);
+ if (eq < 0)
+ return -1;
+ if (!eq)
+ continue;
+ todo = *list;
+ *list = todo->next;
+ todo->next = NULL;
+ free_todo(todo);
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Create todo items for all interior facets of the chamber represented
+ * by "tab" and collect them in first->next, taking care to cancel
+ * opposite todo items.
+ */
+static int update_todo(struct isl_facet_todo *first, struct isl_tab *tab)
+{
+ int i;
+ struct isl_tab_undo *snap;
+ struct isl_facet_todo *todo;
+
+ snap = isl_tab_snap(tab);
+
+ for (i = 0; i < tab->n_con; ++i) {
+ int drop;
+
+ if (tab->con[i].frozen)
+ continue;
+ if (tab->con[i].is_redundant)
+ continue;
+
+ if (isl_tab_select_facet(tab, i) < 0)
+ return -1;
+
+ todo = create_todo(tab, i);
+ if (!todo)
+ return -1;
+
+ drop = has_opposite(todo, &first->next);
+ if (drop < 0)
+ return -1;
+
+ if (drop)
+ free_todo(todo);
+ else {
+ todo->next = first->next;
+ first->next = todo;
+ }
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Compute the chamber decomposition of the parametric polytope respresented
+ * by "bset" given the parametric vertices and their activity domains.
+ *
+ * We are only interested in full-dimensional chambers.
+ * Each of these chambers is the intersection of the activity domains of
+ * one or more vertices and the union of all chambers is equal to the
+ * projection of the entire parametric polytope onto the parameter space.
+ *
+ * We first create an initial chamber by intersecting as many activity
+ * domains as possible without ending up with an empty or lower-dimensional
+ * set. As a minor optimization, we only consider those activity domains
+ * that contain some arbitrary point.
+ *
+ * For each of interior facets of the chamber, we construct a todo item,
+ * containing the facet and a constraint containing the other side of the facet,
+ * for constructing the chamber on the other side.
+ * While their are any todo items left, we pick a todo item and
+ * create the required chamber by intersecting all activity domains
+ * that contain the facet and have a full-dimensional intersection with
+ * the other side of the facet. For each of the interior facets, we
+ * again create todo items, taking care to cancel opposite todo items.
+ */
+static __isl_give isl_vertices *compute_chambers(__isl_take isl_basic_set *bset,
+ __isl_take isl_vertices *vertices)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_vec *sample = NULL;
+ struct isl_tab *tab = NULL;
+ struct isl_tab_undo *snap;
+ int *selection = NULL;
+ int n_chambers = 0;
+ struct isl_chamber_list *list = NULL;
+ struct isl_facet_todo *todo = NULL;
+
+ if (!bset || !vertices)
+ goto error;
+
+ ctx = isl_vertices_get_ctx(vertices);
+ selection = isl_alloc_array(ctx, int, vertices->n_vertices);
+ if (vertices->n_vertices && !selection)
+ goto error;
+
+ bset = isl_basic_set_params(bset);
+
+ tab = isl_tab_from_basic_set(bset, 1);
+ if (!tab)
+ goto error;
+ for (i = 0; i < bset->n_ineq; ++i)
+ if (isl_tab_freeze_constraint(tab, i) < 0)
+ goto error;
+ isl_basic_set_free(bset);
+
+ snap = isl_tab_snap(tab);
+
+ sample = isl_tab_get_sample_value(tab);
+
+ for (i = 0; i < vertices->n_vertices; ++i) {
+ selection[i] = isl_basic_set_contains(vertices->v[i].dom, sample);
+ if (selection[i] < 0)
+ goto error;
+ if (!selection[i])
+ continue;
+ selection[i] = can_intersect(tab, vertices->v[i].dom);
+ if (selection[i] < 0)
+ goto error;
+ }
+
+ if (isl_tab_detect_redundant(tab) < 0)
+ goto error;
+
+ if (add_chamber(&list, vertices, tab, selection) < 0)
+ goto error;
+ n_chambers++;
+
+ if (init_todo(&todo, tab) < 0)
+ goto error;
+
+ while (todo) {
+ struct isl_facet_todo *next;
+
+ if (isl_tab_rollback(tab, snap) < 0)
+ goto error;
+
+ if (isl_tab_add_ineq(tab, todo->constraint->el) < 0)
+ goto error;
+ if (isl_tab_freeze_constraint(tab, tab->n_con - 1) < 0)
+ goto error;
+
+ for (i = 0; i < vertices->n_vertices; ++i) {
+ selection[i] = bset_covers_tab(vertices->v[i].dom,
+ todo->tab);
+ if (selection[i] < 0)
+ goto error;
+ if (!selection[i])
+ continue;
+ selection[i] = can_intersect(tab, vertices->v[i].dom);
+ if (selection[i] < 0)
+ goto error;
+ }
+
+ if (isl_tab_detect_redundant(tab) < 0)
+ goto error;
+
+ if (add_chamber(&list, vertices, tab, selection) < 0)
+ goto error;
+ n_chambers++;
+
+ if (update_todo(todo, tab) < 0)
+ goto error;
+
+ next = todo->next;
+ todo->next = NULL;
+ free_todo(todo);
+ todo = next;
+ }
+
+ isl_vec_free(sample);
+
+ isl_tab_free(tab);
+ free(selection);
+
+ vertices = vertices_add_chambers(vertices, n_chambers, list);
+
+ for (i = 0; vertices && i < vertices->n_vertices; ++i) {
+ isl_basic_set_free(vertices->v[i].dom);
+ vertices->v[i].dom = NULL;
+ }
+
+ return vertices;
+error:
+ free_chamber_list(list);
+ free_todo(todo);
+ isl_vec_free(sample);
+ isl_tab_free(tab);
+ free(selection);
+ if (!tab)
+ isl_basic_set_free(bset);
+ isl_vertices_free(vertices);
+ return NULL;
+}
+
+isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex)
+{
+ return vertex ? isl_vertices_get_ctx(vertex->vertices) : NULL;
+}
+
+int isl_vertex_get_id(__isl_keep isl_vertex *vertex)
+{
+ return vertex ? vertex->id : -1;
+}
+
+__isl_give isl_basic_set *isl_basic_set_set_integral(__isl_take isl_basic_set *bset)
+{
+ if (!bset)
+ return NULL;
+
+ if (!ISL_F_ISSET(bset, ISL_BASIC_MAP_RATIONAL))
+ return bset;
+
+ bset = isl_basic_set_cow(bset);
+ if (!bset)
+ return NULL;
+
+ ISL_F_CLR(bset, ISL_BASIC_MAP_RATIONAL);
+
+ return isl_basic_set_finalize(bset);
+}
+
+/* Return the activity domain of the vertex "vertex".
+ */
+__isl_give isl_basic_set *isl_vertex_get_domain(__isl_keep isl_vertex *vertex)
+{
+ struct isl_vertex *v;
+
+ if (!vertex)
+ return NULL;
+
+ v = &vertex->vertices->v[vertex->id];
+ if (!v->dom) {
+ v->dom = isl_basic_set_copy(v->vertex);
+ v->dom = isl_basic_set_params(v->dom);
+ v->dom = isl_basic_set_set_integral(v->dom);
+ }
+
+ return isl_basic_set_copy(v->dom);
+}
+
+/* Return a multiple quasi-affine expression describing the vertex "vertex"
+ * in terms of the parameters,
+ */
+__isl_give isl_multi_aff *isl_vertex_get_expr(__isl_keep isl_vertex *vertex)
+{
+ struct isl_vertex *v;
+ isl_basic_set *bset;
+
+ if (!vertex)
+ return NULL;
+
+ v = &vertex->vertices->v[vertex->id];
+
+ bset = isl_basic_set_copy(v->vertex);
+ return isl_multi_aff_from_basic_set_equalities(bset);
+}
+
+static __isl_give isl_vertex *isl_vertex_alloc(__isl_take isl_vertices *vertices,
+ int id)
+{
+ isl_ctx *ctx;
+ isl_vertex *vertex;
+
+ if (!vertices)
+ return NULL;
+
+ ctx = isl_vertices_get_ctx(vertices);
+ vertex = isl_alloc_type(ctx, isl_vertex);
+ if (!vertex)
+ goto error;
+
+ vertex->vertices = vertices;
+ vertex->id = id;
+
+ return vertex;
+error:
+ isl_vertices_free(vertices);
+ return NULL;
+}
+
+void isl_vertex_free(__isl_take isl_vertex *vertex)
+{
+ if (!vertex)
+ return;
+ isl_vertices_free(vertex->vertices);
+ free(vertex);
+}
+
+isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell)
+{
+ return cell ? cell->dom->ctx : NULL;
+}
+
+__isl_give isl_basic_set *isl_cell_get_domain(__isl_keep isl_cell *cell)
+{
+ return cell ? isl_basic_set_copy(cell->dom) : NULL;
+}
+
+static __isl_give isl_cell *isl_cell_alloc(__isl_take isl_vertices *vertices,
+ __isl_take isl_basic_set *dom, int id)
+{
+ int i;
+ isl_cell *cell = NULL;
+
+ if (!vertices || !dom)
+ goto error;
+
+ cell = isl_calloc_type(dom->ctx, isl_cell);
+ if (!cell)
+ goto error;
+
+ cell->n_vertices = vertices->c[id].n_vertices;
+ cell->ids = isl_alloc_array(dom->ctx, int, cell->n_vertices);
+ if (cell->n_vertices && !cell->ids)
+ goto error;
+ for (i = 0; i < cell->n_vertices; ++i)
+ cell->ids[i] = vertices->c[id].vertices[i];
+ cell->vertices = vertices;
+ cell->dom = dom;
+
+ return cell;
+error:
+ isl_cell_free(cell);
+ isl_vertices_free(vertices);
+ isl_basic_set_free(dom);
+ return NULL;
+}
+
+void isl_cell_free(__isl_take isl_cell *cell)
+{
+ if (!cell)
+ return;
+
+ isl_vertices_free(cell->vertices);
+ free(cell->ids);
+ isl_basic_set_free(cell->dom);
+ free(cell);
+}
+
+/* Create a tableau of the cone obtained by first homogenizing the given
+ * polytope and then making all inequalities strict by setting the
+ * constant term to -1.
+ */
+static struct isl_tab *tab_for_shifted_cone(__isl_keep isl_basic_set *bset)
+{
+ int i;
+ isl_vec *c = NULL;
+ struct isl_tab *tab;
+
+ if (!bset)
+ return NULL;
+ tab = isl_tab_alloc(bset->ctx, bset->n_ineq + 1,
+ 1 + isl_basic_set_total_dim(bset), 0);
+ if (!tab)
+ return NULL;
+ tab->rational = ISL_F_ISSET(bset, ISL_BASIC_SET_RATIONAL);
+ if (ISL_F_ISSET(bset, ISL_BASIC_MAP_EMPTY)) {
+ if (isl_tab_mark_empty(tab) < 0)
+ goto error;
+ return tab;
+ }
+
+ c = isl_vec_alloc(bset->ctx, 1 + 1 + isl_basic_set_total_dim(bset));
+ if (!c)
+ goto error;
+
+ isl_int_set_si(c->el[0], 0);
+ for (i = 0; i < bset->n_eq; ++i) {
+ isl_seq_cpy(c->el + 1, bset->eq[i], c->size - 1);
+ if (isl_tab_add_eq(tab, c->el) < 0)
+ goto error;
+ }
+
+ isl_int_set_si(c->el[0], -1);
+ for (i = 0; i < bset->n_ineq; ++i) {
+ isl_seq_cpy(c->el + 1, bset->ineq[i], c->size - 1);
+ if (isl_tab_add_ineq(tab, c->el) < 0)
+ goto error;
+ if (tab->empty) {
+ isl_vec_free(c);
+ return tab;
+ }
+ }
+
+ isl_seq_clr(c->el + 1, c->size - 1);
+ isl_int_set_si(c->el[1], 1);
+ if (isl_tab_add_ineq(tab, c->el) < 0)
+ goto error;
+
+ isl_vec_free(c);
+ return tab;
+error:
+ isl_vec_free(c);
+ isl_tab_free(tab);
+ return NULL;
+}
+
+/* Compute an interior point of "bset" by selecting an interior
+ * point in homogeneous space and projecting the point back down.
+ */
+static __isl_give isl_vec *isl_basic_set_interior_point(
+ __isl_keep isl_basic_set *bset)
+{
+ isl_vec *vec;
+ struct isl_tab *tab;
+
+ tab = tab_for_shifted_cone(bset);
+ vec = isl_tab_get_sample_value(tab);
+ isl_tab_free(tab);
+ if (!vec)
+ return NULL;
+
+ isl_seq_cpy(vec->el, vec->el + 1, vec->size - 1);
+ vec->size--;
+
+ return vec;
+}
+
+/* Call "fn" on all chambers of the parametric polytope with the shared
+ * facets of neighboring chambers only appearing in one of the chambers.
+ *
+ * We pick an interior point from one of the chambers and then make
+ * all constraints that do not satisfy this point strict.
+ */
+int isl_vertices_foreach_disjoint_cell(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_cell *cell, void *user), void *user)
+{
+ int i, j;
+ isl_vec *vec;
+ isl_int v;
+ isl_cell *cell;
+
+ if (!vertices)
+ return -1;
+
+ if (vertices->n_chambers == 0)
+ return 0;
+
+ if (vertices->n_chambers == 1) {
+ isl_basic_set *dom = isl_basic_set_copy(vertices->c[0].dom);
+ dom = isl_basic_set_set_integral(dom);
+ cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, 0);
+ if (!cell)
+ return -1;
+ return fn(cell, user);
+ }
+
+ vec = isl_basic_set_interior_point(vertices->c[0].dom);
+ if (!vec)
+ return -1;
+
+ isl_int_init(v);
+
+ for (i = 0; i < vertices->n_chambers; ++i) {
+ int r;
+ isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom);
+ dom = isl_basic_set_cow(dom);
+ if (!dom)
+ goto error;
+ for (j = 0; i && j < dom->n_ineq; ++j) {
+ isl_seq_inner_product(vec->el, dom->ineq[j], vec->size,
+ &v);
+ if (!isl_int_is_neg(v))
+ continue;
+ isl_int_sub_ui(dom->ineq[j][0], dom->ineq[j][0], 1);
+ }
+ dom = isl_basic_set_set_integral(dom);
+ cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i);
+ if (!cell)
+ goto error;
+ r = fn(cell, user);
+ if (r < 0)
+ goto error;
+ }
+
+ isl_int_clear(v);
+ isl_vec_free(vec);
+
+ return 0;
+error:
+ isl_int_clear(v);
+ isl_vec_free(vec);
+ return -1;
+}
+
+int isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_cell *cell, void *user), void *user)
+{
+ int i;
+ isl_cell *cell;
+
+ if (!vertices)
+ return -1;
+
+ if (vertices->n_chambers == 0)
+ return 0;
+
+ for (i = 0; i < vertices->n_chambers; ++i) {
+ int r;
+ isl_basic_set *dom = isl_basic_set_copy(vertices->c[i].dom);
+
+ cell = isl_cell_alloc(isl_vertices_copy(vertices), dom, i);
+ if (!cell)
+ return -1;
+
+ r = fn(cell, user);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user)
+{
+ int i;
+ isl_vertex *vertex;
+
+ if (!vertices)
+ return -1;
+
+ if (vertices->n_vertices == 0)
+ return 0;
+
+ for (i = 0; i < vertices->n_vertices; ++i) {
+ int r;
+
+ vertex = isl_vertex_alloc(isl_vertices_copy(vertices), i);
+ if (!vertex)
+ return -1;
+
+ r = fn(vertex, user);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+int isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
+ int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user)
+{
+ int i;
+ isl_vertex *vertex;
+
+ if (!cell)
+ return -1;
+
+ if (cell->n_vertices == 0)
+ return 0;
+
+ for (i = 0; i < cell->n_vertices; ++i) {
+ int r;
+
+ vertex = isl_vertex_alloc(isl_vertices_copy(cell->vertices),
+ cell->ids[i]);
+ if (!vertex)
+ return -1;
+
+ r = fn(vertex, user);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices)
+{
+ return vertices ? vertices->bset->ctx : NULL;
+}
+
+int isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices)
+{
+ return vertices ? vertices->n_vertices : -1;
+}
+
+__isl_give isl_vertices *isl_morph_vertices(__isl_take isl_morph *morph,
+ __isl_take isl_vertices *vertices)
+{
+ int i;
+ isl_morph *param_morph = NULL;
+
+ if (!morph || !vertices)
+ goto error;
+
+ isl_assert(vertices->bset->ctx, vertices->ref == 1, goto error);
+
+ param_morph = isl_morph_copy(morph);
+ param_morph = isl_morph_dom_params(param_morph);
+ param_morph = isl_morph_ran_params(param_morph);
+
+ for (i = 0; i < vertices->n_vertices; ++i) {
+ vertices->v[i].dom = isl_morph_basic_set(
+ isl_morph_copy(param_morph), vertices->v[i].dom);
+ vertices->v[i].vertex = isl_morph_basic_set(
+ isl_morph_copy(morph), vertices->v[i].vertex);
+ if (!vertices->v[i].vertex)
+ goto error;
+ }
+
+ for (i = 0; i < vertices->n_chambers; ++i) {
+ vertices->c[i].dom = isl_morph_basic_set(
+ isl_morph_copy(param_morph), vertices->c[i].dom);
+ if (!vertices->c[i].dom)
+ goto error;
+ }
+
+ isl_morph_free(param_morph);
+ isl_morph_free(morph);
+ return vertices;
+error:
+ isl_morph_free(param_morph);
+ isl_morph_free(morph);
+ isl_vertices_free(vertices);
+ return NULL;
+}
+
+/* Construct a simplex isl_cell spanned by the vertices with indices in
+ * "simplex_ids" and "other_ids" and call "fn" on this isl_cell.
+ */
+static int call_on_simplex(__isl_keep isl_cell *cell,
+ int *simplex_ids, int n_simplex, int *other_ids, int n_other,
+ int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+ int i;
+ isl_ctx *ctx;
+ struct isl_cell *simplex;
+
+ ctx = isl_cell_get_ctx(cell);
+
+ simplex = isl_calloc_type(ctx, struct isl_cell);
+ if (!simplex)
+ return -1;
+ simplex->vertices = isl_vertices_copy(cell->vertices);
+ if (!simplex->vertices)
+ goto error;
+ simplex->dom = isl_basic_set_copy(cell->dom);
+ if (!simplex->dom)
+ goto error;
+ simplex->n_vertices = n_simplex + n_other;
+ simplex->ids = isl_alloc_array(ctx, int, simplex->n_vertices);
+ if (!simplex->ids)
+ goto error;
+
+ for (i = 0; i < n_simplex; ++i)
+ simplex->ids[i] = simplex_ids[i];
+ for (i = 0; i < n_other; ++i)
+ simplex->ids[n_simplex + i] = other_ids[i];
+
+ return fn(simplex, user);
+error:
+ isl_cell_free(simplex);
+ return -1;
+}
+
+/* Check whether the parametric vertex described by "vertex"
+ * lies on the facet corresponding to constraint "facet" of "bset".
+ * The isl_vec "v" is a temporary vector than can be used by this function.
+ *
+ * We eliminate the variables from the facet constraint using the
+ * equalities defining the vertex and check if the result is identical
+ * to zero.
+ *
+ * It would probably be better to keep track of the constraints defining
+ * a vertex during the vertex construction so that we could simply look
+ * it up here.
+ */
+static int vertex_on_facet(__isl_keep isl_basic_set *vertex,
+ __isl_keep isl_basic_set *bset, int facet, __isl_keep isl_vec *v)
+{
+ int i;
+ isl_int m;
+
+ isl_seq_cpy(v->el, bset->ineq[facet], v->size);
+
+ isl_int_init(m);
+ for (i = 0; i < vertex->n_eq; ++i) {
+ int k = isl_seq_last_non_zero(vertex->eq[i], v->size);
+ isl_seq_elim(v->el, vertex->eq[i], k, v->size, &m);
+ }
+ isl_int_clear(m);
+
+ return isl_seq_first_non_zero(v->el, v->size) == -1;
+}
+
+/* Triangulate the polytope spanned by the vertices with ids
+ * in "simplex_ids" and "other_ids" and call "fn" on each of
+ * the resulting simplices.
+ * If the input polytope is already a simplex, we simply call "fn".
+ * Otherwise, we pick a point from "other_ids" and add it to "simplex_ids".
+ * Then we consider each facet of "bset" that does not contain the point
+ * we just picked, but does contain some of the other points in "other_ids"
+ * and call ourselves recursively on the polytope spanned by the new
+ * "simplex_ids" and those points in "other_ids" that lie on the facet.
+ */
+static int triangulate(__isl_keep isl_cell *cell, __isl_keep isl_vec *v,
+ int *simplex_ids, int n_simplex, int *other_ids, int n_other,
+ int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+ int i, j, k;
+ int d, nparam;
+ int *ids;
+ isl_ctx *ctx;
+ isl_basic_set *vertex;
+ isl_basic_set *bset;
+
+ ctx = isl_cell_get_ctx(cell);
+ d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
+ nparam = isl_basic_set_dim(cell->vertices->bset, isl_dim_param);
+
+ if (n_simplex + n_other == d + 1)
+ return call_on_simplex(cell, simplex_ids, n_simplex,
+ other_ids, n_other, fn, user);
+
+ simplex_ids[n_simplex] = other_ids[0];
+ vertex = cell->vertices->v[other_ids[0]].vertex;
+ bset = cell->vertices->bset;
+
+ ids = isl_alloc_array(ctx, int, n_other - 1);
+ for (i = 0; i < bset->n_ineq; ++i) {
+ if (isl_seq_first_non_zero(bset->ineq[i] + 1 + nparam, d) == -1)
+ continue;
+ if (vertex_on_facet(vertex, bset, i, v))
+ continue;
+
+ for (j = 1, k = 0; j < n_other; ++j) {
+ isl_basic_set *ov;
+ ov = cell->vertices->v[other_ids[j]].vertex;
+ if (vertex_on_facet(ov, bset, i, v))
+ ids[k++] = other_ids[j];
+ }
+ if (k == 0)
+ continue;
+
+ if (triangulate(cell, v, simplex_ids, n_simplex + 1,
+ ids, k, fn, user) < 0)
+ goto error;
+ }
+ free(ids);
+
+ return 0;
+error:
+ free(ids);
+ return -1;
+}
+
+/* Triangulate the given cell and call "fn" on each of the resulting
+ * simplices.
+ */
+int isl_cell_foreach_simplex(__isl_take isl_cell *cell,
+ int (*fn)(__isl_take isl_cell *simplex, void *user), void *user)
+{
+ int d, total;
+ int r;
+ isl_ctx *ctx;
+ isl_vec *v = NULL;
+ int *simplex_ids = NULL;
+
+ if (!cell)
+ return -1;
+
+ d = isl_basic_set_dim(cell->vertices->bset, isl_dim_set);
+ total = isl_basic_set_total_dim(cell->vertices->bset);
+
+ if (cell->n_vertices == d + 1)
+ return fn(cell, user);
+
+ ctx = isl_cell_get_ctx(cell);
+ simplex_ids = isl_alloc_array(ctx, int, d + 1);
+ if (!simplex_ids)
+ goto error;
+
+ v = isl_vec_alloc(ctx, 1 + total);
+ if (!v)
+ goto error;
+
+ r = triangulate(cell, v, simplex_ids, 0,
+ cell->ids, cell->n_vertices, fn, user);
+
+ isl_vec_free(v);
+ free(simplex_ids);
+
+ isl_cell_free(cell);
+
+ return r;
+error:
+ free(simplex_ids);
+ isl_vec_free(v);
+ isl_cell_free(cell);
+ return -1;
+}
diff --git a/polly/lib/External/isl/isl_vertices_private.h b/polly/lib/External/isl/isl_vertices_private.h
new file mode 100644
index 00000000000..7c707fd5492
--- /dev/null
+++ b/polly/lib/External/isl/isl_vertices_private.h
@@ -0,0 +1,64 @@
+#include <isl/set.h>
+#include <isl/vertices.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_morph;
+
+/* A parametric vertex. "vertex" contains the actual description
+ * of the vertex as a singleton parametric set. "dom" is the projection
+ * of "vertex" onto the parameter space, i.e., the activity domain
+ * of the vertex.
+ */
+struct isl_vertex {
+ isl_basic_set *dom;
+ isl_basic_set *vertex;
+};
+
+/* A chamber in the chamber decomposition. The indices of the "n_vertices"
+ * active vertices are stored in "vertices".
+ */
+struct isl_chamber {
+ int n_vertices;
+ int *vertices;
+ isl_basic_set *dom;
+};
+
+struct isl_vertices {
+ int ref;
+
+ /* The rational basic set spanned by the vertices. */
+ isl_basic_set *bset;
+
+ int n_vertices;
+ struct isl_vertex *v;
+
+ int n_chambers;
+ struct isl_chamber *c;
+};
+
+struct isl_cell {
+ int n_vertices;
+ int *ids;
+ isl_vertices *vertices;
+ isl_basic_set *dom;
+};
+
+struct isl_external_vertex {
+ isl_vertices *vertices;
+ int id;
+};
+
+int isl_vertices_foreach_disjoint_cell(__isl_keep isl_vertices *vertices,
+ int (*fn)(__isl_take isl_cell *cell, void *user), void *user);
+int isl_cell_foreach_simplex(__isl_take isl_cell *cell,
+ int (*fn)(__isl_take isl_cell *simplex, void *user), void *user);
+
+__isl_give isl_vertices *isl_morph_vertices(__isl_take struct isl_morph *morph,
+ __isl_take isl_vertices *vertices);
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/polly/lib/External/isl/m4/ax_c___attribute__.m4 b/polly/lib/External/isl/m4/ax_c___attribute__.m4
new file mode 100644
index 00000000000..cf3d62bbdf4
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_c___attribute__.m4
@@ -0,0 +1,66 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_c___attribute__.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_C___ATTRIBUTE__
+#
+# DESCRIPTION
+#
+# Provides a test for the compiler support of __attribute__ extensions.
+# Defines HAVE___ATTRIBUTE__ if it is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Stepan Kasal <skasal@redhat.com>
+# Copyright (c) 2008 Christian Haggstrom
+# Copyright (c) 2008 Ryan McCabe <ryan@numb.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 8
+
+AC_DEFUN([AX_C___ATTRIBUTE__], [
+ AC_CACHE_CHECK([for __attribute__], [ax_cv___attribute__],
+ [AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[#include <stdlib.h>
+ static void foo(void) __attribute__ ((unused));
+ static void
+ foo(void) {
+ exit(1);
+ }
+ ]], [])],
+ [ax_cv___attribute__=yes],
+ [ax_cv___attribute__=no]
+ )
+ ])
+ if test "$ax_cv___attribute__" = "yes"; then
+ AC_DEFINE([HAVE___ATTRIBUTE__], 1, [define if your compiler has __attribute__])
+ fi
+])
diff --git a/polly/lib/External/isl/m4/ax_cc_maxopt.m4 b/polly/lib/External/isl/m4/ax_cc_maxopt.m4
new file mode 100644
index 00000000000..92d522d8603
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_cc_maxopt.m4
@@ -0,0 +1,188 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_cc_maxopt.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CC_MAXOPT
+#
+# DESCRIPTION
+#
+# Try to turn on "good" C optimization flags for various compilers and
+# architectures, for some definition of "good". (In our case, good for
+# FFTW and hopefully for other scientific codes. Modify as needed.)
+#
+# The user can override the flags by setting the CFLAGS environment
+# variable. The user can also specify --enable-portable-binary in order to
+# disable any optimization flags that might result in a binary that only
+# runs on the host architecture.
+#
+# Note also that the flags assume that ANSI C aliasing rules are followed
+# by the code (e.g. for gcc's -fstrict-aliasing), and that floating-point
+# computations can be re-ordered as needed.
+#
+# Requires macros: AX_CHECK_COMPILER_FLAGS, AX_COMPILER_VENDOR,
+# AX_GCC_ARCHFLAG, AX_GCC_X86_CPUID.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2008 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CC_MAXOPT],
+[
+AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AX_COMPILER_VENDOR])
+AC_REQUIRE([AC_CANONICAL_HOST])
+
+AC_ARG_ENABLE(portable-binary, [AC_HELP_STRING([--enable-portable-binary], [disable compiler optimizations that would produce unportable binaries])],
+ acx_maxopt_portable=$withval, acx_maxopt_portable=no)
+
+# Try to determine "good" native compiler flags if none specified via CFLAGS
+if test "$ac_test_CFLAGS" != "set"; then
+ CFLAGS=""
+ case $ax_cv_c_compiler_vendor in
+ dec) CFLAGS="-newc -w0 -O5 -ansi_alias -ansi_args -fp_reorder -tune host"
+ if test "x$acx_maxopt_portable" = xno; then
+ CFLAGS="$CFLAGS -arch host"
+ fi;;
+
+ sun) CFLAGS="-native -fast -xO5 -dalign"
+ if test "x$acx_maxopt_portable" = xyes; then
+ CFLAGS="$CFLAGS -xarch=generic"
+ fi;;
+
+ hp) CFLAGS="+Oall +Optrs_ansi +DSnative"
+ if test "x$acx_maxopt_portable" = xyes; then
+ CFLAGS="$CFLAGS +DAportable"
+ fi;;
+
+ ibm) if test "x$acx_maxopt_portable" = xno; then
+ xlc_opt="-qarch=auto -qtune=auto"
+ else
+ xlc_opt="-qtune=auto"
+ fi
+ AX_CHECK_COMPILER_FLAGS($xlc_opt,
+ CFLAGS="-O3 -qansialias -w $xlc_opt",
+ [CFLAGS="-O3 -qansialias -w"
+ echo "******************************************************"
+ echo "* You seem to have the IBM C compiler. It is *"
+ echo "* recommended for best performance that you use: *"
+ echo "* *"
+ echo "* CFLAGS=-O3 -qarch=xxx -qtune=xxx -qansialias -w *"
+ echo "* ^^^ ^^^ *"
+ echo "* where xxx is pwr2, pwr3, 604, or whatever kind of *"
+ echo "* CPU you have. (Set the CFLAGS environment var. *"
+ echo "* and re-run configure.) For more info, man cc. *"
+ echo "******************************************************"])
+ ;;
+
+ intel) CFLAGS="-O3 -ansi_alias"
+ if test "x$acx_maxopt_portable" = xno; then
+ icc_archflag=unknown
+ icc_flags=""
+ case $host_cpu in
+ i686*|x86_64*)
+ # icc accepts gcc assembly syntax, so these should work:
+ AX_GCC_X86_CPUID(0)
+ AX_GCC_X86_CPUID(1)
+ case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG
+ *:756e6547:*:*) # Intel
+ case $ax_cv_gcc_x86_cpuid_1 in
+ *6a?:*[[234]]:*:*|*6[[789b]]?:*:*:*) icc_flags="-xK";;
+ *f3[[347]]:*:*:*|*f4[1347]:*:*:*) icc_flags="-xP -xN -xW -xK";;
+ *f??:*:*:*) icc_flags="-xN -xW -xK";;
+ esac ;;
+ esac ;;
+ esac
+ if test "x$icc_flags" != x; then
+ for flag in $icc_flags; do
+ AX_CHECK_COMPILER_FLAGS($flag, [icc_archflag=$flag; break])
+ done
+ fi
+ AC_MSG_CHECKING([for icc architecture flag])
+ AC_MSG_RESULT($icc_archflag)
+ if test "x$icc_archflag" != xunknown; then
+ CFLAGS="$CFLAGS $icc_archflag"
+ fi
+ fi
+ ;;
+
+ gnu)
+ # default optimization flags for gcc on all systems
+ CFLAGS="-O3 -fomit-frame-pointer"
+
+ # -malign-double for x86 systems
+ AX_CHECK_COMPILER_FLAGS(-malign-double, CFLAGS="$CFLAGS -malign-double")
+
+ # -fstrict-aliasing for gcc-2.95+
+ AX_CHECK_COMPILER_FLAGS(-fstrict-aliasing,
+ CFLAGS="$CFLAGS -fstrict-aliasing")
+
+ # note that we enable "unsafe" fp optimization with other compilers, too
+ AX_CHECK_COMPILER_FLAGS(-ffast-math, CFLAGS="$CFLAGS -ffast-math")
+
+ AX_GCC_ARCHFLAG($acx_maxopt_portable)
+
+ # drop to -O1 for gcc 4.2
+ $CC --version |
+ sed -e 's/.* \(@<:@0-9@:>@@<:@0-9@:>@*\)\.\(@<:@0-9@:>@@<:@0-9@:>@*\).*/\1 \2/' |
+ (read major minor
+ if test $major -eq 4 -a $minor -eq 2; then
+ exit 0
+ fi
+ exit 1
+ ) && CFLAGS="-O1"
+ ;;
+ esac
+
+ if test -z "$CFLAGS"; then
+ echo ""
+ echo "********************************************************"
+ echo "* WARNING: Don't know the best CFLAGS for this system *"
+ echo "* Use ./configure CFLAGS=... to specify your own flags *"
+ echo "* (otherwise, a default of CFLAGS=-O3 will be used) *"
+ echo "********************************************************"
+ echo ""
+ CFLAGS="-O3"
+ fi
+
+ AX_CHECK_COMPILER_FLAGS($CFLAGS, [], [
+ echo ""
+ echo "********************************************************"
+ echo "* WARNING: The guessed CFLAGS don't seem to work with *"
+ echo "* your compiler. *"
+ echo "* Use ./configure CFLAGS=... to specify your own flags *"
+ echo "********************************************************"
+ echo ""
+ CFLAGS=""
+ ])
+
+fi
+])
diff --git a/polly/lib/External/isl/m4/ax_cflags_warn_all.m4 b/polly/lib/External/isl/m4/ax_cflags_warn_all.m4
new file mode 100644
index 00000000000..026c6e98415
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_cflags_warn_all.m4
@@ -0,0 +1,149 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_cflags_warn_all.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CFLAGS_WARN_ALL [(shellvar [,default, [A/NA]])]
+#
+# DESCRIPTION
+#
+# Try to find a compiler option that enables most reasonable warnings.
+#
+# For the GNU CC compiler it will be -Wall (and -ansi -pedantic) The
+# result is added to the shellvar being CFLAGS by default.
+#
+# Currently this macro knows about GCC, Solaris C compiler, Digital Unix C
+# compiler, C for AIX Compiler, HP-UX C compiler, IRIX C compiler, NEC
+# SX-5 (Super-UX 10) C compiler, and Cray J90 (Unicos 10.0.0.8) C
+# compiler.
+#
+# - $1 shell-variable-to-add-to : CFLAGS
+# - $2 add-value-if-not-found : nothing
+# - $3 action-if-found : add value to shellvariable
+# - $4 action-if-not-found : nothing
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ac_cv_cflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_C
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % -Wall" dnl GCC
+ "-xstrconst % -v" dnl Solaris C
+ "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
+ "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+ "-ansi -ansiE % -fullwarn" dnl IRIX
+ "+ESlit % +w1" dnl HP-UX C
+ "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+ "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl the only difference - the LANG selection... and the default FLAGS
+
+AC_DEFUN([AX_CXXFLAGS_WARN_ALL],[dnl
+AS_VAR_PUSHDEF([FLAGS],[CXXFLAGS])dnl
+AS_VAR_PUSHDEF([VAR],[ax_cv_cxxflags_warn_all])dnl
+AC_CACHE_CHECK([m4_ifval($1,$1,FLAGS) for maximum warnings],
+VAR,[VAR="no, unknown"
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+ ac_save_[]FLAGS="$[]FLAGS"
+for ac_arg dnl
+in "-pedantic % -Wall" dnl GCC
+ "-xstrconst % -v" dnl Solaris C
+ "-std1 % -verbose -w0 -warnprotos" dnl Digital Unix
+ "-qlanglvl=ansi % -qsrcmsg -qinfo=all:noppt:noppc:noobs:nocnd" dnl AIX
+ "-ansi -ansiE % -fullwarn" dnl IRIX
+ "+ESlit % +w1" dnl HP-UX C
+ "-Xc % -pvctl[,]fullmsg" dnl NEC SX-5 (Super-UX 10)
+ "-h conform % -h msglevel 2" dnl Cray C (Unicos)
+ #
+do FLAGS="$ac_save_[]FLAGS "`echo $ac_arg | sed -e 's,%%.*,,' -e 's,%,,'`
+ AC_TRY_COMPILE([],[return 0;],
+ [VAR=`echo $ac_arg | sed -e 's,.*% *,,'` ; break])
+done
+ FLAGS="$ac_save_[]FLAGS"
+ AC_LANG_RESTORE
+])
+case ".$VAR" in
+ .ok|.ok,*) m4_ifvaln($3,$3) ;;
+ .|.no|.no,*) m4_ifvaln($4,$4,[m4_ifval($2,[
+ AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $2"])]) ;;
+ *) m4_ifvaln($3,$3,[
+ if echo " $[]m4_ifval($1,$1,FLAGS) " | grep " $VAR " 2>&1 >/dev/null
+ then AC_RUN_LOG([: m4_ifval($1,$1,FLAGS) does contain $VAR])
+ else AC_RUN_LOG([: m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"])
+ m4_ifval($1,$1,FLAGS)="$m4_ifval($1,$1,FLAGS) $VAR"
+ fi ]) ;;
+esac
+AS_VAR_POPDEF([VAR])dnl
+AS_VAR_POPDEF([FLAGS])dnl
+])
+
+dnl implementation tactics:
+dnl the for-argument contains a list of options. The first part of
+dnl these does only exist to detect the compiler - usually it is
+dnl a global option to enable -ansi or -extrawarnings. All other
+dnl compilers will fail about it. That was needed since a lot of
+dnl compilers will give false positives for some option-syntax
+dnl like -Woption or -Xoption as they think of it is a pass-through
+dnl to later compile stages or something. The "%" is used as a
+dnl delimimiter. A non-option comment can be given after "%%" marks
+dnl which will be shown but not added to the respective C/CXXFLAGS.
diff --git a/polly/lib/External/isl/m4/ax_check_compiler_flags.m4 b/polly/lib/External/isl/m4/ax_check_compiler_flags.m4
new file mode 100644
index 00000000000..7da8324b70f
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_check_compiler_flags.m4
@@ -0,0 +1,74 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_check_compiler_flags.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CHECK_COMPILER_FLAGS(FLAGS, [ACTION-SUCCESS], [ACTION-FAILURE])
+#
+# DESCRIPTION
+#
+# Check whether the given compiler FLAGS work with the current language's
+# compiler, or whether they give an error. (Warnings, however, are
+# ignored.)
+#
+# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
+# success/failure.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2009 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CHECK_COMPILER_FLAGS],
+[AC_PREREQ(2.59) dnl for _AC_LANG_PREFIX
+AC_MSG_CHECKING([whether _AC_LANG compiler accepts $1])
+dnl Some hackery here since AC_CACHE_VAL can't handle a non-literal varname:
+AS_LITERAL_IF([$1],
+ [AC_CACHE_VAL(AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1]), [
+ ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$1"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
+ AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
+ _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])],
+ [ax_save_FLAGS=$[]_AC_LANG_PREFIX[]FLAGS
+ _AC_LANG_PREFIX[]FLAGS="$1"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM()],
+ eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=yes,
+ eval AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])=no)
+ _AC_LANG_PREFIX[]FLAGS=$ax_save_FLAGS])
+eval ax_check_compiler_flags=$AS_TR_SH(ax_cv_[]_AC_LANG_ABBREV[]_flags_[$1])
+AC_MSG_RESULT($ax_check_compiler_flags)
+if test "x$ax_check_compiler_flags" = xyes; then
+ m4_default([$2], :)
+else
+ m4_default([$3], :)
+fi
+])dnl AX_CHECK_COMPILER_FLAGS
diff --git a/polly/lib/External/isl/m4/ax_compiler_vendor.m4 b/polly/lib/External/isl/m4/ax_compiler_vendor.m4
new file mode 100644
index 00000000000..321470697e3
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_compiler_vendor.m4
@@ -0,0 +1,63 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_COMPILER_VENDOR
+#
+# DESCRIPTION
+#
+# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
+# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
+# watcom, etc. The vendor is returned in the cache variable
+# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2008 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 9
+
+AC_DEFUN([AX_COMPILER_VENDOR],
+[
+AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
+ [ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=unknown
+ # note: don't check for gcc first since some other compilers define __GNUC__
+ for ventest in intel:__ICC,__ECC,__INTEL_COMPILER ibm:__xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale:__PATHCC__,__PATHSCALE__ clang:__clang__ gnu:__GNUC__ sun:__SUNPRO_C,__SUNPRO_CC hp:__HP_cc,__HP_aCC dec:__DECC,__DECCXX,__DECC_VER,__DECCXX_VER borland:__BORLANDC__,__TURBOC__ comeau:__COMO__ cray:_CRAYC kai:__KCC lcc:__LCC__ metrowerks:__MWERKS__ sgi:__sgi,sgi microsoft:_MSC_VER watcom:__WATCOMC__ portland:__PGI; do
+ vencpp="defined("`echo $ventest | cut -d: -f2 | sed 's/,/) || defined(/g'`")"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
+#if !($vencpp)
+ thisisanerror;
+#endif
+])], [ax_cv_]_AC_LANG_ABBREV[_compiler_vendor=`echo $ventest | cut -d: -f1`; break])
+ done
+ ])
+])
diff --git a/polly/lib/External/isl/m4/ax_create_pkgconfig_info.m4 b/polly/lib/External/isl/m4/ax_create_pkgconfig_info.m4
new file mode 100644
index 00000000000..308e64ff854
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_create_pkgconfig_info.m4
@@ -0,0 +1,351 @@
+# ============================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_create_pkgconfig_info.html
+# ============================================================================
+#
+# SYNOPSIS
+#
+# AX_CREATE_PKGCONFIG_INFO [(outputfile, [requires [,libs [,summary [,cflags [, ldflags]]]]])]
+#
+# DESCRIPTION
+#
+# Defaults:
+#
+# $1 = $PACKAGE_NAME.pc
+# $2 = (empty)
+# $3 = $PACKAGE_LIBS $LIBS (as set at that point in configure.ac)
+# $4 = $PACKAGE_SUMMARY (or $1 Library)
+# $5 = $PACKAGE_CFLAGS (as set at the point in configure.ac)
+# $6 = $PACKAGE_LDFLAGS (as set at the point in configure.ac)
+#
+# PACKAGE_NAME defaults to $PACKAGE if not set.
+# PACKAGE_LIBS defaults to -l$PACKAGE_NAME if not set.
+#
+# The resulting file is called $PACKAGE.pc.in / $PACKAGE.pc
+#
+# You will find this macro most useful in conjunction with
+# ax_spec_defaults that can read good initializers from the .spec file. In
+# consequencd, most of the generatable installable stuff can be made from
+# information being updated in a single place for the whole project.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+# Copyright (c) 2008 Sven Verdoolaege <skimo@kotnet.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 12
+
+AC_DEFUN([AX_CREATE_PKGCONFIG_INFO],[dnl
+AS_VAR_PUSHDEF([PKGCONFIG_suffix],[ax_create_pkgconfig_suffix])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libdir],[ax_create_pkgconfig_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libfile],[ax_create_pkgconfig_libfile])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libname],[ax_create_pkgconfig_libname])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_version],[ax_create_pkgconfig_version])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_description],[ax_create_pkgconfig_description])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_requires],[ax_create_pkgconfig_requires])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_pkglibs],[ax_create_pkgconfig_pkglibs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_libs],[ax_create_pkgconfig_libs])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_ldflags],[ax_create_pkgconfig_ldflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_cppflags],[ax_create_pkgconfig_cppflags])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_generate],[ax_create_pkgconfig_generate])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_libdir],[ax_create_pkgconfig_src_libdir])dnl
+AS_VAR_PUSHDEF([PKGCONFIG_src_headers],[ax_create_pkgconfig_src_headers])dnl
+
+# we need the expanded forms...
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+AC_MSG_CHECKING(our pkgconfig libname)
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="ifelse($1,,${PACKAGE_NAME},`basename $1 .pc`)"
+test ".$PKGCONFIG_libname" != "." || \
+PKGCONFIG_libname="$PACKAGE"
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+PKGCONFIG_libname=`eval echo "$PKGCONFIG_libname"`
+AC_MSG_RESULT($PKGCONFIG_libname)
+
+AC_MSG_CHECKING(our pkgconfig version)
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="${PACKAGE_VERSION}"
+test ".$PKGCONFIG_version" != "." || \
+PKGCONFIG_version="$VERSION"
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+PKGCONFIG_version=`eval echo "$PKGCONFIG_version"`
+AC_MSG_RESULT($PKGCONFIG_version)
+
+AC_MSG_CHECKING(our pkgconfig_libdir)
+test ".$pkgconfig_libdir" = "." && \
+pkgconfig_libdir='${libdir}/pkgconfig'
+PKGCONFIG_libdir=`eval echo "$pkgconfig_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+PKGCONFIG_libdir=`eval echo "$PKGCONFIG_libdir"`
+AC_MSG_RESULT($pkgconfig_libdir)
+test "$pkgconfig_libdir" != "$PKGCONFIG_libdir" && (
+AC_MSG_RESULT(expanded our pkgconfig_libdir... $PKGCONFIG_libdir))
+AC_SUBST([pkgconfig_libdir])
+
+AC_MSG_CHECKING(our pkgconfig_libfile)
+test ".$pkgconfig_libfile" != "." || \
+pkgconfig_libfile="ifelse($1,,$PKGCONFIG_libname.pc,`basename $1`)"
+PKGCONFIG_libfile=`eval echo "$pkgconfig_libfile"`
+PKGCONFIG_libfile=`eval echo "$PKGCONFIG_libfile"`
+AC_MSG_RESULT($pkgconfig_libfile)
+test "$pkgconfig_libfile" != "$PKGCONFIG_libfile" && (
+AC_MSG_RESULT(expanded our pkgconfig_libfile... $PKGCONFIG_libfile))
+AC_SUBST([pkgconfig_libfile])
+
+AC_MSG_CHECKING(our package / suffix)
+PKGCONFIG_suffix="$program_suffix"
+test ".$PKGCONFIG_suffix" != .NONE || PKGCONFIG_suffix=""
+AC_MSG_RESULT(${PACKAGE_NAME} / ${PKGCONFIG_suffix})
+
+AC_MSG_CHECKING(our pkgconfig description)
+PKGCONFIG_description="ifelse($4,,$PACKAGE_SUMMARY,$4)"
+test ".$PKGCONFIG_description" != "." || \
+PKGCONFIG_description="$PKGCONFIG_libname Library"
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+PKGCONFIG_description=`eval echo "$PKGCONFIG_description"`
+AC_MSG_RESULT($PKGCONFIG_description)
+
+AC_MSG_CHECKING(our pkgconfig requires)
+PKGCONFIG_requires="ifelse($2,,$PACKAGE_REQUIRES,$2)"
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+PKGCONFIG_requires=`eval echo "$PKGCONFIG_requires"`
+AC_MSG_RESULT($PKGCONFIG_requires)
+
+AC_MSG_CHECKING(our pkgconfig ext libs)
+PKGCONFIG_pkglibs="$PACKAGE_LIBS"
+test ".$PKGCONFIG_pkglibs" != "." || PKGCONFIG_pkglibs="-l$PKGCONFIG_libname"
+PKGCONFIG_libs="ifelse($3,,$PKGCONFIG_pkglibs $LIBS,$3)"
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+PKGCONFIG_libs=`eval echo "$PKGCONFIG_libs"`
+AC_MSG_RESULT($PKGCONFIG_libs)
+
+AC_MSG_CHECKING(our pkgconfig cppflags)
+PKGCONFIG_cppflags="ifelse($5,,$PACKAGE_CFLAGS,$5)"
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+PKGCONFIG_cppflags=`eval echo "$PKGCONFIG_cppflags"`
+AC_MSG_RESULT($PKGCONFIG_cppflags)
+
+AC_MSG_CHECKING(our pkgconfig ldflags)
+PKGCONFIG_ldflags="ifelse($6,,$PACKAGE_LDFLAGS,$5)"
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+PKGCONFIG_ldflags=`eval echo "$PKGCONFIG_ldflags"`
+AC_MSG_RESULT($PKGCONFIG_ldflags)
+
+test ".$PKGCONFIG_generate" != "." || \
+PKGCONFIG_generate="ifelse($1,,$PKGCONFIG_libname.pc,$1)"
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+PKGCONFIG_generate=`eval echo "$PKGCONFIG_generate"`
+test "$pkgconfig_libfile" != "$PKGCONFIG_generate" && (
+AC_MSG_RESULT(generate the pkgconfig later... $PKGCONFIG_generate))
+
+if test ".$PKGCONFIG_src_libdir" = "." ; then
+PKGCONFIG_src_libdir=`pwd`
+PKGCONFIG_src_libdir=`AS_DIRNAME("$PKGCONFIG_src_libdir/$PKGCONFIG_generate")`
+test ! -d $PKGCONFIG_src_libdir/src || \
+PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/src"
+case ".$objdir" in
+*libs) PKGCONFIG_src_libdir="$PKGCONFIG_src_libdir/$objdir" ;; esac
+AC_MSG_RESULT(noninstalled pkgconfig -L $PKGCONFIG_src_libdir)
+fi
+
+if test ".$PKGCONFIG_src_headers" = "." ; then
+PKGCONFIG_src_headers=`pwd`
+v="$ac_top_srcdir" ;
+test ".$v" != "." || v="$ax_spec_dir"
+test ".$v" != "." || v="$srcdir"
+case "$v" in /*) PKGCONFIG_src_headers="" ;; esac
+PKGCONFIG_src_headers=`AS_DIRNAME("$PKGCONFIG_src_headers/$v/x")`
+test ! -d $PKGCONFIG_src_headers/incl[]ude || \
+PKGCONFIG_src_headers="$PKGCONFIG_src_headers/incl[]ude"
+AC_MSG_RESULT(noninstalled pkgconfig -I $PKGCONFIG_src_headers)
+fi
+
+
+dnl AC_CONFIG_COMMANDS crap disallows to use $PKGCONFIG_libfile here...
+AC_CONFIG_COMMANDS([$ax_create_pkgconfig_generate],[
+pkgconfig_generate="$ax_create_pkgconfig_generate"
+if test ! -f "$pkgconfig_generate.in"
+then generate="true"
+elif grep ' generated by configure ' $pkgconfig_generate.in >/dev/null
+then generate="true"
+else generate="false";
+fi
+if $generate ; then
+AC_MSG_NOTICE(creating $pkgconfig_generate.in)
+cat > $pkgconfig_generate.in <<AXEOF
+# generated by configure / remove this line to disable regeneration
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+datarootdir=@datarootdir@
+datadir=@datadir@
+sysconfdir=@sysconfdir@
+includedir=@includedir@
+package=@PACKAGE@
+suffix=@suffix@
+
+Name: @PACKAGE_NAME@
+Description: @PACKAGE_DESCRIPTION@
+Version: @PACKAGE_VERSION@
+Requires: @PACKAGE_REQUIRES@
+Libs: -L\${libdir} @LDFLAGS@ @LIBS@
+Cflags: -I\${includedir} @CPPFLAGS@
+AXEOF
+fi # DONE generate $pkgconfig_generate.in
+AC_MSG_NOTICE(creating $pkgconfig_generate)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_libdir}|
+s|@datarootdir@|${pkgconfig_datarootdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_includedir}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_generate
+if test ! -s $pkgconfig_generate ; then
+ AC_MSG_ERROR([$pkgconfig_generate is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_generate
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.pc/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|${pkgconfig_prefix}|
+s|@exec_prefix@|${pkgconfig_execprefix}|
+s|@bindir@|${pkgconfig_bindir}|
+s|@libdir@|${pkgconfig_src_libdir}|
+s|@datarootdir@|${pkgconfig_datarootdir}|
+s|@datadir@|${pkgconfig_datadir}|
+s|@sysconfdir@|${pkgconfig_sysconfdir}|
+s|@includedir@|${pkgconfig_src_headers}|
+s|@suffix@|${pkgconfig_suffix}|
+s|@PACKAGE@|${pkgconfig_package}|
+s|@PACKAGE_NAME@|${pkgconfig_libname}|
+s|@PACKAGE_DESCRIPTION@|${pkgconfig_description}|
+s|@PACKAGE_VERSION@|${pkgconfig_version}|
+s|@PACKAGE_REQUIRES@|${pkgconfig_requires}|
+s|@LIBS@|${pkgconfig_libs}|
+s|@LDFLAGS@|${pkgconfig_ldflags}|
+s|@CPPFLAGS@|${pkgconfig_cppflags}|
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+ pkgconfig_requires_add=`echo ${pkgconfig_requires}`
+if test ".$pkgconfig_requires_add" != "." ; then
+ pkgconfig_requires_add="pkg-config $pkgconfig_requires_add"
+ else pkgconfig_requires_add=":" ; fi
+pkgconfig_uninstalled=`echo $pkgconfig_generate |sed 's/.pc$/-uninstalled.sh/'`
+AC_MSG_NOTICE(creating $pkgconfig_uninstalled)
+cat >conftest.sed <<AXEOF
+s|@prefix@|\"${pkgconfig_prefix}\"|
+s|@exec_prefix@|\"${pkgconfig_execprefix}\"|
+s|@bindir@|\"${pkgconfig_bindir}\"|
+s|@libdir@|\"${pkgconfig_src_libdir}\"|
+s|@datarootdir@|\"${pkgconfig_datarootdir}\"|
+s|@datadir@|\"${pkgconfig_datadir}\"|
+s|@sysconfdir@|\"${pkgconfig_sysconfdir}\"|
+s|@includedir@|\"${pkgconfig_src_headers}\"|
+s|@suffix@|\"${pkgconfig_suffix}\"|
+s|@PACKAGE@|\"${pkgconfig_package}\"|
+s|@PACKAGE_NAME@|\"${pkgconfig_libname}\"|
+s|@PACKAGE_DESCRIPTION@|\"${pkgconfig_description}\"|
+s|@PACKAGE_VERSION@|\"${pkgconfig_version}\"|
+s|@PACKAGE_REQUIRES@|\"${pkgconfig_requires}\"|
+s|@LIBS@|\"${pkgconfig_libs}\"|
+s|@LDFLAGS@|\"${pkgconfig_ldflags}\"|
+s|@CPPFLAGS@|\"${pkgconfig_cppflags}\"|
+s>Name:>for option\\; do case \"\$option\" in --list-all|--name) echo >
+s>Description: *>\\;\\; --help) pkg-config --help \\; echo Buildscript Of >
+s>Version: *>\\;\\; --modversion|--version) echo >
+s>Requires:>\\;\\; --requires) echo $pkgconfig_requires_add>
+s>Libs: *>\\;\\; --libs) echo >
+s>Cflags: *>\\;\\; --cflags) echo >
+/--libs)/a\\
+ $pkgconfig_requires_add
+/--cflags)/a\\
+ $pkgconfig_requires_add\\
+;; --variable=*) eval echo '\$'\`echo \$option | sed -e 's/.*=//'\`\\
+;; --uninstalled) exit 0 \\
+;; *) ;; esac done
+AXEOF
+sed -f conftest.sed $pkgconfig_generate.in > $pkgconfig_uninstalled
+if test ! -s $pkgconfig_uninstalled ; then
+ AC_MSG_ERROR([$pkgconfig_uninstalled is empty])
+fi ; rm conftest.sed # DONE generate $pkgconfig_uninstalled
+],[
+dnl AC_CONFIG_COMMANDS crap, the AS_PUSHVAR defines are invalid here...
+ax_create_pkgconfig_generate="$ax_create_pkgconfig_generate"
+pkgconfig_prefix='$prefix'
+pkgconfig_execprefix='$exec_prefix'
+pkgconfig_bindir='$bindir'
+pkgconfig_libdir='$libdir'
+pkgconfig_includedir='$includedir'
+pkgconfig_datarootdir='$datarootdir'
+pkgconfig_datadir='$datadir'
+pkgconfig_sysconfdir='$sysconfdir'
+pkgconfig_suffix='$ax_create_pkgconfig_suffix'
+pkgconfig_package='$PACKAGE_NAME'
+pkgconfig_libname='$ax_create_pkgconfig_libname'
+pkgconfig_description='$ax_create_pkgconfig_description'
+pkgconfig_version='$ax_create_pkgconfig_version'
+pkgconfig_requires='$ax_create_pkgconfig_requires'
+pkgconfig_libs='$ax_create_pkgconfig_libs'
+pkgconfig_ldflags='$ax_create_pkgconfig_ldflags'
+pkgconfig_cppflags='$ax_create_pkgconfig_cppflags'
+pkgconfig_src_libdir='$ax_create_pkgconfig_src_libdir'
+pkgconfig_src_headers='$ax_create_pkgconfig_src_headers'
+])dnl
+AS_VAR_POPDEF([PKGCONFIG_suffix])dnl
+AS_VAR_POPDEF([PKGCONFIG_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_libfile])dnl
+AS_VAR_POPDEF([PKGCONFIG_libname])dnl
+AS_VAR_POPDEF([PKGCONFIG_version])dnl
+AS_VAR_POPDEF([PKGCONFIG_description])dnl
+AS_VAR_POPDEF([PKGCONFIG_requires])dnl
+AS_VAR_POPDEF([PKGCONFIG_pkglibs])dnl
+AS_VAR_POPDEF([PKGCONFIG_libs])dnl
+AS_VAR_POPDEF([PKGCONFIG_ldflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_cppflags])dnl
+AS_VAR_POPDEF([PKGCONFIG_generate])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_libdir])dnl
+AS_VAR_POPDEF([PKGCONFIG_src_headers])dnl
+])
diff --git a/polly/lib/External/isl/m4/ax_create_stdint_h.m4 b/polly/lib/External/isl/m4/ax_create_stdint_h.m4
new file mode 100644
index 00000000000..7b8216599e7
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_create_stdint_h.m4
@@ -0,0 +1,739 @@
+# ===========================================================================
+# http://autoconf-archive.cryp.to/ax_create_stdint_h.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])]
+#
+# DESCRIPTION
+#
+# the "ISO C9X: 7.18 Integer types <stdint.h>" section requires the
+# existence of an include file <stdint.h> that defines a set of typedefs,
+# especially uint8_t,int32_t,uintptr_t. Many older installations will not
+# provide this file, but some will have the very same definitions in
+# <inttypes.h>. In other enviroments we can use the inet-types in
+# <sys/types.h> which would define the typedefs int8_t and u_int8_t
+# respectivly.
+#
+# This macros will create a local "_stdint.h" or the headerfile given as
+# an argument. In many cases that file will just "#include <stdint.h>" or
+# "#include <inttypes.h>", while in other environments it will provide the
+# set of basic 'stdint's definitions/typedefs:
+#
+# int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t
+# int_least32_t.. int_fast32_t.. intmax_t
+#
+# which may or may not rely on the definitions of other files, or using
+# the AC_CHECK_SIZEOF macro to determine the actual sizeof each type.
+#
+# if your header files require the stdint-types you will want to create an
+# installable file mylib-int.h that all your other installable header may
+# include. So if you have a library package named "mylib", just use
+#
+# AX_CREATE_STDINT_H(mylib-int.h)
+#
+# in configure.ac and go to install that very header file in Makefile.am
+# along with the other headers (mylib.h) - and the mylib-specific headers
+# can simply use "#include <mylib-int.h>" to obtain the stdint-types.
+#
+# Remember, if the system already had a valid <stdint.h>, the generated
+# file will include it directly. No need for fuzzy HAVE_STDINT_H things...
+# (oops, GCC 4.2.x has deliberatly disabled its stdint.h for non-c99
+# compilation and the c99-mode is not the default. Therefore this macro
+# will not use the compiler's stdint.h - please complain to the GCC
+# developers).
+#
+# LAST MODIFICATION
+#
+# 2008-04-12
+#
+# COPYLEFT
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Macro Archive. When you make and
+# distribute a modified version of the Autoconf Macro, you may extend this
+# special exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_CHECK_DATA_MODEL],[
+ AC_CHECK_SIZEOF(char)
+ AC_CHECK_SIZEOF(short)
+ AC_CHECK_SIZEOF(int)
+ AC_CHECK_SIZEOF(long)
+ AC_CHECK_SIZEOF(void*)
+ ac_cv_char_data_model=""
+ ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char"
+ ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short"
+ ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int"
+ ac_cv_long_data_model=""
+ ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int"
+ ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long"
+ ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp"
+ AC_MSG_CHECKING([data model])
+ case "$ac_cv_char_data_model/$ac_cv_long_data_model" in
+ 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;;
+ 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;;
+ 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;;
+ 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;;
+ 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;;
+ 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;;
+ 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;;
+ 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;;
+ 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;;
+ 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;;
+ 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;;
+ 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;;
+ 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;;
+ 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;;
+ 222/*|333/*|444/*|666/*|888/*) :
+ ac_cv_data_model="iDSP" ; n="unusual dsptype" ;;
+ *) ac_cv_data_model="none" ; n="very unusual model" ;;
+ esac
+ AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)])
+])
+
+dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF])
+AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[
+AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[
+ ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h)
+ AC_MSG_RESULT([(..)])
+ for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h])
+ do
+ unset ac_cv_type_uintptr_t
+ unset ac_cv_type_uint64_t
+ AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>])
+ AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+ m4_ifvaln([$2],[$2]) break
+ done
+ AC_MSG_CHECKING([for stdint uintptr_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[
+AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[
+ ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h)
+ AC_MSG_RESULT([(..)])
+ for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h])
+ do
+ unset ac_cv_type_uint32_t
+ unset ac_cv_type_uint64_t
+ AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>])
+ AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>])
+ m4_ifvaln([$2],[$2]) break
+ break;
+ done
+ AC_MSG_CHECKING([for stdint uint32_t])
+ ])
+])
+
+AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[
+AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[
+ ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h)
+ AC_MSG_RESULT([(..)])
+ for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do
+ unset ac_cv_type_u_int32_t
+ unset ac_cv_type_u_int64_t
+ AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>])
+ AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>])
+ m4_ifvaln([$2],[$2]) break
+ break;
+ done
+ AC_MSG_CHECKING([for stdint u_int32_t])
+ ])
+])
+
+AC_DEFUN([AX_CREATE_STDINT_H],
+[# ------ AX CREATE STDINT H -------------------------------------
+AC_MSG_CHECKING([for stdint types])
+ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)`
+# try to shortcircuit - if the default include path of the compiler
+# can find a "stdint.h" header then we assume that all compilers can.
+AC_CACHE_VAL([ac_cv_header_stdint_t],[
+old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS=""
+old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS=""
+old_CFLAGS="$CFLAGS" ; CFLAGS=""
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[ac_cv_stdint_result="(assuming C99 compatible system)"
+ ac_cv_header_stdint_t="stdint.h"; ],
+[ac_cv_header_stdint_t=""])
+if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then
+CFLAGS="-std=c99"
+AC_TRY_COMPILE([#include <stdint.h>],[int_least32_t v = 0;],
+[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)])
+fi
+CXXFLAGS="$old_CXXFLAGS"
+CPPFLAGS="$old_CPPFLAGS"
+CFLAGS="$old_CFLAGS" ])
+
+v="... $ac_cv_header_stdint_h"
+if test "$ac_stdint_h" = "stdint.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)])
+elif test "$ac_stdint_h" = "inttypes.h" ; then
+ AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)])
+elif test "_$ac_cv_header_stdint_t" = "_" ; then
+ AC_MSG_RESULT([(putting them into $ac_stdint_h)$v])
+else
+ ac_cv_header_stdint="$ac_cv_header_stdint_t"
+ AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)])
+fi
+
+if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit..
+
+dnl .....intro message done, now do a few system checks.....
+dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type,
+dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW
+dnl instead that is triggered with 3 or more arguments (see types.m4)
+
+inttype_headers=`echo $2 | sed -e 's/,/ /g'`
+
+ac_cv_stdint_result="(no helpful system typedefs seen)"
+AX_CHECK_HEADER_STDINT_X(dnl
+ stdint.h inttypes.h sys/inttypes.h $inttype_headers,
+ ac_cv_stdint_result="(seen uintptr_t$and64 in $i)")
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+AX_CHECK_HEADER_STDINT_O(dnl,
+ inttypes.h sys/inttypes.h stdint.h $inttype_headers,
+ ac_cv_stdint_result="(seen uint32_t$and64 in $i)")
+fi
+
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+if test "_$ac_cv_header_stdint_o" = "_" ; then
+AX_CHECK_HEADER_STDINT_U(dnl,
+ sys/types.h inttypes.h sys/inttypes.h $inttype_headers,
+ ac_cv_stdint_result="(seen u_int32_t$and64 in $i)")
+fi fi
+
+dnl if there was no good C99 header file, do some typedef checks...
+if test "_$ac_cv_header_stdint_x" = "_" ; then
+ AC_MSG_CHECKING([for stdint datatype model])
+ AC_MSG_RESULT([(..)])
+ AX_CHECK_DATA_MODEL
+fi
+
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+ ac_cv_header_stdint="$ac_cv_header_stdint_x"
+elif test "_$ac_cv_header_stdint_o" != "_" ; then
+ ac_cv_header_stdint="$ac_cv_header_stdint_o"
+elif test "_$ac_cv_header_stdint_u" != "_" ; then
+ ac_cv_header_stdint="$ac_cv_header_stdint_u"
+else
+ ac_cv_header_stdint="stddef.h"
+fi
+
+AC_MSG_CHECKING([for extra inttypes in chosen header])
+AC_MSG_RESULT([($ac_cv_header_stdint)])
+dnl see if int_least and int_fast types are present in _this_ header.
+unset ac_cv_type_int_least32_t
+unset ac_cv_type_int_fast32_t
+AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>])
+AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>])
+AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>])
+
+fi # shortcircut to system "stdint.h"
+# ------------------ PREPARE VARIABLES ------------------------------
+if test "$GCC" = "yes" ; then
+ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1`
+else
+ac_cv_stdint_message="using $CC"
+fi
+
+AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl
+$ac_cv_stdint_result])
+
+dnl -----------------------------------------------------------------
+# ----------------- DONE inttypes.h checks START header -------------
+AC_CONFIG_COMMANDS([$ac_stdint_h],[
+AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h)
+ac_stdint=$tmp/_stdint.h
+
+echo "#ifndef" $_ac_stdint_h >$ac_stdint
+echo "#define" $_ac_stdint_h "1" >>$ac_stdint
+echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint
+echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint
+echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_t" != "_" ; then
+echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint
+echo "#include <stdint.h>" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+echo "#endif" >>$ac_stdint
+else
+
+cat >>$ac_stdint <<STDINT_EOF
+
+/* ................... shortcircuit part ........................... */
+
+#if defined HAVE_STDINT_H || defined _STDINT_HAVE_STDINT_H
+#include <stdint.h>
+#else
+#include <stddef.h>
+
+/* .................... configured part ............................ */
+
+STDINT_EOF
+
+echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_x" != "_" ; then
+ ac_header="$ac_cv_header_stdint_x"
+ echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint
+else
+ echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint
+fi
+
+echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_o" != "_" ; then
+ ac_header="$ac_cv_header_stdint_o"
+ echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+ echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint
+fi
+
+echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint
+if test "_$ac_cv_header_stdint_u" != "_" ; then
+ ac_header="$ac_cv_header_stdint_u"
+ echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint
+else
+ echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint
+fi
+
+echo "" >>$ac_stdint
+
+if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then
+ echo "#include <$ac_header>" >>$ac_stdint
+ echo "" >>$ac_stdint
+fi fi
+
+echo "/* which 64bit typedef has been found */" >>$ac_stdint
+if test "$ac_cv_type_uint64_t" = "yes" ; then
+echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint
+fi
+if test "$ac_cv_type_u_int64_t" = "yes" ; then
+echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* which type model has been detected */" >>$ac_stdint
+if test "_$ac_cv_char_data_model" != "_" ; then
+echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint
+echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint
+else
+echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint
+echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+echo "/* whether int_least types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_least32_t" = "yes"; then
+echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint
+fi
+echo "/* whether int_fast types were detected */" >>$ac_stdint
+if test "$ac_cv_type_int_fast32_t" = "yes"; then
+echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint
+fi
+echo "/* whether intmax_t type was detected */" >>$ac_stdint
+if test "$ac_cv_type_intmax_t" = "yes"; then
+echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint
+else
+echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint
+fi
+echo "" >>$ac_stdint
+
+ cat >>$ac_stdint <<STDINT_EOF
+/* .................... detections part ............................ */
+
+/* whether we need to define bitspecific types from compiler base types */
+#ifndef _STDINT_HEADER_INTPTR
+#ifndef _STDINT_HEADER_UINT32
+#ifndef _STDINT_HEADER_U_INT32
+#define _STDINT_NEED_INT_MODEL_T
+#else
+#define _STDINT_HAVE_U_INT_TYPES
+#endif
+#endif
+#endif
+
+#ifdef _STDINT_HAVE_U_INT_TYPES
+#undef _STDINT_NEED_INT_MODEL_T
+#endif
+
+#ifdef _STDINT_CHAR_MODEL
+#if _STDINT_CHAR_MODEL+0 == 122 || _STDINT_CHAR_MODEL+0 == 124
+#ifndef _STDINT_BYTE_MODEL
+#define _STDINT_BYTE_MODEL 12
+#endif
+#endif
+#endif
+
+#ifndef _STDINT_HAVE_INT_LEAST32_T
+#define _STDINT_NEED_INT_LEAST_T
+#endif
+
+#ifndef _STDINT_HAVE_INT_FAST32_T
+#define _STDINT_NEED_INT_FAST_T
+#endif
+
+#ifndef _STDINT_HEADER_INTPTR
+#define _STDINT_NEED_INTPTR_T
+#ifndef _STDINT_HAVE_INTMAX_T
+#define _STDINT_NEED_INTMAX_T
+#endif
+#endif
+
+
+/* .................... definition part ............................ */
+
+/* some system headers have good uint64_t */
+#ifndef _HAVE_UINT64_T
+#if defined _STDINT_HAVE_UINT64_T || defined HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#elif defined _STDINT_HAVE_U_INT64_T || defined HAVE_U_INT64_T
+#define _HAVE_UINT64_T
+typedef u_int64_t uint64_t;
+#endif
+#endif
+
+#ifndef _HAVE_UINT64_T
+/* .. here are some common heuristics using compiler runtime specifics */
+#if defined __STDC_VERSION__ && defined __STDC_VERSION__ >= 199901L
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+
+#elif !defined __STRICT_ANSI__
+#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__
+#define _HAVE_UINT64_T
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__
+/* note: all ELF-systems seem to have loff-support which needs 64-bit */
+#if !defined _NO_LONGLONG
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+
+#elif defined __alpha || (defined __mips && defined _ABIN32)
+#if !defined _NO_LONGLONG
+typedef long int64_t;
+typedef unsigned long uint64_t;
+#endif
+ /* compiler/cpu type to define int64_t */
+#endif
+#endif
+#endif
+
+#if defined _STDINT_HAVE_U_INT_TYPES
+/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */
+typedef u_int8_t uint8_t;
+typedef u_int16_t uint16_t;
+typedef u_int32_t uint32_t;
+
+/* glibc compatibility */
+#ifndef __int8_t_defined
+#define __int8_t_defined
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INT_MODEL_T
+/* we must guess all the basic types. Apart from byte-adressable system, */
+/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */
+/* (btw, those nibble-addressable systems are way off, or so we assume) */
+
+dnl /* have a look at "64bit and data size neutrality" at */
+dnl /* http://unix.org/version2/whatsnew/login_64bit.html */
+dnl /* (the shorthand "ILP" types always have a "P" part) */
+
+#if defined _STDINT_BYTE_MODEL
+#if _STDINT_LONG_MODEL+0 == 242
+/* 2:4:2 = IP16 = a normal 16-bit system */
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned long uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef char int8_t;
+typedef short int16_t;
+typedef long int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444
+/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */
+/* 4:4:4 = ILP32 = a normal 32-bit system */
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488
+/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */
+/* 4:8:8 = LP64 = a normal 64-bit system */
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+#endif
+/* this system has a "long" of 64bit */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+typedef unsigned long uint64_t;
+typedef long int64_t;
+#endif
+#elif _STDINT_LONG_MODEL+0 == 448
+/* LLP64 a 64-bit system derived from a 32-bit system */
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+#ifndef __int8_t_defined
+#define __int8_t_defined
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+#endif
+/* assuming the system has a "long long" */
+#ifndef _HAVE_UINT64_T
+#define _HAVE_UINT64_T
+#define _HAVE_LONGLONG_UINT64_T
+typedef unsigned long long uint64_t;
+typedef long long int64_t;
+#endif
+#else
+#define _STDINT_NO_INT32_T
+#endif
+#else
+#define _STDINT_NO_INT8_T
+#define _STDINT_NO_INT32_T
+#endif
+#endif
+
+/*
+ * quote from SunOS-5.8 sys/inttypes.h:
+ * Use at your own risk. As of February 1996, the committee is squarely
+ * behind the fixed sized types; the "least" and "fast" types are still being
+ * discussed. The probability that the "fast" types may be removed before
+ * the standard is finalized is high enough that they are not currently
+ * implemented.
+ */
+
+#if defined _STDINT_NEED_INT_LEAST_T
+typedef int8_t int_least8_t;
+typedef int16_t int_least16_t;
+typedef int32_t int_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef int64_t int_least64_t;
+#endif
+
+typedef uint8_t uint_least8_t;
+typedef uint16_t uint_least16_t;
+typedef uint32_t uint_least32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t uint_least64_t;
+#endif
+ /* least types */
+#endif
+
+#if defined _STDINT_NEED_INT_FAST_T
+typedef int8_t int_fast8_t;
+typedef int int_fast16_t;
+typedef int32_t int_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef int64_t int_fast64_t;
+#endif
+
+typedef uint8_t uint_fast8_t;
+typedef unsigned uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+#ifdef _HAVE_UINT64_T
+typedef uint64_t uint_fast64_t;
+#endif
+ /* fast types */
+#endif
+
+#ifdef _STDINT_NEED_INTMAX_T
+#ifdef _HAVE_UINT64_T
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+#else
+typedef long intmax_t;
+typedef unsigned long uintmax_t;
+#endif
+#endif
+
+#ifdef _STDINT_NEED_INTPTR_T
+#ifndef __intptr_t_defined
+#define __intptr_t_defined
+/* we encourage using "long" to store pointer values, never use "int" ! */
+#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484
+typedef unsigned int uintptr_t;
+typedef int intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444
+typedef unsigned long uintptr_t;
+typedef long intptr_t;
+#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T
+typedef uint64_t uintptr_t;
+typedef int64_t intptr_t;
+#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */
+typedef unsigned long uintptr_t;
+typedef long intptr_t;
+#endif
+#endif
+#endif
+
+/* The ISO C99 standard specifies that in C++ implementations these
+ should only be defined if explicitly requested. */
+#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS
+#ifndef UINT32_C
+
+/* Signed. */
+# define INT8_C(c) c
+# define INT16_C(c) c
+# define INT32_C(c) c
+# ifdef _HAVE_LONGLONG_UINT64_T
+# define INT64_C(c) c ## L
+# else
+# define INT64_C(c) c ## LL
+# endif
+
+/* Unsigned. */
+# define UINT8_C(c) c ## U
+# define UINT16_C(c) c ## U
+# define UINT32_C(c) c ## U
+# ifdef _HAVE_LONGLONG_UINT64_T
+# define UINT64_C(c) c ## UL
+# else
+# define UINT64_C(c) c ## ULL
+# endif
+
+/* Maximal type. */
+# ifdef _HAVE_LONGLONG_UINT64_T
+# define INTMAX_C(c) c ## L
+# define UINTMAX_C(c) c ## UL
+# else
+# define INTMAX_C(c) c ## LL
+# define UINTMAX_C(c) c ## ULL
+# endif
+
+ /* literalnumbers */
+#endif
+#endif
+
+/* These limits are merily those of a two complement byte-oriented system */
+
+/* Minimum of signed integral types. */
+# define INT8_MIN (-128)
+# define INT16_MIN (-32767-1)
+# define INT32_MIN (-2147483647-1)
+#ifndef INT64_MIN
+# define INT64_MIN (-__INT64_C(9223372036854775807)-1)
+#endif
+/* Maximum of signed integral types. */
+# define INT8_MAX (127)
+# define INT16_MAX (32767)
+# define INT32_MAX (2147483647)
+#ifndef INT64_MAX
+# define INT64_MAX (__INT64_C(9223372036854775807))
+#endif
+
+/* Maximum of unsigned integral types. */
+#ifndef UINT8_MAX
+# define UINT8_MAX (255)
+#endif
+#ifndef UINT16_MAX
+# define UINT16_MAX (65535)
+#endif
+# define UINT32_MAX (4294967295U)
+#ifndef UINT64_MAX
+# define UINT64_MAX (__UINT64_C(18446744073709551615))
+#endif
+
+/* Minimum of signed integral types having a minimum size. */
+# define INT_LEAST8_MIN INT8_MIN
+# define INT_LEAST16_MIN INT16_MIN
+# define INT_LEAST32_MIN INT32_MIN
+# define INT_LEAST64_MIN INT64_MIN
+/* Maximum of signed integral types having a minimum size. */
+# define INT_LEAST8_MAX INT8_MAX
+# define INT_LEAST16_MAX INT16_MAX
+# define INT_LEAST32_MAX INT32_MAX
+# define INT_LEAST64_MAX INT64_MAX
+
+/* Maximum of unsigned integral types having a minimum size. */
+# define UINT_LEAST8_MAX UINT8_MAX
+# define UINT_LEAST16_MAX UINT16_MAX
+# define UINT_LEAST32_MAX UINT32_MAX
+# define UINT_LEAST64_MAX UINT64_MAX
+
+ /* shortcircuit*/
+#endif
+ /* once */
+#endif
+#endif
+STDINT_EOF
+fi
+ if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then
+ AC_MSG_NOTICE([$ac_stdint_h is unchanged])
+ else
+ ac_dir=`AS_DIRNAME(["$ac_stdint_h"])`
+ AS_MKDIR_P(["$ac_dir"])
+ rm -f $ac_stdint_h
+ mv $ac_stdint $ac_stdint_h
+ fi
+],[# variables for create stdint.h replacement
+PACKAGE="$PACKAGE"
+VERSION="$VERSION"
+ac_stdint_h="$ac_stdint_h"
+_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h)
+ac_cv_stdint_message="$ac_cv_stdint_message"
+ac_cv_header_stdint_t="$ac_cv_header_stdint_t"
+ac_cv_header_stdint_x="$ac_cv_header_stdint_x"
+ac_cv_header_stdint_o="$ac_cv_header_stdint_o"
+ac_cv_header_stdint_u="$ac_cv_header_stdint_u"
+ac_cv_type_uint64_t="$ac_cv_type_uint64_t"
+ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t"
+ac_cv_char_data_model="$ac_cv_char_data_model"
+ac_cv_long_data_model="$ac_cv_long_data_model"
+ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t"
+ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t"
+ac_cv_type_intmax_t="$ac_cv_type_intmax_t"
+])
+])
diff --git a/polly/lib/External/isl/m4/ax_detect_git_head.m4 b/polly/lib/External/isl/m4/ax_detect_git_head.m4
new file mode 100644
index 00000000000..31a6fe32945
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_detect_git_head.m4
@@ -0,0 +1,32 @@
+AC_DEFUN([AX_DETECT_GIT_HEAD], [
+ AC_SUBST(GIT_HEAD_ID)
+ AC_SUBST(GIT_HEAD)
+ AC_SUBST(GIT_HEAD_VERSION)
+ if test -f $srcdir/.git; then
+ gitdir=`GIT_DIR=$srcdir/.git git rev-parse --git-dir`
+ GIT_HEAD="$gitdir/index"
+ GIT_REPO="$gitdir"
+ GIT_HEAD_ID=`GIT_DIR=$GIT_REPO git describe --always`
+ elif test -f $srcdir/.git/HEAD; then
+ GIT_HEAD="$srcdir/.git/index"
+ GIT_REPO="$srcdir/.git"
+ GIT_HEAD_ID=`GIT_DIR=$GIT_REPO git describe --always`
+ elif test -f $srcdir/GIT_HEAD_ID; then
+ GIT_HEAD_ID=`cat $srcdir/GIT_HEAD_ID`
+ else
+ mysrcdir=`(cd $srcdir; pwd)`
+ head=`basename $mysrcdir | sed -e 's/.*-//'`
+ head2=`echo $head | sed -e 's/[^0-9a-f]//'`
+ head3=`echo $head2 | sed -e 's/........................................//'`
+ if test "x$head3" = "x" -a "x$head" = "x$head2"; then
+ GIT_HEAD_ID="$head"
+ else
+ GIT_HEAD_ID="UNKNOWN"
+ fi
+ fi
+ if test -z "$GIT_REPO" ; then
+ GIT_HEAD_VERSION="$GIT_HEAD_ID"
+ else
+ GIT_HEAD_VERSION="\`GIT_DIR=$GIT_REPO git describe --always\`"
+ fi
+])
diff --git a/polly/lib/External/isl/m4/ax_detect_gmp.m4 b/polly/lib/External/isl/m4/ax_detect_gmp.m4
new file mode 100644
index 00000000000..43fa20dc531
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_detect_gmp.m4
@@ -0,0 +1,48 @@
+AC_DEFUN([AX_DETECT_GMP], [
+AC_DEFINE([USE_GMP_FOR_MP], [], [use gmp to implement isl_int])
+AX_SUBMODULE(gmp,system|build,system)
+case "$with_gmp" in
+system)
+ if test "x$with_gmp_prefix" != "x"; then
+ isl_configure_args="$isl_configure_args --with-gmp=$with_gmp_prefix"
+ MP_CPPFLAGS="-I$with_gmp_prefix/include"
+ MP_LDFLAGS="-L$with_gmp_prefix/lib"
+ fi
+ MP_LIBS=-lgmp
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ SAVE_LIBS="$LIBS"
+ CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+ LDFLAGS="$MP_LDFLAGS $LDFLAGS"
+ LIBS="$MP_LIBS $LIBS"
+ AC_CHECK_HEADER([gmp.h], [], [AC_ERROR([gmp.h header not found])])
+ AC_CHECK_LIB([gmp], [main], [], [AC_ERROR([gmp library not found])])
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <gmp.h>]], [[
+ mpz_t n, d;
+ if (mpz_divisible_p(n, d))
+ mpz_divexact_ui(n, n, 4);
+ ]])], [], [AC_ERROR([gmp library too old])])
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+ LIBS="$SAVE_LIBS"
+ ;;
+build)
+ MP_CPPFLAGS="-I$gmp_srcdir -I$with_gmp_builddir"
+ MP_LIBS="$with_gmp_builddir/libgmp.la"
+ ;;
+esac
+SAVE_CPPFLAGS="$CPPFLAGS"
+SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
+CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+LDFLAGS="$MP_LDFLAGS $LDFLAGS"
+LIBS="$MP_LIBS $LIBS"
+need_get_memory_functions=false
+AC_CHECK_DECLS(mp_get_memory_functions,[],[
+ need_get_memory_functions=true
+],[#include <gmp.h>])
+CPPFLAGS="$SAVE_CPPFLAGS"
+LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
+AM_CONDITIONAL(NEED_GET_MEMORY_FUNCTIONS, test x$need_get_memory_functions = xtrue)
+])
diff --git a/polly/lib/External/isl/m4/ax_detect_imath.m4 b/polly/lib/External/isl/m4/ax_detect_imath.m4
new file mode 100644
index 00000000000..9c30a614e3f
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_detect_imath.m4
@@ -0,0 +1,15 @@
+AC_DEFUN([AX_DETECT_IMATH], [
+AC_DEFINE([USE_IMATH_FOR_MP], [], [use imath to implement isl_int])
+
+MP_CPPFLAGS="-I$srcdir/imath_wrap"
+MP_LDFLAGS=""
+MP_LIBS=""
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$MP_CPPFLAGS $CPPFLAGS"
+AC_CHECK_HEADER([imath.h], [], [AC_ERROR([imath.h header not found])])
+AC_CHECK_HEADER([gmp_compat.h], [], [AC_ERROR([gmp_compat.h header not found])])
+CPPFLAGS="$SAVE_CPPFLAGS"
+
+AM_CONDITIONAL(NEED_GET_MEMORY_FUNCTIONS, test x = xfalse)
+])
diff --git a/polly/lib/External/isl/m4/ax_gcc_archflag.m4 b/polly/lib/External/isl/m4/ax_gcc_archflag.m4
new file mode 100644
index 00000000000..dedeef424e9
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_gcc_archflag.m4
@@ -0,0 +1,213 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_gcc_archflag.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE])
+#
+# DESCRIPTION
+#
+# This macro tries to guess the "native" arch corresponding to the target
+# architecture for use with gcc's -march=arch or -mtune=arch flags. If
+# found, the cache variable $ax_cv_gcc_archflag is set to this flag and
+# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is is set to
+# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is
+# to add $ax_cv_gcc_archflag to the end of $CFLAGS.
+#
+# PORTABLE? should be either [yes] (default) or [no]. In the former case,
+# the flag is set to -mtune (or equivalent) so that the architecture is
+# only used for tuning, but the instruction set used is still portable. In
+# the latter case, the flag is set to -march (or equivalent) so that
+# architecture-specific instructions are enabled.
+#
+# The user can specify --with-gcc-arch=<arch> in order to override the
+# macro's choice of architecture, or --without-gcc-arch to disable this.
+#
+# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is
+# called unless the user specified --with-gcc-arch manually.
+#
+# Requires macros: AX_CHECK_COMPILER_FLAGS, AX_GCC_X86_CPUID
+#
+# (The main emphasis here is on recent CPUs, on the principle that doing
+# high-performance computing on old hardware is uncommon.)
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2008 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_ARCHFLAG],
+[AC_REQUIRE([AC_PROG_CC])
+AC_REQUIRE([AC_CANONICAL_HOST])
+
+AC_ARG_WITH(gcc-arch, [AC_HELP_STRING([--with-gcc-arch=<arch>], [use architecture <arch> for gcc -march/-mtune, instead of guessing])],
+ ax_gcc_arch=$withval, ax_gcc_arch=yes)
+
+AC_MSG_CHECKING([for gcc architecture flag])
+AC_MSG_RESULT([])
+AC_CACHE_VAL(ax_cv_gcc_archflag,
+[
+ax_cv_gcc_archflag="unknown"
+
+if test "$GCC" = yes; then
+
+if test "x$ax_gcc_arch" = xyes; then
+ax_gcc_arch=""
+if test "$cross_compiling" = no; then
+case $host_cpu in
+ i[[3456]]86*|x86_64*) # use cpuid codes, in part from x86info-1.7 by D. Jones
+ AX_GCC_X86_CPUID(0)
+ AX_GCC_X86_CPUID(1)
+ case $ax_cv_gcc_x86_cpuid_0 in
+ *:756e6547:*:*) # Intel
+ case $ax_cv_gcc_x86_cpuid_1 in
+ *5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;;
+ *5??:*:*:*) ax_gcc_arch=pentium ;;
+ *6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
+ *6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
+ *6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
+ *6[[9d]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;;
+ *6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
+ *6??:*:*:*) ax_gcc_arch=pentiumpro ;;
+ *f3[[347]]:*:*:*|*f4[1347]:*:*:*)
+ case $host_cpu in
+ x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;;
+ *) ax_gcc_arch="prescott pentium4 pentiumpro" ;;
+ esac ;;
+ *f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";;
+ esac ;;
+ *:68747541:*:*) # AMD
+ case $ax_cv_gcc_x86_cpuid_1 in
+ *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;;
+ *5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;;
+ *5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;;
+ *60?:*:*:*) ax_gcc_arch=k7 ;;
+ *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;;
+ *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;;
+ *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;;
+ *6[[68a]]?:*:*:*)
+ AX_GCC_X86_CPUID(0x80000006) # L2 cache size
+ case $ax_cv_gcc_x86_cpuid_0x80000006 in
+ *:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256
+ ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;;
+ *) ax_gcc_arch="athlon-4 athlon k7" ;;
+ esac ;;
+ *f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;;
+ *f5?:*:*:*) ax_gcc_arch="opteron k8" ;;
+ *f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;;
+ *f??:*:*:*) ax_gcc_arch="k8" ;;
+ esac ;;
+ *:746e6543:*:*) # IDT
+ case $ax_cv_gcc_x86_cpuid_1 in
+ *54?:*:*:*) ax_gcc_arch=winchip-c6 ;;
+ *58?:*:*:*) ax_gcc_arch=winchip2 ;;
+ *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;;
+ *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;;
+ esac ;;
+ esac
+ if test x"$ax_gcc_arch" = x; then # fallback
+ case $host_cpu in
+ i586*) ax_gcc_arch=pentium ;;
+ i686*) ax_gcc_arch=pentiumpro ;;
+ esac
+ fi
+ ;;
+
+ sparc*)
+ AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/])
+ cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null`
+ cputype=`echo "$cputype" | tr -d ' -' |tr $as_cr_LETTERS $as_cr_letters`
+ case $cputype in
+ *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;;
+ *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;;
+ *ultrasparc*) ax_gcc_arch="ultrasparc v9" ;;
+ *supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;;
+ *hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;;
+ *cypress*) ax_gcc_arch=cypress ;;
+ esac ;;
+
+ alphaev5) ax_gcc_arch=ev5 ;;
+ alphaev56) ax_gcc_arch=ev56 ;;
+ alphapca56) ax_gcc_arch="pca56 ev56" ;;
+ alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;;
+ alphaev6) ax_gcc_arch=ev6 ;;
+ alphaev67) ax_gcc_arch=ev67 ;;
+ alphaev68) ax_gcc_arch="ev68 ev67" ;;
+ alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;;
+ alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;;
+ alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;;
+
+ powerpc*)
+ cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null`
+ cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'`
+ case $cputype in
+ *750*) ax_gcc_arch="750 G3" ;;
+ *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;;
+ *74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;;
+ *74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;;
+ *970*) ax_gcc_arch="970 G5 power4";;
+ *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";;
+ *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";;
+ 603ev|8240) ax_gcc_arch="$cputype 603e 603";;
+ *) ax_gcc_arch=$cputype ;;
+ esac
+ ax_gcc_arch="$ax_gcc_arch powerpc"
+ ;;
+esac
+fi # not cross-compiling
+fi # guess arch
+
+if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then
+for arch in $ax_gcc_arch; do
+ if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code
+ flags="-mtune=$arch"
+ # -mcpu=$arch and m$arch generate nonportable code on every arch except
+ # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr.
+ case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac
+ else
+ flags="-march=$arch -mcpu=$arch -m$arch"
+ fi
+ for flag in $flags; do
+ AX_CHECK_COMPILER_FLAGS($flag, [ax_cv_gcc_archflag=$flag; break])
+ done
+ test "x$ax_cv_gcc_archflag" = xunknown || break
+done
+fi
+
+fi # $GCC=yes
+])
+AC_MSG_CHECKING([for gcc architecture flag])
+AC_MSG_RESULT($ax_cv_gcc_archflag)
+if test "x$ax_cv_gcc_archflag" = xunknown; then
+ m4_default([$3],:)
+else
+ m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"])
+fi
+])
diff --git a/polly/lib/External/isl/m4/ax_gcc_warn_unused_result.m4 b/polly/lib/External/isl/m4/ax_gcc_warn_unused_result.m4
new file mode 100644
index 00000000000..a957f8f9eaf
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_gcc_warn_unused_result.m4
@@ -0,0 +1,56 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_gcc_warn_unused_result.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_GCC_WARN_UNUSED_RESULT
+#
+# DESCRIPTION
+#
+# The macro will compile a test program to see whether the compiler does
+# understand the per-function postfix pragma.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_WARN_UNUSED_RESULT],[dnl
+AC_CACHE_CHECK(
+ [whether the compiler supports function __attribute__((__warn_unused_result__))],
+ ax_cv_gcc_warn_unused_result,[
+ AC_TRY_COMPILE([__attribute__((__warn_unused_result__))
+ int f(int i) { return i; }],
+ [],
+ ax_cv_gcc_warn_unused_result=yes, ax_cv_gcc_warn_unused_result=no)])
+ if test "$ax_cv_gcc_warn_unused_result" = yes; then
+ AC_DEFINE([GCC_WARN_UNUSED_RESULT],[__attribute__((__warn_unused_result__))],
+ [most gcc compilers know a function __attribute__((__warn_unused_result__))])
+ fi
+])
diff --git a/polly/lib/External/isl/m4/ax_gcc_x86_cpuid.m4 b/polly/lib/External/isl/m4/ax_gcc_x86_cpuid.m4
new file mode 100644
index 00000000000..5420b095900
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_gcc_x86_cpuid.m4
@@ -0,0 +1,77 @@
+# ===========================================================================
+# http://www.nongnu.org/autoconf-archive/ax_gcc_x86_cpuid.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_GCC_X86_CPUID(OP)
+#
+# DESCRIPTION
+#
+# On Pentium and later x86 processors, with gcc or a compiler that has a
+# compatible syntax for inline assembly instructions, run a small program
+# that executes the cpuid instruction with input OP. This can be used to
+# detect the CPU type.
+#
+# On output, the values of the eax, ebx, ecx, and edx registers are stored
+# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable
+# ax_cv_gcc_x86_cpuid_OP.
+#
+# If the cpuid instruction fails (because you are running a
+# cross-compiler, or because you are not using gcc, or because you are on
+# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP
+# is set to the string "unknown".
+#
+# This macro mainly exists to be used in AX_GCC_ARCHFLAG.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+# Copyright (c) 2008 Matteo Frigo
+#
+# This program is free software: you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or (at your
+# option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+# Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+AC_DEFUN([AX_GCC_X86_CPUID],
+[AC_REQUIRE([AC_PROG_CC])
+AC_LANG_PUSH([C])
+AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1,
+ [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], [
+ int op = $1, eax, ebx, ecx, edx;
+ FILE *f;
+ __asm__("cpuid"
+ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
+ : "a" (op));
+ f = fopen("conftest_cpuid", "w"); if (!f) return 1;
+ fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx);
+ fclose(f);
+ return 0;
+])],
+ [ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid],
+ [ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid],
+ [ax_cv_gcc_x86_cpuid_$1=unknown])])
+AC_LANG_POP([C])
+])
diff --git a/polly/lib/External/isl/m4/ax_set_warning_flags.m4 b/polly/lib/External/isl/m4/ax_set_warning_flags.m4
new file mode 100644
index 00000000000..c64ad7d8478
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_set_warning_flags.m4
@@ -0,0 +1,17 @@
+dnl Add a set of flags to WARNING_FLAGS, that enable compiler warnings for
+dnl isl. The warnings that are enabled vary with the compiler and only include
+dnl warnings that did not trigger at the time of adding these flags.
+AC_DEFUN([AX_SET_WARNING_FLAGS],[dnl
+ AX_COMPILER_VENDOR
+
+ WARNING_FLAGS=""
+
+ if test "${ax_cv_c_compiler_vendor}" = "clang"; then
+ dnl isl is at the moment clean of -Wall warnings. If clang adds
+ dnl new warnings to -Wall which cause false positives, the
+ dnl specific warning types will be disabled explicitally (by
+ dnl adding for example -Wno-return-type). To temporarily disable
+ dnl all warnings run configure with CFLAGS=-Wno-all.
+ WARNING_FLAGS="-Wall"
+ fi
+])
diff --git a/polly/lib/External/isl/m4/ax_submodule.m4 b/polly/lib/External/isl/m4/ax_submodule.m4
new file mode 100644
index 00000000000..7cf899576d7
--- /dev/null
+++ b/polly/lib/External/isl/m4/ax_submodule.m4
@@ -0,0 +1,71 @@
+AC_DEFUN([AX_SUBMODULE],
+[
+
+m4_if(m4_bregexp($2,|,choice),choice,
+ [AC_ARG_WITH($1,
+ [AS_HELP_STRING([--with-$1=$2],
+ [Which $1 to use [default=$3]])])])
+case "system" in
+$2)
+ AC_ARG_WITH($1_prefix,
+ [AS_HELP_STRING([--with-$1-prefix=DIR],
+ [Prefix of $1 installation])])
+ AC_ARG_WITH($1_exec_prefix,
+ [AS_HELP_STRING([--with-$1-exec-prefix=DIR],
+ [Exec prefix of $1 installation])])
+esac
+m4_if(m4_bregexp($2,build,build),build,
+ [AC_ARG_WITH($1_builddir,
+ [AS_HELP_STRING([--with-$1-builddir=DIR],
+ [Location of $1 builddir])])])
+if test "x$with_$1_prefix" != "x" -a "x$with_$1_exec_prefix" = "x"; then
+ with_$1_exec_prefix=$with_$1_prefix
+fi
+if test "x$with_$1_prefix" != "x" -o "x$with_$1_exec_prefix" != "x"; then
+ if test "x$with_$1" != "x" -a "x$with_$1" != "xyes" -a "x$with_$1" != "xsystem"; then
+ AC_MSG_ERROR([Setting $with_$1_prefix implies use of system $1])
+ fi
+ with_$1="system"
+fi
+if test "x$with_$1_builddir" != "x"; then
+ if test "x$with_$1" != "x" -a "x$with_$1" != "xyes" -a "x$with_$1" != "xbuild"; then
+ AC_MSG_ERROR([Setting $with_$1_builddir implies use of build $1])
+ fi
+ with_$1="build"
+ $1_srcdir=`echo @abs_srcdir@ | $with_$1_builddir/config.status --file=-`
+ AC_MSG_NOTICE($1 sources in $$1_srcdir)
+fi
+if test "x$with_$1_exec_prefix" != "x"; then
+ export PKG_CONFIG_PATH="$with_$1_exec_prefix/lib/pkgconfig${PKG_CONFIG_PATH+:$PKG_CONFIG_PATH}"
+fi
+case "$with_$1" in
+$2)
+ ;;
+*)
+ case "$3" in
+ bundled)
+ if test -d $srcdir/.git -a \
+ -d $srcdir/$1 -a \
+ ! -d $srcdir/$1/.git; then
+ AC_MSG_WARN([git repo detected, but submodule $1 not initialized])
+ AC_MSG_WARN([You may want to run])
+ AC_MSG_WARN([ git submodule init])
+ AC_MSG_WARN([ git submodule update])
+ AC_MSG_WARN([ sh autogen.sh])
+ fi
+ if test -f $srcdir/$1/configure; then
+ with_$1="bundled"
+ else
+ with_$1="no"
+ fi
+ ;;
+ *)
+ with_$1="$3"
+ ;;
+ esac
+ ;;
+esac
+AC_MSG_CHECKING([which $1 to use])
+AC_MSG_RESULT($with_$1)
+
+])
diff --git a/polly/lib/External/isl/mp_get_memory_functions.c b/polly/lib/External/isl/mp_get_memory_functions.c
new file mode 100644
index 00000000000..e14e336ceb6
--- /dev/null
+++ b/polly/lib/External/isl/mp_get_memory_functions.c
@@ -0,0 +1,14 @@
+#include <gmp.h>
+
+void mp_get_memory_functions(
+ void *(**alloc_func_ptr) (size_t),
+ void *(**realloc_func_ptr) (void *, size_t, size_t),
+ void (**free_func_ptr) (void *, size_t))
+{
+ if (alloc_func_ptr)
+ *alloc_func_ptr = __gmp_allocate_func;
+ if (realloc_func_ptr)
+ *realloc_func_ptr = __gmp_reallocate_func;
+ if (free_func_ptr)
+ *free_func_ptr = __gmp_free_func;
+}
diff --git a/polly/lib/External/isl/pip.c b/polly/lib/External/isl/pip.c
new file mode 100644
index 00000000000..707da1c4993
--- /dev/null
+++ b/polly/lib/External/isl/pip.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <strings.h>
+#include <isl_map_private.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include "isl_tab.h"
+#include "isl_sample.h"
+#include "isl_scan.h"
+#include <isl_seq.h>
+#include <isl_ilp_private.h>
+#include <isl/printer.h>
+#include <isl_point_private.h>
+#include <isl_vec_private.h>
+#include <isl/options.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"
+ * should always be -1.
+ *
+ * Context constraints in PolyLib format
+ * -1
+ * Problem constraints in PolyLib format
+ * Optional list of options
+ *
+ * The options are
+ * Maximize compute maximum instead of minimum
+ * Rational compute rational optimum instead of integer optimum
+ * Urs_parms don't assume parameters are non-negative
+ * Urs_unknowns don't assume unknowns are non-negative
+ */
+
+struct options {
+ struct isl_options *isl;
+ unsigned verify;
+ unsigned format;
+};
+
+#define FORMAT_SET 0
+#define FORMAT_AFF 1
+
+struct isl_arg_choice pip_format[] = {
+ {"set", FORMAT_SET},
+ {"affine", FORMAT_AFF},
+ {0}
+};
+
+ISL_ARGS_START(struct options, options_args)
+ISL_ARG_CHILD(struct options, isl, "isl", &isl_options_args, "isl options")
+ISL_ARG_BOOL(struct options, verify, 'T', "verify", 0, NULL)
+ISL_ARG_CHOICE(struct options, format, 0, "format",
+ pip_format, FORMAT_SET, "output format")
+ISL_ARGS_END
+
+ISL_ARG_DEF(options, struct options, options_args)
+
+static __isl_give isl_basic_set *set_bounds(__isl_take isl_basic_set *bset)
+{
+ unsigned nparam;
+ int i, r;
+ isl_point *pt, *pt2;
+ isl_basic_set *box;
+
+ nparam = isl_basic_set_dim(bset, isl_dim_param);
+ r = nparam >= 8 ? 4 : nparam >= 5 ? 6 : 30;
+
+ pt = isl_basic_set_sample_point(isl_basic_set_copy(bset));
+ pt2 = isl_point_copy(pt);
+
+ for (i = 0; i < nparam; ++i) {
+ pt = isl_point_add_ui(pt, isl_dim_param, i, r);
+ pt2 = isl_point_sub_ui(pt2, isl_dim_param, i, r);
+ }
+
+ box = isl_basic_set_box_from_points(pt, pt2);
+
+ return isl_basic_set_intersect(bset, box);
+}
+
+static struct isl_basic_set *to_parameter_domain(struct isl_basic_set *context)
+{
+ context = isl_basic_set_move_dims(context, isl_dim_param, 0,
+ isl_dim_set, 0, isl_basic_set_dim(context, isl_dim_set));
+ context = isl_basic_set_params(context);
+ return context;
+}
+
+isl_basic_set *plug_in_parameters(isl_basic_set *bset, struct isl_vec *params)
+{
+ int i;
+
+ for (i = 0; i < params->size - 1; ++i)
+ bset = isl_basic_set_fix(bset,
+ isl_dim_param, i, params->el[1 + i]);
+
+ bset = isl_basic_set_remove_dims(bset,
+ isl_dim_param, 0, params->size - 1);
+
+ isl_vec_free(params);
+
+ return bset;
+}
+
+isl_set *set_plug_in_parameters(isl_set *set, struct isl_vec *params)
+{
+ int i;
+
+ for (i = 0; i < params->size - 1; ++i)
+ set = isl_set_fix(set, isl_dim_param, i, params->el[1 + i]);
+
+ set = isl_set_remove_dims(set, isl_dim_param, 0, params->size - 1);
+
+ isl_vec_free(params);
+
+ return set;
+}
+
+/* Compute the lexicographically minimal (or maximal if max is set)
+ * element of bset for the given values of the parameters, by
+ * successively solving an ilp problem in each direction.
+ */
+struct isl_vec *opt_at(struct isl_basic_set *bset,
+ struct isl_vec *params, int max)
+{
+ unsigned dim;
+ struct isl_vec *opt;
+ struct isl_vec *obj;
+ int i;
+
+ dim = isl_basic_set_dim(bset, isl_dim_set);
+
+ bset = plug_in_parameters(bset, params);
+
+ if (isl_basic_set_plain_is_empty(bset)) {
+ opt = isl_vec_alloc(bset->ctx, 0);
+ isl_basic_set_free(bset);
+ return opt;
+ }
+
+ opt = isl_vec_alloc(bset->ctx, 1 + dim);
+ assert(opt);
+
+ obj = isl_vec_alloc(bset->ctx, 1 + dim);
+ assert(obj);
+
+ isl_int_set_si(opt->el[0], 1);
+ isl_int_set_si(obj->el[0], 0);
+
+ for (i = 0; i < dim; ++i) {
+ enum isl_lp_result res;
+
+ isl_seq_clr(obj->el + 1, dim);
+ isl_int_set_si(obj->el[1 + i], 1);
+ res = isl_basic_set_solve_ilp(bset, max, obj->el,
+ &opt->el[1 + i], NULL);
+ if (res == isl_lp_empty)
+ goto empty;
+ assert(res == isl_lp_ok);
+ bset = isl_basic_set_fix(bset, isl_dim_set, i, opt->el[1 + i]);
+ }
+
+ isl_basic_set_free(bset);
+ isl_vec_free(obj);
+
+ return opt;
+empty:
+ isl_vec_free(opt);
+ opt = isl_vec_alloc(bset->ctx, 0);
+ isl_basic_set_free(bset);
+ isl_vec_free(obj);
+
+ return opt;
+}
+
+struct isl_scan_pip {
+ struct isl_scan_callback callback;
+ isl_basic_set *bset;
+ isl_set *sol;
+ isl_set *empty;
+ int stride;
+ int n;
+ int max;
+};
+
+/* Check if the "manually" computed optimum of bset at the "sample"
+ * values of the parameters agrees with the solution of pilp problem
+ * represented by the pair (sol, empty).
+ * In particular, if there is no solution for this value of the parameters,
+ * then it should be an element of the parameter domain "empty".
+ * Otherwise, the optimal solution, should be equal to the result of
+ * plugging in the value of the parameters in "sol".
+ */
+static int scan_one(struct isl_scan_callback *callback,
+ __isl_take isl_vec *sample)
+{
+ struct isl_scan_pip *sp = (struct isl_scan_pip *)callback;
+ struct isl_vec *opt;
+
+ sp->n--;
+
+ opt = opt_at(isl_basic_set_copy(sp->bset), isl_vec_copy(sample), sp->max);
+ assert(opt);
+
+ if (opt->size == 0) {
+ isl_point *sample_pnt;
+ sample_pnt = isl_point_alloc(isl_set_get_space(sp->empty), sample);
+ assert(isl_set_contains_point(sp->empty, sample_pnt));
+ isl_point_free(sample_pnt);
+ isl_vec_free(opt);
+ } else {
+ isl_set *sol;
+ isl_set *opt_set;
+ opt_set = isl_set_from_basic_set(isl_basic_set_from_vec(opt));
+ sol = set_plug_in_parameters(isl_set_copy(sp->sol), sample);
+ assert(isl_set_is_equal(opt_set, sol));
+ isl_set_free(sol);
+ isl_set_free(opt_set);
+ }
+
+ if (!(sp->n % sp->stride)) {
+ printf("o");
+ fflush(stdout);
+ }
+
+ return sp->n >= 1 ? 0 : -1;
+}
+
+static void check_solution(isl_basic_set *bset, isl_basic_set *context,
+ isl_set *sol, isl_set *empty, int max)
+{
+ struct isl_scan_pip sp;
+ isl_int count, count_max;
+ int i, n;
+ int r;
+
+ context = set_bounds(context);
+ context = isl_basic_set_underlying_set(context);
+
+ isl_int_init(count);
+ isl_int_init(count_max);
+
+ isl_int_set_si(count_max, 2000);
+ r = isl_basic_set_count_upto(context, count_max, &count);
+ assert(r >= 0);
+ n = isl_int_get_si(count);
+
+ isl_int_clear(count_max);
+ isl_int_clear(count);
+
+ sp.callback.add = scan_one;
+ sp.bset = bset;
+ sp.sol = sol;
+ sp.empty = empty;
+ sp.n = n;
+ sp.stride = n > 70 ? 1 + (n + 1)/70 : 1;
+ sp.max = max;
+
+ for (i = 0; i < n; i += sp.stride)
+ printf(".");
+ printf("\r");
+ fflush(stdout);
+
+ isl_basic_set_scan(context, &sp.callback);
+
+ printf("\n");
+
+ isl_basic_set_free(bset);
+}
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx;
+ struct isl_basic_set *context, *bset, *copy, *context_copy;
+ struct isl_set *set = NULL;
+ struct isl_set *empty;
+ isl_pw_multi_aff *pma = NULL;
+ int neg_one;
+ char s[1024];
+ int urs_parms = 0;
+ int urs_unknowns = 0;
+ int max = 0;
+ int rational = 0;
+ int n;
+ int nparam;
+ struct options *options;
+
+ options = options_new_with_defaults();
+ assert(options);
+ argc = options_parse(options, argc, argv, ISL_ARG_ALL);
+
+ ctx = isl_ctx_alloc_with_options(&options_args, options);
+
+ context = isl_basic_set_read_from_file(ctx, stdin);
+ assert(context);
+ n = fscanf(stdin, "%d", &neg_one);
+ assert(n == 1);
+ assert(neg_one == -1);
+ bset = isl_basic_set_read_from_file(ctx, stdin);
+
+ while (fgets(s, sizeof(s), stdin)) {
+ if (strncasecmp(s, "Maximize", 8) == 0)
+ max = 1;
+ if (strncasecmp(s, "Rational", 8) == 0) {
+ rational = 1;
+ bset = isl_basic_set_set_rational(bset);
+ }
+ if (strncasecmp(s, "Urs_parms", 9) == 0)
+ urs_parms = 1;
+ if (strncasecmp(s, "Urs_unknowns", 12) == 0)
+ urs_unknowns = 1;
+ }
+ if (!urs_parms)
+ context = isl_basic_set_intersect(context,
+ isl_basic_set_positive_orthant(isl_basic_set_get_space(context)));
+ context = to_parameter_domain(context);
+ nparam = isl_basic_set_dim(context, isl_dim_param);
+ if (nparam != isl_basic_set_dim(bset, isl_dim_param)) {
+ int dim = isl_basic_set_dim(bset, isl_dim_set);
+ bset = isl_basic_set_move_dims(bset, isl_dim_param, 0,
+ isl_dim_set, dim - nparam, nparam);
+ }
+ if (!urs_unknowns)
+ bset = isl_basic_set_intersect(bset,
+ isl_basic_set_positive_orthant(isl_basic_set_get_space(bset)));
+
+ if (options->verify) {
+ copy = isl_basic_set_copy(bset);
+ context_copy = isl_basic_set_copy(context);
+ }
+
+ if (options->format == FORMAT_AFF) {
+ if (max)
+ pma = isl_basic_set_partial_lexmax_pw_multi_aff(bset,
+ context, &empty);
+ else
+ pma = isl_basic_set_partial_lexmin_pw_multi_aff(bset,
+ context, &empty);
+ } else {
+ if (max)
+ set = isl_basic_set_partial_lexmax(bset,
+ context, &empty);
+ else
+ set = isl_basic_set_partial_lexmin(bset,
+ context, &empty);
+ }
+
+ if (options->verify) {
+ assert(!rational);
+ if (options->format == FORMAT_AFF)
+ set = isl_set_from_pw_multi_aff(pma);
+ check_solution(copy, context_copy, set, empty, max);
+ isl_set_free(set);
+ } else {
+ isl_printer *p;
+ p = isl_printer_to_file(ctx, stdout);
+ if (options->format == FORMAT_AFF)
+ p = isl_printer_print_pw_multi_aff(p, pma);
+ else
+ p = isl_printer_print_set(p, set);
+ p = isl_printer_end_line(p);
+ p = isl_printer_print_str(p, "no solution: ");
+ p = isl_printer_print_set(p, empty);
+ p = isl_printer_end_line(p);
+ isl_printer_free(p);
+ isl_set_free(set);
+ isl_pw_multi_aff_free(pma);
+ }
+
+ isl_set_free(empty);
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/pip_test.sh.in b/polly/lib/External/isl/pip_test.sh.in
new file mode 100755
index 00000000000..28ad1ef4245
--- /dev/null
+++ b/polly/lib/External/isl/pip_test.sh.in
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+EXEEXT=@EXEEXT@
+
+PIP_TESTS="\
+ boulet.pip \
+ brisebarre.pip \
+ cg1.pip \
+ esced.pip \
+ ex2.pip \
+ ex.pip \
+ fimmel.pip \
+ max.pip \
+ negative.pip \
+ seghir-vd.pip \
+ small.pip \
+ sor1d.pip \
+ square.pip \
+ sven.pip \
+ tobi.pip"
+
+for i in $PIP_TESTS; do
+ echo $i;
+ ./isl_pip$EXEEXT --format=set --context=gbr -T < $srcdir/test_inputs/$i || exit
+ ./isl_pip$EXEEXT --format=set --context=lexmin -T < $srcdir/test_inputs/$i || exit
+ ./isl_pip$EXEEXT --format=affine --context=gbr -T < $srcdir/test_inputs/$i || exit
+ ./isl_pip$EXEEXT --format=affine --context=lexmin -T < $srcdir/test_inputs/$i || exit
+done
diff --git a/polly/lib/External/isl/polyhedron_detect_equalities.c b/polly/lib/External/isl/polyhedron_detect_equalities.c
new file mode 100644
index 00000000000..567acec71df
--- /dev/null
+++ b/polly/lib/External/isl/polyhedron_detect_equalities.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <isl/set.h>
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx = isl_ctx_alloc();
+ struct isl_basic_set *bset;
+
+ bset = isl_basic_set_read_from_file(ctx, stdin);
+ bset = isl_basic_set_detect_equalities(bset);
+ isl_basic_set_print(bset, stdout, 0, "", "", ISL_FORMAT_POLYLIB);
+ isl_basic_set_free(bset);
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/polyhedron_minimize.c b/polly/lib/External/isl/polyhedron_minimize.c
new file mode 100644
index 00000000000..526b37368f2
--- /dev/null
+++ b/polly/lib/External/isl/polyhedron_minimize.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl/set.h>
+#include <isl/vec.h>
+#include <isl_ilp_private.h>
+#include <isl_seq.h>
+#include <isl_vec_private.h>
+
+/* The input of this program is the same as that of the "polytope_minimize"
+ * program from the barvinok distribution.
+ *
+ * Constraints of set is PolyLib format.
+ * Linear or affine objective function in PolyLib format.
+ */
+
+static struct isl_vec *isl_vec_lin_to_aff(struct isl_vec *vec)
+{
+ struct isl_vec *aff;
+
+ if (!vec)
+ return NULL;
+ aff = isl_vec_alloc(vec->ctx, 1 + vec->size);
+ if (!aff)
+ goto error;
+ isl_int_set_si(aff->el[0], 0);
+ isl_seq_cpy(aff->el + 1, vec->el, vec->size);
+ isl_vec_free(vec);
+ return aff;
+error:
+ isl_vec_free(vec);
+ return NULL;
+}
+
+/* Rotate elements of vector right.
+ * In particular, move the constant term from the end of the
+ * vector to the start of the vector.
+ */
+static struct isl_vec *vec_ror(struct isl_vec *vec)
+{
+ int i;
+
+ if (!vec)
+ return NULL;
+ for (i = vec->size - 2; i >= 0; --i)
+ isl_int_swap(vec->el[i], vec->el[i + 1]);
+ return vec;
+}
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx = isl_ctx_alloc();
+ struct isl_basic_set *bset;
+ struct isl_vec *obj;
+ struct isl_vec *sol;
+ isl_int opt;
+ unsigned dim;
+ enum isl_lp_result res;
+ isl_printer *p;
+
+ isl_int_init(opt);
+ bset = isl_basic_set_read_from_file(ctx, stdin);
+ assert(bset);
+ obj = isl_vec_read_from_file(ctx, stdin);
+ assert(obj);
+ dim = isl_basic_set_total_dim(bset);
+ assert(obj->size >= dim && obj->size <= dim + 1);
+ if (obj->size != dim + 1)
+ obj = isl_vec_lin_to_aff(obj);
+ else
+ obj = vec_ror(obj);
+ res = isl_basic_set_solve_ilp(bset, 0, obj->el, &opt, &sol);
+ switch (res) {
+ case isl_lp_error:
+ fprintf(stderr, "error\n");
+ return -1;
+ case isl_lp_empty:
+ fprintf(stdout, "empty\n");
+ break;
+ case isl_lp_unbounded:
+ fprintf(stdout, "unbounded\n");
+ break;
+ case isl_lp_ok:
+ p = isl_printer_to_file(ctx, stdout);
+ p = isl_printer_print_vec(p, sol);
+ p = isl_printer_end_line(p);
+ p = isl_printer_print_isl_int(p, opt);
+ p = isl_printer_end_line(p);
+ isl_printer_free(p);
+ }
+ isl_basic_set_free(bset);
+ isl_vec_free(obj);
+ isl_vec_free(sol);
+ isl_ctx_free(ctx);
+ isl_int_clear(opt);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/polyhedron_sample.c b/polly/lib/External/isl/polyhedron_sample.c
new file mode 100644
index 00000000000..3fc442f2999
--- /dev/null
+++ b/polly/lib/External/isl/polyhedron_sample.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl_map_private.h>
+#include "isl_sample.h"
+#include <isl/vec.h>
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx = isl_ctx_alloc();
+ struct isl_basic_set *bset;
+ struct isl_vec *sample;
+ isl_printer *p;
+
+ bset = isl_basic_set_read_from_file(ctx, stdin);
+ sample = isl_basic_set_sample_vec(isl_basic_set_copy(bset));
+ p = isl_printer_to_file(ctx, stdout);
+ p = isl_printer_print_vec(p, sample);
+ p = isl_printer_end_line(p);
+ isl_printer_free(p);
+ assert(sample);
+ if (isl_vec_size(sample) > 0)
+ assert(isl_basic_set_contains(bset, sample));
+ isl_basic_set_free(bset);
+ isl_vec_free(sample);
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/polytope_scan.c b/polly/lib/External/isl/polytope_scan.c
new file mode 100644
index 00000000000..3fb3a4da460
--- /dev/null
+++ b/polly/lib/External/isl/polytope_scan.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, K.U.Leuven, Departement
+ * Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
+ */
+
+#include <assert.h>
+#include <isl_map_private.h>
+#include "isl_equalities.h"
+#include <isl_seq.h>
+#include "isl_scan.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+/* The input of this program is the same as that of the "polytope_scan"
+ * program from the barvinok distribution.
+ *
+ * Constraints of set is PolyLib format.
+ *
+ * The input set is assumed to be bounded.
+ */
+
+struct scan_samples {
+ struct isl_scan_callback callback;
+ struct isl_mat *samples;
+};
+
+static int scan_samples_add_sample(struct isl_scan_callback *cb,
+ __isl_take isl_vec *sample)
+{
+ struct scan_samples *ss = (struct scan_samples *)cb;
+
+ ss->samples = isl_mat_extend(ss->samples, ss->samples->n_row + 1,
+ ss->samples->n_col);
+ if (!ss->samples)
+ goto error;
+
+ isl_seq_cpy(ss->samples->row[ss->samples->n_row - 1],
+ sample->el, sample->size);
+
+ isl_vec_free(sample);
+ return 0;
+error:
+ isl_vec_free(sample);
+ return -1;
+}
+
+static struct isl_mat *isl_basic_set_scan_samples(struct isl_basic_set *bset)
+{
+ isl_ctx *ctx;
+ unsigned dim;
+ struct scan_samples ss;
+
+ ctx = isl_basic_set_get_ctx(bset);
+ dim = isl_basic_set_total_dim(bset);
+ ss.callback.add = scan_samples_add_sample;
+ ss.samples = isl_mat_alloc(ctx, 0, 1 + dim);
+ if (!ss.samples)
+ goto error;
+
+ if (isl_basic_set_scan(bset, &ss.callback) < 0) {
+ isl_mat_free(ss.samples);
+ return NULL;
+ }
+
+ return ss.samples;
+error:
+ isl_basic_set_free(bset);
+ return NULL;
+}
+
+static struct isl_mat *isl_basic_set_samples(struct isl_basic_set *bset)
+{
+ struct isl_mat *T;
+ struct isl_mat *samples;
+
+ if (!bset)
+ return NULL;
+
+ if (bset->n_eq == 0)
+ return isl_basic_set_scan_samples(bset);
+
+ bset = isl_basic_set_remove_equalities(bset, &T, NULL);
+ samples = isl_basic_set_scan_samples(bset);
+ return isl_mat_product(samples, isl_mat_transpose(T));
+}
+
+int main(int argc, char **argv)
+{
+ struct isl_ctx *ctx = isl_ctx_alloc();
+ struct isl_basic_set *bset;
+ struct isl_mat *samples;
+
+ bset = isl_basic_set_read_from_file(ctx, stdin);
+ samples = isl_basic_set_samples(bset);
+ isl_mat_print_internal(samples, stdout, 0);
+ isl_mat_free(samples);
+ isl_ctx_free(ctx);
+
+ return 0;
+}
diff --git a/polly/lib/External/isl/print.c b/polly/lib/External/isl/print.c
new file mode 100644
index 00000000000..5e3a5319636
--- /dev/null
+++ b/polly/lib/External/isl/print.c
@@ -0,0 +1,100 @@
+#include <isl/ctx.h>
+#include <isl/id.h>
+#include <isl/space.h>
+#include <isl/local_space.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>
+#include <isl/polynomial.h>
+#include <isl/band.h>
+#include <isl/constraint.h>
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/printer.h>
+#include <isl/val.h>
+
+#undef BASE
+#define BASE id
+#include <print_templ.c>
+#undef BASE
+#define BASE val
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_val
+#include <print_templ.c>
+#undef BASE
+#define BASE space
+#include <print_templ.c>
+#undef BASE
+#define BASE local_space
+#include <print_templ.c>
+#undef BASE
+#define BASE basic_set
+#include <print_templ.c>
+#undef BASE
+#define BASE basic_map
+#include <print_templ.c>
+#undef BASE
+#define BASE set
+#include <print_templ.c>
+#undef BASE
+#define BASE map
+#include <print_templ.c>
+#undef BASE
+#define BASE union_set
+#include <print_templ.c>
+#undef BASE
+#define BASE union_map
+#include <print_templ.c>
+#undef BASE
+#define BASE qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_qpolynomial
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_qpolynomial_fold
+#include <print_templ.c>
+#undef BASE
+#define BASE band
+#include <print_templ.c>
+#undef BASE
+#define BASE constraint
+#include <print_templ.c>
+#undef BASE
+#define BASE aff
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE pw_multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE union_pw_multi_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_pw_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE point
+#include <print_templ.c>
+#undef BASE
+#define BASE ast_expr
+#include <print_templ.c>
+#undef BASE
+#define BASE ast_node
+#include <print_templ.c>
diff --git a/polly/lib/External/isl/print_templ.c b/polly/lib/External/isl/print_templ.c
new file mode 100644
index 00000000000..f147fdc5480
--- /dev/null
+++ b/polly/lib/External/isl/print_templ.c
@@ -0,0 +1,33 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef TYPE
+#define TYPE CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+
+void FN(TYPE,dump)(__isl_keep TYPE *obj)
+{
+ isl_printer *p;
+
+ if (!obj)
+ return;
+ p = isl_printer_to_file(FN(TYPE,get_ctx)(obj), stderr);
+ p = FN(isl_printer_print,BASE)(p, obj);
+ p = isl_printer_end_line(p);
+ isl_printer_free(p);
+}
+
+__isl_give char *FN(TYPE,to_str)(__isl_keep TYPE *obj)
+{
+ isl_printer *p;
+ char *s;
+
+ if (!obj)
+ return NULL;
+ p = isl_printer_to_str(FN(TYPE,get_ctx)(obj));
+ p = FN(isl_printer_print,BASE)(p, obj);
+ s = isl_printer_get_str(p);
+ isl_printer_free(p);
+
+ return s;
+}
diff --git a/polly/lib/External/isl/test_inputs/affine.polylib b/polly/lib/External/isl/test_inputs/affine.polylib
new file mode 100644
index 00000000000..f14720c0a0a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/affine.polylib
@@ -0,0 +1,9 @@
+# the affine hull of {[a,b] : a=b && 1 <= a <= 163} ...
+3 4
+0 1 -1 0
+1 1 0 -1
+1 -1 0 163
+
+# ... is {[a,b] : a=b} (and not {[In_1,In_2]}, as Omega 1.2 claims)
+1 4
+0 1 -1 0
diff --git a/polly/lib/External/isl/test_inputs/affine2.polylib b/polly/lib/External/isl/test_inputs/affine2.polylib
new file mode 100644
index 00000000000..c67db77bb6e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/affine2.polylib
@@ -0,0 +1,9 @@
+5 5
+1 -2 0 1 0
+1 2 0 -1 1
+1 0 -2 1 0
+1 0 2 -1 1
+1 0 0 1 -1
+
+1 5
+0 1 -1 0 0
diff --git a/polly/lib/External/isl/test_inputs/affine3.polylib b/polly/lib/External/isl/test_inputs/affine3.polylib
new file mode 100644
index 00000000000..f2bc9a2db2f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/affine3.polylib
@@ -0,0 +1,7 @@
+3 4
+1 1 0 0
+1 -7 4 2
+1 5 -4 2
+
+1 4
+0 3 -2 0
diff --git a/polly/lib/External/isl/test_inputs/application.omega b/polly/lib/External/isl/test_inputs/application.omega
new file mode 100644
index 00000000000..8f4fd1db39a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/application.omega
@@ -0,0 +1,3 @@
+{[x]}
+{[x] -> [y] : y = 2x}
+{[y]: Exists ( alpha : 2alpha = y)}
diff --git a/polly/lib/External/isl/test_inputs/application2.omega b/polly/lib/External/isl/test_inputs/application2.omega
new file mode 100644
index 00000000000..f2af1e86958
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/application2.omega
@@ -0,0 +1,3 @@
+{[x] : x >= 0 && x <= 20 }
+{[x] -> [y] : y = 2x}
+{[y]: Exists ( alpha : 2alpha = y && 0 <= y && y <= 40)}
diff --git a/polly/lib/External/isl/test_inputs/basicLinear.pwqp b/polly/lib/External/isl/test_inputs/basicLinear.pwqp
new file mode 100644
index 00000000000..0af7fabb53f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/basicLinear.pwqp
@@ -0,0 +1 @@
+[P, Q] -> { [n, m] -> n : n >= 1 and m >= n and m <= P and m <= Q }
diff --git a/polly/lib/External/isl/test_inputs/basicLinear2.pwqp b/polly/lib/External/isl/test_inputs/basicLinear2.pwqp
new file mode 100644
index 00000000000..d411a369158
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/basicLinear2.pwqp
@@ -0,0 +1 @@
+[P, Q] -> { [n, m] -> n : n >= 1 and m >= n and m <= P and n >= -1 + Q }
diff --git a/polly/lib/External/isl/test_inputs/basicTest.pwqp b/polly/lib/External/isl/test_inputs/basicTest.pwqp
new file mode 100644
index 00000000000..52e7fc8e697
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/basicTest.pwqp
@@ -0,0 +1 @@
+[p] -> { [n, m] -> (n + n^2) : n >= 1 and m >= n and m <= p }
diff --git a/polly/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp b/polly/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp
new file mode 100644
index 00000000000..6cb4490215c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/basicTestParameterPosNeg.pwqp
@@ -0,0 +1 @@
+[p] -> { [n, m] -> (n + n^3) : n >= -1 and m >= n and m <= p }
diff --git a/polly/lib/External/isl/test_inputs/boulet.pip b/polly/lib/External/isl/test_inputs/boulet.pip
new file mode 100644
index 00000000000..78e90ddf58b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/boulet.pip
@@ -0,0 +1,13 @@
+0 3
+
+-1
+
+5 6
+1 1 -1 2 0 0
+1 0 1 1 4 20
+1 0 -1 -1 0 0
+1 0 1 -1 2 10
+1 0 -1 1 2 10
+
+Urs_parms
+Urs_unknowns
diff --git a/polly/lib/External/isl/test_inputs/brisebarre.pip b/polly/lib/External/isl/test_inputs/brisebarre.pip
new file mode 100644
index 00000000000..f3decadfd27
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/brisebarre.pip
@@ -0,0 +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
diff --git a/polly/lib/External/isl/test_inputs/cg1.pip b/polly/lib/External/isl/test_inputs/cg1.pip
new file mode 100644
index 00000000000..78e31f187b1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/cg1.pip
@@ -0,0 +1,15 @@
+2 4
+ 1 1 0 -1
+ 1 -1 1 0
+
+-1
+
+8 7
+ 1 0 1 0 -1 0 0
+ 1 0 -1 0 1 0 0
+ 1 1 0 0 0 -1 0
+ 1 -1 0 0 0 1 0
+ 1 0 1 0 0 0 -1
+ 1 0 -1 0 0 1 0
+ 1 0 -1 1 0 0 -1
+ 1 0 0 -1 0 1 0
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic.c b/polly/lib/External/isl/test_inputs/codegen/atomic.c
new file mode 100644
index 00000000000..73731c0c22b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic.c
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+ if (c0 >= 1)
+ b(c0 - 1);
+ if (c0 <= 9)
+ a(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic.in b/polly/lib/External/isl/test_inputs/codegen/atomic.in
new file mode 100644
index 00000000000..754b3d0cf2f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic.in
@@ -0,0 +1,3 @@
+{ a[i] -> [i] : 0 <= i < 10; b[i] -> [i+1] : 0 <= i < 10 }
+{ : }
+{ [i] -> atomic[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic2.c b/polly/lib/External/isl/test_inputs/codegen/atomic2.c
new file mode 100644
index 00000000000..9c4a57e3e5a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic2.c
@@ -0,0 +1,2 @@
+for (int c0 = ((b0 + 32767) % 32768) + 1; c0 <= 65534; c0 += 32768)
+ A(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic2.in b/polly/lib/External/isl/test_inputs/codegen/atomic2.in
new file mode 100644
index 00000000000..99901d0e191
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic2.in
@@ -0,0 +1,4 @@
+# Check that isl properly handles atomic domains that are unions.
+[nn, b0] -> { A[a] -> [a, 0, b0] : exists (e0 = [(b0 - a)/32768]: 32768e0 = b0 - a and a >= 1 and b0 >= 0 and b0 <= 32767 and a <= 65534) }
+[nn, b0] -> { : b0 >= 0 and b0 <= 32767 }
+[nn, b0] -> { [a, b, c] -> atomic[2] : c >= 1; [a, 0, c] -> atomic[2] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic3.c b/polly/lib/External/isl/test_inputs/codegen/atomic3.c
new file mode 100644
index 00000000000..e63e09201a1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic3.c
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 64; c0 += 1) {
+ if (c0 >= 63) {
+ sync();
+ } else if (c0 >= 1) {
+ sync();
+ } else
+ sync();
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic3.in b/polly/lib/External/isl/test_inputs/codegen/atomic3.in
new file mode 100644
index 00000000000..4d0c4953107
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic3.in
@@ -0,0 +1,5 @@
+# Check that isl is not confused by inconsistent
+# separation_class and atomic options.
+{ sync[] -> [i, 0] : 0 <= i <= 64 }
+{ : }
+{ [i, 0] -> separation_class[[1] -> [0]] : 1 <= i <= 62; [i, 0] -> atomic[1]}
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic4.c b/polly/lib/External/isl/test_inputs/codegen/atomic4.c
new file mode 100644
index 00000000000..624c2af1d25
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic4.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 64; c0 += 1)
+ sync();
diff --git a/polly/lib/External/isl/test_inputs/codegen/atomic4.in b/polly/lib/External/isl/test_inputs/codegen/atomic4.in
new file mode 100644
index 00000000000..c5dab102c6a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/atomic4.in
@@ -0,0 +1,4 @@
+# Check that isl is not confused by inconsistent separate and atomic options.
+{ sync[] -> [i, 0] : 0 <= i <= 64 }
+{ : }
+{ [i, 0] -> separate[1] : 1 <= i <= 62; [i, 0] -> atomic[1] : i <= 10 or i >= 20 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.c
new file mode 100644
index 00000000000..7f22e2e417e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.c
@@ -0,0 +1 @@
+S1();
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.in
new file mode 100644
index 00000000000..10e3e408a6d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-1.in
@@ -0,0 +1,3 @@
+{ S1[] -> [0] }
+{ : }
+{ [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.c
new file mode 100644
index 00000000000..b87b57eacfb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.c
@@ -0,0 +1,2 @@
+if (M >= 0)
+ S1();
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.in
new file mode 100644
index 00000000000..3bbfd35cc2b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-2.in
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> { : }
+[M] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.c
new file mode 100644
index 00000000000..7f22e2e417e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.c
@@ -0,0 +1 @@
+S1();
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.in
new file mode 100644
index 00000000000..f99dd344e46
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/0D-3.in
@@ -0,0 +1,3 @@
+[M] -> { S1[] -> [0] : M >= 0 }
+[M] -> { : M >= 0 }
+[M] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.c
new file mode 100644
index 00000000000..53dd8931e6f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.c
@@ -0,0 +1 @@
+S1(2 * M, M);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.in
new file mode 100644
index 00000000000..efd0a7ff827
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-1.in
@@ -0,0 +1,3 @@
+[M] -> { S1[2M, M] -> [2M, M, 0] }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.c
new file mode 100644
index 00000000000..0a8cbe37d2f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.c
@@ -0,0 +1 @@
+S1(2 * M, N + 2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.in
new file mode 100644
index 00000000000..de5157ceac6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/1point-2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2M, 2 + N] -> [2M, 2 + N, 0] }
+[M, N] -> { : }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.c b/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.c
new file mode 100644
index 00000000000..56659a06779
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.c
@@ -0,0 +1,14 @@
+{
+ for (int c0 = m; c0 <= min(n, p - 1); c0 += 1)
+ S1(c0);
+ for (int c0 = p; c0 <= min(m - 1, q); c0 += 1)
+ S2(c0);
+ for (int c0 = max(m, p); c0 <= min(n, q); c0 += 1) {
+ S1(c0);
+ S2(c0);
+ }
+ for (int c0 = max(max(m, p), q + 1); c0 <= n; c0 += 1)
+ S1(c0);
+ for (int c0 = max(max(m, n + 1), p); c0 <= q; c0 += 1)
+ S2(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.in b/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.in
new file mode 100644
index 00000000000..7814076053b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/4-param.in
@@ -0,0 +1,3 @@
+[m, n, p, q] -> { S1[i0] -> [i0, 0] : i0 >= m and i0 <= n; S2[i0] -> [i0, 1] : i0 >= p and i0 <= q }
+[m, n, p, q] -> { : }
+[m, n, p, q] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/README b/polly/lib/External/isl/test_inputs/codegen/cloog/README
new file mode 100644
index 00000000000..9250f11e161
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/README
@@ -0,0 +1,2 @@
+The tests in this directory have been adapted from the corresponding CLooG
+test cases.
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.c b/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.c
new file mode 100644
index 00000000000..df0407a437e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.c
@@ -0,0 +1 @@
+S1(0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.in b/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.in
new file mode 100644
index 00000000000..b8ec466f559
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/backtrack.in
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{ : }
+{ [i, j] -> atomic[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c
new file mode 100644
index 00000000000..95eb5f716e3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 2; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in
new file mode 100644
index 00000000000..e5f8bfafd15
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-1.in
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 2 }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c
new file mode 100644
index 00000000000..df0407a437e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.c
@@ -0,0 +1 @@
+S1(0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in
new file mode 100644
index 00000000000..7eb48f2da74
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-2.in
@@ -0,0 +1,3 @@
+{ S1[0] -> [0, 0] }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c
new file mode 100644
index 00000000000..d0dd54bd089
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in
new file mode 100644
index 00000000000..59ce2c9249b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-3.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M }
+[M] -> { : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c
new file mode 100644
index 00000000000..0ebb7ccbb43
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M + 1; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in
new file mode 100644
index 00000000000..5f79acf698c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-4.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= 1 + M }
+[M] -> { : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c
new file mode 100644
index 00000000000..09e8c422168
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.c
@@ -0,0 +1 @@
+S1(1, floord(M + 1, 2));
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in
new file mode 100644
index 00000000000..3a6f9085514
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/basic-bounds-5.in
@@ -0,0 +1,3 @@
+[M] -> { S1[1, i1] -> [1, i1, 0] : 2i1 >= M and 2i1 <= 1 + M }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block.c b/polly/lib/External/isl/test_inputs/codegen/cloog/block.c
new file mode 100644
index 00000000000..e24ef30ade7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block.c
@@ -0,0 +1,6 @@
+{
+ S1();
+ S3(0);
+ S2();
+ S3(1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block.in b/polly/lib/External/isl/test_inputs/codegen/cloog/block.in
new file mode 100644
index 00000000000..faf2af5f466
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block.in
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 1] : i0 >= 0 and i0 <= 1; S1[] -> [0, 0]; S2[] -> [1, 0] }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/block2.c
new file mode 100644
index 00000000000..d3fbbd7802a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block2.c
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+ S1(c0, 1);
+ S3(c0, 1);
+ S2(c0, 1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/block2.in
new file mode 100644
index 00000000000..d2b5db44039
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block2.in
@@ -0,0 +1,3 @@
+{ S1[i0, 1] -> [i0, 1, 6] : i0 >= 0 and i0 <= 9; S2[i0, 1] -> [i0, 1, 11] : i0 >= 0 and i0 <= 9; S3[i0, 1] -> [i0, 1, 8] : i0 >= 0 and i0 <= 9 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/block3.c
new file mode 100644
index 00000000000..ff4d5539178
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block3.c
@@ -0,0 +1,6 @@
+{
+ S1();
+ for (int c0 = 0; c0 <= 1; c0 += 1)
+ S3(c0);
+ S2();
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/block3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/block3.in
new file mode 100644
index 00000000000..39c0abb790d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/block3.in
@@ -0,0 +1,3 @@
+{ S2[] -> [1]; S3[i0] -> [i0] : i0 >= 0 and i0 <= 1; S1[] -> [0] }
+{ : }
+{ [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c
new file mode 100644
index 00000000000..8e87cba33db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.c
@@ -0,0 +1,18 @@
+{
+ for (int c0 = 2; c0 <= 3; c0 += 1)
+ for (int c1 = -c0 + 6; c1 <= 6; c1 += 1)
+ S1(c0, c1);
+ for (int c0 = 4; c0 <= 8; c0 += 1) {
+ if (c0 >= 6) {
+ S2(c0, -c0 + 9);
+ } else {
+ if (c0 == 4)
+ for (int c1 = 3; c1 <= 4; c1 += 1)
+ S1(4, c1);
+ S1(c0, -c0 + 9);
+ S2(c0, -c0 + 9);
+ }
+ for (int c1 = max(c0 - 1, -c0 + 10); c1 <= 6; c1 += 1)
+ S1(c0, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in
new file mode 100644
index 00000000000..9f98fb85990
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/byu98-1-2-3.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1] -> [i0, i1, 0] : i1 >= 6 - i0 and i0 >= 2 and i1 >= 3 and i1 <= 6 and i1 >= -1 + i0; S2[i0, 9 - i0] -> [i0, 9 - i0, 1] : i0 <= 8 and i0 >= 4 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.c b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.c
new file mode 100644
index 00000000000..20d4e4d0b9e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.c
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+ S1(c0);
+ for (int c2 = 1; c2 < c0; c2 += 1)
+ S2(c0, c2);
+ S3(c0);
+ for (int c2 = c0 + 1; c2 <= n; c2 += 1) {
+ S4(c0, c2);
+ for (int c4 = 1; c4 < c0; c4 += 1)
+ S5(c0, c2, c4);
+ S6(c0, c2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.in b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.in
new file mode 100644
index 00000000000..90b56c638b3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i0] -> [i0, 1, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S2[i0, i1] -> [i0, 2, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S6[i0, i1] -> [i0, 4, i1, 3, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [i0, 3, 0, 0, 0, 0] : i0 >= 1 and i0 <= n; S4[i0, i1] -> [i0, 4, i1, 1, 0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S5[i0, i1, i2] -> [i0, 4, i1, 2, i2, 1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> { : }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c
new file mode 100644
index 00000000000..c746460b4fa
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c
@@ -0,0 +1,20 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1) {
+ S1(c1);
+ for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+ S4(c1, c2);
+ }
+ for (int c0 = 1; c0 < 3 * M - 1; c0 += 3) {
+ S3((c0 + 2) / 3);
+ if (3 * M >= c0 + 8) {
+ for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1) {
+ S6((c0 + 2) / 3, c1);
+ for (int c4 = (c0 + 5) / 3; c4 < c1; c4 += 1)
+ S5(c4, c1, (c0 + 2) / 3);
+ }
+ } else if (c0 + 5 == 3 * M)
+ S6(M - 1, M);
+ for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1)
+ S2(c1, (c0 + 2) / 3);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in
new file mode 100644
index 00000000000..b44b4568f71
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/cholesky2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [3i1, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0, i1] -> [0, i0, i1] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, i0, 0] : i0 >= 1 and i0 <= M; S6[i0, i1] -> [-1 + 3i0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S3[i0] -> [-2 + 3i0, 0, 0] : i0 >= 1 and i0 <= M; S5[i0, i1, i2] -> [-1 + 3i2, i1, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 and i2 <= -1 + i0 }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/christian.c b/polly/lib/External/isl/test_inputs/codegen/cloog/christian.c
new file mode 100644
index 00000000000..98b52d8d0fe
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/christian.c
@@ -0,0 +1,6 @@
+for (int c0 = -N + 1; c0 <= N; c0 += 1) {
+ for (int c1 = max(0, c0 - 1); c1 < min(N, N + c0 - 1); c1 += 1)
+ S2(c1, -c0 + c1 + 1);
+ for (int c1 = max(0, c0); c1 < min(N, N + c0); c1 += 1)
+ S1(c1, -c0 + c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/christian.in b/polly/lib/External/isl/test_inputs/codegen/cloog/christian.in
new file mode 100644
index 00000000000..af3df07967f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/christian.in
@@ -0,0 +1,3 @@
+[N] -> { S1[i0, i1] -> [i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S2[i0, i1] -> [1 + i0 - i1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N }
+[N] -> { : }
+[N] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/classen.c b/polly/lib/External/isl/test_inputs/codegen/cloog/classen.c
new file mode 100644
index 00000000000..ad7be335451
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/classen.c
@@ -0,0 +1,86 @@
+{
+ if (m == 1) {
+ S1(0, 1, 1, 1);
+ S8(0, 1);
+ } else if (m >= 2) {
+ S1(0, 1, 1, 1);
+ S3(0, 1, 1, 2, 1, 1, 1, 2);
+ S4(0, 1, 2, 2, 1, 1, 2, 2);
+ S2(0, 1, 1, 1, 1, 1, 2, 1);
+ S8(0, 1);
+ }
+ for (int c0 = 1; c0 < 2 * m - 3; c0 += 1) {
+ if (c0 + 1 == m) {
+ S5(m - 2, 1, m - 1, 1, m - 1, 1, m, 1);
+ S1(m - 1, 1, m, 1);
+ S3(m - 1, 1, m, 2, m, 1, m, 2);
+ } else if (m >= c0 + 2) {
+ S5(c0 - 1, 1, c0, 1, c0, 1, c0 + 1, 1);
+ S1(c0, 1, c0 + 1, 1);
+ S3(c0, 1, c0 + 1, 2, c0 + 1, 1, c0 + 1, 2);
+ S4(c0, 1, c0 + 2, 2, c0 + 1, 1, c0 + 2, 2);
+ S2(c0, 1, c0 + 1, 1, c0 + 1, 1, c0 + 2, 1);
+ } else {
+ S5(c0 - 1, -m + c0 + 2, c0, -m + c0 + 2, m - 1, -m + c0 + 2, m, -m + c0 + 2);
+ S6(c0 - 1, -m + c0 + 1, c0, -m + c0 + 2, m, -m + c0 + 1, m, -m + c0 + 2);
+ S1(c0, -m + c0 + 2, m, -m + c0 + 2);
+ S3(c0, -m + c0 + 2, c0 + 1, -m + c0 + 3, m, -m + c0 + 2, m, -m + c0 + 3);
+ }
+ for (int c2 = max(2, -m + c0 + 3); c2 <= min(m - 1, c0); c2 += 1) {
+ S5(c0 - 1, c2, c0, c2, c0 - c2 + 1, c2, c0 - c2 + 2, c2);
+ S7(c0 - 1, c2 - 1, c0 + 1, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 3, c2);
+ S6(c0 - 1, c2 - 1, c0, c2, c0 - c2 + 2, c2 - 1, c0 - c2 + 2, c2);
+ S1(c0, c2, c0 - c2 + 2, c2);
+ S3(c0, c2, c0 + 1, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 2, c2 + 1);
+ S4(c0, c2, c0 + 2, c2 + 1, c0 - c2 + 2, c2, c0 - c2 + 3, c2 + 1);
+ S2(c0, c2, c0 + 1, c2, c0 - c2 + 2, c2, c0 - c2 + 3, c2);
+ }
+ if (c0 + 1 == m) {
+ S7(m - 2, m - 1, m, m, 1, m - 1, 2, m);
+ S6(m - 2, m - 1, m - 1, m, 1, m - 1, 1, m);
+ S1(m - 1, m, 1, m);
+ S2(m - 1, m, m, m, 1, m, 2, m);
+ } else if (c0 >= m) {
+ S5(c0 - 1, m, c0, m, -m + c0 + 1, m, -m + c0 + 2, m);
+ S7(c0 - 1, m - 1, c0 + 1, m, -m + c0 + 2, m - 1, -m + c0 + 3, m);
+ S6(c0 - 1, m - 1, c0, m, -m + c0 + 2, m - 1, -m + c0 + 2, m);
+ S1(c0, m, -m + c0 + 2, m);
+ S2(c0, m, c0 + 1, m, -m + c0 + 2, m, -m + c0 + 3, m);
+ } else {
+ S7(c0 - 1, c0, c0 + 1, c0 + 1, 1, c0, 2, c0 + 1);
+ S6(c0 - 1, c0, c0, c0 + 1, 1, c0, 1, c0 + 1);
+ S1(c0, c0 + 1, 1, c0 + 1);
+ S3(c0, c0 + 1, c0 + 1, c0 + 2, 1, c0 + 1, 1, c0 + 2);
+ S4(c0, c0 + 1, c0 + 2, c0 + 2, 1, c0 + 1, 2, c0 + 2);
+ S2(c0, c0 + 1, c0 + 1, c0 + 1, 1, c0 + 1, 2, c0 + 1);
+ }
+ for (int c8 = max(1, -m + c0 + 2); c8 <= min(m, c0 + 1); c8 += 1)
+ S8(c0, c8);
+ }
+ if (m >= 2) {
+ if (m >= 3) {
+ S5(2 * m - 4, m - 1, 2 * m - 3, m - 1, m - 1, m - 1, m, m - 1);
+ S6(2 * m - 4, m - 2, 2 * m - 3, m - 1, m, m - 2, m, m - 1);
+ S1(2 * m - 3, m - 1, m, m - 1);
+ S3(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+ S5(2 * m - 4, m, 2 * m - 3, m, m - 2, m, m - 1, m);
+ S7(2 * m - 4, m - 1, 2 * m - 2, m, m - 1, m - 1, m, m);
+ S6(2 * m - 4, m - 1, 2 * m - 3, m, m - 1, m - 1, m - 1, m);
+ S1(2 * m - 3, m, m - 1, m);
+ } else {
+ S5(0, 1, 1, 1, 1, 1, 2, 1);
+ S1(1, 1, 2, 1);
+ S3(1, 1, 2, 2, 2, 1, 2, 2);
+ S7(0, 1, 2, 2, 1, 1, 2, 2);
+ S6(0, 1, 1, 2, 1, 1, 1, 2);
+ S1(1, 2, 1, 2);
+ }
+ S2(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+ for (int c8 = m - 1; c8 <= m; c8 += 1)
+ S8(2 * m - 3, c8);
+ S5(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
+ S6(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
+ S1(2 * m - 2, m, m, m);
+ S8(2 * m - 2, m);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/classen.in b/polly/lib/External/isl/test_inputs/codegen/cloog/classen.in
new file mode 100644
index 00000000000..8dc0b76a505
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/classen.in
@@ -0,0 +1,3 @@
+[m] -> { S2[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S4[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S5[i0, i1, 1 + i0, i1, 2 + i0 - i1, i1, 3 + i0 - i1, i1] -> [1 + i0, 0, i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 3 - m + i0 and i1 >= 1; S7[i0, i1, 2 + i0, 1 + i1, 2 + i0 - i1, i1, 3 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -4 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 3 - m + i0 and i1 >= 1; S6[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [1 + i0, 0, 1 + i1, 0, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S3[i0, i1, 1 + i0, 1 + i1, 2 + i0 - i1, i1, 2 + i0 - i1, 1 + i1] -> [i0, 0, i1, 2, 2 + i0 - i1, i1, 1] : m >= 1 and i0 <= -3 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= -1 + m and i1 >= 2 - m + i0 and i1 >= 1; S8[i0, i1] -> [i0, 1, 0, 0, 0, 0, 0] : i0 <= -2 + 2m and i0 >= 0 and i1 <= 1 + i0 and i1 <= m and i1 >= 2 - m + i0 and i1 >= 1; S1[i0, i1, 2 + i0 - i1, i1] -> [i0, 0, i1, 1, 0, 0, 0] : m >= 1 and i1 >= 2 - m + i0 and i1 <= 1 + i0 and i1 <= m and i1 >= 1 }
+[m] -> { : m >= 0 }
+[m] -> { [i, j, k, l, m', n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.c
new file mode 100644
index 00000000000..a737d2d4b1a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.c
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(max(max(4, 5 * outerTimeTileScatter), 5 * outerProcTileScatter1), 5 * outerProcTileScatter2 + 1), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 - N), 10 * outerProcTileScatter2 - N + 1), 10 * outerProcTileScatter1 - 2 * N + 2); c0 <= min(min(min(min(min(min(5 * outerTimeTileScatter + 4, 10 * outerProcTileScatter1 + 4), 5 * outerProcTileScatter1 + 5 * outerProcTileScatter2 + 5), 5 * outerProcTileScatter1 + M + 2), 2 * M + 2 * N - 6), 5 * outerProcTileScatter2 + M + N), 10 * outerProcTileScatter2 + N + 3); c0 += 1)
+ for (int c1 = max(max(max(max(5 * outerProcTileScatter1, 5 * outerProcTileScatter2 + 1), -5 * outerProcTileScatter2 + c0 - 1), -M + c0 + 2), (c0 + 1) / 2 + 2); c1 <= min(min(min(min(5 * outerProcTileScatter1 + 4, 5 * outerProcTileScatter2 + N + 2), -5 * outerProcTileScatter2 + N + c0), c0), N + c0 / 2 - 1); c1 += 1)
+ for (int c2 = max(max(5 * outerProcTileScatter2, -N + c1 + 2), c0 - c1 + 3); c2 <= min(min(5 * outerProcTileScatter2 + 4, c1 - 1), N + c0 - c1); c2 += 1)
+ S1(c0 - c1 + 1, -c0 + c1 + c2 - 2, c1 - c2, c0, c1, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.in
new file mode 100644
index 00000000000..8a74eaa9728
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/classen2.in
@@ -0,0 +1,3 @@
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { S1[i0, i1, i2, 2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] -> [2i0 + i1 + i2, 1 + i0 + i1 + i2, 1 + i0 + i1] : N >= 3 and i2 <= 3 + 5outerProcTileScatter1 - i0 - i1 and i1 >= -1 + 5outerProcTileScatter2 - i0 and M >= 2 and i2 <= 4 + 5outerTimeTileScatter - 2i0 - i1 and i1 <= 3 + 5outerProcTileScatter2 - i0 and i2 >= 1 and i2 <= -2 + N and i1 >= 1 and i1 <= -2 + N and i0 >= 1 and i0 <= -1 + M and i2 >= 5outerTimeTileScatter - 2i0 - i1 and i2 >= -1 + 5outerProcTileScatter1 - i0 - i1 }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { : }
+[outerTimeTileScatter, outerProcTileScatter1, outerProcTileScatter2, M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/constant.c b/polly/lib/External/isl/test_inputs/codegen/cloog/constant.c
new file mode 100644
index 00000000000..f39a3a2bde0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/constant.c
@@ -0,0 +1,18 @@
+{
+ for (int c1 = 0; c1 <= min(1023, M + 1024); c1 += 1) {
+ S1(c1);
+ S3(c1);
+ }
+ for (int c1 = max(0, M + 1025); c1 <= 1023; c1 += 1) {
+ S2(c1);
+ S3(c1);
+ }
+ for (int c0 = 0; c0 <= min(1023, M + 1024); c0 += 1) {
+ S4(c0);
+ S6(c0);
+ }
+ for (int c0 = max(0, M + 1025); c0 <= 1023; c0 += 1) {
+ S5(c0);
+ S6(c0);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/constant.in b/polly/lib/External/isl/test_inputs/codegen/cloog/constant.in
new file mode 100644
index 00000000000..7cd365a8967
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/constant.in
@@ -0,0 +1,3 @@
+[M] -> { S5[i0] -> [i0, 0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S1[i0] -> [-1, i0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S3[i0] -> [-1, i0, 2] : i0 >= 0 and i0 <= 1023; S2[i0] -> [-1, i0, 1] : i0 >= 0 and i0 <= 1023 and i0 >= 1025 + M; S4[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 1023 and i0 <= 1024 + M; S6[i0] -> [i0, 0, 2] : i0 >= 0 and i0 <= 1023 }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.c b/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.c
new file mode 100644
index 00000000000..219165dc8c9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.c
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= 199; c0 += 1) {
+ for (int c2 = 50 * c0; c2 <= 50 * c0 + 24; c2 += 1)
+ for (int c3 = 0; c3 <= c2; c3 += 1)
+ S1(c0, c2, c3);
+ for (int c2 = 50 * c0 + 25; c2 <= 50 * c0 + 49; c2 += 1)
+ for (int c3 = 0; c3 <= c2; c3 += 1)
+ S2(c0, c2, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.in b/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.in
new file mode 100644
index 00000000000..24727a8737c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/constbound.in
@@ -0,0 +1,3 @@
+{ S2[i0, i1, i2] -> [i0, 1, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 25 + 50i0 and i1 <= 49 + 50i0; S1[i0, i1, i2] -> [i0, 0, i1, i2] : i1 >= 0 and i1 <= 9999 and i2 >= 0 and i2 <= i1 and i1 >= 50i0 and i1 <= 24 + 50i0 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/darte.c b/polly/lib/External/isl/test_inputs/codegen/cloog/darte.c
new file mode 100644
index 00000000000..acb63714ed2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/darte.c
@@ -0,0 +1,14 @@
+for (int c0 = -n + 1; c0 <= n; c0 += 1) {
+ if (c0 <= 0)
+ for (int c2 = -c0 + 4; c2 <= 2 * n - c0 + 2; c2 += 2)
+ S1(1, -c0 + 1, ((c0 + c2) / 2) - 1);
+ for (int c1 = max(c0 + 2, -c0 + 4); c1 <= min(2 * n - c0, 2 * n + c0); c1 += 2) {
+ for (int c2 = c1 + 2; c2 <= 2 * n + c1; c2 += 2)
+ S1((c0 + c1) / 2, (-c0 + c1) / 2, (-c1 + c2) / 2);
+ for (int c2 = 1; c2 <= n; c2 += 1)
+ S2(((c0 + c1) / 2) - 1, (-c0 + c1) / 2, c2);
+ }
+ if (c0 >= 1)
+ for (int c2 = 1; c2 <= n; c2 += 1)
+ S2(n, n - c0 + 1, c2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/darte.in b/polly/lib/External/isl/test_inputs/codegen/cloog/darte.in
new file mode 100644
index 00000000000..55897a5a7e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/darte.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [1 + i0 - i1, 2 + i0 + i1, i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n; S1[i0, i1, i2] -> [i0 - i1, i0 + i1, i0 + i1 + 2i2] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= n and i2 >= 1 and i2 <= n }
+[n] -> { : }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.c b/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.c
new file mode 100644
index 00000000000..7db605d5d5b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.c
@@ -0,0 +1,12 @@
+{
+ for (int c0 = 0; c0 <= min(T_2 - 1, T_66); c0 += 1) {
+ S1(c0);
+ S2(c0);
+ }
+ for (int c0 = T_2; c0 <= min(T_67 - 1, T_66); c0 += 1)
+ S2(c0);
+ for (int c0 = max(0, T_66 + 1); c0 < T_2; c0 += 1)
+ S1(c0);
+ if (T_2 == 0 && T_67 == 0)
+ S1(0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.in b/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.in
new file mode 100644
index 00000000000..fc0310b638f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dealII.in
@@ -0,0 +1,3 @@
+[T_2, T_67, T_66] -> { S1[scat_0] -> [scat_0, 0] : (scat_0 <= -1 + T_2 and scat_0 >= 0) or (scat_0 <= -T_67 and scat_0 >= 0); S2[scat_0] -> [scat_0, 1] : (scat_0 <= -1 + T_2 and scat_0 >= 0 and scat_0 <= T_66) or (scat_0 <= -1 + T_67 and scat_0 >= 0 and scat_0 <= T_66) }
+[T_2, T_67, T_66] -> { : T_2 <= 4 and T_2 >= 0 and T_67 <= 4 and T_67 >= 0 }
+[T_2, T_67, T_66] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c b/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c
new file mode 100644
index 00000000000..4c482e2997e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.c
@@ -0,0 +1,6 @@
+for (int c1 = 1; c1 <= 10; c1 += 1) {
+ for (int c3 = 1; c3 <= c1; c3 += 1)
+ S1(c1, c3);
+ for (int c3 = 11; c3 <= M; c3 += 1)
+ S2(c1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in b/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in
new file mode 100644
index 00000000000..c1541ccff7e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/donotsimp.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 11 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= 10 and i1 >= 1 and i1 <= i0 }
+[M] -> { : M >= 20 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dot.c b/polly/lib/External/isl/test_inputs/codegen/cloog/dot.c
new file mode 100644
index 00000000000..b08de331226
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dot.c
@@ -0,0 +1,7 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S1(0, c1);
+ for (int c0 = 1; c0 <= N; c0 += 1)
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dot.in b/polly/lib/External/isl/test_inputs/codegen/cloog/dot.in
new file mode 100644
index 00000000000..37e1f14bad2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dot.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[0, i1] -> [0, i1, 0] : i1 <= M and N >= 0 and i1 >= 1; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i1 <= M and i0 <= N and i1 >= 1 }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.c
new file mode 100644
index 00000000000..a1b10692c2a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.c
@@ -0,0 +1,12 @@
+{
+ for (int c0 = 1; c0 <= min(M, N); c0 += 1) {
+ S1(c0);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c0, c1);
+ }
+ for (int c0 = N + 1; c0 <= M; c0 += 1)
+ S1(c0);
+ for (int c0 = M + 1; c0 <= N; c0 += 1)
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.in
new file mode 100644
index 00000000000..8fa8381e20b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/dot2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= M }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c b/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c
new file mode 100644
index 00000000000..25590998d5f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.c
@@ -0,0 +1,23 @@
+{
+ S4(1, 0, 0);
+ S7(1, 0, 0);
+ S8(1, 0, 3);
+ for (int c0 = 2; c0 <= 9; c0 += 1) {
+ S2(c0, -7, 0);
+ for (int c1 = -7; c1 < c0 - 8; c1 += 1)
+ S3(c0, c1, 1);
+ S6(c0, c0 - 9, 2);
+ S8(c0, 0, 3);
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ S5(c0, c1, 3);
+ }
+ S2(10, -7, 0);
+ for (int c1 = -7; c1 <= 1; c1 += 1)
+ S3(10, c1, 1);
+ S6(10, 1, 2);
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ S5(10, c1, 3);
+ S1(10, c1, 4);
+ }
+ S1(10, 10, 4);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in b/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in
new file mode 100644
index 00000000000..77d32ad73f9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/durbin_e_s.in
@@ -0,0 +1,3 @@
+{ S5[i0, i1, 3] -> [i0, i1, 3, 4] : i1 <= -1 + i0 and i0 <= 10 and i1 >= 1; S8[i0, 0, 3] -> [i0, 0, 3, 7] : i0 >= 1 and i0 <= 9; S2[i0, -7, 0] -> [i0, -7, 0, 1] : i0 >= 2 and i0 <= 10; S3[i0, i1, 1] -> [i0, i1, 1, 2] : i1 >= -7 and i0 <= 10 and i1 <= -9 + i0; S1[10, i1, 4] -> [10, i1, 4, 0] : i1 >= 1 and i1 <= 10; S7[1, 0, 0] -> [1, 0, 0, 6]; S4[1, 0, 0] -> [1, 0, 0, 3]; S6[i0, -9 + i0, 2] -> [i0, -9 + i0, 2, 5] : i0 >= 2 and i0 <= 10 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.c b/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.c
new file mode 100644
index 00000000000..80ee37d5921
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+ S1(c0);
+ for (int c1 = 1; c1 <= m; c1 += 1)
+ S2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.in b/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.in
new file mode 100644
index 00000000000..57016623a25
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/emploi.in
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0, 0] : (i0 >= 1 and i0 <= n and i0 <= 2m) or (i0 >= 1 and i0 <= n and i0 >= m); S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= m }
+[m, n] -> { : }
+[m, n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/equality.c b/polly/lib/External/isl/test_inputs/codegen/cloog/equality.c
new file mode 100644
index 00000000000..2535b8b975e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/equality.c
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 <= 5; c0 += 1)
+ for (int c1 = c0 <= 2 ? 2 * c0 : 4; c1 <= (c0 >= 2 ? 2 * c0 : 4); c1 += 1) {
+ if (c1 == 2 * c0)
+ S1(c0, 2 * c0);
+ if (c1 == 4)
+ S2(c0, 4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/equality.in b/polly/lib/External/isl/test_inputs/codegen/cloog/equality.in
new file mode 100644
index 00000000000..677fa901324
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/equality.in
@@ -0,0 +1,3 @@
+{ S1[i0, 2i0] -> [i0, 2i0, 0] : i0 >= 0 and i0 <= 5; S2[i0, 4] -> [i0, 4, 1] : i0 >= 0 and i0 <= 5 }
+{ : }
+{ [i, j, k] -> atomic[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.c
new file mode 100644
index 00000000000..be22da28be4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.c
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= 10000; c0 += 1)
+ for (int c1 = 1000; c1 <= 1016; c1 += 1)
+ for (int c2 = 1; c2 < 2 * c1 - 1998; c2 += 1) {
+ if (c1 <= 1008 && c2 + 1999 == 2 * c1)
+ S2(c0, c1, 2 * c1 - 1999, 1, c0, 2 * c1 - 1000, 1, 2, c0, c1 - 499, 2 * c1 - 1999, c0, 2 * c1 - 1999, c1 - 999, c1 - 999);
+ if (c2 == 1 && c1 % 2 == 0)
+ S1(c0, c1, 1, 2, c0, (c1 / 2) + 1, c1 - 999, c0, c1 - 999, (c1 / 2) - 499, (c1 / 2) - 499);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.in
new file mode 100644
index 00000000000..95b3f793407
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/equality2.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, 1, 2, i0, i5, -999 + i1, i0, -999 + i1, i9, i10] -> [i0, i1, 1, 2, i0, n, -999 + i1, i0, -999 + i1, r, s, 0, 0, 0, 0, 0] : 2s = -998 + i1 and 2n = 2 + i1 and 2i10 = -998 + i1 and 2i5 = 2 + i1 and 2i9 = -998 + i1 and 2r = -998 + i1 and i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1016; S2[i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1] -> [i0, i1, -1999 + 2i1, 1, i0, -1000 + 2i1, 1, 2, i0, -499 + i1, -1999 + 2i1, i0, -1999 + 2i1, -999 + i1, -999 + i1, 1] : i0 >= 1 and i0 <= 10000 and i1 >= 1000 and i1 <= 1008 }
+{ : }
+{ [i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x] -> atomic[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/esced.c b/polly/lib/External/isl/test_inputs/codegen/cloog/esced.c
new file mode 100644
index 00000000000..f7c7ee0678c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/esced.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= m; c0 += 1) {
+ S1(c0);
+ for (int c1 = 1; c1 <= n; c1 += 1)
+ S2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/esced.in b/polly/lib/External/isl/test_inputs/codegen/cloog/esced.in
new file mode 100644
index 00000000000..3bef6fd90f0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/esced.in
@@ -0,0 +1,3 @@
+[n, m] -> { S1[i0] -> [i0, 0, 0] : i0 >= 1 and i0 <= m; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= m and i1 >= 1 and i1 <= n }
+[n, m] -> { : }
+[n, m] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.c
new file mode 100644
index 00000000000..2627f23ddde
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.c
@@ -0,0 +1,15 @@
+{
+ for (int c0 = 0; c0 <= 14; c0 += 1)
+ for (int c1 = 0; c1 < n - 14; c1 += 1)
+ S1(c0, c1);
+ for (int c0 = 15; c0 <= n; c0 += 1) {
+ for (int c1 = 0; c1 <= 9; c1 += 1)
+ S1(c0, c1);
+ for (int c1 = 10; c1 < n - 14; c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = n - 14; c1 <= n; c1 += 1)
+ S2(c0, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.in
new file mode 100644
index 00000000000..457b834afe2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/ex1.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 15 and i0 <= n and i1 >= 10 and i1 <= n; S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= -15 + n }
+[n] -> { : n >= 25 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/faber.c b/polly/lib/External/isl/test_inputs/codegen/cloog/faber.c
new file mode 100644
index 00000000000..b398206b260
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/faber.c
@@ -0,0 +1,155 @@
+{
+ for (int c0 = 0; c0 <= 36; c0 += 1) {
+ for (int c1 = -6; c1 < c0 / 14 - 5; c1 += 1) {
+ for (int c2 = -((-2 * c1 + 3) / 5) + 9; c2 <= c1 + 12; c2 += 1)
+ S6(c0, c1, c2);
+ for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
+ S2(c0, c1, c2);
+ for (int c2 = -2 * c1 + 30; c2 <= c1 + 48; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ for (int c1 = c0 / 14 - 5; c1 < 0; c1 += 1) {
+ if (c1 >= -3 && 2 * c0 >= 7 * c1 + 42)
+ S7(c0, c1, 6);
+ for (int c2 = max(c1 - (6 * c0 + 77) / 77 + 13, -((-2 * c1 + 3) / 5) + 9); c2 <= c1 + 12; c2 += 1)
+ S6(c0, c1, c2);
+ for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 + 48; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ S3(c0, 0, 0);
+ S10(c0, 0, 0);
+ for (int c2 = 1; c2 <= 5; c2 += 1)
+ S3(c0, 0, c2);
+ for (int c2 = 6; c2 <= 2 * c0 / 21 + 4; c2 += 1) {
+ S3(c0, 0, c2);
+ S7(c0, 0, c2);
+ }
+ for (int c2 = max(6, 2 * c0 / 21 + 5); c2 <= -((6 * c0 + 77) / 77) + 12; c2 += 1)
+ S3(c0, 0, c2);
+ for (int c2 = -((6 * c0 + 77) / 77) + 13; c2 <= 12; c2 += 1) {
+ S3(c0, 0, c2);
+ S6(c0, 0, c2);
+ }
+ for (int c2 = 13; c2 <= 24; c2 += 1)
+ S3(c0, 0, c2);
+ for (int c2 = -((3 * c0 + 14) / 14) + 49; c2 <= 48; c2 += 1)
+ S1(c0, 0, c2);
+ for (int c1 = 1; c1 <= 18; c1 += 1) {
+ for (int c2 = -8 * c1; c2 <= min(6, -8 * c1 + 24); c2 += 1)
+ S3(c0, c1, c2);
+ if (c1 == 2) {
+ S3(c0, 2, 7);
+ } else if (c0 >= 35 && c1 == 1) {
+ S3(c0, 1, 7);
+ S7(c0, 1, 7);
+ } else if (c0 <= 34 && c1 == 1)
+ S3(c0, 1, 7);
+ for (int c2 = 8; c2 <= min(-8 * c1 + 24, c1 - (6 * c0 + 77) / 77 + 12); c2 += 1)
+ S3(c0, c1, c2);
+ for (int c2 = max(-8 * c1 + 25, c1 - (6 * c0 + 77) / 77 + 13); c2 <= c1 + 12; c2 += 1)
+ S6(c0, c1, c2);
+ if (c1 == 1) {
+ for (int c2 = -((6 * c0 + 77) / 77) + 14; c2 <= 13; c2 += 1) {
+ S3(c0, 1, c2);
+ S6(c0, 1, c2);
+ }
+ for (int c2 = 14; c2 <= 16; c2 += 1)
+ S3(c0, 1, c2);
+ }
+ for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 + 48; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ for (int c1 = 19; c1 <= 24; c1 += 1) {
+ for (int c2 = -8 * c1; c2 <= -8 * c1 + 24; c2 += 1)
+ S3(c0, c1, c2);
+ for (int c2 = c1 - (6 * c0 + 77) / 77 + 13; c2 <= 30; c2 += 1)
+ S6(c0, c1, c2);
+ }
+ }
+ for (int c0 = 37; c0 <= 218; c0 += 1) {
+ for (int c1 = (c0 + 5) / 14 - 8; c1 < min(0, c0 / 14 - 5); c1 += 1) {
+ if (c0 <= 46 && c1 == -3)
+ S7(c0, -3, 6);
+ if (-77 * ((-3 * c1 + 1) / 5) + 447 >= 6 * c0)
+ S6(c0, c1, -((-2 * c1 + 3) / 5) + 9);
+ for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
+ S2(c0, c1, c2);
+ for (int c2 = -2 * c1 + 30; c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ if (c0 <= 148)
+ for (int c1 = max(0, (c0 + 5) / 14 - 8); c1 < c0 / 14 - 5; c1 += 1) {
+ if (c1 == 0)
+ S2(c0, 0, 24);
+ 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)
+ 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) {
+ 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)
+ S6(c0, c1, c2);
+ for (int c2 = c1 - (3 * c0 + 14) / 14 + 49; c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+ 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(-2 * c1 + 24, (2 * c0 - 7 * c1 - 10) / 21 + 1); c2 += 1)
+ S9(c0, c1, c2);
+ if (c1 >= 1 && c1 <= 6 && 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)
+ 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 = max(max(c1 + 6, c1 - (6 * c0 + 91) / 77 + 16), (2 * c0 - 7 * c1 - 10) / 21 + 2); 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);
+ for (int c2 = max(c1 + 24, c1 - (3 * c0 + 14) / 14 + 49); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ for (int c1 = c0 / 14 - 2; c1 <= 18; c1 += 1) {
+ for (int c2 = c1 + 6; c2 <= min((2 * c1 + 1) / 5 + 7, floord(2 * c0 - 7 * c1, 21) + 4); c2 += 1)
+ S7(c0, c1, c2);
+ for (int c2 = max(6, (c0 + 5) / 14 + 1); c2 <= min(min(c1, c0 / 14 + 3), -c1 + c1 / 2 + 18); c2 += 1)
+ S5(c0, c1, c2);
+ for (int c2 = max(max(c1 + 6, c1 - (6 * c0 + 77) / 77 + 13), (2 * c1 + 1) / 5 + 9); c2 <= c1 - (6 * c0 + 91) / 77 + 15; c2 += 1)
+ S6(c0, c1, c2);
+ for (int c2 = max(c1 + (3 * c0 + 3) / 14 - 40, -c1 + (c1 + 1) / 2 + 21); c2 <= min(c1, c1 + 3 * c0 / 14 - 33); c2 += 1)
+ S4(c0, c1, c2);
+ for (int c2 = max(c1, c1 - (3 * c0 + 14) / 14 + 40); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
+ S8(c0, c1, c2);
+ for (int c2 = max(c1 + 24, c1 - (3 * c0 + 14) / 14 + 49); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
+ S1(c0, c1, c2);
+ }
+ for (int c1 = 19; c1 <= 24; c1 += 1) {
+ for (int c2 = max(c1 - 12, (c0 + 5) / 14 + 1); c2 <= min(c0 / 14 + 3, -c1 + c1 / 2 + 18); c2 += 1)
+ S5(c0, c1, c2);
+ for (int c2 = max(max(c1 - 12, c1 + (3 * c0 + 3) / 14 - 40), -c1 + (c1 + 1) / 2 + 21); c2 <= min(c1, c1 + 3 * c0 / 14 - 33); c2 += 1)
+ S4(c0, c1, c2);
+ for (int c2 = max(c1 + 6, c1 - (6 * c0 + 77) / 77 + 13); c2 <= min(30, c1 - (6 * c0 + 91) / 77 + 15); c2 += 1)
+ S6(c0, c1, c2);
+ for (int c2 = max(c1, c1 - (3 * c0 + 14) / 14 + 40); c2 <= min(c1 + 24, c1 - (3 * c0 + 17) / 14 + 47); c2 += 1)
+ S8(c0, c1, c2);
+ }
+ for (int c1 = 25; c1 <= min(42, -((3 * c0 + 17) / 14) + 71); c1 += 1)
+ for (int c2 = max(c1 - 12, c1 + (3 * c0 + 3) / 14 - 40); c2 <= min(min(30, c1), c1 + 3 * c0 / 14 - 33); c2 += 1)
+ S4(c0, c1, c2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/faber.in b/polly/lib/External/isl/test_inputs/codegen/cloog/faber.in
new file mode 100644
index 00000000000..4f78a5561d0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/faber.in
@@ -0,0 +1,3 @@
+{ S5[idx4, idx5, idx6] -> [idx4, idx5, idx6, 4] : 14idx6 <= 42 + idx4 and 14idx6 >= 6 + idx4 and idx6 <= idx5 and idx6 >= -12 + idx5 and idx6 >= 6 and idx6 <= 30 and 2idx6 <= 36 - idx5; S8[idx4, idx5, idx6] -> [idx4, idx5, idx6, 7] : 14idx6 >= 546 - 3idx4 + 14idx5 and 14idx6 <= 654 - 3idx4 + 14idx5 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 >= 30 - 2idx5; S2[idx4, idx5, idx6] -> [idx4, idx5, idx6, 1] : 14idx5 <= -84 + idx4 and 14idx5 >= -120 + idx4 and idx6 >= 24 + idx5 and idx6 <= 48 + idx5 and idx5 >= -6 and idx5 <= 18 and idx6 <= 24 - 2idx5; S10[idx4, idx5, idx6] -> [idx4, idx5, idx6, 9] : 7idx6 <= idx4 - 28idx5 and 7idx6 >= -36 + idx4 - 28idx5 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 <= -2idx5; S3[idx4, idx5, idx6] -> [idx4, idx5, idx6, 2] : idx4 >= 0 and idx4 <= 36 and idx6 >= -8idx5 and idx6 <= 24 - 8idx5 and idx5 >= 0 and idx5 <= 24; S1[idx4, idx5, idx6] -> [idx4, idx5, idx6, 0] : 14idx6 >= 672 - 3idx4 + 14idx5 and 14idx6 <= 780 - 3idx4 + 14idx5 and idx6 >= 24 + idx5 and idx6 <= 48 + idx5 and idx5 >= -6 and idx5 <= 18 and idx6 >= 30 - 2idx5; S7[idx4, idx5, idx6] -> [idx4, idx5, idx6, 6] : 21idx6 <= 84 + 2idx4 - 7idx5 and 21idx6 >= 12 + 2idx4 - 7idx5 and idx6 <= 12 + idx5 and idx6 >= 6 + idx5 and idx6 >= 6 and idx6 <= 30 and 5idx6 <= 36 + 2idx5; S9[idx4, idx5, idx6] -> [idx4, idx5, idx6, 8] : 14idx5 <= -42 + idx4 and 14idx5 >= -78 + idx4 and idx6 >= idx5 and idx6 <= 24 + idx5 and idx5 >= 0 and idx5 <= 24 and idx6 <= 24 - 2idx5 and idx6 >= 6 - 2idx5; S4[idx4, idx5, idx6] -> [idx4, idx5, idx6, 3] : 14idx6 <= -462 + 3idx4 + 14idx5 and 14idx6 >= -570 + 3idx4 + 14idx5 and idx6 <= idx5 and idx6 >= -12 + idx5 and idx6 >= 6 and idx6 <= 30 and 2idx6 >= 42 - idx5; S6[idx4, idx5, idx6] -> [idx4, idx5, idx6, 5] : 77idx6 >= 924 - 6idx4 + 77idx5 and 77idx6 <= 1140 - 6idx4 + 77idx5 and idx6 <= 12 + idx5 and idx6 >= 6 + idx5 and idx6 >= 6 and idx6 <= 30 and 5idx6 >= 42 + 2idx5 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c
new file mode 100644
index 00000000000..45fe75ef372
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.c
@@ -0,0 +1,9 @@
+{
+ S3(1, 1);
+ for (int c0 = 2; c0 <= M; c0 += 1) {
+ S1(c0, 1);
+ for (int c1 = 2; c1 < c0; c1 += 1)
+ S2(c0, c1);
+ S4(c0, c0);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in
new file mode 100644
index 00000000000..ede8856d545
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-1-1-2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i1 <= -1 + i0 and i1 >= 2 and i0 <= M; S4[i0, i0] -> [i0, i0, 3] : M >= 3 and i0 <= M and i0 >= 2; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= M and i0 >= 2; S3[1, 1] -> [1, 1, 2] : M >= 3 }
+[M] -> { : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c
new file mode 100644
index 00000000000..cfc3e7d7bea
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.c
@@ -0,0 +1,10 @@
+{
+ S3(1, 0);
+ for (int c2 = 2; c2 <= M; c2 += 1)
+ S1(1, 1, c2);
+ for (int c0 = 2; c0 <= M; c0 += 1) {
+ S4(c0, 0);
+ for (int c2 = c0 + 1; c2 <= M; c2 += 1)
+ S2(c0, 1, c2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in
new file mode 100644
index 00000000000..57863cc5727
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-2-1-2-3.in
@@ -0,0 +1,3 @@
+[M] -> { S1[1, 1, i2] -> [1, 1, i2, 0] : M >= 3 and i2 <= M and i2 >= 2; S2[i0, 1, i2] -> [i0, 1, i2, 1] : i2 >= 1 + i0 and i0 >= 2 and i2 <= M; S4[i0, 0] -> [i0, 0, 0, 3] : i0 >= 2 and M >= 3 and i0 <= M; S3[1, 0] -> [1, 0, 0, 2] : M >= 3 }
+[M] -> { : M >= 3 }
+[M] -> { [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c
new file mode 100644
index 00000000000..9300d189691
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.c
@@ -0,0 +1,17 @@
+{
+ S3(2, 1);
+ S1(3, 1);
+ for (int c0 = 4; c0 <= M + 1; c0 += 1) {
+ S1(c0, 1);
+ for (int c1 = 2; c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0, c1);
+ if (c0 % 2 == 0)
+ S4(c0, c0 / 2);
+ }
+ for (int c0 = M + 2; c0 <= 2 * M; c0 += 1) {
+ for (int c1 = -M + c0; c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0, c1);
+ if (c0 % 2 == 0)
+ S4(c0, c0 / 2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in
new file mode 100644
index 00000000000..c40383d8b6e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/forwardsub-3-1-2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : 2i1 <= -1 + i0 and i1 >= 2 and i1 >= -M + i0; S4[i0, i1] -> [i0, j, 3] : 2j = i0 and 2i1 = i0 and M >= 3 and i0 <= 2M and i0 >= 4; S1[i0, 1] -> [i0, 1, 0] : M >= 3 and i0 <= 1 + M and i0 >= 3; S3[2, 1] -> [2, 1, 2] : M >= 3 }
+[M] -> { : M >= 3 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.c b/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.c
new file mode 100644
index 00000000000..13a8e137173
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 < M; c0 += 1)
+ for (int c1 = c0 + 1; c1 <= M; c1 += 1) {
+ for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+ S2(c0, c3, c1);
+ for (int c3 = 1; c3 < c0; c3 += 1)
+ S1(c0, c3, c1);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.in b/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.in
new file mode 100644
index 00000000000..439e72e7f34
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gauss.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1, i2] -> [i0, i2] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 + i0 and i2 <= M }
+[M] -> { : }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.c b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.c
new file mode 100644
index 00000000000..a36715ca3db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.c
@@ -0,0 +1,16 @@
+{
+ for (int c0 = 1; c0 <= N; c0 += 1)
+ S1(c0);
+ for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+ for (int c1 = 1; c1 <= N; c1 += 1)
+ S2(c1, -N + c0);
+ for (int c0 = 2 * N + 1; c0 <= M + N; c0 += 1) {
+ for (int c1 = 1; c1 <= N; c1 += 1)
+ S3(c1, -2 * N + c0);
+ for (int c1 = 1; c1 <= N; c1 += 1)
+ S2(c1, -N + c0);
+ }
+ for (int c0 = M + N + 1; c0 <= M + 2 * N; c0 += 1)
+ for (int c1 = 1; c1 <= N; c1 += 1)
+ S3(c1, -2 * N + c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.in b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.in
new file mode 100644
index 00000000000..6043f4b3fb9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced.in
@@ -0,0 +1,3 @@
+[M, N] -> { S3[i0, i1] -> [2N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S2[i0, i1] -> [N + i1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0] : i0 >= 1 and i0 <= N }
+[M, N] -> { : N <= M and M >= 2 and N >= 2 }
+[M, N] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.c
new file mode 100644
index 00000000000..0baf706ed99
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.c
@@ -0,0 +1,20 @@
+{
+ for (int c0 = 1; c0 <= 4; c0 += 1)
+ for (int c1 = 5; c1 < M - 9; c1 += 1)
+ S1(c0, c1);
+ for (int c0 = 5; c0 < M - 9; c0 += 1) {
+ for (int c1 = -c0 + 1; c1 <= 4; c1 += 1)
+ S2(c0 + c1, c0);
+ for (int c1 = 5; c1 <= min(M - 10, M - c0); c1 += 1) {
+ S1(c0, c1);
+ S2(c0 + c1, c0);
+ }
+ for (int c1 = M - c0 + 1; c1 < M - 9; c1 += 1)
+ S1(c0, c1);
+ for (int c1 = M - 9; c1 <= M - c0; c1 += 1)
+ S2(c0 + c1, c0);
+ }
+ for (int c0 = M - 9; c0 <= M; c0 += 1)
+ for (int c1 = 5; c1 < M - 9; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.in
new file mode 100644
index 00000000000..a5d5bd27e28
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced2.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M; S2[i0, i1] -> [i1, i0 - i1] : i0 >= 1 and i0 <= M and i1 >= 5 and i1 <= -10 + M }
+[M] -> { : M >= 16 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.c
new file mode 100644
index 00000000000..c163ed0735e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.c
@@ -0,0 +1,10 @@
+{
+ for (int c0 = M + 1; c0 <= 2 * M; c0 += 1)
+ S1(-M + c0);
+ for (int c0 = 2 * M + 1; c0 <= M + N; c0 += 1) {
+ S2(-2 * M + c0);
+ S1(-M + c0);
+ }
+ for (int c0 = M + N + 1; c0 <= 2 * M + N; c0 += 1)
+ S2(-2 * M + c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.in
new file mode 100644
index 00000000000..29f57f32176
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/gesced3.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0] -> [2M + i0] : i0 >= 1 and i0 <= N; S1[i0] -> [M + i0] : i0 >= 1 and i0 <= N }
+[M, N] -> { : N >= M and M >= 2 }
+[M, N] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/guide.c b/polly/lib/External/isl/test_inputs/codegen/cloog/guide.c
new file mode 100644
index 00000000000..bc48f1efe8a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/guide.c
@@ -0,0 +1,6 @@
+{
+ for (int c0 = 1; c0 <= N; c0 += 1)
+ S1(c0);
+ for (int c0 = N + 1; c0 <= 2 * N; c0 += 1)
+ S2(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/guide.in b/polly/lib/External/isl/test_inputs/codegen/cloog/guide.in
new file mode 100644
index 00000000000..38c418c6c65
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/guide.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= N and i0 <= 2M) or (i0 >= 1 and i0 <= N and i0 >= M); S2[i0] -> [i0, 1] : i0 >= 1 + N and i0 <= 2N }
+[M, N] -> { : }
+[M, N] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.c b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.c
new file mode 100644
index 00000000000..0f41fb7902a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.c
@@ -0,0 +1,2 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.in b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.in
new file mode 100644
index 00000000000..741399d48a0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest.in
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [i0, 0] : (i0 >= 1 and i0 <= n and i0 >= m) or (i0 >= 1 and i0 <= n and i0 <= 2m) }
+[m, n] -> { : }
+[m, n] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.c
new file mode 100644
index 00000000000..8e3e4c1b90b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.in
new file mode 100644
index 00000000000..a2e3212ece3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/iftest2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : (i0 >= 1 and i0 <= N and i0 >= M and i1 >= 1 and i1 <= M) or (i0 >= 1 and i0 <= N and i0 <= 2M and i1 >= 1 and i1 <= M) }
+[M, N] -> { : }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.c
new file mode 100644
index 00000000000..bbb6d6e750a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.c
@@ -0,0 +1,9 @@
+{
+ for (int c0 = 1; c0 <= N; c0 += 1) {
+ S1(c0);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c0, c1);
+ }
+ for (int c0 = N + 1; 1; c0 += 1)
+ S1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.in
new file mode 100644
index 00000000000..64fb5d55735
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/infinite2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0] -> [i0, 0, 0] : i0 >= 1 }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c b/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c
new file mode 100644
index 00000000000..50840a86877
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.c
@@ -0,0 +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);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in b/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in
new file mode 100644
index 00000000000..d6153244284
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/jacobi-shared.in
@@ -0,0 +1,3 @@
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[i0, i1] -> [1 - g1 + i0, 1 - g2 + i1, t0, t1] : exists (e0 = [(-1 + h0)/2], e1 = [(-2016b0 - g1)/2048], e2 = [(-992b1 - g2)/1024], e3 = [(-1 + t0 - i0)/16], e4 = [(-1 + t1 - i1)/32]: g0 = h0 and 2e0 = -1 + h0 and 2048e1 = -2016b0 - g1 and 1024e2 = -992b1 - g2 and 16e3 = -1 + t0 - i0 and 32e4 = -1 + t1 - i1 and h0 >= 1 and h0 <= -1 + 2T and i0 >= 2 and i0 <= -2 + N and i1 >= 2 and i1 <= -2 + N and b1 <= 31 and b1 >= 0 and b0 <= 63 and b0 >= 0 and i1 <= 31 + g2 and i1 >= g2 and N >= 4 and i0 >= g1 and i0 <= 31 + g1 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and g1 >= 32b0 and g2 >= 32b1 and 32b0 <= -2 + N and 32b1 <= -2 + N and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { : exists (e0 = [(-32b0 + g1)/2048], e1 = [(-32b1 + g2)/1024]: g0 = h0 and 2048e0 = -32b0 + g1 and 1024e1 = -32b1 + g2 and g2 <= -2 + N and g2 >= -29 and g1 <= -2 + N and g1 >= -29 and b1 >= 0 and b1 <= 31 and b0 <= 63 and 32b1 <= -2 + N and 32b0 <= -2 + N and b0 >= 0 and N >= 4 and h0 >= 0 and h0 <= -1 + 2T and g2 >= 32b1 and g1 >= 32b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 31) }
+[T, N, h0, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[x] : x >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.c b/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.c
new file mode 100644
index 00000000000..faced0a5573
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= M; c0 += 1)
+ for (int c1 = 1; c1 <= c0; c1 += 1)
+ S1(c1, c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.in b/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.in
new file mode 100644
index 00000000000..3a25146b10f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/largeur.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i1, i0] : i0 >= 1 and i0 <= M and i1 >= i0 and i1 <= M }
+[M] -> { : M >= 0 }
+[M] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c
new file mode 100644
index 00000000000..0e470b4d73b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.c
@@ -0,0 +1,32 @@
+{
+ S1(0, 0);
+ for (int c0 = 1; c0 <= N; c0 += 1) {
+ S2(c0, 0);
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ S6(c0, c1);
+ S3(c0, c0);
+ }
+ S7(N + 1, 0);
+ for (int c1 = 1; c1 <= N; c1 += 1) {
+ S6(N + 1, c1);
+ S8(N + 1, c1);
+ }
+ for (int c0 = N + 2; c0 < 2 * M - N - 1; c0 += 1) {
+ S7(c0, -N + (N + c0 + 1) / 2 - 1);
+ if ((N - c0) % 2 == 0) {
+ S5(c0, (-N + c0) / 2);
+ S8(c0, (-N + c0) / 2);
+ }
+ for (int c1 = -N + (N + c0) / 2 + 1; c1 < (N + c0 + 1) / 2; c1 += 1) {
+ S6(c0, c1);
+ S8(c0, c1);
+ }
+ if ((N - c0) % 2 == 0) {
+ S4(c0, (N + c0) / 2);
+ S8(c0, (N + c0) / 2);
+ }
+ }
+ for (int c0 = 2 * M - N - 1; c0 < 2 * M - 1; c0 += 1)
+ for (int c1 = -M + c0 + 1; c1 < M; c1 += 1)
+ S6(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in
new file mode 100644
index 00000000000..dc9446410e6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/levenshtein-1-2-3.in
@@ -0,0 +1,3 @@
+[M, N] -> { S8[i0, i1] -> [i0, i1, 7] : i0 >= 1 + N and 2i1 <= N + i0 and 2i1 >= -N + i0 and i0 <= -2 + 2M - N and N <= -2 + M and N >= 1; S1[0, 0] -> [0, 0, 0] : N <= -2 + M and N >= 1; S5[i0, i1] -> [i0, j, 4] : 2j = -N + i0 and 2i1 = -N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S7[i0, i1] -> [i0, i1, 6] : i0 >= 1 + N and 2i1 <= -1 - N + i0 and i0 <= -2 + 2M - N and 2i1 >= -2 - N + i0 and N <= -2 + M and N >= 1; S2[i0, 0] -> [i0, 0, 1] : i0 >= 1 and i0 <= N and N <= -2 + M; S3[i0, i0] -> [i0, i0, 2] : i0 >= 1 and i0 <= N and N <= -2 + M; S4[i0, i1] -> [i0, j, 3] : 2j = N + i0 and 2i1 = N + i0 and i0 >= 2 + N and i0 <= -2 + 2M - N and N >= 1; S6[i0, i1] -> [i0, i1, 5] : 2i1 <= -1 + N + i0 and i1 <= -1 + i0 and i1 >= 1 - M + i0 and 2i1 >= 1 - N + i0 and i1 >= 1 and i1 <= -1 + M and N <= -2 + M }
+[M, N] -> { : N <= -2 + M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lex.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lex.c
new file mode 100644
index 00000000000..e81e97e75a9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lex.c
@@ -0,0 +1,4 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+ S2(c0);
+ S1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lex.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lex.in
new file mode 100644
index 00000000000..7a268b605f0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lex.in
@@ -0,0 +1,3 @@
+{ S2[i0] -> [i0, -1, 0] : i0 >= 0 and i0 <= 10; S1[i0] -> [i0, 0, 0] : i0 >= 0 and i0 <= 10 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c
new file mode 100644
index 00000000000..bb1e0718719
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.c
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ S1(c0, c1);
+ S1(c0, c0);
+ S2(c0, c0);
+ for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in
new file mode 100644
index 00000000000..b7d06d05953
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-1-2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i0] -> [i0, i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> { : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c
new file mode 100644
index 00000000000..23f50d24818
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.c
@@ -0,0 +1,12 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+ for (int c1 = 1; c1 <= min(M, c0 + 1); c1 += 1)
+ S1(c0, c1);
+ if (c0 + 1 >= M) {
+ S2(c0, c0 + 2);
+ } else {
+ S1(c0, c0 + 2);
+ S2(c0, c0 + 2);
+ }
+ for (int c1 = c0 + 3; c1 <= M; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in
new file mode 100644
index 00000000000..6ed9040ab03
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lineality-2-1-2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, 2 + i0] -> [i0, 2 + i0, 1] : i0 >= 1 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 1 and i0 <= M and i1 <= M }
+[M] -> { : M >= 2 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/logo.c b/polly/lib/External/isl/test_inputs/codegen/cloog/logo.c
new file mode 100644
index 00000000000..abe35b5916f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/logo.c
@@ -0,0 +1,17 @@
+{
+ for (int c1 = 0; c1 <= 7; c1 += 1)
+ S1(1, c1);
+ for (int c0 = 2; c0 <= 6; c0 += 1) {
+ for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+ S2(c0, c1);
+ for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = 5; c1 <= 7; c1 += 1)
+ S1(c0, c1);
+ }
+ for (int c0 = 7; c0 <= 8; c0 += 1)
+ for (int c1 = c0 - 1; c1 <= 7; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/logo.in b/polly/lib/External/isl/test_inputs/codegen/cloog/logo.in
new file mode 100644
index 00000000000..33e2d88b540
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/logo.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= 6 and i1 >= 0 and i1 <= 4; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= 7 and i1 >= -1 + i0 }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.c b/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.c
new file mode 100644
index 00000000000..70f98e8cd89
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.c
@@ -0,0 +1,17 @@
+{
+ for (int c1 = 0; c1 <= m; c1 += 1)
+ S1(1, c1);
+ for (int c0 = 2; c0 <= n; c0 += 1) {
+ for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+ S2(c0, c1);
+ for (int c1 = c0 - 1; c1 <= n; c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = n + 1; c1 <= m; c1 += 1)
+ S1(c0, c1);
+ }
+ for (int c0 = n + 1; c0 <= m + 1; c0 += 1)
+ for (int c1 = c0 - 1; c1 <= m; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.in b/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.in
new file mode 100644
index 00000000000..48b70fde5b5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/logopar.in
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 <= m and i1 >= -1 + i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 2 and i0 <= n and i1 >= 0 and i1 <= n }
+[m, n] -> { : n <= m and m >= 0 and n >= 2 }
+[m, n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lu.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lu.c
new file mode 100644
index 00000000000..a7fe2b36eed
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lu.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+ for (int c1 = 2; c1 <= n; c1 += 1)
+ for (int c2 = 1; c2 < min(c0, c1); c2 += 1)
+ S2(c2, c1, c0);
+ for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+ S1(c0, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lu.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lu.in
new file mode 100644
index 00000000000..49952ccc46e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lu.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [i2, i1] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 + i0 and i2 <= n; S1[i0, i1] -> [i0, n] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n }
+[n] -> { : }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.c
new file mode 100644
index 00000000000..d5cc912359c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1) {
+ for (int c1 = 2; c1 <= n; c1 += 1)
+ for (int c2 = 1; c2 < min(c0, c1); c2 += 1)
+ S2(c0, c1, c2, c1, c0);
+ for (int c3 = c0 + 1; c3 <= n; c3 += 1)
+ S1(c0, n, c0, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.in
new file mode 100644
index 00000000000..5c71fc0aacc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lu2.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, n, i0, i3] -> [i0, n, i0, i3, 0, 0] : i0 >= 1 and i0 <= n and i3 >= 1 + i0 and i3 <= n; S2[i0, i1, i2, i1, i0] -> [i0, i1, i2, i1, i0, 1] : i2 >= 1 and i2 <= n and i2 <= -1 + i1 and i1 <= n and i2 <= -1 + i0 and i0 <= n }
+[n] -> { : }
+[n] -> { [i, j, k, l, m, n'] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lux.c b/polly/lib/External/isl/test_inputs/codegen/cloog/lux.c
new file mode 100644
index 00000000000..3b33025e227
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lux.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ for (int c2 = c1 + 1; c2 <= M; c2 += 1)
+ S2(c0, c1, c2, c2, c0);
+ for (int c3 = c0 + 1; c3 <= M; c3 += 1)
+ S1(c0, c0, M, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/lux.in b/polly/lib/External/isl/test_inputs/codegen/cloog/lux.in
new file mode 100644
index 00000000000..75ed7e24000
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/lux.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i0, M, i3] -> [i0, i0, M, i3, 0, 0] : i0 >= 1 and i0 <= M and i3 >= 1 + i0 and i3 <= M; S2[i0, i1, i2, i2, i0] -> [i0, i1, i2, i2, i0, 1] : i1 >= 1 and i1 <= M and i2 >= 1 + i1 and i2 <= M and i1 <= -1 + i0 and i0 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/merge.c b/polly/lib/External/isl/test_inputs/codegen/cloog/merge.c
new file mode 100644
index 00000000000..64564ad9987
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/merge.c
@@ -0,0 +1,8 @@
+{
+ S1(0);
+ for (int c0 = 0; c0 <= 10; c0 += 1) {
+ if (c0 >= 2)
+ S2(c0);
+ S3(c0);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/merge.in b/polly/lib/External/isl/test_inputs/codegen/cloog/merge.in
new file mode 100644
index 00000000000..1747c44cf32
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/merge.in
@@ -0,0 +1,3 @@
+{ S3[i0] -> [i0, 2] : i0 >= 0 and i0 <= 10; S2[i0] -> [i0, 1] : i0 >= 2 and i0 <= 10; S1[0] -> [0, 0] }
+{ : }
+{ [i, j] -> atomic[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c
new file mode 100644
index 00000000000..b869e1b8b40
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= min(min(M, c0), N - c0); c1 += 1)
+ S1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in
new file mode 100644
index 00000000000..76e511ff2fa
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-1-1.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 }
+[M, N] -> { : }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c
new file mode 100644
index 00000000000..8e6fabf7d28
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.c
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= N; c0 += 1)
+ for (int c1 = 0; c1 <= min(min(M, c0), N - c0); c1 += 1)
+ for (int c2 = 0; c2 <= min(min(M, c0), N - c0); c2 += 1)
+ S1(c0, c1, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in
new file mode 100644
index 00000000000..aa0bcaefd86
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-2-1.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [i0, i1, i2, 0] : i0 >= 1 and i1 >= 0 and i1 <= M and i1 <= i0 and i1 <= N - i0 and i2 >= 0 and i2 <= M and i2 <= i0 and i2 <= N - i0 }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c
new file mode 100644
index 00000000000..8d11d76d568
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= min(10, M); c0 += 1)
+ for (int c1 = 0; c1 <= min(10, M); c1 += 1)
+ S1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in
new file mode 100644
index 00000000000..1676ac9318e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-3-1.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i0 <= 10 and i1 >= 0 and i1 <= M and i1 <= 10 }
+[M] -> { : M >= 0 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c
new file mode 100644
index 00000000000..da272fc291f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.c
@@ -0,0 +1,2 @@
+for (int c0 = max(-M, -N); c0 <= min(N, O); c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in
new file mode 100644
index 00000000000..72fd01269be
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/min-4-1.in
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0] -> [i0, 0] : i0 >= -M and i0 >= -N and i0 <= N and i0 <= O }
+[M, N, O] -> { : }
+[M, N, O] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mod.c
new file mode 100644
index 00000000000..cafe0b85ddb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+ if ((c0 + 1) % 3 >= 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mod.in
new file mode 100644
index 00000000000..2759c0e506e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod.in
@@ -0,0 +1,3 @@
+{ S1[i0] -> [i0, 0] : exists (e0 = [(1 + i0)/3]: i0 >= 0 and i0 <= 3 and 3e0 <= i0 and 3e0 >= -1 + i0) }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.c
new file mode 100644
index 00000000000..cafe0b85ddb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 3; c0 += 1)
+ if ((c0 + 1) % 3 >= 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.in
new file mode 100644
index 00000000000..58134bbbfe6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod2.in
@@ -0,0 +1,3 @@
+{ S1[i] -> [i, 0] : exists (e0 = [(i)/3]: i >= 0 and i <= 3 and 3e0 <= i and 3e0 >= -1 + i) }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.c
new file mode 100644
index 00000000000..f8d879ce1ae
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.c
@@ -0,0 +1,4 @@
+for (int c0 = max(0, 32 * h0 - 1991); c0 <= min(999, 32 * h0 + 31); c0 += 1)
+ if ((32 * h0 - c0 + 32) % 64 >= 1)
+ for (int c1 = 0; c1 <= 999; c1 += 1)
+ S1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.in
new file mode 100644
index 00000000000..bd0713eeba3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod3.in
@@ -0,0 +1,3 @@
+[h0] -> { S1[i0, i1] -> [i0, i1, 0] : exists (e0 = [(32 + 32h0 - i0)/64]: i0 >= 0 and i0 <= 999 and i0 >= -2015 + 32h0 and 32e0 >= -999 + 32h0 - i0 and i1 >= 0 and i1 <= 999 and 64e0 >= -31 + 32h0 - i0 and 64e0 <= 31 + 32h0 - i0 and i0 <= 32 + 32h0) }
+[h0] -> { : h0 <= 93 and h0 >= 0 }
+[h0] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.c
new file mode 100644
index 00000000000..a5dca247b96
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.c
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= 10; c0 += 3) {
+ S1(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+ S2(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+ S3(c0, (c0 + 1) / 3, (c0 + 1) / 3, 2, (c0 - 2) / 3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.in
new file mode 100644
index 00000000000..2002cef3ed3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mod4.in
@@ -0,0 +1,3 @@
+{ S2[j, div41, div42, 2, mod6_a] -> [j, div41, k, 2, m, 1] : 3k = 1 + j and 3div42 = 1 + j and 3m = -2 + j and 3mod6_a = -2 + j and 3div41 >= 1 + j and 3div41 <= 2 + j and j >= 1 and j <= 10; S1[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 0] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j; S3[j, div41, div42, 2, mod6_a] -> [j, div41, div42, 2, m, 2] : 3m = -2 + j and 3mod6_a = -2 + j and j >= 1 and j <= 10 and 3div41 >= j and 3div42 >= -1 + j and 3div42 <= 1 + j and 3div41 <= 2 + j }
+{ : }
+{ [i, j, k, l, m, n] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mode.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mode.c
new file mode 100644
index 00000000000..bcfd31839bb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mode.c
@@ -0,0 +1,10 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+ for (int c1 = 0; c1 <= min(N, c0); c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = max(0, N + 1); c1 <= c0; c1 += 1)
+ S1(c0, c1);
+ for (int c1 = c0 + 1; c1 <= N; c1 += 1)
+ S2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mode.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mode.in
new file mode 100644
index 00000000000..914c37e642a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mode.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= i0; S2[i0, i1] -> [i0, i1, 1] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> { : }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c
new file mode 100644
index 00000000000..271d863f008
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.c
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 <= M; c0 += 1) {
+ for (int c1 = 0; c1 <= min(N, c0); c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = N + 1; c1 <= c0; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in
new file mode 100644
index 00000000000..22bdd1b4234
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-mm-1.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i1 >= 0 and i1 <= i0 and i0 <= M; S2[i0, i1] -> [i0, i1, 1] : i1 >= 0 and i1 <= i0 and i0 <= M and i1 <= N }
+[M, N] -> { : N <= M and N >= 1 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c
new file mode 100644
index 00000000000..2c63c085104
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.c
@@ -0,0 +1,2 @@
+{
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in
new file mode 100644
index 00000000000..fdef8f90c2e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 6k = -2 + i0 and 6i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c
new file mode 100644
index 00000000000..14f80506e0b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.c
@@ -0,0 +1,2 @@
+for (int c0 = 5; c0 <= 100; c0 += 6)
+ S1(c0, (c0 - 1) / 2, (c0 - 2) / 3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in
new file mode 100644
index 00000000000..d2c4bbc965e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/multi-stride2.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = -1 + i0 and 2j = -1 + i0 and 3k = -2 + i0 and 3i2 = -2 + i0 and i0 >= 0 and i0 <= 100 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c b/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c
new file mode 100644
index 00000000000..c2423f01f5c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c
@@ -0,0 +1,6 @@
+if (g4 == 0 && N >= g0 + t1 + 1 && t1 <= 7) {
+ for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
+ S1(g0 + t1, g1 + c0);
+} else if (g4 >= 4 && N >= g0 + t1 + 1 && t1 <= 7 && g4 % 4 == 0)
+ for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
+ S1(g0 + t1, g1 + c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in b/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in
new file mode 100644
index 00000000000..a525e9c0dd8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.in
@@ -0,0 +1,3 @@
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g1 >= 128b1 and t1 <= -1 + N - g0 and g0 >= 8b0 and i1 <= -1 + N and b0 <= 15 and b0 >= 0 and b1 <= 31 and b1 >= 0 and i1 <= 127 + g1 and t1 >= 0 and t1 <= 7 and i1 >= g1 and t0 >= 0 and t0 <= 15 and N >= 1)) or (exists (e0 = [(-g1)/128], e1 = [(128b1 + 31g1)/4096], e2 = [(t0 - i1)/16], e3 = [(-120b0 - g0)/128]: g4 = 0 and g2 = 8b0 and g3 = 128b1 and 128e0 = -g1 and 4096e1 = 128b1 + 31g1 and 16e2 = t0 - i1 and 128e3 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and N >= 1 and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and t0 <= 15 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0)); S1[g0 + t1, i1] -> [-g1 + i1, t1, t0, t1] : exists (e0 = [(g4)/4], e1 = [(-g1)/128], e2 = [(128b1 + 31g1)/4096], e3 = [(t0 - i1)/16], e4 = [(-120b0 - g0)/128]: g3 = 128b1 and g2 = 8b0 and 4e0 = g4 and 128e1 = -g1 and 4096e2 = 128b1 + 31g1 and 16e3 = t0 - i1 and 128e4 = -120b0 - g0 and g0 >= 8b0 and t1 <= -1 + N - g0 and g1 >= 128b1 and i1 <= -1 + N and g4 <= -1 + N and t1 <= 7 and b1 <= 31 and b1 >= 0 and b0 <= 15 and b0 >= 0 and g4 >= 0 and i1 <= 127 + g1 and i1 >= g1 and t1 >= 0 and t0 >= 0 and t0 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { : exists (e0 = [(g0)/8], e1 = [(-128b1 + g1)/4096], e2 = [(8b0 - g0)/128]: g2 = 8b0 and g3 = 128b1 and 8e0 = g0 and 4096e1 = -128b1 + g1 and 128e2 = 8b0 - g0 and b0 >= 0 and g4 <= -1 + N and b0 <= 15 and g1 <= -1 + N and g4 >= 0 and b1 <= 31 and g0 <= -1 + N and g1 >= 128b1 and b1 >= 0 and g0 >= 8b0 and t0 >= 0 and t0 <= 15 and t1 >= 0 and t1 <= 15) }
+[N, b0, b1, g0, g1, g2, g3, g4, t0, t1] -> { [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c b/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c
new file mode 100644
index 00000000000..1432b5e4e3c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.c
@@ -0,0 +1 @@
+S1(N + 2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in b/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in
new file mode 100644
index 00000000000..078992925f7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/no_lindep.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[2 + N] -> [1 + M, N] }
+[M, N] -> { : }
+[M, N] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c
new file mode 100644
index 00000000000..9293aef92c7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= M; c0 += 2)
+ S1(c0, c0 / 2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in
new file mode 100644
index 00000000000..e10488f68ef
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic1.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 0 and i0 <= M }
+[M] -> { : }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c
new file mode 100644
index 00000000000..2b7bb4d22c6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.c
@@ -0,0 +1,5 @@
+for (int c0 = 2; c0 <= n; c0 += 2) {
+ if (c0 % 4 == 0)
+ S2(c0, c0 / 4);
+ S1(c0, c0 / 2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in
new file mode 100644
index 00000000000..54f9374a5d3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_basic2.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1] -> [i0, j, 1] : 4j = i0 and 4i1 = i0 and i0 >= 1 and i0 <= n; S1[i0, i1] -> [i0, j, 0] : 2j = i0 and 2i1 = i0 and i0 >= 1 and i0 <= n }
+[n] -> { : n >= 2 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c
new file mode 100644
index 00000000000..7053351603e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 5 * n; c0 += 1)
+ for (int c1 = max(-((5 * n - c0 + 1) % 2) - n + c0 + 1, 2 * floord(c0 - 1, 3) + 2); c1 <= min(c0, n + c0 - (n + c0 + 2) / 3); c1 += 2)
+ S1((3 * c1 / 2) - c0, c0 - c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in
new file mode 100644
index 00000000000..277e62ef171
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [2i0 + 3i1, 2i0 + 2i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> { : }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c
new file mode 100644
index 00000000000..e6f39682d49
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.c
@@ -0,0 +1,13 @@
+{
+ for (int c0 = 1; c0 <= 6; c0 += 2) {
+ for (int c2 = 1; c2 <= c0; c2 += 1) {
+ S1(c0, (c0 - 1) / 2, c2);
+ S2(c0, (c0 - 1) / 2, c2);
+ }
+ for (int c2 = c0 + 1; c2 <= p; c2 += 1)
+ S1(c0, (c0 - 1) / 2, c2);
+ }
+ for (int c0 = 7; c0 <= m; c0 += 2)
+ for (int c2 = 1; c2 <= p; c2 += 1)
+ S1(c0, (c0 - 1) / 2, c2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in
new file mode 100644
index 00000000000..e3a4e99fcf3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/nul_lcpc.in
@@ -0,0 +1,3 @@
+[m, n, p] -> { S1[i, k, j] -> [i, j', j, 0] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= m and j >= 1 and j <= p; S2[i, k, j] -> [i, j', j, 1] : 2k = -1 + i and 2j' = -1 + i and i >= 1 and i <= n and j >= 1 and j <= i }
+[m, n, p] -> { : n = 6 and m >= 7 and p >= 7 }
+[m, n, p] -> { [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/orc.c b/polly/lib/External/isl/test_inputs/codegen/cloog/orc.c
new file mode 100644
index 00000000000..8ad0162832c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/orc.c
@@ -0,0 +1,16 @@
+{
+ for (int c1 = 0; c1 <= 2; c1 += 1) {
+ S1(c1);
+ for (int c2 = 0; c2 <= -c1 + 11; c2 += 1) {
+ S2(c1, c2);
+ S3(c1, c2);
+ }
+ S4(c1);
+ }
+ for (int c1 = 0; c1 <= 14; c1 += 1) {
+ S5(c1);
+ for (int c2 = 0; c2 <= 9; c2 += 1)
+ S6(c1, c2);
+ S7(c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/orc.in b/polly/lib/External/isl/test_inputs/codegen/cloog/orc.in
new file mode 100644
index 00000000000..d81bf4728e9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/orc.in
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + 3i0, 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0; S4[i0] -> [0, 2 + 3i0, 0] : i0 >= 0 and i0 <= 2; S5[i0] -> [2, 3i0, 0] : i0 >= 0 and i0 <= 14; S6[i0, i1] -> [2, 1 + 3i0, i1] : i0 >= 0 and i0 <= 14 and i1 >= 0 and i1 <= 9; S1[i0] -> [0, 3i0, 0] : i0 >= 0 and i0 <= 2; S7[i0] -> [2, 2 + 3i0, 0] : i0 >= 0 and i0 <= 14; S3[i0, i1] -> [0, 1 + 3i0, 1 + 2i1] : i0 >= 0 and i0 <= 2 and i1 >= 0 and i1 <= 11 - i0 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/otl.c b/polly/lib/External/isl/test_inputs/codegen/cloog/otl.c
new file mode 100644
index 00000000000..793733447ee
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/otl.c
@@ -0,0 +1,7 @@
+if (M >= 3 && N >= 4)
+ for (int c0 = 1; c0 < (2 * M + 2 * N - 2) / 5; c0 += 1)
+ for (int c1 = max(c0 - (M + 2) / 5, (c0 + 1) / 2); c1 <= min(min(c0, (M + 2 * N) / 5 - 1), (2 * N + 5 * c0 + 1) / 10); c1 += 1)
+ for (int c2 = max(max(max(max(0, c0 - c1 - 1), c1 - (N + 6) / 5 + 1), c0 - (M + N + 4) / 5 + 1), floord(-N + 5 * c0 - 3, 10) + 1); c2 <= min(min(min(c1, (M + N - 2) / 5), c0 - c1 + (N - 1) / 5 + 1), (N + 5 * c0 + 3) / 10); c2 += 1)
+ for (int c3 = max(max(max(c0, 2 * c1 - (2 * N + 5) / 5 + 1), c1 + c2 - (N + 3) / 5), 2 * c2 - (N + 2) / 5); c3 <= min(min(min(min(min(c0 + 1, c1 + c2 + 1), c1 + (M - 2) / 5 + 1), 2 * c2 + (N - 2) / 5 + 1), (2 * M + 2 * N - 1) / 5 - 1), c2 + (M + N) / 5); c3 += 1)
+ for (int c4 = max(max(max(max(c1, c0 - c2), c0 - (M + 6) / 5 + 1), c3 - (M + 2) / 5), (c3 + 1) / 2); c4 <= min(min(min(min(min(min(min(c0, c1 + 1), -c2 + c3 + (N - 1) / 5 + 1), c0 - c2 + N / 5 + 1), (M + 2 * N + 1) / 5 - 1), c2 + (N + 2) / 5), (2 * N + 5 * c0 + 3) / 10), (2 * N + 5 * c3 + 2) / 10); c4 += 1)
+ S1(c0, c1, c2, c3, c4, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/otl.in b/polly/lib/External/isl/test_inputs/codegen/cloog/otl.in
new file mode 100644
index 00000000000..a6ad5d2fc58
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/otl.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2, i3, i4, i2] -> [i0, i1, i2, i3, i4, i2] : 5i0 <= -7 + 2M + 2N and i4 >= i0 - i2 and 10i2 >= -2 - N + 5i0 and i2 >= -1 + i0 - i1 and 2i4 >= i0 and i0 >= 1 and i1 >= 1 and 2i1 >= i0 and i2 >= 0 and 5i2 >= 1 - M - N + 5i0 and 5i4 >= -1 - M + 5i0 and i3 >= i0 and 5i1 >= -2 - M + 5i0 and i3 >= 1 and 5i3 >= -3 - N + 5i1 + 5i2 and 5i2 <= 4 + N + 5i0 - 5i1 and i4 >= 1 and i2 <= i0 and 5i3 >= -2N + 10i1 and 5i1 <= -5 + M + 2N and 10i1 <= 1 + 2N + 5i0 and 5i2 >= -1 - N + 5i1 and i4 >= i1 and i3 >= i1 and i2 <= i1 and i1 <= i0 and 5i4 <= 4 + N - 5i2 + 5i3 and 5i4 <= 5 + N + 5i0 - 5i2 and 5i3 >= -2 - N + 10i2 and 5i2 <= -2 + M + N and 10i2 <= 3 + N + 5i0 and N >= 4 and i4 >= i2 and i3 >= i2 and M >= 3 and i4 <= i0 and 5i3 <= -6 + 2M + 2N and i4 >= -1 - i2 + i3 and 5i3 <= 3 + N + 10i2 and i3 <= 1 + i1 + i2 and i4 <= 1 + i1 and 2i4 >= i3 and 5i4 <= 2 + N + 5i2 and i3 <= 1 + 2i1 and i4 <= i3 and 5i3 <= M + N + 5i2 and 5i4 >= -2 - M + 5i3 and 10i4 <= 3 + 2N + 5i0 and i3 <= 1 + i0 and 5i3 <= 3 + M + 5i1 and 5i4 <= -4 + M + 2N and 10i4 <= 2 + 2N + 5i3 }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m, n] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.c b/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.c
new file mode 100644
index 00000000000..e7774d55d1e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.c
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= (M <= 0 ? 0 : M); c0 += 1) {
+ if (M >= c0)
+ S1(c0);
+ if (c0 == 0)
+ S2(0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.in b/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.in
new file mode 100644
index 00000000000..7b8a59e641e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/param-split.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0, 0] : i0 >= 0 and i0 <= M; S2[0] -> [0, 1] }
+[M] -> { : }
+[M] -> { [i, j] -> atomic[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.c b/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.c
new file mode 100644
index 00000000000..dc844442ca5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.c
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= floord(Ny, 2) + 2; c0 += 1)
+ for (int c1 = max(c0 - 1, c0 / 2 + 1); c1 <= min(c0, (Ny + 2 * c0) / 4); c1 += 1) {
+ if (Ny + 2 * c0 >= 4 * c1 + 1) {
+ for (int c2 = 1; c2 <= 2; c2 += 1) {
+ S1(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1, c2);
+ S2(c0 - c1, c1, 2 * c0 - 2 * c1, -2 * c0 + 4 * c1 - 1, c2);
+ }
+ } else
+ for (int c2 = 1; c2 <= 2; c2 += 1)
+ S2((-Ny + 2 * c0) / 4, (Ny + 2 * c0) / 4, (-Ny / 2) + c0, Ny - 1, c2);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.in b/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.in
new file mode 100644
index 00000000000..95d59dc29da
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/pouchet.in
@@ -0,0 +1,3 @@
+[Ny] -> { S1[i0, i1, 2i0, -2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= -1 + Ny + 2i0 and i4 >= 1 and i4 <= 2; S2[i0, i1, 2i0, -1 - 2i0 + 2i1, i4] -> [i0 + i1, i1, i4, 2i0, -2i0 + 2i1, 1 + i4] : i0 >= 0 and i0 <= 1 and i1 >= 1 + i0 and 2i1 <= Ny + 2i0 and i4 >= 1 and i4 <= 2 }
+[Ny] -> { : }
+[Ny] -> { [i, j, k, l, m, n] -> separate[x] : x >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.c b/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.c
new file mode 100644
index 00000000000..10d1f76c19d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 2 * n; c0 += 1)
+ for (int c1 = max(0, -n + c0); c1 <= min(n, c0); c1 += 1)
+ S1(c1, c0 - c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.in b/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.in
new file mode 100644
index 00000000000..fab0f945c37
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/rectangle.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, i1] -> [i0 + i1] : i0 >= 0 and i0 <= n and i1 >= 0 and i1 <= n }
+[n] -> { : n >= 0 }
+[n] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c
new file mode 100644
index 00000000000..253791a50b0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.c
@@ -0,0 +1,54 @@
+if (N >= 1) {
+ S1(0);
+ if (N == 1) {
+ for (int c3 = 0; c3 < M; c3 += 1)
+ S2(0, c3);
+ S3(0);
+ for (int c3 = 0; c3 < M; c3 += 1)
+ S4(0, c3);
+ S10(0);
+ S5(0);
+ } else {
+ for (int c3 = 0; c3 < M; c3 += 1)
+ S2(0, c3);
+ S3(0);
+ for (int c3 = 0; c3 < M; c3 += 1)
+ S4(0, c3);
+ S10(0);
+ S1(1);
+ S5(0);
+ }
+ for (int c1 = 2; c1 < N; c1 += 1) {
+ for (int c3 = c1 - 1; c3 < N; c3 += 1) {
+ S6(c1 - 2, c3);
+ for (int c5 = c1 - 2; c5 < M; c5 += 1)
+ S7(c1 - 2, c3, c5);
+ S8(c1 - 2, c3);
+ for (int c5 = c1 - 2; c5 < M; c5 += 1)
+ S9(c1 - 2, c3, c5);
+ }
+ for (int c3 = c1 - 1; c3 < M; c3 += 1)
+ S2(c1 - 1, c3);
+ S3(c1 - 1);
+ for (int c3 = c1 - 1; c3 < M; c3 += 1)
+ S4(c1 - 1, c3);
+ S10(c1 - 1);
+ S1(c1);
+ S5(c1 - 1);
+ }
+ if (N >= 2) {
+ S6(N - 2, N - 1);
+ for (int c5 = N - 2; c5 < M; c5 += 1)
+ S7(N - 2, N - 1, c5);
+ S8(N - 2, N - 1);
+ for (int c5 = N - 2; c5 < M; c5 += 1)
+ S9(N - 2, N - 1, c5);
+ for (int c3 = N - 1; c3 < M; c3 += 1)
+ S2(N - 1, c3);
+ S3(N - 1);
+ for (int c3 = N - 1; c3 < M; c3 += 1)
+ S4(N - 1, c3);
+ S10(N - 1);
+ S5(N - 1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in
new file mode 100644
index 00000000000..b81c03d7252
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-QR.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 5, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S9[i0, i1, i2] -> [0, 2 + i0, 0, i1, 3, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S10[i0] -> [0, 1 + i0, 4, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S3[i0] -> [0, 1 + i0, 2, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N; S6[i0, i1] -> [0, 2 + i0, 0, i1, 0, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S8[i0, i1] -> [0, 2 + i0, 0, i1, 2, 0, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N; S2[i0, i1] -> [0, 1 + i0, 1, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S4[i0, i1] -> [0, 1 + i0, 3, i1, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= i0 and i1 <= -1 + M; S7[i0, i1, i2] -> [0, 2 + i0, 0, i1, 1, i2, 0] : i0 >= 0 and i1 >= 1 + i0 and i1 <= -1 + N and i2 >= i0 and i2 <= -1 + M; S5[i0] -> [0, 1 + i0, 6, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c
new file mode 100644
index 00000000000..6d82ce4a89b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.c
@@ -0,0 +1,3 @@
+for (int c0 = 3; c0 <= 9; c0 += 1)
+ for (int c1 = max(c0 - 6, -(c0 % 2) + 2); c1 <= min(3, c0 - 2); c1 += 2)
+ S1(c0, c1, (c0 - c1) / 2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in
new file mode 100644
index 00000000000..a6a4ffc9297
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-bastoul3.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, i1, k, 0] : 2k = i0 - i1 and 2i2 = i0 - i1 and i1 >= 1 and i1 <= 3 and i1 <= -2 + i0 and i1 >= -6 + i0 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c
new file mode 100644
index 00000000000..4d1a9118bb9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.c
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < 3 * M; c1 += 1) {
+ if ((c1 - 2) % 3 == 0)
+ S1((c1 + 1) / 3);
+ for (int c3 = (c1 + 1) / 3 + 1; c3 <= min(M, c1 - 2); c3 += 1)
+ for (int c5 = -c3 + (c1 + c3 + 1) / 2 + 1; c5 <= min(c3, c1 - c3); c5 += 1)
+ S3(c1 - c3 - c5 + 1, c3, c5);
+ for (int c3 = -c1 + 2 * ((2 * c1 + 1) / 3) + 2; c3 <= min(M, c1); c3 += 2)
+ S2(((c1 - c3) / 2) + 1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in
new file mode 100644
index 00000000000..7f62b1f0264
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-cholesky2.in
@@ -0,0 +1,3 @@
+[M] -> { S3[i0, i1, i2] -> [0, -1 + i0 + i1 + i2, 1, i1, 1, i2, 0] : i0 >= 1 and i1 <= M and i2 >= 1 + i0 and i2 <= i1; S2[i0, i1] -> [0, -2 + 2i0 + i1, 2, i1, 0, 0, 0] : i0 >= 1 and i1 >= 1 + i0 and i1 <= M; S1[i0] -> [0, -1 + 3i0, 0, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c
new file mode 100644
index 00000000000..201ffee0bc3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.c
@@ -0,0 +1,8 @@
+{
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ S1(c1);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c1);
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ S3(c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in
new file mode 100644
index 00000000000..ca4282e49b3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion1.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [0, i0, 0] : i0 >= 0 and i0 <= M; S3[i0] -> [2, i0, 0] : i0 >= 0 and i0 <= M; S2[i0] -> [1, i0, 0] : i0 >= 1 and i0 <= M }
+[M] -> { : M >= 1 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c
new file mode 100644
index 00000000000..13c30301620
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.c
@@ -0,0 +1,12 @@
+if (N >= 1) {
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(1, c3);
+ for (int c1 = 2; c1 <= N; c1 += 1) {
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(c1 - 1, c3);
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ }
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(N, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in
new file mode 100644
index 00000000000..53905d8df35
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-fusion2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 1 + i0, 0, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 1, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c
new file mode 100644
index 00000000000..407fc8b73e1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.c
@@ -0,0 +1,3 @@
+for (int c1 = 0; c1 < M; c1 += 1)
+ for (int c3 = 0; c3 < M; c3 += 1)
+ S1(c1, c3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in
new file mode 100644
index 00000000000..ea86283a7b7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi2.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= -1 + M and i1 >= 0 and i1 <= -1 + M }
+[M] -> { : M >= 1 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c
new file mode 100644
index 00000000000..1df9bb90c24
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.c
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+ for (int c3 = 2; c3 < N; c3 += 1)
+ for (int c5 = 2; c5 < N; c5 += 1)
+ S1(c1, c3, c5);
+ for (int c3 = 2; c3 < N; c3 += 1)
+ for (int c5 = 2; c5 < N; c5 += 1)
+ S2(c1, c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in
new file mode 100644
index 00000000000..4f5cc77904a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-jacobi3.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c
new file mode 100644
index 00000000000..d8a80d66363
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.c
@@ -0,0 +1,10 @@
+for (int c1 = -99; c1 <= 100; c1 += 1) {
+ if (c1 <= 0)
+ S1(1, -c1 + 1);
+ for (int c3 = max(1, -2 * c1 + 3); c3 <= min(199, -2 * c1 + 199); c3 += 2) {
+ S2(((c3 - 1) / 2) + c1, (c3 + 1) / 2);
+ S1(((c3 + 1) / 2) + c1, (c3 + 1) / 2);
+ }
+ if (c1 >= 1)
+ S2(100, -c1 + 101);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in
new file mode 100644
index 00000000000..b2338b0321b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam1.in
@@ -0,0 +1,3 @@
+{ S2[i0, i1] -> [0, 1 + i0 - i1, 0, -1 + 2i1, 1] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100; S1[i0, i1] -> [0, i0 - i1, 0, 2i1, 0] : i0 >= 1 and i0 <= 100 and i1 >= 1 and i1 <= 100 }
+{ : }
+{ [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c
new file mode 100644
index 00000000000..f3215bf69bd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.c
@@ -0,0 +1,10 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S1(c1);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 2; c3 <= N; c3 += 1)
+ S2(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ S3(c1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in
new file mode 100644
index 00000000000..eb62bb7d009
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam2.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0] -> [0, i0, 0, 0, 0] : i0 >= 1 and i0 <= M; S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= N; S3[i0, i1] -> [2, i0, 2, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + N }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c
new file mode 100644
index 00000000000..c786628d804
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.c
@@ -0,0 +1,11 @@
+for (int c1 = 5; c1 <= 5 * M; c1 += 1) {
+ for (int c3 = max(2, floord(-M + c1, 4)); c3 < min(M, (c1 + 1) / 3 - 2); c3 += 1)
+ for (int c5 = max(1, -M - c3 + (M + c1) / 2 - 2); c5 < min(c3, -2 * c3 + (c1 + c3) / 2 - 2); c5 += 1)
+ S1(c1 - 2 * c3 - 2 * c5 - 5, c3, c5);
+ for (int c3 = max(1, floord(-M + c1, 4)); c3 < (c1 + 1) / 5; c3 += 1)
+ S2(c1 - 4 * c3 - 3, c3);
+ if (c1 % 5 == 0)
+ S4(c1 / 5);
+ for (int c3 = max(-3 * M - c1 + 3 * ((M + c1) / 2) + 1, -((c1 - 1) % 3) + 3); c3 < (c1 + 1) / 5; c3 += 3)
+ S3((c1 - 2 * c3 - 1) / 3, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in
new file mode 100644
index 00000000000..ebf78ae0b6b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam3.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, 5 + i0 + 2i1 + 2i2, 0, i1, 0, i2, 0] : i0 <= M and i1 <= -1 + i0 and i2 >= 1 and i2 <= -1 + i1; S3[i0, i1] -> [0, 1 + 3i0 + 2i1, 2, i1, 0, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S2[i0, i1] -> [0, 3 + i0 + 4i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0; S4[i0] -> [0, 5i0, 2, 0, 0, 0, 0] : i0 >= 1 and i0 <= M }
+[M] -> { : M >= 1 }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c
new file mode 100644
index 00000000000..6a0b0badab6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.c
@@ -0,0 +1,10 @@
+for (int c1 = 1; c1 < 2 * M - 1; c1 += 1) {
+ for (int c3 = max(-M + 1, -c1 + 1); c3 < 0; c3 += 1) {
+ for (int c7 = max(1, -M + c1 + 1); c7 <= min(M - 1, c1 + c3); c7 += 1)
+ S1(c7, c1 + c3 - c7, -c3);
+ for (int c5 = max(-M + c1 + 1, -c3); c5 < min(M, c1); c5 += 1)
+ S2(c1 - c5, c3 + c5, c5);
+ }
+ for (int c7 = max(1, -M + c1 + 1); c7 <= min(M - 1, c1); c7 += 1)
+ S1(c7, c1 - c7, 0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in
new file mode 100644
index 00000000000..1bb684f8e2b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam4.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1 + i2, 0, -i2, 0, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 0 and i2 <= -1 + M - i1; S2[i0, i1, i2] -> [0, i0 + i2, 0, i1 - i2, 1, i2, 0] : i0 >= 1 and i0 <= -1 + M and i1 >= 0 and i2 >= 1 + i1 and i2 <= -1 + M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c
new file mode 100644
index 00000000000..f476185713c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.c
@@ -0,0 +1,11 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S3(c1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in
new file mode 100644
index 00000000000..2e2046f1db9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam5.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S3[i0, i1] -> [2, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c
new file mode 100644
index 00000000000..2cc512261d6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.c
@@ -0,0 +1,8 @@
+{
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ for (int c1 = 0; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(c3, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in
new file mode 100644
index 00000000000..2699212b1df
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-lim-lam6.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i1, 0, i0, 0] : i0 >= 1 and i0 <= M and i1 >= 0 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
new file mode 100644
index 00000000000..dfc7d37d901
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.c
@@ -0,0 +1,17 @@
+if (M >= 0 && N >= 0)
+ for (int c1 = -4; c1 <= 3 * M + N; c1 += 1) {
+ if (3 * M + N >= c1 + 1 && c1 >= 3 * M) {
+ S2(M, -3 * M + c1);
+ } else if (3 * M >= c1 + 4 && (c1 - 2) % 3 == 0)
+ S1((c1 + 4) / 3, 0);
+ for (int c3 = max(-3 * M + c1 + 3, (c1 + 6) % 3); c3 <= min(N - 1, c1); c3 += 3) {
+ S2((c1 - c3) / 3, c3);
+ S1(((c1 - c3) / 3) + 1, c3 + 1);
+ }
+ if (c1 >= N && (N - c1) % 3 == 0) {
+ S2((-N + c1) / 3, N);
+ } else if (N >= c1 + 4 && c1 >= -3)
+ S1(0, c1 + 4);
+ for (int c3 = max(-3 * M + c1, (c1 + 6) % 3); c3 <= min(N, c1); c3 += 3)
+ S3((c1 - c3) / 3, c3);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in
new file mode 100644
index 00000000000..fd4dcc884f9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-liu-zhuge1.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1] -> [0, 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S3[i0, i1] -> [0, 3i0 + i1, 1, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N; S1[i0, i1] -> [0, -4 + 3i0 + i1, 0, i1, 0] : i0 >= 0 and i0 <= M and i1 >= 0 and i1 <= N }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c
new file mode 100644
index 00000000000..d37df98b692
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.c
@@ -0,0 +1,4 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 2; c3 <= M + c1; c3 += 1)
+ for (int c5 = max(1, -c1 + c3); c5 <= min(M, c3 - 1); c5 += 1)
+ S1(c1, c5, c3 - c5);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in
new file mode 100644
index 00000000000..03731713ff7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner3.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i1, 0] : i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= i0 }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c
new file mode 100644
index 00000000000..7a67212b2bb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.c
@@ -0,0 +1,5 @@
+for (int c1 = 2; c1 <= 2 * M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ for (int c7 = max(1, -M + c1); c7 <= min(M, c1 - 1); c7 += 1)
+ S1(c5, c3, c7, c1 - c7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in
new file mode 100644
index 00000000000..1a8070210cd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner4.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2 + i3, 0, i1, 0, i0, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c
new file mode 100644
index 00000000000..c5f8fcc38e8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.c
@@ -0,0 +1,5 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ for (int c7 = 1; c7 <= M; c7 += 1)
+ S1(c3, c5, c1, c7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in
new file mode 100644
index 00000000000..9122fc0a626
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-loechner5.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2, i3] -> [0, i2, 0, i0, 0, i1, 0, i3, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M and i3 >= 1 and i3 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c
new file mode 100644
index 00000000000..cff8f1724e3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.c
@@ -0,0 +1,85 @@
+{
+ if (N >= 2)
+ for (int c1 = 1; c1 < O; c1 += 1) {
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S1(c1, 1, c5);
+ for (int c5 = 1; c5 < M; c5 += 1) {
+ S6(c1, 1, c5);
+ S7(c1, 1, c5);
+ }
+ if (N >= 3) {
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S3(c1, 1, c5);
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S1(c1, 2, c5);
+ for (int c5 = 1; c5 < M; c5 += 1) {
+ S6(c1, 2, c5);
+ S7(c1, 2, c5);
+ }
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S11(c1, 1, c5);
+ } else {
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S3(c1, 1, c5);
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S11(c1, 1, c5);
+ }
+ for (int c3 = 3; c3 < 2 * N - 4; c3 += 2) {
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S10(c1, (c3 - 1) / 2, c5);
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S3(c1, (c3 + 1) / 2, c5);
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S1(c1, (c3 + 3) / 2, c5);
+ for (int c5 = 1; c5 < M; c5 += 1) {
+ S6(c1, (c3 + 3) / 2, c5);
+ S7(c1, (c3 + 3) / 2, c5);
+ }
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S11(c1, (c3 + 1) / 2, c5);
+ }
+ if (N >= 3) {
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S10(c1, N - 2, c5);
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S3(c1, N - 1, c5);
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S11(c1, N - 1, c5);
+ }
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S10(c1, N - 1, c5);
+ }
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1) {
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S2(c1, c3, c5);
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S8(c1, c3, c5);
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S9(c1, c3, c5);
+ }
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S4(c1, c3, c5);
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S5(c1, c3, c5);
+ for (int c1 = R; c1 < O; c1 += 1)
+ for (int c3 = Q; c3 < N; c3 += 1)
+ for (int c5 = P; c5 < M; c5 += 1)
+ S12(c1, c3, c5);
+ for (int c1 = R; c1 < O; c1 += 1)
+ for (int c3 = Q; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S13(c1, c3, c5);
+ for (int c1 = R; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = P; c5 < M; c5 += 1)
+ S14(c1, c3, c5);
+ for (int c1 = R; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S15(c1, c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in
new file mode 100644
index 00000000000..b7fdb69788c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp.in
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S8[i0, i1, i2] -> [1, i0, 0, 2i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S11[i0, i1, i2] -> [0, i0, 0, 2i1, 4, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S6[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S9[i0, i1, i2] -> [1, i0, 0, 1 + 2i1, 3, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S1[i0, i1, i2] -> [0, i0, 0, -3 + 2i1, 2, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S4[i0, i1, i2] -> [2, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, 2i1, 0, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S7[i0, i1, i2] -> [0, i0, 0, -2 + 2i1, 2, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S10[i0, i1, i2] -> [0, i0, 0, 1 + 2i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 1, i2, 2] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S15[i0, i1, i2] -> [7, i0, 1, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S5[i0, i1, i2] -> [3, i0, 0, i1, 1, i2, 1] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S13[i0, i1, i2] -> [5, i0, 0, i1, 1, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S12[i0, i1, i2] -> [4, i0, 0, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S14[i0, i1, i2] -> [6, i0, 1, i1, 0, i2, 0] : i0 >= R and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M }
+[M, N, O, P, Q, R, S, T, U] -> { : }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c
new file mode 100644
index 00000000000..98cd4b0707a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.c
@@ -0,0 +1,18 @@
+{
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = Q; c3 < N; c3 += 1)
+ for (int c5 = P; c5 < M; c5 += 1)
+ S1(c1, c3, c5);
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = Q; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S2(c1, c3, c5);
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = P; c5 < M; c5 += 1)
+ S3(c1, c3, c5);
+ for (int c1 = 1; c1 < O; c1 += 1)
+ for (int c3 = 1; c3 < N; c3 += 1)
+ for (int c5 = 1; c5 < M; c5 += 1)
+ S4(c1, c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in
new file mode 100644
index 00000000000..8a5dfb12d5a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-interp2.in
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R, S, T, U] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= P and i2 <= -1 + M; S4[i0, i1, i2] -> [3, i0, 1, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= Q and i1 <= -1 + N and i2 >= 1 and i2 <= -1 + M; S3[i0, i1, i2] -> [2, i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= -1 + O and i1 >= 1 and i1 <= -1 + N and i2 >= P and i2 <= -1 + M }
+[M, N, O, P, Q, R, S, T, U] -> { : }
+[M, N, O, P, Q, R, S, T, U] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c
new file mode 100644
index 00000000000..e3a5deeb1e7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.c
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < O; c1 += 1)
+ for (int c3 = 3; c3 < 2 * N - 2; c3 += 2) {
+ for (int c5 = 1; c5 <= M; c5 += 1) {
+ S1(c1, (c3 + 1) / 2, c5);
+ S2(c1, (c3 + 1) / 2, c5);
+ }
+ for (int c5 = 2; c5 < M; c5 += 1)
+ S3(c1, (c3 + 1) / 2, c5);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in
new file mode 100644
index 00000000000..835f81a4725
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-psinv.in
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> { : }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c
new file mode 100644
index 00000000000..e3a5deeb1e7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.c
@@ -0,0 +1,9 @@
+for (int c1 = 2; c1 < O; c1 += 1)
+ for (int c3 = 3; c3 < 2 * N - 2; c3 += 2) {
+ for (int c5 = 1; c5 <= M; c5 += 1) {
+ S1(c1, (c3 + 1) / 2, c5);
+ S2(c1, (c3 + 1) / 2, c5);
+ }
+ for (int c5 = 2; c5 < M; c5 += 1)
+ S3(c1, (c3 + 1) / 2, c5);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in
new file mode 100644
index 00000000000..835f81a4725
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-resid.in
@@ -0,0 +1,3 @@
+[M, N, O] -> { S1[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S2[i0, i1, i2] -> [0, i0, 0, -1 + 2i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 1 and i2 <= M; S3[i0, i1, i2] -> [0, i0, 0, 2i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M }
+[M, N, O] -> { : }
+[M, N, O] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c
new file mode 100644
index 00000000000..992bfd53f02
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.c
@@ -0,0 +1,33 @@
+if (M >= 2 && N >= 3)
+ for (int c1 = 2; c1 < O; c1 += 1) {
+ for (int c5 = 2; c5 <= M; c5 += 1)
+ S1(c1, 2, c5);
+ for (int c3 = 3; c3 < N; c3 += 1) {
+ for (int c5 = 2; c5 <= M; c5 += 1)
+ S2(c1, c3 - 1, c5);
+ if (M >= 3) {
+ S4(c1, c3 - 1, 2);
+ for (int c5 = 2; c5 < M - 1; c5 += 1) {
+ S3(c1, c3 - 1, c5);
+ S5(c1, c3 - 1, c5);
+ S4(c1, c3 - 1, c5 + 1);
+ }
+ S3(c1, c3 - 1, M - 1);
+ S5(c1, c3 - 1, M - 1);
+ }
+ for (int c5 = 2; c5 <= M; c5 += 1)
+ S1(c1, c3, c5);
+ }
+ for (int c5 = 2; c5 <= M; c5 += 1)
+ S2(c1, N - 1, c5);
+ if (M >= 3) {
+ S4(c1, N - 1, 2);
+ for (int c5 = 2; c5 < M - 1; c5 += 1) {
+ S3(c1, N - 1, c5);
+ S5(c1, N - 1, c5);
+ S4(c1, N - 1, c5 + 1);
+ }
+ S3(c1, N - 1, M - 1);
+ S5(c1, N - 1, M - 1);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in
new file mode 100644
index 00000000000..03f4134661f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-mg-rprj3.in
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R] -> { S1[i0, i1, i2] -> [0, i0, 0, i1, 2, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M; S4[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, -1 + i2, 2] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S3[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 0] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S5[i0, i1, i2] -> [0, i0, 0, 1 + i1, 1, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + M; S2[i0, i1, i2] -> [0, i0, 0, 1 + i1, 0, i2, 1] : i0 >= 2 and i0 <= -1 + O and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= M }
+[M, N, O, P, Q, R] -> { : }
+[M, N, O, P, Q, R] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c
new file mode 100644
index 00000000000..7268c23d080
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.c
@@ -0,0 +1,7 @@
+for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 < 2 * N; c3 += 1) {
+ for (int c5 = max(1, -N + c3); c5 < (c3 + 1) / 2; c5 += 1)
+ S1(c1, c3 - c5, c5);
+ if ((c3 - 1) % 2 == 0)
+ S2(c1, (c3 + 1) / 2);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in
new file mode 100644
index 00000000000..ecbb320de01
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali1.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1, i2] -> [0, i0, 0, i1 + i2, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 <= N and i2 >= 1 and i2 <= -1 + i1; S2[i0, i1] -> [0, i0, 0, -1 + 2i1, 1, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= N }
+[M, N] -> { : }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c
new file mode 100644
index 00000000000..a407cad52d2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.c
@@ -0,0 +1,8 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(c1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in
new file mode 100644
index 00000000000..9ba248fb0fc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali2.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 1, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c
new file mode 100644
index 00000000000..c281b826e01
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.c
@@ -0,0 +1,9 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ for (int c5 = 1; c5 <= M; c5 += 1)
+ S2(c1, c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in
new file mode 100644
index 00000000000..70da8ea5c11
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali3.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1, i2] -> [1, i0, 0, i1, 1, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M and i2 >= 1 and i2 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0, 0, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c
new file mode 100644
index 00000000000..a407cad52d2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.c
@@ -0,0 +1,8 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S1(c1, c3);
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ for (int c3 = 1; c3 <= M; c3 += 1)
+ S2(c1, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in
new file mode 100644
index 00000000000..e975faef4c7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali4.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [1, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M; S1[i0, i1] -> [0, i0, 0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : M >= 2 }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c
new file mode 100644
index 00000000000..51f2f0c154e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.c
@@ -0,0 +1,10 @@
+for (int c1 = 3; c1 < 2 * M; c1 += 1) {
+ for (int c3 = c1 / 2 + 2; c3 <= M; c3 += 1)
+ for (int c7 = c1 / 2 + 1; c7 < min(c1, c3); c7 += 1)
+ S1(c7, c1 - c7, c3);
+ for (int c3 = max(1, -M + c1); c3 < (c1 + 1) / 2; c3 += 1)
+ S2(c1 - c3, c3);
+ for (int c3 = c1 / 2 + 2; c3 <= M; c3 += 1)
+ for (int c7 = c1 / 2 + 1; c7 < min(c1, c3); c7 += 1)
+ S3(c7, c1 - c7, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in
new file mode 100644
index 00000000000..1b77acdc8d6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali5.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1, i2] -> [0, i0 + i1, 0, i2, 0, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S3[i0, i1, i2] -> [0, i0 + i1, 2, i2, 2, i2, 0] : i1 >= 1 and i1 <= -1 + i0 and i2 >= 1 + i0 and i2 <= M; S2[i0, i1] -> [0, i0 + i1, 1, i1, 1, 0, 0] : i0 <= M and i1 >= 1 and i1 <= -1 + i0 }
+[M] -> { : }
+[M] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c
new file mode 100644
index 00000000000..1df9bb90c24
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.c
@@ -0,0 +1,8 @@
+for (int c1 = 1; c1 <= M; c1 += 1) {
+ for (int c3 = 2; c3 < N; c3 += 1)
+ for (int c5 = 2; c5 < N; c5 += 1)
+ S1(c1, c3, c5);
+ for (int c3 = 2; c3 < N; c3 += 1)
+ for (int c5 = 2; c5 < N; c5 += 1)
+ S2(c1, c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in
new file mode 100644
index 00000000000..7a08ca76e8e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-pingali6.in
@@ -0,0 +1,3 @@
+[M, N] -> { S2[i0, i1, i2] -> [0, 1 + 2i0, 1, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N; S1[i0, i1, i2] -> [0, 2i0, 0, i1, 0, i2, 0] : i0 >= 1 and i0 <= M and i1 >= 2 and i1 <= -1 + N and i2 >= 2 and i2 <= -1 + N }
+[M, N] -> { : M >= 1 and N >= 1 }
+[M, N] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c
new file mode 100644
index 00000000000..104e2620fdd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.c
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+ S1(c1, (c1 - 2) / 7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in
new file mode 100644
index 00000000000..46a1c35375e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 2 and i0 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c
new file mode 100644
index 00000000000..104e2620fdd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.c
@@ -0,0 +1,2 @@
+for (int c1 = 2; c1 <= M; c1 += 7)
+ S1(c1, (c1 - 2) / 7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in
new file mode 100644
index 00000000000..be6b1978a4b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-stride2.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0, i1] -> [0, i0, 0, 0, 0] : 7i1 = -2 + i0 and i0 >= 0 and i0 <= M }
+[M] -> { : }
+[M] -> { [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c
new file mode 100644
index 00000000000..8874eabfceb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.c
@@ -0,0 +1,5 @@
+for (int c1 = 0; c1 <= 9; c1 += 2)
+ for (int c3 = 0; c3 <= min(4, c1 + 3); c3 += 2)
+ for (int c5 = max(1, c1); c5 <= min(c1 + 1, c1 - c3 + 4); c5 += 1)
+ for (int c7 = max(1, -c1 + c3 + c5); c7 <= min(4, -c1 + c3 + c5 + 1); c7 += 1)
+ S1(c1 / 2, (-c1 + c3) / 2, -c1 + c5, -c3 + c7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.in
new file mode 100644
index 00000000000..0c9ffc9f77f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-tang-xue1.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2, i3] -> [0, 2i0, 0, 2i0 + 2i1, 0, 2i0 + i2, 0, 2i0 + 2i1 + i3, 0] : i3 <= 4 - 2i0 - 2i1 and i3 >= i2 and i2 <= 9 - 2i0 and i2 >= 0 and i2 >= 1 - 2i0 and i3 <= 1 + i2 and i2 <= 1 and i3 >= 1 - 2i0 - 2i1 }
+{ : }
+{ [i, j, k, l, m, n, o, p, q] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.c b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.c
new file mode 100644
index 00000000000..3946c423f15
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.c
@@ -0,0 +1 @@
+S1(1, 1, 5);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.in b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.in
new file mode 100644
index 00000000000..a7eb204753b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/reservoir-two.in
@@ -0,0 +1,3 @@
+{ S1[i0, i1, i2] -> [i0, j, k, 0] : 2i1 = 3 - i0 and 2j = 3 - i0 and 2k = 9 + i0 and 2i2 = 9 + i0 and i0 >= 0 and i0 <= 1 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.c b/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.c
new file mode 100644
index 00000000000..0023bc6cd9a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.c
@@ -0,0 +1,4 @@
+{
+ S2();
+ S1();
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.in b/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.in
new file mode 100644
index 00000000000..a0a5a8a1dde
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/singleton.in
@@ -0,0 +1,3 @@
+{ S2[] -> [-1]; S1[] -> [0] }
+{ : }
+{ [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c
new file mode 100644
index 00000000000..316213f18f1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= M; c0 += 1) {
+ S1(c0, 1);
+ for (int c1 = 2; c1 <= c0; c1 += 1) {
+ S1(c0, c1);
+ S2(c0, c1);
+ }
+ for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+ S1(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in
new file mode 100644
index 00000000000..028c792b640
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/square+triangle-1-1-2-3.in
@@ -0,0 +1,3 @@
+[M] -> { S2[i0, i1] -> [i0, i1, 1] : i1 >= 2 and i1 <= i0 and i0 <= M; S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= M }
+[M] -> { : M >= 1 }
+[M] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride.c b/polly/lib/External/isl/test_inputs/codegen/cloog/stride.c
new file mode 100644
index 00000000000..9bd4ddfb307
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride.c
@@ -0,0 +1,7 @@
+{
+ for (int c0 = 3; c0 <= 24; c0 += 3)
+ S2(c0, c0 / 3);
+ S1(25);
+ for (int c0 = 27; c0 <= 100; c0 += 3)
+ S2(c0, c0 / 3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride.in b/polly/lib/External/isl/test_inputs/codegen/cloog/stride.in
new file mode 100644
index 00000000000..410c6843527
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride.in
@@ -0,0 +1,3 @@
+{ S1[25] -> [25, 0]; S2[i0, i1] -> [i0, j] : 3i1 = i0 and 3j = i0 and i0 >= 3 and i0 <= 100 }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.c
new file mode 100644
index 00000000000..c56af8e749e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.c
@@ -0,0 +1,8 @@
+{
+ for (int c0 = 3; c0 <= 26; c0 += 3)
+ S2(c0, c0 / 3);
+ S1(27);
+ S2(27, 9);
+ for (int c0 = 30; c0 <= 100; c0 += 3)
+ S2(c0, c0 / 3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.in
new file mode 100644
index 00000000000..97e40866adf
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride2.in
@@ -0,0 +1,3 @@
+{ S1[27] -> [27, 0]; S2[i0, i1] -> [i0, j] : 3i1 = i0 and 3j = i0 and i0 >= 3 and i0 <= 100 }
+{ : }
+{ [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.c
new file mode 100644
index 00000000000..d145938b663
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.c
@@ -0,0 +1,2 @@
+for (int c0 = max(1, m); c0 <= n; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.in
new file mode 100644
index 00000000000..9b87b899243
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride3.in
@@ -0,0 +1,3 @@
+[m, n] -> { S1[i0] -> [50i0, 0] : i0 >= 1 and i0 <= n and i0 >= m }
+[m, n] -> { : }
+[m, n] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.c b/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.c
new file mode 100644
index 00000000000..03908e60c07
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.c
@@ -0,0 +1,3 @@
+if (t >= 0 && t <= 15)
+ for (int c0 = t; c0 <= 99; c0 += 16)
+ S1(c0, t);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.in b/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.in
new file mode 100644
index 00000000000..436cad3c5a5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/stride4.in
@@ -0,0 +1,3 @@
+[t] -> { S1[i0, t] -> [i0, t, 0] : exists (e0 = [(t - i0)/16]: 16e0 = t - i0 and i0 >= 0 and i0 <= 99 and t >= 0 and t <= 15) }
+[t] -> { : }
+[t] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/swim.c b/polly/lib/External/isl/test_inputs/codegen/cloog/swim.c
new file mode 100644
index 00000000000..47b4ebe5ff8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/swim.c
@@ -0,0 +1,159 @@
+if (M == 1) {
+ S1();
+ S2();
+ S3();
+ S4();
+ S5();
+ S6();
+ S7();
+ S8();
+ S9();
+ S10();
+ S11();
+ S12();
+ S13();
+ S14();
+ S15();
+ S16();
+ S17();
+ S18();
+ S19();
+ S20();
+ S21();
+ S22();
+ S23();
+ S24();
+ S25();
+ S26();
+ S27();
+ for (int c1 = 1; c1 <= N; c1 += 1) {
+ for (int c3 = 1; c3 <= N; c3 += 1) {
+ S28(c1, c3);
+ S29(c1, c3);
+ S30(c1, c3);
+ }
+ S31(c1);
+ }
+ S32();
+ S33();
+ S34();
+ if (O <= 1)
+ S35();
+ S36();
+ S37();
+ for (int c1 = 2; c1 <= P; c1 += 1) {
+ S38(c1);
+ S39(c1);
+ for (int c3 = 1; c3 <= Q; c3 += 1)
+ for (int c5 = 1; c5 <= R; c5 += 1) {
+ S40(c1, c3, c5);
+ S41(c1, c3, c5);
+ S42(c1, c3, c5);
+ S43(c1, c3, c5);
+ }
+ for (int c3 = 1; c3 <= Q; c3 += 1) {
+ S44(c1, c3);
+ S45(c1, c3);
+ S46(c1, c3);
+ S47(c1, c3);
+ }
+ for (int c3 = 1; c3 <= R; c3 += 1) {
+ S48(c1, c3);
+ S49(c1, c3);
+ S50(c1, c3);
+ S51(c1, c3);
+ }
+ S52(c1);
+ S53(c1);
+ S54(c1);
+ S55(c1);
+ S56(c1);
+ S57(c1);
+ S58(c1);
+ for (int c3 = 1; c3 <= Q; c3 += 1)
+ for (int c5 = 1; c5 <= R; c5 += 1) {
+ S59(c1, c3, c5);
+ S60(c1, c3, c5);
+ S61(c1, c3, c5);
+ }
+ for (int c3 = 1; c3 <= Q; c3 += 1) {
+ S62(c1, c3);
+ S63(c1, c3);
+ S64(c1, c3);
+ }
+ for (int c3 = 1; c3 <= R; c3 += 1) {
+ S65(c1, c3);
+ S66(c1, c3);
+ S67(c1, c3);
+ }
+ S68(c1);
+ S69(c1);
+ S70(c1);
+ S71(c1);
+ S72(c1);
+ S73(c1);
+ S74(c1);
+ S75(c1);
+ S76(c1);
+ S77(c1);
+ S78(c1);
+ S79(c1);
+ S80(c1);
+ S81(c1);
+ S82(c1);
+ S83(c1);
+ S84(c1);
+ S85(c1);
+ S86(c1);
+ S87(c1);
+ S88(c1);
+ S89(c1);
+ S90(c1);
+ S91(c1);
+ S92(c1);
+ S93(c1);
+ S94(c1);
+ for (int c3 = 1; c3 <= N; c3 += 1) {
+ for (int c5 = 1; c5 <= N; c5 += 1) {
+ S95(c1, c3, c5);
+ S96(c1, c3, c5);
+ S97(c1, c3, c5);
+ }
+ S98(c1, c3);
+ }
+ S99(c1);
+ S100(c1);
+ S101(c1);
+ for (int c3 = 1; c3 <= Q; c3 += 1)
+ for (int c5 = 1; c5 <= R; c5 += 1) {
+ S102(c1, c3, c5);
+ S103(c1, c3, c5);
+ S104(c1, c3, c5);
+ S105(c1, c3, c5);
+ S106(c1, c3, c5);
+ S107(c1, c3, c5);
+ }
+ for (int c3 = 1; c3 <= Q; c3 += 1) {
+ S108(c1, c3);
+ S109(c1, c3);
+ S110(c1, c3);
+ S111(c1, c3);
+ S112(c1, c3);
+ S113(c1, c3);
+ }
+ for (int c3 = 1; c3 <= R; c3 += 1) {
+ S114(c1, c3);
+ S115(c1, c3);
+ S116(c1, c3);
+ S117(c1, c3);
+ S118(c1, c3);
+ S119(c1, c3);
+ }
+ S120(c1);
+ S121(c1);
+ S122(c1);
+ S123(c1);
+ S124(c1);
+ S125(c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/swim.in b/polly/lib/External/isl/test_inputs/codegen/cloog/swim.in
new file mode 100644
index 00000000000..4661ff0cff2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/swim.in
@@ -0,0 +1,3 @@
+[M, N, O, P, Q, R] -> { S84[i0] -> [34, i0, 31, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S6[] -> [5, 0, 0, 0, 0, 0, 0] : M = 1; S25[] -> [24, 0, 0, 0, 0, 0, 0] : M = 1; S115[i0, i1] -> [34, i0, 48, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S64[i0, i1] -> [34, i0, 13, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S62[i0, i1] -> [34, i0, 13, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S40[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S123[i0] -> [34, i0, 52, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S5[] -> [4, 0, 0, 0, 0, 0, 0] : M = 1; S15[] -> [14, 0, 0, 0, 0, 0, 0] : M = 1; S76[i0] -> [34, i0, 23, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S39[i0] -> [34, i0, 1, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S13[] -> [12, 0, 0, 0, 0, 0, 0] : M = 1; S28[i0, i1] -> [27, i0, 0, i1, 0, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S70[i0] -> [34, i0, 17, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S53[i0] -> [34, i0, 6, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S121[i0] -> [34, i0, 50, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S47[i0, i1] -> [34, i0, 3, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S59[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S71[i0] -> [34, i0, 18, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S77[i0] -> [34, i0, 24, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S63[i0, i1] -> [34, i0, 13, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S51[i0, i1] -> [34, i0, 4, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S100[i0] -> [34, i0, 44, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S22[] -> [21, 0, 0, 0, 0, 0, 0] : M = 1; S95[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S8[] -> [7, 0, 0, 0, 0, 0, 0] : M = 1; S120[i0] -> [34, i0, 49, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S50[i0, i1] -> [34, i0, 4, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S45[i0, i1] -> [34, i0, 3, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S72[i0] -> [34, i0, 19, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S52[i0] -> [34, i0, 5, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S7[] -> [6, 0, 0, 0, 0, 0, 0] : M = 1; S78[i0] -> [34, i0, 25, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S110[i0, i1] -> [34, i0, 47, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S124[i0] -> [34, i0, 53, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S60[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S27[] -> [26, 0, 0, 0, 0, 0, 0] : M = 1; S114[i0, i1] -> [34, i0, 48, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S49[i0, i1] -> [34, i0, 4, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S94[i0] -> [34, i0, 41, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S57[i0] -> [34, i0, 10, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S66[i0, i1] -> [34, i0, 14, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S18[] -> [17, 0, 0, 0, 0, 0, 0] : M = 1; S92[i0] -> [34, i0, 39, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S3[] -> [2, 0, 0, 0, 0, 0, 0] : M = 1; S35[] -> [31, 0, 0, 0, 0, 0, 0] : M = 1 and O <= 1; S36[] -> [32, 0, 0, 0, 0, 0, 0] : M = 1; S10[] -> [9, 0, 0, 0, 0, 0, 0] : M = 1; S2[] -> [1, 0, 0, 0, 0, 0, 0] : M = 1; S48[i0, i1] -> [34, i0, 4, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S30[i0, i1] -> [27, i0, 0, i1, 2, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S75[i0] -> [34, i0, 22, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S83[i0] -> [34, i0, 30, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S87[i0] -> [34, i0, 34, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S88[i0] -> [34, i0, 35, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S33[] -> [29, 0, 0, 0, 0, 0, 0] : M = 1; S101[i0] -> [34, i0, 45, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S21[] -> [20, 0, 0, 0, 0, 0, 0] : M = 1; S32[] -> [28, 0, 0, 0, 0, 0, 0] : M = 1; S118[i0, i1] -> [34, i0, 48, i1, 4, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S79[i0] -> [34, i0, 26, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S38[i0] -> [34, i0, 0, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S108[i0, i1] -> [34, i0, 47, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S65[i0, i1] -> [34, i0, 14, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S91[i0] -> [34, i0, 38, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S17[] -> [16, 0, 0, 0, 0, 0, 0] : M = 1; S80[i0] -> [34, i0, 27, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S54[i0] -> [34, i0, 7, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S46[i0, i1] -> [34, i0, 3, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S68[i0] -> [34, i0, 15, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S116[i0, i1] -> [34, i0, 48, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S43[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 3] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S26[] -> [25, 0, 0, 0, 0, 0, 0] : M = 1; S31[i0] -> [27, i0, 1, 0, 0, 0, 0] : M = 1 and i0 >= 1 and i0 <= N; S69[i0] -> [34, i0, 16, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S24[] -> [23, 0, 0, 0, 0, 0, 0] : M = 1; S90[i0] -> [34, i0, 37, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S89[i0] -> [34, i0, 36, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S82[i0] -> [34, i0, 29, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S67[i0, i1] -> [34, i0, 14, i1, 2, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S58[i0] -> [34, i0, 11, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S109[i0, i1] -> [34, i0, 47, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S122[i0] -> [34, i0, 51, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S61[i0, i1, i2] -> [34, i0, 12, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S1[] -> [0, 0, 0, 0, 0, 0, 0] : M = 1; S4[] -> [3, 0, 0, 0, 0, 0, 0] : M = 1; S86[i0] -> [34, i0, 33, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S14[] -> [13, 0, 0, 0, 0, 0, 0] : M = 1; S93[i0] -> [34, i0, 40, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S56[i0] -> [34, i0, 9, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S37[] -> [33, 0, 0, 0, 0, 0, 0] : M = 1; S125[i0] -> [34, i0, 54, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S96[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S9[] -> [8, 0, 0, 0, 0, 0, 0] : M = 1; S41[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S102[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S112[i0, i1] -> [34, i0, 47, i1, 4, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S16[] -> [15, 0, 0, 0, 0, 0, 0] : M = 1; S85[i0] -> [34, i0, 32, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S42[i0, i1, i2] -> [34, i0, 2, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S12[] -> [11, 0, 0, 0, 0, 0, 0] : M = 1; S55[i0] -> [34, i0, 8, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S11[] -> [10, 0, 0, 0, 0, 0, 0] : M = 1; S19[] -> [18, 0, 0, 0, 0, 0, 0] : M = 1; S107[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 5] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S98[i0, i1] -> [34, i0, 42, i1, 1, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N; S104[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S29[i0, i1] -> [27, i0, 0, i1, 1, 0, 0] : M = 1 and i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= N; S20[] -> [19, 0, 0, 0, 0, 0, 0] : M = 1; S103[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 1] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S105[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 3] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S97[i0, i1, i2] -> [34, i0, 42, i1, 0, i2, 2] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= N and i2 >= 1 and i2 <= N; S44[i0, i1] -> [34, i0, 3, i1, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S106[i0, i1, i2] -> [34, i0, 46, i1, 0, i2, 4] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q and i2 >= 1 and i2 <= R; S34[] -> [30, 0, 0, 0, 0, 0, 0] : M = 1; S111[i0, i1] -> [34, i0, 47, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S99[i0] -> [34, i0, 43, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S81[i0] -> [34, i0, 28, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S23[] -> [22, 0, 0, 0, 0, 0, 0] : M = 1; S117[i0, i1] -> [34, i0, 48, i1, 3, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S74[i0] -> [34, i0, 21, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P; S113[i0, i1] -> [34, i0, 47, i1, 5, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= Q; S119[i0, i1] -> [34, i0, 48, i1, 5, 0, 0] : M = 1 and i0 >= 2 and i0 <= P and i1 >= 1 and i1 <= R; S73[i0] -> [34, i0, 20, 0, 0, 0, 0] : M = 1 and i0 >= 2 and i0 <= P }
+[M, N, O, P, Q, R] -> { : }
+[M, N, O, P, Q, R] -> { [i, j, k, l, m, n, o] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/test.c b/polly/lib/External/isl/test_inputs/codegen/cloog/test.c
new file mode 100644
index 00000000000..84c84931e35
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/test.c
@@ -0,0 +1,17 @@
+{
+ for (int c0 = 1; c0 <= 2; c0 += 1)
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S1(c0, c1);
+ for (int c0 = 3; c0 <= N; c0 += 1) {
+ for (int c1 = 1; c1 <= min(M, c0 - 1); c1 += 1)
+ S1(c0, c1);
+ if (M >= c0) {
+ S1(c0, c0);
+ S2(c0, c0);
+ }
+ for (int c1 = c0 + 1; c1 <= M; c1 += 1)
+ S1(c0, c1);
+ if (c0 >= M + 1)
+ S2(c0, c0);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/test.in b/polly/lib/External/isl/test_inputs/codegen/cloog/test.in
new file mode 100644
index 00000000000..981d9339f52
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/test.in
@@ -0,0 +1,3 @@
+[M, N] -> { S1[i0, i1] -> [i0, i1, 0] : i0 >= 1 and i0 <= N and i1 >= 1 and i1 <= M; S2[i0, i0] -> [i0, i0, 1] : i0 >= 3 and i0 <= N }
+[M, N] -> { : N >= M and M >= 4 }
+[M, N] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.c b/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.c
new file mode 100644
index 00000000000..8d6709e7d9b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.c
@@ -0,0 +1,9 @@
+{
+ for (int c0 = 0; c0 <= floord(n - 1, 3); c0 += 1)
+ for (int c2 = 3 * c0 + 1; c2 <= min(n, 3 * c0 + 3); c2 += 1)
+ S1(c2, c0);
+ for (int c0 = floord(n, 3); c0 <= 2 * floord(n, 3); c0 += 1)
+ for (int c1 = 0; c1 < n; c1 += 1)
+ for (int c3 = max(1, (n % 3) - n + 3 * c0); c3 <= min(n, (n % 3) - n + 3 * c0 + 2); c3 += 1)
+ S2(c1 + 1, c3, 0, n / 3, c0 - n / 3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.in b/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.in
new file mode 100644
index 00000000000..398e5234603
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/thomasset.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, 0, i3, i4] -> [i3 + i4, -1 + i0] : i0 <= n and i1 <= n and i1 >= 1 and i0 >= 1 and 3i4 <= i1 and 3i4 >= -2 + i1 and 3i3 <= n and 3i3 >= -2 + n; S1[i0, i1] -> [i1, 0] : i0 <= n and i0 >= 1 and 3i1 <= -1 + i0 and 3i1 >= -3 + i0 }
+[n] -> { : }
+[n] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.c b/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.c
new file mode 100644
index 00000000000..971b988a578
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= n / 10; c0 += 1)
+ for (int c1 = 10 * c0; c1 <= min(n, 10 * c0 + 9); c1 += 1)
+ S1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.in b/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.in
new file mode 100644
index 00000000000..6f0530f2ba0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/tiling.in
@@ -0,0 +1,3 @@
+[n] -> { S1[ii, i] -> [ii, i, 0] : i >= 0 and i <= n and i <= 9 + 10ii and i >= 10ii }
+[n] -> { : n >= 0 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.c b/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.c
new file mode 100644
index 00000000000..d8002a86d86
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.c
@@ -0,0 +1,6 @@
+{
+ for (int c2 = 0; c2 <= n; c2 += 1)
+ S1(c2, 0, 0);
+ for (int c2 = 0; c2 <= n; c2 += 1)
+ S2(0, c2, 0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.in b/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.in
new file mode 100644
index 00000000000..ae29bb54f89
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/uday_scalars.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i0, 0, 0] -> [0, 1, i0, 0] : i0 >= 0 and i0 <= n; S2[0, i1, 0] -> [1, 0, i1, 1] : i1 >= 0 and i1 <= n }
+[n] -> { : }
+[n] -> { [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/union.c b/polly/lib/External/isl/test_inputs/codegen/cloog/union.c
new file mode 100644
index 00000000000..6dc0a9b877f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/union.c
@@ -0,0 +1,6 @@
+if (M >= 11) {
+ for (int c0 = -100; c0 <= 0; c0 += 1)
+ S1(-c0);
+} else
+ for (int c0 = 0; c0 <= 100; c0 += 1)
+ S1(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/union.in b/polly/lib/External/isl/test_inputs/codegen/cloog/union.in
new file mode 100644
index 00000000000..23b6cab9a89
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/union.in
@@ -0,0 +1,3 @@
+[M] -> { S1[i0] -> [i0] : M <= 10 and i0 >= 0 and i0 <= 100; S1[i0] -> [-i0] : M >= 11 and i0 >= 0 and i0 <= 100 }
+[M] -> { : M >= 1 or M <= -1 }
+[M] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.c b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.c
new file mode 100644
index 00000000000..83c4577b479
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.c
@@ -0,0 +1,13 @@
+{
+ S1(0);
+ S1(1);
+ S1(2);
+ S1(3);
+ S1(4);
+ S1(5);
+ S1(6);
+ S1(7);
+ S1(8);
+ S1(9);
+ S1(10);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.in b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.in
new file mode 100644
index 00000000000..1e449e0b420
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i] -> [i, 0] : i >= 0 and i <= 10 }
+[n] -> { : }
+[n] -> { [i, j] -> unroll[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.c
new file mode 100644
index 00000000000..b96ddd73fe2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.c
@@ -0,0 +1,6 @@
+{
+ if (n >= 0 && n <= 9)
+ S1(n);
+ if (n >= -1 && n <= 9)
+ S1(n + 1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.in
new file mode 100644
index 00000000000..eb71e075ab3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/unroll2.in
@@ -0,0 +1,3 @@
+[n] -> { S1[i] -> [i, 0] : i >= n and i <= 1 + n and n <= 9 and i >= 0 }
+[n] -> { : }
+[n] -> { [i, j] -> unroll[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.c b/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.c
new file mode 100644
index 00000000000..af8c9fe42f0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.c
@@ -0,0 +1,348 @@
+{
+ for (int c0 = 0; c0 <= 2; c0 += 1) {
+ S1(c0, 0, 0);
+ for (int c1 = 0; c1 <= 4; c1 += 1)
+ S2(c0, c1, 0);
+ }
+ S1(3, 0, 0);
+ for (int c1 = 0; c1 <= 4; c1 += 1)
+ S2(3, c1, 0);
+ for (int c1 = 7; c1 <= 11; c1 += 1)
+ S8(3, c1, 0);
+ S1(4, 0, 0);
+ S2(4, 0, 0);
+ S3(4, 0, 0);
+ S5(4, 0, 0);
+ for (int c1 = 1; c1 <= 4; c1 += 1) {
+ S2(4, c1, 0);
+ S5(4, c1, 0);
+ }
+ for (int c1 = 7; c1 <= 11; c1 += 1)
+ S8(4, c1, 0);
+ for (int c0 = 5; c0 <= 6; c0 += 1) {
+ for (int c1 = -4; c1 < c0 - 8; c1 += 1)
+ S6(c0, c1, 0);
+ for (int c1 = c0 - 9; c1 < 0; c1 += 1)
+ S7(c0, c1, 0);
+ S3(c0, 0, 0);
+ S7(c0, 0, 0);
+ for (int c1 = 1; c1 < c0 - 3; c1 += 1)
+ S4(c0, c1, -1);
+ for (int c1 = c0 - 4; c1 <= 4; c1 += 1)
+ S5(c0, c1, 0);
+ for (int c1 = 7; c1 <= 11; c1 += 1)
+ S8(c0, c1, 0);
+ }
+ for (int c1 = -4; c1 < -1; c1 += 1)
+ S6(7, c1, 0);
+ for (int c1 = -2; c1 < 0; c1 += 1)
+ S7(7, c1, 0);
+ S3(7, 0, 0);
+ S7(7, 0, 0);
+ for (int c1 = 1; c1 <= 3; c1 += 1)
+ S4(7, c1, -1);
+ for (int c1 = 3; c1 <= 4; c1 += 1)
+ S5(7, c1, 0);
+ S9(7, 4, 0);
+ S10(7, 4, 0);
+ S11(7, 4, 0);
+ S21(7, 4, 0);
+ S23(7, 4, 0);
+ S11(7, 4, 1);
+ S16(7, 4, 1);
+ S17(7, 4, 1);
+ for (int c2 = 2; c2 <= 4; c2 += 1)
+ S11(7, 4, c2);
+ S12(7, 5, 0);
+ S21(7, 5, 0);
+ S22(7, 5, 0);
+ S23(7, 5, 0);
+ S12(7, 5, 1);
+ S16(7, 5, 1);
+ S17(7, 5, 1);
+ for (int c2 = 2; c2 <= 4; c2 += 1)
+ S12(7, 5, c2);
+ S21(7, 6, 0);
+ S22(7, 6, 0);
+ S23(7, 6, 0);
+ for (int c1 = 7; c1 <= 8; c1 += 1) {
+ S8(7, c1, 0);
+ S21(7, c1, 0);
+ S22(7, c1, 0);
+ S23(7, c1, 0);
+ }
+ S8(7, 9, 0);
+ S22(7, 9, 0);
+ for (int c1 = 10; c1 <= 11; c1 += 1)
+ S8(7, c1, 0);
+ for (int c1 = -4; c1 < 0; c1 += 1)
+ S6(8, c1, 0);
+ S7(8, -1, 0);
+ S3(8, 0, 0);
+ S7(8, 0, 0);
+ S19(8, 1, -2);
+ S4(8, 1, -1);
+ S19(8, 1, -1);
+ S19(8, 1, 0);
+ S15(8, 1, 4);
+ S18(8, 1, 4);
+ for (int c2 = -4; c2 < -2; c2 += 1) {
+ S14(8, 2, c2);
+ S20(8, 2, c2);
+ }
+ S14(8, 2, -2);
+ S19(8, 2, -2);
+ S20(8, 2, -2);
+ S4(8, 2, -1);
+ S14(8, 2, -1);
+ S19(8, 2, -1);
+ S20(8, 2, -1);
+ S14(8, 2, 0);
+ S19(8, 2, 0);
+ S20(8, 2, 0);
+ S15(8, 2, 4);
+ S18(8, 2, 4);
+ for (int c2 = -4; c2 < -1; c2 += 1) {
+ S14(8, 3, c2);
+ S20(8, 3, c2);
+ }
+ S4(8, 3, -1);
+ S14(8, 3, -1);
+ S20(8, 3, -1);
+ S14(8, 3, 0);
+ S20(8, 3, 0);
+ S15(8, 3, 4);
+ S18(8, 3, 4);
+ for (int c2 = -4; c2 < -1; c2 += 1) {
+ S14(8, 4, c2);
+ S20(8, 4, c2);
+ }
+ S4(8, 4, -1);
+ S14(8, 4, -1);
+ S20(8, 4, -1);
+ S5(8, 4, 0);
+ S9(8, 4, 0);
+ S10(8, 4, 0);
+ S14(8, 4, 0);
+ S20(8, 4, 0);
+ S23(8, 4, 0);
+ S13(8, 4, 1);
+ S21(8, 4, 1);
+ S23(8, 4, 1);
+ S24(8, 4, 1);
+ S13(8, 4, 2);
+ S16(8, 4, 2);
+ S17(8, 4, 2);
+ S24(8, 4, 2);
+ S13(8, 4, 3);
+ S24(8, 4, 3);
+ S13(8, 4, 4);
+ S15(8, 4, 4);
+ S23(8, 5, 0);
+ S11(8, 5, 1);
+ S21(8, 5, 1);
+ S22(8, 5, 1);
+ S23(8, 5, 1);
+ S24(8, 5, 1);
+ S11(8, 5, 2);
+ S16(8, 5, 2);
+ S17(8, 5, 2);
+ S24(8, 5, 2);
+ S11(8, 5, 3);
+ S24(8, 5, 3);
+ S11(8, 5, 4);
+ S15(8, 5, 4);
+ S23(8, 6, 0);
+ S12(8, 6, 1);
+ S21(8, 6, 1);
+ S22(8, 6, 1);
+ S23(8, 6, 1);
+ S24(8, 6, 1);
+ S12(8, 6, 2);
+ S16(8, 6, 2);
+ S17(8, 6, 2);
+ S24(8, 6, 2);
+ S12(8, 6, 3);
+ S24(8, 6, 3);
+ S12(8, 6, 4);
+ for (int c1 = 7; c1 <= 8; c1 += 1) {
+ S23(8, c1, 0);
+ S21(8, c1, 1);
+ S22(8, c1, 1);
+ S23(8, c1, 1);
+ for (int c2 = 1; c2 <= 3; c2 += 1)
+ S24(8, c1, c2);
+ }
+ S22(8, 9, 1);
+ S7(9, 0, 0);
+ for (int c1 = 1; c1 <= 2; c1 += 1) {
+ for (int c2 = -1; c2 <= 0; c2 += 1)
+ S19(9, c1, c2);
+ for (int c2 = 4; c2 <= 5; c2 += 1) {
+ S15(9, c1, c2);
+ S18(9, c1, c2);
+ }
+ }
+ S20(9, 3, -4);
+ for (int c2 = -3; c2 < -1; c2 += 1) {
+ S14(9, 3, c2);
+ S20(9, 3, c2);
+ }
+ for (int c2 = -1; c2 <= 0; c2 += 1) {
+ S14(9, 3, c2);
+ S19(9, 3, c2);
+ S20(9, 3, c2);
+ }
+ for (int c2 = 4; c2 <= 5; c2 += 1) {
+ S15(9, 3, c2);
+ S18(9, 3, c2);
+ }
+ S20(9, 4, -4);
+ for (int c2 = -3; c2 < 0; c2 += 1) {
+ S14(9, 4, c2);
+ S20(9, 4, c2);
+ }
+ S9(9, 4, 0);
+ S10(9, 4, 0);
+ S14(9, 4, 0);
+ S20(9, 4, 0);
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S23(9, 4, c2);
+ S13(9, 4, 2);
+ S21(9, 4, 2);
+ S23(9, 4, 2);
+ S24(9, 4, 2);
+ S13(9, 4, 3);
+ S16(9, 4, 3);
+ S17(9, 4, 3);
+ S24(9, 4, 3);
+ S13(9, 4, 4);
+ for (int c2 = 4; c2 <= 5; c2 += 1) {
+ S15(9, 4, c2);
+ S18(9, 4, c2);
+ }
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S23(9, 5, c2);
+ S13(9, 5, 2);
+ S21(9, 5, 2);
+ S22(9, 5, 2);
+ S23(9, 5, 2);
+ S24(9, 5, 2);
+ S13(9, 5, 3);
+ S16(9, 5, 3);
+ S17(9, 5, 3);
+ S24(9, 5, 3);
+ S13(9, 5, 4);
+ for (int c2 = 4; c2 <= 5; c2 += 1)
+ S15(9, 5, c2);
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S23(9, 6, c2);
+ S11(9, 6, 2);
+ S21(9, 6, 2);
+ S22(9, 6, 2);
+ S23(9, 6, 2);
+ S24(9, 6, 2);
+ S11(9, 6, 3);
+ S16(9, 6, 3);
+ S17(9, 6, 3);
+ S24(9, 6, 3);
+ S11(9, 6, 4);
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S23(9, 7, c2);
+ S12(9, 7, 2);
+ S21(9, 7, 2);
+ S22(9, 7, 2);
+ S23(9, 7, 2);
+ S24(9, 7, 2);
+ S12(9, 7, 3);
+ S16(9, 7, 3);
+ S17(9, 7, 3);
+ S24(9, 7, 3);
+ S12(9, 7, 4);
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S23(9, 8, c2);
+ S21(9, 8, 2);
+ S22(9, 8, 2);
+ S23(9, 8, 2);
+ for (int c2 = 2; c2 <= 3; c2 += 1)
+ S24(9, 8, c2);
+ S22(9, 9, 2);
+ for (int c1 = 1; c1 <= 3; c1 += 1) {
+ S19(10, c1, 0);
+ S26(10, c1, 3);
+ S15(10, c1, 4);
+ S18(10, c1, 4);
+ S25(10, c1, 4);
+ for (int c2 = 5; c2 <= 6; c2 += 1) {
+ S15(10, c1, c2);
+ S18(10, c1, c2);
+ }
+ }
+ for (int c2 = -4; c2 < -2; c2 += 1)
+ S20(10, 4, c2);
+ for (int c2 = -2; c2 < 0; c2 += 1) {
+ S14(10, 4, c2);
+ S20(10, 4, c2);
+ }
+ S9(10, 4, 0);
+ S10(10, 4, 0);
+ S14(10, 4, 0);
+ S19(10, 4, 0);
+ S20(10, 4, 0);
+ S13(10, 4, 3);
+ S21(10, 4, 3);
+ S24(10, 4, 3);
+ S26(10, 4, 3);
+ S13(10, 4, 4);
+ S15(10, 4, 4);
+ S16(10, 4, 4);
+ S17(10, 4, 4);
+ S18(10, 4, 4);
+ S25(10, 4, 4);
+ for (int c2 = 5; c2 <= 6; c2 += 1) {
+ S15(10, 4, c2);
+ S18(10, 4, c2);
+ }
+ S13(10, 5, 3);
+ S21(10, 5, 3);
+ S22(10, 5, 3);
+ S24(10, 5, 3);
+ S26(10, 5, 3);
+ S13(10, 5, 4);
+ S15(10, 5, 4);
+ S16(10, 5, 4);
+ S17(10, 5, 4);
+ S18(10, 5, 4);
+ S25(10, 5, 4);
+ for (int c2 = 5; c2 <= 6; c2 += 1) {
+ S15(10, 5, c2);
+ S18(10, 5, c2);
+ }
+ S13(10, 6, 3);
+ S21(10, 6, 3);
+ S22(10, 6, 3);
+ S24(10, 6, 3);
+ S13(10, 6, 4);
+ S16(10, 6, 4);
+ S17(10, 6, 4);
+ S11(10, 7, 3);
+ S21(10, 7, 3);
+ S22(10, 7, 3);
+ S24(10, 7, 3);
+ S11(10, 7, 4);
+ S16(10, 7, 4);
+ S17(10, 7, 4);
+ S12(10, 8, 3);
+ S21(10, 8, 3);
+ S22(10, 8, 3);
+ S24(10, 8, 3);
+ S12(10, 8, 4);
+ S16(10, 8, 4);
+ S17(10, 8, 4);
+ S22(10, 9, 3);
+ for (int c0 = 11; c0 <= 14; c0 += 1)
+ for (int c1 = 1; c1 <= 5; c1 += 1) {
+ S26(c0, c1, 3);
+ S25(c0, c1, 4);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.in b/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.in
new file mode 100644
index 00000000000..feb8f0898bb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/usvd_e_t.in
@@ -0,0 +1,3 @@
+{ S19[i0, i1, i2] -> [i0, i1, i2, 18] : i0 >= 8 and i1 >= 1 and i2 <= 0 and i2 >= -10 + i0 and i1 <= -6 + i0; S21[i0, i1, -7 + i0] -> [i0, i1, -7 + i0, 20] : i0 <= 10 and i1 >= 4 and i1 <= 8 and i0 >= 7; S17[i0, i1, -6 + i0] -> [i0, i1, -6 + i0, 16] : i0 >= 7 and i1 >= 4 and i0 <= 10 and i1 <= -2 + i0; S4[i0, i1, -1] -> [i0, i1, -1, 3] : i0 <= 8 and i1 >= 1 and i1 <= -4 + i0; S1[i0, 0, 0] -> [i0, 0, 0, 0] : i0 >= 0 and i0 <= 4; S10[i0, 4, 0] -> [i0, 4, 0, 9] : i0 >= 7 and i0 <= 10; S16[i0, i1, -6 + i0] -> [i0, i1, -6 + i0, 15] : i0 <= 10 and i1 >= 4 and i0 >= 7 and i1 <= -2 + i0; S24[i0, i1, i2] -> [i0, i1, i2, 23] : i0 >= 8 and i1 >= 4 and i1 <= 8 and i2 <= 3 and i2 >= -7 + i0; S23[i0, i1, i2] -> [i0, i1, i2, 22] : i0 <= 9 and i1 >= 4 and i1 <= 8 and i2 >= 0 and i2 <= -7 + i0; S7[i0, i1, 0] -> [i0, i1, 0, 6] : i0 >= 5 and i1 <= 0 and i1 >= -9 + i0; S25[i0, i1, 4] -> [i0, i1, 4, 24] : i0 >= 10 and i0 <= 14 and i1 >= 1 and i1 <= 5; S18[i0, i1, i2] -> [i0, i1, i2, 17] : i0 <= 10 and i1 >= 1 and i2 >= 4 and i2 <= -4 + i0 and i1 <= -5 + i0; S14[i0, i1, i2] -> [i0, i1, i2, 13] : i0 >= 8 and i1 <= 4 and i2 <= 0 and i2 >= -12 + i0 and i1 >= -6 + i0; S6[i0, i1, 0] -> [i0, i1, 0, 5] : i0 <= 8 and i1 >= -4 and i1 <= -9 + i0; S8[i0, i1, 0] -> [i0, i1, 0, 7] : i0 >= 3 and i0 <= 7 and i1 >= 7 and i1 <= 11; S15[i0, i1, i2] -> [i0, i1, i2, 14] : i0 <= 10 and i1 >= 1 and i1 <= 5 and i2 >= 4 and i2 <= -4 + i0; S11[i0, -3 + i0, i2] -> [i0, -3 + i0, i2, 10] : i0 <= 10 and i0 >= 7 and i2 <= 4 and i2 >= -7 + i0; S20[i0, i1, i2] -> [i0, i1, i2, 19] : i0 >= 8 and i1 <= 4 and i2 >= -4 and i2 <= 0 and i1 >= -6 + i0; S12[i0, -2 + i0, i2] -> [i0, -2 + i0, i2, 11] : i0 >= 7 and i0 <= 10 and i2 <= 4 and i2 >= -7 + i0; S9[i0, 4, 0] -> [i0, 4, 0, 8] : i0 >= 7 and i0 <= 10; S22[i0, i1, -7 + i0] -> [i0, i1, -7 + i0, 21] : i0 >= 7 and i1 >= 5 and i1 <= 9 and i0 <= 10; S13[i0, i1, i2] -> [i0, i1, i2, 12] : i0 <= 10 and i1 >= 4 and i2 <= 4 and i2 >= -7 + i0 and i1 <= -4 + i0; S26[i0, i1, 3] -> [i0, i1, 3, 25] : i0 >= 10 and i0 <= 14 and i1 >= 1 and i1 <= 5; S3[i0, 0, 0] -> [i0, 0, 0, 2] : i0 >= 4 and i0 <= 8; S5[i0, i1, 0] -> [i0, i1, 0, 4] : i0 >= 4 and i1 <= 4 and i1 >= -4 + i0; S2[i0, i1, 0] -> [i0, i1, 0, 1] : i0 >= 0 and i0 <= 4 and i1 >= 0 and i1 <= 4 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.c b/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.c
new file mode 100644
index 00000000000..c6d32ca637b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.c
@@ -0,0 +1,23 @@
+{
+ S1();
+ S2();
+ for (int c1 = 0; c1 < N; c1 += 1)
+ for (int c3 = 0; c3 < N; c3 += 1) {
+ S4(c1, c3);
+ S5(c1, c3);
+ }
+ for (int c1 = 0; c1 < N; c1 += 1)
+ for (int c3 = 0; c3 < N; c3 += 1)
+ for (int c5 = 0; c5 <= (N - 1) / 32; c5 += 1) {
+ S7(c1, c3, c5, 32 * c5);
+ for (int c7 = 32 * c5 + 1; c7 <= min(N - 1, 32 * c5 + 31); c7 += 1) {
+ S6(c1, c3, c5, c7 - 1);
+ S7(c1, c3, c5, c7);
+ }
+ if (32 * c5 + 31 >= N) {
+ S6(c1, c3, c5, N - 1);
+ } else
+ S6(c1, c3, c5, 32 * c5 + 31);
+ }
+ S8();
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.in b/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.in
new file mode 100644
index 00000000000..a9b9860fd2b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vasilache.in
@@ -0,0 +1,3 @@
+[M, N] -> { S4[i0, i1] -> [3, i0, 0, i1, 0, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S1[] -> [0, 0, 0, 0, 0, 0, 0, 0, 0]; S6[i0, i1, i2, i3] -> [4, i0, 0, i1, 0, i2, 0, 1 + i3, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N and i3 >= 0 and i3 <= -1 + N and i3 >= 32i2 and i3 <= 31 + 32i2; S7[i0, i1, i2, i3] -> [4, i0, 0, i1, 0, i2, 0, i3, 1] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N and i3 >= 0 and i3 <= -1 + N and i3 >= 32i2 and i3 <= 31 + 32i2; S5[i0, i1] -> [3, i0, 0, i1, 1, 0, 0, 0, 0] : i0 >= 0 and i0 <= -1 + N and i1 >= 0 and i1 <= -1 + N; S2[] -> [1, 0, 0, 0, 0, 0, 0, 0, 0]; S8[] -> [5, 0, 0, 0, 0, 0, 0, 0, 0]; S3[] -> [2, 0, 0, 0, 0, 0, 0, 0, 0] : M >= 79 }
+[M, N] -> { : M <= 3 and N >= 100 }
+[M, N] -> { [i, j, k, l, m, n, o, p, q] -> separate[x] : x >= 7 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.c b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.c
new file mode 100644
index 00000000000..ce38c10e833
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.c
@@ -0,0 +1,85 @@
+{
+ for (int c0 = -27 * n + 2; c0 <= 1; c0 += 1)
+ S1(c0 - 1);
+ for (int c0 = 2; c0 <= min(2 * n, n + 29); c0 += 1) {
+ if (c0 >= 3) {
+ if (2 * n >= c0 + 1) {
+ S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+ if (c0 + 2 >= 2 * n) {
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ } else if (c0 >= 5) {
+ S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+ for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
+ S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+ }
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (2 * n >= c0 + 3 && c0 >= n + 2) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ }
+ if (c0 >= n + 3 && 2 * n >= c0 + 1) {
+ S6(-n + c0, n);
+ } else {
+ if (c0 >= 5 && n + 1 >= c0) {
+ S6(2, c0 - 2);
+ S1(c0 - 1);
+ } else if (n + 1 >= c0 && c0 <= 4)
+ S1(c0 - 1);
+ if (n + 1 >= c0) {
+ S6(1, c0 - 1);
+ } else if (n >= 3 && c0 == n + 2) {
+ S6(2, n);
+ S1(n + 1);
+ }
+ }
+ if (c0 >= n + 3)
+ S1(c0 - 1);
+ if (n == 2 && c0 == 4)
+ S1(3);
+ } else
+ S1(1);
+ if (c0 % 2 == 0)
+ S3(c0 / 2);
+ for (int c1 = max(1, -n + c0); c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0 - c1, c1);
+ }
+ for (int c0 = max(2 * n + 1, -27 * n + 2); c0 <= n + 29; c0 += 1)
+ S1(c0 - 1);
+ for (int c0 = n + 30; c0 <= 2 * n; c0 += 1) {
+ if (2 * n >= c0 + 1) {
+ S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+ if (c0 + 2 >= 2 * n) {
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ } else {
+ S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+ for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
+ S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= n - c0; c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (2 * n >= c0 + 3) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ }
+ S6(-n + c0, n);
+ }
+ if (c0 % 2 == 0)
+ S3(c0 / 2);
+ for (int c1 = -n + c0; c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0 - c1, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.in b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.in
new file mode 100644
index 00000000000..b591ef35976
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien.in
@@ -0,0 +1,3 @@
+[n] -> { S6[i0, i1] -> [2i0 + 2i1, 2 - i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S2[i0, i1] -> [1 + 2i0 + 2i1, i1, 0] : 29i1 >= 1 - i0 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S1[i0] -> [2 + 2i0, 0, 0] : i0 >= 1 - 27n and i0 <= 28 + n; S4[i0, i1] -> [2i0 + 2i1, -i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [1 + 4i0, 0, 0] : i0 >= 1 and i0 <= n; S5[i0, i1, i2] -> [2i0 + 2i1, 1 - i0, i2] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> { : }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.c
new file mode 100644
index 00000000000..7fe52ff319b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.c
@@ -0,0 +1,77 @@
+{
+ for (int c0 = -27 * n + 2; c0 <= 1; c0 += 1)
+ S1(c0 - 1);
+ for (int c0 = 2; c0 <= n + 29; c0 += 1) {
+ if (c0 >= 3) {
+ S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+ if (c0 >= 5 && 2 * n >= c0 + 3) {
+ S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+ for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
+ S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (2 * n >= c0 + 3 && c0 >= n + 2) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ } else if (c0 + 2 >= 2 * n)
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ if (c0 >= n + 3) {
+ S6(-n + c0, n);
+ S1(c0 - 1);
+ } else {
+ if (c0 >= 5 && n + 1 >= c0) {
+ S6(2, c0 - 2);
+ S1(c0 - 1);
+ } else if (c0 <= 4)
+ S1(c0 - 1);
+ if (n + 1 >= c0) {
+ S6(1, c0 - 1);
+ } else {
+ S6(2, n);
+ S1(n + 1);
+ }
+ }
+ } else
+ S1(1);
+ if (c0 % 2 == 0)
+ S3(c0 / 2);
+ for (int c1 = max(1, -n + c0); c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0 - c1, c1);
+ }
+ for (int c0 = n + 30; c0 <= 2 * n; c0 += 1) {
+ if (2 * n >= c0 + 1) {
+ S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+ if (c0 + 2 >= 2 * n) {
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ } else {
+ S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+ for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
+ S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= n - c0; c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (2 * n >= c0 + 3) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ }
+ S6(-n + c0, n);
+ }
+ if (c0 % 2 == 0)
+ S3(c0 / 2);
+ for (int c1 = -n + c0; c1 < (c0 + 1) / 2; c1 += 1)
+ S2(c0 - c1, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.in
new file mode 100644
index 00000000000..d8b1b1a007b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/vivien2.in
@@ -0,0 +1,3 @@
+[n] -> { S6[i0, i1] -> [2i0 + 2i1, 2 - i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S2[i0, i1] -> [1 + 2i0 + 2i1, i1, 0] : 29i1 >= 1 - i0 and i0 <= n and i1 >= 1 and i1 <= -1 + i0; S1[i0] -> [2 + 2i0, 0, 0] : i0 >= 1 - 27n and i0 <= 28 + n; S4[i0, i1] -> [2i0 + 2i1, -i0, 0] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n; S3[i0] -> [1 + 4i0, 0, 0] : i0 >= 1 and i0 <= n; S5[i0, i1, i2] -> [2i0 + 2i1, 1 - i0, i2] : i0 >= 1 and i0 <= n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 and i2 <= -1 + i0 }
+[n] -> { : n >= 30 }
+[n] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters.c b/polly/lib/External/isl/test_inputs/codegen/cloog/walters.c
new file mode 100644
index 00000000000..2c1bd93858b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters.c
@@ -0,0 +1,15 @@
+{
+ S2(1, 0, 1, 0);
+ S4(1, 0, 1, 0);
+ S3(2, 0, 1, 1);
+ S4(2, 0, 1, 1);
+ for (int c0 = 3; c0 <= 10; c0 += 1) {
+ if (c0 % 3 == 0) {
+ S1(c0, c0 / 3, c0 / 3, c0 / 3);
+ } else if ((c0 - 1) % 3 == 0) {
+ S2(c0, (c0 - 1) / 3, (c0 + 2) / 3, (c0 - 1) / 3);
+ } else
+ S3(c0, (c0 - 2) / 3, (c0 + 1) / 3, (c0 + 1) / 3);
+ S4(c0, c0 / 3, (c0 - 1) / 3 + 1, c0 - (c0 - 1) / 3 - c0 / 3 - 1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters.in b/polly/lib/External/isl/test_inputs/codegen/cloog/walters.in
new file mode 100644
index 00000000000..6e2645147e6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters.in
@@ -0,0 +1,3 @@
+{ S2[i, div36, div37, div38] -> [i, div36, k, div38, 1] : 3div37 = 2 + i and 3k = 2 + i and i >= 1 and i <= 10 and 3div36 >= -2 + i and 3div38 <= 1 + i and 3div38 >= -1 + i and 3div36 <= i; S1[i, div36, div37, div38] -> [i, j, div37, div38, 0] : 3j = i and 3div36 = i and i >= 3 and i <= 10 and 3div37 >= i and 3div38 <= 1 + i and 3div37 <= 2 + i and 3div38 >= -1 + i; S3[i, div36, div37, div38] -> [i, div36, div37, l, 2] : 3l = 1 + i and 3div38 = 1 + i and i <= 10 and i >= 2 and 3div36 >= -2 + i and 3div37 <= 2 + i and 3div36 <= i and 3div37 >= i; S4[i, div36, div37, div38] -> [i, div36, div37, div38, 3] : i >= 1 and i <= 10 and 3div36 <= i and 3div36 >= -2 + i and 3div37 <= 2 + i and 3div37 >= i and 3div38 <= 1 + i and 3div38 >= -1 + i }
+{ : }
+{ [i, j, k, l, m] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.c
new file mode 100644
index 00000000000..27565fbde9a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.c
@@ -0,0 +1,12 @@
+{
+ for (int c1 = 0; c1 <= 51; c1 += 1)
+ S2(0, c1);
+ for (int c0 = 1; c0 <= 24; c0 += 1) {
+ S2(c0, 0);
+ for (int c1 = 1; c1 <= 50; c1 += 1)
+ S1(c0, c1);
+ S2(c0, 51);
+ }
+ for (int c1 = 0; c1 <= 51; c1 += 1)
+ S2(25, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.in
new file mode 100644
index 00000000000..ea01a10a336
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters2.in
@@ -0,0 +1,3 @@
+{ S1[j, i] -> [j, i, 0] : j >= 1 and j <= 24 and i >= 1 and i <= 50; S2[j, 51] -> [j, 51, 1] : j >= 1 and j <= 24; S2[25, i] -> [25, i, 1] : i >= 1 and i <= 51; S2[0, i] -> [0, i, 1] : i >= 0 and i <= 51; S2[j, 0] -> [j, 0, 1] : j >= 1 and j <= 25 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.c b/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.c
new file mode 100644
index 00000000000..bafb9acbc8e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.c
@@ -0,0 +1,7 @@
+{
+ for (int c0 = 2; c0 <= 8; c0 += 2) {
+ S1(c0, c0 / 2, c0 / 2);
+ S2(c0, c0 / 2, c0 / 2);
+ }
+ S2(10, 5, 5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.in b/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.in
new file mode 100644
index 00000000000..802bd4f0435
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/walters3.in
@@ -0,0 +1,3 @@
+{ S2[j, a, b] -> [j, j', b, 1] : 2a = j and 2j' = j and j >= 1 and j <= 10 and 2b <= j and 2b >= -1 + j; S1[j, a, b] -> [j, j', k, 0] : 2a = j and 2j' = j and 2k = j and 2b = j and j <= 8 and j >= 2 }
+{ : }
+{ [i, j, k, l] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.c b/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.c
new file mode 100644
index 00000000000..7db0788fc68
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= n + m; c0 += 1)
+ for (int c1 = max(1, -m + c0); c1 <= min(n, c0 - 1); c1 += 1)
+ S1(c1, c0 - c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.in b/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.in
new file mode 100644
index 00000000000..61618c37a45
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/wavefront.in
@@ -0,0 +1,3 @@
+[n, m] -> { S1[i0, i1] -> [i0 + i1, i0] : i0 >= 1 and i0 <= n and i1 >= 1 and i1 <= m }
+[n, m] -> { : }
+[n, m] -> { [i, j] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.c b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.c
new file mode 100644
index 00000000000..1c20057bd1b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.c
@@ -0,0 +1,12 @@
+{
+ for (int c0 = 1; c0 < n; c0 += 1) {
+ for (int c2 = c0 + 1; c2 <= n; c2 += 1)
+ S1(c0, c2);
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ for (int c2 = c1 + 1; c2 <= n; c2 += 1)
+ S2(c1, c2, c0);
+ }
+ for (int c1 = 1; c1 < n; c1 += 1)
+ for (int c2 = c1 + 1; c2 <= n; c2 += 1)
+ S2(c1, c2, n);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.in b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.in
new file mode 100644
index 00000000000..dcc93e5a69e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr.in
@@ -0,0 +1,3 @@
+[n] -> { S2[i0, i1, i2] -> [i2] : i0 >= 1 and i0 <= -1 + n and i1 >= 1 + i0 and i1 <= n and i2 >= 1 + i0 and i2 <= n; S1[i0, i1] -> [i0] : i0 >= 1 and i0 <= -1 + n and i1 >= 1 + i0 and i1 <= n }
+[n] -> { : }
+[n] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.c b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.c
new file mode 100644
index 00000000000..a52909ccd45
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.c
@@ -0,0 +1,13 @@
+{
+ for (int c1 = 1; c1 <= M; c1 += 1)
+ S2(c1);
+ for (int c0 = 2; c0 <= M; c0 += 1) {
+ for (int c2 = c0 + 1; c2 <= M; c2 += 1)
+ for (int c3 = 1; c3 < c0; c3 += 1)
+ S3(c0, c2, c3);
+ for (int c1 = 1; c1 < c0; c1 += 1)
+ S4(c1, c0);
+ for (int c2 = 1; c2 < c0; c2 += 1)
+ S1(c0, c2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.in b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.in
new file mode 100644
index 00000000000..a07e1492b1c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/yosr2.in
@@ -0,0 +1,3 @@
+[M] -> { S3[i0, i1, i2] -> [i0] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M and i2 >= 1 and i2 <= -1 + i0; S4[i0, i1] -> [i1] : i0 >= 1 and i0 <= M and i1 >= 1 + i0 and i1 <= M; S1[i0, i1] -> [i0] : i0 >= 1 and i0 <= M and i1 >= 1 and i1 <= -1 + i0; S2[i0] -> [0] : i0 >= 1 and i0 <= M }
+[M] -> { : M >= 2 }
+[M] -> { [i] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.c b/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.c
new file mode 100644
index 00000000000..1bc7ffd0524
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.c
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 5; c0 += 1) {
+ S1(c0, c0);
+ for (int c1 = c0; c1 <= 5; c1 += 1)
+ S2(c0, c1);
+ S3(c0, 5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.in b/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.in
new file mode 100644
index 00000000000..5164abe2874
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/youcef.in
@@ -0,0 +1,3 @@
+{ S1[i0, i0] -> [i0, i0, 0] : i0 >= 0 and i0 <= 5; S2[i0, i1] -> [i0, i1, 1] : i0 >= 0 and i0 <= 5 and i1 >= i0 and i1 <= 5; S3[i0, 5] -> [i0, 5, 2] : i0 >= 0 and i0 <= 5 }
+{ : }
+{ [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.c b/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.c
new file mode 100644
index 00000000000..1107790b201
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.c
@@ -0,0 +1,10 @@
+{
+ for (int c0 = 1; c0 <= n; c0 += 1) {
+ S1(c0, c0);
+ for (int c1 = c0; c1 <= n; c1 += 1)
+ S2(c0, c1);
+ S3(c0, n);
+ }
+ for (int c0 = n + 1; c0 <= m; c0 += 1)
+ S3(c0, n);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.in b/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.in
new file mode 100644
index 00000000000..b21e30d7fa7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/cloog/youcefn.in
@@ -0,0 +1,3 @@
+[n, m] -> { S3[i0, n] -> [i0, n, 2] : i0 >= 1 and i0 <= m; S2[i0, i1] -> [i0, i1, 1] : i0 >= 1 and i0 <= n and i1 >= i0 and i1 <= n; S1[i0, i0] -> [i0, i0, 0] : i0 >= 1 and i0 <= n }
+[n, m] -> { : n >= 2 and m >= n }
+[n, m] -> { [i, j, k] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/disjuncts.c b/polly/lib/External/isl/test_inputs/codegen/disjuncts.c
new file mode 100644
index 00000000000..207e3377835
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/disjuncts.c
@@ -0,0 +1,10 @@
+for (int c0 = 0; c0 <= n; c0 += 1)
+ for (int c1 = 0; c1 <= n; c1 += 1)
+ if (c1 == n || c0 == n || c1 == 0 || c0 == 0) {
+ for (int c3 = 0; c3 <= n; c3 += 1)
+ for (int c4 = 0; c4 <= n; c4 += 1)
+ a(c0, c1, c3, c4);
+ for (int c3 = 0; c3 <= n; c3 += 1)
+ for (int c4 = 0; c4 <= n; c4 += 1)
+ b(c0, c1, c3, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/disjuncts.in b/polly/lib/External/isl/test_inputs/codegen/disjuncts.in
new file mode 100644
index 00000000000..01386701c69
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/disjuncts.in
@@ -0,0 +1,7 @@
+# Check that conditions are hoisted up from the innermost loop
+[n] -> { a[i,j,k,l] -> [i,j,0,k,l] :
+ 0 <= i,j,k,l <= n and (i = 0 or j = 0 or i = n or j = n);
+ b[i,j,k,l] -> [i,j,1,k,l] :
+ 0 <= i,j,k,l <= n and (i = 0 or j = 0 or i = n or j = n) }
+{ : }
+{ [i,j,t,k,l] -> atomic[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/dwt.c b/polly/lib/External/isl/test_inputs/codegen/dwt.c
new file mode 100644
index 00000000000..52adb5d6e0d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/dwt.c
@@ -0,0 +1,8 @@
+for (int c0 = 0; c0 < Ncl; c0 += 1) {
+ if (Ncl >= c0 + 2 && c0 >= 1) {
+ S(c0, 28);
+ } else if (c0 == 0) {
+ S(0, 26);
+ } else
+ S(Ncl - 1, 27);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/dwt.in b/polly/lib/External/isl/test_inputs/codegen/dwt.in
new file mode 100644
index 00000000000..424b0f3fd09
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/dwt.in
@@ -0,0 +1,3 @@
+[Ncl] -> { S[j, 28] -> [j] : j <= -2 + Ncl and Ncl <= 256 and Ncl >= 40 and j >= 1; S[0, 26] -> [0] : Ncl <= 256 and Ncl >= 40; S[-1 + Ncl, 27] -> [-1 + Ncl] : Ncl <= 256 and Ncl >= 40 }
+[Ncl] -> { : Ncl >= 40 and Ncl <= 256 }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/empty.c b/polly/lib/External/isl/test_inputs/codegen/empty.c
new file mode 100644
index 00000000000..58f7b7b295b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/empty.c
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 10; c0 += 1) {
+ S0(c0);
+ if (c0 == 5)
+ S2();
+ S1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/empty.in b/polly/lib/External/isl/test_inputs/codegen/empty.in
new file mode 100644
index 00000000000..17febea4be6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/empty.in
@@ -0,0 +1,5 @@
+# Earlier versions of isl would end up with an empty partial
+# executed relation and fail to detect this emptiness.
+[M] -> { S0[i] -> [i, -M] : 0 <= i <= 10; S1[i] -> [i, 0] : 0 <= i <= 10; S2[] -> [5, 0] }
+[M] -> { : M >= 1 }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/hoist.c b/polly/lib/External/isl/test_inputs/codegen/hoist.c
new file mode 100644
index 00000000000..7ba854f8e2f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/hoist.c
@@ -0,0 +1,45 @@
+if (ni >= t0 + 1 && nj >= t1 + 1)
+ for (int c2 = 0; c2 <= min(15, nk - 1); c2 += 1) {
+ S_1(t0, t1, c2);
+ if (nj >= t1 + 17) {
+ S_1(t0, t1 + 16, c2);
+ if (nj >= t1 + 33) {
+ S_1(t0, t1 + 32, c2);
+ if (nj >= t1 + 49)
+ S_1(t0, t1 + 48, c2);
+ }
+ }
+ if (ni >= t0 + 17) {
+ S_1(t0 + 16, t1, c2);
+ if (nj >= t1 + 17) {
+ S_1(t0 + 16, t1 + 16, c2);
+ if (nj >= t1 + 33) {
+ S_1(t0 + 16, t1 + 32, c2);
+ if (nj >= t1 + 49)
+ S_1(t0 + 16, t1 + 48, c2);
+ }
+ }
+ if (ni >= t0 + 33) {
+ S_1(t0 + 32, t1, c2);
+ if (nj >= t1 + 17) {
+ S_1(t0 + 32, t1 + 16, c2);
+ if (nj >= t1 + 33) {
+ S_1(t0 + 32, t1 + 32, c2);
+ if (nj >= t1 + 49)
+ S_1(t0 + 32, t1 + 48, c2);
+ }
+ }
+ if (ni >= t0 + 49) {
+ S_1(t0 + 48, t1, c2);
+ if (nj >= t1 + 17) {
+ S_1(t0 + 48, t1 + 16, c2);
+ if (nj >= t1 + 33) {
+ S_1(t0 + 48, t1 + 32, c2);
+ if (nj >= t1 + 49)
+ S_1(t0 + 48, t1 + 48, c2);
+ }
+ }
+ }
+ }
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/hoist.in b/polly/lib/External/isl/test_inputs/codegen/hoist.in
new file mode 100644
index 00000000000..80a905200e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/hoist.in
@@ -0,0 +1,10 @@
+# check that the shared conditions ni >= t0 + 1 and nj >= t1 + 1
+# are hoisted out of the loop
+[ni, nj, nk, t0, t1] -> { S_1[i, j, k] -> [t0, t1, k, i, j] :
+ exists (e0 = [(-t0 + i)/16], e1 = [(-t1 + j)/16]:
+ 16e0 = -t0 + i and 16e1 = -t1 + j and k >= 0 and j >= 0 and
+ j <= -1 + nj and i >= 0 and i <= -1 + ni and k <= -1 + nk and
+ ni >= 1 and nj >= 1 and nk >= 1 and j <= 63 and t1 >= 0 and
+ i <= 63 and k <= 15 and t0 >= 0 and t1 <= 15 and t0 <= 15) }
+[t0, t1] -> { : 0 <= t0, t1 <= 15 }
+{ [t0, t1, i5, i6, i7] -> unroll[x] : x >= 3}
diff --git a/polly/lib/External/isl/test_inputs/codegen/hoist2.c b/polly/lib/External/isl/test_inputs/codegen/hoist2.c
new file mode 100644
index 00000000000..24cfc639166
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/hoist2.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 5; c0 += 1)
+ for (int c1 = t1 - 64 * b + 64; c1 <= min(70, -((c0 - 1) % 2) - c0 + 73); c1 += 64)
+ A(c0, 64 * b + c1 - 8);
diff --git a/polly/lib/External/isl/test_inputs/codegen/hoist2.in b/polly/lib/External/isl/test_inputs/codegen/hoist2.in
new file mode 100644
index 00000000000..6a29a026f20
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/hoist2.in
@@ -0,0 +1,5 @@
+# Check that the constraints hoisted from the inner loop
+# do not end up involving the inner loop iterator.
+[t1, b] -> { A[i1, i2] -> [i1, 8 - 64b + i2] : exists (e0, e1 = [(-8 + t1 - i2)/64]: 64e1 = -8 + t1 - i2 and i2 >= 1 and i2 <= 127 and 2e0 >= -3 + i1 and 2e0 >= -1 - i1 and 2e0 <= 8 - i1 and 2e0 <= 6 + i1 and 2e0 >= -65 - 64b + i2 and 2e0 >= -1 + 64b - i2 and e0 <= 1 and e0 >= 0 and 2e0 <= 62 + 64b - i2 and b <= 1 and b >= 0 and i1 >= 1 and i1 <= 2046 and t1 >= 5 and t1 <= 8) }
+[t1, b] -> { : b >= 0 and b <= 1 and t1 >= 5 and t1 <= 8 }
+[t1] -> { [i0, i1, i5, a] -> atomic[x]}
diff --git a/polly/lib/External/isl/test_inputs/codegen/lu.c b/polly/lib/External/isl/test_inputs/codegen/lu.c
new file mode 100644
index 00000000000..ecbb895d3ac
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/lu.c
@@ -0,0 +1,17 @@
+for (int c0 = 0; c0 < n - 1; c0 += 32)
+ for (int c1 = c0; c1 < n; c1 += 32)
+ for (int c2 = c0; c2 < n; c2 += 32) {
+ if (c1 >= c0 + 32) {
+ for (int c3 = c0; c3 <= min(c0 + 31, c2 + 30); c3 += 1)
+ for (int c4 = c1; c4 <= min(n - 1, c1 + 31); c4 += 1)
+ for (int c5 = max(c2, c3 + 1); c5 <= min(n - 1, c2 + 31); c5 += 1)
+ S_6(c3, c4, c5);
+ } else
+ for (int c3 = c0; c3 <= min(min(n - 2, c0 + 31), c2 + 30); c3 += 1) {
+ for (int c5 = max(c2, c3 + 1); c5 <= min(n - 1, c2 + 31); c5 += 1)
+ S_2(c3, c5);
+ for (int c4 = c3 + 1; c4 <= min(n - 1, c0 + 31); c4 += 1)
+ for (int c5 = max(c2, c3 + 1); c5 <= min(n - 1, c2 + 31); c5 += 1)
+ S_6(c3, c4, c5);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/lu.in b/polly/lib/External/isl/test_inputs/codegen/lu.in
new file mode 100644
index 00000000000..ea884f59d60
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/lu.in
@@ -0,0 +1,4 @@
+# Check that the stride of the second loop is properly detected
+[n] -> { S_2[k, j] -> [o0, o0, o2, k, k, j, 1] : exists (e0 = floor((o2)/32), e1 = floor((o0)/32): 32e0 = o2 and 32e1 = o0 and o0 <= k and o0 >= -31 + k and k >= 0 and j <= -1 + n and o2 <= j and o2 >= -31 + j and j >= 1 + k); S_6[k, i, j] -> [o0, o1, o2, k, i, j, 0] : exists (e0 = floor((o0)/32), e1 = floor((o1)/32), e2 = floor((o2)/32): 32e0 = o0 and 32e1 = o1 and 32e2 = o2 and o0 <= k and o0 >= -31 + k and o1 <= i and o1 >= -31 + i and o2 <= j and o2 >= -31 + j and k >= 0 and i >= 1 + k and j <= -1 + n and j >= 1 + k and i <= -1 + n) }
+{ : }
+{ [a,b,c,d,e,f,g] -> atomic[x] : x < 3; [a,b,c,d,e,f,g] -> separate[x] : x >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/mod.c b/polly/lib/External/isl/test_inputs/codegen/mod.c
new file mode 100644
index 00000000000..dcd8319f4ca
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/mod.c
@@ -0,0 +1,2 @@
+if (2 * (n % 100) == 3 * (m % 200))
+ A();
diff --git a/polly/lib/External/isl/test_inputs/codegen/mod.in b/polly/lib/External/isl/test_inputs/codegen/mod.in
new file mode 100644
index 00000000000..7a04c5a4158
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/mod.in
@@ -0,0 +1,4 @@
+# check that modulo constraint is generated correctly
+[n, m] -> { A[] -> [] : 2 * (n % 100) = 3 * (m % 200) }
+[n, m] -> { : m, n >= 0 }
+{}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/README b/polly/lib/External/isl/test_inputs/codegen/omega/README
new file mode 100644
index 00000000000..80e27fd462d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/README
@@ -0,0 +1,5 @@
+The tests in this directory have been adapted from the corresponding omega+
+test cases.
+The options have been derived semi-automatically and may not always
+correspond to the intended meaning of the specified "effort" in the omega+
+test cases.
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.c
new file mode 100644
index 00000000000..53995e9e89e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.c
@@ -0,0 +1,8 @@
+{
+ for (int c0 = 5; c0 <= 8; c0 += 1)
+ s0(c0);
+ for (int c0 = 10; c0 <= 16; c0 += 2)
+ s0(c0);
+ for (int c0 = 20; c0 <= 25; c0 += 1)
+ s0(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.in
new file mode 100644
index 00000000000..025da3d30d6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/basics-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : (In_1 >= 5 and In_1 <= 8) or (exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 10 and In_1 <= 16)) or (In_1 >= 20 and In_1 <= 25) }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.c
new file mode 100644
index 00000000000..d3d69704165
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.c
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+ for (int c1 = max(1, -c0 + 1); c1 <= min(10, -c0 + 10); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.in
new file mode 100644
index 00000000000..82e109311bc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/basics-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.c
new file mode 100644
index 00000000000..464ee493499
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.c
@@ -0,0 +1,9 @@
+{
+ for (int c1 = 2; c1 <= n; c1 += 1)
+ s0(c1);
+ for (int c1 = 1; c1 < n; c1 += 1) {
+ for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+ s1(c3, c1);
+ s2(c1 + 1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.in
new file mode 100644
index 00000000000..81fde503f74
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [0, i, 0, 0] : i >= 2 and i <= n; s1[i, j] -> [1, j, 0, i] : j >= 1 and j <= -1 + i and i <= n; s2[i] -> [1, -1 + i, 1, 0] : i >= 2 and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.c
new file mode 100644
index 00000000000..464ee493499
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.c
@@ -0,0 +1,9 @@
+{
+ for (int c1 = 2; c1 <= n; c1 += 1)
+ s0(c1);
+ for (int c1 = 1; c1 < n; c1 += 1) {
+ for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+ s1(c3, c1);
+ s2(c1 + 1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.in
new file mode 100644
index 00000000000..b5abf2917e8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/chosol-1.in
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [0, i, 0, 0] : i >= 2 and i <= n; s1[i, j] -> [1, j, 0, i] : j >= 1 and j <= -1 + i and i <= n; s2[i] -> [1, -1 + i, 1, 0] : i >= 2 and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.c
new file mode 100644
index 00000000000..6340134fcdb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= 8; c0 += 1)
+ for (int c1 = 0; c1 <= 7; c1 += 1) {
+ if (c0 >= 2 && c0 <= 6 && c1 <= 4)
+ s1(c0, c1);
+ if (c1 + 1 >= c0)
+ s0(c0, c1);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.in
new file mode 100644
index 00000000000..a3fa3b1652d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-0.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.c
new file mode 100644
index 00000000000..f4ec0e9c066
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.c
@@ -0,0 +1,15 @@
+for (int c0 = 1; c0 <= 8; c0 += 1) {
+ if (c0 >= 2) {
+ if (c0 <= 6)
+ for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+ s1(c0, c1);
+ for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+ s1(c0, c1);
+ s0(c0, c1);
+ }
+ for (int c1 = max(5, c0 - 1); c1 <= 7; c1 += 1)
+ s0(c0, c1);
+ } else
+ for (int c1 = 0; c1 <= 7; c1 += 1)
+ s0(1, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.in
new file mode 100644
index 00000000000..c6f7fa54a91
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-1.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.c
new file mode 100644
index 00000000000..f92e58368a5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.c
@@ -0,0 +1,17 @@
+{
+ for (int c1 = 0; c1 <= 7; c1 += 1)
+ s0(1, c1);
+ for (int c0 = 2; c0 <= 6; c0 += 1) {
+ for (int c1 = 0; c1 < c0 - 1; c1 += 1)
+ s1(c0, c1);
+ for (int c1 = c0 - 1; c1 <= 4; c1 += 1) {
+ s1(c0, c1);
+ s0(c0, c1);
+ }
+ for (int c1 = 5; c1 <= 7; c1 += 1)
+ s0(c0, c1);
+ }
+ for (int c0 = 7; c0 <= 8; c0 += 1)
+ for (int c1 = c0 - 1; c1 <= 7; c1 += 1)
+ s0(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.in
new file mode 100644
index 00000000000..03a7b5df3a3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/code_gen-2.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 6 and In_2 >= 0 and In_2 <= 4; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_2 >= -1 + In_1 and In_2 <= 7 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.c
new file mode 100644
index 00000000000..413fbda482f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.c
@@ -0,0 +1,16 @@
+{
+ for (int c4 = 1; c4 <= n; c4 += 1)
+ s2(c4);
+ for (int c1 = 1; c1 < n; c1 += 1) {
+ for (int c4 = 0; c4 < n - c1; c4 += 1)
+ s0(c1, n - c4);
+ for (int c3 = 0; c3 < n - c1; c3 += 1)
+ for (int c4 = c1 + 1; c4 <= n; c4 += 1)
+ s1(c1, n - c3, c4);
+ }
+ for (int c1 = 1; c1 <= n; c1 += 1) {
+ s4(c1);
+ for (int c3 = c1 + 1; c3 <= n; c3 += 1)
+ s3(c3, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.in
new file mode 100644
index 00000000000..d803da7574c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/collard-0.in
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [1, i, 1, n - j, k] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s2[i] -> [0, 0, 0, 0, i] : i >= 1 and i <= n; s4[i] -> [2, i, 0, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [1, i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s3[i, j] -> [2, j, 1, i, j] : j >= 1 and j <= -1 + i and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.c
new file mode 100644
index 00000000000..3e403ddcd33
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 99; c0 += 1)
+ s0(c0 % 10, c0 / 10);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.in
new file mode 100644
index 00000000000..0c2b107517a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i + 10j] : i >= 0 and i <= 9 and j >= 0 and j <= 9 }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.c
new file mode 100644
index 00000000000..a3e4458f146
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.c
@@ -0,0 +1,2 @@
+for (int c0 = 0; c0 <= 99; c0 += 1)
+ s0(c0, c0 % 10, (c0 + 10) / 10 - 1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.in
new file mode 100644
index 00000000000..e0c72739736
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/dagstuhl1-1.in
@@ -0,0 +1,3 @@
+{s0[p,i,j] -> [p,i,j] : 0 <= i,j <= 9 && p = i+10j}
+{ : }
+{ [p,i,j] -> separate[o0] : o0 >= 2; [p,i,j] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.c
new file mode 100644
index 00000000000..fbec13a719b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 < n - 1; c0 += 1) {
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ s0(c0 + 1, n - c3);
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+ s1(c0 + 1, n - c3, c6);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.in
new file mode 100644
index 00000000000..688f9580d9b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.c
new file mode 100644
index 00000000000..768a04fbc4d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.c
@@ -0,0 +1,17 @@
+{
+ for (int c3 = 1; c3 <= n; c3 += 1)
+ s2(c3);
+ for (int c0 = 0; c0 < n - 1; c0 += 1) {
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ s0(c0 + 1, n - c3);
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+ s1(c0 + 1, n - c3, c6);
+ }
+ for (int c0 = n - 1; c0 < 2 * n - 1; c0 += 1) {
+ if (c0 >= n)
+ for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+ s3(c2, -n + c0 + 1);
+ s4(-n + c0 + 2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.in
new file mode 100644
index 00000000000..c9135fff76c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-1.in
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.c
new file mode 100644
index 00000000000..768a04fbc4d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.c
@@ -0,0 +1,17 @@
+{
+ for (int c3 = 1; c3 <= n; c3 += 1)
+ s2(c3);
+ for (int c0 = 0; c0 < n - 1; c0 += 1) {
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ s0(c0 + 1, n - c3);
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+ s1(c0 + 1, n - c3, c6);
+ }
+ for (int c0 = n - 1; c0 < 2 * n - 1; c0 += 1) {
+ if (c0 >= n)
+ for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+ s3(c2, -n + c0 + 1);
+ s4(-n + c0 + 2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.in
new file mode 100644
index 00000000000..6d9a1626a5b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc1-2.in
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.c
new file mode 100644
index 00000000000..fbec13a719b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 0; c0 < n - 1; c0 += 1) {
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ s0(c0 + 1, n - c3);
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+ s1(c0 + 1, n - c3, c6);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.in
new file mode 100644
index 00000000000..688f9580d9b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.c
new file mode 100644
index 00000000000..768a04fbc4d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.c
@@ -0,0 +1,17 @@
+{
+ for (int c3 = 1; c3 <= n; c3 += 1)
+ s2(c3);
+ for (int c0 = 0; c0 < n - 1; c0 += 1) {
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ s0(c0 + 1, n - c3);
+ for (int c3 = 0; c3 < n - c0 - 1; c3 += 1)
+ for (int c6 = c0 + 2; c6 <= n; c6 += 1)
+ s1(c0 + 1, n - c3, c6);
+ }
+ for (int c0 = n - 1; c0 < 2 * n - 1; c0 += 1) {
+ if (c0 >= n)
+ for (int c2 = -n + c0 + 2; c2 <= n; c2 += 1)
+ s3(c2, -n + c0 + 1);
+ s4(-n + c0 + 2);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.in
new file mode 100644
index 00000000000..c9135fff76c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/fc2-1.in
@@ -0,0 +1,3 @@
+[n] -> { s1[i, j, k] -> [-1 + i, 1, n - i, n - j] : j >= 1 + i and k >= 1 + i and i >= 1 and j <= n and k <= n; s3[i, j] -> [-1 + n + j, 0, i, j] : j >= 1 and j <= -1 + i and i <= n; s4[i] -> [-2 + n + i, 1, 0, 0] : i >= 1 and i <= n; s0[i, j] -> [-1 + i, 0, n - i, n - j] : i >= 1 and j >= 1 + i and j <= n; s2[i] -> [0, 0, 0, i] : i >= 1 and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.c
new file mode 100644
index 00000000000..db7f43707c3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 4 * floord(m - 1, 12) + 4; c0 <= floord(n, 3); c0 += 4)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.in
new file mode 100644
index 00000000000..45faa57c37d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-0.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and 3In_1 >= m and 3In_1 <= n) }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.c
new file mode 100644
index 00000000000..bc879829073
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.c
@@ -0,0 +1,2 @@
+for (int c0 = floord(m, 4); c0 <= n; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.in
new file mode 100644
index 00000000000..7ae72abb93e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-1.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : 4In_1 >= -3 + m and In_1 <= n }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.c
new file mode 100644
index 00000000000..ff5f3c33745
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.c
@@ -0,0 +1,2 @@
+for (int c0 = 4 * floord(m, 4); c0 <= n; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.in
new file mode 100644
index 00000000000..73e1b8eb554
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-2.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/4]: 4e0 <= m and 4e0 >= -3 + m and 4e0 <= In_1 and In_1 <= n) }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.c
new file mode 100644
index 00000000000..e3c9728de91
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.c
@@ -0,0 +1,2 @@
+for (int c0 = 3 * floord(m, 3) + 4 * floord(m, 4); c0 <= n; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.in
new file mode 100644
index 00000000000..1ff7e2c3861
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-3.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/3], e1 = [(m)/4]: 4e1 <= m and 3e0 <= m and 4e1 >= -3 + m and 3e0 >= -2 + m and In_1 <= n and 4e1 <= In_1 - 3e0) }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.c
new file mode 100644
index 00000000000..dc6ba0ae941
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.c
@@ -0,0 +1,3 @@
+if (n >= 3 * floord(n + 1, 3))
+ for (int c0 = m; c0 <= 5 * floord(n + 1, 3); c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.in
new file mode 100644
index 00000000000..7a726c39379
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-4.in
@@ -0,0 +1,3 @@
+[n, m] -> { s0[In_1] -> [In_1] : exists (e0 = [(1 + n)/3]: In_1 >= m and 5e0 >= In_1 and 3e0 <= n and 3e0 >= -1 + n) }
+{ : }
+[n, m] -> { [i0] -> atomic[o0] : o0 <= -1; [i0] -> separate[o0] : o0 >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.c
new file mode 100644
index 00000000000..3e9f47d4ccc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.c
@@ -0,0 +1,2 @@
+for (int c0 = 4 * floord(m, 32); c0 <= n; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.in
new file mode 100644
index 00000000000..cc24250ddaa
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-5.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(m)/32]: 32e0 <= m and 32e0 >= -31 + m and 4e0 <= In_1 and In_1 <= n) }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.c b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.c
new file mode 100644
index 00000000000..743b0c938c5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.c
@@ -0,0 +1,3 @@
+if (m >= 8 * floord(m + 1, 8))
+ for (int c0 = 4 * floord(m + 1, 32); c0 <= n; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.in b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.in
new file mode 100644
index 00000000000..78d2be97e2a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/floor_bound-6.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[In_1] -> [In_1] : exists (e0 = [(1 + m)/8], e1 = [(e0)/4]: 8e0 <= m and 8e0 >= -6 + m and 4e1 <= In_1 and In_1 <= n and 32e1 <= 1 + m and 32e1 >= -30 + m) }
+{ : }
+[m, n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.c
new file mode 100644
index 00000000000..d8234a378ce
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 2; c0 <= 8; c0 += 2)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.in
new file mode 100644
index 00000000000..063e35361f1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gc-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 2 and In_1 <= 8) }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.c
new file mode 100644
index 00000000000..1c22a5d9b0a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 2; c0 <= n; c0 += 1)
+ for (int c1 = 1; c1 <= n; c1 += 1) {
+ for (int c3 = 1; c3 < min(c0, c1); c3 += 1)
+ s1(c3, c0, c1);
+ if (c0 >= c1 + 1)
+ s0(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.in
new file mode 100644
index 00000000000..edd7c36ee61
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ge-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[k, i] -> [i, k, 1, 0] : k >= 1 and i >= 1 + k and i <= n; s1[k, i, j] -> [i, j, 0, k] : i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.c
new file mode 100644
index 00000000000..1c22a5d9b0a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.c
@@ -0,0 +1,7 @@
+for (int c0 = 2; c0 <= n; c0 += 1)
+ for (int c1 = 1; c1 <= n; c1 += 1) {
+ for (int c3 = 1; c3 < min(c0, c1); c3 += 1)
+ s1(c3, c0, c1);
+ if (c0 >= c1 + 1)
+ s0(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.in
new file mode 100644
index 00000000000..4a08142d506
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ge-1.in
@@ -0,0 +1,3 @@
+[n] -> { s0[k, i] -> [i, k, 1, 0] : k >= 1 and i >= 1 + k and i <= n; s1[k, i, j] -> [i, j, 0, k] : i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.c
new file mode 100644
index 00000000000..4608d61d8db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+ for (int c1 = c0; c1 <= n; c1 += 3)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.in
new file mode 100644
index 00000000000..b2f3366f8d3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-3 - In_1 + 4In_2)/12]: 4e0 = -1 + In_1 and 12e1 = -3 - In_1 + 4In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.c
new file mode 100644
index 00000000000..8f1c692c8ea
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+ for (int c1 = c0; c1 <= n; c1 += 8)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.in
new file mode 100644
index 00000000000..ecbf8e7b06e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-1.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-In_1 + In_2)/8]: 4e0 = -1 + In_1 and 8e1 = -In_1 + In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.c
new file mode 100644
index 00000000000..317498782d4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 256)
+ for (int c1 = c0; c1 <= n; c1 += 8)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.in
new file mode 100644
index 00000000000..63edb52b5f7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-2.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/256], e1 = [(-1 + In_2)/8]: 256e0 = -1 + In_1 and 8e1 = -1 + In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.c
new file mode 100644
index 00000000000..513f385c3c5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 < n; c0 += 4)
+ for (int c1 = c0 + 1; c1 <= n; c1 += 6)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.in
new file mode 100644
index 00000000000..43cac1243b8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-3.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/4], e1 = [(-1 - In_1 + In_2)/6]: 4e0 = -1 + In_1 and 6e1 = -1 - In_1 + In_2 and In_1 >= 1 and In_2 >= 1 + In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.c
new file mode 100644
index 00000000000..a6f6fd001b0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 6)
+ for (int c1 = c0; c1 <= n; c1 += 4)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.in
new file mode 100644
index 00000000000..f67f837d598
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-4.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/6], e1 = [(-2 - In_1 + 3In_2)/12]: 6e0 = -1 + In_1 and 12e1 = -2 - In_1 + 3In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.c b/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.c
new file mode 100644
index 00000000000..c2df61fb4e1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 12)
+ for (int c1 = c0; c1 <= n; c1 += 8)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.in b/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.in
new file mode 100644
index 00000000000..8b192c132fd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/gist-5.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-1 + In_1)/12], e1 = [(-2 - In_1 + 3In_2)/24]: 12e0 = -1 + In_1 and 24e1 = -2 - In_1 + 3In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.c
new file mode 100644
index 00000000000..555d644f561
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.c
@@ -0,0 +1,2 @@
+if ((n - m + 2) % 3 == 0)
+ s0(n, m);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.in
new file mode 100644
index 00000000000..52964e26489
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-0.in
@@ -0,0 +1,3 @@
+[n, m] -> { s0[n, m] -> [n, m] : exists (e0 = [(-2 - n + m)/3]: 3e0 = -2 - n + m) }
+{ : }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.c
new file mode 100644
index 00000000000..335c1b838fe
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.c
@@ -0,0 +1,2 @@
+if ((n - m + 1) % 2 == 0)
+ s0(n, m);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.in
new file mode 100644
index 00000000000..141f585d358
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/guard1-1.in
@@ -0,0 +1,3 @@
+[n, m] -> { s0[n, m] -> [n, m] : exists (e0 = [(-1 - n + m)/2]: 2e0 = -1 - n + m) }
+{ : }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.c
new file mode 100644
index 00000000000..c676558941f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.c
@@ -0,0 +1,4 @@
+if (P2 >= 0 && P2 <= 3 && P1 == P2)
+ for (int c0 = 0; c0 <= min(2, -P2 + 4); c0 += 1)
+ for (int c2 = (-P2 - c0 + 6) % 3; c2 <= 3; c2 += 3)
+ s0(c0, c0, c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.in
new file mode 100644
index 00000000000..e697792ea66
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/hpf-0.in
@@ -0,0 +1,3 @@
+[P1, P2] -> { s0[In_1, In_1, In_3, In_3] -> [In_1, In_1, In_3, In_3] : exists (e0 = [(-2P2 - 2In_1 + In_3)/3]: P1 = P2 and 3e0 = -2P2 - 2In_1 + In_3 and P2 >= 0 and P2 <= 3 and In_1 <= 4 - P2 and In_1 >= 0 and In_1 <= 2 and In_3 >= 0 and In_3 <= 3) }
+{ : }
+[P2, P1] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.c
new file mode 100644
index 00000000000..bc8d3370a6d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.c
@@ -0,0 +1,12 @@
+if (m <= 1) {
+ for (int c0 = 1; c0 <= n; c0 += 1)
+ for (int c1 = 1; c1 <= n; c1 += 1)
+ s2(c0, c1);
+} else if (n >= m + 1) {
+ for (int c0 = 1; c0 <= n; c0 += 1)
+ for (int c1 = 1; c1 <= n; c1 += 1)
+ s0(c0, c1);
+} else
+ for (int c0 = 1; c0 <= n; c0 += 1)
+ for (int c1 = 1; c1 <= n; c1 += 1)
+ s1(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.in
new file mode 100644
index 00000000000..93f3f7c2bc8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-0.in
@@ -0,0 +1,3 @@
+[n, m] -> { s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= n and In_2 >= 1 and In_2 <= n and m <= 1; s0[In_1, In_2] -> [In_1, In_2] : m >= 2 and m <= -1 + n and In_1 >= 1 and In_1 <= n and In_2 >= 1 and In_2 <= n; s1[In_1, In_2] -> [In_1, In_2] : In_1 <= n and In_2 <= n and m >= n and In_1 >= 1 and In_2 >= 1 and m >= 2 }
+{ : }
+[n, m] -> { [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.c
new file mode 100644
index 00000000000..18ca3702186
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (n >= 2)
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ if (n >= 2)
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.in
new file mode 100644
index 00000000000..0258439fff7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-1.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{ : }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 2; [i0,i1] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.c
new file mode 100644
index 00000000000..d1ce579aa97
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.c
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (n >= 2) {
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+ } else
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.in
new file mode 100644
index 00000000000..0a220ee3a54
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-2.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{ : }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 1; [i0,i1] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.c
new file mode 100644
index 00000000000..570cbe5556f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.c
@@ -0,0 +1,12 @@
+if (n >= 2) {
+ for (int c0 = 1; c0 <= 100; c0 += 1) {
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+ }
+} else
+ for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s2(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.in
new file mode 100644
index 00000000000..a0315f1a7b1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-3.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1] -> [In_1,0] : In_1 >= 1 and In_1 <= 100 and n >= 2; s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and n >= 2; s2[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 }
+{ : }
+[n] -> { [i0,i1] -> separate[o0] : o0 >= 0; [i0,i1] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.c
new file mode 100644
index 00000000000..fa81628ade8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.c
@@ -0,0 +1,7 @@
+for (int c0 = 4; c0 <= 100; c0 += 4) {
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s0(c0, c1);
+ if (c0 >= 8 && c0 <= 96)
+ for (int c1 = 10; c1 <= 100; c1 += 1)
+ s1(c0 + 2, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.in
new file mode 100644
index 00000000000..30dc8dc24d2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-4.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-2 + In_1)/4]: 4e0 = -2 + In_1 and In_1 >= 10 and In_1 <= 98 and In_2 >= 10 and In_2 <= 100); s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and In_1 >= 4 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100) }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 1; [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.c b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.c
new file mode 100644
index 00000000000..fa81628ade8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.c
@@ -0,0 +1,7 @@
+for (int c0 = 4; c0 <= 100; c0 += 4) {
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s0(c0, c1);
+ if (c0 >= 8 && c0 <= 96)
+ for (int c1 = 10; c1 <= 100; c1 += 1)
+ s1(c0 + 2, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.in b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.in
new file mode 100644
index 00000000000..87a40f4733a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/if_then-5.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-2 + In_1)/4]: 4e0 = -2 + In_1 and In_1 >= 10 and In_1 <= 98 and In_2 >= 10 and In_2 <= 100); s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/4]: 4e0 = In_1 and In_1 >= 4 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100) }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.c
new file mode 100644
index 00000000000..c15c86b2f6b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.in
new file mode 100644
index 00000000000..8b876786027
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter1-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : In_1 >= 2 and In_1 <= 9 }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.c
new file mode 100644
index 00000000000..5506929a106
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 10; c0 += 1)
+ for (int c1 = 10; c1 <= 100; c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.in
new file mode 100644
index 00000000000..16ea0df1805
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter2-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 10 and In_2 >= 10 and In_2 <= 100 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.c
new file mode 100644
index 00000000000..43b6e3aa0f6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 8; c0 += 1)
+ for (int c1 = c0 + 1; c1 <= 9; c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.in
new file mode 100644
index 00000000000..fc26493e28e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter3-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 9 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.c
new file mode 100644
index 00000000000..65e37023ff3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+ for (int c1 = c0 + 1; c1 <= 2 * c0; c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.in
new file mode 100644
index 00000000000..94001d5251d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter4-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 2In_1 and In_1 <= 9 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.c
new file mode 100644
index 00000000000..66c7c0971f8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 9; c0 += 1)
+ for (int c1 = c0 + 1; c1 <= min(16, 2 * c0); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.in
new file mode 100644
index 00000000000..1e4f739447e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter5-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_2 >= 1 + In_1 and In_2 <= 2In_1 and In_2 <= 16 and In_1 <= 9 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.c
new file mode 100644
index 00000000000..a0346b69cdd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 5; c0 += 1)
+ for (int c1 = 12; c1 <= 17; c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.in
new file mode 100644
index 00000000000..1b8ed2b3c04
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 1 and In_1 <= 5 and In_2 >= 12 and In_2 <= 17 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.c
new file mode 100644
index 00000000000..daccd39be7a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.c
@@ -0,0 +1,2 @@
+for (int c0 = 46; c0 <= 70; c0 += 12)
+ s0(c0, (17 * c0 - 170) / 12);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.in
new file mode 100644
index 00000000000..4ee2ad6608d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter6-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, o1] : 12In_2 = -170 + 17In_1 and 12o1 = -170 + 17In_1 and In_1 >= 46 and In_1 <= 70 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.c
new file mode 100644
index 00000000000..2606890886e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 1; c0 <= 3; c0 += 2)
+ s0(c0, (-3 * c0 + 15) / 2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.in
new file mode 100644
index 00000000000..90d3efb7de0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter7-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, o1] : 2In_2 = 15 - 3In_1 and 2o1 = 15 - 3In_1 and In_1 <= 3 and In_1 >= 1 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.c
new file mode 100644
index 00000000000..a33fc49b76a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.c
@@ -0,0 +1,2 @@
+for (int c0 = max(exprVar2 + 1, exprVar2 + 8 * floord(-exprVar2 + exprVar1 - 1, 8) + 9); c0 <= 16; c0 += 8)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.in
new file mode 100644
index 00000000000..682928048df
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter8-0.in
@@ -0,0 +1,3 @@
+[exprVar2, exprVar3, exprVar1] -> { s0[In_1] -> [In_1] : exists (e0 = [(-1 - exprVar2 + In_1)/8]: exprVar3 = 0 and 8e0 = -1 - exprVar2 + In_1 and exprVar1 >= 1 and In_1 >= 1 + exprVar1 and In_1 <= 16 and In_1 >= 1 + exprVar2) }
+[exprVar3, exprVar2, exprVar1] -> { : exists (e0: exprVar3 = 0 and 8e0 >= -15 + exprVar2 and exprVar2 <= 15 and exprVar1 >= 1 and 8e0 <= exprVar2 - exprVar1) }
+[exprVar2, exprVar3, exprVar1] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.c
new file mode 100644
index 00000000000..9b8522ba7d8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.c
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= 15; c0 += 1) {
+ if (((-exprVar1 + 15) % 8) + c0 <= 15) {
+ s4(c0);
+ s0(c0);
+ s3(c0);
+ s2(c0);
+ s1(c0);
+ }
+ if (((-exprVar1 + 15) % 8) + c0 <= 15 || (c0 >= exprVar1 + 1 && (exprVar1 - c0 + 1) % 8 == 0))
+ s5(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.in
new file mode 100644
index 00000000000..9596d73727c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/iter9-0.in
@@ -0,0 +1,3 @@
+[exprVar2, exprVar1] -> { s3[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s4[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s1[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s5[In_1] -> [In_1] : (exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1)) or (exists (e0 = [(-1 - exprVar1 + In_1)/8]: exprVar2 = 0 and 8e0 = -1 - exprVar1 + In_1 and In_1 >= 1 + exprVar1 and In_1 >= 1 and In_1 <= 15)); s0[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1); s2[In_1] -> [In_1] : exists (e0: exprVar2 = 0 and 8e0 >= -15 + exprVar1 and exprVar1 <= 15 and In_1 >= 1 and 8e0 <= exprVar1 - In_1) }
+[exprVar2, exprVar1] -> { : exprVar2 = 0 and exprVar1 <= 15 }
+[exprVar2, exprVar1] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c
new file mode 100644
index 00000000000..aab26208811
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+ for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
+ s0(c0, c1, c2, c3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.in
new file mode 100644
index 00000000000..cf99c811b7e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur00-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{ : }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c
new file mode 100644
index 00000000000..aab26208811
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+ for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
+ s0(c0, c1, c2, c3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.in
new file mode 100644
index 00000000000..cf99c811b7e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{ : }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c
new file mode 100644
index 00000000000..aab26208811
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c
@@ -0,0 +1,5 @@
+for (int c0 = 0; c0 <= 15; c0 += 1)
+ for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
+ s0(c0, c1, c2, c3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.in
new file mode 100644
index 00000000000..bc9611db469
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur01-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4] -> [In_1, In_2, In_3, In_4] : In_3 >= 1 and In_4 >= In_3 and In_4 <= 1 + 2In_3 and In_3 <= 1000 and In_4 >= 200In_1 - In_3 and In_4 <= 199 + 200In_1 - In_3 and 2In_4 >= 200In_2 + In_3 and 2In_4 <= 199 + 200In_2 + In_3 }
+{ : }
+{ [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.c
new file mode 100644
index 00000000000..05ac73f3a44
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.c
@@ -0,0 +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(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)
+ for (int c5 = max(max(max(c4, 1000 * c0 - c4), 1000 * c3 - 2 * c4 + 2), 500 * c1 + (c4 + 1) / 2); c5 <= min(min(min(2 * c4 + 1, 1000 * c0 - c4 + 999), 1000 * c3 - 2 * c4 + 1001), 500 * c1 + (c4 + 1) / 2 + 499); c5 += 1)
+ s0(c0, c1, c2, c3, c4, c5);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.in
new file mode 100644
index 00000000000..890f413e743
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur03-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5, In_6] -> [In_1, In_2, In_3, In_4, In_5, In_6] : In_6 >= In_5 and In_6 <= 1 + 2In_5 and In_5 <= 1000 and In_6 >= 1000In_1 - In_5 and In_6 <= 999 + 1000In_1 - In_5 and In_6 >= 2 + 1000In_4 - 2In_5 and In_6 <= 1001 + 1000In_4 - 2In_5 and In_4 >= 0 and 2In_6 >= 1000In_2 + In_5 and 2In_6 <= 999 + 1000In_2 + In_5 and 3In_5 >= -1 + 1000In_3 and 3In_5 <= 998 + 1000In_3 }
+{ : }
+{ [i0, i1, i2, i3, i4, i5] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4, i5] -> atomic[o0] : o0 <= 4 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.c
new file mode 100644
index 00000000000..124d0f15cb5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.c
@@ -0,0 +1,8 @@
+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 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)
+ s0(c0, c1, c2, c3, c2 / 3, c5, c6, c7);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.in
new file mode 100644
index 00000000000..c50a0da4c51
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lefur04-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5, In_6, In_7, In_8] -> [In_1, In_2, In_3, In_4, In_5, In_6, In_7, In_8] : In_7 >= 1000In_5 and In_8 >= In_7 and In_8 <= 501 + 500In_6 and In_8 <= 1 + 2In_7 and In_7 <= 999 + 1000In_5 and In_7 <= 1000 and In_8 >= 1000In_1 - In_7 and In_8 <= 999 + 1000In_1 - In_7 and 2In_8 >= 1000In_2 + In_7 and 2In_8 <= 999 + 1000In_2 + In_7 and 3In_7 >= -1 + 1000In_3 and 3In_7 <= 998 + 1000In_3 and In_8 >= 2 + 500In_6 and In_6 >= 0 and In_8 >= 2 + 1000In_4 - 2In_7 and In_8 <= 1001 + 1000In_4 - 2In_7 }
+{ : }
+{ [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 6; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 7 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.c
new file mode 100644
index 00000000000..f7b1ae9ae7b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ if (c0 <= 60)
+ s0(c0, c1, c2, c3, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.in
new file mode 100644
index 00000000000..31ae11ad533
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.c
new file mode 100644
index 00000000000..3910e4f264d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.c
@@ -0,0 +1,13 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1) {
+ if (c0 >= 61) {
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.in
new file mode 100644
index 00000000000..44de4acbb94
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.c
new file mode 100644
index 00000000000..8737f3c50bf
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1) {
+ if (c0 >= 61) {
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.in
new file mode 100644
index 00000000000..241fbb96293
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-2.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.c
new file mode 100644
index 00000000000..4d73f89d63d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.c
@@ -0,0 +1,15 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ if (c0 >= 61) {
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.in
new file mode 100644
index 00000000000..a50a9ece72c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-3.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 2; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.c
new file mode 100644
index 00000000000..7d2de29261c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.c
@@ -0,0 +1,16 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (c0 >= 61) {
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.in
new file mode 100644
index 00000000000..db7d85c8eed
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-4.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 1; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.c
new file mode 100644
index 00000000000..2a24f683e66
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.c
@@ -0,0 +1,16 @@
+{
+ for (int c0 = 1; c0 <= 60; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ for (int c0 = 61; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.in
new file mode 100644
index 00000000000..2f9d5786569
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift1-5.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 0; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.c
new file mode 100644
index 00000000000..181d6e58fc3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ if (c0 >= 5 && c0 <= 60)
+ s0(c0, c1, c2, c3, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.in
new file mode 100644
index 00000000000..5df0444130e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 5; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.c
new file mode 100644
index 00000000000..f914743ecc2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.c
@@ -0,0 +1,16 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1) {
+ if (c0 >= 61) {
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else if (c0 <= 4) {
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.in
new file mode 100644
index 00000000000..7ef2a8d9a9e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.c
new file mode 100644
index 00000000000..8b6dbafc507
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.c
@@ -0,0 +1,18 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1) {
+ if (c0 >= 61) {
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else if (c0 <= 4) {
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.in
new file mode 100644
index 00000000000..3e9a9782460
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-2.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.c
new file mode 100644
index 00000000000..1a5954a8081
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.c
@@ -0,0 +1,20 @@
+for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ if (c0 >= 61) {
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else if (c0 <= 4) {
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.in
new file mode 100644
index 00000000000..0580f079dbc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-3.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 2; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.c
new file mode 100644
index 00000000000..d1d04d6507d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.c
@@ -0,0 +1,22 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (c0 >= 61) {
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else if (c0 <= 4) {
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ } else
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.in
new file mode 100644
index 00000000000..d64462ae11b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-4.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 1; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.c b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.c
new file mode 100644
index 00000000000..16bd6dbafd7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.c
@@ -0,0 +1,22 @@
+{
+ for (int c0 = 1; c0 <= 4; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+ for (int c0 = 5; c0 <= 60; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1) {
+ s1(c0, c1, c2, c3, c4);
+ s0(c0, c1, c2, c3, c4);
+ }
+ for (int c0 = 61; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ for (int c2 = 1; c2 <= 100; c2 += 1)
+ for (int c3 = 1; c3 <= 100; c3 += 1)
+ for (int c4 = 1; c4 <= 100; c4 += 1)
+ s1(c0, c1, c2, c3, c4);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.in b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.in
new file mode 100644
index 00000000000..37a57befecd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lift2-5.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 5 and In_1 <= 60 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100; s1[In_1, In_2, In_3, In_4, In_5] -> [In_1, In_2, In_3, In_4, In_5] : In_1 >= 1 and In_1 <= 100 and In_2 >= 1 and In_2 <= 100 and In_3 >= 1 and In_3 <= 100 and In_4 >= 1 and In_4 <= 100 and In_5 >= 1 and In_5 <= 100 }
+{ : }
+{ [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 0; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.c
new file mode 100644
index 00000000000..e71f47bbd58
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.c
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 < n; c0 += 64)
+ for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+ for (int c2 = c0; c2 <= n; c2 += 1) {
+ for (int c3 = c0; c3 <= min(min(c0 + 63, c1 + 62), c2 - 1); c3 += 1)
+ for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s1(c3, c4, c2);
+ if (c0 + 63 >= c2)
+ for (int c4 = max(c1, c2 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s0(c2, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.in
new file mode 100644
index 00000000000..510d677c350
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-0.in
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{ : }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 5; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 4 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.c
new file mode 100644
index 00000000000..e71f47bbd58
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.c
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 < n; c0 += 64)
+ for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+ for (int c2 = c0; c2 <= n; c2 += 1) {
+ for (int c3 = c0; c3 <= min(min(c0 + 63, c1 + 62), c2 - 1); c3 += 1)
+ for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s1(c3, c4, c2);
+ if (c0 + 63 >= c2)
+ for (int c4 = max(c1, c2 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s0(c2, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.in
new file mode 100644
index 00000000000..2e8f7efa535
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-1.in
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{ : }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 4; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.c
new file mode 100644
index 00000000000..e71f47bbd58
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.c
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 < n; c0 += 64)
+ for (int c1 = c0 - 1; c1 <= n; c1 += 64)
+ for (int c2 = c0; c2 <= n; c2 += 1) {
+ for (int c3 = c0; c3 <= min(min(c0 + 63, c1 + 62), c2 - 1); c3 += 1)
+ for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s1(c3, c4, c2);
+ if (c0 + 63 >= c2)
+ for (int c4 = max(c1, c2 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s0(c2, c4);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.in
new file mode 100644
index 00000000000..ab2ec412b06
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-2.in
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{ : }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 3; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.c
new file mode 100644
index 00000000000..3fd0d4eb543
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 < n; c0 += 64)
+ for (int c1 = c0 - 1; c1 <= n; c1 += 64) {
+ for (int c2 = c0; c2 <= min(n, c0 + 63); c2 += 1) {
+ for (int c3 = c0; c3 <= min(c1 + 62, c2 - 1); c3 += 1)
+ for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s1(c3, c4, c2);
+ for (int c4 = max(c1, c2 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s0(c2, c4);
+ }
+ for (int c2 = c0 + 64; c2 <= n; c2 += 1)
+ for (int c3 = c0; c3 <= min(c0 + 63, c1 + 62); c3 += 1)
+ for (int c4 = max(c1, c3 + 1); c4 <= min(n, c1 + 63); c4 += 1)
+ s1(c3, c4, c2);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.in
new file mode 100644
index 00000000000..817db46120a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu-3.in
@@ -0,0 +1,3 @@
+[n] -> { s1[k, i, j] -> [t1, t2, j, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and i >= 1 + k and j >= 1 + k and k >= 1 and i <= n and j <= n); s0[k, i] -> [t1, t2, k, k, i] : exists (e0 = [(-1 + t1)/64], e1 = [(t2)/64]: 64e0 = -1 + t1 and 64e1 = t2 and t1 >= -63 + k and t1 <= k and t2 >= -63 + i and t2 <= i and k >= 1 and i >= 1 + k and i <= n) }
+{ : }
+[n] -> { [t1, t2, i2, i3, i4] -> separate[o0] : o0 >= 2; [t1, t2, i2, i3, i4] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.c
new file mode 100644
index 00000000000..da2571ac530
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+ for (int c1 = 2; c1 <= n; c1 += 1) {
+ for (int c3 = 1; c3 < min(c0, c1); c3 += 1)
+ s1(c3, c1, c0);
+ if (c1 >= c0 + 1)
+ s0(c0, c1);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.in
new file mode 100644
index 00000000000..5aae58cfb57
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.c
new file mode 100644
index 00000000000..da2571ac530
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= n; c0 += 1)
+ for (int c1 = 2; c1 <= n; c1 += 1) {
+ for (int c3 = 1; c3 < min(c0, c1); c3 += 1)
+ s1(c3, c1, c0);
+ if (c1 >= c0 + 1)
+ s0(c0, c1);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.in
new file mode 100644
index 00000000000..06a860c43fe
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-1.in
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.c
new file mode 100644
index 00000000000..561ae1104b5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.c
@@ -0,0 +1,11 @@
+if (n >= 2)
+ for (int c0 = 1; c0 <= n; c0 += 1) {
+ for (int c1 = 2; c1 <= c0; c1 += 1)
+ for (int c3 = 1; c3 < c1; c3 += 1)
+ s1(c3, c1, c0);
+ for (int c1 = c0 + 1; c1 <= n; c1 += 1) {
+ for (int c3 = 1; c3 < c0; c3 += 1)
+ s1(c3, c1, c0);
+ s0(c0, c1);
+ }
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.in
new file mode 100644
index 00000000000..6ad8a4497e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_ijk-2.in
@@ -0,0 +1,3 @@
+[n] -> { s0[k, j] -> [k, j, 1, 0] : k >= 1 and j >= 1 + k and j <= n; s1[k, j, i] -> [i, j, 0, k] : j >= 1 + k and i >= 1 + k and k >= 1 and j <= n and i <= n }
+{ : }
+[n] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 0; [i0, i1, i2, i3] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.c
new file mode 100644
index 00000000000..4c8c72ad594
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.c
@@ -0,0 +1,12 @@
+if (ub >= lb)
+ for (int c0 = 1; c0 <= ub; c0 += 1)
+ for (int c1 = c0; c1 <= n; c1 += 1) {
+ if (c0 >= lb && c1 >= c0 + 1) {
+ s0(c0, c1);
+ if (n >= ub + 1)
+ s2(c0, c1);
+ } else if (lb >= c0 + 1)
+ s3(c0, c1, lb, c0, c1);
+ for (int c3 = max(lb, c0); c3 <= ub; c3 += 1)
+ s1(c0, c1, c3);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.in
new file mode 100644
index 00000000000..0dd09538192
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-0.in
@@ -0,0 +1,3 @@
+[n, lb, ub] -> { s1[k, i, j] -> [k, i, 1, j, 0, 0, 0, 0] : k >= 1 and j >= k and j <= n and j <= ub and i >= k and i <= n and j >= lb; s3[k, i, lb, k, i] -> [k, i, 1, lb, -1, k, i, 0] : k >= 1 and k <= -1 + lb and lb <= n and ub >= lb and i >= k and i <= n; s0[k, i] -> [k, i, 0, 0, 0, 0, 0, 0] : k >= 1 and k >= lb and i >= 1 + k and i <= n and k <= ub; s2[k, i] -> [k, i, 0, 0, 1, 0, 0, 0] : k >= 1 and k >= lb and k <= ub and ub <= -1 + n and i >= 1 + k and i <= n }
+[lb, n, ub] -> { : ub <= n and lb >= 1 }
+[n, lb, ub] -> { [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 7; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 8 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.c
new file mode 100644
index 00000000000..4c8c72ad594
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.c
@@ -0,0 +1,12 @@
+if (ub >= lb)
+ for (int c0 = 1; c0 <= ub; c0 += 1)
+ for (int c1 = c0; c1 <= n; c1 += 1) {
+ if (c0 >= lb && c1 >= c0 + 1) {
+ s0(c0, c1);
+ if (n >= ub + 1)
+ s2(c0, c1);
+ } else if (lb >= c0 + 1)
+ s3(c0, c1, lb, c0, c1);
+ for (int c3 = max(lb, c0); c3 <= ub; c3 += 1)
+ s1(c0, c1, c3);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.in
new file mode 100644
index 00000000000..5d628befe3e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/lu_spmd-1.in
@@ -0,0 +1,3 @@
+[n, lb, ub] -> { s1[k, i, j] -> [k, i, 1, j, 0, 0, 0, 0] : k >= 1 and j >= k and j <= n and j <= ub and i >= k and i <= n and j >= lb; s3[k, i, lb, k, i] -> [k, i, 1, lb, -1, k, i, 0] : k >= 1 and k <= -1 + lb and lb <= n and ub >= lb and i >= k and i <= n; s0[k, i] -> [k, i, 0, 0, 0, 0, 0, 0] : k >= 1 and k >= lb and i >= 1 + k and i <= n and k <= ub; s2[k, i] -> [k, i, 0, 0, 1, 0, 0, 0] : k >= 1 and k >= lb and k <= ub and ub <= -1 + n and i >= 1 + k and i <= n }
+[lb, n, ub] -> { : ub <= n and lb >= 1 }
+[n, lb, ub] -> { [i0, i1, i2, i3, i4, i5, i6, i7] -> atomic[o0] : o0 <= 6; [i0, i1, i2, i3, i4, i5, i6, i7] -> separate[o0] : o0 >= 7 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.c
new file mode 100644
index 00000000000..bb149359f93
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.c
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c0, c1);
+ if (c0 == 5)
+ s1(5, c1);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.in
new file mode 100644
index 00000000000..ca2b8a9b2c0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m1-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i, j, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[5, j] -> [5, j, 1] : j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.c
new file mode 100644
index 00000000000..07b91f794e0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.c
@@ -0,0 +1,13 @@
+for (int c0 = 1; c0 <= 9; c0 += 1) {
+ if (c0 >= 6) {
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c0, c1);
+ } else if (c0 <= 4) {
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c0, c1);
+ } else
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(5, c1);
+ s1(5, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.in
new file mode 100644
index 00000000000..08dbf45ed10
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m1-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i, j, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[5, j] -> [5, j, 1] : j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.c
new file mode 100644
index 00000000000..2b51c7b9106
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.c
@@ -0,0 +1,7 @@
+for (int c0 = 1; c0 <= 18; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ if (c0 % 2 == 0)
+ s0(c1, c0 / 2);
+ if (c0 <= 9)
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.in
new file mode 100644
index 00000000000..3046811e743
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m10-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.c
new file mode 100644
index 00000000000..b3f34f6ec93
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 18; c0 += 1) {
+ if (c0 >= 2 && c0 <= 9) {
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ if (c0 % 2 == 0)
+ s0(c1, c0 / 2);
+ s1(c1, c0);
+ }
+ } else if (c0 == 1) {
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s1(c1, 1);
+ } else if (c0 % 2 == 0)
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c1, c0 / 2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.in
new file mode 100644
index 00000000000..81dfc3bbdea
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m10-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.c
new file mode 100644
index 00000000000..1ecb4a53289
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.c
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= min(4, floord(2 * m - 1, 17) + 1); c0 += 1)
+ for (int c1 = 1; c1 <= 2; c1 += 1)
+ for (int c2 = 0; c2 <= min(2, -c0 - c1 + (2 * m + 3 * c0 + 10 * c1 + 6) / 20 + 1); c2 += 1)
+ for (int c3 = 8 * c0 + (c0 + 1) / 2 - 8; c3 <= min(min(30, m - 5 * c1 - 10 * c2 + 5), 8 * c0 + c0 / 2); c3 += 1)
+ for (int c4 = 5 * c1 + 10 * c2 - 4; c4 <= min(5 * c1 + 10 * c2, m - c3 + 1); c4 += 1)
+ s0(c0, c1, c2, c3, c4, -9 * c0 + c3 + c0 / 2 + 9, -5 * c1 - 5 * c2 + c4 + 5);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.in
new file mode 100644
index 00000000000..d85fcf2734b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m11-0.in
@@ -0,0 +1,3 @@
+[m] -> { s0[In_1, In_2, In_3, In_4, In_5, In_6, 5 - 5In_2 - 5In_3 + In_5] -> [In_1, In_2, In_3, In_4, In_5, In_6, 5 - 5In_2 - 5In_3 + In_5] : In_2 >= 1 and 2In_3 >= 1 - In_2 and In_2 <= 2 and 2In_3 <= 6 - In_2 and In_4 <= 30 and In_1 >= 1 and 2In_6 <= 18 - 17In_1 + 2In_4 and 2In_6 >= 17 - 17In_1 + 2In_4 and In_5 <= 5In_2 + 10In_3 and In_5 >= -4 + 5In_2 + 10In_3 and 2In_4 <= 17In_1 and 2In_4 >= -16 + 17In_1 and In_5 <= 1 + m - In_4 }
+{ : }
+[m] -> { [i0, i1, i2, i3, i4, i5, i6] -> atomic[o0] : o0 <= 5; [i0, i1, i2, i3, i4, i5, i6] -> separate[o0] : o0 >= 6 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.c
new file mode 100644
index 00000000000..2dc6ab1fea6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.c
@@ -0,0 +1,3 @@
+for (int c1 = 1; c1 <= n; c1 += 1)
+ for (int c2 = 1; c2 <= m; c2 += 1)
+ s0(1, c1, c2, 0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.in
new file mode 100644
index 00000000000..0c988ab110c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m12-0.in
@@ -0,0 +1,3 @@
+[m, n] -> { s0[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n }
+{ : }
+[m, n] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.c
new file mode 100644
index 00000000000..eba7c8a6170
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.c
@@ -0,0 +1,25 @@
+{
+ for (int c1 = 1; c1 <= n; c1 += 1)
+ for (int c2 = 1; c2 <= m; c2 += 1) {
+ s0(1, c1, c2, 0);
+ s1(1, c1, c2, 0);
+ }
+ for (int c1 = 1; c1 <= n; c1 += 1) {
+ s3(2, c1, 0, 0);
+ s2(2, c1, 0, 0);
+ }
+ for (int c1 = 1; c1 <= m; c1 += 1) {
+ for (int c3 = 1; c3 <= n; c3 += 1) {
+ s5(3, c1, 1, c3);
+ s4(3, c1, 1, c3);
+ }
+ for (int c3 = 1; c3 <= n; c3 += 1) {
+ s7(3, c1, 2, c3);
+ s6(3, c1, 2, c3);
+ }
+ }
+ for (int c1 = 1; c1 <= m; c1 += 1) {
+ s8(4, c1, 0, 0);
+ s9(4, c1, 0, 0);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.in
new file mode 100644
index 00000000000..355075faf68
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m12-1.in
@@ -0,0 +1,3 @@
+[m, n] -> { s1[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n; s2[2, In_2, 0, 0] -> [2, In_2, 0, 0] : In_2 >= 1 and In_2 <= n; s3[2, In_2, 0, 0] -> [2, In_2, 0, 0] : In_2 >= 1 and In_2 <= n; s8[4, In_2, 0, 0] -> [4, In_2, 0, 0] : In_2 >= 1 and In_2 <= m; s0[1, In_2, In_3, 0] -> [1, In_2, In_3, 0] : In_3 >= 1 and In_3 <= m and In_2 >= 1 and In_2 <= n; s7[3, In_2, 2, In_4] -> [3, In_2, 2, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s4[3, In_2, 1, In_4] -> [3, In_2, 1, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s6[3, In_2, 2, In_4] -> [3, In_2, 2, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m; s9[4, In_2, 0, 0] -> [4, In_2, 0, 0] : In_2 >= 1 and In_2 <= m; s5[3, In_2, 1, In_4] -> [3, In_2, 1, In_4] : In_4 >= 1 and In_4 <= n and In_2 >= 1 and In_2 <= m }
+{ : }
+[m, n] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.c
new file mode 100644
index 00000000000..669f51a7d14
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.c
@@ -0,0 +1,11 @@
+for (int c0 = 2; c0 <= 9; c0 += 1) {
+ if (c0 >= 5) {
+ s1(c0, 1);
+ for (int c1 = 2; c1 <= 9; c1 += 1) {
+ s1(c0, c1);
+ s0(c0, c1);
+ }
+ } else
+ for (int c1 = 2; c1 <= 9; c1 += 1)
+ s0(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.in
new file mode 100644
index 00000000000..ae7780e0403
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m2-0.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 5 and In_1 <= 9 and In_2 >= 1 and In_2 <= 9; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 9 and In_2 >= 2 and In_2 <= 9 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.c
new file mode 100644
index 00000000000..09255e0c510
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.c
@@ -0,0 +1,12 @@
+{
+ for (int c0 = 2; c0 <= 4; c0 += 1)
+ for (int c1 = 2; c1 <= 9; c1 += 1)
+ s0(c0, c1);
+ for (int c0 = 5; c0 <= 9; c0 += 1) {
+ s1(c0, 1);
+ for (int c1 = 2; c1 <= 9; c1 += 1) {
+ s1(c0, c1);
+ s0(c0, c1);
+ }
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.in
new file mode 100644
index 00000000000..32302bb11e6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m2-1.in
@@ -0,0 +1,3 @@
+{ s1[In_1, In_2] -> [In_1, In_2] : In_1 >= 5 and In_1 <= 9 and In_2 >= 1 and In_2 <= 9; s0[In_1, In_2] -> [In_1, In_2] : In_1 >= 2 and In_1 <= 9 and In_2 >= 2 and In_2 <= 9 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.c
new file mode 100644
index 00000000000..d3d69704165
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.c
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+ for (int c1 = max(1, -c0 + 1); c1 <= min(10, -c0 + 10); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.in
new file mode 100644
index 00000000000..82e109311bc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m3-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.c
new file mode 100644
index 00000000000..a5280732a46
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.in
new file mode 100644
index 00000000000..b7912a306b6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m4-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.c
new file mode 100644
index 00000000000..a5280732a46
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.in
new file mode 100644
index 00000000000..c9e17d93466
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m4-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.c
new file mode 100644
index 00000000000..d9f93d96fcd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.c
@@ -0,0 +1,6 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ if (c0 % 2 == 0)
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.in
new file mode 100644
index 00000000000..45a185043bc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m7-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.c
new file mode 100644
index 00000000000..a01856e4b4d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.c
@@ -0,0 +1,10 @@
+for (int c0 = 1; c0 <= 9; c0 += 1) {
+ if (c0 % 2 == 0) {
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
+ } else
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c1, c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.in
new file mode 100644
index 00000000000..f4b6f6ffce8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m7-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.c
new file mode 100644
index 00000000000..9aaed9e9636
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.c
@@ -0,0 +1,6 @@
+for (int c0 = 2; c0 <= 8; c0 += 2)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ if (c0 % 4 == 0)
+ s0(c1, c0);
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.in
new file mode 100644
index 00000000000..e9a0e39646b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m8-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : exists (e0 = [(j)/4]: 4e0 = j and i >= 1 and i <= 9 and j >= 4 and j <= 8); s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.c
new file mode 100644
index 00000000000..51c77daeca4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.c
@@ -0,0 +1,10 @@
+for (int c0 = 2; c0 <= 8; c0 += 2) {
+ if (c0 % 4 == 0) {
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
+ } else
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s1(c1, c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.in
new file mode 100644
index 00000000000..80e57e499db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m8-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [j, i, 0] : exists (e0 = [(j)/4]: 4e0 = j and i >= 1 and i <= 9 and j >= 4 and j <= 8); s1[i, j] -> [j, i, 1] : exists (e0 = [(j)/2]: 2e0 = j and i >= 1 and i <= 9 and j >= 2 and j <= 8) }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.c
new file mode 100644
index 00000000000..a5280732a46
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.in
new file mode 100644
index 00000000000..fc38bf2e486
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m9-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.c
new file mode 100644
index 00000000000..a5280732a46
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.c
@@ -0,0 +1,5 @@
+for (int c0 = 1; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ s0(c1, c0);
+ s1(c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.in
new file mode 100644
index 00000000000..398e3260abf
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/m9-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [2j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.c
new file mode 100644
index 00000000000..b05f991ad1f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.c
@@ -0,0 +1,8 @@
+for (int c0 = 1; c0 <= morb; c0 += 1)
+ for (int c1 = 1; c1 <= np; c1 += 1)
+ for (int c2 = 1; c2 <= np; c2 += 1) {
+ if (c2 >= c1)
+ s0(c2, c1, c0);
+ if (c1 >= c2)
+ s1(c1, c2, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.in
new file mode 100644
index 00000000000..88f86f558c5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/olda-0.in
@@ -0,0 +1,3 @@
+[np, morb] -> { s0[mp, mq, mi] -> [mi, mq, mp, 0] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb; s1[mp, mq, mi] -> [mi, mp, mq, 1] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb }
+{ : }
+[np, morb] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2; [i0, i1, i2, i3] -> separate[o0] : o0 >= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.c
new file mode 100644
index 00000000000..4b3098068e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= morb; c0 += 1)
+ for (int c1 = 1; c1 <= np; c1 += 1) {
+ for (int c2 = 1; c2 < c1; c2 += 1)
+ s1(c1, c2, c0);
+ s0(c1, c1, c0);
+ s1(c1, c1, c0);
+ for (int c2 = c1 + 1; c2 <= np; c2 += 1)
+ s0(c2, c1, c0);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.in
new file mode 100644
index 00000000000..a3a387fbac4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/olda-1.in
@@ -0,0 +1,3 @@
+[np, morb] -> { s0[mp, mq, mi] -> [mi, mq, mp, 0] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb; s1[mp, mq, mi] -> [mi, mp, mq, 1] : mq >= 1 and mq <= mp and mp <= np and mi >= 1 and mi <= morb }
+{ : }
+[np, morb] -> { [i0, i1, i2, i3] -> atomic[o0] : o0 <= 1; [i0, i1, i2, i3] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.c
new file mode 100644
index 00000000000..c676558941f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.c
@@ -0,0 +1,4 @@
+if (P2 >= 0 && P2 <= 3 && P1 == P2)
+ for (int c0 = 0; c0 <= min(2, -P2 + 4); c0 += 1)
+ for (int c2 = (-P2 - c0 + 6) % 3; c2 <= 3; c2 += 3)
+ s0(c0, c0, c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.in
new file mode 100644
index 00000000000..5b277a12d78
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft-0.in
@@ -0,0 +1,3 @@
+[P2, P1] -> { s0[In_1, In_1, In_3, In_3] -> [In_1, In_1, In_3, In_3] : exists (e0 = [(-2P2 - 2In_1 + In_3)/3]: P1 = P2 and 3e0 = -2P2 - 2In_1 + In_3 and P2 >= 0 and P2 <= 3 and In_1 <= 4 - P2 and In_1 >= 0 and In_1 <= 2 and In_3 >= 0 and In_3 <= 3) }
+{ : }
+[P2, P1] -> { [i0, i1, i2, i3] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.c
new file mode 100644
index 00000000000..ad5a4cab0d6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.c
@@ -0,0 +1,10 @@
+if (P1 >= 0 && P1 <= 3 && P2 >= 0 && P2 <= 3)
+ for (int c0 = P1 - 1; c0 <= 3; c0 += 1)
+ for (int c2 = 0; c2 <= 7; c2 += 1)
+ 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);
+ } else if (P1 == 0 && c0 == 3 && c2 % 4 == 0)
+ s0(3, P2, c2, c3, (-c2 / 4) + 3, (-4 * P2 + 2 * c3 + 9) % 9);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.in
new file mode 100644
index 00000000000..f44b9bfdaa9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p.delft2-0.in
@@ -0,0 +1,3 @@
+[P1, P2] -> { s0[In_1, P2, In_3, In_4, In_5, In_6] -> [In_1, P2, In_3, In_4, In_5, In_6] : (exists (e0 = [(8 + 4In_1 + 16In_3 + In_5)/9], e1 = [(12 - 4P1 + 9e0)/16], e2 = [(-2In_1 - 2In_3 + In_5)/3], e3 = [(-5P2 - 2In_4 + In_6)/9]: 3e2 = -2In_1 - 2In_3 + In_5 and 9e3 = -5P2 - 2In_4 + In_6 and P1 >= 0 and In_1 >= 1 + P1 and In_1 <= 3 and P2 >= 0 and P2 <= 3 and In_6 >= 0 and In_6 <= 3 and In_5 >= 0 and In_5 <= 3 and In_5 >= 1 - 4In_1 - 16In_3 and In_5 <= 126 - 4In_1 - 16In_3 and In_6 <= 126 - 4P2 - 16In_4 and 16e1 <= -4P1 + 9e0 and 2In_6 <= P2 + 4In_4 and 9e0 <= 3 + 4In_1 + 16In_3 + In_5 and 9e0 >= 4In_1 + 16In_3 + In_5 and 16e1 >= -3 - 4P1 + 9e0)) or (exists (e0 = [(8 + 4In_1 + 16In_3 + In_5)/9], e1 = [(12 - 4P1 + 9e0)/16], e2 = [(-2In_1 - 2In_3 + In_5)/3], e3 = [(-5P2 - 2In_4 + In_6)/9]: 3e2 = -2In_1 - 2In_3 + In_5 and 9e3 = -5P2 - 2In_4 + In_6 and In_1 >= 0 and In_1 <= -1 + P1 and P1 <= 3 and In_6 >= 0 and In_6 <= 3 and In_6 <= 1 + 2In_4 and P2 >= 0 and P2 <= 3 and In_5 >= 0 and In_5 <= 3 and In_5 >= 1 - 4In_1 - 16In_3 and In_5 <= 126 - 4In_1 - 16In_3 and In_6 <= 126 - 4P2 - 16In_4 and 16e1 <= -4P1 + 9e0 and 9e0 <= 3 + 4In_1 + 16In_3 + In_5 and 9e0 >= 4In_1 + 16In_3 + In_5 and 16e1 >= -3 - 4P1 + 9e0)) }
+{ : }
+[P1, P2] -> { [i0, i1, i2, i3, i4, i5] -> atomic[o0] : o0 <= 4; [i0, i1, i2, i3, i4, i5] -> separate[o0] : o0 >= 5 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.c
new file mode 100644
index 00000000000..53995e9e89e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.c
@@ -0,0 +1,8 @@
+{
+ for (int c0 = 5; c0 <= 8; c0 += 1)
+ s0(c0);
+ for (int c0 = 10; c0 <= 16; c0 += 2)
+ s0(c0);
+ for (int c0 = 20; c0 <= 25; c0 += 1)
+ s0(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.in
new file mode 100644
index 00000000000..025da3d30d6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p6-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : (In_1 >= 5 and In_1 <= 8) or (exists (e0 = [(In_1)/2]: 2e0 = In_1 and In_1 >= 10 and In_1 <= 16)) or (In_1 >= 20 and In_1 <= 25) }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.c
new file mode 100644
index 00000000000..d3d69704165
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.c
@@ -0,0 +1,3 @@
+for (int c0 = -9; c0 <= 9; c0 += 1)
+ for (int c1 = max(1, -c0 + 1); c1 <= min(10, -c0 + 10); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.in
new file mode 100644
index 00000000000..82e109311bc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/p6-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : In_2 >= 1 - In_1 and In_2 >= 1 and In_2 <= 10 - In_1 and In_2 <= 10 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.c
new file mode 100644
index 00000000000..c65c2e39fbc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 3; c0 <= 9; c0 += 3)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.in
new file mode 100644
index 00000000000..e09908713f1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride1-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(In_1)/3]: 3e0 = In_1 and In_1 >= 3 and In_1 <= 9) }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.c
new file mode 100644
index 00000000000..0a7e8e7464d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= n; c0 += 32)
+ for (int c1 = c0; c1 <= min(n, c0 + 31); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.in
new file mode 100644
index 00000000000..73dc13d60e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride2-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/32]: 32e0 = In_1 and In_2 <= 31 + In_1 and In_1 >= 0 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.c
new file mode 100644
index 00000000000..8913c802cc0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 3; c0 <= n; c0 += 32)
+ for (int c1 = c0; c1 <= min(n, c0 + 31); c1 += 1)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.in
new file mode 100644
index 00000000000..360d7d01de1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride3-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(-3 + In_1)/32]: 32e0 = -3 + In_1 and In_2 <= 31 + In_1 and In_1 >= 3 and In_2 >= In_1 and In_2 <= n) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.c
new file mode 100644
index 00000000000..ed62b592ee2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.c
@@ -0,0 +1,2 @@
+for (int c0 = 18; c0 <= 98; c0 += 5)
+ s0(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.in
new file mode 100644
index 00000000000..8779c3ceffa
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride4-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1] -> [In_1] : exists (e0 = [(-3 + In_1)/5]: 5e0 = -3 + In_1 and In_1 >= 18 and In_1 <= 98) }
+{ : }
+{ [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.c
new file mode 100644
index 00000000000..2eeeb5a7b54
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= min(100, -2 * n + 400); c0 += 2)
+ for (int c1 = 2 * n + c0; c1 <= 400; c1 += 2)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.in
new file mode 100644
index 00000000000..c26c5476b3c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride5-0.in
@@ -0,0 +1,3 @@
+[n] -> { s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_1 <= 100 and In_2 <= 400 and In_2 >= 2n + In_1) }
+{ : }
+[n] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.c
new file mode 100644
index 00000000000..f4df469cf62
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= 101; c0 += 1)
+ for (int c1 = -((c0 - 1) % 2) + c0 + 1; c1 <= 400; c1 += 2)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.in
new file mode 100644
index 00000000000..16fda744249
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-0.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_2)/2]: 2e0 = In_2 and In_1 >= 1 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 101) }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.c
new file mode 100644
index 00000000000..070028f0504
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 100; c0 += 2)
+ for (int c1 = c0; c1 <= 400; c1 += 2)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.in
new file mode 100644
index 00000000000..91eaab26a32
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-1.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 100) }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.c
new file mode 100644
index 00000000000..070028f0504
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.c
@@ -0,0 +1,3 @@
+for (int c0 = 2; c0 <= 100; c0 += 2)
+ for (int c1 = c0; c1 <= 400; c1 += 2)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.in
new file mode 100644
index 00000000000..91eaab26a32
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride6-2.in
@@ -0,0 +1,3 @@
+{ s0[In_1, In_2] -> [In_1, In_2] : exists (e0 = [(In_1)/2], e1 = [(In_2)/2]: 2e0 = In_1 and 2e1 = In_2 and In_1 >= 2 and In_2 >= In_1 and In_2 <= 400 and In_1 <= 100) }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.c
new file mode 100644
index 00000000000..7fe17588f3d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 36; c0 += 1) {
+ if (c0 <= 3) {
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s1(c1, c0);
+ } else if (c0 <= 9) {
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ if (c0 % 4 == 0)
+ s0(c1, c0 / 4);
+ s1(c1, c0);
+ }
+ } else if (c0 % 4 == 0)
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c1, c0 / 4);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.in
new file mode 100644
index 00000000000..b84f2045fde
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.c
new file mode 100644
index 00000000000..e79d58deb10
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.c
@@ -0,0 +1,14 @@
+{
+ for (int c0 = 1; c0 <= 3; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s1(c1, c0);
+ for (int c0 = 4; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1) {
+ if (c0 % 4 == 0)
+ s0(c1, c0 / 4);
+ s1(c1, c0);
+ }
+ for (int c0 = 3; c0 <= 9; c0 += 1)
+ for (int c1 = 1; c1 <= 9; c1 += 1)
+ s0(c1, c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.in
new file mode 100644
index 00000000000..3ec82b9c39a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/stride7-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [4j, i, 0] : i >= 1 and i <= 9 and j >= 1 and j <= 9; s1[i, j] -> [j, i, 1] : i >= 1 and i <= 9 and j >= 1 and j <= 9 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 0; [i0, i1, i2] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.c
new file mode 100644
index 00000000000..b12c07d3751
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 10; c0 += 1)
+ for (int c1 = max(2 * c0 - 4, c0); c1 <= min(2 * c0, c0 + 6); c1 += 1)
+ s0(2 * c0 - c1, -c0 + c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.in
new file mode 100644
index 00000000000..f4af71649b6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [i + j, i + 2j] : i >= 0 and i <= 4 and j >= 0 and j <= 6 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.c
new file mode 100644
index 00000000000..486514c0433
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.c
@@ -0,0 +1,3 @@
+for (int c0 = 0; c0 <= 14; c0 += 1)
+ for (int c1 = max(2 * c0 - 12, -c0 + 3 * floord(c0 - 1, 2) + 3); c1 <= min(2 * c0, c0 / 2 + 9); c1 += 3)
+ s0((2 * c0 - c1) / 3, (-c0 + 2 * c1) / 3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.in
new file mode 100644
index 00000000000..504b220fbef
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [2i + j, i + 2j] : i >= 0 and i <= 4 and j >= 0 and j <= 6 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.c
new file mode 100644
index 00000000000..9748950ae52
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.c
@@ -0,0 +1,2 @@
+for (int c0 = -3; c0 <= 96; c0 += 1)
+ s0(c0, c0 + 4);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.in
new file mode 100644
index 00000000000..bc9af0c0063
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-2.in
@@ -0,0 +1,3 @@
+{ s0[i, 4 + i] -> [i, 4 + i] : i >= -3 and i <= 96 }
+{ : }
+{ [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.c
new file mode 100644
index 00000000000..86c197f7a95
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.c
@@ -0,0 +1 @@
+s0(n + 19);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.in
new file mode 100644
index 00000000000..ea1ac1ab914
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-3.in
@@ -0,0 +1,3 @@
+[n] -> { s0[19 + n] -> [19 + n] }
+{ : }
+[n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.c b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.c
new file mode 100644
index 00000000000..27b3199c0c3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.c
@@ -0,0 +1 @@
+s0(n + 1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.in b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.in
new file mode 100644
index 00000000000..ecb07cd85bd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/substitution-4.in
@@ -0,0 +1,3 @@
+[n] -> { s0[i] -> [i] : exists (e0 = [(-1 - n + i)/18]: 18e0 = -1 - n + i and i <= 16 + n and i >= 1 + n) }
+{ : }
+[n] -> { [i0] -> separate[o0] : o0 >= 0; [i0] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.c
new file mode 100644
index 00000000000..bb3ef7fa252
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.c
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(n, 2 * b - 1); c0 += 1)
+ for (int c1 = max(-n + 1, -b + 1); c1 <= min(b - c0, n - c0); c1 += 1)
+ for (int c2 = max(1, c0 + c1); c2 <= min(n, n + c1); c2 += 1)
+ s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.in
new file mode 100644
index 00000000000..28a7deb1f05
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-0.in
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+{ : }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.c
new file mode 100644
index 00000000000..22ec83ec7ee
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.c
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(n, 2 * b - 1); c0 += 1)
+ for (int c1 = -b + 1; c1 <= b - c0; c1 += 1)
+ for (int c2 = max(1, c0 + c1); c2 <= min(n, n + c1); c2 += 1)
+ s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.in
new file mode 100644
index 00000000000..496aebe2e8f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-1.in
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+[b, n] -> { : b >= 1 and n >= b }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.c b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.c
new file mode 100644
index 00000000000..bb3ef7fa252
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.c
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(n, 2 * b - 1); c0 += 1)
+ for (int c1 = max(-n + 1, -b + 1); c1 <= min(b - c0, n - c0); c1 += 1)
+ for (int c2 = max(1, c0 + c1); c2 <= min(n, n + c1); c2 += 1)
+ s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.in b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.in
new file mode 100644
index 00000000000..28a7deb1f05
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-2.in
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+{ : }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.c b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.c
new file mode 100644
index 00000000000..22ec83ec7ee
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.c
@@ -0,0 +1,4 @@
+for (int c0 = 1; c0 <= min(n, 2 * b - 1); c0 += 1)
+ for (int c1 = -b + 1; c1 <= b - c0; c1 += 1)
+ for (int c2 = max(1, c0 + c1); c2 <= min(n, n + c1); c2 += 1)
+ s0(-c0 - c1 + c2 + 1, -c1 + c2, c2);
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.in b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.in
new file mode 100644
index 00000000000..496aebe2e8f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/syr2k-3.in
@@ -0,0 +1,3 @@
+[n, b] -> { s0[i, j, k] -> [1 - i + j, -j + k, k] : i >= 1 and j >= i and j <= n and k >= 1 and k <= n and k <= -1 + b + i and k >= 1 - b + j }
+[b, n] -> { : b >= 1 and n >= b }
+[n, b] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2; [i0, i1, i2] -> atomic[o0] : o0 <= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.c
new file mode 100644
index 00000000000..c70e95bcb41
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.c
@@ -0,0 +1,14 @@
+{
+ for (int c1 = 0; c1 <= 1; c1 += 1) {
+ if (c1 == 1) {
+ s0(1, 1, 1, 0, 0);
+ s0(1, 1, 1, N - 1, 0);
+ } else
+ for (int c3 = 0; c3 < N; c3 += 1)
+ s0(1, 0, 1, c3, 0);
+ }
+ for (int c1 = 0; c1 <= floord(T - 1, 1000); c1 += 1)
+ for (int c2 = 1000 * c1 + 1; c2 <= min(N + T - 3, N + 1000 * c1 + 997); c2 += 1)
+ for (int c3 = max(0, -N - 1000 * c1 + c2 + 2); c3 <= min(min(999, T - 1000 * c1 - 1), -1000 * c1 + c2 - 1); c3 += 1)
+ s1(2, 1000 * c1 + c3, 1, -1000 * c1 + c2 - c3, 1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.in
new file mode 100644
index 00000000000..b1f92ea71a7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check-sblock-0.in
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 1, i, 1] -> [2, tb, t + i, t - 1000tb, 0] : 1000tb <= t and 1000tb >= -999 + t and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s0[1, 0, 1, In_4, 0] -> [1, 0, 1, In_4, 0] : In_4 >= 0 and In_4 <= -1 + N; s0[1, 1, 1, 0, 0] -> [1, 1, 1, 0, 0]; s0[1, 1, 1, -1 + N, 0] -> [1, 1, 1, -1 + N, 0] }
+[T, N] -> { : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.c
new file mode 100644
index 00000000000..5cf4bc9f5c8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.c
@@ -0,0 +1,13 @@
+{
+ for (int c1 = 0; c1 < N; c1 += 1)
+ s0(1, c1, 1, 0, 0);
+ for (int c1 = 0; c1 <= floord(T - 1, 500); c1 += 1)
+ for (int c2 = 1000 * c1; c2 <= min(N + 2 * T - 3, N + 1000 * c1 + 997); c2 += 1) {
+ for (int c3 = max(0, -((N + c2) % 2) - N - 1000 * c1 + c2 + 2); c3 <= min(min(998, 2 * T - 1000 * c1 - 2), -1000 * c1 + c2 - 2); c3 += 2) {
+ s1(2, 1000 * c1 + c3, 0, -1000 * c1 + c2 - c3, 1);
+ 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);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.in
new file mode 100644
index 00000000000..ce585b0836c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-check0-0.in
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 0, i, 1] -> [2, tb, t + i, t - 1000tb, 1] : exists (e0 = [(t - 1000tb)/2]: 2e0 = t - 1000tb and 1000tb <= t and 1000tb >= -999 + t and i >= 0 and i <= -1 + N and t >= 0 and t <= -2 + 2T); s0[1, In_2, 1, 0, 0] -> [1, In_2, 1, 0, 0] : In_2 >= 0 and In_2 <= -1 + N; s2[2, t, 0, i, 1] -> [2, tb, t + i, t - 1000tb, 1] : exists (e0 = [(-1 + t - 1000tb)/2]: 2e0 = -1 + t - 1000tb and 1000tb <= t and 1000tb >= -999 + t and i >= 1 and i <= -2 + N and t >= 1 and t <= -1 + 2T) }
+[T, N] -> { : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 3; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c
new file mode 100644
index 00000000000..41e3ae6094e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.c
@@ -0,0 +1,35 @@
+{
+ for (int c1 = -1; c1 < T; c1 += 1)
+ for (int c2 = 0; c2 < N; c2 += 1) {
+ if (c1 == -1) {
+ s0(1, -1, c2, 0, 0);
+ } else if (c2 == 0) {
+ s0(1, c1, 0, 0, 0);
+ } else if (c2 + 1 == N)
+ s0(1, c1, N - 1, 0, 0);
+ }
+ for (int c1 = 0; c1 <= floord(T - 1, 500); c1 += 1) {
+ for (int c3 = -((c1 + 9) / 8) + 2; c3 <= floord(N - 500 * c1 - 3, 4000) + 1; c3 += 1)
+ for (int c4 = max(500 * c1 + 1, 1000 * c1 + 4000 * c3 - 3999); c4 <= min(min(N + T - 3, 1000 * c1 + 4000 * c3 - 3000), 2 * N - 4000 * c3 + 3995); c4 += 1)
+ for (int c5 = max(0, -N - 500 * c1 + c4 + 2); c5 <= min(min(T - 500 * c1 - 1, -500 * c1 + c4 - 1), -500 * c1 - 2000 * c3 + (c4 + 1) / 2 + 1999); c5 += 1)
+ s1(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+ for (int c3 = max(-((T + 4000) / 4000) + 2, -((c1 + 9) / 8) + 2); c3 <= floord(N - 500 * c1 - 3, 4000) + 1; c3 += 1)
+ for (int c4 = max(1000 * c1 + 4000 * c3 - 3999, -4000 * c3 + 4000); c4 <= min(min(2 * T + 4000 * c3 - 4000, 1000 * c1 + 4000 * c3 - 3000), 2 * N - 4000 * c3 + 3995); c4 += 1)
+ s2(2, -2000 * c3 + (c4 + 1) / 2 + 1999, 1, 2000 * c3 + c4 - (c4 + 1) / 2 - 1999, 1);
+ for (int c3 = -((c1 + 7) / 8) + 1; c3 <= min(floord(N + T - 1000 * c1 - 1004, 4000) + 1, floord(N - 500 * c1 - 504, 4000) + 1); c3 += 1)
+ for (int c4 = max(500 * c1 + 1, 1000 * c1 + 4000 * c3 - 2999); c4 <= min(min(N + T - 3, N + 500 * c1 + 497), 1000 * c1 + 4000 * c3); c4 += 1)
+ for (int c5 = max(0, -N - 500 * c1 + c4 + 2); c5 <= min(min(499, T - 500 * c1 - 1), -500 * c1 + c4 - 1); c5 += 1)
+ s3(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+ for (int c3 = max(-((T + 4000) / 4000) + 1, -((c1 + 9) / 8) + 1); c3 <= floord(N - 500 * c1 - 3, 4000); c3 += 1)
+ for (int c4 = max(-4000 * c3, 1000 * c1 + 4000 * c3 + 1); c4 <= min(min(2 * N - 4000 * c3 - 5, 2 * T + 4000 * c3), 1000 * c1 + 4000 * c3 + 1000); c4 += 1)
+ s4(2, -2000 * c3 + (c4 + 1) / 2 - 1, 1, 2000 * c3 + c4 - (c4 + 1) / 2 + 1, 1);
+ for (int c3 = -((c1 + 8) / 8) + 1; c3 <= min(floord(N + T - 1000 * c1 - 4, 4000), floord(N - 500 * c1 + 496, 4000)); c3 += 1)
+ for (int c4 = max(1000 * c1 + 4000 * c3 + 1, -4000 * c3 + 2); c4 <= min(min(min(N + T - 3, N + 500 * c1 + 497), 2 * T + 4000 * c3 - 2), 1000 * c1 + 4000 * c3 + 998); c4 += 1)
+ for (int c5 = max(-N - 500 * c1 + c4 + 2, -500 * c1 - 2000 * c3 + (c4 + 1) / 2); c5 <= min(min(499, T - 500 * c1 - 1), -500 * c1 + c4 - 1); c5 += 1)
+ s5(2, 500 * c1 + c5, 1, -500 * c1 + c4 - c5, 1);
+ }
+ if (T >= 1)
+ for (int c3 = -((T + 3998) / 4000) + 1; c3 <= floord(N - T - 2, 4000) + 1; c3 += 1)
+ for (int c4 = max(T, 2 * T + 4000 * c3 - 4001); c4 < min(N + T - 2, 2 * T + 4000 * c3 - 1); c4 += 1)
+ s6(2, T - 1, 1, -T + c4 + 1, 1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in
new file mode 100644
index 00000000000..0f86a1c38b9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-mp-i_ts-m_b-0.in
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, t, 1, i, 1] -> [2, tb, 1, proc, t + i, t - 500tb, 0] : 4000proc >= 3000 + t + i - 1000tb and 500tb <= t and 4000proc <= 3999 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s0[1, -1, c, 0, 0] -> [1, -1, c, 0, 0, 0, 0] : c >= 0 and c <= -1 + N; s0[1, b, 0, 0, 0] -> [1, b, 0, 0, 0, 0, 0] : b >= 0 and b <= -1 + T; s0[1, b, -1 + N, 0, 0] -> [1, b, -1 + N, 0, 0, 0, 0] : b >= 0 and b <= -1 + T; s6[2, -1 + T, 1, i, 1] -> [3, tb, 7, proc, -1 + T + i, -1 + T - 500tb, 0] : 500tb <= -1 + T and 500tb >= -500 + T and 4000proc >= 1 - T + i and 4000proc <= 4000 - T + i and i >= 1 and i <= -2 + N and T >= 1; s3[2, t, 1, i, 1] -> [2, tb, 3, proc, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000proc <= 2999 + t + i - 1000tb and 4000proc >= t + i - 1000tb and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s2[2, t, 1, i, 1] -> [2, tb, 2, proc, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000proc <= 3999 - t + i and 4000proc >= 3998 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s4[2, t, 1, i, 1] -> [2, tb, 4, Out_4, t + i, t - 500tb, 0] : 500tb <= t and 500tb >= -499 + t and 4000Out_4 <= -1 - t + i and 4000Out_4 >= -2 - t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T; s5[2, t, 1, i, 1] -> [2, tb, 5, proc, t + i, t - 500tb, 0] : 500tb >= -499 + t and 4000proc <= -1 + t + i - 1000tb and 4000proc >= -t + i and i >= 1 and i <= -2 + N and t >= 0 and t <= -1 + T }
+[T, N] -> { : T >= 0 and N >= 4 }
+[N, T] -> { [i0, i1, i2, i3, i4, i5, i6] -> atomic[o0] : o0 <= 5; [i0, i1, i2, i3, i4, i5, i6] -> separate[o0] : o0 >= 6 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.c
new file mode 100644
index 00000000000..9eff756c5bd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.c
@@ -0,0 +1,10 @@
+{
+ for (int c1 = 0; c1 < N; c1 += 1)
+ s0(1, c1, 1, 0, 0);
+ for (int c1 = 0; c1 < T; c1 += 1) {
+ for (int c3 = 0; c3 < N; c3 += 1)
+ s1(2, c1, 0, c3, 1);
+ for (int c3 = 1; c3 < N - 1; c3 += 1)
+ s2(2, c1, 1, c3, 1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.in
new file mode 100644
index 00000000000..153ba7e9bfe
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/ts1d-orig0-0.in
@@ -0,0 +1,3 @@
+[T, N] -> { s1[2, In_2, 0, In_4, 1] -> [2, In_2, 0, In_4, 1] : In_4 >= 0 and In_4 <= -1 + N and In_2 >= 0 and In_2 <= -1 + T; s0[1, In_2, 1, 0, 0] -> [1, In_2, 1, 0, 0] : In_2 >= 0 and In_2 <= -1 + N; s2[2, In_2, 1, In_4, 1] -> [2, In_2, 1, In_4, 1] : In_4 >= 1 and In_4 <= -2 + N and In_2 >= 0 and In_2 <= -1 + T }
+[T, N] -> { : T >= 0 and N >= 4 }
+[N] -> { [i0, i1, i2, i3, i4] -> separate[o0] : o0 >= 4; [i0, i1, i2, i3, i4] -> atomic[o0] : o0 <= 3 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.c
new file mode 100644
index 00000000000..2c310e8d2ee
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.c
@@ -0,0 +1,27 @@
+{
+ for (int c0 = a2; c0 <= min(min(a1 - 1, a3 - 1), b2); c0 += 1)
+ s1(c0);
+ for (int c0 = a1; c0 <= min(b1, a3 - 1); c0 += 1) {
+ s0(c0);
+ if (c0 >= a2 && b2 >= c0)
+ s1(c0);
+ }
+ for (int c0 = max(max(a1, b1 + 1), a2); c0 <= min(a3 - 1, b2); c0 += 1)
+ s1(c0);
+ for (int c0 = a3; c0 <= b3; c0 += 1) {
+ if (c0 >= a1 && b1 >= c0)
+ s0(c0);
+ if (c0 >= a2 && b2 >= c0)
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = max(max(a3, b3 + 1), a2); c0 <= min(a1 - 1, b2); c0 += 1)
+ s1(c0);
+ for (int c0 = max(max(a1, a3), b3 + 1); c0 <= b1; c0 += 1) {
+ s0(c0);
+ if (c0 >= a2 && b2 >= c0)
+ s1(c0);
+ }
+ for (int c0 = max(max(max(max(a1, b1 + 1), a3), b3 + 1), a2); c0 <= b2; c0 += 1)
+ s1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.in
new file mode 100644
index 00000000000..4cf37cb3192
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-0.in
@@ -0,0 +1,3 @@
+[a3, b3, a2, b2, a1, b1] -> { s2[i] -> [i, 2] : i >= a3 and i <= b3; s0[i] -> [i, 0] : i >= a1 and i <= b1; s1[i] -> [i, 1] : i >= a2 and i <= b2 }
+{ : }
+[a1, b1] -> { [i0, i1] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.c
new file mode 100644
index 00000000000..7fdda1dd58c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.c
@@ -0,0 +1,55 @@
+{
+ for (int c0 = a2; c0 <= min(min(a1 - 1, a3 - 1), b2); c0 += 1)
+ s1(c0);
+ for (int c0 = a3; c0 <= min(min(a1 - 1, b3), a2 - 1); c0 += 1)
+ s2(c0);
+ for (int c0 = max(a3, a2); c0 <= min(min(a1 - 1, b3), b2); c0 += 1) {
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = a1; c0 <= min(min(b1, a3 - 1), a2 - 1); c0 += 1)
+ s0(c0);
+ for (int c0 = max(a1, a2); c0 <= min(min(b1, a3 - 1), b2); c0 += 1) {
+ s0(c0);
+ s1(c0);
+ }
+ for (int c0 = max(max(a1, b1 + 1), a2); c0 <= min(a3 - 1, b2); c0 += 1)
+ s1(c0);
+ for (int c0 = max(a1, a3); c0 <= min(min(b1, b3), a2 - 1); c0 += 1) {
+ s0(c0);
+ s2(c0);
+ }
+ for (int c0 = max(max(a1, b1 + 1), a3); c0 <= min(b3, a2 - 1); c0 += 1)
+ s2(c0);
+ for (int c0 = max(max(a1, a3), a2); c0 <= min(min(b1, b3), b2); c0 += 1) {
+ s0(c0);
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = max(max(max(a1, b1 + 1), a3), a2); c0 <= min(b3, b2); c0 += 1) {
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = max(max(a3, a2), b2 + 1); c0 <= min(a1 - 1, b3); c0 += 1)
+ s2(c0);
+ for (int c0 = max(max(a1, a2), b2 + 1); c0 <= min(b1, a3 - 1); c0 += 1)
+ s0(c0);
+ for (int c0 = max(max(max(a1, a3), a2), b2 + 1); c0 <= min(b1, b3); c0 += 1) {
+ s0(c0);
+ s2(c0);
+ }
+ for (int c0 = max(max(max(max(a1, b1 + 1), a3), a2), b2 + 1); c0 <= b3; c0 += 1)
+ s2(c0);
+ for (int c0 = max(max(a3, b3 + 1), a2); c0 <= min(a1 - 1, b2); c0 += 1)
+ s1(c0);
+ for (int c0 = max(max(a1, a3), b3 + 1); c0 <= min(b1, a2 - 1); c0 += 1)
+ s0(c0);
+ for (int c0 = max(max(max(a1, a3), b3 + 1), a2); c0 <= min(b1, b2); c0 += 1) {
+ s0(c0);
+ s1(c0);
+ }
+ for (int c0 = max(max(max(max(a1, b1 + 1), a3), b3 + 1), a2); c0 <= b2; c0 += 1)
+ s1(c0);
+ for (int c0 = max(max(max(max(a1, a3), b3 + 1), a2), b2 + 1); c0 <= b1; c0 += 1)
+ s0(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.in
new file mode 100644
index 00000000000..75c96d49895
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak1-1.in
@@ -0,0 +1,3 @@
+[a3, b3, a2, b2, a1, b1] -> { s2[i] -> [i, 2] : i >= a3 and i <= b3; s0[i] -> [i, 0] : i >= a1 and i <= b1; s1[i] -> [i, 1] : i >= a2 and i <= b2 }
+{ : }
+[a1, b1] -> { [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.c
new file mode 100644
index 00000000000..3f51dbca273
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.c
@@ -0,0 +1,26 @@
+{
+ for (int c0 = a1; c0 <= min(b1, a2 - 1); c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ if (c2 >= d2 + 1) {
+ for (int c0 = max(a1, a2); c0 <= min(b1, b2); c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ } else
+ for (int c0 = a2; c0 <= b2; c0 += 1) {
+ if (c0 >= a1 && b1 >= c0)
+ for (int c1_0 = c1; c1_0 <= min(d1, c2 - 1); c1_0 += 1)
+ s0(c0, c1_0);
+ for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1) {
+ if (c0 >= a1 && b1 >= c0 && c1_0 >= c1 && d1 >= c1_0)
+ s0(c0, c1_0);
+ s1(c0, c1_0);
+ }
+ if (c0 >= a1 && b1 >= c0)
+ for (int c1_0 = max(c1, d2 + 1); c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ }
+ for (int c0 = max(max(a1, a2), b2 + 1); c0 <= b1; c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.in
new file mode 100644
index 00000000000..da7a6953bf3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-0.in
@@ -0,0 +1,3 @@
+[a2, b2, c2, d2, a1, b1, c1, d1] -> { s0[i, j] -> [i, j, 0] : i >= a1 and i <= b1 and j >= c1 and j <= d1; s1[i, j] -> [i, j, 1] : i >= a2 and i <= b2 and j >= c2 and j <= d2 }
+{ : }
+[a1, b1, c1, d1] -> { [i0, i1, i2] -> separate[o0] : o0 >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.c
new file mode 100644
index 00000000000..cc20357718a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.c
@@ -0,0 +1,35 @@
+{
+ for (int c0 = a1; c0 <= min(b1, a2 - 1); c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ if (c2 >= d2 + 1) {
+ for (int c0 = max(a1, a2); c0 <= min(b1, b2); c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ } else
+ for (int c0 = a2; c0 <= b2; c0 += 1) {
+ if (a1 >= c0 + 1) {
+ for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1)
+ s1(c0, c1_0);
+ } else if (c0 >= b1 + 1) {
+ for (int c1_0 = c2; c1_0 <= d2; c1_0 += 1)
+ s1(c0, c1_0);
+ } else {
+ for (int c1_0 = c1; c1_0 <= min(d1, c2 - 1); c1_0 += 1)
+ s0(c0, c1_0);
+ for (int c1_0 = c2; c1_0 <= min(c1 - 1, d2); c1_0 += 1)
+ s1(c0, c1_0);
+ for (int c1_0 = max(c1, c2); c1_0 <= min(d1, d2); c1_0 += 1) {
+ s0(c0, c1_0);
+ s1(c0, c1_0);
+ }
+ for (int c1_0 = max(c1, d2 + 1); c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+ for (int c1_0 = max(max(c1, d1 + 1), c2); c1_0 <= d2; c1_0 += 1)
+ s1(c0, c1_0);
+ }
+ }
+ for (int c0 = max(max(a1, a2), b2 + 1); c0 <= b1; c0 += 1)
+ for (int c1_0 = c1; c1_0 <= d1; c1_0 += 1)
+ s0(c0, c1_0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.in
new file mode 100644
index 00000000000..c92ac3c82c8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak2-1.in
@@ -0,0 +1,3 @@
+[a2, b2, c2, d2, a1, b1, c1, d1] -> { s0[i, j] -> [i, j, 0] : i >= a1 and i <= b1 and j >= c1 and j <= d1; s1[i, j] -> [i, j, 1] : i >= a2 and i <= b2 and j >= c2 and j <= d2 }
+{ : }
+[a1, b1, c1, d1] -> { [i0, i1, i2] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.c
new file mode 100644
index 00000000000..06be04aae78
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.c
@@ -0,0 +1,8 @@
+for (int c0 = a; c0 <= b + 20; c0 += 1) {
+ if (b >= c0)
+ s0(c0);
+ if (c0 >= a + 10 && b + 10 >= c0)
+ s1(c0);
+ if (c0 >= a + 20)
+ s2(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.in
new file mode 100644
index 00000000000..a4c4de9c88c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-0.in
@@ -0,0 +1,3 @@
+[a, b] -> { s2[i] -> [i, 2] : i >= 20 + a and i <= 20 + b; s0[i] -> [i, 0] : i >= a and i <= b; s1[i] -> [i, 1] : i >= 10 + a and i <= 10 + b }
+{ : }
+[a, b] -> { [i0, i1] -> atomic[o0] : o0 <= 0; [i0, i1] -> separate[o0] : o0 >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.c
new file mode 100644
index 00000000000..3045b2195cb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.c
@@ -0,0 +1,21 @@
+{
+ for (int c0 = a; c0 <= min(a + 9, b); c0 += 1)
+ s0(c0);
+ for (int c0 = a + 10; c0 <= min(a + 19, b); c0 += 1) {
+ s0(c0);
+ s1(c0);
+ }
+ for (int c0 = max(a + 10, b + 1); c0 <= min(a + 19, b + 10); c0 += 1)
+ s1(c0);
+ for (int c0 = a + 20; c0 <= b; c0 += 1) {
+ s0(c0);
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = max(a + 20, b + 1); c0 <= b + 10; c0 += 1) {
+ s1(c0);
+ s2(c0);
+ }
+ for (int c0 = max(a + 20, b + 11); c0 <= b + 20; c0 += 1)
+ s2(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.in
new file mode 100644
index 00000000000..ae319e5ddeb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak3-1.in
@@ -0,0 +1,3 @@
+[a, b] -> { s2[i] -> [i, 2] : i >= 20 + a and i <= 20 + b; s0[i] -> [i, 0] : i >= a and i <= b; s1[i] -> [i, 1] : i >= 10 + a and i <= 10 + b }
+{ : }
+[a, b] -> { [i0, i1] -> atomic[o0] : o0 <= -1; [i0, i1] -> separate[o0] : o0 >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.c
new file mode 100644
index 00000000000..5cefe4be4d3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.c
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(a1, a2), a3), a4), a5); c0 <= min(min(min(min(b1, b2), b3), b4), b5); c0 += 1) {
+ s0(c0);
+ s1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.in
new file mode 100644
index 00000000000..9862df21458
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-0.in
@@ -0,0 +1,3 @@
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { s0[i] -> [i, 0] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5; s1[i] -> [i, 1] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5 }
+{ : }
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { [i0, i1] -> separate[o0] : o0 >= 1; [i0, i1] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.c
new file mode 100644
index 00000000000..5cefe4be4d3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.c
@@ -0,0 +1,4 @@
+for (int c0 = max(max(max(max(a1, a2), a3), a4), a5); c0 <= min(min(min(min(b1, b2), b3), b4), b5); c0 += 1) {
+ s0(c0);
+ s1(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.in
new file mode 100644
index 00000000000..076cdd1f48a
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/wak4-1.in
@@ -0,0 +1,3 @@
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { s0[i] -> [i, 0] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5; s1[i] -> [i, 1] : i >= a1 and i >= a2 and i >= a3 and i >= a4 and i >= a5 and i <= b1 and i <= b2 and i <= b3 and i <= b4 and i <= b5 }
+{ : }
+[a1, a2, a3, a4, a5, b1, b2, b3, b4, b5] -> { [i0, i1] -> separate[o0] : o0 >= 0; [i0, i1] -> atomic[o0] : o0 <= -1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/x-0.c b/polly/lib/External/isl/test_inputs/codegen/omega/x-0.c
new file mode 100644
index 00000000000..f890920d709
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/x-0.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 11; c0 += 1) {
+ for (int c1 = max(1, c0 - 3); c1 <= min(c0, -c0 + 8); c1 += 1)
+ s1(c1, c0 - c1 + 1);
+ for (int c1 = max(1, -c0 + 9); c1 <= min(c0 - 4, -c0 + 12); c1 += 1)
+ s0(c1, c0 + c1 - 8);
+ for (int c1 = max(c0 - 3, -c0 + 9); c1 <= min(c0, -c0 + 12); c1 += 1) {
+ s0(c1, c0 + c1 - 8);
+ s1(c1, c0 - c1 + 1);
+ }
+ for (int c1 = max(c0 - 3, -c0 + 13); c1 <= min(8, c0); c1 += 1)
+ s1(c1, c0 - c1 + 1);
+ for (int c1 = max(c0 + 1, -c0 + 9); c1 <= min(8, -c0 + 12); c1 += 1)
+ s0(c1, c0 + c1 - 8);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/x-0.in b/polly/lib/External/isl/test_inputs/codegen/omega/x-0.in
new file mode 100644
index 00000000000..24340efe4d8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/x-0.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [8 - i + j, i, 0] : i >= 1 and i <= 8 and j >= 1 and j <= 4; s1[i, j] -> [-1 + i + j, i, 1] : i >= 1 and i <= 8 and j >= 1 and j <= 4 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/x-1.c b/polly/lib/External/isl/test_inputs/codegen/omega/x-1.c
new file mode 100644
index 00000000000..f890920d709
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/x-1.c
@@ -0,0 +1,14 @@
+for (int c0 = 1; c0 <= 11; c0 += 1) {
+ for (int c1 = max(1, c0 - 3); c1 <= min(c0, -c0 + 8); c1 += 1)
+ s1(c1, c0 - c1 + 1);
+ for (int c1 = max(1, -c0 + 9); c1 <= min(c0 - 4, -c0 + 12); c1 += 1)
+ s0(c1, c0 + c1 - 8);
+ for (int c1 = max(c0 - 3, -c0 + 9); c1 <= min(c0, -c0 + 12); c1 += 1) {
+ s0(c1, c0 + c1 - 8);
+ s1(c1, c0 - c1 + 1);
+ }
+ for (int c1 = max(c0 - 3, -c0 + 13); c1 <= min(8, c0); c1 += 1)
+ s1(c1, c0 - c1 + 1);
+ for (int c1 = max(c0 + 1, -c0 + 9); c1 <= min(8, -c0 + 12); c1 += 1)
+ s0(c1, c0 + c1 - 8);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/omega/x-1.in b/polly/lib/External/isl/test_inputs/codegen/omega/x-1.in
new file mode 100644
index 00000000000..24340efe4d8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/omega/x-1.in
@@ -0,0 +1,3 @@
+{ s0[i, j] -> [8 - i + j, i, 0] : i >= 1 and i <= 8 and j >= 1 and j <= 4; s1[i, j] -> [-1 + i + j, i, 1] : i >= 1 and i <= 8 and j >= 1 and j <= 4 }
+{ : }
+{ [i0, i1, i2] -> separate[o0] : o0 >= 1; [i0, i1, i2] -> atomic[o0] : o0 <= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/README b/polly/lib/External/isl/test_inputs/codegen/pldi2012/README
new file mode 100644
index 00000000000..316e8387782
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/README
@@ -0,0 +1,2 @@
+These examples are taken from the "Polyhedra Scanning Revisited" paper
+by Chun Chen.
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.c b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.c
new file mode 100644
index 00000000000..18ca3702186
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.c
@@ -0,0 +1,9 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (n >= 2)
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ if (n >= 2)
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.in b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.in
new file mode 100644
index 00000000000..93149176bc4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_b.in
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+ s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+ s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> { : }
+[n] -> { [i,j] -> separate[x] : x >= 2 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.c b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.c
new file mode 100644
index 00000000000..d1ce579aa97
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.c
@@ -0,0 +1,11 @@
+for (int c0 = 1; c0 <= 100; c0 += 1) {
+ if (n >= 2) {
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+ } else
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s2(c0, c1);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.in b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.in
new file mode 100644
index 00000000000..06a32663ec8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_c.in
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+ s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+ s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> { : }
+[n] -> { [i,j] -> separate[x] : x >= 1 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.c b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.c
new file mode 100644
index 00000000000..570cbe5556f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.c
@@ -0,0 +1,12 @@
+if (n >= 2) {
+ for (int c0 = 1; c0 <= 100; c0 += 1) {
+ s0(c0);
+ for (int c1 = 1; c1 <= 100; c1 += 1) {
+ s1(c0, c1);
+ s2(c0, c1);
+ }
+ }
+} else
+ for (int c0 = 1; c0 <= 100; c0 += 1)
+ for (int c1 = 1; c1 <= 100; c1 += 1)
+ s2(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.in b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.in
new file mode 100644
index 00000000000..339e39d8cee
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure7_d.in
@@ -0,0 +1,5 @@
+[n] -> { s0[i] -> [i,0] : 1 <= i <= 100 and n > 1;
+ s1[i,j] -> [i,j] : 1 <= i,j <= 100 and n > 1;
+ s2[i,j] -> [i,j] : 1 <= i,j <= 100 }
+[n] -> { : }
+[n] -> { [i,j] -> separate[x] : x >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.c b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.c
new file mode 100644
index 00000000000..4608d61d8db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.c
@@ -0,0 +1,3 @@
+for (int c0 = 1; c0 <= n; c0 += 4)
+ for (int c1 = c0; c1 <= n; c1 += 3)
+ s0(c0, c1);
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.in b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.in
new file mode 100644
index 00000000000..df6543cce22
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_a.in
@@ -0,0 +1,4 @@
+[n] -> { s0[i,j] -> [i,j] : exists alpha, beta: 1 <= i <= n and i <= j <= n and
+ i = 1 + 4 alpha and j = i + 3 beta}
+[n] -> { : }
+[n] -> {}
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.c b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.c
new file mode 100644
index 00000000000..d7fa3cd8a37
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.c
@@ -0,0 +1,8 @@
+{
+ for (int c0 = 2; c0 < n - 1; c0 += 4) {
+ s1(c0);
+ s0(c0 + 2);
+ }
+ if (n >= 2 && n % 4 >= 2)
+ s1(-(n % 4) + n + 2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.in b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.in
new file mode 100644
index 00000000000..2effb0a09cd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/pldi2012/figure8_b.in
@@ -0,0 +1,4 @@
+[n] -> { s0[i] -> [i] : exists alpha: 1 <= i <= n and i = 4 alpha;
+ s1[i] -> [i] : exists alpha: 1 <= i <= n and i = 4 alpha + 2 }
+[n] -> { : }
+[n] -> { }
diff --git a/polly/lib/External/isl/test_inputs/codegen/roman.c b/polly/lib/External/isl/test_inputs/codegen/roman.c
new file mode 100644
index 00000000000..1dd43c52012
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/roman.c
@@ -0,0 +1,32 @@
+{
+ for (int c1 = 0; c1 <= min(np1 - i, -i + 1); c1 += 1) {
+ S_9(c1);
+ S_12(c1);
+ }
+ for (int c1 = max(0, -i + 2); c1 <= -((-np1 + i + 4294967295) % 4294967296) + 4294967295; c1 += 1) {
+ S_9(c1);
+ S_10(c1);
+ for (int c3 = 0; c3 <= min(19, i + c1 - 3); c3 += 1) {
+ S_15(c1, c3);
+ for (int c5 = 0; c5 < c3; c5 += 1) {
+ S_16(c1, c3, c5);
+ S_17(c1, c3, c5);
+ }
+ S_16(c1, c3, c3);
+ S_18(c1, c3);
+ S_24(c1, c3);
+ S_19(c1, c3);
+ }
+ if (np1 >= i && 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);
+ S_17(c1, i + c1 - 2, c5);
+ }
+ S_16(c1, i + c1 - 2, i + c1 - 2);
+ S_18(c1, i + c1 - 2);
+ S_24(c1, i + c1 - 2);
+ }
+ S_12(c1);
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/roman.in b/polly/lib/External/isl/test_inputs/codegen/roman.in
new file mode 100644
index 00000000000..55182a6efdb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/roman.in
@@ -0,0 +1,5 @@
+# Older versions of isl would get confused on this input due to disappearing
+# div constraints.
+[np1, i] -> { S_17[i0, i1, i2] -> [0, i0, 2, i1, 1, i2, 1] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296], e2 = [(i1)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i2 >= 0 and 4294967296e2 <= i1 and 4294967296e2 >= -4294967295 + i1 and 4294967296e2 <= i1 - i2 and i2 <= 19 and i0 >= 2 - i and i2 <= -1 + i1); S_18[i0, i1] -> [0, i0, 2, i1, 2, 0, 0] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i0 >= 2 - i); S_24[i0, i1] -> [0, i0, 2, i1, 3, 0, 0] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i0 >= 2 - i); S_15[i0, i1] -> [0, i0, 2, i1, 0, 0, 0] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i0 >= 2 - i); S_9[i0] -> [0, i0, 0, 0, 0, 0, 0] : exists (e0 = [(np1 - i)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20); S_10[i0] -> [0, i0, 1, 0, 0, 0, 0] : exists (e0 = [(np1 - i)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i0 >= 2 - i); S_19[i0, i1] -> [0, i0, 2, i1, 4, 0, 0] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i0 >= 2 - i and i1 <= -3 + i + i0); S_12[i0] -> [0, i0, 3, 0, 0, 0, 0] : exists (e0 = [(np1 - i)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20); S_16[i0, i1, i2] -> [0, i0, 2, i1, 1, i2, 0] : exists (e0 = [(np1 - i)/4294967296], e1 = [(-2 + i + i0)/4294967296], e2 = [(i1)/4294967296]: i0 >= 0 and 4294967296e0 <= np1 - i and 4294967296e0 >= -4294967295 + np1 - i and 4294967296e0 <= np1 - i - i0 and i0 <= 20 and i1 >= 0 and 4294967296e1 <= -2 + i + i0 and 4294967296e1 >= -4294967297 + i + i0 and 4294967296e1 <= -2 + i + i0 - i1 and i1 <= 19 and i2 >= 0 and 4294967296e2 <= i1 and 4294967296e2 >= -4294967295 + i1 and 4294967296e2 <= i1 - i2 and i2 <= 19 and i0 >= 2 - i) }
+[np1, i] -> { : exists (e0 = [(np1 - i)/4294967296]: 4294967296e0 <= np1 - i and 4294967296e0 >= -20 + np1 - i and np1 >= -2147483648 and np1 <= 2147483647 and i >= -2147483648 and i <= 2147483647) }
+[np1, i] -> { [i0, i1, i2, i3, i4, i5, i6] -> separate[o0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/separate.c b/polly/lib/External/isl/test_inputs/codegen/separate.c
new file mode 100644
index 00000000000..042e3e77c6c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separate.c
@@ -0,0 +1,8 @@
+{
+ a(0);
+ for (int c0 = 1; c0 <= 9; c0 += 1) {
+ b(c0 - 1);
+ a(c0);
+ }
+ b(9);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separate.in b/polly/lib/External/isl/test_inputs/codegen/separate.in
new file mode 100644
index 00000000000..58486c3d356
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separate.in
@@ -0,0 +1,3 @@
+{ a[i] -> [i] : 0 <= i < 10; b[i] -> [i+1] : 0 <= i < 10 }
+{ : }
+{ [i] -> separate[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/separate2.c b/polly/lib/External/isl/test_inputs/codegen/separate2.c
new file mode 100644
index 00000000000..81668215c9e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separate2.c
@@ -0,0 +1,9 @@
+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);
+ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/separate2.in b/polly/lib/External/isl/test_inputs/codegen/separate2.in
new file mode 100644
index 00000000000..8f4ebf1a5b9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separate2.in
@@ -0,0 +1,4 @@
+# Check that rational affine expressions are printer properly.
+[tsteps, length] -> { S_0[iter, i, j] -> [iter, 0, o2, o3, 0, o5, o6, 4] : exists (e0 = [(o2)/32], e1 = [(o3)/32], e2 = [(-i + o5)/32], e3 = [(-31 + j - o6)/32]: tsteps = 2 and 32e0 = o2 and 32e1 = o3 and 32e2 = -i + o5 and 32e3 = -31 + j - o6 and o2 <= i and o2 >= -31 + i and o3 <= 1 + j and o3 >= -30 + j and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 31 and i <= -1 + length and i >= 0 and iter >= 0 and iter <= 1 and j <= -1 + length and j >= 0 and o2 >= -31 + length and o3 >= -30 + 2length); S_3[iter, 0, j] -> [iter, 0, o2, o3, o4, o5, o6, 2] : exists (e0 = [(o2)/32], e1 = [(o3)/32], e2 = [(o4)/32], e3 = [(-2o5 + o6)/32], e4 = [(j - o5)/32]: tsteps = 2 and 32e0 = o2 and 32e1 = o3 and 32e2 = o4 and 32e3 = -2o5 + o6 and 32e4 = j - o5 and iter <= 1 and j <= -1 + length and o2 <= j and o2 >= -31 + j and o3 <= 2j and o3 >= -30 + 2j and o4 >= 0 and o4 <= 31 and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 30 and j >= 1 and iter >= 0 and o2 >= -31 + length and o3 >= -30 + 2length) }
+[tsteps, length] -> { : length >= 1 and length <= 1024 and tsteps = 2 }
+{ [o0,o1,o2,o3,o4,o5,o6,o7] -> separate[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class.c b/polly/lib/External/isl/test_inputs/codegen/separation_class.c
new file mode 100644
index 00000000000..daac0d76a88
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class.c
@@ -0,0 +1,17 @@
+{
+ for (int c0 = 0; c0 <= 8; c0 += 1) {
+ for (int c1 = 0; c1 <= -c0 + 8; c1 += 1)
+ for (int c2 = 10 * c0; c2 <= 10 * c0 + 9; c2 += 1)
+ for (int c3 = 10 * c1; c3 <= 10 * c1 + 9; c3 += 1)
+ A(c2, c3);
+ for (int c1 = -c0 + 9; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0; c2 <= min(10 * c0 + 9, -10 * c1 + 100); c2 += 1)
+ for (int c3 = 10 * c1; c3 <= min(10 * c1 + 9, -c2 + 100); c3 += 1)
+ A(c2, c3);
+ }
+ for (int c0 = 9; c0 <= 10; c0 += 1)
+ for (int c1 = 0; c1 <= -c0 + 10; c1 += 1)
+ for (int c2 = 10 * c0; c2 <= min(10 * c0 + 9, -10 * c1 + 100); c2 += 1)
+ for (int c3 = 10 * c1; c3 <= min(10 * c1 + 9, -c2 + 100); c3 += 1)
+ A(c2, c3);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class.in b/polly/lib/External/isl/test_inputs/codegen/separation_class.in
new file mode 100644
index 00000000000..f42ea27fa56
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class.in
@@ -0,0 +1,6 @@
+{ A[i,j] -> [([i/10]),[j/10],i,j] : 0 <= i,j and i + j <= 100 }
+{ : }
+{ [a,b,c,d] -> separation_class[[0]->[0]] :
+ exists b': 0 <= 10a,10b' and 10a+9+10b'+9 <= 100;
+ [a,b,c,d] -> separation_class[[1]->[0]] :
+ 0 <= 10a,10b and 10a+9+10b+9 <= 100 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class2.c b/polly/lib/External/isl/test_inputs/codegen/separation_class2.c
new file mode 100644
index 00000000000..0fdbc3238e3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class2.c
@@ -0,0 +1,15 @@
+{
+ for (int c0 = 0; c0 < -(n % 8) + n; c0 += 8) {
+ for (int c1 = 0; c1 < -(n % 8) + n; c1 += 8)
+ for (int c2 = 0; c2 <= 7; c2 += 1)
+ for (int c3 = 0; c3 <= 7; c3 += 1)
+ 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);
+ }
+ 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);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class2.in b/polly/lib/External/isl/test_inputs/codegen/separation_class2.in
new file mode 100644
index 00000000000..5469626ae7e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class2.in
@@ -0,0 +1,3 @@
+[n] -> { A[i,j] -> [it,jt, ip, jp] : 0 <= i,j < n and ip = i % 8 and it = i - ip and jp = j % 8 and jt = j - jp}
+[n] -> { : n >= 10}
+[n] -> { [it, jt, ip, jp] -> separation_class[[x]->[1]]: (exists id, jd: 0 <= x <= 3 and it < n - id and jt < n - jd and id = n %8 and jd = n %8)}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class3.c b/polly/lib/External/isl/test_inputs/codegen/separation_class3.c
new file mode 100644
index 00000000000..d21b19c29bc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class3.c
@@ -0,0 +1,29 @@
+for (int c0 = 0; c0 <= 4; c0 += 1) {
+ if (c0 == 0) {
+ S_0(0, 4);
+ } else {
+ S_0(2 * c0 - 1, 1);
+ if (c0 == 4) {
+ for (int c6 = 3; c6 <= 5; c6 += 1)
+ S_0(7, c6);
+ } else
+ for (int c4 = 2 * c0 - 1; c4 <= 2 * c0; c4 += 1)
+ for (int c6 = -2 * c0 + c4 + 4; c6 <= 2 * c0 - c4 + 4; c6 += 1)
+ S_0(c4, c6);
+ }
+ for (int c4 = max(0, 2 * c0 - 1); c4 <= min(7, 2 * c0); c4 += 1)
+ for (int c6 = -2 * c0 + c4 + 8; c6 <= 8; c6 += 1)
+ S_0(c4, c6);
+ if (c0 >= 1 && c0 <= 3) {
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ for (int c4 = 2 * c0 - 1; c4 <= 2 * c0; c4 += 1)
+ for (int c6 = 2 * c0 + 4 * c2 - c4 + 1; c6 <= -2 * c0 + 4 * c2 + c4 + 3; c6 += 1)
+ S_0(c4, c6);
+ } else if (c0 == 4) {
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ S_0(7, 4 * c2 + 2);
+ } else
+ for (int c2 = 0; c2 <= 1; c2 += 1)
+ for (int c6 = 4 * c2 + 1; c6 <= 4 * c2 + 3; c6 += 1)
+ S_0(0, c6);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class3.in b/polly/lib/External/isl/test_inputs/codegen/separation_class3.in
new file mode 100644
index 00000000000..1aaf2517c18
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class3.in
@@ -0,0 +1,4 @@
+{ S_0[t, i] -> [o0, 1, o2, 0, t, 0, i] : 4o2 >= -4 + t + i - 2o0 and 4o2 >= -3 - t + i + 2o0 and 2o0 <= 1 + t and 2o0 >= t and 4o2 <= -1 + t + i - 2o0 and t >= 0 and t <= 7 and i >= 1 and i <= 8; S_0[t, i] -> [o0, 0, o2, 0, t, 0, i] : 4o2 >= t + i - 2o0 and 4o2 <= -t + i + 2o0 and 2o0 <= 1 + t and 2o0 >= t and t >= 0 and t <= 7 and i >= 1 and i <= 8 }
+{:}
+{ [i0, 1, i2, i3, i4, i5, i6] -> separation_class[[2] -> [0]] : i2 <= 1 and i2 >= 0 and i0 <= 3 and i0 >= 1; [i0, 0, 1, i3, i4, i5, i6] -> separation_class[[2] -> [0]] : i0 <= 3 and i0 >= 1; [i0, i1, i2, i3, i4, i5, i6] -> unroll[1] }
+
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class4.c b/polly/lib/External/isl/test_inputs/codegen/separation_class4.c
new file mode 100644
index 00000000000..2ff23642e8d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class4.c
@@ -0,0 +1,20 @@
+for (int c0 = 0; c0 <= 128; c0 += 1) {
+ if (c0 <= 127) {
+ if (c0 == 0) {
+ for (int c3 = 0; c3 <= 1; c3 += 1)
+ for (int c5 = c3 + 58; c5 <= -c3 + 61; c5 += 1)
+ S_0(c3, c5);
+ } else
+ for (int c2 = 1; c2 <= 2; c2 += 1)
+ for (int c3 = max(4 * c0 - 2, 4 * c0 + 6 * c2 - 12); c3 <= min(4 * c0 + 1, 4 * c0 + 6 * c2 - 7); c3 += 1)
+ for (int c5 = max(4 * c0 - c3 + 57, -4 * c0 + c3 + 58); c5 <= min(4 * c0 - c3 + 61, -4 * c0 + c3 + 62); c5 += 1)
+ S_0(c3, c5);
+ for (int c2 = 1; c2 <= 2; c2 += 1)
+ for (int c3 = max(4 * c0, 4 * c0 + 6 * c2 - 10); c3 <= min(4 * c0 + 3, 4 * c0 + 6 * c2 - 5); c3 += 1)
+ for (int c5 = max(-4 * c0 + c3 + 59, 4 * c0 - c3 + 62); c5 <= min(-4 * c0 + c3 + 63, 4 * c0 - c3 + 66); c5 += 1)
+ S_0(c3, c5);
+ } else
+ for (int c3 = 510; c3 <= 511; c3 += 1)
+ for (int c5 = -c3 + 569; c5 < c3 - 449; c5 += 1)
+ S_0(c3, c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/separation_class4.in b/polly/lib/External/isl/test_inputs/codegen/separation_class4.in
new file mode 100644
index 00000000000..c04dd79bf23
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/separation_class4.in
@@ -0,0 +1,10 @@
+# Check that isl is not confused by the combination of separation classes
+# and unroll.
+{ S_0[t, i] -> [o0, 1, o9, t] : 4o0 >= -3 + t and 4o0 <= t and i >= 60 and i <= 65 and 6o9 >= 5 + t - 4o0 and 6o9 <= 10 + t - 4o0 and 4o0 <= -62 + t + i and 4o0 >= 59 + t - i and o0 >= 0 and o0 <= 127 and t <= 511 and t >= 0 and 4o0 >= -66 + t + i and 4o0 <= 63 + t - i;
+S_0[t, i] -> [o0, 0, o9, t] : 4o0 >= -1 + t and 4o0 <= 2 + t and i >= 57 and i <= 62 and 6o9 >= 7 + t - 4o0 and 6o9 <= 12 + t - 4o0 and t >= 0 and t <= 511 and 4o0 <= -57 + t + i and 4o0 >= 58 + t - i and o0 >= 0 and o0 <= 128 and 4o0 >= -61 + t + i and 4o0 <= 62 + t - i }
+{ : }
+{ [i0, i1, i2, t] -> unroll[1];
+[i0, 1, i2, t] -> separation_class[[1] -> [0]]
+ : 0 <= i0 <= 127;
+[i0, 0, i2, t] -> separation_class[[1] -> [0]]
+ : 1 <= i0 <= 127}
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift.c b/polly/lib/External/isl/test_inputs/codegen/shift.c
new file mode 100644
index 00000000000..f4156bca99b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift.c
@@ -0,0 +1,4 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+ A(c0);
+ B(c0);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift.in b/polly/lib/External/isl/test_inputs/codegen/shift.in
new file mode 100644
index 00000000000..702c5275621
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift.in
@@ -0,0 +1,3 @@
+{ A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+{ : }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift2.c b/polly/lib/External/isl/test_inputs/codegen/shift2.c
new file mode 100644
index 00000000000..30ea633b674
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift2.c
@@ -0,0 +1,43 @@
+for (int c0 = 0; c0 <= 1; c0 += 1) {
+ for (int c2 = 0; c2 <= length; c2 += 32) {
+ if (length >= c2 + 1) {
+ for (int c3 = 0; c3 <= length; c3 += 32) {
+ for (int c5 = 0; c5 <= min(31, length - c2 - 1); c5 += 1) {
+ for (int c6 = max(0, -c3 + 1); c6 <= min(min(31, length - c3), 2 * c2 - c3 + 2 * c5 - 1); c6 += 1)
+ S_0(c0, c2 + c5, c3 + c6 - 1);
+ if (c2 + c5 >= 1 && 2 * c2 + 2 * c5 >= c3 && c3 + 30 >= 2 * c2 + 2 * c5) {
+ S_3(c0, 0, c2 + c5);
+ if (length >= 2 * c2 + 2 * c5)
+ S_0(c0, c2 + c5, 2 * c2 + 2 * c5 - 1);
+ }
+ for (int c6 = max(0, 2 * c2 - c3 + 2 * c5 + 1); c6 <= min(31, length - c3); c6 += 1)
+ S_0(c0, c2 + c5, c3 + c6 - 1);
+ }
+ if (length <= 15 && c2 == 0 && c3 == 0)
+ S_4(c0);
+ if (c3 >= 2 * c2 && 2 * c2 + 32 >= c3)
+ for (int c4 = 1; c4 <= min(min(31, length - 2), (c3 / 2) + 14); c4 += 1)
+ for (int c5 = max((c3 / 2) - c2, -c2 + c4 + 1); c5 <= min(length - c2 - 1, (c3 / 2) - c2 + 15); c5 += 1)
+ S_3(c0, c4, c2 + c5);
+ }
+ for (int c3 = max(2 * c2, -(length % 32) + length + 32); c3 <= min(2 * length - 2, 2 * c2 + 62); c3 += 32)
+ for (int c4 = 0; c4 <= min(31, length - 2); c4 += 1) {
+ for (int c5 = max((c3 / 2) - c2, -c2 + c4 + 1); c5 <= min(length - c2 - 1, (c3 / 2) - c2 + 15); c5 += 1)
+ S_3(c0, c4, c2 + c5);
+ if (c3 + 30 >= 2 * length && c4 == 0)
+ S_4(c0);
+ }
+ if (c2 + 16 == length && (length - 16) % 32 == 0)
+ S_4(c0);
+ } else if (length == 0) {
+ S_4(c0);
+ } else
+ S_4(c0);
+ }
+ for (int c1 = 32; c1 < length - 1; c1 += 32)
+ for (int c2 = c1; c2 < length; c2 += 32)
+ for (int c3 = c2; c3 <= min(length - 1, c2 + 31); c3 += 16)
+ for (int c4 = 0; c4 <= min(min(31, length - c1 - 2), -c1 + c3 + 14); c4 += 1)
+ for (int c5 = max(-c2 + c3, c1 - c2 + c4 + 1); c5 <= min(length - c2 - 1, -c2 + c3 + 15); c5 += 1)
+ S_3(c0, c1 + c4, c2 + c5);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift2.in b/polly/lib/External/isl/test_inputs/codegen/shift2.in
new file mode 100644
index 00000000000..3c05fac3687
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift2.in
@@ -0,0 +1,5 @@
+# Check that the shifting code is not confused by domains that
+# have a non-obviously fixed value.
+[tsteps, length] -> { S_4[iter] -> [iter, 0, o2, o3, 0, o5, o6, 3] : exists (e0 = [(o2)/32], e1 = [(o3)/32], e2 = [(-length + o5)/32], e3 = [(-2length + o6)/32]: tsteps = 2 and 32e0 = o2 and 32e1 = o3 and 32e2 = -length + o5 and 32e3 = -2length + o6 and o2 <= length and o2 >= -31 + length and o3 <= 2length and o3 >= -30 + 2length and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 30 and iter <= 1 and iter >= 0); S_3[iter, i, j] -> [iter, o1, o2, o3, o4, o5, o6, 2] : exists (e0 = [(o1)/32], e1 = [(o2)/32], e2 = [(o3)/32], e3 = [(-i + o4)/32], e4 = [(-j + o5)/32], e5 = [(-2j + o6)/32]: tsteps = 2 and 32e0 = o1 and 32e1 = o2 and 32e2 = o3 and 32e3 = -i + o4 and 32e4 = -j + o5 and 32e5 = -2j + o6 and o1 <= i and o1 >= -31 + i and o2 <= j and o2 >= -31 + j and o3 <= 2j and o3 >= -30 + 2j and o4 >= 0 and o4 <= 31 and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 30 and j >= 1 + i and i >= 0 and iter <= 1 and iter >= 0 and j <= -1 + length); S_0[iter, i, j] -> [iter, 0, o2, o3, 0, o5, o6, 4] : exists (e0 = [(o2)/32], e1 = [(o3)/32], e2 = [(-i + o5)/32], e3 = [(-31 + j - o6)/32]: tsteps = 2 and 32e0 = o2 and 32e1 = o3 and 32e2 = -i + o5 and 32e3 = -31 + j - o6 and o2 <= i and o2 >= -31 + i and o3 <= 1 + j and o3 >= -30 + j and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 31 and i <= -1 + length and i >= 0 and iter >= 0 and iter <= 1 and j <= -1 + length and j >= 0) }
+[tsteps, length] -> { : length >= 0 and length <= 1024 and tsteps = 2 }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift_unroll.c b/polly/lib/External/isl/test_inputs/codegen/shift_unroll.c
new file mode 100644
index 00000000000..2a38286272c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift_unroll.c
@@ -0,0 +1,14 @@
+for (int c0 = 0; c0 <= 9; c0 += 1) {
+ A(c0, 0);
+ A(c0, 1);
+ A(c0, 2);
+ A(c0, 3);
+ A(c0, 4);
+ A(c0, 5);
+ A(c0, 6);
+ A(c0, 7);
+ A(c0, 8);
+ A(c0, 9);
+ for (int c2 = 0; c2 <= 9; c2 += 1)
+ B(c0, c2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/shift_unroll.in b/polly/lib/External/isl/test_inputs/codegen/shift_unroll.in
new file mode 100644
index 00000000000..4b773c27ac3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/shift_unroll.in
@@ -0,0 +1,3 @@
+{ A[i,j] -> [2i,0,j]: 0 <= i,j < 10; B[i,j] -> [2i+1,1,j] : 0 <= i,j < 10 }
+{ : }
+{ [i,0,j] -> unroll[2] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/single_valued.c b/polly/lib/External/isl/test_inputs/codegen/single_valued.c
new file mode 100644
index 00000000000..e071002b79d
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/single_valued.c
@@ -0,0 +1,2 @@
+if (2 * ((t1 - 1) % 64) + 8 >= t1)
+ S(-(2 * ((t1 - 1) % 64)) + t1 + 126);
diff --git a/polly/lib/External/isl/test_inputs/codegen/single_valued.in b/polly/lib/External/isl/test_inputs/codegen/single_valued.in
new file mode 100644
index 00000000000..d729942077e
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/single_valued.in
@@ -0,0 +1,5 @@
+# Check that isl recognizes that the inverse schedule is single-valued
+# and does not end up in an infinite recursion.
+[t1] -> {S[c2] -> [c2]: t1 <= c2 <= 134 and (c2+t1) % 128 = 0 and c2 > 0}
+[t1] -> {: t1 > 0}
+[t1] -> {}
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride.c b/polly/lib/External/isl/test_inputs/codegen/stride.c
new file mode 100644
index 00000000000..5b688292cc5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride.c
@@ -0,0 +1,6 @@
+for (int c0 = 0; c0 <= 100; c0 += 2) {
+ for (int c3 = 0; c3 <= 100; c3 += 1)
+ A(c0, c3);
+ for (int c2 = 0; c2 <= 100; c2 += 1)
+ B(c0, c2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride.in b/polly/lib/External/isl/test_inputs/codegen/stride.in
new file mode 100644
index 00000000000..b01c56617d7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride.in
@@ -0,0 +1,6 @@
+# Check that we find a common stride on the first dimension
+# even if it is imposed by different inner dimensions
+{ A[i,k] -> [i,0,j,k] : 0 <= i,k <= 100 and i = 2 j;
+ B[i,k] -> [i,1,k,j] : 0 <= i,k <= 100 and i = 2 j }
+{ : }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride5.c b/polly/lib/External/isl/test_inputs/codegen/stride5.c
new file mode 100644
index 00000000000..ee89e367598
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride5.c
@@ -0,0 +1,3 @@
+if (n % 2 == 0)
+ for (int c0 = (n / 2) + 2 * floord(-n - 1, 4) + 2; c0 <= 100; c0 += 2)
+ S(c0);
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride5.in b/polly/lib/External/isl/test_inputs/codegen/stride5.in
new file mode 100644
index 00000000000..a67a80276e4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride5.in
@@ -0,0 +1,3 @@
+[n] -> { S[t] -> [t] : exists e : 2 t - n = 4e and 0 <= t <= 100 }
+[n] -> { : }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride6.c b/polly/lib/External/isl/test_inputs/codegen/stride6.c
new file mode 100644
index 00000000000..c09e8b5441f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride6.c
@@ -0,0 +1,4 @@
+for (int c1 = -1024; c1 <= 0; c1 += 32)
+ for (int c2 = max(-((niter - 1) % 32) + niter - 1, -((niter - c1) % 32) + niter - c1 - 32); c2 <= min(niter + 1022, niter - c1 - 1); c2 += 32)
+ for (int c5 = max(max(0, -c1 - 1023), niter - c1 - c2 - 32); c5 <= min(min(31, -c1), niter - c1 - c2 - 1); c5 += 1)
+ S_4(niter - 1, -c1 - c5);
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride6.in b/polly/lib/External/isl/test_inputs/codegen/stride6.in
new file mode 100644
index 00000000000..86ca54a92c6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride6.in
@@ -0,0 +1,3 @@
+[niter] -> { S_4[-1 + niter, i] -> [o0, o1, o2, o3, o4, o5, o6, o7, 4] : exists (e0 = [(o0)/32], e1 = [(o1)/32], e2 = [(o2)/32], e3 = [(o3)/32], e4 = [(-31i + o5)/32], e5 = [(-i - o4 + o6)/32], e6 = [(-o4 + o7)/32], e7 = [(-1 + niter - o4)/32]: 32e0 = o0 and 32e1 = o1 and 32e2 = o2 and 32e3 = o3 and 32e4 = -31i + o5 and 32e5 = -i - o4 + o6 and 32e6 = -o4 + o7 and 32e7 = -1 + niter - o4 and o0 <= -1 + niter and o0 >= -32 + niter and o1 <= -i and o1 >= -31 - i and o2 <= -1 + niter + i and o2 >= -32 + niter + i and o3 <= 1023 + niter and o3 >= 992 + niter and o4 >= 0 and o4 <= 31 and o5 >= 0 and o5 <= 31 and o6 >= 0 and o6 <= 31 and o7 >= 0 and o7 <= 31 and i <= 1023 and i >= 0 and niter >= 1) }
+[niter] -> { : niter <= 8192 and niter >= 1 }
+[niter] -> { }
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride7.c b/polly/lib/External/isl/test_inputs/codegen/stride7.c
new file mode 100644
index 00000000000..b64c66d3810
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride7.c
@@ -0,0 +1,6 @@
+for (int c0 = 2; c0 <= 200; c0 += 64) {
+ for (int c2 = c0 - 1; c2 <= 120; c2 += 1)
+ s2(c0, c2);
+ for (int c2 = 122; c2 <= c0 + 62; c2 += 1)
+ s4(c0, c2);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/stride7.in b/polly/lib/External/isl/test_inputs/codegen/stride7.in
new file mode 100644
index 00000000000..cac9caca480
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/stride7.in
@@ -0,0 +1,7 @@
+# Check that no redundant guards are introduced
+{ s4[a, b] -> [a, 2, b] : exists (e0 = floor((-2 + a)/64):
+ 64e0 = -2 + a and a <= 200 and b <= 62 + a and b >= 122);
+ s2[a, b] -> [a, 2, b] : exists (e0 = floor((-2 + a)/64):
+ 64e0 = -2 + a and a >= 2 and b <= 120 and b >= -1 + a and a <= 100) }
+{ : }
+{ }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll.c b/polly/lib/External/isl/test_inputs/codegen/unroll.c
new file mode 100644
index 00000000000..63594bb6bc7
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll.c
@@ -0,0 +1,5 @@
+{
+ A(0);
+ A(100000000);
+ A(200000000);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll.in b/polly/lib/External/isl/test_inputs/codegen/unroll.in
new file mode 100644
index 00000000000..65561e2b8de
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll.in
@@ -0,0 +1,5 @@
+# Test that unrolling takes into account stride constraints.
+# If it didn't, it would run essentially forever on this example.
+[n] -> { A[i] -> [i] : exists a : i = 100000000 a and 0 <= a <= 2 }
+{:}
+{ [i] -> unroll[0] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll10.c b/polly/lib/External/isl/test_inputs/codegen/unroll10.c
new file mode 100644
index 00000000000..061954ef628
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll10.c
@@ -0,0 +1,29 @@
+if (m >= 1 && n >= 1) {
+ A(0);
+ if (m >= 2 && n >= 2) {
+ A(1);
+ if (m >= 3 && n >= 3) {
+ A(2);
+ if (m >= 4 && n >= 4) {
+ A(3);
+ if (m >= 5 && n >= 5) {
+ A(4);
+ if (m >= 6 && n >= 6) {
+ A(5);
+ if (m >= 7 && n >= 7) {
+ A(6);
+ if (m >= 8 && n >= 8) {
+ A(7);
+ if (m >= 9 && n >= 9) {
+ A(8);
+ if (m >= 10 && n >= 10)
+ A(9);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll10.in b/polly/lib/External/isl/test_inputs/codegen/unroll10.in
new file mode 100644
index 00000000000..5890c4eaaa0
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll10.in
@@ -0,0 +1,4 @@
+# Check that all information is taken into account while trying to unroll
+[m,n] -> { A[i] -> [i] : 0 <= i < n,m }
+[m,n] -> { : m <= 10 or n <= 10 }
+{ [i] -> unroll[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll2.c b/polly/lib/External/isl/test_inputs/codegen/unroll2.c
new file mode 100644
index 00000000000..7ae38be1cb1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll2.c
@@ -0,0 +1,11 @@
+{
+ A(0);
+ A(1);
+ A(2);
+ A(3);
+ for (int c0 = 4; c0 <= 99996; c0 += 1)
+ A(c0);
+ A(99997);
+ A(99998);
+ A(99999);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll2.in b/polly/lib/External/isl/test_inputs/codegen/unroll2.in
new file mode 100644
index 00000000000..0fb36ab06dc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll2.in
@@ -0,0 +1,5 @@
+# Check that the different disjuncts in the unroll option
+# are handled separately.
+{ A[i] -> [i] : 0 <= i < 100000 }
+{ : }
+{ [i] -> unroll[0] : i < 4 or i > 99996 }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll3.c b/polly/lib/External/isl/test_inputs/codegen/unroll3.c
new file mode 100644
index 00000000000..95a30ba7ccc
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll3.c
@@ -0,0 +1,2 @@
+if ((t1 + 121) % 128 <= 123)
+ write_shared_A(((t1 + 125) % 128) - 3);
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll3.in b/polly/lib/External/isl/test_inputs/codegen/unroll3.in
new file mode 100644
index 00000000000..098e5010577
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll3.in
@@ -0,0 +1,6 @@
+# Check that the entire schedule is completely unrolled and
+# in particular that no spurious loop is introduced.
+[t1] -> { write_shared_A[i2] -> [1, 3, 6 + i2, 0, t1] : (exists (e0 = [(-6 + t1 - i2)/128]: 128e0 = -6 + t1 - i2 and i2 <= 122 and i2 >= 1 and t1 >= 0 and t1 <= 127)) or (exists (e0 = [(-6 + t1 - i2)/128]: 128e0 = -6 + t1 - i2 and i2 >= 123 and i2 <= 124 and t1 <= 127 and t1 >= 0 )) }
+[t1] -> { : t1 >= 0 and t1 <= 127 }
+[t1] -> { [i0, i1, i2, i3, i4] -> unroll[o0] }
+
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll4.c b/polly/lib/External/isl/test_inputs/codegen/unroll4.c
new file mode 100644
index 00000000000..8e2ac05ca97
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll4.c
@@ -0,0 +1,22 @@
+{
+ 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 && 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 && t2 >= t1 + 1 && t2 <= 4)
+ write_shared_A(4, t1 + 4, t2 + 32);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll4.in b/polly/lib/External/isl/test_inputs/codegen/unroll4.in
new file mode 100644
index 00000000000..d8be866f948
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll4.in
@@ -0,0 +1,5 @@
+# Check that the generated code does not contain two declarations
+# of the same variable in the same scope.
+[t1, t2, g] -> { write_shared_A[a, b, c] -> [0, a, b, c] : exists (e0, e1 = [(-t1 + b)/4], e2 = [(-t2 + c)/32]: 4e1 = -t1 + b and 32e2 = -t2 + c and e0 <= 2 + 3g and e0 >= 3g and a <= 4 and a >= 3 and t2 >= 0 and t1 <= 3 and 2e0 >= 5 - c + 6g and 2e0 <= 36 - c + 6g and 2e0 >= 5 - b + 6g and 2e0 <= 8 - b + 6g and 2e0 <= 638 - c and 2e0 <= 638 - b and 2e0 >= 2 - a + 6g and 2e0 >= -8 + a + 6g and 2e0 <= 1 + a + 6g and 2e0 <= 11 - a + 6g and e0 >= 0 and e0 <= 254 and t1 >= 0 and t2 <= 31 and b >= 1 and b <= 126 and c >= 1 and c <= 126 and g <= 3 and g >= 0) }
+[t1, t2, g] -> { : g <= 3 and g >= 0 and t1 >= 0 and t1 <= 3 and t2 >= 0 and t2 <= 5 }
+[t1, t2] -> { [i0, i1, i2, i3] -> unroll[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll6.c b/polly/lib/External/isl/test_inputs/codegen/unroll6.c
new file mode 100644
index 00000000000..1d8cc5eb771
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll6.c
@@ -0,0 +1,8 @@
+{
+ if (g >= 0 && nn >= 128 * g + 6 && nn >= ((t1 + 127) % 128) + 128 * g + 3)
+ for (int c1 = 393214; c1 < nn - 1; c1 += 393216)
+ A(c1, ((t1 + 127) % 128) + 128 * g + 1, ((t1 + 127) % 128) + 1);
+ if (t1 >= 1 && t1 <= 2 && nn >= t1 + 128 * g + 130 && t1 + 128 * g >= -127)
+ for (int c1 = 393214; c1 < nn - 1; c1 += 393216)
+ A(c1, t1 + 128 * g + 128, t1 + 128);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll6.in b/polly/lib/External/isl/test_inputs/codegen/unroll6.in
new file mode 100644
index 00000000000..b4338e331f9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll6.in
@@ -0,0 +1,7 @@
+# Check that the right lower bound is chosen for unrolling.
+# Older versions of isl would pick a lower bound that resulted
+# in a number of slices that exceeds the maximal value of an integer
+# and then only generated code for a truncated number (zero) of slices.
+[nn, t1, g] -> { A[a, b, c] -> [c] : exists (e0 = [(2 + a)/393216], e1 = [(t1 - c)/128]: 128g = b - c and 393216e0 = 2 + a and 128e1 = t1 - c and c <= 130 and c >= 6 - nn + b and c <= 128 + b and nn >= 137 and t1 >= 0 and c >= 1 and a <= -2 + nn and a >= 1 and nn <= 9223372036854775807 and b >= 1 and b <= -2 + nn and t1 <= 127) }
+[nn, t1, g] -> { : nn <= 9223372036854775807 and nn >= 137 and t1 >= 0 and t1 <= 127 }
+{ [c] -> unroll[x] }
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll7.c b/polly/lib/External/isl/test_inputs/codegen/unroll7.c
new file mode 100644
index 00000000000..8392185f71c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll7.c
@@ -0,0 +1,10 @@
+{
+ S(0, 0);
+ S(0, 3);
+ S(0, 4);
+ S(1, 1);
+ S(1, 4);
+ S(2, 2);
+ S(3, 3);
+ S(4, 4);
+}
diff --git a/polly/lib/External/isl/test_inputs/codegen/unroll7.in b/polly/lib/External/isl/test_inputs/codegen/unroll7.in
new file mode 100644
index 00000000000..494e5975564
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/codegen/unroll7.in
@@ -0,0 +1,5 @@
+# Check that some code is generated.
+# Older versions of isl would abort on unknown divs.
+{ S[i,j] -> [i,j]: exists (alpha, beta: j=i+4alpha +3beta and 0 <= alpha < 24 and 0 <= beta and 0 <= i,j < 5) }
+{ : }
+{ [i,j] -> unroll[x] }
diff --git a/polly/lib/External/isl/test_inputs/convex0.polylib b/polly/lib/External/isl/test_inputs/convex0.polylib
new file mode 100644
index 00000000000..cbc4d3b6ceb
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex0.polylib
@@ -0,0 +1,11 @@
+2 3
+1 1 0
+1 -1 1
+
+2 3
+1 1 -1
+1 -1 2
+
+2 3
+1 1 0
+1 -1 2
diff --git a/polly/lib/External/isl/test_inputs/convex1.polylib b/polly/lib/External/isl/test_inputs/convex1.polylib
new file mode 100644
index 00000000000..b563d8de7ff
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex1.polylib
@@ -0,0 +1,17 @@
+# {j,N | 0<=j<=N-1; 2<=N}
+4 4
+1 1 0 0
+1 -1 1 -1
+1 0 1 -2
+1 0 0 1
+# {j, N | 1<=j<=N; 1<=N}
+4 4
+1 1 0 -1
+1 -1 1 0
+1 0 1 -1
+1 0 0 1
+# {j,N | 0<=j<=N; 2<=j+N}
+3 4
+ 1 1 1 -2
+ 1 1 0 0
+ 1 -1 1 0
diff --git a/polly/lib/External/isl/test_inputs/convex10.polylib b/polly/lib/External/isl/test_inputs/convex10.polylib
new file mode 100644
index 00000000000..3d58cbf70e1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex10.polylib
@@ -0,0 +1,17 @@
+3 4
+1 54 1 -4
+1 2 -1 58
+1 0 -1 6
+
+4 4
+1 54 1 -4
+1 2 -1 58
+1 0 1 -7
+1 -4 1 0
+
+4 4
+1 54 1 -4
+1 2 -1 58
+1 0 -1 116
+1 0 0 1
+
diff --git a/polly/lib/External/isl/test_inputs/convex11.polylib b/polly/lib/External/isl/test_inputs/convex11.polylib
new file mode 100644
index 00000000000..f664114d048
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex11.polylib
@@ -0,0 +1,14 @@
+3 4
+1 0 -1 6
+1 -1 1 1
+1 1 1 -10
+
+3 4
+1 1 0 -4
+1 -1 -1 8
+1 -1 1 1
+
+3 4
+1 0 -1 6
+1 1 0 -4
+1 -1 1 1
diff --git a/polly/lib/External/isl/test_inputs/convex12.polylib b/polly/lib/External/isl/test_inputs/convex12.polylib
new file mode 100644
index 00000000000..e4766307477
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex12.polylib
@@ -0,0 +1,12 @@
+3 5
+1 0 0 1 1
+1 0 1 0 1
+1 -1 -1 0 -2
+
+3 5
+1 0 0 1 2
+1 1 -1 0 0
+1 1 0 0 -1
+
+1 5
+1 0 0 1 2
diff --git a/polly/lib/External/isl/test_inputs/convex13.polylib b/polly/lib/External/isl/test_inputs/convex13.polylib
new file mode 100644
index 00000000000..1b3591200f8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex13.polylib
@@ -0,0 +1,17 @@
+3 5
+1 0 0 -1 3
+1 0 -1 0 2
+1 1 1 1 -4
+
+3 5
+1 0 0 1 0
+1 1 0 0 -1
+1 1 2 0 1
+
+6 5
+1 3 2 0 -1
+1 3 0 2 -3
+1 1 0 1 -1
+1 1 1 1 0
+1 1 1 0 0
+1 1 0 0 1
diff --git a/polly/lib/External/isl/test_inputs/convex14.polylib b/polly/lib/External/isl/test_inputs/convex14.polylib
new file mode 100644
index 00000000000..caaa8f5d316
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex14.polylib
@@ -0,0 +1,14 @@
+3 4
+0 1 0 2
+1 0 1 0
+1 0 -1 2
+
+3 4
+1 1 0 0
+1 0 1 0
+1 0 -1 2
+
+3 4
+1 1 0 2
+1 0 1 0
+1 0 -1 2
diff --git a/polly/lib/External/isl/test_inputs/convex15.polylib b/polly/lib/External/isl/test_inputs/convex15.polylib
new file mode 100644
index 00000000000..0118fa861db
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex15.polylib
@@ -0,0 +1,66 @@
+17 8
+1 -1 -8 0 16 0 0 37
+1 1 0 -48 0 2 0 -3
+1 0 -16 -32 16 1 0 14
+1 -1 24 0 0 1 0 18
+1 -1 8 16 0 0 1 21
+1 0 0 -16 0 1 1 -2
+1 1 32 16 -32 0 0 -1
+1 -1 16 16 0 0 0 28
+1 1 -8 -32 0 1 0 -1
+1 0 0 0 0 1 0 -1
+1 0 16 16 -16 0 1 -1
+1 1 8 0 -16 0 0 0
+1 0 3 2 -2 0 0 0
+1 0 1 2 -1 0 0 0
+1 0 -1 -1 1 0 0 0
+1 -1 8 0 0 1 2 4
+1 -1 -24 -32 32 1 0 36
+
+13 8
+1 -1 0 0 0 1 3 -4
+1 1 0 -48 0 2 0 -2
+1 0 0 0 0 1 0 -1
+1 0 -8 0 0 0 1 -1
+1 0 3 2 -2 0 0 0
+1 1 -16 -16 0 0 0 0
+1 1 -24 0 0 0 0 0
+1 0 1 0 0 0 0 0
+1 0 -3 -2 2 0 0 1
+1 -1 0 16 0 0 2 13
+1 -1 24 0 0 1 0 20
+1 -1 16 16 0 0 0 29
+1 -1 0 48 0 0 0 45
+
+31 8
+ 1 0 1 0 0 0 0 0
+ 1 0 0 -16 0 1 1 -2
+ 1 0 0 0 0 1 0 -1
+ 1 -1 8 0 0 1 2 4
+ 1 0 3 2 -2 0 0 0
+ 1 -1 24 0 0 1 0 20
+ 1 1 0 -48 0 2 0 -2
+ 1 -1 -24 -32 32 1 0 36
+ 1 0 0 0 0 0 1 -1
+ 1 -1 24 64 -16 0 0 45
+ 1 -15 120 112 0 15 38 52
+ 1 1 24 32 -32 0 0 0
+ 1 0 -2 -2 2 0 0 1
+ 1 -1 8 16 0 0 1 21
+ 1 -15 120 352 0 0 23 307
+ 1 1 -8 -32 0 1 0 -1
+ 1 1 -8 0 0 0 0 0
+ 1 1 -8 -16 0 0 0 0
+ 1 0 16 16 -16 0 1 -1
+ 1 -1 16 16 0 0 0 29
+ 1 -1 -8 0 16 0 0 37
+ 1 -1 8 32 0 0 0 37
+ 1 1 8 0 -16 0 0 0
+ 1 -15 360 592 -240 0 23 307
+ 1 -1 -6 2 14 0 2 20
+ 1 -15 360 352 -240 15 38 52
+ 1 -1 8 48 0 0 0 45
+ 1 0 -16 -32 16 1 0 14
+ 1 -1 -6 -14 14 1 3 3
+ 1 1 -38 -78 30 2 0 13
+ 1 1 -3 -50 2 2 0 -1
diff --git a/polly/lib/External/isl/test_inputs/convex2.polylib b/polly/lib/External/isl/test_inputs/convex2.polylib
new file mode 100644
index 00000000000..0bfd737291c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex2.polylib
@@ -0,0 +1,24 @@
+# {i,j,N | 1<=i<=N; 0<=j<=N-1; 2<=N}
+6 5
+1 1 0 0 -1
+1 -1 0 1 0
+1 0 1 0 0
+1 0 -1 1 -1
+1 0 0 1 -2
+1 0 0 0 1
+# {i,j,N | 1<=i<=N; 1<=j<=N; 2<=N}
+6 5
+1 1 0 0 -1
+1 -1 0 1 0
+1 0 1 0 -1
+1 0 -1 1 0
+1 0 0 1 -2
+1 0 0 0 1
+# {i,j,N | 1<=i<=N; 0<=j<=N; 2<=N}
+6 5
+ 1 0 0 1 -2
+ 1 -1 0 1 0
+ 1 0 -1 1 0
+ 1 1 0 0 -1
+ 1 0 1 0 0
+ 1 0 0 0 1
diff --git a/polly/lib/External/isl/test_inputs/convex3.polylib b/polly/lib/External/isl/test_inputs/convex3.polylib
new file mode 100644
index 00000000000..ea612c6b81f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex3.polylib
@@ -0,0 +1,10 @@
+1 4
+1 1 1 -6
+
+3 4
+1 1 1 -3
+1 1 0 -5
+1 -1 0 10
+
+1 4
+1 1 1 -3
diff --git a/polly/lib/External/isl/test_inputs/convex4.polylib b/polly/lib/External/isl/test_inputs/convex4.polylib
new file mode 100644
index 00000000000..0c086538a66
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex4.polylib
@@ -0,0 +1,9 @@
+1 4
+1 1 1 -6
+
+2 4
+0 1 0 -1
+0 0 1 -4
+
+1 4
+1 1 1 -5
diff --git a/polly/lib/External/isl/test_inputs/convex5.polylib b/polly/lib/External/isl/test_inputs/convex5.polylib
new file mode 100644
index 00000000000..3aae7c26bcf
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex5.polylib
@@ -0,0 +1,12 @@
+2 4
+0 1 0 -2
+0 0 1 -6
+
+2 4
+0 1 0 -1
+0 0 1 -4
+
+3 4
+0 -2 1 -2
+1 1 0 -1
+1 -1 0 2
diff --git a/polly/lib/External/isl/test_inputs/convex6.polylib b/polly/lib/External/isl/test_inputs/convex6.polylib
new file mode 100644
index 00000000000..1bdb4e1c9dd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex6.polylib
@@ -0,0 +1,17 @@
+3 4
+1 1 1 -2
+1 -1 1 2
+1 0 -1 2
+
+3 4
+1 0 1 -1
+1 1 -1 1
+1 -1 -1 5
+
+6 4
+1 -1 0 4
+1 1 0 0
+1 1 2 -2
+1 -1 2 2
+1 1 -2 4
+1 -1 -2 8
diff --git a/polly/lib/External/isl/test_inputs/convex7.polylib b/polly/lib/External/isl/test_inputs/convex7.polylib
new file mode 100644
index 00000000000..70eb483175b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex7.polylib
@@ -0,0 +1,9 @@
+1 4
+0 0 1 0
+
+2 4
+1 1 -1 1
+1 -1 -1 1
+
+1 4
+1 0 -1 1
diff --git a/polly/lib/External/isl/test_inputs/convex8.polylib b/polly/lib/External/isl/test_inputs/convex8.polylib
new file mode 100644
index 00000000000..ea1b757108c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex8.polylib
@@ -0,0 +1,24 @@
+4 5
+1 1 1 1 0
+1 0 -1 0 0
+1 -1 0 0 2
+1 1 1 -1 0
+
+4 5
+1 -1 1 0 2
+1 1 -2 -2 -1
+1 -1 0 2 3
+1 1 0 0 -1
+
+10 5
+1 1 0 1 0
+1 1 1 0 0
+1 0 1 1 2
+1 -3 1 -1 8
+1 -3 1 1 8
+1 0 1 -1 2
+1 1 0 -1 0
+1 1 -2 -1 0
+1 -1 -3 2 6
+1 1 -5 -2 2
+
diff --git a/polly/lib/External/isl/test_inputs/convex9.polylib b/polly/lib/External/isl/test_inputs/convex9.polylib
new file mode 100644
index 00000000000..f68fca097a9
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/convex9.polylib
@@ -0,0 +1,14 @@
+4 4
+1 1 0 0
+1 -1 0 1
+1 0 1 0
+1 0 -1 10
+
+2 4
+1 1 0 -10
+0 0 -1 5
+
+3 4
+1 1 0 0
+1 0 1 0
+1 0 -1 10
diff --git a/polly/lib/External/isl/test_inputs/devos.pwqp b/polly/lib/External/isl/test_inputs/devos.pwqp
new file mode 100644
index 00000000000..b4525446904
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/devos.pwqp
@@ -0,0 +1 @@
+[U] -> { [i0] -> ((1/3 * U + 2/3 * i0) - [(U + 2i0)/3]) : 2i0 >= -3 - U and 2i0 <= -U and U >= 0 and U <= 10 }
diff --git a/polly/lib/External/isl/test_inputs/equality1.pwqp b/polly/lib/External/isl/test_inputs/equality1.pwqp
new file mode 100644
index 00000000000..eb16a4ba7b8
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/equality1.pwqp
@@ -0,0 +1 @@
+[n] -> { [x] -> 1 + [(x+1)/3] : exists a : x = 3a +1 && 0 <= x <= n }
diff --git a/polly/lib/External/isl/test_inputs/equality2.pwqp b/polly/lib/External/isl/test_inputs/equality2.pwqp
new file mode 100644
index 00000000000..1629a6549ea
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/equality2.pwqp
@@ -0,0 +1 @@
+[n] -> { [x,y] -> x^2 * y : n = 2x + 4y and 0 <= x,y <= 10 }
diff --git a/polly/lib/External/isl/test_inputs/equality3.pwqp b/polly/lib/External/isl/test_inputs/equality3.pwqp
new file mode 100644
index 00000000000..c6f8c3acf19
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/equality3.pwqp
@@ -0,0 +1 @@
+[m,n] -> { [x,y] -> x^2 * y : n = 2x + 4y and 0 <= x,y <= 10 and 3 n = 5 m }
diff --git a/polly/lib/External/isl/test_inputs/equality4.pwqp b/polly/lib/External/isl/test_inputs/equality4.pwqp
new file mode 100644
index 00000000000..49da2e7eff6
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/equality4.pwqp
@@ -0,0 +1 @@
+[m,n] -> { [x,y] -> x^2 * y + m + 13 * n: n = 2x + 4y and 0 <= x,y <= 10 and 3 n = 5 m }
diff --git a/polly/lib/External/isl/test_inputs/equality5.pwqp b/polly/lib/External/isl/test_inputs/equality5.pwqp
new file mode 100644
index 00000000000..09cb7520113
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/equality5.pwqp
@@ -0,0 +1 @@
+[m,n] -> { [x,y,z] -> x^2 * y + z + m + 13 * n: n = 2x + 4y and 0 <= x,y <= 10 and 3 n = 5 m and z = x + y }
diff --git a/polly/lib/External/isl/test_inputs/esced.pip b/polly/lib/External/isl/test_inputs/esced.pip
new file mode 100644
index 00000000000..dbf56ffa0fd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/esced.pip
@@ -0,0 +1,27 @@
+0 2
+
+-1
+
+16 18
+1 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0 0 0
+1 0 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0 0
+1 0 0 0 0 0 0 0 0 0 0 -1 0 0 1 0 0 0
+1 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
+
+
+0 0 0 0 -1 0 0 0 0 1 -1 0 0 0 0 0 0 0
+0 0 0 0 0 -1 0 0 0 0 0 1 0 0 0 0 0 0
+
+0 -1 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0
+
+0 0 0 0 0 0 -1 0 0 0 0 0 1 -1 0 -1 0 0
+0 0 0 0 0 0 0 -1 0 0 0 0 0 0 1 0 0 0
+0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 1 0
+
+0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0
+0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0
+
+1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1
+1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 -1
diff --git a/polly/lib/External/isl/test_inputs/ex.pip b/polly/lib/External/isl/test_inputs/ex.pip
new file mode 100644
index 00000000000..a405450b2ad
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/ex.pip
@@ -0,0 +1,9 @@
+1 5
+1 -1 1 1 0
+
+-1
+
+3 7
+1 0 -1 0 1 0 0
+1 -1 0 0 0 1 0
+1 1 1 -1 0 0 0
diff --git a/polly/lib/External/isl/test_inputs/ex2.pip b/polly/lib/External/isl/test_inputs/ex2.pip
new file mode 100644
index 00000000000..bb59848c8f2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/ex2.pip
@@ -0,0 +1,9 @@
+1 5
+1 -1 1 1 0
+
+-1
+
+3 7
+1 0 -1 0 1 0 0
+1 -1 0 0 0 1 0
+1 1 1 -1 0 0 0
diff --git a/polly/lib/External/isl/test_inputs/faddeev.pwqp b/polly/lib/External/isl/test_inputs/faddeev.pwqp
new file mode 100644
index 00000000000..e7db61d1bc5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/faddeev.pwqp
@@ -0,0 +1 @@
+[N] -> { [i, j, k] -> (((4 + 6 * N + 2 * N^2) + (-2 - 2 * N) * j) + ((-2 - N) + j) * k) : j = 1 + i and k = 1 + i and i >= 3 and N <= 100 and i <= N and N >= 10 }
diff --git a/polly/lib/External/isl/test_inputs/fimmel.pip b/polly/lib/External/isl/test_inputs/fimmel.pip
new file mode 100644
index 00000000000..a6dee417c02
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/fimmel.pip
@@ -0,0 +1,12 @@
+0 4
+
+-1
+
+7 6
+1 2 6 0 0 -9
+1 5 -3 0 0 0
+1 2 -10 0 0 15
+1 -2 6 0 0 -3
+1 -2 -6 0 0 17
+1 0 1 -1 0 0
+1 1 0 0 -1 0
diff --git a/polly/lib/External/isl/test_inputs/gist1.polylib b/polly/lib/External/isl/test_inputs/gist1.polylib
new file mode 100644
index 00000000000..802a4eb6ff2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/gist1.polylib
@@ -0,0 +1,14 @@
+4 5
+0 1 0 0 -1
+0 0 1 0 1
+0 0 0 1 -3
+1 0 0 0 1
+
+4 5
+0 1 0 0 -1
+0 0 1 1 -2
+1 0 0 1 0
+1 0 0 -1 3
+
+1 5
+0 0 1 0 1
diff --git a/polly/lib/External/isl/test_inputs/linearExample.pwqp b/polly/lib/External/isl/test_inputs/linearExample.pwqp
new file mode 100644
index 00000000000..24c53946a0b
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/linearExample.pwqp
@@ -0,0 +1 @@
+[N, M, L] -> { [i, j, k] -> ((1/2 * i + 5 * j) + 1/7 * k) : i >= 0 and k >= -N + i and k >= -M - j and j <= L + i and L >= 0 and L >= -M }
diff --git a/polly/lib/External/isl/test_inputs/max.pip b/polly/lib/External/isl/test_inputs/max.pip
new file mode 100644
index 00000000000..e8af57b9f51
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/max.pip
@@ -0,0 +1,9 @@
+0 3
+
+-1
+
+4 5
+1 -1 0 1 0
+1 0 -1 1 0
+1 -1 3 -2 12
+1 2 -1 -1 3
diff --git a/polly/lib/External/isl/test_inputs/neg.pwqp b/polly/lib/External/isl/test_inputs/neg.pwqp
new file mode 100644
index 00000000000..596a7d77d09
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/neg.pwqp
@@ -0,0 +1 @@
+[n] -> { [i0] -> i0^2 : i0 >= -20 - n and i0 <= n and i0 <= -1 and n >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/negative.pip b/polly/lib/External/isl/test_inputs/negative.pip
new file mode 100644
index 00000000000..45090a59230
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/negative.pip
@@ -0,0 +1,9 @@
+1 3
+# n 1
+1 1 -1 # n >= 1
+-1
+
+2 4
+# i n 1
+1 1 0 1 # i >= -1
+1 -1 1 0 # i <= n
diff --git a/polly/lib/External/isl/test_inputs/philippe.pwqp b/polly/lib/External/isl/test_inputs/philippe.pwqp
new file mode 100644
index 00000000000..1c56e7af707
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippe.pwqp
@@ -0,0 +1 @@
+[N] -> { [i, j] -> ((1/2 * i + 1/2 * i^2) + j) : i <= N and j >= 0 and j <= i }
diff --git a/polly/lib/External/isl/test_inputs/philippe3vars.pwqp b/polly/lib/External/isl/test_inputs/philippe3vars.pwqp
new file mode 100644
index 00000000000..8d074962578
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippe3vars.pwqp
@@ -0,0 +1 @@
+[N] -> { [i, j, k] -> (((1/2 * i + 1/2 * i^2) + j) + k^3) : i >= 0 and k >= -N + i and k >= -j and j <= i }
diff --git a/polly/lib/External/isl/test_inputs/philippe3vars3pars.pwqp b/polly/lib/External/isl/test_inputs/philippe3vars3pars.pwqp
new file mode 100644
index 00000000000..f81b8cc5a68
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippe3vars3pars.pwqp
@@ -0,0 +1 @@
+[N, M, L] -> { [i, j, k] -> (((1/2 * i + 1/2 * i^2) + j) + k^3) : i >= 0 and k >= -N + i and k >= -M - j and j <= L + i and L >= 0 and L >= -M }
diff --git a/polly/lib/External/isl/test_inputs/philippeNeg.pwqp b/polly/lib/External/isl/test_inputs/philippeNeg.pwqp
new file mode 100644
index 00000000000..24dc805ed18
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippeNeg.pwqp
@@ -0,0 +1 @@
+[N] -> { [i, j] -> ((1/2 * i + 1/2 * i^2) + j) : i <= N and j >= -1 and j <= i }
diff --git a/polly/lib/External/isl/test_inputs/philippePolynomialCoeff.pwqp b/polly/lib/External/isl/test_inputs/philippePolynomialCoeff.pwqp
new file mode 100644
index 00000000000..e6327c78f35
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippePolynomialCoeff.pwqp
@@ -0,0 +1 @@
+[N, M] -> { [i, j] -> ((N * i + (1/5 * N + N^2) * i^2) + 5 * j) : i <= N and j >= 0 and j <= i and M >= 0 }
diff --git a/polly/lib/External/isl/test_inputs/philippePolynomialCoeff1P.pwqp b/polly/lib/External/isl/test_inputs/philippePolynomialCoeff1P.pwqp
new file mode 100644
index 00000000000..ae01d2fcb87
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/philippePolynomialCoeff1P.pwqp
@@ -0,0 +1 @@
+[N] -> { [i, j] -> ((N * i + (1/5 * N + N^2) * i^2) + 5 * j) : i <= N and j >= 0 and j <= i }
diff --git a/polly/lib/External/isl/test_inputs/product.pwqp b/polly/lib/External/isl/test_inputs/product.pwqp
new file mode 100644
index 00000000000..ee48b859ee3
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/product.pwqp
@@ -0,0 +1 @@
+[N] -> { [i0, i1, i2] -> (i0^3 * i1^2 + N * i1 * i2) : i0 >= 0 and i0 <= N and i1 >= 0 and i1 <= N and i2 >= 0 and i2 <= N }
diff --git a/polly/lib/External/isl/test_inputs/seghir-vd.pip b/polly/lib/External/isl/test_inputs/seghir-vd.pip
new file mode 100644
index 00000000000..b5395fbdb38
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/seghir-vd.pip
@@ -0,0 +1,17 @@
+0 6
+
+-1
+
+9 8
+ 0 0 0 1 1 0 0 2
+ 1 2 1 0 0 1 0 0
+ 1 0 1 0 -1 0 0 -1
+ 1 -2 -1 0 0 0 0 -1
+ 1 7 3 0 0 0 0 -1
+ 1 -6 -4 0 1 0 3 1
+ 1 -7 -3 0 0 1 6 4
+ 1 0 0 0 0 0 1 0
+ 1 0 0 0 0 0 0 1
+
+Urs_parms
+Urs_unknowns
diff --git a/polly/lib/External/isl/test_inputs/set.omega b/polly/lib/External/isl/test_inputs/set.omega
new file mode 100644
index 00000000000..ac8485fb9a4
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/set.omega
@@ -0,0 +1 @@
+{[y]: Exists ( alpha : 2alpha = y)}
diff --git a/polly/lib/External/isl/test_inputs/small.pip b/polly/lib/External/isl/test_inputs/small.pip
new file mode 100644
index 00000000000..59557d262bd
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/small.pip
@@ -0,0 +1,9 @@
+0 2
+
+-1
+
+4 4
+1 1 0 0
+1 0 1 0
+1 1 -3 12
+1 -2 1 3
diff --git a/polly/lib/External/isl/test_inputs/sor1d.pip b/polly/lib/External/isl/test_inputs/sor1d.pip
new file mode 100644
index 00000000000..1bef89e5bf1
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/sor1d.pip
@@ -0,0 +1,28 @@
+2 4
+ 1 1 0 0
+ 1 0 1 0
+
+-1
+
+20 8
+
+ 0 -1 0 0 0 0 0 2
+ 0 0 -1 0 0 0 0 1
+ 0 0 0 -1 0 0 0 2
+ 0 0 0 0 -1 0 0 4
+ 1 0 0 0 1 0 0 -2
+ 1 -2 0 2 1 0 0 -4
+ 1 0 0 0 -1 0 1 -1
+ 1 2 0 -2 -1 0 0 5
+ 1 0 0 1 0 0 0 -1
+ 1 0 -2 1 0 0 0 0
+ 1 -2 0 2 0 0 1 -5
+ 1 0 0 -1 0 1 0 0
+ 1 0 2 -1 0 0 0 1
+ 1 2 0 -2 0 0 0 3
+ 1 0 1 0 0 0 0 0
+ 1 -2 4 0 0 0 1 -3
+ 1 0 -2 0 0 1 0 0
+ 1 2 -4 0 0 0 0 3
+ 1 2 0 0 0 0 0 1
+ 1 -2 0 0 0 2 1 -5
diff --git a/polly/lib/External/isl/test_inputs/split.pwqp b/polly/lib/External/isl/test_inputs/split.pwqp
new file mode 100644
index 00000000000..1804563600c
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/split.pwqp
@@ -0,0 +1 @@
+[n] -> { [x] -> -1 + [(x+5)/7] : -n - 20 <= x <= n }
diff --git a/polly/lib/External/isl/test_inputs/square.pip b/polly/lib/External/isl/test_inputs/square.pip
new file mode 100644
index 00000000000..7bb3f0c90b5
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/square.pip
@@ -0,0 +1,9 @@
+0 3
+
+-1
+
+4 5
+1 1 0 0 0
+1 -1 0 1 0
+1 0 1 0 0
+1 0 -1 1 0
diff --git a/polly/lib/External/isl/test_inputs/sven.pip b/polly/lib/External/isl/test_inputs/sven.pip
new file mode 100644
index 00000000000..86027691036
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/sven.pip
@@ -0,0 +1,7 @@
+0 3
+
+-1
+
+2 3
+1 1 -4
+1 -1 10
diff --git a/polly/lib/External/isl/test_inputs/test3Deg3Var.pwqp b/polly/lib/External/isl/test_inputs/test3Deg3Var.pwqp
new file mode 100644
index 00000000000..d9a9ea9da01
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/test3Deg3Var.pwqp
@@ -0,0 +1 @@
+[p] -> { [n, m] -> (n + n^3) : n >= 1 and m >= n and m <= p }
diff --git a/polly/lib/External/isl/test_inputs/tobi.pip b/polly/lib/External/isl/test_inputs/tobi.pip
new file mode 100644
index 00000000000..c31beae1b0f
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/tobi.pip
@@ -0,0 +1,15 @@
+2 3
+1 1 -281
+1 -1 14000
+
+-1
+
+6 6
+0 -392 0 8 -1 0
+0 392 8 0 1 0
+1 -1 0 0 0 0
+1 1 0 0 0 35
+1 392 0 0 1 0
+1 -392 0 0 -1 280
+
+Urs_unknowns
diff --git a/polly/lib/External/isl/test_inputs/toplas.pwqp b/polly/lib/External/isl/test_inputs/toplas.pwqp
new file mode 100644
index 00000000000..9c0999540b2
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/toplas.pwqp
@@ -0,0 +1 @@
+[n] -> { [i0, i1] -> (((4 * n - n^2) + (-3/2 + 2 * n) * i0 - 1/2 * i0^2) - i1) : i1 >= -1 + 3n - i0 and i1 >= -1 + 2n - i0 and i0 >= 0 and i1 <= -2 + 4n - i0 and i0 <= -2 + 4n and i0 <= -1 + 3n and i1 >= 0 and i1 <= -1 + n }
diff --git a/polly/lib/External/isl/test_inputs/unexpanded.pwqp b/polly/lib/External/isl/test_inputs/unexpanded.pwqp
new file mode 100644
index 00000000000..5626d3baa41
--- /dev/null
+++ b/polly/lib/External/isl/test_inputs/unexpanded.pwqp
@@ -0,0 +1 @@
+{ [x, y] -> ((x - x^2) * y + (-x + x^2) * y^2) : x >= 0 and x <= 2 and y >= 0 and y <= 2 }
diff --git a/polly/lib/Makefile b/polly/lib/Makefile
index eb9ed8557ec..49e9333d9f0 100644
--- a/polly/lib/Makefile
+++ b/polly/lib/Makefile
@@ -11,6 +11,7 @@ LOADABLE_MODULE = 1
# TODO: Export symbols for RTTI or EH?
CPP.Flags += $(POLLY_INC)
+C.Flags += $(POLLY_CFLAGS)
LD.Flags += $(POLLY_LD) $(POLLY_LIB)
include $(LEVEL)/Makefile.config
@@ -32,6 +33,82 @@ POLLY_JSON_FILES= JSON/json_reader.cpp \
JSON/json_value.cpp \
JSON/json_writer.cpp
+ISL_FILES= External/isl/basis_reduction_tab.c \
+ External/isl/isl_aff.c \
+ External/isl/isl_affine_hull.c \
+ External/isl/isl_arg.c \
+ External/isl/isl_ast_build.c \
+ External/isl/isl_ast_build_expr.c \
+ External/isl/isl_ast.c \
+ External/isl/isl_ast_codegen.c \
+ External/isl/isl_ast_graft.c \
+ External/isl/isl_band.c \
+ External/isl/isl_bernstein.c \
+ External/isl/isl_blk.c \
+ External/isl/isl_bound.c \
+ External/isl/isl_coalesce.c \
+ External/isl/isl_constraint.c \
+ External/isl/isl_convex_hull.c \
+ External/isl/isl_ctx.c \
+ External/isl/isl_deprecated.c \
+ External/isl/isl_dim.c \
+ External/isl/isl_dim_map.c \
+ External/isl/isl_equalities.c \
+ External/isl/isl_factorization.c \
+ External/isl/isl_farkas.c \
+ External/isl/isl_flow.c \
+ External/isl/isl_fold.c \
+ External/isl/isl_hash.c \
+ External/isl/isl_id.c \
+ External/isl/isl_id_to_ast_expr.c \
+ External/isl/isl_id_to_pw_aff.c \
+ External/isl/isl_ilp.c \
+ External/isl/isl_imath.c \
+ External/isl/isl_input.c \
+ External/isl/isl_local_space.c \
+ External/isl/isl_lp.c \
+ External/isl/isl_map.c \
+ External/isl/isl_map_simplify.c \
+ External/isl/isl_map_subtract.c \
+ External/isl/isl_map_to_basic_set.c \
+ External/isl/isl_mat.c \
+ External/isl/isl_morph.c \
+ External/isl/isl_obj.c \
+ External/isl/isl_options.c \
+ External/isl/isl_output.c \
+ External/isl/isl_point.c \
+ External/isl/isl_polynomial.c \
+ External/isl/isl_printer.c \
+ External/isl/isl_range.c \
+ External/isl/isl_reordering.c \
+ External/isl/isl_sample.c \
+ External/isl/isl_scan.c \
+ External/isl/isl_schedule.c \
+ External/isl/isl_scheduler.c \
+ External/isl/isl_seq.c \
+ External/isl/isl_set_list.c \
+ External/isl/isl_sort.c \
+ External/isl/isl_space.c \
+ External/isl/isl_stream.c \
+ External/isl/isl_tab.c \
+ External/isl/isl_tab_pip.c \
+ External/isl/isl_tarjan.c \
+ External/isl/isl_transitive_closure.c \
+ External/isl/isl_union_map.c \
+ External/isl/isl_val.c \
+ External/isl/isl_val_imath.c \
+ External/isl/isl_vec.c \
+ External/isl/isl_version.c \
+ External/isl/isl_vertices.c \
+ External/isl/print.c \
+ External/isl/imath/gmp_compat.c \
+ External/isl/imath/imath.c \
+ External/isl/imath/imdrover.c \
+ External/isl/imath/imrat.c \
+ External/isl/imath/iprime.c \
+ External/isl/imath/pi.c \
+ External/isl/imath/rsamath.c
+
SOURCES= Polly.cpp \
Support/GICHelper.cpp \
Support/SCEVValidator.cpp \
@@ -58,7 +135,8 @@ SOURCES= Polly.cpp \
${GPGPU_FILES} \
${ISL_CODEGEN_FILES} \
${POLLY_JSON_FILES} \
- ${POLLY_PLUTO_FILES}
+ ${POLLY_PLUTO_FILES} \
+ ${ISL_FILES}
#
# Include Makefile.common so we know what to do.
OpenPOWER on IntegriCloud