|
PPL
0.12.1
|
00001 /* Interval boundary functions. 00002 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> 00003 Copyright (C) 2010-2012 BUGSENG srl (http://bugseng.com) 00004 00005 This file is part of the Parma Polyhedra Library (PPL). 00006 00007 The PPL is free software; you can redistribute it and/or modify it 00008 under the terms of the GNU General Public License as published by the 00009 Free Software Foundation; either version 3 of the License, or (at your 00010 option) any later version. 00011 00012 The PPL is distributed in the hope that it will be useful, but WITHOUT 00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00014 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00015 for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software Foundation, 00019 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. 00020 00021 For the most up-to-date information see the Parma Polyhedra Library 00022 site: http://bugseng.com/products/ppl/ . */ 00023 00024 #ifndef PPL_Boundary_defs_hh 00025 #define PPL_Boundary_defs_hh 1 00026 00027 #include "Checked_Number.defs.hh" 00028 00029 namespace Parma_Polyhedra_Library { 00030 00031 namespace Boundary_NS { 00032 00033 struct Property { 00034 enum Type { 00035 SPECIAL_, 00036 OPEN_, 00037 }; 00038 typedef bool Value; 00039 static const Value default_value = true; 00040 static const Value unsupported_value = false; 00041 Property(Type t) 00042 : type(t) { 00043 } 00044 Type type; 00045 }; 00046 00047 static const Property SPECIAL(Property::SPECIAL_); 00048 static const Property OPEN(Property::OPEN_); 00049 00050 enum Boundary_Type { 00051 LOWER = ROUND_DOWN, 00052 UPPER = ROUND_UP 00053 }; 00054 00055 inline Rounding_Dir 00056 round_dir_check(Boundary_Type t, bool check = false) { 00057 if (check) 00058 return static_cast<Rounding_Dir>(t) | ROUND_STRICT_RELATION; 00059 else 00060 return static_cast<Rounding_Dir>(t); 00061 } 00062 00063 template <typename T, typename Info> 00064 inline Result 00065 special_set_boundary_infinity(Boundary_Type type, T&, Info& info) { 00066 PPL_ASSERT(Info::store_special); 00067 info.set_boundary_property(type, SPECIAL); 00068 return V_EQ; 00069 } 00070 00071 template <typename T, typename Info> 00072 inline bool 00073 special_is_open(Boundary_Type, const T&, const Info&) { 00074 return !Info::may_contain_infinity; 00075 } 00076 00077 template <typename T, typename Info> 00078 inline bool 00079 normal_is_open(Boundary_Type type, const T& x, const Info& info) { 00080 if (Info::store_open) 00081 return info.get_boundary_property(type, OPEN); 00082 else 00083 return !Info::store_special && !Info::may_contain_infinity 00084 && normal_is_boundary_infinity(type, x, info); 00085 } 00086 00087 template <typename T, typename Info> 00088 inline bool 00089 is_open(Boundary_Type type, const T& x, const Info& info) { 00090 if (Info::store_open) 00091 return info.get_boundary_property(type, OPEN); 00092 else 00093 return !Info::may_contain_infinity 00094 && is_boundary_infinity(type, x, info); 00095 } 00096 00097 template <typename T, typename Info> 00098 inline Result 00099 set_unbounded(Boundary_Type type, T& x, Info& info) { 00100 PPL_COMPILE_TIME_CHECK(Info::store_special 00101 || std::numeric_limits<T>::is_bounded 00102 || std::numeric_limits<T>::has_infinity, 00103 "unbounded is not representable"); 00104 Result r; 00105 if (Info::store_special) 00106 r = special_set_boundary_infinity(type, x, info); 00107 else if (type == LOWER) 00108 r = assign_r(x, MINUS_INFINITY, ROUND_UP); 00109 else 00110 r = assign_r(x, PLUS_INFINITY, ROUND_DOWN); 00111 if (result_relation(r) == VR_EQ && !Info::may_contain_infinity) 00112 info.set_boundary_property(type, OPEN); 00113 return r; 00114 } 00115 00116 template <typename T, typename Info> 00117 inline Result 00118 set_minus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) { 00119 /* 00120 PPL_COMPILE_TIME_CHECK(Info::store_special 00121 || std::numeric_limits<T>::has_infinity, 00122 "minus infinity is not representable"); 00123 */ 00124 if (open) { 00125 PPL_ASSERT(type == LOWER); 00126 } 00127 else { 00128 PPL_ASSERT(Info::may_contain_infinity); 00129 } 00130 Result r; 00131 if (Info::store_special) { 00132 PPL_ASSERT(type == LOWER); 00133 r = special_set_boundary_infinity(type, x, info); 00134 } 00135 else { 00136 r = assign_r(x, MINUS_INFINITY, round_dir_check(type)); 00137 PPL_ASSERT(result_representable(r)); 00138 } 00139 if (open || result_relation(r) != VR_EQ) 00140 info.set_boundary_property(type, OPEN); 00141 return r; 00142 } 00143 00144 template <typename T, typename Info> 00145 inline Result 00146 set_plus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) { 00147 /* 00148 PPL_COMPILE_TIME_CHECK(Info::store_special 00149 || std::numeric_limits<T>::has_infinity, 00150 "minus infinity is not representable"); 00151 */ 00152 if (open) { 00153 PPL_ASSERT(type == UPPER); 00154 } 00155 else { 00156 PPL_ASSERT(Info::may_contain_infinity); 00157 } 00158 Result r; 00159 if (Info::store_special) { 00160 PPL_ASSERT(type == UPPER); 00161 r = special_set_boundary_infinity(type, x, info); 00162 } 00163 else { 00164 r = assign_r(x, PLUS_INFINITY, round_dir_check(type)); 00165 PPL_ASSERT(result_representable(r)); 00166 } 00167 if (open || result_relation(r) != VR_EQ) 00168 info.set_boundary_property(type, OPEN); 00169 return r; 00170 } 00171 00172 template <typename T, typename Info> 00173 inline Result 00174 set_boundary_infinity(Boundary_Type type, T& x, Info& info, bool open = false) { 00175 PPL_ASSERT(open || Info::may_contain_infinity); 00176 Result r; 00177 if (Info::store_special) 00178 r = special_set_boundary_infinity(type, x, info); 00179 else if (type == LOWER) 00180 r = assign_r(x, MINUS_INFINITY, round_dir_check(type)); 00181 else 00182 r = assign_r(x, PLUS_INFINITY, round_dir_check(type)); 00183 PPL_ASSERT(result_representable(r)); 00184 if (open) 00185 info.set_boundary_property(type, OPEN); 00186 return r; 00187 } 00188 00189 template <typename T, typename Info> 00190 inline bool 00191 is_domain_inf(Boundary_Type type, const T& x, const Info& info) { 00192 if (Info::store_special && type == LOWER) 00193 return info.get_boundary_property(type, SPECIAL); 00194 else if (std::numeric_limits<T>::has_infinity) 00195 return Parma_Polyhedra_Library::is_minus_infinity(x); 00196 else if (std::numeric_limits<T>::is_bounded) 00197 return x == std::numeric_limits<T>::min(); 00198 else 00199 return false; 00200 } 00201 00202 template <typename T, typename Info> 00203 inline bool 00204 is_domain_sup(Boundary_Type type, const T& x, const Info& info) { 00205 if (Info::store_special && type == UPPER) 00206 return info.get_boundary_property(type, SPECIAL); 00207 else if (std::numeric_limits<T>::has_infinity) 00208 return Parma_Polyhedra_Library::is_plus_infinity(x); 00209 else if (std::numeric_limits<T>::is_bounded) 00210 return x == std::numeric_limits<T>::max(); 00211 else 00212 return false; 00213 } 00214 00215 template <typename T, typename Info> 00216 inline bool 00217 normal_is_boundary_infinity(Boundary_Type type, const T& x, const Info&) { 00218 if (!std::numeric_limits<T>::has_infinity) 00219 return false; 00220 if (type == LOWER) 00221 return Parma_Polyhedra_Library::is_minus_infinity(x); 00222 else 00223 return Parma_Polyhedra_Library::is_plus_infinity(x); 00224 } 00225 00226 template <typename T, typename Info> 00227 inline bool 00228 is_boundary_infinity(Boundary_Type type, const T& x, const Info& info) { 00229 if (Info::store_special) 00230 return info.get_boundary_property(type, SPECIAL); 00231 else 00232 return normal_is_boundary_infinity(type, x, info); 00233 } 00234 00235 template <typename T, typename Info> 00236 inline bool 00237 normal_is_reverse_infinity(Boundary_Type type, const T& x, const Info&) { 00238 if (!Info::may_contain_infinity) 00239 return false; 00240 else if (type == LOWER) 00241 return Parma_Polyhedra_Library::is_plus_infinity(x); 00242 else 00243 return Parma_Polyhedra_Library::is_minus_infinity(x); 00244 } 00245 00246 template <typename T, typename Info> 00247 inline bool 00248 is_minus_infinity(Boundary_Type type, const T& x, const Info& info) { 00249 if (type == LOWER) { 00250 if (Info::store_special) 00251 return info.get_boundary_property(type, SPECIAL); 00252 else 00253 return normal_is_boundary_infinity(type, x, info); 00254 } 00255 else 00256 return !Info::store_special && normal_is_reverse_infinity(type, x, info); 00257 } 00258 00259 template <typename T, typename Info> 00260 inline bool 00261 is_plus_infinity(Boundary_Type type, const T& x, const Info& info) { 00262 if (type == UPPER) { 00263 if (Info::store_special) 00264 return info.get_boundary_property(type, SPECIAL); 00265 else 00266 return normal_is_boundary_infinity(type, x, info); 00267 } 00268 else 00269 return !Info::store_special && normal_is_reverse_infinity(type, x, info); 00270 } 00271 00272 template <typename T, typename Info> 00273 inline bool 00274 is_reverse_infinity(Boundary_Type type, const T& x, const Info& info) { 00275 return normal_is_reverse_infinity(type, x, info); 00276 } 00277 00278 template <typename T, typename Info> 00279 inline int 00280 infinity_sign(Boundary_Type type, const T& x, const Info& info) { 00281 if (is_boundary_infinity(type, x, info)) 00282 return (type == LOWER) ? -1 : 1; 00283 else if (is_reverse_infinity(type, x, info)) 00284 return (type == UPPER) ? -1 : 1; 00285 else 00286 return 0; 00287 } 00288 00289 template <typename T, typename Info> 00290 inline bool 00291 is_boundary_infinity_closed(Boundary_Type type, const T& x, const Info& info) { 00292 return Info::may_contain_infinity 00293 && !info.get_boundary_property(type, OPEN) 00294 && is_boundary_infinity(type, x, info); 00295 } 00296 00297 template <typename Info> 00298 inline bool 00299 boundary_infinity_is_open(Boundary_Type type, const Info& info) { 00300 return !Info::may_contain_infinity 00301 || info.get_boundary_property(type, OPEN); 00302 } 00303 00304 template <typename T, typename Info> 00305 inline int 00306 sgn_b(Boundary_Type type, const T& x, const Info& info) { 00307 if (info.get_boundary_property(type, SPECIAL)) 00308 return (type == LOWER) ? -1 : 1; 00309 else 00310 // The following Parma_Polyhedra_Library:: qualification is to work 00311 // around a bug of GCC 4.0.x. 00312 return Parma_Polyhedra_Library::sgn(x); 00313 } 00314 00315 template <typename T, typename Info> 00316 inline int 00317 sgn(Boundary_Type type, const T& x, const Info& info) { 00318 int sign = sgn_b(type, x, info); 00319 if (x == 0 && info.get_boundary_property(type, OPEN)) 00320 return (type == LOWER) ? -1 : 1; 00321 else 00322 return sign; 00323 } 00324 00325 template <typename T1, typename Info1, typename T2, typename Info2> 00326 inline bool 00327 eq(Boundary_Type type1, const T1& x1, const Info1& info1, 00328 Boundary_Type type2, const T2& x2, const Info2& info2) { 00329 if (type1 == type2) { 00330 if (is_open(type1, x1, info1) 00331 != is_open(type2, x2, info2)) 00332 return false; 00333 } 00334 else if (is_open(type1, x1, info1) 00335 || is_open(type2, x2, info2)) 00336 return false; 00337 if (is_minus_infinity(type1, x1, info1)) 00338 return is_minus_infinity(type2, x2, info2); 00339 else if (is_plus_infinity(type1, x1, info1)) 00340 return is_plus_infinity(type2, x2, info2); 00341 else if (is_minus_infinity(type2, x2, info2) 00342 || is_plus_infinity(type2, x2, info2)) 00343 return false; 00344 else 00345 return equal(x1, x2); 00346 } 00347 00348 template <typename T1, typename Info1, typename T2, typename Info2> 00349 inline bool 00350 lt(Boundary_Type type1, const T1& x1, const Info1& info1, 00351 Boundary_Type type2, const T2& x2, const Info2& info2) { 00352 if (is_open(type1, x1, info1)) { 00353 if (type1 == UPPER 00354 && (type2 == LOWER 00355 || !is_open(type2, x2, info2))) 00356 goto le; 00357 } 00358 else if (type2 == LOWER 00359 && is_open(type2, x2, info2)) { 00360 le: 00361 if (is_minus_infinity(type1, x1, info1) 00362 || is_plus_infinity(type2, x2, info2)) 00363 return true; 00364 if (is_plus_infinity(type1, x1, info1) 00365 || is_minus_infinity(type2, x2, info2)) 00366 return false; 00367 else 00368 return less_or_equal(x1, x2); 00369 } 00370 if (is_plus_infinity(type1, x1, info1) 00371 || is_minus_infinity(type2, x2, info2)) 00372 return false; 00373 if (is_minus_infinity(type1, x1, info1) 00374 || is_plus_infinity(type2, x2, info2)) 00375 return true; 00376 else 00377 return less_than(x1, x2); 00378 } 00379 00380 template <typename T1, typename Info1, typename T2, typename Info2> 00381 inline bool 00382 gt(Boundary_Type type1, const T1& x1, const Info1& info1, 00383 Boundary_Type type2, const T2& x2, const Info2& info2) { 00384 return lt(type2, x2, info2, type1, x1, info1); 00385 } 00386 00387 template <typename T1, typename Info1, typename T2, typename Info2> 00388 inline bool 00389 le(Boundary_Type type1, const T1& x1, const Info1& info1, 00390 Boundary_Type type2, const T2& x2, const Info2& info2) { 00391 return !gt(type1, x1, info1, type2, x2, info2); 00392 } 00393 00394 template <typename T1, typename Info1, typename T2, typename Info2> 00395 inline bool 00396 ge(Boundary_Type type1, const T1& x1, const Info1& info1, 00397 Boundary_Type type2, const T2& x2, const Info2& info2) { 00398 return !lt(type1, x1, info1, type2, x2, info2); 00399 } 00400 00401 template <typename T, typename Info> 00402 inline Result 00403 adjust_boundary(Boundary_Type type, T& x, Info& info, 00404 bool open, Result r) { 00405 r = result_relation_class(r); 00406 if (type == LOWER) { 00407 switch (r) { 00408 case V_GT_MINUS_INFINITY: 00409 open = true; 00410 /* Fall through */ 00411 case V_EQ_MINUS_INFINITY: 00412 if (!Info::store_special) 00413 return r; 00414 if (open) 00415 info.set_boundary_property(type, OPEN); 00416 return special_set_boundary_infinity(type, x, info); 00417 case V_GT: 00418 open = true; 00419 /* Fall through */ 00420 case V_GE: 00421 case V_EQ: 00422 if (open) 00423 info.set_boundary_property(type, OPEN); 00424 return r; 00425 default: 00426 PPL_UNREACHABLE; 00427 return V_NAN; 00428 } 00429 } 00430 else { 00431 switch (r) { 00432 case V_LT_PLUS_INFINITY: 00433 open = true; 00434 /* Fall through */ 00435 case V_EQ_PLUS_INFINITY: 00436 if (!Info::store_special) 00437 return r; 00438 if (open) 00439 info.set_boundary_property(type, OPEN); 00440 return special_set_boundary_infinity(type, x, info); 00441 case V_LT: 00442 open = true; 00443 /* Fall through */ 00444 case V_LE: 00445 case V_EQ: 00446 if (open) 00447 info.set_boundary_property(type, OPEN); 00448 return r; 00449 default: 00450 PPL_UNREACHABLE; 00451 return V_NAN; 00452 } 00453 } 00454 } 00455 00456 template <typename To, typename To_Info, typename T, typename Info> 00457 inline Result 00458 complement(Boundary_Type to_type, To& to, To_Info& to_info, 00459 Boundary_Type type, const T& x, const Info& info) { 00460 PPL_ASSERT(to_type != type); 00461 bool should_shrink; 00462 if (info.get_boundary_property(type, SPECIAL)) { 00463 should_shrink = !special_is_open(type, x, info); 00464 if (type == LOWER) 00465 return set_minus_infinity(to_type, to, to_info, should_shrink); 00466 else 00467 return set_plus_infinity(to_type, to, to_info, should_shrink); 00468 } 00469 should_shrink = !normal_is_open(type, x, info); 00470 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00471 Result r = assign_r(to, x, round_dir_check(to_type, check)); 00472 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00473 } 00474 00475 template <typename To, typename To_Info, typename T, typename Info> 00476 inline Result 00477 assign(Boundary_Type to_type, To& to, To_Info& to_info, 00478 Boundary_Type type, const T& x, const Info& info, 00479 bool should_shrink = false) { 00480 PPL_ASSERT(to_type == type); 00481 if (info.get_boundary_property(type, SPECIAL)) { 00482 should_shrink = (should_shrink || special_is_open(type, x, info)); 00483 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00484 } 00485 should_shrink = (should_shrink || normal_is_open(type, x, info)); 00486 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00487 Result r = assign_r(to, x, round_dir_check(to_type, check)); 00488 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00489 } 00490 00491 template <typename To, typename To_Info, typename T, typename Info> 00492 inline Result 00493 min_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00494 Boundary_Type type, const T& x, const Info& info) { 00495 if (lt(type, x, info, to_type, to, to_info)) { 00496 to_info.clear_boundary_properties(to_type); 00497 return assign(to_type, to, to_info, type, x, info); 00498 } 00499 return V_EQ; 00500 } 00501 00502 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00503 inline Result 00504 min_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00505 Boundary_Type type1, const T1& x1, const Info1& info1, 00506 Boundary_Type type2, const T2& x2, const Info2& info2) { 00507 if (lt(type1, x1, info1, type2, x2, info2)) 00508 return assign(to_type, to, to_info, type1, x1, info1); 00509 else 00510 return assign(to_type, to, to_info, type2, x2, info2); 00511 } 00512 00513 template <typename To, typename To_Info, typename T, typename Info> 00514 inline Result 00515 max_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00516 Boundary_Type type, const T& x, const Info& info) { 00517 if (gt(type, x, info, to_type, to, to_info)) { 00518 to_info.clear_boundary_properties(to_type); 00519 return assign(to_type, to, to_info, type, x, info); 00520 } 00521 return V_EQ; 00522 } 00523 00524 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00525 inline Result 00526 max_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00527 Boundary_Type type1, const T1& x1, const Info1& info1, 00528 Boundary_Type type2, const T2& x2, const Info2& info2) { 00529 if (gt(type1, x1, info1, type2, x2, info2)) 00530 return assign(to_type, to, to_info, type1, x1, info1); 00531 else 00532 return assign(to_type, to, to_info, type2, x2, info2); 00533 } 00534 00535 template <typename To, typename To_Info, typename T, typename Info> 00536 inline Result 00537 neg_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00538 Boundary_Type type, const T& x, const Info& info) { 00539 PPL_ASSERT(to_type != type); 00540 bool should_shrink; 00541 if (info.get_boundary_property(type, SPECIAL)) { 00542 should_shrink = special_is_open(type, x, info); 00543 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00544 } 00545 should_shrink = normal_is_open(type, x, info); 00546 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00547 Result r = neg_assign_r(to, x, round_dir_check(to_type, check)); 00548 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00549 } 00550 00551 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00552 inline Result 00553 add_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00554 Boundary_Type type1, const T1& x1, const Info1& info1, 00555 Boundary_Type type2, const T2& x2, const Info2& info2) { 00556 PPL_ASSERT(type1 == type2); 00557 bool should_shrink; 00558 if (is_boundary_infinity(type1, x1, info1)) { 00559 should_shrink = (boundary_infinity_is_open(type1, info1) 00560 && !is_boundary_infinity_closed(type2, x2, info2)); 00561 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00562 } 00563 else if (is_boundary_infinity(type2, x2, info2)) { 00564 should_shrink = (boundary_infinity_is_open(type2, info2) 00565 && !is_boundary_infinity_closed(type1, x1, info1)); 00566 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00567 } 00568 should_shrink = (normal_is_open(type1, x1, info1) 00569 || normal_is_open(type2, x2, info2)); 00570 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00571 // FIXME: extended handling is not needed 00572 Result r = add_assign_r(to, x1, x2, round_dir_check(to_type, check)); 00573 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00574 } 00575 00576 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00577 inline Result 00578 sub_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00579 Boundary_Type type1, const T1& x1, const Info1& info1, 00580 Boundary_Type type2, const T2& x2, const Info2& info2) { 00581 PPL_ASSERT(type1 != type2); 00582 bool should_shrink; 00583 if (is_boundary_infinity(type1, x1, info1)) { 00584 should_shrink = (boundary_infinity_is_open(type1, info1) 00585 && !is_boundary_infinity_closed(type2, x2, info2)); 00586 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00587 } 00588 else if (is_boundary_infinity(type2, x2, info2)) { 00589 should_shrink = (boundary_infinity_is_open(type2, info2) 00590 && !is_boundary_infinity_closed(type1, x1, info1)); 00591 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00592 } 00593 should_shrink = (normal_is_open(type1, x1, info1) 00594 || normal_is_open(type2, x2, info2)); 00595 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00596 // FIXME: extended handling is not needed 00597 Result r = sub_assign_r(to, x1, x2, round_dir_check(to_type, check)); 00598 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00599 } 00600 00601 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00602 inline Result 00603 mul_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00604 Boundary_Type type1, const T1& x1, const Info1& info1, 00605 Boundary_Type type2, const T2& x2, const Info2& info2) { 00606 bool should_shrink; 00607 if (is_boundary_infinity(type1, x1, info1)) { 00608 should_shrink = (boundary_infinity_is_open(type1, info1) 00609 && !is_boundary_infinity_closed(type2, x2, info2)); 00610 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00611 } 00612 else if (is_boundary_infinity(type2, x2, info2)) { 00613 should_shrink = (boundary_infinity_is_open(type2, info2) 00614 && !is_boundary_infinity_closed(type1, x1, info1)); 00615 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00616 } 00617 should_shrink = (normal_is_open(type1, x1, info1) 00618 || normal_is_open(type2, x2, info2)); 00619 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00620 PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value); 00621 // FIXME: extended handling is not needed 00622 Result r = mul_assign_r(to, x1, x2, round_dir_check(to_type, check)); 00623 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00624 } 00625 00626 template <typename To, typename To_Info> 00627 inline Result 00628 set_zero(Boundary_Type to_type, To& to, To_Info& to_info, bool should_shrink) { 00629 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00630 Result r = assign_r(to, Constant<0>::value, round_dir_check(to_type, check)); 00631 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00632 } 00633 00634 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00635 inline Result 00636 mul_assign_z(Boundary_Type to_type, To& to, To_Info& to_info, 00637 Boundary_Type type1, const T1& x1, const Info1& info1, int x1s, 00638 Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) { 00639 bool should_shrink; 00640 if (x1s != 0) { 00641 if (x2s != 0) 00642 return mul_assign(to_type, to, to_info, 00643 type1, x1, info1, 00644 type2, x2, info2); 00645 else 00646 should_shrink = info2.get_boundary_property(type2, OPEN); 00647 } 00648 else { 00649 should_shrink = (info1.get_boundary_property(type1, OPEN) 00650 && (x2s != 0 || info2.get_boundary_property(type2, OPEN))); 00651 } 00652 return set_zero(to_type, to, to_info, should_shrink); 00653 } 00654 00655 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00656 inline Result 00657 div_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00658 Boundary_Type type1, const T1& x1, const Info1& info1, 00659 Boundary_Type type2, const T2& x2, const Info2& info2) { 00660 bool should_shrink; 00661 if (is_boundary_infinity(type1, x1, info1)) { 00662 should_shrink = boundary_infinity_is_open(type1, info1); 00663 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00664 } 00665 else if (is_boundary_infinity(type2, x2, info2)) { 00666 should_shrink = boundary_infinity_is_open(type2, info2); 00667 return set_zero(to_type, to, to_info, should_shrink); 00668 } 00669 should_shrink = (normal_is_open(type1, x1, info1) 00670 || normal_is_open(type2, x2, info2)); 00671 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00672 PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value); 00673 // FIXME: extended handling is not needed 00674 Result r = div_assign_r(to, x1, x2, round_dir_check(to_type, check)); 00675 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00676 } 00677 00678 00679 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2> 00680 inline Result 00681 div_assign_z(Boundary_Type to_type, To& to, To_Info& to_info, 00682 Boundary_Type type1, const T1& x1, const Info1& info1, int x1s, 00683 Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) { 00684 if (x1s != 0) { 00685 if (x2s != 0) 00686 return div_assign(to_type, to, to_info, 00687 type1, x1, info1, 00688 type2, x2, info2); 00689 else { 00690 return set_boundary_infinity(to_type, to, to_info, true); 00691 } 00692 } 00693 else { 00694 bool should_shrink = info1.get_boundary_property(type1, OPEN) 00695 && !is_boundary_infinity_closed(type2, x2, info2); 00696 return set_zero(to_type, to, to_info, should_shrink); 00697 } 00698 } 00699 00700 template <typename To, typename To_Info, typename T, typename Info> 00701 inline Result 00702 umod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00703 Boundary_Type type, const T& x, const Info& info, 00704 unsigned int exp) { 00705 PPL_ASSERT(to_type == type); 00706 bool should_shrink; 00707 if (is_boundary_infinity(type, x, info)) { 00708 should_shrink = boundary_infinity_is_open(type, info); 00709 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00710 } 00711 should_shrink = normal_is_open(type, x, info); 00712 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00713 Result r = umod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check)); 00714 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00715 } 00716 00717 template <typename To, typename To_Info, typename T, typename Info> 00718 inline Result 00719 smod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info, 00720 Boundary_Type type, const T& x, const Info& info, 00721 unsigned int exp) { 00722 PPL_ASSERT(to_type == type); 00723 bool should_shrink; 00724 if (is_boundary_infinity(type, x, info)) { 00725 should_shrink = boundary_infinity_is_open(type, info); 00726 return set_boundary_infinity(to_type, to, to_info, should_shrink); 00727 } 00728 should_shrink = normal_is_open(type, x, info); 00729 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open)); 00730 Result r = smod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check)); 00731 return adjust_boundary(to_type, to, to_info, should_shrink, r); 00732 } 00733 00734 } // namespace Boundary_NS 00735 00736 } // namespace Parma_Polyhedra_Library 00737 00738 #endif // !defined(PPL_Boundary_defs_hh)