24 #include "ppl-config.h"
30 #include "assertions.hh"
42 space_dim(y.space_dim),
43 dim_kinds(y.dim_kinds) {
69 "the space dimension of cs "
70 "exceeds the maximum allowed "
72 gen_sys(cs.space_dimension()) {
78 cs_end = cs.
end(); i != cs_end; ++i) {
79 if (i->is_inconsistent()) {
96 cs_end = cs.
end(); i != cs_end; ++i) {
97 if (i->is_equality()) {
112 "the space dimension of cs "
113 "exceeds the maximum allowed "
115 gen_sys(cs.space_dimension()) {
121 cs_end = cs.
end(); i != cs_end; ++i) {
122 if (i->is_inconsistent()) {
139 cs_end = cs.
end(); i != cs_end; ++i) {
140 if (i->is_equality()) {
156 "the space dimension of ph "
157 "exceeds the maximum allowed "
159 gen_sys(ph.space_dimension()) {
190 if (use_constraints) {
196 cs_end = cs.end(); i != cs_end; ++i) {
197 if (i->is_equality()) {
213 gs_end = gs.end(); g != gs_end; ++g) {
214 if (g->is_point() || g->is_closure_point()) {
217 point_divisor = g->divisor();
218 ggs.
insert(grid_point(point_expr, point_divisor));
227 gs_end = gs.end(); g != gs_end; ++g) {
230 if (g->is_point() || g->is_closure_point()) {
257 else if (space_dim == 0) {
274 if (space_dim == 0 || is_empty()) {
278 if (generators_are_up_to_date()) {
279 if (generators_are_minimized()) {
280 return gen_sys.num_rows() - 1;
282 if (!(congruences_are_up_to_date() && congruences_are_minimized())) {
283 return minimized_grid_generators().num_rows() - 1;
287 minimized_congruences();
289 PPL_ASSERT(congruences_are_minimized());
292 if (con_sys[i].is_equality()) {
301 if (marked_empty()) {
305 if (space_dim == 0) {
307 PPL_ASSERT(con_sys.num_rows() == 0 && con_sys.space_dimension() == 0);
311 if (!congruences_are_up_to_date()) {
312 update_congruences();
320 if (congruences_are_up_to_date() && !congruences_are_minimized()) {
322 Grid& gr =
const_cast<Grid&
>(*this);
330 return congruences();
335 if (space_dim == 0) {
336 PPL_ASSERT(gen_sys.space_dimension() == 0
337 && gen_sys.num_rows() == (marked_empty() ? 0U : 1U));
341 if (marked_empty()) {
342 PPL_ASSERT(gen_sys.has_no_rows());
346 if (!generators_are_up_to_date() && !update_generators()) {
357 if (space_dim == 0) {
358 PPL_ASSERT(gen_sys.space_dimension() == 0
359 && gen_sys.num_rows() == (marked_empty() ? 0U : 1U));
363 if (marked_empty()) {
364 PPL_ASSERT(gen_sys.has_no_rows());
368 if (generators_are_up_to_date()) {
369 if (!generators_are_minimized()) {
371 Grid& gr =
const_cast<Grid&
>(*this);
376 else if (!update_generators()) {
389 throw_dimension_incompatible(
"relation_with(cg)",
"cg", cg);
392 if (marked_empty()) {
398 if (space_dim == 0) {
412 if (!generators_are_up_to_date() && !update_generators()) {
434 bool known_to_intersect =
false;
437 i_end = gen_sys.end(); i != i_end; ++i) {
451 known_to_intersect =
true;
459 if (known_to_intersect) {
477 if (point_sp % div == 0) {
495 if (known_to_intersect) {
505 if (point_sp % div == 0) {
547 PPL_ASSERT(!known_to_intersect);
555 throw_dimension_incompatible(
"relation_with(g)",
"g", g);
559 if (marked_empty()) {
565 if (space_dim == 0) {
569 if (!congruences_are_up_to_date()) {
570 update_congruences();
574 con_sys.satisfies_all_congruences(g)
584 if (space_dim < g_space_dim) {
585 throw_dimension_incompatible(
"relation_with(g)",
"g", g);
589 if (marked_empty()) {
595 if (space_dim == 0) {
599 if (!congruences_are_up_to_date()) {
600 update_congruences();
607 gg = grid_point(expr, g.
divisor());
612 gg = grid_line(expr);
616 con_sys.satisfies_all_congruences(gg)
625 throw_dimension_incompatible(
"relation_with(c)",
"c", c);
630 return relation_with(cg);
633 if (marked_empty()) {
639 if (space_dim == 0) {
663 if (!generators_are_up_to_date() && !update_generators()) {
676 bool point_is_included =
false;
677 bool point_saturates =
false;
681 i_end = gen_sys.end(); i != i_end; ++i) {
686 if (first_point == 0) {
708 PPL_ASSERT(gen.
OK());
729 if (point_saturates) {
734 if (point_is_included) {
743 if (marked_empty()) {
748 if (generators_are_up_to_date()) {
751 if (space_dim == 0) {
754 if (congruences_are_minimized()) {
759 Grid& gr =
const_cast<Grid&
>(*this);
770 if (marked_empty()) {
774 if (space_dim == 0) {
778 if (congruences_are_up_to_date()) {
779 if (congruences_are_minimized()) {
782 return con_sys.num_rows() == 1 && con_sys[0].is_tautological();
786 update_congruences();
787 return con_sys.num_rows() == 1 && con_sys[0].is_tautological();
797 if (!con_sys.satisfies_all_congruences(grid_line(expr))) {
804 PPL_ASSERT(con_sys.satisfies_all_congruences(grid_point(expr)));
814 || (!generators_are_up_to_date() && !update_generators())) {
819 if (gen_sys.num_rows() > 1) {
840 || (!generators_are_up_to_date() && !update_generators())) {
845 if (gen_sys[row].is_line()) {
863 if (marked_empty()) {
869 if (space_dim == 0) {
889 if (space_dim < var_space_dim) {
890 throw_dimension_incompatible(
"constrains(v)",
"v", var);
894 if (marked_empty()) {
898 if (generators_are_up_to_date()) {
901 if (congruences_are_up_to_date()) {
904 goto syntactic_check;
907 if (generators_are_minimized()) {
913 if (gen_sys[i].is_line()) {
918 if (num_lines == space_dim) {
939 update_congruences();
940 goto syntactic_check;
950 if (con_sys[i].coefficient(var) != 0) {
969 if (marked_empty()) {
970 if (check_not_empty) {
973 cerr <<
"Empty grid!" << endl;
978 if (con_sys.space_dimension() != space_dim) {
980 cerr <<
"The grid is in a space of dimension " << space_dim
981 <<
" while the system of congruences is in a space of dimension "
982 << con_sys.space_dimension()
993 if (space_dim == 0) {
994 if (con_sys.has_no_rows()) {
995 if (gen_sys.num_rows() == 1 && gen_sys[0].is_point()) {
1000 cerr <<
"Zero-dimensional grid should have an empty congruence" << endl
1001 <<
"system and a generator system of a single point." << endl;
1008 if (!congruences_are_up_to_date() && !generators_are_up_to_date()) {
1010 cerr <<
"Grid not empty, not zero-dimensional" << endl
1011 <<
"and with neither congruences nor generators up-to-date!"
1026 if (congruences_are_up_to_date()) {
1027 if (con_sys.space_dimension() != space_dim) {
1029 cerr <<
"Incompatible size! (con_sys and space_dim)"
1035 if (generators_are_up_to_date()) {
1036 if (gen_sys.space_dimension() != space_dim) {
1038 cerr <<
"Incompatible size! (gen_sys and space_dim)"
1046 if (!gen_sys.has_no_rows() && !gen_sys.has_points()) {
1048 cerr <<
"Non-empty generator system declared up-to-date "
1055 if (generators_are_minimized()) {
1058 if (dim_kinds.size() != num_columns) {
1060 cerr <<
"Size of dim_kinds should equal the number of columns."
1066 if (!upper_triangular(gs, dim_kinds)) {
1068 cerr <<
"Reduced generators should be upper triangular."
1076 row = gen_sys.num_rows(); dim > 0; --dim) {
1077 if (dim_kinds[dim] == GEN_VIRTUAL) {
1080 if (gen_sys[--row].is_parameter_or_point()
1081 && dim_kinds[dim] == PARAMETER) {
1084 PPL_ASSERT(gen_sys[row].is_line());
1085 if (dim_kinds[dim] == LINE) {
1089 cerr <<
"Kinds in dim_kinds should match those in gen_sys."
1094 PPL_ASSERT(row <= dim);
1103 simplify(gs, dim_kinds_copy);
1114 cerr <<
"Generators are declared minimized,"
1115 " but they change under reduction.\n"
1116 <<
"Here is the generator system:\n";
1118 cerr <<
"and here is the minimized form of the temporary copy:\n";
1128 if (congruences_are_up_to_date()) {
1130 if (!con_sys.OK()) {
1134 Grid tmp_gr = *
this;
1144 if (check_not_empty) {
1147 cerr <<
"Unsatisfiable system of congruences!"
1156 if (congruences_are_minimized()) {
1158 if (!lower_triangular(con_sys, dim_kinds)) {
1160 cerr <<
"Reduced congruences should be lower triangular." << endl;
1168 if (!con_sys.is_equal_to(cs_copy)) {
1170 cerr <<
"Congruences are declared minimized, but they change under reduction!"
1172 <<
"Here is the minimized form of the congruence system:"
1180 if (dim_kinds.size() != con_sys.space_dimension() + 1 ) {
1182 cerr <<
"Size of dim_kinds should equal the number of columns."
1190 if (dim_kinds[dim] == CON_VIRTUAL) {
1193 if (con_sys[row++].is_proper_congruence()
1194 && dim_kinds[dim] == PROPER_CONGRUENCE) {
1197 PPL_ASSERT(con_sys[row-1].is_equality());
1198 if (dim_kinds[dim] == EQUALITY) {
1202 cerr <<
"Kinds in dim_kinds should match those in con_sys." << endl;
1213 cerr <<
"Here is the grid under check:" << endl;
1223 throw_dimension_incompatible(
"add_constraints(cs)",
"cs", cs);
1225 if (marked_empty()) {
1230 cs_end = cs.
end(); i != cs_end; ++i) {
1231 add_constraint_no_check(*i);
1232 if (marked_empty()) {
1242 if (space_dim < g_space_dim) {
1243 throw_dimension_incompatible(
"add_grid_generator(g)",
"g", g);
1247 if (space_dim == 0) {
1250 if (marked_empty()) {
1252 throw_invalid_generator(
"add_grid_generator(g)",
"g");
1254 set_zero_dim_univ();
1261 || (!generators_are_up_to_date() && !update_generators())) {
1265 throw_invalid_generator(
"add_grid_generator(g)",
"g");
1271 PPL_ASSERT(generators_are_up_to_date());
1274 normalize_divisors(gen_sys);
1279 clear_congruences_up_to_date();
1281 clear_generators_minimized();
1282 set_generators_up_to_date();
1290 if (space_dim < cgs_space_dim) {
1291 throw_dimension_incompatible(
"add_recycled_congruences(cgs)",
"cgs", cgs);
1298 if (marked_empty()) {
1302 if (space_dim == 0) {
1315 if (!congruences_are_up_to_date()) {
1316 update_congruences();
1324 clear_congruences_minimized();
1325 clear_generators_up_to_date();
1335 if (space_dim < gs_space_dim) {
1336 throw_dimension_incompatible(
"add_recycled_grid_generators(gs)",
"gs", gs);
1346 if (space_dim == 0) {
1347 if (marked_empty()) {
1348 set_zero_dim_univ();
1353 PPL_ASSERT(OK(
true));
1357 if (!marked_empty()) {
1360 if (!generators_are_up_to_date()) {
1361 update_generators();
1363 normalize_divisors(gs, gen_sys);
1368 clear_congruences_up_to_date();
1369 clear_generators_minimized();
1371 PPL_ASSERT(OK(
true));
1379 throw_invalid_generators(
"add_recycled_grid_generators(gs)",
"gs");
1386 normalize_divisors(gen_sys);
1389 set_generators_up_to_date();
1399 add_recycled_grid_generators(gs_copy);
1406 throw_dimension_incompatible(
"refine_with_constraint(c)",
"c", c);
1408 if (marked_empty()) {
1418 throw_dimension_incompatible(
"refine_with_constraints(cs)",
"cs", cs);
1422 cs_end = cs.
end(); !marked_empty() && i != cs_end; ++i) {
1423 refine_no_check(*i);
1431 throw_dimension_incompatible(
"unconstrain(var)", var.
space_dimension());
1436 || (!generators_are_up_to_date() && !update_generators())) {
1440 PPL_ASSERT(generators_are_up_to_date());
1444 clear_congruences_up_to_date();
1445 clear_generators_minimized();
1459 if (space_dim < min_space_dim) {
1460 throw_dimension_incompatible(
"unconstrain(vs)", min_space_dim);
1465 || (!generators_are_up_to_date() && !update_generators())) {
1470 PPL_ASSERT(generators_are_up_to_date());
1473 for (Variables_Set::const_iterator vsi = vars.begin(),
1474 vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
1479 clear_generators_minimized();
1480 clear_congruences_up_to_date();
1489 throw_dimension_incompatible(
"intersection_assign(y)",
"y", y);
1522 PPL_ASSERT(x.
OK() && y.
OK());
1530 throw_dimension_incompatible(
"upper_bound_assign(y)",
"y", y);
1559 normalize_divisors(x.
gen_sys, gs);
1567 PPL_ASSERT(x.
OK(
true) && y.
OK(
true));
1572 const Grid& x = *
this;
1576 throw_dimension_incompatible(
"upper_bound_assign_if_exact(y)",
"y", y);
1590 PPL_ASSERT(generators_are_up_to_date());
1608 throw_dimension_incompatible(
"difference_assign(y)",
"y", y);
1631 y_cgs_end = y_cgs.
end(); i != y_cgs_end; ++i) {
1676 struct Ruled_Out_Pair {
1681 struct Ruled_Out_Less_Than {
1682 bool operator()(
const Ruled_Out_Pair& x,
1683 const Ruled_Out_Pair& y)
const {
1684 return x.num_ruled_out > y.num_ruled_out;
1695 throw_dimension_incompatible(
"simplify_using_context_assign(y)",
"y", y);
1701 set_zero_dim_univ();
1730 gr.refine_no_check(
le == 1);
1735 if (y_modulus_i > 1) {
1736 gr.refine_no_check(
le == 1);
1741 gr.refine_no_check(le2 == y_modulus_i);
1761 std::vector<bool> redundant_by_y(x_cs_num_rows,
false);
1765 redundant_by_y[i] =
true;
1766 ++num_redundant_by_y;
1770 if (num_redundant_by_y < x_cs_num_rows) {
1778 const bool x_first = (x_cs_num_rows > y_cs_num_rows);
1779 Grid z(x_first ? x : y);
1787 if (!redundant_by_y[i]) {
1807 std::vector<Ruled_Out_Pair>
1808 ruled_out_vec(x_cs_num_rows - num_redundant_by_y);
1814 if (!redundant_by_y[i]) {
1822 y_gs_end = y_gs.
end(); k != y_gs_end; ++k) {
1844 ++num_ruled_out_generators;
1846 ruled_out_vec[j].congruence_index = i;
1847 ruled_out_vec[j].num_ruled_out = num_ruled_out_generators;
1851 std::sort(ruled_out_vec.begin(), ruled_out_vec.end(),
1852 Ruled_Out_Less_Than());
1854 const bool empty_intersection = (!z.
minimize());
1858 for (std::vector<Ruled_Out_Pair>::const_iterator
1859 j = ruled_out_vec.begin(), ruled_out_vec_end = ruled_out_vec.end();
1860 j != ruled_out_vec_end;
1865 if ((empty_intersection && w.
is_empty())
1871 return !empty_intersection;
1889 Coefficient_traits::const_reference denominator) {
1891 if (denominator == 0) {
1892 throw_invalid_argument(
"affine_image(v, e, d)",
"d == 0");
1898 if (space_dim < expr_space_dim) {
1899 throw_dimension_incompatible(
"affine_image(v, e, d)",
"e", expr);
1903 if (space_dim < var_space_dim) {
1904 throw_dimension_incompatible(
"affine_image(v, e, d)",
"v", var);
1907 if (marked_empty()) {
1911 Coefficient_traits::const_reference expr_var = expr.
coefficient(var);
1913 if (var_space_dim <= expr_space_dim
1916 if (generators_are_up_to_date()) {
1919 if (denominator > 0) {
1920 gen_sys.affine_image(var, expr, denominator);
1923 gen_sys.affine_image(var, -expr, -denominator);
1925 clear_generators_minimized();
1928 normalize_divisors(gen_sys);
1930 if (congruences_are_up_to_date()) {
1938 con_sys.affine_preimage(var, inverse, expr_var);
1946 con_sys.affine_preimage(var, inverse, -expr_var);
1948 clear_congruences_minimized();
1954 if (!generators_are_up_to_date()) {
1957 if (!marked_empty()) {
1960 if (denominator > 0) {
1961 gen_sys.affine_image(var, expr, denominator);
1964 gen_sys.affine_image(var, -expr, -denominator);
1967 clear_congruences_up_to_date();
1968 clear_generators_minimized();
1971 normalize_divisors(gen_sys);
1981 Coefficient_traits::const_reference denominator) {
1983 if (denominator == 0) {
1984 throw_invalid_argument(
"affine_preimage(v, e, d)",
"d == 0");
1991 if (space_dim < expr_space_dim) {
1992 throw_dimension_incompatible(
"affine_preimage(v, e, d)",
"e", expr);
1996 if (space_dim < var_space_dim) {
1997 throw_dimension_incompatible(
"affine_preimage(v, e, d)",
"v", var);
2000 if (marked_empty()) {
2004 Coefficient_traits::const_reference expr_var = expr.
coefficient(var);
2006 if (var_space_dim <= expr_space_dim && expr_var != 0) {
2008 if (congruences_are_up_to_date()) {
2011 if (denominator > 0) {
2012 con_sys.affine_preimage(var, expr, denominator);
2015 con_sys.affine_preimage(var, -expr, -denominator);
2017 clear_congruences_minimized();
2019 if (generators_are_up_to_date()) {
2027 gen_sys.affine_image(var, inverse, expr_var);
2035 gen_sys.affine_image(var, inverse, -expr_var);
2037 clear_generators_minimized();
2043 if (!congruences_are_up_to_date()) {
2048 if (denominator > 0) {
2049 con_sys.affine_preimage(var, expr, denominator);
2052 con_sys.affine_preimage(var, -expr, -denominator);
2055 clear_generators_up_to_date();
2056 clear_congruences_minimized();
2066 Coefficient_traits::const_reference denominator,
2067 Coefficient_traits::const_reference modulus) {
2069 if (denominator == 0) {
2070 throw_invalid_argument(
"generalized_affine_image(v, r, e, d, m)",
2078 if (space_dim < expr_space_dim) {
2079 throw_dimension_incompatible(
"generalized_affine_image(v, r, e, d, m)",
2084 if (space_dim < var_space_dim) {
2085 throw_dimension_incompatible(
"generalized_affine_image(v, r, e, d, m)",
2090 throw_invalid_argument(
"generalized_affine_image(v, r, e, d, m)",
2091 "r is the disequality relation symbol");
2095 if (marked_empty()) {
2101 if (relsym !=
EQUAL) {
2104 throw_invalid_argument(
"generalized_affine_image(v, r, e, d, m)",
2105 "r != EQUAL && m != 0");
2108 if (!generators_are_up_to_date()) {
2113 if (marked_empty()) {
2117 add_grid_generator(grid_line(var));
2123 PPL_ASSERT(relsym ==
EQUAL);
2125 affine_image(var, expr, denominator);
2133 if (!generators_are_up_to_date()) {
2139 if (marked_empty()) {
2144 gen_sys.insert(parameter(-modulus * var));
2147 gen_sys.insert(parameter(modulus * var));
2150 normalize_divisors(gen_sys);
2152 clear_generators_minimized();
2153 clear_congruences_up_to_date();
2163 Coefficient_traits::const_reference denominator,
2164 Coefficient_traits::const_reference modulus) {
2166 if (denominator == 0) {
2167 throw_invalid_argument(
"generalized_affine_preimage(v, r, e, d, m)",
2174 if (space_dim < expr_space_dim) {
2175 throw_dimension_incompatible(
"generalized_affine_preimage(v, r, e, d, m)",
2180 if (space_dim < var_space_dim) {
2181 throw_dimension_incompatible(
"generalized_affine_preimage(v, r, e, d, m)",
2186 throw_invalid_argument(
"generalized_affine_preimage(v, r, e, d, m)",
2187 "r is the disequality relation symbol");
2192 if (relsym !=
EQUAL) {
2195 throw_invalid_argument(
"generalized_affine_preimage(v, r, e, d, m)",
2196 "r != EQUAL && m != 0");
2199 if (!generators_are_up_to_date()) {
2204 if (marked_empty()) {
2208 add_grid_generator(grid_line(var));
2214 PPL_ASSERT(relsym ==
EQUAL);
2216 if (marked_empty()) {
2221 affine_preimage(var, expr, denominator);
2228 if (var_space_dim <= expr_space_dim && var_coefficient != 0) {
2230 = expr - (denominator + var_coefficient) * var;
2232 neg_assign(inverse_denominator, var_coefficient);
2234 generalized_affine_image(var,
EQUAL, inverse_expr, inverse_denominator,
2238 generalized_affine_image(var,
EQUAL, inverse_expr, inverse_denominator,
2248 Congruence cg((denominator*var %= expr) / denominator);
2255 add_congruence_no_check(cg);
2263 add_grid_generator(grid_line(var));
2272 Coefficient_traits::const_reference modulus) {
2277 if (space_dim < lhs_space_dim) {
2278 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2, m)",
2284 if (space_dim < rhs_space_dim) {
2285 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2, m)",
2290 throw_invalid_argument(
"generalized_affine_image(e1, r, e2, m)",
2291 "r is the disequality relation symbol");
2295 if (marked_empty()) {
2301 if (relsym !=
EQUAL) {
2304 throw_invalid_argument(
"generalized_affine_image(e1, r, e2, m)",
2305 "r != EQUAL && m != 0");
2308 if (!generators_are_up_to_date()) {
2313 if (marked_empty()) {
2319 add_grid_generator(grid_line(i.variable()));
2326 PPL_ASSERT(relsym ==
EQUAL);
2329 tmp_modulus = modulus;
2330 if (tmp_modulus < 0) {
2338 if (lhs_space_dim == 0) {
2340 add_congruence_no_check((lhs %= rhs) / tmp_modulus);
2349 new_lines.
insert(grid_line(i.variable()));
2352 const dimension_type num_common_dims = std::min(lhs_space_dim, rhs_space_dim);
2357 add_space_dimensions_and_embed(1);
2362 add_recycled_congruences(new_cgs1);
2372 update_generators();
2374 normalize_divisors(gen_sys);
2376 clear_congruences_up_to_date();
2377 clear_generators_minimized();
2383 add_recycled_congruences(new_cgs2);
2387 remove_higher_space_dimensions(space_dim-1);
2400 add_recycled_grid_generators(new_lines);
2404 add_congruence_no_check((lhs %= rhs) / tmp_modulus);
2415 Coefficient_traits::const_reference modulus) {
2418 if (space_dim < lhs_space_dim) {
2419 throw_dimension_incompatible(
"generalized_affine_preimage(e1, r, e2, m)",
2424 if (space_dim < rhs_space_dim) {
2425 throw_dimension_incompatible(
"generalized_affine_preimage(e1, r, e2, m)",
2430 throw_invalid_argument(
"generalized_affine_preimage(e1, r, e2, m)",
2431 "r is the disequality relation symbol");
2435 if (marked_empty()) {
2441 if (relsym !=
EQUAL) {
2444 throw_invalid_argument(
"generalized_affine_preimage(e1, r, e2, m)",
2445 "r != EQUAL && m != 0");
2448 if (!generators_are_up_to_date()) {
2452 if (marked_empty()) {
2458 add_grid_generator(grid_line(i.variable()));
2465 PPL_ASSERT(relsym ==
EQUAL);
2468 tmp_modulus = modulus;
2469 if (tmp_modulus < 0) {
2476 if (lhs_space_dim == 0) {
2479 add_congruence_no_check((lhs %= rhs) / tmp_modulus);
2488 new_lines.
insert(grid_line(i.variable()));
2492 = std::min(lhs_space_dim, rhs_space_dim);
2497 add_space_dimensions_and_embed(1);
2502 add_recycled_congruences(new_cgs1);
2512 update_generators();
2514 normalize_divisors(gen_sys);
2516 clear_congruences_up_to_date();
2517 clear_generators_minimized();
2523 add_recycled_congruences(new_cgs2);
2527 remove_higher_space_dimensions(space_dim-1);
2535 add_congruence_no_check((lhs %= rhs) / tmp_modulus);
2543 add_recycled_grid_generators(new_lines);
2553 Coefficient_traits::const_reference denominator) {
2556 if (denominator == 0) {
2557 throw_invalid_argument(
"bounded_affine_image(v, lb, ub, d)",
"d == 0");
2562 if (space_dim < var_space_dim) {
2563 throw_dimension_incompatible(
"bounded_affine_image(v, lb, ub, d)",
2569 if (space_dim < lb_space_dim) {
2570 throw_dimension_incompatible(
"bounded_affine_image(v, lb, ub, d)",
2574 if (space_dim < ub_space_dim) {
2575 throw_dimension_incompatible(
"bounded_affine_image(v, lb, ub, d)",
2580 if (marked_empty()) {
2585 generalized_affine_image(var,
2599 Coefficient_traits::const_reference denominator) {
2602 if (denominator == 0) {
2603 throw_invalid_argument(
"bounded_affine_preimage(v, lb, ub, d)",
"d == 0");
2608 if (space_dim < var_space_dim) {
2609 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
2615 if (space_dim < lb_space_dim) {
2616 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
2620 if (space_dim < ub_space_dim) {
2621 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
2626 if (marked_empty()) {
2632 generalized_affine_preimage(var,
2645 throw_dimension_incompatible(
"time_elapse_assign(y)",
"y", y);
2671 normalize_divisors(gs, gen_sys);
2681 PPL_ASSERT(gs.
sys.OK());
2683 if (gs_num_rows == 0) {
2696 PPL_ASSERT(x.
OK(
true) && y.
OK(
true));
2705 throw_dimension_incompatible(
"frequency(e, ...)",
"e", expr);
2710 if (space_dim == 0) {
2720 if (!generators_are_minimized() && !minimize()) {
2725 return frequency_no_check(expr, freq_n, freq_d, val_n, val_d);
2764 const Grid& x = *
this;
2768 throw_dimension_incompatible(
"contains(y)",
"y", y);
2790 throw_dimension_incompatible(
"is_disjoint_from(y)",
"y", y);
2804 status.ascii_dump(s);
2806 << (congruences_are_up_to_date() ?
"" :
"not_")
2809 con_sys.ascii_dump(s);
2811 << (generators_are_up_to_date() ?
"" :
"not_")
2814 gen_sys.ascii_dump(s);
2815 s <<
"dimension_kinds";
2816 if ((generators_are_up_to_date() && generators_are_minimized())
2817 || (congruences_are_up_to_date() && congruences_are_minimized())) {
2818 for (Dimension_Kinds::const_iterator i = dim_kinds.begin();
2819 i != dim_kinds.end();
2833 if (!(s >> str) || str !=
"space_dim") {
2837 if (!(s >> space_dim)) {
2841 if (!status.ascii_load(s)) {
2845 if (!(s >> str) || str !=
"con_sys") {
2852 if (str ==
"(up-to-date)") {
2853 set_congruences_up_to_date();
2855 else if (str !=
"(not_up-to-date)") {
2859 if (!con_sys.ascii_load(s)) {
2863 if (!(s >> str) || str !=
"gen_sys") {
2870 if (str ==
"(up-to-date)") {
2871 set_generators_up_to_date();
2873 else if (str !=
"(not_up-to-date)") {
2877 if (!gen_sys.ascii_load(s)) {
2881 if (!(s >> str) || str !=
"dimension_kinds") {
2886 && ((generators_are_up_to_date() && generators_are_minimized())
2887 || (congruences_are_up_to_date() && congruences_are_minimized()))) {
2888 dim_kinds.resize(space_dim + 1);
2889 for (Dimension_Kinds::size_type dim = 0; dim <= space_dim; ++dim) {
2890 short unsigned int dim_kind;
2891 if (!(s >> dim_kind)) {
2896 dim_kinds[dim] = PARAMETER;
2899 dim_kinds[dim] = LINE;
2902 dim_kinds[dim] = GEN_VIRTUAL;
2918 con_sys.external_memory_in_bytes()
2919 + gen_sys.external_memory_in_bytes();
2935 throw_dimension_incompatible(
"wrap_assign(vs, ...)", cs_p_space_dim);
2946 if (space_dim < min_space_dim) {
2947 throw_dimension_incompatible(
"wrap_assign(vs, ...)", min_space_dim);
2951 if (marked_empty()) {
2954 if (!generators_are_minimized() && !minimize()) {
2980 const Grid gr = *
this;
2988 for (Variables_Set::const_iterator i = vars.begin(),
2989 vars_end = vars.end(); i != vars_end; ++i) {
3006 if ((v_n > max_value) || (v_n < min_value)) {
3015 v_n %= wrap_frequency;
3018 v_n += wrap_frequency;
3021 add_constraint(x == v_n);
3027 PPL_ASSERT(f_n != 0);
3029 if (f_d % v_d != 0) {
3037 add_congruence((x %= 0) / 1);
3042 add_grid_generator(parameter(wrap_frequency * x));
3045 || (f_n == wrap_frequency)) {
3053 add_constraint(x == v_n);
3073 for (Variables_Set::const_iterator i = vars.begin(),
3074 vars_end = vars.end(); i != vars_end; ++i) {
3084 add_congruence(x %= 0);
3090 add_grid_generator(parameter(x));
3097 if (coeff_x % div != 0) {
3104 if (coeff_x > max_value || coeff_x < min_value) {
3105 add_grid_generator(parameter(x));
3113 if (marked_empty() || space_dim == 0) {
3133 if (space_dimension() < min_space_dim) {
3134 throw_dimension_incompatible(
"drop_some_non_integer_points(vs, cmpl)",
3138 if (marked_empty() || min_space_dim == 0) {
3147 for (Variables_Set::const_iterator i = vars.begin(),
3148 vars_end = vars.end(); i != vars_end; ++i) {
bool is_parameter_or_point() const
Returns true if and only if *this row represents a parameter or a point.
Grid_Generator_System gen_sys
The system of generators.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
bool constraints_are_minimized() const
Returns true if the system of constraints is minimized.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new space dimensions and embeds the old grid in the new vector space.
void drop_some_non_integer_points(Complexity_Class complexity=ANY_COMPLEXITY)
Possibly tightens *this by dropping all points with non-integer coordinates.
An iterator over a system of constraints.
dimension_type space_dimension() const
Returns the dimension of the smallest vector space enclosing all the variables whose indexes are in t...
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
The empty element, i.e., the empty set.
static Poly_Con_Relation is_disjoint()
The polyhedron and the set of points satisfying the constraint are disjoint.
static Poly_Gen_Relation subsumes()
Adding the generator would not change the polyhedron.
dimension_type max_space_dimension()
Returns the maximum space dimension this library can handle.
bool constrains(Variable var) const
Returns true if and only if var is constrained in *this.
Status status
The status flags to keep track of the grid's internal state.
Coefficient_traits::const_reference modulus() const
Returns a const reference to the modulus of *this.
void clear_congruences_minimized()
Sets status to express that congruences are no longer minimized.
A linear equality or inequality.
const_iterator begin() const
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_zero())
Assigns to *this the image of *this with respect to the generalized affine relation ...
bool is_equality() const
Returns true if and only if *this is an equality constraint.
bool is_universe() const
Returns true if and only if *this is a universe grid.
void clear_generators_up_to_date()
Sets status to express that generators are out of date.
bool is_included_in(const Grid &y) const
Returns true if and only if *this is included in y.
void set_space_dimension(dimension_type n)
Sets the dimension of the vector space enclosing *this to n .
void difference_assign(const Grid &y)
Assigns to *this the grid-difference of *this and y.
An iterator over a system of generators.
void set_empty()
Sets status to express that the grid is empty, clearing all corresponding matrices.
Grid(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a grid having the specified properties.
static bool implies(flags_t x, flags_t y)
True if and only if the conjunction x implies the conjunction y.
bool is_equal_to(const Grid_Generator &y) const
Returns true if *this is identical to y.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void add_constraints(const Constraint_System &cs)
Adds to *this congruences equivalent to the constraints in cs.
size_t dimension_type
An unsigned integral type for representing space dimensions.
void insert(const Congruence &cg)
Inserts in *this a copy of the congruence cg, increasing the number of space dimensions if needed...
An std::set of variables' indexes.
Linear_System< Grid_Generator > sys
Congruence_System con_sys
The system of congruences.
bool is_line() const
Returns true if and only if *this is a line.
const Congruence_System & congruences() const
Returns the system of congruences.
A line, ray, point or closure point.
void clear_generators_minimized()
Sets status to express that generators are no longer minimized.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
const Grid_Generator_System & minimized_grid_generators() const
Returns the minimized system of generators.
void add_congruence_no_check(const Congruence &cg)
Adds the congruence cg to *this.
const_iterator end() const
Returns the past-the-end const_iterator.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
Enable_If< Is_Native_Or_Checked< T >::value, void >::type ascii_dump(std::ostream &s, const T &t)
bool is_disjoint_from(const Grid &y) const
Returns true if and only if *this and y are disjoint.
void bounded_affine_image(Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the bounded affine relation . ...
bool set_space_dimension(dimension_type new_space_dim)
Sets the number of space dimensions to new_space_dim.
std::ostream & operator<<(std::ostream &s, const Ask_Tell< D > &x)
bool has_points() const
Returns true if and only if *this contains one or more points.
bool is_discrete() const
Returns true if and only if *this is discrete.
const_iterator end() const
Returns the past-the-end const_iterator.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
static Poly_Con_Relation is_included()
The polyhedron is included in the set of points satisfying the constraint.
The standard C++ namespace.
const_iterator begin() const
Returns the const_iterator pointing to the first generator, if this is not empty; otherwise...
expr_type expression() const
Partial read access to the (adapted) internal expression.
dimension_type last_nonzero() const
expr_type expression() const
Partial read access to the (adapted) internal expression.
void add_congruences(const Congruence_System &cgs)
Adds a copy of each congruence in cgs to *this.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Poly_Con_Relation relation_with(const Congruence &cg) const
Returns the relations holding between *this and cg.
const Constraint_System & constraints() const
Returns the system of constraints.
void set_coefficient(Variable v, Coefficient_traits::const_reference n)
Sets the coefficient of v in *this to n.
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
void set_inhomogeneous_term(Coefficient_traits::const_reference n)
Sets the inhomogeneous term of *this to n.
bool contains_integer_point() const
Returns true if and only if *this contains at least one integer point.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
On overflow, wrapping takes place.
void refine_with_constraints(const Constraint_System &cs)
Uses a copy of the constraints in cs to refine *this.
static bool simplify(Congruence_System &cgs, Dimension_Kinds &dim_kinds)
Converts cgs to upper triangular (i.e. minimized) form.
void set_space_dimension(dimension_type space_dim)
Resizes the system to the specified space dimension.
bool congruences_are_up_to_date() const
Returns true if the system of congruences is up-to-date.
expr_type expression() const
Partial read access to the (adapted) internal expression.
void clear_congruences_up_to_date()
Sets status to express that congruences are out of date.
void m_swap(Grid_Generator_System &y)
Swaps *this with y.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
void time_elapse_assign(const Grid &y)
Assigns to *this the result of computing the time-elapse between *this and y.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void set_generators_minimized()
Sets status to express that generators are minimized.
bool is_proper_congruence() const
Returns true if the modulus is greater than zero.
static const Congruence & zero_dim_false()
Returns a reference to the false (zero-dimension space) congruence .
A dimension of the vector space.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
Bounded_Integer_Type_Overflow
bool have_a_common_variable(const Linear_Expression &x, Variable first, Variable last) const
Returns true if there is a variable from index first (included) to index last (excluded) whose coeffi...
Rounding_Dir inverse(Rounding_Dir dir)
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
bool simplify_using_context_assign(const Grid &y)
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned...
Complexity_Class
Complexity pseudo-classes.
void add_recycled_grid_generators(Grid_Generator_System &gs)
Adds the generators in gs to the system of generators of this.
The base class for convex polyhedra.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Three_Valued_Boolean quick_equivalence_test(const Grid &y) const
Polynomial but incomplete equivalence test between grids.
bool upper_bound_assign_if_exact(const Grid &y)
If the upper bound of *this and y is exact it is assigned to this and true is returned, otherwise false is returned.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool OK(bool check_not_empty=false) const
Checks if all the invariants are satisfied.
void intersection_assign(const Grid &y)
Assigns to *this the intersection of *this and y.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void affine_preimage(Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the affine preimage of *this under the function mapping variable var to the affine e...
Coefficient_traits::const_reference divisor() const
Returns the divisor of *this.
On overflow, the result is undefined.
static int reduced_sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the reduced scalar product of x and y, where the coefficient of x is ignored...
Relation_Symbol
Relation symbols.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool is_equality() const
Returns true if *this is an equality.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
std::vector< Dimension_Kind > Dimension_Kinds
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
An iterator over a system of grid generators.
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Bounded_Integer_Type_Width
const_iterator end() const
Returns the past-the-end const_iterator.
const Congruence_System & minimized_congruences() const
Returns the system of congruences in minimal form.
bool is_line_or_parameter() const
Returns true if and only if *this is a line or a parameter.
const Generator_System & generators() const
Returns the system of generators.
bool is_topologically_closed() const
Returns true if and only if *this is a topologically closed subset of the vector space.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
bool is_point() const
Returns true if and only if *this is a point.
void add_grid_generator(const Grid_Generator &g)
Adds a copy of grid generator g to the system of generators of *this.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
void bounded_affine_preimage(Variable var, const Linear_Expression &lb_expr, const Linear_Expression &ub_expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the preimage of *this with respect to the bounded affine relation ...
Type type() const
Returns the generator type of *this.
const_iterator begin() const
Returns the const_iterator pointing to the first congruence, if this is not empty; otherwise...
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
const Grid_Generator_System & grid_generators() const
Returns the system of generators.
bool contains(const Grid &y) const
Returns true if and only if *this contains y.
bool all_homogeneous_terms_are_zero() const
Returns true if and only if all the homogeneous terms of *this are .
bool frequency_no_check(const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
Returns true if and only if *this is not empty and frequency for *this with respect to expr is define...
bool minimize(const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
bool is_point() const
Returns true if and only if *this is a point.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
void wrap_assign(const Variables_Set &vars, Bounded_Integer_Type_Width w, Bounded_Integer_Type_Representation r, Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p=0, unsigned complexity_threshold=16, bool wrap_individually=true)
Wraps the specified dimensions of the vector space.
void unconstrain(Variable var)
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *...
void mul_2exp_assign(GMP_Integer &x, const GMP_Integer &y, unsigned int exp)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
The universe element, i.e., the whole vector space.
void set_zero_dim_univ()
Sets status to express that the grid is the universe 0-dimension vector space, clearing all correspon...
bool minimize(const Linear_Expression &expr, Coefficient &inf_n, Coefficient &inf_d, bool &minimum) const
Returns true if and only if *this is not empty and expr is bounded from below in *this, in which case the infimum value is computed.
dimension_type space_dim
The number of dimensions of the enclosing vector space.
void neg_assign(GMP_Integer &x)
#define PPL_OUTPUT_DEFINITIONS(class_name)
The entire library is confined to this namespace.
void refine_with_constraint(const Constraint &c)
Uses a copy of the constraint c to refine *this.
An iterator over a system of congruences.
dimension_type affine_dimension() const
Returns , if *this is empty; otherwise, returns the affine dimension of *this.
dimension_type num_rows() const
Returns the number of rows in the system.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Signed binary where negative values are represented by the two's complement of the absolute value...
bool marked_empty() const
Returns true if the grid is known to be empty.
dimension_type num_rows() const
Returns the number of rows (generators) in the system.
bool congruences_are_minimized() const
Returns true if the system of congruences is minimized.
void add_congruence(const Congruence &cg)
Adds a copy of congruence cg to *this.
static void throw_invalid_constraints(const char *method, const char *cs_name)
bool frequency(const Linear_Expression &expr, Coefficient &freq_n, Coefficient &freq_d, Coefficient &val_n, Coefficient &val_d) const
Returns true if and only if *this is not empty and frequency for *this with respect to expr is define...
Dimension_Kinds dim_kinds
const_iterator end() const
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void gcd_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
int sgn(Boundary_Type type, const T &x, const Info &info)
bool operator==(const Box< ITV > &x, const Box< ITV > &y)
bool is_bounded() const
Returns true if and only if *this is bounded.
void update_congruences() const
Updates and minimizes the congruences from the generators.
static int sign(const Linear_Expression &x, const Linear_Expression &y)
Returns the sign of the scalar product between x and y.
void strong_normalize()
Strong normalization: ensures that different Grid_Generator objects represent different hyperplanes o...
static void assign(Coefficient &z, const Linear_Expression &x, const Linear_Expression &y)
Computes the scalar product of x and y and assigns it to z.
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
Coefficient_traits::const_reference divisor() const
If *this is either a point or a closure point, returns its divisor.
void add_grid_generators(const Grid_Generator_System &gs)
Adds a copy of the generators in gs to the system of generators of *this.
bool has_no_rows() const
Returns true if num_rows()==0.
void linear_combine(const Linear_Expression &y, Variable v)
void generalized_affine_preimage(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one(), Coefficient_traits::const_reference modulus=Coefficient_zero())
Assigns to *this the preimage of *this with respect to the generalized affine relation ...
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
bool is_parameter() const
Returns true if and only if *this is a parameter.
Coefficient_traits::const_reference Coefficient_one()
Returns a const reference to a Coefficient with value 1.
void m_swap(Grid &y)
Swaps *this with grid y. (*this and y can be dimension-incompatible.)
void upper_bound_assign(std::map< dimension_type, Linear_Form< FP_Interval_Type > > &ls1, const std::map< dimension_type, Linear_Form< FP_Interval_Type > > &ls2)
bool generators_are_minimized() const
Returns true if the system of generators is minimized.
Grid & operator=(const Grid &y)
The assignment operator. (*this and y can be dimension-incompatible.)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
bool bounds_no_check(const Linear_Expression &expr) const
Checks if and how expr is bounded in *this.
void add_recycled_congruences(Congruence_System &cgs)
Adds the congruences in cgs to *this.
static void throw_invalid_constraint(const char *method, const char *c_name)
void construct(dimension_type num_dimensions, Degenerate_Element kind)
Builds a grid universe or empty grid.
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
const_iterator lower_bound(Variable v) const
bool OK() const
Checks if all the invariants are satisfied.
static Poly_Gen_Relation nothing()
The assertion that says nothing.
void insert(const Grid_Generator &g)
Inserts into *this a copy of the generator g, increasing the number of space dimensions if needed...
void upper_bound_assign(const Grid &y)
Assigns to *this the least upper bound of *this and y.
void affine_image(Variable var, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the affine image of this under the function mapping variable var to the affine expre...
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
The relation between a polyhedron and a generator.
Bounded_Integer_Type_Representation
bool update_generators() const
Updates and minimizes the generators from the congruences.
A grid line, parameter or grid point.
bool all_zeroes(const Variables_Set &vars) const
Returns true if the coefficient of each variable in vars is zero.
void set_congruences_minimized()
Sets status to express that congruences are minimized.
bool is_empty() const
Returns true if and only if *this is an empty grid.
A system of grid generators.
The relation between a polyhedron and a constraint.
bool is_closure_point() const
Returns true if and only if *this is a closure point.
void set_is_parameter()
Converts the Grid_Generator into a parameter.