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_Interval_inlines_hh
00025 #define PPL_Interval_inlines_hh 1
00026
00027 namespace Parma_Polyhedra_Library {
00028
00029 template <typename From>
00030 typename Enable_If<Is_Interval<From>::value, I_Result>::type
00031 neg_assign(From& x) {
00032
00033 From y;
00034 typename Enable_If<Is_Interval<From>::value, I_Result>::type res =
00035 y.neg_assign(x);
00036 x = y;
00037 return res;
00038 }
00039
00040 template <typename Boundary, typename Info>
00041 inline memory_size_type
00042 Interval<Boundary, Info>::external_memory_in_bytes() const {
00043 return Parma_Polyhedra_Library::external_memory_in_bytes(lower())
00044 + Parma_Polyhedra_Library::external_memory_in_bytes(upper());
00045 }
00046
00047 template <typename Boundary, typename Info>
00048 inline memory_size_type
00049 Interval<Boundary, Info>::total_memory_in_bytes() const {
00050 return sizeof(*this) + external_memory_in_bytes();
00051 }
00052
00053 template <typename Boundary, typename Info>
00054 inline void
00055 Interval<Boundary, Info>::swap(Interval<Boundary, Info>& y) {
00056 std::swap(lower(), y.lower());
00057 std::swap(upper(), y.upper());
00058 std::swap(info(), y.info());
00059 }
00060
00061 template <typename Boundary, typename Info>
00062 inline bool
00063 f_is_empty(const Interval<Boundary, Info>& x) {
00064 return x.is_empty();
00065 }
00066 template <typename Boundary, typename Info>
00067 inline bool
00068 f_is_singleton(const Interval<Boundary, Info>& x) {
00069 return x.is_singleton();
00070 }
00071 template <typename Boundary, typename Info>
00072 inline int
00073 is_infinity(const Interval<Boundary, Info>& x) {
00074 return x.is_infinity();
00075 }
00076
00077 namespace Interval_NS {
00078
00079 template <typename Boundary, typename Info>
00080 inline const Boundary&
00081 f_lower(const Interval<Boundary, Info>& x) {
00082 return x.lower();
00083 }
00084 template <typename Boundary, typename Info>
00085 inline const Boundary&
00086 f_upper(const Interval<Boundary, Info>& x) {
00087 return x.upper();
00088 }
00089 template <typename Boundary, typename Info>
00090 inline const Info&
00091 f_info(const Interval<Boundary, Info>& x) {
00092 return x.info();
00093 }
00094
00095 struct Scalar_As_Interval_Policy {
00096 const_bool_nodef(may_be_empty, true);
00097 const_bool_nodef(may_contain_infinity, true);
00098 const_bool_nodef(check_inexact, false);
00099 };
00100
00101 typedef Interval_Restriction_None<Interval_Info_Null<Scalar_As_Interval_Policy> > Scalar_As_Interval_Info;
00102
00103 const Scalar_As_Interval_Info SCALAR_INFO;
00104
00105 typedef Interval_Restriction_None<Interval_Info_Null_Open<Scalar_As_Interval_Policy> > Scalar_As_Interval_Info_Open;
00106
00107 template <typename T>
00108 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
00109 f_lower(const T& x) {
00110 return x;
00111 }
00112 template <typename T>
00113 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
00114 f_upper(const T& x) {
00115 return x;
00116 }
00117 template <typename T>
00118 inline typename Enable_If<Is_Singleton<T>::value, const Scalar_As_Interval_Info&>::type
00119 f_info(const T&) {
00120 return SCALAR_INFO;
00121 }
00122 template <typename T>
00123 inline typename Enable_If<Is_Singleton<T>::value, Scalar_As_Interval_Info_Open>::type
00124 f_info(const T&, bool open) {
00125 return Scalar_As_Interval_Info_Open(open);
00126 }
00127
00128 template <typename T>
00129 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
00130 f_is_empty(const T& x) {
00131 return is_not_a_number(x);
00132 }
00133
00134 template <typename T>
00135 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
00136 f_is_singleton(const T& x) {
00137 return !f_is_empty(x);
00138 }
00139
00140 }
00141
00142 template <typename T>
00143 inline typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, bool>::type
00144 is_singleton_integer(const T& x) {
00145 return is_singleton(x) && is_integer(f_lower(x));
00146 }
00147
00148 template <typename T>
00149 inline typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, bool>::type
00150 check_empty_arg(const T& x) {
00151 if (f_info(x).may_be_empty)
00152 return f_is_empty(x);
00153 else {
00154 PPL_ASSERT(!f_is_empty(x));
00155 return false;
00156 }
00157 }
00158
00159 template <typename T1, typename T2>
00160 inline typename Enable_If<((Is_Singleton<T1>::value || Is_Interval<T1>::value)
00161 && (Is_Singleton<T2>::value || Is_Interval<T2>::value)
00162 && (Is_Interval<T1>::value || Is_Interval<T2>::value)),
00163 bool>::type
00164 operator==(const T1& x, const T2& y) {
00165 PPL_ASSERT(f_OK(x));
00166 PPL_ASSERT(f_OK(y));
00167 if (check_empty_arg(x))
00168 return check_empty_arg(y);
00169 else if (check_empty_arg(y))
00170 return false;
00171
00172
00173 return eq_restriction(f_info(x), f_info(y))
00174 && eq(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y))
00175 && eq(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
00176 }
00177
00178 template <typename T1, typename T2>
00179 inline typename Enable_If<((Is_Singleton<T1>::value || Is_Interval<T1>::value)
00180 && (Is_Singleton<T2>::value || Is_Interval<T2>::value)
00181 && (Is_Interval<T1>::value || Is_Interval<T2>::value)),
00182 bool>::type
00183 operator!=(const T1& x, const T2& y) {
00184 return !(x == y);
00185 }
00186
00187 template <typename Boundary, typename Info>
00188 template <typename T>
00189 inline typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, bool>::type
00190 Interval<Boundary, Info>::contains(const T& y) const {
00191 PPL_ASSERT(OK());
00192 PPL_ASSERT(f_OK(y));
00193 if (check_empty_arg(y))
00194 return true;
00195 if (check_empty_arg(*this))
00196 return false;
00197
00198
00199 if (!contains_restriction(info(), f_info(y)))
00200 return false;
00201 return le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
00202 && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y));
00203 }
00204
00205 template <typename Boundary, typename Info>
00206 template <typename T>
00207 inline typename Enable_If<Is_Singleton<T>::value || Is_Interval<T>::value, bool>::type
00208 Interval<Boundary, Info>::strictly_contains(const T& y) const {
00209 PPL_ASSERT(OK());
00210 PPL_ASSERT(f_OK(y));
00211 if (check_empty_arg(y))
00212 return !check_empty_arg(*this);
00213 if (check_empty_arg(*this))
00214 return false;
00215
00216
00217 if (!contains_restriction(info(), f_info(y)))
00218 return false;
00219 else if (!eq_restriction(info(), f_info(y)))
00220 return le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
00221 && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y));
00222 return (lt(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
00223 && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)))
00224 || (le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
00225 && gt(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)));
00226 }
00227
00228 template <typename Boundary, typename Info>
00229 template <typename T>
00230 inline typename Enable_If<Is_Singleton<T>::value
00231 || Is_Interval<T>::value, bool>::type
00232 Interval<Boundary, Info>::is_disjoint_from(const T& y) const {
00233 PPL_ASSERT(OK());
00234 PPL_ASSERT(f_OK(y));
00235 if (check_empty_arg(*this) || check_empty_arg(y))
00236 return true;
00237
00238
00239
00240 return gt(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y))
00241 || lt(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
00242 }
00243
00244 template <typename To_Boundary, typename To_Info>
00245 template <typename From>
00246 inline typename Enable_If<Is_Singleton<From>::value
00247 || Is_Interval<From>::value, I_Result>::type
00248 Interval<To_Boundary, To_Info>::assign(const From& x) {
00249 PPL_ASSERT(f_OK(x));
00250 if (check_empty_arg(x))
00251 return assign(EMPTY);
00252 PPL_DIRTY_TEMP(To_Info, to_info);
00253 to_info.clear();
00254 if (!assign_restriction(to_info, x))
00255 return assign(EMPTY);
00256 Result rl = Boundary_NS::assign(LOWER, lower(), to_info,
00257 LOWER, f_lower(x), f_info(x));
00258 Result ru = Boundary_NS::assign(UPPER, upper(), to_info,
00259 UPPER, f_upper(x), f_info(x));
00260 assign_or_swap(info(), to_info);
00261 PPL_ASSERT(OK());
00262 return combine(rl, ru);
00263 }
00264
00265 template <typename To_Boundary, typename To_Info>
00266 template <typename From>
00267 inline typename Enable_If<Is_Singleton<From>::value
00268 || Is_Interval<From>::value, I_Result>::type
00269 Interval<To_Boundary, To_Info>::join_assign(const From& x) {
00270 PPL_ASSERT(f_OK(x));
00271 if (check_empty_arg(*this))
00272 return assign(x);
00273 if (check_empty_arg(x))
00274 return combine(V_EQ, V_EQ);
00275 if (!join_restriction(info(), *this, x))
00276 return assign(EMPTY);
00277 Result rl, ru;
00278 rl = min_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
00279 ru = max_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
00280 PPL_ASSERT(OK());
00281 return combine(rl, ru);
00282 }
00283
00284 template <typename To_Boundary, typename To_Info>
00285 template <typename From1, typename From2>
00286 inline typename Enable_If<((Is_Singleton<From1>::value
00287 || Is_Interval<From1>::value)
00288 && (Is_Singleton<From2>::value
00289 || Is_Interval<From2>::value)), I_Result>::type
00290 Interval<To_Boundary, To_Info>::join_assign(const From1& x, const From2& y) {
00291 PPL_ASSERT(f_OK(x));
00292 PPL_ASSERT(f_OK(y));
00293 if (check_empty_arg(x))
00294 return assign(y);
00295 if (check_empty_arg(y))
00296 return assign(x);
00297 PPL_DIRTY_TEMP(To_Info, to_info);
00298 to_info.clear();
00299 if (!join_restriction(to_info, x, y))
00300 return assign(EMPTY);
00301 Result rl, ru;
00302 rl = min_assign(LOWER, lower(), to_info,
00303 LOWER, f_lower(x), f_info(x),
00304 LOWER, f_lower(y), f_info(y));
00305 ru = max_assign(UPPER, upper(), to_info,
00306 UPPER, f_upper(x), f_info(x),
00307 UPPER, f_upper(y), f_info(y));
00308 assign_or_swap(info(), to_info);
00309 PPL_ASSERT(OK());
00310 return combine(rl, ru);
00311 }
00312
00313 template <typename Boundary, typename Info>
00314 template <typename Type>
00315 inline typename Enable_If<Is_Singleton<Type>::value
00316 || Is_Interval<Type>::value, bool>::type
00317 Interval<Boundary, Info>::can_be_exactly_joined_to(const Type& x) const {
00318
00319
00320 if (!eq_restriction(info(), f_info(x)))
00321 return false;
00322 PPL_DIRTY_TEMP(Boundary, b);
00323 if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
00324 b = lower();
00325 return info().restrict(round_dir_check(LOWER, true), b, V_LT) == V_EQ
00326 && eq(LOWER, b, info(), UPPER, f_upper(x), f_info(x));
00327 }
00328 else if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
00329 b = upper();
00330 return info().restrict(round_dir_check(UPPER, true), b, V_GT) == V_EQ
00331 && eq(UPPER, b, info(), LOWER, f_lower(x), f_info(x));
00332 }
00333 return true;
00334 }
00335
00336
00337 template <typename To_Boundary, typename To_Info>
00338 template <typename From>
00339 inline typename Enable_If<Is_Singleton<From>::value
00340 || Is_Interval<From>::value, I_Result>::type
00341 Interval<To_Boundary, To_Info>::intersect_assign(const From& x) {
00342 PPL_ASSERT(f_OK(x));
00343 if (!intersect_restriction(info(), *this, x))
00344 return assign(EMPTY);
00345 Result rl, ru;
00346 rl = max_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
00347 ru = min_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
00348 PPL_ASSERT(OK());
00349 return I_ANY;
00350 }
00351
00352 template <typename To_Boundary, typename To_Info>
00353 template <typename From1, typename From2>
00354 inline typename Enable_If<((Is_Singleton<From1>::value
00355 || Is_Interval<From1>::value)
00356 && (Is_Singleton<From2>::value
00357 || Is_Interval<From2>::value)), I_Result>::type
00358 Interval<To_Boundary, To_Info>::intersect_assign(const From1& x,
00359 const From2& y) {
00360 PPL_ASSERT(f_OK(x));
00361 PPL_ASSERT(f_OK(y));
00362 PPL_DIRTY_TEMP(To_Info, to_info);
00363 to_info.clear();
00364 if (!intersect_restriction(to_info, x, y))
00365 return assign(EMPTY);
00366 Result rl, ru;
00367 rl = max_assign(LOWER, lower(), to_info,
00368 LOWER, f_lower(x), f_info(x),
00369 LOWER, f_lower(y), f_info(y));
00370 ru = min_assign(UPPER, upper(), to_info,
00371 UPPER, f_upper(x), f_info(x),
00372 UPPER, f_upper(y), f_info(y));
00373 assign_or_swap(info(), to_info);
00374 PPL_ASSERT(OK());
00375 return I_NOT_EMPTY;
00376 }
00377
00378 template <typename To_Boundary, typename To_Info>
00379 template <typename From>
00380 inline typename Enable_If<Is_Singleton<From>::value
00381 || Is_Interval<From>::value, I_Result>::type
00382 Interval<To_Boundary, To_Info>::difference_assign(const From& x) {
00383 PPL_ASSERT(f_OK(x));
00384
00385 if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))
00386 ||
00387 gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x)))
00388 return combine(V_EQ, V_EQ);
00389 bool nl = ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
00390 bool nu = le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
00391 Result rl = V_EQ, ru = V_EQ;
00392 if (nl) {
00393 if (nu)
00394 return assign(EMPTY);
00395 else {
00396 info().clear_boundary_properties(LOWER);
00397 rl = complement(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x));
00398 }
00399 }
00400 else if (nu) {
00401 info().clear_boundary_properties(UPPER);
00402 ru = complement(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x));
00403 }
00404 PPL_ASSERT(OK());
00405 return combine(rl, ru);
00406 }
00407
00408 template <typename To_Boundary, typename To_Info>
00409 template <typename From1, typename From2>
00410 inline typename Enable_If<((Is_Singleton<From1>::value
00411 || Is_Interval<From1>::value)
00412 && (Is_Singleton<From2>::value
00413 || Is_Interval<From2>::value)), I_Result>::type
00414 Interval<To_Boundary, To_Info>::difference_assign(const From1& x,
00415 const From2& y) {
00416 PPL_ASSERT(f_OK(x));
00417 PPL_ASSERT(f_OK(y));
00418 PPL_DIRTY_TEMP(To_Info, to_info);
00419 to_info.clear();
00420
00421 if (lt(UPPER, f_upper(x), f_info(x), LOWER, f_lower(y), f_info(y))
00422 ||
00423 gt(LOWER, f_lower(x), f_info(x), UPPER, f_upper(y), f_info(y)))
00424 return assign(x);
00425 bool nl = ge(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y));
00426 bool nu = le(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
00427 Result rl = V_EQ, ru = V_EQ;
00428 if (nl) {
00429 if (nu)
00430 return assign(EMPTY);
00431 else {
00432 rl = complement(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y));
00433 ru = Boundary_NS::assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
00434 }
00435 }
00436 else if (nu) {
00437 ru = complement(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
00438 rl = Boundary_NS::assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
00439 }
00440 assign_or_swap(info(), to_info);
00441 PPL_ASSERT(OK());
00442 return combine(rl, ru);
00443 }
00444
00445 template <typename To_Boundary, typename To_Info>
00446 template <typename From>
00447 inline typename Enable_If<Is_Singleton<From>::value
00448 || Is_Interval<From>::value, I_Result>::type
00449 Interval<To_Boundary, To_Info>
00450 ::refine_existential(Relation_Symbol rel, const From& x) {
00451 PPL_ASSERT(OK());
00452 PPL_ASSERT(f_OK(x));
00453 if (check_empty_arg(x))
00454 return assign(EMPTY);
00455 switch (rel) {
00456 case LESS_THAN:
00457 {
00458 if (lt(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x)))
00459 return combine(V_EQ, V_EQ);
00460 info().clear_boundary_properties(UPPER);
00461 Boundary_NS::assign(UPPER, upper(), info(),
00462 UPPER, f_upper(x), f_info(x), true);
00463 normalize();
00464 return I_ANY;
00465 }
00466 case LESS_OR_EQUAL:
00467 {
00468 if (le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x)))
00469 return combine(V_EQ, V_EQ);
00470 info().clear_boundary_properties(UPPER);
00471 Boundary_NS::assign(UPPER, upper(), info(),
00472 UPPER, f_upper(x), f_info(x));
00473 normalize();
00474 return I_ANY;
00475 }
00476 case GREATER_THAN:
00477 {
00478 if (gt(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x)))
00479 return combine(V_EQ, V_EQ);
00480 info().clear_boundary_properties(LOWER);
00481 Boundary_NS::assign(LOWER, lower(), info(),
00482 LOWER, f_lower(x), f_info(x), true);
00483 normalize();
00484 return I_ANY;
00485 }
00486 case GREATER_OR_EQUAL:
00487 {
00488 if (ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x)))
00489 return combine(V_EQ, V_EQ);
00490 info().clear_boundary_properties(LOWER);
00491 Boundary_NS::assign(LOWER, lower(), info(),
00492 LOWER, f_lower(x), f_info(x));
00493 normalize();
00494 return I_ANY;
00495 }
00496 case EQUAL:
00497 return intersect_assign(x);
00498 case NOT_EQUAL:
00499 {
00500 if (!f_is_singleton(x))
00501 return combine(V_EQ, V_EQ);
00502 if (check_empty_arg(*this))
00503 return I_EMPTY;
00504 if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x)))
00505 remove_inf();
00506 if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x)))
00507 remove_sup();
00508 normalize();
00509 return I_ANY;
00510 }
00511 default:
00512 PPL_ASSERT(false);
00513 return I_EMPTY;
00514 }
00515 }
00516
00517 template <typename To_Boundary, typename To_Info>
00518 template <typename From>
00519 inline typename Enable_If<Is_Singleton<From>::value
00520 || Is_Interval<From>::value, I_Result>::type
00521 Interval<To_Boundary, To_Info>::refine_universal(Relation_Symbol rel,
00522 const From& x) {
00523 PPL_ASSERT(OK());
00524 PPL_ASSERT(f_OK(x));
00525 if (check_empty_arg(x))
00526 return combine(V_EQ, V_EQ);
00527 switch (rel) {
00528 case LESS_THAN:
00529 {
00530 if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x)))
00531 return combine(V_EQ, V_EQ);
00532 info().clear_boundary_properties(UPPER);
00533 Result ru = Boundary_NS::assign(UPPER, upper(), info(),
00534 LOWER, f_lower(x), SCALAR_INFO, !is_open(LOWER, f_lower(x), f_info(x)));
00535 normalize();
00536 return I_ANY;
00537 }
00538 case LESS_OR_EQUAL:
00539 {
00540 if (le(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x)))
00541 return combine(V_EQ, V_EQ);
00542 info().clear_boundary_properties(UPPER);
00543 Result ru = Boundary_NS::assign(UPPER, upper(), info(),
00544 LOWER, f_lower(x), SCALAR_INFO);
00545 normalize();
00546 return I_ANY;
00547 }
00548 case GREATER_THAN:
00549 {
00550 if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x)))
00551 return combine(V_EQ, V_EQ);
00552 info().clear_boundary_properties(LOWER);
00553 Result rl = Boundary_NS::assign(LOWER, lower(), info(),
00554 UPPER, f_upper(x), SCALAR_INFO, !is_open(UPPER, f_upper(x), f_info(x)));
00555 normalize();
00556 return I_ANY;
00557 }
00558 case GREATER_OR_EQUAL:
00559 {
00560 if (ge(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x)))
00561 return combine(V_EQ, V_EQ);
00562 info().clear_boundary_properties(LOWER);
00563 Result rl = Boundary_NS::assign(LOWER, lower(), info(),
00564 UPPER, f_upper(x), SCALAR_INFO);
00565 normalize();
00566 return I_ANY;
00567 }
00568 case EQUAL:
00569 if (!f_is_singleton(x))
00570 return assign(EMPTY);
00571 return intersect_assign(x);
00572 case NOT_EQUAL:
00573 {
00574 if (check_empty_arg(*this))
00575 return I_EMPTY;
00576 if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x)))
00577 remove_inf();
00578 if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x)))
00579 remove_sup();
00580 normalize();
00581 return I_ANY;
00582 }
00583 default:
00584 PPL_ASSERT(false);
00585 return I_EMPTY;
00586 }
00587 }
00588
00589 template <typename To_Boundary, typename To_Info>
00590 template <typename From>
00591 inline typename Enable_If<Is_Singleton<From>::value
00592 || Is_Interval<From>::value, I_Result>::type
00593 Interval<To_Boundary, To_Info>::neg_assign(const From& x) {
00594 PPL_ASSERT(f_OK(x));
00595 if (check_empty_arg(x))
00596 return assign(EMPTY);
00597 PPL_DIRTY_TEMP(To_Info, to_info);
00598 to_info.clear();
00599 if (!neg_restriction(to_info, x))
00600 return assign(EMPTY);
00601 Result rl, ru;
00602 PPL_DIRTY_TEMP(To_Boundary, to_lower);
00603 rl = Boundary_NS::neg_assign(LOWER, to_lower, to_info, UPPER, f_upper(x), f_info(x));
00604 ru = Boundary_NS::neg_assign(UPPER, upper(), to_info, LOWER, f_lower(x), f_info(x));
00605 assign_or_swap(lower(), to_lower);
00606 assign_or_swap(info(), to_info);
00607 PPL_ASSERT(OK());
00608 return combine(rl, ru);
00609 }
00610
00611 template <typename To_Boundary, typename To_Info>
00612 template <typename From1, typename From2>
00613 inline typename Enable_If<((Is_Singleton<From1>::value
00614 || Is_Interval<From1>::value)
00615 && (Is_Singleton<From2>::value
00616 || Is_Interval<From2>::value)), I_Result>::type
00617 Interval<To_Boundary, To_Info>::add_assign(const From1& x, const From2& y) {
00618 PPL_ASSERT(f_OK(x));
00619 PPL_ASSERT(f_OK(y));
00620 if (check_empty_arg(x) || check_empty_arg(y))
00621 return assign(EMPTY);
00622 int inf = Parma_Polyhedra_Library::is_infinity(x);
00623 if (inf) {
00624 if (Parma_Polyhedra_Library::is_infinity(y) == -inf)
00625 return assign(EMPTY);
00626 }
00627 else
00628 inf = Parma_Polyhedra_Library::is_infinity(y);
00629 if (inf < 0)
00630 return assign(MINUS_INFINITY);
00631 else if (inf > 0)
00632 return assign(PLUS_INFINITY);
00633 PPL_DIRTY_TEMP(To_Info, to_info);
00634 to_info.clear();
00635 if (!add_restriction(to_info, x, y))
00636 return assign(EMPTY);
00637 Result rl = Boundary_NS::add_assign(LOWER, lower(), to_info,
00638 LOWER, f_lower(x), f_info(x),
00639 LOWER, f_lower(y), f_info(y));
00640 Result ru = Boundary_NS::add_assign(UPPER, upper(), to_info,
00641 UPPER, f_upper(x), f_info(x),
00642 UPPER, f_upper(y), f_info(y));
00643 assign_or_swap(info(), to_info);
00644 PPL_ASSERT(OK());
00645 return combine(rl, ru);
00646 }
00647
00648 template <typename To_Boundary, typename To_Info>
00649 template <typename From1, typename From2>
00650 inline typename Enable_If<((Is_Singleton<From1>::value
00651 || Is_Interval<From1>::value)
00652 && (Is_Singleton<From2>::value
00653 || Is_Interval<From2>::value)), I_Result>::type
00654 Interval<To_Boundary, To_Info>::sub_assign(const From1& x, const From2& y) {
00655 PPL_ASSERT(f_OK(x));
00656 PPL_ASSERT(f_OK(y));
00657 if (check_empty_arg(x) || check_empty_arg(y))
00658 return assign(EMPTY);
00659 int inf = Parma_Polyhedra_Library::is_infinity(x);
00660 if (inf) {
00661 if (Parma_Polyhedra_Library::is_infinity(y) == inf)
00662 return assign(EMPTY);
00663 }
00664 else
00665 inf = -Parma_Polyhedra_Library::is_infinity(y);
00666 if (inf < 0)
00667 return assign(MINUS_INFINITY);
00668 else if (inf > 0)
00669 return assign(PLUS_INFINITY);
00670
00671 PPL_DIRTY_TEMP(To_Info, to_info);
00672 to_info.clear();
00673 if (!sub_restriction(to_info, x, y))
00674 return assign(EMPTY);
00675 Result rl, ru;
00676 PPL_DIRTY_TEMP(To_Boundary, to_lower);
00677 rl = Boundary_NS::sub_assign(LOWER, to_lower, to_info,
00678 LOWER, f_lower(x), f_info(x),
00679 UPPER, f_upper(y), f_info(y));
00680 ru = Boundary_NS::sub_assign(UPPER, upper(), to_info,
00681 UPPER, f_upper(x), f_info(x),
00682 LOWER, f_lower(y), f_info(y));
00683 assign_or_swap(lower(), to_lower);
00684 assign_or_swap(info(), to_info);
00685 PPL_ASSERT(OK());
00686 return combine(rl, ru);
00687 }
00688
00701 template <typename To_Boundary, typename To_Info>
00702 template <typename From1, typename From2>
00703 inline typename Enable_If<((Is_Singleton<From1>::value
00704 || Is_Interval<From1>::value)
00705 && (Is_Singleton<From2>::value
00706 || Is_Interval<From2>::value)), I_Result>::type
00707 Interval<To_Boundary, To_Info>::mul_assign(const From1& x, const From2& y) {
00708 PPL_ASSERT(f_OK(x));
00709 PPL_ASSERT(f_OK(y));
00710 if (check_empty_arg(x) || check_empty_arg(y))
00711 return assign(EMPTY);
00712 int xls = sgn_b(LOWER, f_lower(x), f_info(x));
00713 int xus = xls > 0 ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
00714 int yls = sgn_b(LOWER, f_lower(y), f_info(y));
00715 int yus = yls > 0 ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
00716 int inf = Parma_Polyhedra_Library::is_infinity(x);
00717 int ls, us;
00718 if (inf) {
00719 ls = yls;
00720 us = yus;
00721 goto inf;
00722 }
00723 else {
00724 inf = Parma_Polyhedra_Library::is_infinity(y);
00725 if (inf) {
00726 ls = xls;
00727 us = xus;
00728 inf:
00729 if (ls == 0 && us == 0)
00730 return assign(EMPTY);
00731 if (ls == -us)
00732 return set_infinities();
00733 if (ls < 0 || us < 0)
00734 inf = -inf;
00735 if (inf < 0)
00736 return assign(MINUS_INFINITY);
00737 else
00738 return assign(PLUS_INFINITY);
00739 }
00740 }
00741
00742 PPL_DIRTY_TEMP(To_Info, to_info);
00743 to_info.clear();
00744 if (!mul_restriction(to_info, x, y))
00745 return assign(EMPTY);
00746 Result rl, ru;
00747 PPL_DIRTY_TEMP(To_Boundary, to_lower);
00748
00749 if (xls >= 0) {
00750 if (yls >= 0) {
00751
00752 rl = mul_assign_z(LOWER, to_lower, to_info,
00753 LOWER, f_lower(x), f_info(x), xls,
00754 LOWER, f_lower(y), f_info(y), yls);
00755 ru = mul_assign_z(UPPER, upper(), to_info,
00756 UPPER, f_upper(x), f_info(x), xus,
00757 UPPER, f_upper(y), f_info(y), yus);
00758 }
00759 else if (yus <= 0) {
00760
00761 rl = mul_assign_z(LOWER, to_lower, to_info,
00762 UPPER, f_upper(x), f_info(x), xus,
00763 LOWER, f_lower(y), f_info(y), yls);
00764 ru = mul_assign_z(UPPER, upper(), to_info,
00765 LOWER, f_lower(x), f_info(x), xls,
00766 UPPER, f_upper(y), f_info(y), yus);
00767 }
00768 else {
00769
00770 rl = mul_assign_z(LOWER, to_lower, to_info,
00771 UPPER, f_upper(x), f_info(x), xus,
00772 LOWER, f_lower(y), f_info(y), yls);
00773 ru = mul_assign_z(UPPER, upper(), to_info,
00774 UPPER, f_upper(x), f_info(x), xus,
00775 UPPER, f_upper(y), f_info(y), yus);
00776 }
00777 }
00778 else if (xus <= 0) {
00779 if (yls >= 0) {
00780
00781 rl = mul_assign_z(LOWER, to_lower, to_info,
00782 LOWER, f_lower(x), f_info(x), xls,
00783 UPPER, f_upper(y), f_info(y), yus);
00784 ru = mul_assign_z(UPPER, upper(), to_info,
00785 UPPER, f_upper(x), f_info(x), xus,
00786 LOWER, f_lower(y), f_info(y), yls);
00787 }
00788 else if (yus <= 0) {
00789
00790 rl = mul_assign_z(LOWER, to_lower, to_info,
00791 UPPER, f_upper(x), f_info(x), xus,
00792 UPPER, f_upper(y), f_info(y), yus);
00793 ru = mul_assign_z(UPPER, upper(), to_info,
00794 LOWER, f_lower(x), f_info(x), xls,
00795 LOWER, f_lower(y), f_info(y), yls);
00796 }
00797 else {
00798
00799 rl = mul_assign_z(LOWER, to_lower, to_info,
00800 LOWER, f_lower(x), f_info(x), xls,
00801 UPPER, f_upper(y), f_info(y), yus);
00802 ru = mul_assign_z(UPPER, upper(), to_info,
00803 LOWER, f_lower(x), f_info(x), xls,
00804 LOWER, f_lower(y), f_info(y), yls);
00805 }
00806 }
00807 else if (yls >= 0) {
00808
00809 rl = mul_assign_z(LOWER, to_lower, to_info,
00810 LOWER, f_lower(x), f_info(x), xls,
00811 UPPER, f_upper(y), f_info(y), yus);
00812 ru = mul_assign_z(UPPER, upper(), to_info,
00813 UPPER, f_upper(x), f_info(x), xus,
00814 UPPER, f_upper(y), f_info(y), yus);
00815 }
00816 else if (yus <= 0) {
00817
00818 rl = mul_assign_z(LOWER, to_lower, to_info,
00819 UPPER, f_upper(x), f_info(x), xus,
00820 LOWER, f_lower(y), f_info(y), yls);
00821 ru = mul_assign_z(UPPER, upper(), to_info,
00822 LOWER, f_lower(x), f_info(x), xls,
00823 LOWER, f_lower(y), f_info(y), yls);
00824 }
00825 else {
00826
00827 PPL_DIRTY_TEMP(To_Boundary, tmp);
00828 PPL_DIRTY_TEMP(To_Info, tmp_info);
00829 tmp_info.clear();
00830 Result tmp_r;
00831 tmp_r = Boundary_NS::mul_assign(LOWER, tmp, tmp_info,
00832 UPPER, f_upper(x), f_info(x),
00833 LOWER, f_lower(y), f_info(y));
00834 rl = Boundary_NS::mul_assign(LOWER, to_lower, to_info,
00835 LOWER, f_lower(x), f_info(x),
00836 UPPER, f_upper(y), f_info(y));
00837 if (gt(LOWER, to_lower, to_info, LOWER, tmp, tmp_info)) {
00838 to_lower = tmp;
00839 rl = tmp_r;
00840 }
00841 tmp_info.clear();
00842 tmp_r = Boundary_NS::mul_assign(UPPER, tmp, tmp_info,
00843 UPPER, f_upper(x), f_info(x),
00844 UPPER, f_upper(y), f_info(y));
00845 ru = Boundary_NS::mul_assign(UPPER, upper(), to_info,
00846 LOWER, f_lower(x), f_info(x),
00847 LOWER, f_lower(y), f_info(y));
00848 if (lt(UPPER, upper(), to_info, UPPER, tmp, tmp_info)) {
00849 upper() = tmp;
00850 ru = tmp_r;
00851 }
00852 }
00853 assign_or_swap(lower(), to_lower);
00854 assign_or_swap(info(), to_info);
00855 PPL_ASSERT(OK());
00856 return combine(rl, ru);
00857 }
00858
00870 template <typename To_Boundary, typename To_Info>
00871 template <typename From1, typename From2>
00872 inline typename Enable_If<((Is_Singleton<From1>::value
00873 || Is_Interval<From1>::value)
00874 && (Is_Singleton<From2>::value
00875 || Is_Interval<From2>::value)), I_Result>::type
00876 Interval<To_Boundary, To_Info>::div_assign(const From1& x, const From2& y) {
00877 PPL_ASSERT(f_OK(x));
00878 PPL_ASSERT(f_OK(y));
00879 if (check_empty_arg(x) || check_empty_arg(y))
00880 return assign(EMPTY);
00881 int yls = sgn_b(LOWER, f_lower(y), f_info(y));
00882 int yus = yls > 0 ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
00883 if (yls == 0 && yus == 0)
00884 return assign(EMPTY);
00885 int inf = Parma_Polyhedra_Library::is_infinity(x);
00886 if (inf) {
00887 if (Parma_Polyhedra_Library::is_infinity(y))
00888 return assign(EMPTY);
00889 if (yls == -yus)
00890 return set_infinities();
00891 if (yls < 0 || yus < 0)
00892 inf = -inf;
00893 if (inf < 0)
00894 return assign(MINUS_INFINITY);
00895 else
00896 return assign(PLUS_INFINITY);
00897 }
00898 int xls = sgn_b(LOWER, f_lower(x), f_info(x));
00899 int xus = xls > 0 ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
00900
00901 PPL_DIRTY_TEMP(To_Info, to_info);
00902 to_info.clear();
00903 if (!div_restriction(to_info, x, y))
00904 return assign(EMPTY);
00905 Result rl, ru;
00906 PPL_DIRTY_TEMP(To_Boundary, to_lower);
00907 if (yls >= 0) {
00908 if (xls >= 0) {
00909 rl = div_assign_z(LOWER, to_lower, to_info,
00910 LOWER, f_lower(x), f_info(x), xls,
00911 UPPER, f_upper(y), f_info(y), yus);
00912 ru = div_assign_z(UPPER, upper(), to_info,
00913 UPPER, f_upper(x), f_info(x), xus,
00914 LOWER, f_lower(y), f_info(y), yls);
00915 }
00916 else if (xus <= 0) {
00917 rl = div_assign_z(LOWER, to_lower, to_info,
00918 LOWER, f_lower(x), f_info(x), xls,
00919 LOWER, f_lower(y), f_info(y), yls);
00920 ru = div_assign_z(UPPER, upper(), to_info,
00921 UPPER, f_upper(x), f_info(x), xus,
00922 UPPER, f_upper(y), f_info(y), yus);
00923 }
00924 else {
00925 rl = div_assign_z(LOWER, to_lower, to_info,
00926 LOWER, f_lower(x), f_info(x), xls,
00927 LOWER, f_lower(y), f_info(y), yls);
00928 ru = div_assign_z(UPPER, upper(), to_info,
00929 UPPER, f_upper(x), f_info(x), xus,
00930 LOWER, f_lower(y), f_info(y), yls);
00931 }
00932 }
00933 else if (yus <= 0) {
00934 if (xls >= 0) {
00935 rl = div_assign_z(LOWER, to_lower, to_info,
00936 UPPER, f_upper(x), f_info(x), xus,
00937 UPPER, f_upper(y), f_info(y), yus);
00938 ru = div_assign_z(UPPER, upper(), to_info,
00939 LOWER, f_lower(x), f_info(x), xls,
00940 LOWER, f_lower(y), f_info(y), yls);
00941 }
00942 else if (xus <= 0) {
00943 rl = div_assign_z(LOWER, to_lower, to_info,
00944 UPPER, f_upper(x), f_info(x), xus,
00945 LOWER, f_lower(y), f_info(y), yls);
00946 ru = div_assign_z(UPPER, upper(), to_info,
00947 LOWER, f_lower(x), f_info(x), xls,
00948 UPPER, f_upper(y), f_info(y), yus);
00949 }
00950 else {
00951 rl = div_assign_z(LOWER, to_lower, to_info,
00952 UPPER, f_upper(x), f_info(x), xus,
00953 UPPER, f_upper(y), f_info(y), yus);
00954 ru = div_assign_z(UPPER, upper(), to_info,
00955 LOWER, f_lower(x), f_info(x), xls,
00956 UPPER, f_upper(y), f_info(y), yus);
00957 }
00958 }
00959 else {
00960
00961 return static_cast<I_Result>(assign(UNIVERSE) | I_SINGULARITIES);
00962 }
00963 assign_or_swap(lower(), to_lower);
00964 assign_or_swap(info(), to_info);
00965 PPL_ASSERT(OK());
00966 return combine(rl, ru);
00967 }
00968
00969 template <typename B, typename Info, typename T>
00970 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
00971 operator+(const Interval<B, Info>& x, const T& y) {
00972 Interval<B, Info> z;
00973 z.add_assign(x, y);
00974 return z;
00975 }
00976
00977 template <typename B, typename Info, typename T>
00978 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
00979 operator+(const T& x, const Interval<B, Info>& y) {
00980 Interval<B, Info> z;
00981 z.add_assign(x, y);
00982 return z;
00983 }
00984
00985 template <typename B, typename Info>
00986 inline Interval<B, Info>
00987 operator+(const Interval<B, Info>& x, const Interval<B, Info>& y) {
00988 Interval<B, Info> z;
00989 z.add_assign(x, y);
00990 return z;
00991 }
00992
00993 template <typename B, typename Info, typename T>
00994 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
00995 operator-(const Interval<B, Info>& x, const T& y) {
00996 Interval<B, Info> z;
00997 z.sub_assign(x, y);
00998 return z;
00999 }
01000
01001 template <typename B, typename Info, typename T>
01002 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
01003 operator-(const T& x, const Interval<B, Info>& y) {
01004 Interval<B, Info> z;
01005 z.sub_assign(x, y);
01006 return z;
01007 }
01008
01009 template <typename B, typename Info>
01010 inline Interval<B, Info>
01011 operator-(const Interval<B, Info>& x, const Interval<B, Info>& y) {
01012 Interval<B, Info> z;
01013 z.sub_assign(x, y);
01014 return z;
01015 }
01016
01017 template <typename B, typename Info, typename T>
01018 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
01019 operator*(const Interval<B, Info>& x, const T& y) {
01020 Interval<B, Info> z;
01021 z.mul_assign(x, y);
01022 return z;
01023 }
01024
01025 template <typename B, typename Info, typename T>
01026 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
01027 operator*(const T& x, const Interval<B, Info>& y) {
01028 Interval<B, Info> z;
01029 z.mul_assign(x, y);
01030 return z;
01031 }
01032
01033 template <typename B, typename Info>
01034 inline Interval<B, Info>
01035 operator*(const Interval<B, Info>& x, const Interval<B, Info>& y) {
01036 Interval<B, Info> z;
01037 z.mul_assign(x, y);
01038 return z;
01039 }
01040
01041 template <typename B, typename Info, typename T>
01042 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
01043 operator/(const Interval<B, Info>& x, const T& y) {
01044 Interval<B, Info> z;
01045 z.div_assign(x, y);
01046 return z;
01047 }
01048
01049 template <typename B, typename Info, typename T>
01050 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
01051 operator/(const T& x, const Interval<B, Info>& y) {
01052 Interval<B, Info> z;
01053 z.div_assign(x, y);
01054 return z;
01055 }
01056
01057 template <typename B, typename Info>
01058 inline Interval<B, Info>
01059 operator/(const Interval<B, Info>& x, const Interval<B, Info>& y) {
01060 Interval<B, Info> z;
01061 z.div_assign(x, y);
01062 return z;
01063 }
01064
01065 template <typename Boundary, typename Info>
01066 inline std::ostream&
01067 operator<<(std::ostream& os, const Interval<Boundary, Info>& x) {
01068
01069 if (check_empty_arg(x))
01070 return os << "[]";
01071 if (x.is_singleton()) {
01072 output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
01073 return os;
01074 }
01075 os << (x.lower_is_open() ? "(" : "[");
01076 if (x.info().get_boundary_property(LOWER, SPECIAL))
01077 os << "-inf";
01078 else
01079 output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
01080 os << ", ";
01081 if (x.info().get_boundary_property(UPPER, SPECIAL))
01082 os << "+inf";
01083 else
01084 output(os, x.upper(), Numeric_Format(), ROUND_NOT_NEEDED);
01085 os << (x.upper_is_open() ? ")" : "]");
01086 output_restriction(os, x.info());
01087 return os;
01088 }
01089
01090 template <typename Boundary, typename Info>
01091 inline void
01092 Interval<Boundary, Info>::ascii_dump(std::ostream& s) const {
01093 using Parma_Polyhedra_Library::ascii_dump;
01094 s << "info ";
01095 info().ascii_dump(s);
01096 s << " lower ";
01097 ascii_dump(s, lower());
01098 s << " upper ";
01099 ascii_dump(s, upper());
01100 s << '\n';
01101 }
01102
01103 template <typename Boundary, typename Info>
01104 inline bool
01105 Interval<Boundary, Info>::ascii_load(std::istream& s) {
01106 using Parma_Polyhedra_Library::ascii_load;
01107 std::string str;
01108 if (!(s >> str) || str != "info")
01109 return false;
01110 if (!info().ascii_load(s))
01111 return false;
01112 if (!(s >> str) || str != "lower")
01113 return false;
01114 if (!ascii_load(s, lower()))
01115 return false;
01116 if (!(s >> str) || str != "upper")
01117 return false;
01118 if (!ascii_load(s, upper()))
01119 return false;
01120 PPL_ASSERT(OK());
01121 return true;
01122 }
01123
01129 template <typename Interval_Boundary_Type> struct Select_Temp_Boundary_Type;
01130
01131 template <typename Interval_Boundary_Type>
01132 struct Select_Temp_Boundary_Type {
01133 typedef Interval_Boundary_Type type;
01134 };
01135
01136 template <>
01137 struct Select_Temp_Boundary_Type<float> {
01138 typedef double type;
01139 };
01140
01141 template <>
01142 struct Select_Temp_Boundary_Type<char> {
01143 typedef signed long long type;
01144 };
01145
01146 template <>
01147 struct Select_Temp_Boundary_Type<signed char> {
01148 typedef signed long long type;
01149 };
01150
01151 template <>
01152 struct Select_Temp_Boundary_Type<unsigned char> {
01153 typedef signed long long type;
01154 };
01155
01156 template <>
01157 struct Select_Temp_Boundary_Type<signed short> {
01158 typedef signed long long type;
01159 };
01160
01161 template <>
01162 struct Select_Temp_Boundary_Type<unsigned short> {
01163 typedef signed long long type;
01164 };
01165
01166 template <>
01167 struct Select_Temp_Boundary_Type<signed int> {
01168 typedef signed long long type;
01169 };
01170
01171 template <>
01172 struct Select_Temp_Boundary_Type<unsigned int> {
01173 typedef signed long long type;
01174 };
01175
01176 template <>
01177 struct Select_Temp_Boundary_Type<signed long> {
01178 typedef signed long long type;
01179 };
01180
01181 template <>
01182 struct Select_Temp_Boundary_Type<unsigned long> {
01183 typedef signed long long type;
01184 };
01185
01186 template <>
01187 struct Select_Temp_Boundary_Type<unsigned long long> {
01188 typedef signed long long type;
01189 };
01190
01191 }
01192
01193 namespace std {
01194
01196 template <typename Boundary, typename Info>
01197 inline void
01198 swap(Parma_Polyhedra_Library::Interval<Boundary, Info>& x,
01199 Parma_Polyhedra_Library::Interval<Boundary, Info>& y) {
01200 x.swap(y);
01201 }
01202
01203 }
01204
01205 #endif // !defined(PPL_Interval_inlines_hh)