summaryrefslogtreecommitdiffstats
path: root/polly/lib
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib')
-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
1018 files changed, 177237 insertions, 1 deletions
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