00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PPL_Box_inlines_hh
00025 #define PPL_Box_inlines_hh 1
00026
00027 #include "Boundary.defs.hh"
00028 #include "Constraint_System.defs.hh"
00029 #include "Constraint_System.inlines.hh"
00030 #include "Congruence_System.defs.hh"
00031 #include "Congruence_System.inlines.hh"
00032 #include "distances.defs.hh"
00033
00034 namespace Parma_Polyhedra_Library {
00035
00036 template <typename ITV>
00037 inline bool
00038 Box<ITV>::marked_empty() const {
00039 return status.test_empty_up_to_date() && status.test_empty();
00040 }
00041
00042 template <typename ITV>
00043 inline void
00044 Box<ITV>::set_empty() {
00045 status.set_empty();
00046 status.set_empty_up_to_date();
00047 }
00048
00049 template <typename ITV>
00050 inline void
00051 Box<ITV>::set_nonempty() {
00052 status.reset_empty();
00053 status.set_empty_up_to_date();
00054 }
00055
00056 template <typename ITV>
00057 inline void
00058 Box<ITV>::set_empty_up_to_date() {
00059 status.set_empty_up_to_date();
00060 }
00061
00062 template <typename ITV>
00063 inline void
00064 Box<ITV>::reset_empty_up_to_date() {
00065 return status.reset_empty_up_to_date();
00066 }
00067
00068 template <typename ITV>
00069 inline
00070 Box<ITV>::Box(const Box& y, Complexity_Class)
00071 : seq(y.seq), status(y.status) {
00072 }
00073
00074 template <typename ITV>
00075 inline Box<ITV>&
00076 Box<ITV>::operator=(const Box& y) {
00077 seq = y.seq;
00078 status = y.status;
00079 return *this;
00080 }
00081
00082 template <typename ITV>
00083 inline void
00084 Box<ITV>::swap(Box& y) {
00085 Box& x = *this;
00086 std::swap(x.seq, y.seq);
00087 std::swap(x.status, y.status);
00088 }
00089
00090 template <typename ITV>
00091 inline
00092 Box<ITV>::Box(const Constraint_System& cs, Recycle_Input) {
00093
00094 Box<ITV> tmp(cs);
00095 this->swap(tmp);
00096 }
00097
00098 template <typename ITV>
00099 inline
00100 Box<ITV>::Box(const Generator_System& gs, Recycle_Input) {
00101
00102 Box<ITV> tmp(gs);
00103 this->swap(tmp);
00104 }
00105
00106 template <typename ITV>
00107 inline
00108 Box<ITV>::Box(const Congruence_System& cgs, Recycle_Input) {
00109
00110 Box<ITV> tmp(cgs);
00111 this->swap(tmp);
00112 }
00113
00114 template <typename ITV>
00115 inline memory_size_type
00116 Box<ITV>::total_memory_in_bytes() const {
00117 return sizeof(*this) + external_memory_in_bytes();
00118 }
00119
00120 template <typename ITV>
00121 inline dimension_type
00122 Box<ITV>::space_dimension() const {
00123 return seq.size();
00124 }
00125
00126 template <typename ITV>
00127 inline dimension_type
00128 Box<ITV>::max_space_dimension() {
00129
00130
00131 return Sequence().max_size() - 1;
00132 }
00133
00134 template <typename ITV>
00135 inline const ITV&
00136 Box<ITV>::operator[](const dimension_type k) const {
00137 PPL_ASSERT(k < seq.size());
00138 return seq[k];
00139 }
00140
00141 template <typename ITV>
00142 inline const ITV&
00143 Box<ITV>::get_interval(const Variable var) const {
00144 if (space_dimension() < var.space_dimension())
00145 throw_dimension_incompatible("get_interval(v)", "v", var);
00146
00147 if (is_empty()) {
00148 static ITV empty_interval(EMPTY);
00149 return empty_interval;
00150 }
00151
00152 return seq[var.id()];
00153 }
00154
00155 template <typename ITV>
00156 inline void
00157 Box<ITV>::set_interval(const Variable var, const ITV& i) {
00158 const dimension_type space_dim = space_dimension();
00159 if (space_dim < var.space_dimension())
00160 throw_dimension_incompatible("set_interval(v, i)", "v", var);
00161
00162 if (is_empty() && space_dim >= 2)
00163
00164
00165 return;
00166
00167 seq[var.id()] = i;
00168 reset_empty_up_to_date();
00169
00170 PPL_ASSERT(OK());
00171 }
00172
00173 template <typename ITV>
00174 inline bool
00175 Box<ITV>::is_empty() const {
00176 return marked_empty() || check_empty();
00177 }
00178
00179 template <typename ITV>
00180 inline bool
00181 Box<ITV>::bounds_from_above(const Linear_Expression& expr) const {
00182 return bounds(expr, true);
00183 }
00184
00185 template <typename ITV>
00186 inline bool
00187 Box<ITV>::bounds_from_below(const Linear_Expression& expr) const {
00188 return bounds(expr, false);
00189 }
00190
00191 template <typename ITV>
00192 inline bool
00193 Box<ITV>::maximize(const Linear_Expression& expr,
00194 Coefficient& sup_n, Coefficient& sup_d,
00195 bool& maximum) const {
00196 return max_min(expr, true, sup_n, sup_d, maximum);
00197 }
00198
00199 template <typename ITV>
00200 inline bool
00201 Box<ITV>::maximize(const Linear_Expression& expr,
00202 Coefficient& sup_n, Coefficient& sup_d, bool& maximum,
00203 Generator& g) const {
00204 return max_min(expr, true, sup_n, sup_d, maximum, g);
00205 }
00206
00207 template <typename ITV>
00208 inline bool
00209 Box<ITV>::minimize(const Linear_Expression& expr,
00210 Coefficient& inf_n, Coefficient& inf_d,
00211 bool& minimum) const {
00212 return max_min(expr, false, inf_n, inf_d, minimum);
00213 }
00214
00215 template <typename ITV>
00216 inline bool
00217 Box<ITV>::minimize(const Linear_Expression& expr,
00218 Coefficient& inf_n, Coefficient& inf_d, bool& minimum,
00219 Generator& g) const {
00220 return max_min(expr, false, inf_n, inf_d, minimum, g);
00221 }
00222
00223 template <typename ITV>
00224 inline bool
00225 Box<ITV>::strictly_contains(const Box& y) const {
00226 const Box& x = *this;
00227 return x.contains(y) && !y.contains(x);
00228 }
00229
00230 template <typename ITV>
00231 inline void
00232 Box<ITV>::expand_space_dimension(const Variable var,
00233 const dimension_type m) {
00234 const dimension_type space_dim = space_dimension();
00235
00236 if (var.space_dimension() > space_dim)
00237 throw_dimension_incompatible("expand_space_dimension(v, m)", "v", var);
00238
00239
00240
00241 if (m > max_space_dimension() - space_dim)
00242 throw_generic("expand_dimension(v, m)",
00243 "adding m new space dimensions exceeds "
00244 "the maximum allowed space dimension");
00245
00246
00247
00248 seq.insert(seq.end(), m, seq[var.id()]);
00249 PPL_ASSERT(OK());
00250 }
00251
00252 template <typename ITV>
00253 inline bool
00254 operator!=(const Box<ITV>& x, const Box<ITV>& y) {
00255 return !(x == y);
00256 }
00257
00258 template <typename ITV>
00259 inline bool
00260 Box<ITV>::get_lower_bound(const dimension_type k, bool& closed,
00261 Coefficient& n, Coefficient& d) const {
00262 PPL_ASSERT(k < seq.size());
00263 const ITV& seq_k = seq[k];
00264
00265 if (seq_k.lower_is_boundary_infinity())
00266 return false;
00267
00268 closed = !seq_k.lower_is_open();
00269
00270 PPL_DIRTY_TEMP0(mpq_class, lr);
00271 assign_r(lr, seq_k.lower(), ROUND_NOT_NEEDED);
00272 n = lr.get_num();
00273 d = lr.get_den();
00274
00275 return true;
00276 }
00277
00278 template <typename ITV>
00279 inline bool
00280 Box<ITV>::get_upper_bound(const dimension_type k, bool& closed,
00281 Coefficient& n, Coefficient& d) const {
00282 PPL_ASSERT(k < seq.size());
00283 const ITV& seq_k = seq[k];
00284
00285 if (seq_k.upper_is_boundary_infinity())
00286 return false;
00287
00288 closed = !seq_k.upper_is_open();
00289
00290 PPL_DIRTY_TEMP0(mpq_class, ur);
00291 assign_r(ur, seq_k.upper(), ROUND_NOT_NEEDED);
00292 n = ur.get_num();
00293 d = ur.get_den();
00294
00295 return true;
00296 }
00297
00298 template <typename ITV>
00299 inline void
00300 Box<ITV>::add_constraint(const Constraint& c) {
00301 const dimension_type c_space_dim = c.space_dimension();
00302
00303 if (c_space_dim > space_dimension())
00304 throw_dimension_incompatible("add_constraint(c)", c);
00305
00306 add_constraint_no_check(c);
00307 }
00308
00309 template <typename ITV>
00310 inline void
00311 Box<ITV>::add_constraints(const Constraint_System& cs) {
00312
00313 if (cs.space_dimension() > space_dimension())
00314 throw_dimension_incompatible("add_constraints(cs)", cs);
00315
00316 add_constraints_no_check(cs);
00317 }
00318
00319 template <typename T>
00320 inline void
00321 Box<T>::add_recycled_constraints(Constraint_System& cs) {
00322 add_constraints(cs);
00323 }
00324
00325 template <typename ITV>
00326 inline void
00327 Box<ITV>::add_congruence(const Congruence& cg) {
00328 const dimension_type cg_space_dim = cg.space_dimension();
00329
00330 if (cg_space_dim > space_dimension())
00331 throw_dimension_incompatible("add_congruence(cg)", cg);
00332
00333 add_congruence_no_check(cg);
00334 }
00335
00336 template <typename ITV>
00337 inline void
00338 Box<ITV>::add_congruences(const Congruence_System& cgs) {
00339 if (cgs.space_dimension() > space_dimension())
00340 throw_dimension_incompatible("add_congruences(cgs)", cgs);
00341 add_congruences_no_check(cgs);
00342 }
00343
00344 template <typename T>
00345 inline void
00346 Box<T>::add_recycled_congruences(Congruence_System& cgs) {
00347 add_congruences(cgs);
00348 }
00349
00350 template <typename T>
00351 inline bool
00352 Box<T>::can_recycle_constraint_systems() {
00353 return false;
00354 }
00355
00356 template <typename T>
00357 inline bool
00358 Box<T>::can_recycle_congruence_systems() {
00359 return false;
00360 }
00361
00362 template <typename T>
00363 inline void
00364 Box<T>::widening_assign(const Box& y, unsigned* tp) {
00365 CC76_widening_assign(y, tp);
00366 }
00367
00368 template <typename ITV>
00369 inline Congruence_System
00370 Box<ITV>::minimized_congruences() const {
00371
00372 return congruences();
00373 }
00374
00375 template <typename ITV>
00376 inline I_Result
00377 Box<ITV>::refine_interval_no_check(ITV& itv,
00378 const Constraint::Type type,
00379 Coefficient_traits::const_reference num,
00380 Coefficient_traits::const_reference den) {
00381 PPL_ASSERT(den != 0);
00382
00383
00384
00385
00386
00387 PPL_DIRTY_TEMP0(mpq_class, q);
00388 assign_r(q.get_num(), num, ROUND_NOT_NEEDED);
00389 assign_r(q.get_den(), den, ROUND_NOT_NEEDED);
00390 q.canonicalize();
00391
00392 q = -q;
00393
00394 I_Result res;
00395 switch (type) {
00396 case Constraint::EQUALITY:
00397 res = itv.add_constraint(i_constraint(EQUAL, q));
00398 break;
00399 case Constraint::NONSTRICT_INEQUALITY:
00400 res = itv.add_constraint(i_constraint(den > 0
00401 ? GREATER_OR_EQUAL
00402 : LESS_OR_EQUAL, q));
00403 break;
00404 case Constraint::STRICT_INEQUALITY:
00405 res = itv.add_constraint(i_constraint(den > 0
00406 ? GREATER_THAN
00407 : LESS_THAN, q));
00408 break;
00409 default:
00410
00411 PPL_ASSERT(false);
00412 res = I_ANY;
00413 }
00414 PPL_ASSERT(itv.OK());
00415 return res;
00416 }
00417
00418 template <typename ITV>
00419 inline void
00420 Box<ITV>
00421 ::add_interval_constraint_no_check(const dimension_type var_id,
00422 const Constraint::Type type,
00423 Coefficient_traits::const_reference num,
00424 Coefficient_traits::const_reference den) {
00425 PPL_ASSERT(!marked_empty());
00426 PPL_ASSERT(var_id < space_dimension());
00427 PPL_ASSERT(den != 0);
00428 refine_interval_no_check(seq[var_id], type, num, den);
00429
00430
00431
00432 reset_empty_up_to_date();
00433 PPL_ASSERT(OK());
00434 }
00435
00436 template <typename ITV>
00437 inline void
00438 Box<ITV>::refine_with_constraint(const Constraint& c) {
00439 const dimension_type c_space_dim = c.space_dimension();
00440
00441 if (c_space_dim > space_dimension())
00442 throw_dimension_incompatible("refine_with_constraint(c)", c);
00443
00444
00445 if (marked_empty())
00446 return;
00447
00448 refine_no_check(c);
00449 }
00450
00451 template <typename ITV>
00452 inline void
00453 Box<ITV>::refine_with_constraints(const Constraint_System& cs) {
00454
00455 if (cs.space_dimension() > space_dimension())
00456 throw_dimension_incompatible("refine_with_constraints(cs)", cs);
00457
00458
00459 if (marked_empty())
00460 return;
00461
00462 refine_no_check(cs);
00463 }
00464
00465 template <typename ITV>
00466 inline void
00467 Box<ITV>::refine_with_congruence(const Congruence& cg) {
00468 const dimension_type cg_space_dim = cg.space_dimension();
00469
00470 if (cg_space_dim > space_dimension())
00471 throw_dimension_incompatible("refine_with_congruence(cg)", cg);
00472
00473
00474 if (marked_empty())
00475 return;
00476
00477 refine_no_check(cg);
00478 }
00479
00480 template <typename ITV>
00481 inline void
00482 Box<ITV>::refine_with_congruences(const Congruence_System& cgs) {
00483
00484 if (cgs.space_dimension() > space_dimension())
00485 throw_dimension_incompatible("refine_with_congruences(cgs)", cgs);
00486
00487
00488 if (marked_empty())
00489 return;
00490
00491 refine_no_check(cgs);
00492 }
00493
00494 template <typename ITV>
00495 inline void
00496 Box<ITV>::propagate_constraint(const Constraint& c) {
00497 const dimension_type c_space_dim = c.space_dimension();
00498
00499 if (c_space_dim > space_dimension())
00500 throw_dimension_incompatible("propagate_constraint(c)", c);
00501
00502
00503 if (marked_empty())
00504 return;
00505
00506 propagate_constraint_no_check(c);
00507 }
00508
00509 template <typename ITV>
00510 inline void
00511 Box<ITV>::propagate_constraints(const Constraint_System& cs,
00512 const dimension_type max_iterations) {
00513
00514 if (cs.space_dimension() > space_dimension())
00515 throw_dimension_incompatible("propagate_constraints(cs)", cs);
00516
00517
00518 if (marked_empty())
00519 return;
00520
00521 propagate_constraints_no_check(cs, max_iterations);
00522 }
00523
00524 template <typename ITV>
00525 inline void
00526 Box<ITV>::unconstrain(const Variable var) {
00527 const dimension_type var_id = var.id();
00528
00529 if (space_dimension() < var_id + 1)
00530 throw_dimension_incompatible("unconstrain(var)", var_id + 1);
00531
00532
00533 if (marked_empty())
00534 return;
00535
00536
00537
00538 ITV& seq_var = seq[var_id];
00539 if (seq_var.is_empty())
00540 set_empty();
00541 else
00542 seq_var.assign(UNIVERSE);
00543
00544 PPL_ASSERT(OK());
00545 }
00546
00548 template <typename Temp, typename To, typename ITV>
00549 inline bool
00550 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00551 const Box<ITV>& x,
00552 const Box<ITV>& y,
00553 const Rounding_Dir dir,
00554 Temp& tmp0,
00555 Temp& tmp1,
00556 Temp& tmp2) {
00557 return l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >
00558 (r, x, y, dir, tmp0, tmp1, tmp2);
00559 }
00560
00562 template <typename Temp, typename To, typename ITV>
00563 inline bool
00564 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00565 const Box<ITV>& x,
00566 const Box<ITV>& y,
00567 const Rounding_Dir dir) {
00568 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00569 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00570 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00571 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00572 return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00573 }
00574
00576 template <typename To, typename ITV>
00577 inline bool
00578 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00579 const Box<ITV>& x,
00580 const Box<ITV>& y,
00581 const Rounding_Dir dir) {
00582
00583
00584 return Parma_Polyhedra_Library
00585 ::rectilinear_distance_assign<To, To, ITV>(r, x, y, dir);
00586 }
00587
00589 template <typename Temp, typename To, typename ITV>
00590 inline bool
00591 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00592 const Box<ITV>& x,
00593 const Box<ITV>& y,
00594 const Rounding_Dir dir,
00595 Temp& tmp0,
00596 Temp& tmp1,
00597 Temp& tmp2) {
00598 return l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >
00599 (r, x, y, dir, tmp0, tmp1, tmp2);
00600 }
00601
00603 template <typename Temp, typename To, typename ITV>
00604 inline bool
00605 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00606 const Box<ITV>& x,
00607 const Box<ITV>& y,
00608 const Rounding_Dir dir) {
00609 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00610 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00611 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00612 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00613 return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00614 }
00615
00617 template <typename To, typename ITV>
00618 inline bool
00619 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00620 const Box<ITV>& x,
00621 const Box<ITV>& y,
00622 const Rounding_Dir dir) {
00623
00624
00625 return Parma_Polyhedra_Library
00626 ::euclidean_distance_assign<To, To, ITV>(r, x, y, dir);
00627 }
00628
00630 template <typename Temp, typename To, typename ITV>
00631 inline bool
00632 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00633 const Box<ITV>& x,
00634 const Box<ITV>& y,
00635 const Rounding_Dir dir,
00636 Temp& tmp0,
00637 Temp& tmp1,
00638 Temp& tmp2) {
00639 return l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >
00640 (r, x, y, dir, tmp0, tmp1, tmp2);
00641 }
00642
00644 template <typename Temp, typename To, typename ITV>
00645 inline bool
00646 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00647 const Box<ITV>& x,
00648 const Box<ITV>& y,
00649 const Rounding_Dir dir) {
00650 typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
00651 PPL_DIRTY_TEMP(Checked_Temp, tmp0);
00652 PPL_DIRTY_TEMP(Checked_Temp, tmp1);
00653 PPL_DIRTY_TEMP(Checked_Temp, tmp2);
00654 return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
00655 }
00656
00658 template <typename To, typename ITV>
00659 inline bool
00660 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00661 const Box<ITV>& x,
00662 const Box<ITV>& y,
00663 const Rounding_Dir dir) {
00664
00665
00666 return Parma_Polyhedra_Library
00667 ::l_infinity_distance_assign<To, To, ITV>(r, x, y, dir);
00668 }
00669
00670 }
00671
00672 #endif // !defined(PPL_Box_inlines_hh)