24 #ifndef PPL_Box_templates_hh
25 #define PPL_Box_templates_hh 1
48 template <
typename ITV>
55 "n exceeds the maximum "
56 "allowed space dimension")),
72 template <
typename ITV>
79 "cs exceeds the maximum "
80 "allowed space dimension")),
89 template <
typename ITV>
96 "cgs exceeds the maximum "
97 "allowed space dimension")),
106 template <
typename ITV>
107 template <
typename Other_ITV>
110 : seq(y.space_dimension()),
127 template <
typename ITV>
133 "gs exceeds the maximum "
134 "allowed space dimension")),
138 if (gs_begin == gs_end) {
149 bool point_seen =
false;
152 gs_i = gs_begin; gs_i != gs_end; ++gs_i) {
167 seq[i].join_assign(iq);
188 throw std::invalid_argument(
"PPL::Box<ITV>::Box(gs):\n"
189 "the non-empty generator system gs "
190 "contains no points.");
195 gs_i != gs_end; ++gs_i) {
211 seq[i.variable().id()].upper_extend();
214 seq[i.variable().id()].lower_extend();
246 template <
typename ITV>
247 template <
typename T>
253 "bds exceeds the maximum "
254 "allowed space dimension")),
268 if (space_dim == 0) {
282 const Coeff& u = dbm_0[i+1];
288 const Coeff& negated_l = bds.
dbm[i+1][0];
294 seq_i.build(lower, upper);
299 template <
typename ITV>
300 template <
typename T>
306 "oct exceeds the maximum "
307 "allowed space dimension")),
320 if (space_dim == 0) {
335 const Coeff& twice_ub = oct.
matrix[cii][ii];
343 const Coeff& twice_lb = oct.
matrix[ii][cii];
350 seq_i.build(lower, upper);
354 template <
typename ITV>
360 "ph exceeds the maximum "
361 "allowed space dimension")),
375 if (space_dim == 0) {
411 ph_cs_end = ph_cs.
end(); i != ph_cs_end; ++i) {
458 seq_i.build(lower, upper);
473 template <
typename ITV>
479 "gr exceeds the maximum "
480 "allowed space dimension")),
493 if (space_dim == 0) {
515 if (gr.
maximize(var, bound_numer, bound_denom, max)) {
518 bound.canonicalize();
527 template <
typename ITV>
528 template <
typename D1,
typename D2,
typename R>
536 "dp exceeds the maximum "
537 "allowed space dimension");
544 template <
typename ITV>
553 "add_space_dimensions_and_embed(m)",
554 "adding m new space dimensions exceeds "
555 "the maximum allowed space dimension");
558 seq.insert(seq.end(), m, ITV(
UNIVERSE));
562 template <
typename ITV>
571 "add_space_dimensions_and_project(m)",
572 "adding m new space dimensions exceeds "
573 "the maximum allowed space dimension");
575 seq.insert(seq.end(), m, ITV(0));
579 template <
typename ITV>
596 if (x.
seq[k] != y.
seq[k]) {
603 template <
typename ITV>
609 if (space_dim < expr_space_dim) {
610 throw_dimension_incompatible((from_above
611 ?
"bounds_from_above(e)"
612 :
"bounds_from_below(e)"),
"e", expr);
615 if (space_dim == 0 || is_empty()) {
618 const int from_above_sign = from_above ? 1 : -1;
622 i_end = expr.
end(); i != i_end; ++i) {
624 switch (
sgn(*i) * from_above_sign) {
626 if (seq[v.
id()].upper_is_boundary_infinity()) {
634 if (seq[v.
id()].lower_is_boundary_infinity()) {
643 template <
typename ITV>
647 Coefficient_traits::const_reference numer,
648 Coefficient_traits::const_reference denom) {
650 if (i.is_universe()) {
657 bound.canonicalize();
659 const bool is_lower_bound = (denom > 0);
663 if (i.lower_is_boundary_infinity()) {
664 PPL_ASSERT(!i.upper_is_boundary_infinity());
667 switch (
sgn(bound_diff)) {
671 return i.upper_is_open()
681 switch (
sgn(bound_diff)) {
685 if (i.lower_is_open()) {
688 if (i.is_singleton()) {
694 if (i.upper_is_boundary_infinity()) {
700 switch (
sgn(bound_diff)) {
704 if (i.upper_is_open()) {
719 if (is_lower_bound) {
720 if (i.lower_is_boundary_infinity()) {
721 PPL_ASSERT(!i.upper_is_boundary_infinity());
724 switch (
sgn(bound_diff)) {
729 || i.upper_is_open()) {
742 switch (
sgn(bound_diff)) {
747 || i.lower_is_open()) {
749 if (i.is_singleton()) {
756 && !i.lower_is_open());
757 if (i.is_singleton()) {
766 if (i.upper_is_boundary_infinity()) {
772 switch (
sgn(bound_diff)) {
777 || i.upper_is_open()) {
792 if (i.upper_is_boundary_infinity()) {
798 switch (
sgn(bound_diff)) {
803 || i.upper_is_open()) {
805 if (i.is_singleton()) {
812 && !i.upper_is_open());
813 if (i.is_singleton()) {
822 if (i.lower_is_boundary_infinity()) {
828 switch (
sgn(bound_diff)) {
833 || i.lower_is_open()) {
852 template <
typename ITV>
859 if (cg_space_dim > space_dim) {
860 throw_dimension_incompatible(
"relation_with(cg)", cg);
868 if (space_dim == 0) {
880 return relation_with(c);
893 t.build(seq[v.
id()].lower_constraint(), seq[v.
id()].upper_constraint());
898 if (r.lower_is_boundary_infinity() || r.upper_is_boundary_infinity()) {
911 v -= ((lower / mod) * mod);
918 template <
typename ITV>
925 if (c_space_dim > space_dim) {
926 throw_dimension_incompatible(
"relation_with(c)", c);
935 if (space_dim == 0) {
962 if (c_num_vars == 0) {
1000 t.build(seq[v.
id()].lower_constraint(), seq[v.
id()].upper_constraint());
1014 template <
typename ITV>
1021 if (space_dim < g_space_dim) {
1022 throw_dimension_incompatible(
"relation_with(g)", g);
1032 if (space_dim == 0) {
1041 if (!seq[i.variable().id()].is_universe()) {
1055 if (!seq[v.
id()].upper_is_boundary_infinity()) {
1063 if (!seq[v.
id()].lower_is_boundary_infinity()) {
1081 const ITV& seq_i = seq[i];
1082 if (seq_i.is_universe()) {
1087 g_coord.canonicalize();
1089 if (!seq_i.lower_is_boundary_infinity()) {
1091 if (g_coord <= bound) {
1092 if (seq_i.lower_is_open()) {
1093 if (g.
is_point() || g_coord != bound) {
1097 else if (g_coord != bound) {
1103 if (!seq_i.upper_is_boundary_infinity()) {
1105 if (g_coord >= bound) {
1106 if (seq_i.upper_is_open()) {
1107 if (g.
is_point() || g_coord != bound) {
1111 else if (g_coord != bound) {
1121 template <
typename ITV>
1124 const bool maximize,
1126 bool& included)
const {
1130 if (space_dim < expr_space_dim) {
1131 throw_dimension_incompatible((maximize
1132 ?
"maximize(e, ...)"
1133 :
"minimize(e, ...)"),
"e", expr);
1137 if (space_dim == 0) {
1138 if (marked_empty()) {
1156 bool is_included =
true;
1157 const int maximize_sign = maximize ? 1 : -1;
1161 i_end = expr.
end(); i != i_end; ++i) {
1162 const ITV& seq_i = seq[i.variable().id()];
1164 switch (
sgn(expr_i) * maximize_sign) {
1166 if (seq_i.upper_is_boundary_infinity()) {
1171 if (seq_i.upper_is_open()) {
1172 is_included =
false;
1179 if (seq_i.lower_is_boundary_infinity()) {
1184 if (seq_i.lower_is_open()) {
1185 is_included =
false;
1192 ext_n = result.get_num();
1193 ext_d = result.get_den();
1194 included = is_included;
1198 template <
typename ITV>
1201 const bool maximize,
1205 if (!max_min(expr, maximize, ext_n, ext_d, included)) {
1212 const int maximize_sign = maximize ? 1 : -1;
1221 const ITV& seq_i = seq[i];
1230 if (seq_i.contains(0)) {
1233 if (!seq_i.lower_is_boundary_infinity()) {
1234 if (seq_i.lower_is_open()) {
1235 if (!seq_i.upper_is_boundary_infinity()) {
1236 if (seq_i.upper_is_open()) {
1241 g_coord += q_seq_i_upper;
1263 PPL_ASSERT(!seq_i.upper_is_boundary_infinity());
1265 if (seq_i.upper_is_open()) {
1289 template <
typename ITV>
1292 const Box& x = *
this;
1310 if (!x.
seq[k].contains(y.
seq[k])) {
1317 template <
typename ITV>
1320 const Box& x = *
this;
1334 if (x.
seq[k].is_disjoint_from(y.
seq[k])) {
1341 template <
typename ITV>
1360 bool x_j_does_not_contain_y_j =
false;
1361 bool y_j_does_not_contain_x_j =
false;
1364 const ITV& x_seq_i = x.
seq[i];
1365 const ITV& y_seq_i = y.
seq[i];
1367 if (!x_seq_i.can_be_exactly_joined_to(y_seq_i)) {
1374 bool y_i_does_not_contain_x_i = !y_seq_i.contains(x_seq_i);
1375 if (y_i_does_not_contain_x_i && x_j_does_not_contain_y_j) {
1378 if (!x_seq_i.contains(y_seq_i)) {
1379 if (y_j_does_not_contain_x_j) {
1383 x_j_does_not_contain_y_j =
true;
1386 if (y_i_does_not_contain_x_i) {
1387 y_j_does_not_contain_x_j =
true;
1393 x.
seq[k].join_assign(y.
seq[k]);
1398 template <
typename ITV>
1401 if (status.test_empty_up_to_date() && !status.test_empty()) {
1406 std::cerr <<
"The box is empty, but it is marked as non-empty."
1414 if (!marked_empty()) {
1425 template <
typename ITV>
1440 if (seq[k].is_singleton()) {
1448 template <
typename ITV>
1451 PPL_ASSERT(!marked_empty());
1454 if (seq[k].is_empty()) {
1463 template <
typename ITV>
1466 if (marked_empty()) {
1470 if (!seq[k].is_universe()) {
1477 template <
typename ITV>
1480 if (ITV::is_always_topologically_closed() || is_empty()) {
1485 if (!seq[k].is_topologically_closed()) {
1492 template <
typename ITV>
1499 if (!seq[k].is_singleton()) {
1506 template <
typename ITV>
1513 if (!seq[k].is_bounded()) {
1520 template <
typename ITV>
1523 if (marked_empty()) {
1527 if (!seq[k].contains_integer_point()) {
1534 template <
typename ITV>
1542 throw_dimension_incompatible(
"frequency(e, ...)",
"e", expr);
1552 if (space_dim == 0) {
1579 const ITV& seq_i = seq[i.variable().id()];
1581 if (seq_i.is_singleton()) {
1584 numer = tmp.get_num();
1585 denom = tmp.get_den();
1587 c += numer * val_denom * (*i);
1604 template <
typename ITV>
1609 if (space_dimension() < var_space_dim) {
1610 throw_dimension_incompatible(
"constrains(v)",
"v", var);
1613 if (marked_empty() || !seq[var_space_dim-1].is_universe()) {
1620 template <
typename ITV>
1632 if (space_dimension() < min_space_dim) {
1633 throw_dimension_incompatible(
"unconstrain(vs)", min_space_dim);
1636 if (marked_empty()) {
1643 for (Variables_Set::const_iterator vsi = vars.begin(),
1644 vsi_end = vars.end(); vsi != vsi_end; ++vsi) {
1645 ITV& seq_vsi = seq[*vsi];
1646 if (!seq_vsi.is_empty()) {
1657 template <
typename ITV>
1660 if (ITV::is_always_topologically_closed() || is_empty()) {
1665 seq[k].topological_closure_assign();
1669 template <
typename ITV>
1676 unsigned complexity_threshold,
1677 bool wrap_individually) {
1678 #if 0 // Generic implementation commented out.
1680 vars, w, r, o, cs_p,
1681 complexity_threshold, wrap_individually,
1683 #else // Specialized implementation.
1691 std::ostringstream s;
1692 s <<
"PPL::Box<ITV>::wrap_assign(vars, w, r, o, cs_p, ...):"
1694 <<
"vars.space_dimension() == " << vars_space_dim
1696 throw std::invalid_argument(s.str());
1702 refine_with_constraints(*cs_p);
1709 if (space_dim < vars_space_dim) {
1710 std::ostringstream s;
1711 s <<
"PPL::Box<ITV>::wrap_assign(vars, ...):"
1713 <<
"this->space_dimension() == " << space_dim
1714 <<
", required space dimension == " << vars_space_dim <<
".";
1715 throw std::invalid_argument(s.str());
1746 integer_quadrant_itv.build(lower, upper);
1751 rational_quadrant_itv.build(lower, upper);
1755 const Variables_Set::const_iterator vs_end = vars.end();
1761 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1762 x.
seq[*i].wrap_assign(w, r, integer_quadrant_itv);
1764 reset_empty_up_to_date();
1767 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1768 ITV& x_seq_v = x.
seq[*i];
1769 if (!rational_quadrant_itv.contains(x_seq_v)) {
1770 x_seq_v.assign(integer_quadrant_itv);
1775 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1776 x.
seq[*i].intersect_assign(integer_quadrant_itv);
1778 reset_empty_up_to_date();
1785 PPL_ASSERT(cs_p != 0);
1788 typedef std::map<dimension_type, std::vector<const Constraint*> > map_type;
1789 map_type var_cs_map;
1791 i_end = cs.
end(); i != i_end; ++i) {
1796 if (c_num_vars == 1) {
1798 PPL_ASSERT(c_only_var < space_dim);
1800 if (vars.find(c_only_var) != vs_end) {
1801 var_cs_map[c_only_var].push_back(&c);
1805 PPL_ASSERT(c_num_vars == 0);
1815 const map_type::const_iterator var_cs_map_end = var_cs_map.end();
1817 for (Variables_Set::const_iterator i = vars.begin(); i != vs_end; ++i) {
1819 refinement_itv = integer_quadrant_itv;
1821 map_type::const_iterator var_cs_map_iter = var_cs_map.find(v);
1822 if (var_cs_map_iter != var_cs_map_end) {
1824 const map_type::mapped_type& var_cs = var_cs_map_iter->second;
1827 refine_interval_no_check(refinement_itv,
1834 ITV& x_seq_v = x.
seq[v];
1837 x_seq_v.wrap_assign(w, r, refinement_itv);
1840 if (!rational_quadrant_itv.contains(x_seq_v)) {
1845 x_seq_v.intersect_assign(refinement_itv);
1853 template <
typename ITV>
1857 && !ITV::info_type::store_open) {
1861 if (marked_empty()) {
1866 seq[k].drop_some_non_integer_points();
1872 template <
typename ITV>
1878 if (space_dimension() < min_space_dim) {
1879 throw_dimension_incompatible(
"drop_some_non_integer_points(vs, cmpl)",
1883 && !ITV::info_type::store_open) {
1887 if (marked_empty()) {
1891 for (Variables_Set::const_iterator v_i = vars.begin(),
1892 v_end = vars.end(); v_i != v_end; ++v_i) {
1893 seq[*v_i].drop_some_non_integer_points();
1899 template <
typename ITV>
1921 if (space_dim == 0) {
1927 reset_empty_up_to_date();
1930 x.
seq[k].intersect_assign(y.
seq[k]);
1936 template <
typename ITV>
1956 x.
seq[k].join_assign(y.
seq[k]);
1962 template <
typename ITV>
1975 if (y_space_dim == 0) {
1982 "concatenate_assign(y)",
1983 "concatenation exceeds the maximum "
1984 "allowed space dimension");
1987 x.
seq.reserve(x_space_dim + y_space_dim);
1992 x.
seq.insert(x.
seq.end(), y_space_dim, ITV(
EMPTY));
1998 std::copy(y.
seq.begin(), y.
seq.end(),
1999 std::back_insert_iterator<Sequence>(x.
seq));
2002 reset_empty_up_to_date();
2008 template <
typename ITV>
2015 throw_dimension_incompatible(
"difference_assign(y)", y);
2022 switch (space_dim) {
2030 x.
seq[0].difference_assign(y.
seq[0]);
2031 if (x.
seq[0].is_empty()) {
2041 if (!y.
seq[i].contains(x.
seq[i])) {
2042 if (++number_non_contained == 1) {
2043 index_non_contained = i;
2051 switch (number_non_contained) {
2057 x.
seq[index_non_contained]
2058 .difference_assign(y.
seq[index_non_contained]);
2059 if (x.
seq[index_non_contained].is_empty()) {
2073 template <
typename ITV>
2084 if (num_dims == 0) {
2106 if (y.
seq[i].is_universe()) {
2111 ITV& seq_i = x.
seq[i];
2112 seq_i.empty_intersection_assign(y.
seq[i]);
2113 if (seq_i.is_empty()) {
2121 for (++i; i < num_dims; ++i) {
2137 if (!x.
seq[i].simplify_using_context_assign(y.
seq[i])) {
2138 PPL_ASSERT(!x.
seq[i].is_empty());
2155 template <
typename ITV>
2167 if (x_space_dim == 0) {
2183 ITV& x_seq_i = x.
seq[i];
2184 const ITV& y_seq_i = y.
seq[i];
2185 if (!x_seq_i.lower_is_boundary_infinity()) {
2186 if (y_seq_i.lower_is_boundary_infinity() || y_seq_i.lower() < 0) {
2187 x_seq_i.lower_extend();
2190 if (!x_seq_i.upper_is_boundary_infinity()) {
2191 if (y_seq_i.upper_is_boundary_infinity() || y_seq_i.upper() > 0) {
2192 x_seq_i.upper_extend();
2199 template <
typename ITV>
2214 if (old_space_dim < vsi_space_dim) {
2215 throw_dimension_incompatible(
"remove_space_dimensions(vs)",
2219 const dimension_type new_space_dim = old_space_dim - vars.size();
2224 if (is_empty() || new_space_dim == 0) {
2225 seq.resize(new_space_dim);
2232 Variables_Set::const_iterator vsi = vars.begin();
2233 Variables_Set::const_iterator vsi_end = vars.end();
2236 for (++vsi; vsi != vsi_end; ++vsi) {
2239 while (src < vsi_next) {
2240 swap(seq[dst++], seq[src++]);
2246 while (src < old_space_dim) {
2247 swap(seq[dst++], seq[src++]);
2250 PPL_ASSERT(dst == new_space_dim);
2251 seq.resize(new_space_dim);
2256 template <
typename ITV>
2262 if (new_dimension > space_dim) {
2263 throw_dimension_incompatible(
"remove_higher_space_dimensions(nd)",
2270 if (new_dimension == space_dim) {
2275 seq.resize(new_dimension);
2279 template <
typename ITV>
2280 template <
typename Partial_Function>
2284 if (space_dim == 0) {
2290 remove_higher_space_dimensions(0);
2297 remove_higher_space_dimensions(new_space_dim);
2306 if (pfunc.
maps(i, new_i)) {
2314 template <
typename ITV>
2321 throw_dimension_incompatible(
"fold_space_dimensions(vs, v)",
"v", dest);
2331 throw_dimension_incompatible(
"fold_space_dimensions(vs, v)",
2335 if (vars.find(dest.
id()) != vars.end()) {
2336 throw_invalid_argument(
"fold_space_dimensions(vs, v)",
2337 "v should not occur in vs");
2344 ITV& seq_v = seq[dest.
id()];
2345 for (Variables_Set::const_iterator i = vars.begin(),
2346 vs_end = vars.end(); i != vs_end; ++i) {
2347 seq_v.join_assign(seq[*i]);
2350 remove_space_dimensions(vars);
2353 template <
typename ITV>
2362 throw_invalid_argument(
"add_constraint(c)",
2363 "c is not an interval constraint");
2369 && ITV::is_always_topologically_closed()) {
2370 throw_invalid_argument(
"add_constraint(c)",
2371 "c is a nontrivial strict constraint");
2375 if (marked_empty()) {
2380 if (c_num_vars == 0) {
2390 PPL_ASSERT(c_num_vars == 1);
2392 add_interval_constraint_no_check(c_only_var, c.
type(), n, d);
2395 template <
typename ITV>
2403 cs_end = cs.
end(); i != cs_end; ++i) {
2404 add_constraint_no_check(*i);
2409 template <
typename ITV>
2424 throw_invalid_argument(
"add_congruence(cg)",
2425 "cg is a nontrivial proper congruence");
2434 throw_invalid_argument(
"add_congruence(cg)",
2435 "cg is not an interval congruence");
2439 if (marked_empty()) {
2444 if (cg_num_vars == 0) {
2452 PPL_ASSERT(cg_num_vars == 1);
2457 template <
typename ITV>
2465 cgs_end = cgs.
end(); i != cgs_end; ++i) {
2466 add_congruence_no_check(*i);
2471 template <
typename ITV>
2475 PPL_ASSERT(!marked_empty());
2481 propagate_constraint_no_check(c);
2486 if (c_num_vars == 0) {
2496 PPL_ASSERT(c_num_vars == 1);
2498 add_interval_constraint_no_check(c_only_var, c.
type(), n, d);
2501 template <
typename ITV>
2506 cs_end = cs.
end(); !marked_empty() && i != cs_end; ++i) {
2507 refine_no_check(*i);
2512 template <
typename ITV>
2515 PPL_ASSERT(!marked_empty());
2533 template <
typename ITV>
2538 cgs_end = cgs.
end(); !marked_empty() && i != cgs_end; ++i) {
2539 refine_no_check(*i);
2544 #if 1 // Alternative implementations for propagate_constraint_no_check.
2545 namespace Implementation {
2579 template <
typename ITV>
2582 using namespace Implementation::Boxes;
2597 if (last_k == c_space_dim + 1) {
2599 if (c_inhomogeneous_term < 0
2600 || (c_inhomogeneous_term == 0
2608 PPL_ASSERT(last_k <= c_space_dim);
2609 Temp_Boundary_Type t_bound;
2610 Temp_Boundary_Type t_a;
2611 Temp_Boundary_Type t_x;
2617 const Variable k_var = k.variable();
2618 const int sgn_a_k =
sgn(a_k);
2626 maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2630 goto maybe_refine_upper_1;
2632 r = neg_assign_r(t_bound, t_bound,
ROUND_DOWN);
2634 goto maybe_refine_upper_1;
2638 const Variable i_var = i.variable();
2639 if (i_var.
id() == k_var.
id()) {
2643 const int sgn_a_i =
sgn(a_i);
2644 ITV& x_i = seq[i_var.
id()];
2646 if (x_i.lower_is_boundary_infinity()) {
2647 goto maybe_refine_upper_1;
2651 goto maybe_refine_upper_1;
2655 goto maybe_refine_upper_1;
2657 if (x_i.lower_is_open()) {
2660 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_DOWN);
2662 goto maybe_refine_upper_1;
2666 PPL_ASSERT(sgn_a_i > 0);
2667 if (x_i.upper_is_boundary_infinity()) {
2668 goto maybe_refine_upper_1;
2672 goto maybe_refine_upper_1;
2676 goto maybe_refine_upper_1;
2678 if (x_i.upper_is_open()) {
2681 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_DOWN);
2683 goto maybe_refine_upper_1;
2689 goto maybe_refine_upper_1;
2691 r = div_assign_r(t_bound, t_bound, t_a,
ROUND_DOWN);
2693 goto maybe_refine_upper_1;
2698 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2706 reset_empty_up_to_date();
2707 maybe_refine_upper_1:
2712 maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2717 r = neg_assign_r(t_bound, t_bound,
ROUND_UP);
2723 const Variable i_var = i.variable();
2724 if (i_var.
id() == k_var.
id()) {
2728 const int sgn_a_i =
sgn(a_i);
2729 ITV& x_i = seq[i_var.
id()];
2731 if (x_i.upper_is_boundary_infinity()) {
2742 if (x_i.upper_is_open()) {
2745 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_UP);
2751 PPL_ASSERT(sgn_a_i > 0);
2752 if (x_i.lower_is_boundary_infinity()) {
2763 if (x_i.lower_is_open()) {
2766 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_UP);
2776 r = div_assign_r(t_bound, t_bound, t_a,
ROUND_UP);
2783 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2789 reset_empty_up_to_date();
2792 PPL_ASSERT(sgn_a_k < 0);
2795 maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2799 goto maybe_refine_upper_2;
2801 r = neg_assign_r(t_bound, t_bound,
ROUND_DOWN);
2803 goto maybe_refine_upper_2;
2807 const Variable i_var = i.variable();
2808 if (i_var.
id() == k_var.
id()) {
2812 const int sgn_a_i =
sgn(a_i);
2813 ITV& x_i = seq[i_var.
id()];
2815 if (x_i.lower_is_boundary_infinity()) {
2816 goto maybe_refine_upper_2;
2820 goto maybe_refine_upper_2;
2824 goto maybe_refine_upper_2;
2826 if (x_i.lower_is_open()) {
2829 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_UP);
2831 goto maybe_refine_upper_2;
2835 PPL_ASSERT(sgn_a_i > 0);
2836 if (x_i.upper_is_boundary_infinity()) {
2837 goto maybe_refine_upper_2;
2841 goto maybe_refine_upper_2;
2845 goto maybe_refine_upper_2;
2847 if (x_i.upper_is_open()) {
2850 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_DOWN);
2852 goto maybe_refine_upper_2;
2858 goto maybe_refine_upper_2;
2860 r = div_assign_r(t_bound, t_bound, t_a,
ROUND_UP);
2862 goto maybe_refine_upper_2;
2866 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2874 reset_empty_up_to_date();
2875 maybe_refine_upper_2:
2880 maybe_reset_fpu_inexact<Temp_Boundary_Type>();
2885 r = neg_assign_r(t_bound, t_bound,
ROUND_UP);
2891 const Variable i_var = i.variable();
2892 if (i_var.
id() == k_var.
id()) {
2896 const int sgn_a_i =
sgn(a_i);
2897 ITV& x_i = seq[i_var.
id()];
2899 if (x_i.upper_is_boundary_infinity()) {
2910 if (x_i.upper_is_open()) {
2913 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_UP);
2919 PPL_ASSERT(sgn_a_i > 0);
2920 if (x_i.lower_is_boundary_infinity()) {
2931 if (x_i.lower_is_open()) {
2934 r = sub_mul_assign_r(t_bound, t_a, t_x,
ROUND_UP);
2944 r = div_assign_r(t_bound, t_bound, t_a,
ROUND_DOWN);
2951 && maybe_check_fpu_inexact<Temp_Boundary_Type>() == 1) {
2957 reset_empty_up_to_date();
2964 #else // Alternative implementations for propagate_constraint_no_check.
2966 template <
typename ITV>
2975 i_end = c_e.lower_bound(
Variable(c_space_dim)); i != i_end; ++i) {
2976 const Variable i_var = i.variable();
2978 ITV& p_i = p[i_var.
id()];
2979 p_i = seq[i_var.
id()];
2980 p_i.mul_assign(p_i, k[i_var.
id()]);
2984 i_end = c_e.lower_bound(Variable(c_space_dim)); i != i_end; ++i) {
2985 const Variable i_var = i.variable();
2986 int sgn_coefficient_i =
sgn(*i);
2987 ITV q(inhomogeneous_term);
2989 j_end = c_e.lower_bound(Variable(c_space_dim)); j != j_end; ++j) {
2990 const Variable j_var = j.variable();
2991 if (i_var == j_var) {
2994 q.add_assign(q, p[j_var.id()]);
2996 q.div_assign(q, k[i_var.id()]);
3016 if (seq[i_var.id()].is_empty()) {
3025 #endif // Alternative implementations for propagate_constraint_no_check.
3027 template <
typename ITV>
3048 propagate_constraint_no_check(*i);
3059 if (num_iterations == max_iterations) {
3063 changed = (copy != seq);
3067 template <
typename ITV>
3071 Coefficient_traits::const_reference denominator) {
3073 if (denominator == 0) {
3074 throw_invalid_argument(
"affine_image(v, e, d)",
"d == 0");
3080 if (space_dim < expr_space_dim) {
3081 throw_dimension_incompatible(
"affine_image(v, e, d)",
"e", expr);
3085 if (space_dim < var_space_dim) {
3086 throw_dimension_incompatible(
"affine_image(v, e, d)",
"v", var);
3098 i_end = expr.
end(); i != i_end; ++i) {
3100 temp1.assign(seq[i.variable().id()]);
3101 temp0.mul_assign(temp0, temp1);
3102 expr_value.add_assign(expr_value, temp0);
3104 if (denominator != 1) {
3105 temp0.assign(denominator);
3106 expr_value.div_assign(expr_value, temp0);
3108 seq[var.
id()].assign(expr_value);
3113 template <
typename ITV>
3120 ::is_exact,
"Box<ITV>::affine_form_image(Variable, Linear_Form):"
3121 "ITV has not a floating point boundary type.");
3126 if (space_dim < lf_space_dim) {
3127 throw_dimension_incompatible(
"affine_form_image(var, lf)",
"lf", lf);
3132 if (space_dim < var_space_dim) {
3133 throw_dimension_incompatible(
"affine_form_image(var, lf)",
"var", var);
3144 const ITV& curr_int = seq[i];
3145 current_addend *= curr_int;
3146 result += current_addend;
3149 seq[var.
id()].assign(result);
3153 template <
typename ITV>
3157 Coefficient_traits::const_reference
3160 if (denominator == 0) {
3161 throw_invalid_argument(
"affine_preimage(v, e, d)",
"d == 0");
3167 if (x_space_dim < expr_space_dim) {
3168 throw_dimension_incompatible(
"affine_preimage(v, e, d)",
"e", expr);
3172 if (x_space_dim < var_space_dim) {
3173 throw_dimension_incompatible(
"affine_preimage(v, e, d)",
"v", var);
3181 const bool invertible = (expr_v != 0);
3188 i_end = expr.
end(); i != i_end; ++i) {
3190 temp1.assign(seq[i.variable().id()]);
3191 temp0.mul_assign(temp0, temp1);
3192 expr_value.add_assign(expr_value, temp0);
3194 if (denominator != 1) {
3195 temp0.assign(denominator);
3196 expr_value.div_assign(expr_value, temp0);
3198 ITV& x_seq_v = seq[var.
id()];
3199 expr_value.intersect_assign(x_seq_v);
3200 if (expr_value.is_empty()) {
3214 inverse += (expr_v + denominator) * var;
3215 affine_image(var, inverse, expr_v);
3220 template <
typename ITV>
3226 Coefficient_traits::const_reference denominator) {
3228 if (denominator == 0) {
3229 throw_invalid_argument(
"bounded_affine_image(v, lb, ub, d)",
"d == 0");
3237 if (space_dim < lb_space_dim) {
3238 throw_dimension_incompatible(
"bounded_affine_image(v, lb, ub, d)",
3242 if (space_dim < ub_space_dim) {
3243 throw_dimension_incompatible(
"bounded_affine_image(v, lb, ub, d)",
3248 if (space_dim < var_space_dim) {
3249 throw_dimension_incompatible(
"affine_image(v, e, d)",
"v", var);
3256 if (denominator > 0) {
3257 refine_with_constraint(lb_expr <= ub_expr);
3260 refine_with_constraint(lb_expr >= ub_expr);
3266 generalized_affine_image(var,
3270 if (denominator > 0) {
3271 refine_with_constraint(lb_expr <= denominator*var);
3274 refine_with_constraint(denominator*var <= lb_expr);
3279 generalized_affine_image(var,
3283 if (denominator > 0) {
3284 refine_with_constraint(denominator*var <= ub_expr);
3287 refine_with_constraint(ub_expr <= denominator*var);
3301 ITV& seq_v = seq[var.
id()];
3302 if (maximize(ub_expr, max_numer, max_denom, max_included)) {
3303 if (minimize(lb_expr, min_numer, min_denom, min_included)) {
3307 min_denom *= denominator;
3315 max_denom *= denominator;
3320 if (denominator > 0) {
3336 max_denom *= denominator;
3346 else if (minimize(lb_expr, min_numer, min_denom, min_included)) {
3350 min_denom *= denominator;
3371 template <
typename ITV>
3377 Coefficient_traits::const_reference denominator) {
3380 if (denominator == 0) {
3381 throw_invalid_argument(
"bounded_affine_preimage(v, lb, ub, d)",
"d == 0");
3387 if (space_dim < var_space_dim) {
3388 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
3394 if (space_dim < lb_space_dim) {
3395 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
3399 if (space_dim < ub_space_dim) {
3400 throw_dimension_incompatible(
"bounded_affine_preimage(v, lb, ub, d)",
3405 if (marked_empty()) {
3409 const bool negative_denom = (denominator < 0);
3415 if (lb_var_coeff == ub_var_coeff) {
3416 if (negative_denom) {
3417 refine_with_constraint(lb_expr >= ub_expr);
3420 refine_with_constraint(lb_expr <= ub_expr);
3424 ITV& seq_var = seq[var.
id()];
3425 if (!seq_var.is_universe()) {
3429 pos_denominator = denominator;
3430 if (negative_denom) {
3431 neg_assign(pos_denominator, pos_denominator);
3435 bool open_lower = seq_var.lower_is_open();
3436 bool unbounded_lower = seq_var.lower_is_boundary_infinity();
3440 if (!unbounded_lower) {
3444 if (negative_denom) {
3447 numer_lower *= pos_denominator;
3448 seq_var.lower_extend();
3450 bool open_upper = seq_var.upper_is_open();
3451 bool unbounded_upper = seq_var.upper_is_boundary_infinity();
3455 if (!unbounded_upper) {
3459 if (negative_denom) {
3462 numer_upper *= pos_denominator;
3463 seq_var.upper_extend();
3466 if (!unbounded_lower) {
3471 revised_lb_expr -= ub_var_coeff * var;
3474 revised_lb_expr *= d;
3475 revised_lb_expr += numer_lower;
3481 if (minimize(revised_lb_expr, numer_lower, denom, included)) {
3482 denom_lower *= (denom * ub_var_coeff);
3491 if ((ub_var_coeff >= 0) ? !negative_denom : negative_denom) {
3498 if (seq_var.is_empty()) {
3505 if (!unbounded_upper) {
3510 revised_ub_expr -= lb_var_coeff * var;
3513 revised_ub_expr *= d;
3514 revised_ub_expr += numer_upper;
3520 if (maximize(revised_ub_expr, numer_upper, denom, included)) {
3521 denom_upper *= (denom * lb_var_coeff);
3530 if ((lb_var_coeff >= 0) ? !negative_denom : negative_denom) {
3537 if (seq_var.is_empty()) {
3547 if (lb_var_coeff != ub_var_coeff) {
3548 if (denominator > 0) {
3549 refine_with_constraint(lb_expr <= ub_expr);
3552 refine_with_constraint(lb_expr >= ub_expr);
3559 template <
typename ITV>
3565 Coefficient_traits::const_reference denominator) {
3567 if (denominator == 0) {
3568 throw_invalid_argument(
"generalized_affine_image(v, r, e, d)",
"d == 0");
3576 throw_dimension_incompatible(
"generalized_affine_image(v, r, e, d)",
3581 if (space_dim < var_space_dim) {
3582 throw_dimension_incompatible(
"generalized_affine_image(v, r, e, d)",
3588 throw_invalid_argument(
"generalized_affine_image(v, r, e, d)",
3589 "r is the disequality relation symbol");
3593 affine_image(var, expr, denominator);
3595 if (relsym ==
EQUAL) {
3604 ITV& seq_var = seq[var.
id()];
3607 seq_var.lower_extend();
3610 seq_var.lower_extend();
3611 if (!seq_var.upper_is_boundary_infinity()) {
3612 seq_var.remove_sup();
3616 seq_var.upper_extend();
3619 seq_var.upper_extend();
3620 if (!seq_var.lower_is_boundary_infinity()) {
3621 seq_var.remove_inf();
3632 template <
typename ITV>
3638 Coefficient_traits::const_reference denominator)
3641 if (denominator == 0) {
3642 throw_invalid_argument(
"generalized_affine_preimage(v, r, e, d)",
3650 throw_dimension_incompatible(
"generalized_affine_preimage(v, r, e, d)",
3655 if (space_dim < var_space_dim) {
3656 throw_dimension_incompatible(
"generalized_affine_preimage(v, r, e, d)",
3661 throw_invalid_argument(
"generalized_affine_preimage(v, r, e, d)",
3662 "r is the disequality relation symbol");
3666 if (relsym ==
EQUAL) {
3667 affine_preimage(var, expr, denominator);
3695 if (var_coefficient != 0) {
3697 = expr - (denominator + var_coefficient) * var;
3699 neg_assign(inverse_denominator, var_coefficient);
3701 = (
sgn(denominator) ==
sgn(inverse_denominator))
3704 generalized_affine_image(var, inverse_relsym, inverse_expr,
3705 inverse_denominator);
3719 bool bound_above = maximize(denominator*var, max_numer, max_denom, max_included);
3723 bool bound_below = minimize(denominator*var, min_numer, min_denom, min_included);
3726 = (denominator > 0) ? relsym : reversed_relsym;
3733 revised_expr = expr;
3740 revised_expr = expr;
3742 revised_expr *= max_denom;
3746 switch (corrected_relsym) {
3749 refine_with_constraint(min_numer < revised_expr);
3755 ? refine_with_constraint(min_numer <= revised_expr)
3756 : refine_with_constraint(min_numer < revised_expr);
3762 ? refine_with_constraint(max_numer >= revised_expr)
3763 : refine_with_constraint(max_numer > revised_expr);
3768 refine_with_constraint(max_numer > revised_expr);
3780 ITV& seq_v = seq[var.id()];
3785 template <
typename ITV>
3796 if (space_dim < lhs_space_dim) {
3797 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2)",
3803 if (space_dim < rhs_space_dim) {
3804 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2)",
3810 throw_invalid_argument(
"generalized_affine_image(e1, r, e2)",
3811 "r is the disequality relation symbol");
3815 if (marked_empty()) {
3823 bool max_rhs = maximize(rhs, max_numer, max_denom, max_included);
3827 bool min_rhs = minimize(rhs, min_numer, min_denom, min_included);
3833 bool has_var =
false;
3836 if (has_var_id != 0) {
3841 if (other_var != has_var_id) {
3844 ITV& seq_var = seq[has_var_id];
3849 ITV& seq_i = seq[other_var];
3858 ITV& seq_var = seq[has_var_id];
3867 max_numer -= inhomo * max_denom;
3871 q_max.canonicalize();
3874 min_numer -= inhomo * min_denom;
3878 q_min.canonicalize();
3913 seq_var.build(l, u);
3969 seq_var.build(l, u);
4003 refine_with_constraint(inhomo < rhs);
4006 refine_with_constraint(inhomo <= rhs);
4009 refine_with_constraint(inhomo == rhs);
4012 refine_with_constraint(inhomo >= rhs);
4015 refine_with_constraint(inhomo > rhs);
4026 template <
typename ITV>
4036 if (space_dim < lhs_space_dim) {
4037 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2)",
4043 if (space_dim < rhs_space_dim) {
4044 throw_dimension_incompatible(
"generalized_affine_image(e1, r, e2)",
4050 throw_invalid_argument(
"generalized_affine_image(e1, r, e2)",
4051 "r is the disequality relation symbol");
4054 if (marked_empty()) {
4063 i_end = lhs.
end(); i != i_end; ++i) {
4071 generalized_affine_image(revised_lhs, relsym, revised_rhs);
4075 template <
typename ITV>
4076 template <
typename T,
typename Iterator>
4085 seq[i].CC76_widening_assign(y.seq[i], first, last);
4091 template <
typename ITV>
4092 template <
typename T>
4094 && Is_Same_Or_Derived<Interval_Base, ITV>::value,
4097 static typename ITV::boundary_type stop_points[] = {
4098 typename ITV::boundary_type(-2),
4099 typename ITV::boundary_type(-1),
4100 typename ITV::boundary_type(0),
4101 typename ITV::boundary_type(1),
4102 typename ITV::boundary_type(2)
4107 if (tp != 0 && *tp > 0) {
4119 +
sizeof(stop_points)/
sizeof(stop_points[0]));
4122 template <
typename ITV>
4125 Box& limiting_box)
const {
4130 cs_end = cs.
end(); cs_i != cs_end; ++cs_i) {
4139 if (c_num_vars != 0) {
4153 template <
typename ITV>
4163 throw_dimension_incompatible(
"limited_CC76_extrapolation_assign(y, cs)",
4168 if (space_dim < cs_space_dim) {
4169 throw_constraint_incompatible(
"limited_CC76_extrapolation_assign(y, cs)");
4173 if (space_dim == 0) {
4177 PPL_EXPECT_HEAVY(copy_contains(*
this, y));
4180 if (marked_empty()) {
4190 get_limiting_box(cs, limiting_box);
4195 intersection_assign(limiting_box);
4198 template <
typename ITV>
4199 template <
typename T>
4201 && Is_Same_Or_Derived<Interval_Base, ITV>::value,
4207 if (space_dim != y.space_dimension()) {
4208 throw_dimension_incompatible(
"CC76_narrowing_assign(y)", y);
4212 PPL_EXPECT_HEAVY(copy_contains(y, *
this));
4216 if (space_dim == 0) {
4231 const ITV& y_i = y.seq[i];
4232 if (!x_i.lower_is_boundary_infinity()
4233 && !y_i.lower_is_boundary_infinity()
4234 && x_i.lower() != y_i.lower()) {
4235 x_i.lower() = y_i.lower();
4237 if (!x_i.upper_is_boundary_infinity()
4238 && !y_i.upper_is_boundary_infinity()
4239 && x_i.upper() != y_i.upper()) {
4240 x_i.upper() = y_i.upper();
4246 template <
typename ITV>
4253 if (space_dim == 0) {
4254 if (marked_empty()) {
4260 if (marked_empty()) {
4269 bool closed =
false;
4270 if (has_lower_bound(v_k, n, d, closed)) {
4278 if (has_upper_bound(v_k, n, d, closed)) {
4290 template <
typename ITV>
4297 if (space_dim == 0) {
4298 if (marked_empty()) {
4314 bool closed =
false;
4315 if (has_lower_bound(v_k, n, d, closed)) {
4318 if (seq[k].is_singleton()) {
4330 if (has_upper_bound(v_k, n, d, closed)) {
4342 template <
typename ITV>
4348 if (space_dim == 0) {
4349 if (marked_empty()) {
4365 bool closed =
false;
4366 if (has_lower_bound(v_k, n, d, closed) && closed) {
4368 if (seq[k].is_singleton()) {
4369 cgs.
insert((d * v_k %= n) / 0);
4376 template <
typename ITV>
4381 n += seq[k].external_memory_in_bytes();
4387 template <
typename ITV>
4389 IO_Operators::operator<<(std::ostream& s, const Box<ITV>& box) {
4390 if (box.is_empty()) {
4393 else if (box.is_universe()) {
4398 space_dim = box.space_dimension(); k < space_dim; ) {
4399 s <<
Variable(k) <<
" in " << box[k];
4401 if (k < space_dim) {
4412 template <
typename ITV>
4416 status.ascii_dump(s);
4418 s <<
"space_dim" << separator << space_dim;
4421 seq[i].ascii_dump(s);
4427 template <typename ITV>
4430 if (!status.ascii_load(s)) {
4435 if (!(s >> str) || str !=
"space_dim") {
4438 if (!(s >> space_dim)) {
4444 if (seq_i.ascii_load(s)) {
4445 seq.push_back(seq_i);
4457 template <
typename ITV>
4460 const Box& y)
const {
4461 std::ostringstream s;
4462 s <<
"PPL::Box::" << method <<
":" << std::endl
4463 <<
"this->space_dimension() == " << this->space_dimension()
4465 throw std::invalid_argument(s.str());
4468 template <
typename ITV>
4473 std::ostringstream s;
4474 s <<
"PPL::Box::" << method <<
":" << std::endl
4475 <<
"this->space_dimension() == " << space_dimension()
4476 <<
", required dimension == " << required_dim <<
".";
4477 throw std::invalid_argument(s.str());
4480 template <
typename ITV>
4484 std::ostringstream s;
4485 s <<
"PPL::Box::" << method <<
":" << std::endl
4486 <<
"this->space_dimension() == " << space_dimension()
4488 throw std::invalid_argument(s.str());
4491 template <
typename ITV>
4495 std::ostringstream s;
4496 s <<
"PPL::Box::" << method <<
":" << std::endl
4497 <<
"this->space_dimension() == " << space_dimension()
4499 throw std::invalid_argument(s.str());
4502 template <
typename ITV>
4506 std::ostringstream s;
4507 s <<
"PPL::Box::" << method <<
":" << std::endl
4508 <<
"this->space_dimension() == " << space_dimension()
4510 throw std::invalid_argument(s.str());
4513 template <
typename ITV>
4517 std::ostringstream s;
4518 s <<
"PPL::Box::" << method <<
":" << std::endl
4519 <<
"this->space_dimension() == " << space_dimension()
4521 throw std::invalid_argument(s.str());
4524 template <
typename ITV>
4528 std::ostringstream s;
4529 s <<
"PPL::Box::" << method <<
":" << std::endl
4530 <<
"this->space_dimension() == " << space_dimension()
4532 throw std::invalid_argument(s.str());
4535 template <
typename ITV>
4538 std::ostringstream s;
4539 s <<
"PPL::Box::" << method <<
":" << std::endl
4540 <<
"the constraint is incompatible.";
4541 throw std::invalid_argument(s.str());
4544 template <
typename ITV>
4548 using namespace IO_Operators;
4549 std::ostringstream s;
4550 s <<
"PPL::Box::" << method <<
":" << std::endl
4551 << le <<
" is too complex.";
4552 throw std::invalid_argument(s.str());
4555 template <
typename ITV>
4558 const char* le_name,
4560 std::ostringstream s;
4561 s <<
"PPL::Box::" << method <<
":" << std::endl
4562 <<
"this->space_dimension() == " << space_dimension()
4563 <<
", " << le_name <<
"->space_dimension() == "
4565 throw std::invalid_argument(s.str());
4568 template <
typename ITV>
4569 template <
typename C>
4572 const char* lf_name,
4574 std::ostringstream s;
4575 s <<
"PPL::Box::" << method <<
":\n"
4576 <<
"this->space_dimension() == " << space_dimension()
4577 <<
", " << lf_name <<
"->space_dimension() == "
4579 throw std::invalid_argument(s.str());
4582 template <
typename ITV>
4585 std::ostringstream s;
4586 s <<
"PPL::Box::" << method <<
":" << std::endl
4588 throw std::invalid_argument(s.str());
4591 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
4593 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
4594 template <
typename Specialization,
4595 typename Temp,
typename To,
typename ITV>
4600 Temp& tmp0, Temp& tmp1, Temp& tmp2) {
4607 if (x_space_dim == 0) {
4634 const ITV& x_i = x.
seq[i];
4635 const ITV& y_i = y.
seq[i];
4637 if (x_i.lower_is_boundary_infinity()) {
4638 if (!y_i.lower_is_boundary_infinity()) {
4642 else if (y_i.lower_is_boundary_infinity()) {
4648 if (x_i.lower() > y_i.lower()) {
4656 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
4657 PPL_ASSERT(
sgn(tmp1) >= 0);
4661 if (x_i.upper_is_boundary_infinity()) {
4662 if (y_i.upper_is_boundary_infinity()) {
4669 else if (y_i.upper_is_boundary_infinity()) {
4675 if (x_i.upper() > y_i.upper()) {
4683 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
4684 PPL_ASSERT(
sgn(tmp1) >= 0);
4699 #endif // !defined(PPL_Box_templates_hh)
Congruence_System congruences() const
Returns a system of congruences approximating *this.
Grid_Generator_System gen_sys
The system of generators.
bool marked_empty() const
Returns true if the BDS is known to be empty.
Minimization is requested.
bool has_pending_constraints() const
Returns true if there are pending constraints.
bool is_satisfiable() const
Checks satisfiability of *this.
static bool extract_interval_congruence(const Congruence &cg, dimension_type &cg_num_vars, dimension_type &cg_only_var)
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
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...
void m_swap(Box &y)
Swaps *this with y (*this and y can be dimension-incompatible).
bool marked_empty() const
Returns true if the polyhedron is known to be empty.
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
The partially reduced product of two abstractions.
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 is_disjoint_from(const Box &y) const
Returns true if and only if *this and y are disjoint.
The computed result is exact.
void set_optimization_mode(Optimization_Mode mode)
Sets the optimization mode to mode.
void throw_dimension_incompatible(const char *method, const Box &y) const
Coefficient_traits::const_reference modulus() const
Returns a const reference to the modulus of *this.
bool l_m_distance_assign(Checked_Number< To, Extended_Number_Policy > &r, const Box< ITV > &x, const Box< ITV > &y, const Rounding_Dir dir, Temp &tmp0, Temp &tmp1, Temp &tmp2)
A linear equality or inequality.
std::vector< ITV > Sequence
The type of sequence used to implement the box.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
const_iterator begin() const
bool is_equality() const
Returns true if and only if *this is an equality constraint.
void swap(CO_Tree &x, CO_Tree &y)
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
An iterator over a system of generators.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void add_congruences_no_check(const Congruence_System &cgs)
WRITE ME.
size_t dimension_type
An unsigned integral type for representing space dimensions.
bool empty() const
Returns true if and only if *this has no generators.
void limited_CC76_extrapolation_assign(const Box &y, const Constraint_System &cs, unsigned *tp=0)
Improves the result of the CC76-extrapolation computation by also enforcing those constraints in cs t...
Box(dimension_type num_dimensions=0, Degenerate_Element kind=UNIVERSE)
Builds a universe or empty box of the specified space dimension.
Type type() const
Returns the constraint type of *this.
Status status
The status flags to keep track of the internal state.
void insert(const Congruence &cg)
Inserts in *this a copy of the congruence cg, increasing the number of space dimensions if needed...
void generalized_affine_image(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the image of *this with respect to the generalized affine relation ...
void set_space_dimension(dimension_type space_dim)
Sets the space dimension of the rows in the system to space_dim .
An std::set of variables' indexes.
A line, ray, point or closure point.
void add_constraints(const Constraint_System &cs)
Adds a copy of the constraints in cs to the MIP problem.
void remove_higher_space_dimensions(dimension_type new_dimension)
Removes the higher dimensions so that the resulting space will have dimension new_dimension.
bool is_empty() const
Returns true if and only if *this is an empty polyhedron.
bool is_line_or_ray() const
Returns true if and only if *this is a line or a ray.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
Rounding_Dir
Rounding directions for arithmetic computations.
#define PPL_DIRTY_TEMP_COEFFICIENT(id)
Declare a local variable named id, of type Coefficient, and containing an unknown initial value...
ITV Tmp_Interval_Type
The type of intervals used by inner computations when trying to limit the cumulative effect of approx...
void add_congruence_no_check(const Congruence &cg)
WRITE ME.
A positive integer overflow occurred (rounding up).
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false congruence).
bool is_topologically_closed() const
Returns true if and only if *this is a topologically closed subset of the vector space.
bool contains_integer_point() const
Returns true if and only if *this contains at least one integer point.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
static const Constraint_System & zero_dim_empty()
Returns the singleton system containing only Constraint::zero_dim_false().
bool is_empty() const
Returns true if and only if *this is an empty box.
static const Constraint & zero_dim_false()
The unsatisfiable (zero-dimension space) constraint .
void propagate_constraints_no_check(const Constraint_System &cs, dimension_type max_iterations)
Propagates the constraints in cs to refine *this.
void insert(const Constraint &c)
Inserts in *this a copy of the constraint c, increasing the number of space dimensions if needed...
dimension_type num_constraints(const Constraint_System &cs)
Helper returning number of constraints in system.
Result
Possible outcomes of a checked arithmetic computation.
const_iterator end() const
Returns the past-the-end const_iterator.
From bool Type Type Rounding_Dir To
static const Congruence_System & zero_dim_empty()
Returns the system containing only Congruence::zero_dim_false().
void add_constraints_no_check(const Constraint_System &cs)
WRITE ME.
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.
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 there exist a unique value val such that *this saturates the equality exp...
The standard C++ namespace.
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.
#define PPL_OUTPUT_TEMPLATE_DEFINITIONS(type_symbol, class_prefix)
void lcm_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void unconstrain(Variable var)
Computes the cylindrification of *this with respect to space dimension var, assigning the result to *...
void upper_bound_assign(const Box &y)
Assigns to *this the smallest box containing the union of *this and y.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
const Constraint_System & constraints() const
Returns the system of constraints.
bool has_empty_codomain() const
Returns true if and only if the represented partial function has an empty codomain (i...
static Poly_Con_Relation saturates()
The polyhedron is included in the set of points saturating the constraint.
void evaluate_objective_function(const Generator &evaluating_point, Coefficient &numer, Coefficient &denom) const
Sets num and denom so that is the result of evaluating the objective function on evaluating_point...
void set_inhomogeneous_term(Coefficient_traits::const_reference n)
Sets the inhomogeneous term of *this to n.
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *this.
void add_constraint(const Constraint &c)
Adds a copy of constraint c to the MIP problem.
const_iterator begin() const
Returns the const_iterator pointing to the first constraint, if *this is not empty; otherwise...
OR_Matrix< N > matrix
The matrix that represents the octagonal shape.
bool check_empty() const
Checks the hard way whether *this is an empty box: returns true if and only if it is so...
On overflow, wrapping takes place.
void exact_div_assign(Checked_Number< T, Policy > &x, const Checked_Number< T, Policy > &y, const Checked_Number< T, Policy > &z)
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
const_iterator lower_bound(Variable v) const
Worst-case polynomial complexity.
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
The computed result is inexact and rounded down.
dimension_type id() const
Returns the index of the Cartesian axis associated to the variable.
static bool extract_interval_constraint(const Constraint &c, dimension_type &c_num_vars, dimension_type &c_only_var)
Decodes the constraint c as an interval constraint.
const Generator & optimizing_point() const
Returns an optimal point for *this, if it exists.
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.
Bounded_Integer_Type_Overflow
void topological_closure_assign()
Assigns to *this its topological closure.
Enable_If< Is_Same< T, Box >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type CC76_narrowing_assign(const T &y)
Assigns to *this the result of restoring in y the constraints of *this that were lost by CC76-extrapo...
void shortest_path_closure_assign() const
Assigns to this->dbm its shortest-path closure.
Rounding_Dir inverse(Rounding_Dir dir)
Constraint_System minimized_constraints() const
Returns a minimized system of constraints defining *this.
bool is_strict_inequality() const
Returns true if and only if *this is a strict inequality constraint.
Complexity_Class
Complexity pseudo-classes.
The base class for convex polyhedra.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Worst-case exponential complexity but typically polynomial behavior.
The base class for the single rows of matrices.
void get_limiting_box(const Constraint_System &cs, Box &limiting_box) const
Adds to limiting_box the interval constraints in cs that are satisfied by *this.
bool is_inequality() const
Returns true if and only if *this is an inequality constraint (either strict or non-strict).
Constraint_System simplified_constraints() const
If constraints are up-to-date, obtain a simplified copy of them.
A wrapper for numeric types implementing a given policy.
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
bool is_canonical(const mpq_class &x)
Returns true if and only if x is in canonical form.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
On overflow, the result is undefined.
Poly_Con_Relation interval_relation(const ITV &i, const Constraint::Type constraint_type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom=Coefficient_one())
Returns the relations holding between an interval and an interval constraint.
void finalize()
Finalizes the library.
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
void strong_closure_assign() const
Assigns to this->matrix its strong closure.
void intersection_assign(const Box &y)
Assigns to *this the intersection of *this and y.
A class holding a constant called value that evaluates to true if and only if Base is the same type a...
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.
Degenerate_Element
Kinds of degenerate abstract elements.
Type type() const
Returns the generator type of *this.
bool constraints_are_up_to_date() const
Returns true if the system of constraints is up-to-date.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
dimension_type affine_dimension() const
Returns , if *this is empty; otherwise, returns the affine dimension of *this.
dimension_type last_nonzero() const
dimension_type check_space_dimension_overflow(const dimension_type dim, const dimension_type max, const char *domain, const char *method, const char *reason)
Greater than or equal to.
Bounded_Integer_Type_Width
void reset_empty_up_to_date()
Invalidates empty flag of *this.
void drop_some_non_integer_points(Complexity_Class complexity=ANY_COMPLEXITY)
Possibly tightens *this by dropping some points with non-integer coordinates.
const_iterator end() const
Returns the past-the-end const_iterator.
static void throw_constraint_incompatible(const char *method)
void set_nonempty()
Marks *this as definitely not empty.
A Mixed Integer (linear) Programming problem.
const_iterator end() const
Iterator pointing after the last nonzero variable coefficient.
const Generator_System & generators() const
Returns the system of generators.
void propagate_constraint_no_check(const Constraint &c)
Propagates the constraint c to refine *this.
bool is_inconsistent() const
Returns true if and only if *this is inconsistent (i.e., an always false constraint).
Sequence seq
A sequence of intervals, one for each dimension of the vector space.
#define WEIGHT_ADD_MUL(delta, factor)
Result result_relation_class(Result r)
bool propagate_constraint_check_result(Result r, Ternary &open)
static dimension_type max_space_dimension()
Returns the maximum space dimension that a Box can handle.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
static void throw_invalid_argument(const char *method, const char *reason)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
A not necessarily closed, iso-oriented hyperrectangle.
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.
const_iterator begin() const
Returns the const_iterator pointing to the first congruence, if this is not empty; otherwise...
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 ...
PPL_COEFFICIENT_TYPE Coefficient
An alias for easily naming the type of PPL coefficients.
bool is_point() const
Returns true if and only if *this is a point.
bool marked_empty() const
Returns true if the OS is known to be empty.
bool is_tautological() const
Returns true if and only if *this is a tautology (i.e., an always true congruence).
void wrap_assign(PSET &pointset, const Variables_Set &vars, const Bounded_Integer_Type_Width w, const Bounded_Integer_Type_Representation r, const Bounded_Integer_Type_Overflow o, const Constraint_System *cs_p, const unsigned complexity_threshold, const bool wrap_individually, const char *class_name)
void mul_2exp_assign(GMP_Integer &x, const GMP_Integer &y, unsigned int exp)
void add_space_dimensions_and_project(dimension_type m)
Adds m new dimensions to the box and does not embed it in the new vector space.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
void fold_space_dimensions(const Variables_Set &vars, Variable dest)
Folds the space dimensions in vars into dest.
The computed result may be inexact and rounded up.
bool upper_bound_assign_if_exact(const Box &y)
If the upper bound of *this and y is exact, it is assigned to *this and true is returned, otherwise false is returned.
#define PPL_DIRTY_TEMP(T, id)
bool generators_are_up_to_date() const
Returns true if the system of generators is up-to-date.
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 . ...
Interval_Boundary_Type type
The universe element, i.e., the whole vector space.
void add_constraint_no_check(const Constraint &c)
WRITE ME.
A generic, not necessarily closed, possibly restricted interval.
dimension_type max_in_codomain() const
If the codomain is not empty, returns the maximum value in it.
static Generator point(const Linear_Expression &e=Linear_Expression::zero(), Coefficient_traits::const_reference d=Coefficient_one(), Representation r=default_representation)
Returns the point at e / d.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Plus_Infinity PLUS_INFINITY
void neg_assign(GMP_Integer &x)
Coefficient_traits::const_reference Coefficient_zero()
Returns a const reference to a Coefficient with value 0.
bool is_ray() const
Returns true if and only if *this is a ray.
The entire library is confined to this namespace.
An iterator over a system of congruences.
void refine_no_check(const Constraint &c)
Uses the constraint c to refine *this.
const D2 & domain2() const
Returns a constant reference to the second of the pair.
bool test_empty_up_to_date() const
bool bounds(const Linear_Expression &expr, bool from_above) const
Checks if and how expr is bounded in *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.
void concatenate_assign(const Box &y)
Seeing a box as a set of tuples (its points), assigns to *this all the tuples that can be obtained by...
Maximization is requested.
void set_empty_up_to_date()
Asserts the validity of the empty flag of *this.
const_iterator end() const
Returns the past-the-end const_iterator.
Constraint_System constraints() const
Returns a system of constraints defining *this.
const_iterator begin() const
Returns the const_iterator pointing to the first generator, if *this is not empty; otherwise...
bool is_bounded() const
Returns true if and only if *this is a bounded box.
void difference_assign(const Box &y)
Assigns to *this the difference of *this and y.
A bounded difference shape.
The computed result may be inexact and rounded down.
I_Result combine(Result l, Result u)
void set_objective_function(const Linear_Expression &obj)
Sets the objective function to obj.
MIP_Problem_Status solve() const
Optimizes the MIP problem.
bool maximize(const Linear_Expression &expr, Coefficient &sup_n, Coefficient &sup_d, bool &maximum) const
Returns true if and only if *this is not empty and expr is bounded from above in *this, in which case the supremum value is computed.
void time_elapse_assign(const Box &y)
Assigns to *this the result of computing the time-elapse between *this and y.
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
static void throw_expression_too_complex(const char *method, const Linear_Expression &le)
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
bool simplify_using_context_assign(const Box &y)
Assigns to *this a meet-preserving simplification of *this with respect to y. If false is returned...
const_iterator end() const
int sgn(Boundary_Type type, const T &x, const Info &info)
void sub_mul_assign(GMP_Integer &x, const GMP_Integer &y, const GMP_Integer &z)
void affine_form_image(Variable var, const Linear_Form< ITV > &lf)
Assigns to *this the affine form image of *this under the function mapping variable var into the affi...
#define PPL_USED(v)
No-op macro that allows to avoid unused variable warnings from the compiler.
bool operator==(const Box< ITV > &x, const Box< ITV > &y)
void normalize2(Coefficient_traits::const_reference x, Coefficient_traits::const_reference y, Coefficient &n_x, Coefficient &n_y)
If is the GCD of x and y, the values of x and y divided by are assigned to n_x and n_y...
bool maps(dimension_type i, dimension_type &j) const
If *this maps i to a value k, assigns k to j and returns true; otherwise, j is unchanged and false is...
bool constrains(Variable var) const
Returns true if and only if var is constrained in *this.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.
void generalized_affine_preimage(Variable var, Relation_Symbol relsym, const Linear_Expression &expr, Coefficient_traits::const_reference denominator=Coefficient_one())
Assigns to *this the preimage of *this with respect to the generalized affine relation ...
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.
A negative integer overflow occurred (rounding down).
base_type::const_iterator const_iterator
The type of const iterators on coefficients.
bool contains(const Box &y) const
Returns true if and only if *this contains y.
void map_space_dimensions(const Partial_Function &pfunc)
Remaps the dimensions of the vector space according to a partial function.
dimension_type first_nonzero(dimension_type first, dimension_type last) const
Coefficient_traits::const_reference inhomogeneous_term() const
Returns the inhomogeneous term of *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...
Poly_Con_Relation relation_with(const Constraint &c) const
Returns the relations holding between *this and the constraint c.
Coefficient_traits::const_reference Coefficient_one()
Returns a const reference to a Coefficient with value 1.
expr_type expression() const
Partial read access to the (adapted) internal expression.
The computed result is inexact and rounded up.
A class that provides a type member called type equivalent to T if and only if b is true...
Coefficient_traits::const_reference coefficient(Variable v) const
Returns the coefficient of v in *this.
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 expr...
const_iterator begin() const
Iterator pointing to the first nonzero variable coefficient.
bool OK() const
Returns true if and only if *this satisfies all its invariants.
bool is_discrete() const
Returns true if and only if *this is discrete.
dimension_type space_dimension() const
Returns the dimension of the vector space enclosing *this.
Enable_If< Is_Same< T, Box >::value &&Is_Same_Or_Derived< Interval_Base, ITV >::value, void >::type CC76_widening_assign(const T &y, unsigned *tp=0)
Assigns to *this the result of computing the CC76-widening between *this and y.
void remove_space_dimensions(const Variables_Set &vars)
Removes all the specified dimensions.
bool is_line() const
Returns true if and only if *this is a line.
static Poly_Con_Relation nothing()
The assertion that says nothing.
void set(I_Constraint_Rel r, Arg_Type v)
static Poly_Con_Relation strictly_intersects()
The polyhedron intersects the set of points satisfying the constraint, but it is not included in it...
static Poly_Gen_Relation nothing()
The assertion that says nothing.
bool max_min(const Linear_Expression &expr, bool maximize, Coefficient &ext_n, Coefficient &ext_d, bool &included, Generator &g) const
Maximizes or minimizes expr subject to *this.
An adapter for Linear_Expression that maybe hides the last coefficient.
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
void add_interval_constraint_no_check(dimension_type var_id, Constraint::Type type, Coefficient_traits::const_reference numer, Coefficient_traits::const_reference denom)
WRITE ME.
The relation between a polyhedron and a generator.
Bounded_Integer_Type_Representation
bool update_generators() const
Updates and minimizes the generators from the congruences.
DB_Matrix< N > dbm
The matrix representing the system of bounded differences.
The problem has an optimal solution.
Result maybe_assign(const To *&top, To &tmp, const From &from, Rounding_Dir dir)
Assigns to top a pointer to a location that holds the conversion, according to dir, of from to type To. When necessary, and only when necessary, the variable tmp is used to hold the result of conversion.
const D1 & domain1() const
Returns a constant reference to the first of the pair.
bool is_universe() const
Returns true if and only if *this is a universe box.
bool marked_empty() const
Returns true if and only if the box is known to be empty.
The relation between a polyhedron and a constraint.
void add_space_dimensions_and_embed(dimension_type m)
Adds m new dimensions and embeds the old box into the new space.
const_iterator end() const
Iterator pointing after the last nonzero variable coefficient.
void set_empty()
Causes the box to become empty, i.e., to represent the empty set.
bool has_strict_inequalities() const
Returns true if and only if *this contains one or more strict inequality constraints.