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_Restriction_defs_hh
00025 #define PPL_Interval_Restriction_defs_hh 1
00026
00027 #include "meta_programming.hh"
00028 #include "Slow_Copy.hh"
00029 #include "assign_or_swap.hh"
00030 #include "Result.defs.hh"
00031 #include "Rounding_Dir.defs.hh"
00032 #include "Checked_Number.defs.hh"
00033
00034 namespace Parma_Polyhedra_Library {
00035
00036 struct Interval_Base;
00037
00038 template <typename T, typename Enable = void>
00039 struct Boundary_Value {
00040 typedef T type;
00041 };
00042
00043 template <typename T>
00044 struct Boundary_Value<T, typename Enable_If<Is_Same_Or_Derived<Interval_Base, T>::value>::type > {
00045 typedef typename T::boundary_type type;
00046 };
00047
00048 class Interval_Restriction_None_Base {
00049 public:
00050 bool has_restriction() const {
00051 return false;
00052 }
00053 void normalize() const {
00054 }
00055 template <typename T>
00056 Result restrict(Rounding_Dir, T&, Result dir) const {
00057 return dir;
00058 }
00059 };
00060
00061 inline bool
00062 eq_restriction(const Interval_Restriction_None_Base&, const Interval_Restriction_None_Base) {
00063 return true;
00064 }
00065
00066 template <typename T>
00067 inline bool
00068 contains_restriction(const Interval_Restriction_None_Base&, const T&) {
00069 return true;
00070 }
00071
00072 template <typename T>
00073 inline bool
00074 assign_restriction(Interval_Restriction_None_Base&, const T&) {
00075 return true;
00076 }
00077
00078 template <typename T1, typename T2>
00079 inline bool
00080 join_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00081 return true;
00082 }
00083
00084 template <typename T1, typename T2>
00085 inline bool
00086 intersect_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00087 return true;
00088 }
00089
00090 template <typename T1, typename T2>
00091 inline bool
00092 diff_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00093 return true;
00094 }
00095
00096 template <typename T>
00097 inline bool
00098 neg_restriction(Interval_Restriction_None_Base&, const T&) {
00099 return true;
00100 }
00101
00102 template <typename T1, typename T2>
00103 inline bool
00104 add_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00105 return true;
00106 }
00107
00108 template <typename T1, typename T2>
00109 inline bool
00110 sub_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00111 return true;
00112 }
00113
00114 template <typename T1, typename T2>
00115 inline bool
00116 mul_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00117 return true;
00118 }
00119
00120 template <typename T1, typename T2>
00121 inline bool
00122 div_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
00123 return true;
00124 }
00125
00126 inline void
00127 output_restriction(std::ostream&, const Interval_Restriction_None_Base&) {
00128 }
00129
00130 template <typename Base>
00131 class Interval_Restriction_None : public Interval_Restriction_None_Base,
00132 public Base {
00133 public:
00134 Interval_Restriction_None() {
00135 }
00136 template <typename T>
00137 Interval_Restriction_None(const T& init)
00138 : Base(init) {
00139 }
00140 };
00141
00142 class Interval_Restriction_Integer_Base {
00143 };
00144
00145 template <typename Base>
00146 class Interval_Restriction_Integer : public Interval_Restriction_Integer_Base, public Base {
00147 public:
00148 Interval_Restriction_Integer() {
00149 }
00150 void set_integer(bool v = true) {
00151 return set_bit(Base::bitset, integer_bit, v);
00152 }
00153 bool get_integer() const {
00154 return get_bit(Base::bitset, integer_bit);
00155 }
00156
00157 const_int_nodef(integer_bit, Base::next_bit);
00158 const_int_nodef(next_bit, integer_bit + 1);
00159 bool has_restriction() const {
00160 return get_integer();
00161 }
00162 void normalize() const {
00163 }
00164 template <typename T>
00165 Result restrict(Rounding_Dir rdir, T& x, Result dir) const {
00166 if (!has_restriction())
00167 return dir;
00168 switch (dir) {
00169 case V_GT:
00170 if (is_integer(x))
00171 return add_assign_r(x, x, static_cast<T>(1), rdir);
00172
00173 case V_GE:
00174 return ceil_assign_r(x, x, rdir);
00175 case V_LT:
00176 if (is_integer(x))
00177 return sub_assign_r(x, x, static_cast<T>(1), rdir);
00178
00179 case V_LE:
00180 return floor_assign_r(x, x, rdir);
00181 default:
00182 PPL_ASSERT(false);
00183 return dir;
00184 }
00185 }
00186 };
00187
00188 class Simple_Restriction_Integer : public Interval_Restriction_Integer_Base {
00189 public:
00190 Simple_Restriction_Integer(bool i)
00191 : integer(i) {
00192 }
00193 bool get_integer() const {
00194 return integer;
00195 }
00196 private:
00197 bool integer;
00198 };
00199
00200 template <typename From, typename Base, typename Enable = void>
00201 struct Restriction_Integer;
00202
00203 template <typename From, typename Base>
00204 struct Restriction_Integer<From, Base, typename Enable_If<Is_Native_Or_Checked<From>::value>::type> {
00205 typedef Simple_Restriction_Integer type;
00206 static type get(const From& x) {
00207 return Simple_Restriction_Integer(is_integer(x));
00208 }
00209 };
00210
00211 template <typename From, typename Base>
00212 struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_None_Base, typename From::info_type>::value>::type> {
00213 typedef Simple_Restriction_Integer type;
00214 static type get(const From& x) {
00215 return Simple_Restriction_Integer(x.is_singleton() && is_integer(x.lower()));
00216 }
00217 };
00218
00219 template <typename From, typename Base>
00220 struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, typename From::info_type>::value>::type> {
00221 typedef Interval_Restriction_Integer<Base> type;
00222 static const type& get(const From& x) {
00223 return x.info();
00224 }
00225 };
00226
00227 template <typename T1, typename T2>
00228 inline typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, T1>::value && Is_Same_Or_Derived<Interval_Restriction_Integer_Base, T2>::value, bool>::type
00229 eq_restriction(const T1& x, const T2& y) {
00230 return x.get_integer() == y.get_integer();
00231 }
00232
00233 template <typename T1, typename T2>
00234 inline typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, T1>::value && Is_Same_Or_Derived<Interval_Restriction_Integer_Base, T2>::value, bool>::type
00235 contains_restriction(const T1& x, const T2& y) {
00236 return !x.get_integer() || y.get_integer();
00237 }
00238
00239 template <typename Base, typename From>
00240 inline bool
00241 assign_restriction(Interval_Restriction_Integer<Base>& to, const From& x) {
00242 to.set_integer(Restriction_Integer<From, Base>::get(x).get_integer());
00243 return true;
00244 }
00245
00246 template <typename Base, typename From1, typename From2>
00247 inline bool
00248 join_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
00249 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
00250 && Restriction_Integer<From2, Base>::get(y).get_integer());
00251 return true;
00252 }
00253
00254 template <typename Base, typename From1, typename From2>
00255 inline bool
00256 intersect_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
00257 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
00258 || Restriction_Integer<From2, Base>::get(y).get_integer());
00259 return true;
00260 }
00261
00262 template <typename Base, typename From1, typename From2>
00263 inline bool
00264 diff_restriction(Interval_Restriction_Integer<Base>& to,
00265 const From1& x, const From2&) {
00266 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer());
00267 return true;
00268 }
00269
00270 template <typename Base, typename From>
00271 inline bool
00272 neg_restriction(Interval_Restriction_Integer<Base>& to, const From& x) {
00273 to.set_integer(Restriction_Integer<From, Base>::get(x).get_integer());
00274 return true;
00275 }
00276
00277 template <typename Base, typename From1, typename From2>
00278 inline bool
00279 add_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
00280 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
00281 && Restriction_Integer<From2, Base>::get(y).get_integer());
00282 return true;
00283 }
00284
00285 template <typename Base, typename From1, typename From2>
00286 inline bool
00287 sub_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
00288 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
00289 && Restriction_Integer<From2, Base>::get(y).get_integer());
00290 return true;
00291 }
00292
00293 template <typename Base, typename From1, typename From2>
00294 inline bool
00295 mul_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
00296 to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
00297 && Restriction_Integer<From2, Base>::get(y).get_integer());
00298 return true;
00299 }
00300
00301 template <typename Base, typename From1, typename From2>
00302 inline bool
00303 div_restriction(Interval_Restriction_Integer<Base>& to, const From1&, const From2&) {
00304 to.set_integer(false);
00305 return true;
00306 }
00307
00308 template <typename Base>
00309 inline void
00310 output_restriction(std::ostream& s, const Interval_Restriction_Integer<Base>& x) {
00311 if (x.get_integer())
00312 s << "i";
00313 }
00314
00315 class Interval_Restriction_Integer_Modulo_Base {
00316 };
00317
00318 template <typename T, typename Base>
00319 class Interval_Restriction_Integer_Modulo : public Interval_Restriction_Integer_Modulo_Base, public Base {
00320 public:
00321 PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_exact,
00322 "type for modulo values must be exact");
00323 Interval_Restriction_Integer_Modulo() {
00324
00325
00326 clear();
00327 }
00328 bool has_restriction() const {
00329 return divisor != 0;
00330 }
00331 void clear() {
00332 remainder = 0;
00333 divisor = 0;
00334 Base::clear();
00335 }
00336 void normalize() const {
00337 }
00338 template <typename V>
00339 Result restrict(Rounding_Dir rdir, V& x, Result dir) const {
00340 if (!has_restriction())
00341 return dir;
00342 PPL_DIRTY_TEMP(V, n);
00343 PPL_DIRTY_TEMP(V, div);
00344 Result r;
00345 r = assign_r(div, divisor, ROUND_CHECK);
00346 PPL_ASSERT(r == V_EQ);
00347 int s;
00348 r = rem_assign_r(n, x, div, ROUND_NOT_NEEDED);
00349 PPL_ASSERT(r == V_EQ);
00350 s = sgn(n);
00351 switch (dir) {
00352 case V_GT:
00353 if (s >= 0) {
00354 r = sub_assign_r(n, div, n, ROUND_NOT_NEEDED);
00355 PPL_ASSERT(r == V_EQ);
00356 return add_assign_r(x, x, n, rdir);
00357 }
00358 else
00359 return sub_assign_r(x, x, n, rdir);
00360 case V_GE:
00361 if (s > 0) {
00362 r = sub_assign_r(n, div, n, ROUND_NOT_NEEDED);
00363 PPL_ASSERT(r == V_EQ);
00364 return add_assign_r(x, x, n, rdir);
00365 }
00366 else if (s < 0)
00367 return sub_assign_r(x, x, n, rdir);
00368 else
00369 return V_EQ;
00370 case V_LT:
00371 if (s <= 0) {
00372 r = add_assign_r(n, div, n, ROUND_NOT_NEEDED);
00373 PPL_ASSERT(r == V_EQ);
00374 return sub_assign_r(x, x, n, rdir);
00375 }
00376 else
00377 return sub_assign_r(x, x, n, rdir);
00378 case V_LE:
00379 if (s < 0) {
00380 r = add_assign_r(n, div, n, ROUND_NOT_NEEDED);
00381 PPL_ASSERT(r == V_EQ);
00382 return sub_assign_r(x, x, n, rdir);
00383 }
00384 else if (s > 0)
00385 return sub_assign_r(x, x, n, rdir);
00386 else
00387 return V_EQ;
00388 default:
00389 PPL_ASSERT(false);
00390 return dir;
00391 }
00392 }
00393 void assign_or_swap(Interval_Restriction_Integer_Modulo& x) {
00394 Parma_Polyhedra_Library::assign_or_swap(remainder, x.remainder);
00395 Parma_Polyhedra_Library::assign_or_swap(divisor, x.divisor);
00396 }
00397 typedef T modulo_type;
00398 T remainder;
00399 T divisor;
00400 };
00401
00402 template <typename T, typename Base>
00403 struct Slow_Copy<Interval_Restriction_Integer_Modulo<T, Base> > : public Bool<Slow_Copy<T>::value> {};
00404
00405
00406 template <typename From, typename Base>
00407 struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, typename From::info_type>::value>::type> {
00408 typedef Simple_Restriction_Integer type;
00409 static type get(const From& x) {
00410 return Simple_Restriction_Integer(x.info().divisor != 0);
00411 }
00412 };
00413
00414 template <typename T>
00415 struct Simple_Restriction_Integer_Modulo : public Interval_Restriction_Integer_Modulo_Base {
00416 template <typename From>
00417 Simple_Restriction_Integer_Modulo(const From& r, const From& d)
00418 : remainder(r), divisor(d) {
00419 }
00420 typedef T modulo_type;
00421 T remainder;
00422 T divisor;
00423 };
00424
00425 template <typename From, typename T, typename Base, typename Enable = void>
00426 struct Restriction_Integer_Modulo;
00427
00428 template <typename From, typename T, typename Base>
00429 struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Native_Or_Checked<From>::value>::type> {
00430 typedef Simple_Restriction_Integer_Modulo<T> type;
00431 static const type& get(const From& x) {
00432 static const type integer(0, 1);
00433 static const type not_integer(0, 0);
00434 if (is_integer(x))
00435 return integer;
00436 else
00437 return not_integer;
00438 }
00439 };
00440
00441 template <typename From, typename T, typename Base>
00442 struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_None_Base, typename From::info_type>::value>::type> {
00443 typedef Simple_Restriction_Integer_Modulo<T> type;
00444 static const type& get(const From& x) {
00445 static const type integer(0, 1);
00446 static const type not_integer(0, 0);
00447 if (x.is_singleton() && is_integer(x.lower()))
00448 return integer;
00449 else
00450 return not_integer;
00451 }
00452 };
00453
00454 template <typename From, typename T, typename Base>
00455 struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, typename From::info_type>::value>::type> {
00456 typedef Simple_Restriction_Integer_Modulo<T> type;
00457 static const type& get(const From& x) {
00458 static const type integer(0, 1);
00459 static const type not_integer(0, 0);
00460 if (x.info().get_integer())
00461 return integer;
00462 else
00463 return not_integer;
00464 }
00465 };
00466
00467 template <typename From, typename T, typename Base>
00468 struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, typename From::info_type>::value>::type> {
00469 typedef Interval_Restriction_Integer_Modulo<T, Base> type;
00470 static const type& get(const From& x) {
00471 return x.info();
00472 }
00473 };
00474
00475 template <typename T1, typename T2>
00476 inline typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, T1>::value && Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, T2>::value, bool>::type
00477 eq_restriction(const T1& x, const T2& y) {
00478 return x.remainder == y.remainder
00479 && x.divisor == y.divisor;
00480 }
00481
00482 template <typename T1, typename T2>
00483 inline typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, T1>::value && Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, T2>::value, bool>::type
00484 contains_restriction(const T1& x, const T2& y) {
00485 if (x.divisor == 0)
00486 return true;
00487 if (y.divisor == 0)
00488 return false;
00489 if (x.divisor == y.divisor)
00490 return x.remainder == y.remainder;
00491 PPL_DIRTY_TEMP(typename T1::modulo_type, v);
00492 Result r;
00493 r = rem_assign_r(v, y.divisor, x.divisor, ROUND_NOT_NEEDED);
00494 PPL_ASSERT(r == V_EQ);
00495 if (v != 0)
00496 return false;
00497 r = rem_assign_r(v, y.remainder, x.divisor, ROUND_NOT_NEEDED);
00498 PPL_ASSERT(r == V_EQ);
00499 return v == x.remainder;
00500 }
00501
00502 template <typename T, typename Base>
00503 inline bool
00504 set_unrestricted(Interval_Restriction_Integer_Modulo<T, Base>& to) {
00505 to.remainder = 0;
00506 to.divisor = 0;
00507 return true;
00508 }
00509
00510 template <typename T, typename Base>
00511 inline bool
00512 set_integer(Interval_Restriction_Integer_Modulo<T, Base>& to) {
00513 to.remainder = 0;
00514 to.divisor = 1;
00515 return true;
00516 }
00517
00518 template <typename T, typename Base, typename From>
00519 inline bool
00520 assign_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From& x) {
00521 to.remainder = Restriction_Integer_Modulo<From, T, Base>::get(x).remainder;
00522 to.divisor = Restriction_Integer_Modulo<From, T, Base>::get(x).divisor;
00523 return true;
00524 }
00525
00526 template <typename T, typename Base, typename From1, typename From2>
00527 inline bool
00528 join_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
00529 typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
00530 const typename Rx::type& rx = Rx::get(x);
00531 if (rx.divisor == 0)
00532 return set_unrestricted(to);
00533 typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
00534 const typename Ry::type& ry = Ry::get(y);
00535 if (ry.divisor == 0)
00536 return set_unrestricted(to);
00537 else if (rx.divisor == 1 && ry.divisor == 1
00538 && is_singleton(x) && is_singleton(y)) {
00539 PPL_DIRTY_TEMP(typename Boundary_Value<From1>::type, a);
00540 PPL_DIRTY_TEMP(typename Boundary_Value<From2>::type, b);
00541 Result r;
00542 r = abs_assign_r(a, f_lower(x), ROUND_CHECK);
00543 if (r != V_EQ)
00544 return set_integer(to);
00545 r = abs_assign_r(b, f_lower(y), ROUND_CHECK);
00546 if (r != V_EQ)
00547 return set_integer(to);
00548 if (a > b)
00549 r = sub_assign_r(a, a, b, ROUND_CHECK);
00550 else
00551 r = sub_assign_r(a, b, a, ROUND_CHECK);
00552 if (r != V_EQ)
00553 return set_integer(to);
00554 r = assign_r(to.divisor, a, ROUND_CHECK);
00555 if (r != V_EQ)
00556 return set_integer(to);
00557 r = rem_assign_r(b, b, a, ROUND_CHECK);
00558 if (r != V_EQ)
00559 return set_integer(to);
00560 r = assign_r(to.remainder, b, ROUND_CHECK);
00561 if (r != V_EQ)
00562 return set_integer(to);
00563 }
00564 else if (contains_restriction(rx, ry)) {
00565 to.remainder = rx.remainder;
00566 to.divisor = rx.divisor;
00567 }
00568 else if (contains_restriction(ry, rx)) {
00569 to.remainder = ry.remainder;
00570 to.divisor = ry.divisor;
00571 }
00572 else
00573 return set_integer(to);
00574 return true;
00575 }
00576
00577 template <typename T, typename Base, typename From1, typename From2>
00578 inline bool
00579 intersect_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
00580 typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
00581 const typename Rx::type& rx = Rx::get(x);
00582 typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
00583 const typename Ry::type& ry = Ry::get(y);
00584 if (rx.divisor == 0) {
00585 to.remainder = ry.remainder;
00586 to.divisor = ry.divisor;
00587 return true;
00588 }
00589 if (ry.divisor == 0) {
00590 to.remainder = rx.remainder;
00591 to.divisor = rx.divisor;
00592 return true;
00593 }
00594 PPL_DIRTY_TEMP(T, g);
00595 Result r;
00596 r = gcd_assign_r(g, rx.divisor, ry.divisor, ROUND_DIRECT);
00597 if (r != V_EQ)
00598 return set_integer(to);
00599 PPL_DIRTY_TEMP(T, d);
00600 if (rx.remainder > ry.remainder)
00601 r = sub_assign_r(d, rx.remainder, ry.remainder, ROUND_DIRECT);
00602 else
00603 r = sub_assign_r(d, ry.remainder, rx.remainder, ROUND_DIRECT);
00604 if (r != V_EQ)
00605 return set_integer(to);
00606 r = div_assign_r(d, d, g, ROUND_DIRECT);
00607 if (r != V_EQ)
00608 return false;
00609 r = lcm_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_DIRECT);
00610 if (r != V_EQ)
00611 return set_integer(to);
00612
00613 return true;
00614 }
00615
00616 template <typename T, typename Base, typename From1, typename From2>
00617 inline bool
00618 diff_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
00619 const From1& x, const From2& y) {
00620
00621 return true;
00622 }
00623
00624 template <typename T, typename Base, typename From>
00625 inline bool
00626 neg_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
00627 const From& x) {
00628 return assign_restriction(to, x);
00629 }
00630
00631 template <typename T>
00632 inline void
00633 addmod(T& to, const T& x, const T& y, const T& to_m, const T& y_m) {
00634 Result r;
00635 if (std::numeric_limits<T>::is_bounded) {
00636 r = sub_assign_r(to, y_m, y, ROUND_NOT_NEEDED);
00637 PPL_ASSERT(r == V_EQ);
00638 if (x <= to) {
00639 r = add_assign_r(to, x, y, ROUND_NOT_NEEDED);
00640 PPL_ASSERT(r == V_EQ);
00641 }
00642 else {
00643 r = sub_assign_r(to, x, to, ROUND_NOT_NEEDED);
00644 PPL_ASSERT(r == V_EQ);
00645 }
00646 }
00647 else {
00648 r = add_assign_r(to, x, y, ROUND_NOT_NEEDED);
00649 PPL_ASSERT(r == V_EQ);
00650 }
00651 r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
00652 PPL_ASSERT(r == V_EQ);
00653 }
00654
00655 template <typename M, typename T>
00656 inline bool
00657 assign_rem(M& rem, const T& n, const M& div) {
00658 PPL_DIRTY_TEMP(T, divisor);
00659 PPL_DIRTY_TEMP(T, remainder);
00660 Result r;
00661 r = assign_r(divisor, div, ROUND_CHECK);
00662 if (r != V_EQ)
00663 return false;
00664 r = rem_assign_r(remainder, n, divisor, ROUND_CHECK);
00665 if (r != V_EQ)
00666 return false;
00667 if (sgn(remainder) < 0) {
00668 r = add_assign_r(remainder, remainder, divisor, ROUND_CHECK);
00669 if (r != V_EQ)
00670 return false;
00671 }
00672 r = assign_r(rem, remainder, ROUND_CHECK);
00673 return r == V_EQ;
00674 }
00675
00676
00677 template <typename T, typename Base, typename From1, typename From2>
00678 inline bool
00679 add_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
00680 typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
00681 const typename Rx::type& rx = Rx::get(x);
00682 if (rx.divisor == 0)
00683 return set_unrestricted(to);
00684 typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
00685 const typename Ry::type& ry = Ry::get(y);
00686 if (ry.divisor == 0)
00687 return set_unrestricted(to);
00688 Result r;
00689 PPL_DIRTY_TEMP(T, rem);
00690 if (is_singleton(x)) {
00691 if (is_singleton(y))
00692 return set_integer(to);
00693 if (!assign_rem(rem, f_lower(x), ry.divisor))
00694 return set_integer(to);
00695 r = assign_r(to.divisor, ry.divisor, ROUND_NOT_NEEDED);
00696 PPL_ASSERT(r == V_EQ);
00697 addmod(to.remainder, rem, ry.remainder, to.divisor, ry.divisor);
00698 }
00699 else if (is_singleton(y)) {
00700 if (!assign_rem(rem, f_lower(y), rx.divisor))
00701 return set_integer(to);
00702 r = assign_r(to.divisor, rx.divisor, ROUND_NOT_NEEDED);
00703 PPL_ASSERT(r == V_EQ);
00704 addmod(to.remainder, rx.remainder, rem, to.divisor, to.divisor);
00705 }
00706 else {
00707 r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
00708 PPL_ASSERT(r == V_EQ);
00709 addmod(to.remainder, rx.remainder, ry.remainder, to.divisor, ry.divisor);
00710 }
00711 return true;
00712 }
00713
00714 template <typename T>
00715 inline void
00716 submod(T& to, const T& x, const T& y, const T& to_m, const T& y_m) {
00717 Result r;
00718 if (x >= y) {
00719 r = sub_assign_r(to, x, y, ROUND_NOT_NEEDED);
00720 PPL_ASSERT(r == V_EQ);
00721 }
00722 else {
00723 r = sub_assign_r(to, y_m, y, ROUND_NOT_NEEDED);
00724 PPL_ASSERT(r == V_EQ);
00725 r = add_assign_r(to, x, to, ROUND_NOT_NEEDED);
00726 PPL_ASSERT(r == V_EQ);
00727 }
00728 r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
00729 PPL_ASSERT(r == V_EQ);
00730 }
00731
00732 template <typename T, typename Base, typename From1, typename From2>
00733 inline bool
00734 sub_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
00735 typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
00736 const typename Rx::type& rx = Rx::get(x);
00737 if (rx.divisor == 0)
00738 return set_unrestricted(to);
00739 typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
00740 const typename Ry::type& ry = Ry::get(y);
00741 if (ry.divisor == 0)
00742 return set_unrestricted(to);
00743 Result r;
00744 PPL_DIRTY_TEMP(T, rem);
00745 if (is_singleton(x)) {
00746 if (is_singleton(y))
00747 return set_integer(to);
00748 if (!assign_rem(rem, f_lower(x), ry.divisor))
00749 return set_integer(to);
00750 r = assign_r(to.divisor, ry.divisor, ROUND_NOT_NEEDED);
00751 PPL_ASSERT(r == V_EQ);
00752 submod(to.remainder, rem, ry.remainder, to.divisor, ry.divisor);
00753 }
00754 else if (is_singleton(y)) {
00755 if (!assign_rem(rem, f_lower(y), rx.divisor))
00756 return set_integer(to);
00757 r = assign_r(to.divisor, rx.divisor, ROUND_NOT_NEEDED);
00758 PPL_ASSERT(r == V_EQ);
00759 submod(to.remainder, rx.remainder, rem, to.divisor, to.divisor);
00760 }
00761 else {
00762 r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
00763 PPL_ASSERT(r == V_EQ);
00764 submod(to.remainder, rx.remainder, ry.remainder, to.divisor, ry.divisor);
00765 }
00766 return true;
00767 }
00768
00769 template <typename T>
00770 inline void
00771 mulmod(T& to, const T& x, const T& y, const T& to_m) {
00772 Result r;
00773 if (std::numeric_limits<T>::is_bounded) {
00774 PPL_DIRTY_TEMP0(mpz_class, a);
00775 PPL_DIRTY_TEMP0(mpz_class, b);
00776 r = assign_r(a, x, ROUND_NOT_NEEDED);
00777 PPL_ASSERT(r == V_EQ);
00778 r = assign_r(b, y, ROUND_NOT_NEEDED);
00779 PPL_ASSERT(r == V_EQ);
00780 r = mul_assign_r(a, a, b, ROUND_NOT_NEEDED);
00781 PPL_ASSERT(r == V_EQ);
00782 r = assign_r(b, to_m, ROUND_NOT_NEEDED);
00783 PPL_ASSERT(r == V_EQ);
00784 r = rem_assign_r(a, a, b, ROUND_NOT_NEEDED);
00785 PPL_ASSERT(r == V_EQ);
00786 r = assign_r(to, a, ROUND_NOT_NEEDED);
00787 PPL_ASSERT(r == V_EQ);
00788 }
00789 else {
00790 r = mul_assign_r(to, x, y, ROUND_NOT_NEEDED);
00791 PPL_ASSERT(r == V_EQ);
00792 r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
00793 PPL_ASSERT(r == V_EQ);
00794 }
00795 }
00796
00797
00798 template <typename T, typename Base, typename From1, typename From2>
00799 inline bool
00800 mul_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
00801 typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
00802 const typename Rx::type& rx = Rx::get(x);
00803 if (rx.divisor == 0)
00804 return set_unrestricted(to);
00805 typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
00806 const typename Ry::type& ry = Ry::get(y);
00807 if (ry.divisor == 0)
00808 return set_unrestricted(to);
00809 Result r;
00810 PPL_DIRTY_TEMP(T, mul);
00811 if (is_singleton(x)) {
00812 if (is_singleton(y))
00813 return set_integer(to);
00814 PPL_DIRTY_TEMP(typename Boundary_Value<From1>::type, n);
00815 r = abs_assign_r(n, f_lower(x), ROUND_CHECK);
00816 if (r != V_EQ)
00817 return set_integer(to);
00818 r = assign_r(mul, n, ROUND_CHECK);
00819 if (r != V_EQ)
00820 return set_integer(to);
00821 r = mul_assign_r(to.remainder, mul, ry.remainder, ROUND_NOT_NEEDED);
00822 if (r != V_EQ)
00823 return set_integer(to);
00824 r = mul_assign_r(to.divisor, mul, ry.divisor, ROUND_NOT_NEEDED);
00825 if (r != V_EQ)
00826 return set_integer(to);
00827 }
00828 else if (is_singleton(y)) {
00829 PPL_DIRTY_TEMP(typename Boundary_Value<From2>::type, n);
00830 r = abs_assign_r(n, f_lower(y), ROUND_CHECK);
00831 if (r != V_EQ)
00832 return set_integer(to);
00833 r = assign_r(mul, n, ROUND_CHECK);
00834 if (r != V_EQ)
00835 return set_integer(to);
00836 r = mul_assign_r(to.remainder, rx.remainder, mul, ROUND_NOT_NEEDED);
00837 if (r != V_EQ)
00838 return set_integer(to);
00839 r = mul_assign_r(to.divisor, rx.divisor, mul, ROUND_NOT_NEEDED);
00840 if (r != V_EQ)
00841 return set_integer(to);
00842 }
00843 else {
00844 r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
00845 PPL_ASSERT(r == V_EQ);
00846 mulmod(to.remainder, rx.remainder, ry.remainder, to.divisor);
00847 }
00848 return true;
00849 }
00850
00851 template <typename T, typename Base, typename From1, typename From2>
00852 inline bool
00853 div_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
00854 const From1& x, const From2& y) {
00855 if (is_singleton(y)) {
00856 if (is_singleton(x)) {
00857
00858 }
00859 }
00860 return set_unrestricted(to);
00861 }
00862
00863 template <typename T, typename Base>
00864 inline void
00865 output_restriction(std::ostream& s, const Interval_Restriction_Integer_Modulo<T, Base>& x) {
00866 if (x.divisor == 1)
00867 s << "i";
00868 else if (x.divisor != 0)
00869 s << "{" << x.remainder << "%" << x.divisor << "}";
00870 }
00871
00872 }
00873
00874 #endif // !defined(PPL_Interval_Info_defs_hh)