PPL  0.12.1
Boundary.defs.hh
Go to the documentation of this file.
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)