summaryrefslogtreecommitdiff
path: root/src/Interval_Restriction.defs.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/Interval_Restriction.defs.hh')
-rw-r--r--src/Interval_Restriction.defs.hh874
1 files changed, 874 insertions, 0 deletions
diff --git a/src/Interval_Restriction.defs.hh b/src/Interval_Restriction.defs.hh
new file mode 100644
index 000000000..a912454ea
--- /dev/null
+++ b/src/Interval_Restriction.defs.hh
@@ -0,0 +1,874 @@
+/* Interval_Restriction class declaration.
+ Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
+ Copyright (C) 2010-2011 BUGSENG srl (http://bugseng.com)
+
+This file is part of the Parma Polyhedra Library (PPL).
+
+The PPL is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+The PPL is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
+
+For the most up-to-date information see the Parma Polyhedra Library
+site: http://www.cs.unipr.it/ppl/ . */
+
+#ifndef PPL_Interval_Restriction_defs_hh
+#define PPL_Interval_Restriction_defs_hh 1
+
+#include "meta_programming.hh"
+#include "Slow_Copy.hh"
+#include "assign_or_swap.hh"
+#include "Result.defs.hh"
+#include "Rounding_Dir.defs.hh"
+#include "Checked_Number.defs.hh"
+
+namespace Parma_Polyhedra_Library {
+
+struct Interval_Base;
+
+template <typename T, typename Enable = void>
+struct Boundary_Value {
+ typedef T type;
+};
+
+template <typename T>
+struct Boundary_Value<T, typename Enable_If<Is_Same_Or_Derived<Interval_Base, T>::value>::type > {
+ typedef typename T::boundary_type type;
+};
+
+class Interval_Restriction_None_Base {
+public:
+ bool has_restriction() const {
+ return false;
+ }
+ void normalize() const {
+ }
+ template <typename T>
+ Result restrict(Rounding_Dir, T&, Result dir) const {
+ return dir;
+ }
+};
+
+inline bool
+eq_restriction(const Interval_Restriction_None_Base&, const Interval_Restriction_None_Base) {
+ return true;
+}
+
+template <typename T>
+inline bool
+contains_restriction(const Interval_Restriction_None_Base&, const T&) {
+ return true;
+}
+
+template <typename T>
+inline bool
+assign_restriction(Interval_Restriction_None_Base&, const T&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+join_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+intersect_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+diff_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T>
+inline bool
+neg_restriction(Interval_Restriction_None_Base&, const T&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+add_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+sub_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+mul_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+template <typename T1, typename T2>
+inline bool
+div_restriction(Interval_Restriction_None_Base&, const T1&, const T2&) {
+ return true;
+}
+
+inline void
+output_restriction(std::ostream&, const Interval_Restriction_None_Base&) {
+}
+
+template <typename Base>
+class Interval_Restriction_None : public Interval_Restriction_None_Base,
+ public Base {
+public:
+ Interval_Restriction_None() {
+ }
+ template <typename T>
+ Interval_Restriction_None(const T& init)
+ : Base(init) {
+ }
+};
+
+class Interval_Restriction_Integer_Base {
+};
+
+template <typename Base>
+class Interval_Restriction_Integer : public Interval_Restriction_Integer_Base, public Base {
+public:
+ Interval_Restriction_Integer() {
+ }
+ void set_integer(bool v = true) {
+ return set_bit(Base::bitset, integer_bit, v);
+ }
+ bool get_integer() const {
+ return get_bit(Base::bitset, integer_bit);
+ }
+
+ const_int_nodef(integer_bit, Base::next_bit);
+ const_int_nodef(next_bit, integer_bit + 1);
+ bool has_restriction() const {
+ return get_integer();
+ }
+ void normalize() const {
+ }
+ template <typename T>
+ Result restrict(Rounding_Dir rdir, T& x, Result dir) const {
+ if (!has_restriction())
+ return dir;
+ switch (dir) {
+ case V_GT:
+ if (is_integer(x))
+ return add_assign_r(x, x, static_cast<T>(1), rdir);
+ /* Fall through */
+ case V_GE:
+ return ceil_assign_r(x, x, rdir);
+ case V_LT:
+ if (is_integer(x))
+ return sub_assign_r(x, x, static_cast<T>(1), rdir);
+ /* Fall through */
+ case V_LE:
+ return floor_assign_r(x, x, rdir);
+ default:
+ PPL_ASSERT(false);
+ return dir;
+ }
+ }
+};
+
+class Simple_Restriction_Integer : public Interval_Restriction_Integer_Base {
+public:
+ Simple_Restriction_Integer(bool i)
+ : integer(i) {
+ }
+ bool get_integer() const {
+ return integer;
+ }
+private:
+ bool integer;
+};
+
+template <typename From, typename Base, typename Enable = void>
+struct Restriction_Integer;
+
+template <typename From, typename Base>
+struct Restriction_Integer<From, Base, typename Enable_If<Is_Native_Or_Checked<From>::value>::type> {
+ typedef Simple_Restriction_Integer type;
+ static type get(const From& x) {
+ return Simple_Restriction_Integer(is_integer(x));
+ }
+};
+
+template <typename From, typename Base>
+struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_None_Base, typename From::info_type>::value>::type> {
+ typedef Simple_Restriction_Integer type;
+ static type get(const From& x) {
+ return Simple_Restriction_Integer(x.is_singleton() && is_integer(x.lower()));
+ }
+};
+
+template <typename From, typename Base>
+struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, typename From::info_type>::value>::type> {
+ typedef Interval_Restriction_Integer<Base> type;
+ static const type& get(const From& x) {
+ return x.info();
+ }
+};
+
+template <typename T1, typename T2>
+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
+eq_restriction(const T1& x, const T2& y) {
+ return x.get_integer() == y.get_integer();
+}
+
+template <typename T1, typename T2>
+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
+contains_restriction(const T1& x, const T2& y) {
+ return !x.get_integer() || y.get_integer();
+}
+
+template <typename Base, typename From>
+inline bool
+assign_restriction(Interval_Restriction_Integer<Base>& to, const From& x) {
+ to.set_integer(Restriction_Integer<From, Base>::get(x).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+join_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
+ && Restriction_Integer<From2, Base>::get(y).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+intersect_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
+ || Restriction_Integer<From2, Base>::get(y).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+diff_restriction(Interval_Restriction_Integer<Base>& to,
+ const From1& x, const From2&) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer());
+ return true;
+}
+
+template <typename Base, typename From>
+inline bool
+neg_restriction(Interval_Restriction_Integer<Base>& to, const From& x) {
+ to.set_integer(Restriction_Integer<From, Base>::get(x).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+add_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
+ && Restriction_Integer<From2, Base>::get(y).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+sub_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
+ && Restriction_Integer<From2, Base>::get(y).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+mul_restriction(Interval_Restriction_Integer<Base>& to, const From1& x, const From2& y) {
+ to.set_integer(Restriction_Integer<From1, Base>::get(x).get_integer()
+ && Restriction_Integer<From2, Base>::get(y).get_integer());
+ return true;
+}
+
+template <typename Base, typename From1, typename From2>
+inline bool
+div_restriction(Interval_Restriction_Integer<Base>& to, const From1&, const From2&) {
+ to.set_integer(false);
+ return true;
+}
+
+template <typename Base>
+inline void
+output_restriction(std::ostream& s, const Interval_Restriction_Integer<Base>& x) {
+ if (x.get_integer())
+ s << "i";
+}
+
+class Interval_Restriction_Integer_Modulo_Base {
+};
+
+template <typename T, typename Base>
+class Interval_Restriction_Integer_Modulo : public Interval_Restriction_Integer_Modulo_Base, public Base {
+public:
+ PPL_COMPILE_TIME_CHECK(std::numeric_limits<T>::is_exact,
+ "type for modulo values must be exact");
+ Interval_Restriction_Integer_Modulo() {
+ // FIXME: would we have speed benefits with uninitialized info?
+ // (Dirty_Temp)
+ clear();
+ }
+ bool has_restriction() const {
+ return divisor != 0;
+ }
+ void clear() {
+ remainder = 0;
+ divisor = 0;
+ Base::clear();
+ }
+ void normalize() const {
+ }
+ template <typename V>
+ Result restrict(Rounding_Dir rdir, V& x, Result dir) const {
+ if (!has_restriction())
+ return dir;
+ PPL_DIRTY_TEMP(V, n);
+ PPL_DIRTY_TEMP(V, div);
+ Result r;
+ r = assign_r(div, divisor, ROUND_CHECK);
+ PPL_ASSERT(r == V_EQ);
+ int s;
+ r = rem_assign_r(n, x, div, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ s = sgn(n);
+ switch (dir) {
+ case V_GT:
+ if (s >= 0) {
+ r = sub_assign_r(n, div, n, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ return add_assign_r(x, x, n, rdir);
+ }
+ else
+ return sub_assign_r(x, x, n, rdir);
+ case V_GE:
+ if (s > 0) {
+ r = sub_assign_r(n, div, n, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ return add_assign_r(x, x, n, rdir);
+ }
+ else if (s < 0)
+ return sub_assign_r(x, x, n, rdir);
+ else
+ return V_EQ;
+ case V_LT:
+ if (s <= 0) {
+ r = add_assign_r(n, div, n, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ return sub_assign_r(x, x, n, rdir);
+ }
+ else
+ return sub_assign_r(x, x, n, rdir);
+ case V_LE:
+ if (s < 0) {
+ r = add_assign_r(n, div, n, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ return sub_assign_r(x, x, n, rdir);
+ }
+ else if (s > 0)
+ return sub_assign_r(x, x, n, rdir);
+ else
+ return V_EQ;
+ default:
+ PPL_ASSERT(false);
+ return dir;
+ }
+ }
+ void assign_or_swap(Interval_Restriction_Integer_Modulo& x) {
+ Parma_Polyhedra_Library::assign_or_swap(remainder, x.remainder);
+ Parma_Polyhedra_Library::assign_or_swap(divisor, x.divisor);
+ }
+ typedef T modulo_type;
+ T remainder;
+ T divisor;
+};
+
+template <typename T, typename Base>
+struct Slow_Copy<Interval_Restriction_Integer_Modulo<T, Base> > : public Bool<Slow_Copy<T>::value> {};
+
+
+template <typename From, typename Base>
+struct Restriction_Integer<From, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Modulo_Base, typename From::info_type>::value>::type> {
+ typedef Simple_Restriction_Integer type;
+ static type get(const From& x) {
+ return Simple_Restriction_Integer(x.info().divisor != 0);
+ }
+};
+
+template <typename T>
+struct Simple_Restriction_Integer_Modulo : public Interval_Restriction_Integer_Modulo_Base {
+ template <typename From>
+ Simple_Restriction_Integer_Modulo(const From& r, const From& d)
+ : remainder(r), divisor(d) {
+ }
+ typedef T modulo_type;
+ T remainder;
+ T divisor;
+};
+
+template <typename From, typename T, typename Base, typename Enable = void>
+struct Restriction_Integer_Modulo;
+
+template <typename From, typename T, typename Base>
+struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Native_Or_Checked<From>::value>::type> {
+ typedef Simple_Restriction_Integer_Modulo<T> type;
+ static const type& get(const From& x) {
+ static const type integer(0, 1);
+ static const type not_integer(0, 0);
+ if (is_integer(x))
+ return integer;
+ else
+ return not_integer;
+ }
+};
+
+template <typename From, typename T, typename Base>
+struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_None_Base, typename From::info_type>::value>::type> {
+ typedef Simple_Restriction_Integer_Modulo<T> type;
+ static const type& get(const From& x) {
+ static const type integer(0, 1);
+ static const type not_integer(0, 0);
+ if (x.is_singleton() && is_integer(x.lower()))
+ return integer;
+ else
+ return not_integer;
+ }
+};
+
+template <typename From, typename T, typename Base>
+struct Restriction_Integer_Modulo<From, T, Base, typename Enable_If<Is_Same_Or_Derived<Interval_Restriction_Integer_Base, typename From::info_type>::value>::type> {
+ typedef Simple_Restriction_Integer_Modulo<T> type;
+ static const type& get(const From& x) {
+ static const type integer(0, 1);
+ static const type not_integer(0, 0);
+ if (x.info().get_integer())
+ return integer;
+ else
+ return not_integer;
+ }
+};
+
+template <typename From, typename T, typename Base>
+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> {
+ typedef Interval_Restriction_Integer_Modulo<T, Base> type;
+ static const type& get(const From& x) {
+ return x.info();
+ }
+};
+
+template <typename T1, typename T2>
+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
+eq_restriction(const T1& x, const T2& y) {
+ return x.remainder == y.remainder
+ && x.divisor == y.divisor;
+}
+
+template <typename T1, typename T2>
+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
+contains_restriction(const T1& x, const T2& y) {
+ if (x.divisor == 0)
+ return true;
+ if (y.divisor == 0)
+ return false;
+ if (x.divisor == y.divisor)
+ return x.remainder == y.remainder;
+ PPL_DIRTY_TEMP(typename T1::modulo_type, v);
+ Result r;
+ r = rem_assign_r(v, y.divisor, x.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ if (v != 0)
+ return false;
+ r = rem_assign_r(v, y.remainder, x.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ return v == x.remainder;
+}
+
+template <typename T, typename Base>
+inline bool
+set_unrestricted(Interval_Restriction_Integer_Modulo<T, Base>& to) {
+ to.remainder = 0;
+ to.divisor = 0;
+ return true;
+}
+
+template <typename T, typename Base>
+inline bool
+set_integer(Interval_Restriction_Integer_Modulo<T, Base>& to) {
+ to.remainder = 0;
+ to.divisor = 1;
+ return true;
+}
+
+template <typename T, typename Base, typename From>
+inline bool
+assign_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From& x) {
+ to.remainder = Restriction_Integer_Modulo<From, T, Base>::get(x).remainder;
+ to.divisor = Restriction_Integer_Modulo<From, T, Base>::get(x).divisor;
+ return true;
+}
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+join_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
+ typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
+ const typename Rx::type& rx = Rx::get(x);
+ if (rx.divisor == 0)
+ return set_unrestricted(to);
+ typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
+ const typename Ry::type& ry = Ry::get(y);
+ if (ry.divisor == 0)
+ return set_unrestricted(to);
+ else if (rx.divisor == 1 && ry.divisor == 1
+ && is_singleton(x) && is_singleton(y)) {
+ PPL_DIRTY_TEMP(typename Boundary_Value<From1>::type, a);
+ PPL_DIRTY_TEMP(typename Boundary_Value<From2>::type, b);
+ Result r;
+ r = abs_assign_r(a, f_lower(x), ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = abs_assign_r(b, f_lower(y), ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ if (a > b)
+ r = sub_assign_r(a, a, b, ROUND_CHECK);
+ else
+ r = sub_assign_r(a, b, a, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = assign_r(to.divisor, a, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = rem_assign_r(b, b, a, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = assign_r(to.remainder, b, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ }
+ else if (contains_restriction(rx, ry)) {
+ to.remainder = rx.remainder;
+ to.divisor = rx.divisor;
+ }
+ else if (contains_restriction(ry, rx)) {
+ to.remainder = ry.remainder;
+ to.divisor = ry.divisor;
+ }
+ else
+ return set_integer(to);
+ return true;
+}
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+intersect_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
+ typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
+ const typename Rx::type& rx = Rx::get(x);
+ typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
+ const typename Ry::type& ry = Ry::get(y);
+ if (rx.divisor == 0) {
+ to.remainder = ry.remainder;
+ to.divisor = ry.divisor;
+ return true;
+ }
+ if (ry.divisor == 0) {
+ to.remainder = rx.remainder;
+ to.divisor = rx.divisor;
+ return true;
+ }
+ PPL_DIRTY_TEMP(T, g);
+ Result r;
+ r = gcd_assign_r(g, rx.divisor, ry.divisor, ROUND_DIRECT);
+ if (r != V_EQ)
+ return set_integer(to);
+ PPL_DIRTY_TEMP(T, d);
+ if (rx.remainder > ry.remainder)
+ r = sub_assign_r(d, rx.remainder, ry.remainder, ROUND_DIRECT);
+ else
+ r = sub_assign_r(d, ry.remainder, rx.remainder, ROUND_DIRECT);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = div_assign_r(d, d, g, ROUND_DIRECT);
+ if (r != V_EQ)
+ return false;
+ r = lcm_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_DIRECT);
+ if (r != V_EQ)
+ return set_integer(to);
+ // FIXME: to be completed
+ return true;
+}
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+diff_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
+ const From1& x, const From2& y) {
+ // FIXME: to be written
+ return true;
+}
+
+template <typename T, typename Base, typename From>
+inline bool
+neg_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
+ const From& x) {
+ return assign_restriction(to, x);
+}
+
+template <typename T>
+inline void
+addmod(T& to, const T& x, const T& y, const T& to_m, const T& y_m) {
+ Result r;
+ if (std::numeric_limits<T>::is_bounded) {
+ r = sub_assign_r(to, y_m, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ if (x <= to) {
+ r = add_assign_r(to, x, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ else {
+ r = sub_assign_r(to, x, to, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ }
+ else {
+ r = add_assign_r(to, x, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+}
+
+template <typename M, typename T>
+inline bool
+assign_rem(M& rem, const T& n, const M& div) {
+ PPL_DIRTY_TEMP(T, divisor);
+ PPL_DIRTY_TEMP(T, remainder);
+ Result r;
+ r = assign_r(divisor, div, ROUND_CHECK);
+ if (r != V_EQ)
+ return false;
+ r = rem_assign_r(remainder, n, divisor, ROUND_CHECK);
+ if (r != V_EQ)
+ return false;
+ if (sgn(remainder) < 0) {
+ r = add_assign_r(remainder, remainder, divisor, ROUND_CHECK);
+ if (r != V_EQ)
+ return false;
+ }
+ r = assign_r(rem, remainder, ROUND_CHECK);
+ return r == V_EQ;
+}
+
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+add_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
+ typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
+ const typename Rx::type& rx = Rx::get(x);
+ if (rx.divisor == 0)
+ return set_unrestricted(to);
+ typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
+ const typename Ry::type& ry = Ry::get(y);
+ if (ry.divisor == 0)
+ return set_unrestricted(to);
+ Result r;
+ PPL_DIRTY_TEMP(T, rem);
+ if (is_singleton(x)) {
+ if (is_singleton(y))
+ return set_integer(to);
+ if (!assign_rem(rem, f_lower(x), ry.divisor))
+ return set_integer(to);
+ r = assign_r(to.divisor, ry.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ addmod(to.remainder, rem, ry.remainder, to.divisor, ry.divisor);
+ }
+ else if (is_singleton(y)) {
+ if (!assign_rem(rem, f_lower(y), rx.divisor))
+ return set_integer(to);
+ r = assign_r(to.divisor, rx.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ addmod(to.remainder, rx.remainder, rem, to.divisor, to.divisor);
+ }
+ else {
+ r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ addmod(to.remainder, rx.remainder, ry.remainder, to.divisor, ry.divisor);
+ }
+ return true;
+}
+
+template <typename T>
+inline void
+submod(T& to, const T& x, const T& y, const T& to_m, const T& y_m) {
+ Result r;
+ if (x >= y) {
+ r = sub_assign_r(to, x, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ else {
+ r = sub_assign_r(to, y_m, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = add_assign_r(to, x, to, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+}
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+sub_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
+ typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
+ const typename Rx::type& rx = Rx::get(x);
+ if (rx.divisor == 0)
+ return set_unrestricted(to);
+ typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
+ const typename Ry::type& ry = Ry::get(y);
+ if (ry.divisor == 0)
+ return set_unrestricted(to);
+ Result r;
+ PPL_DIRTY_TEMP(T, rem);
+ if (is_singleton(x)) {
+ if (is_singleton(y))
+ return set_integer(to);
+ if (!assign_rem(rem, f_lower(x), ry.divisor))
+ return set_integer(to);
+ r = assign_r(to.divisor, ry.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ submod(to.remainder, rem, ry.remainder, to.divisor, ry.divisor);
+ }
+ else if (is_singleton(y)) {
+ if (!assign_rem(rem, f_lower(y), rx.divisor))
+ return set_integer(to);
+ r = assign_r(to.divisor, rx.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ submod(to.remainder, rx.remainder, rem, to.divisor, to.divisor);
+ }
+ else {
+ r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ submod(to.remainder, rx.remainder, ry.remainder, to.divisor, ry.divisor);
+ }
+ return true;
+}
+
+template <typename T>
+inline void
+mulmod(T& to, const T& x, const T& y, const T& to_m) {
+ Result r;
+ if (std::numeric_limits<T>::is_bounded) {
+ PPL_DIRTY_TEMP0(mpz_class, a);
+ PPL_DIRTY_TEMP0(mpz_class, b);
+ r = assign_r(a, x, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = assign_r(b, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = mul_assign_r(a, a, b, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = assign_r(b, to_m, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = rem_assign_r(a, a, b, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = assign_r(to, a, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+ else {
+ r = mul_assign_r(to, x, y, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ r = rem_assign_r(to, to, to_m, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ }
+}
+
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+mul_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to, const From1& x, const From2& y) {
+ typedef Restriction_Integer_Modulo<From1, T, Base> Rx;
+ const typename Rx::type& rx = Rx::get(x);
+ if (rx.divisor == 0)
+ return set_unrestricted(to);
+ typedef Restriction_Integer_Modulo<From2, T, Base> Ry;
+ const typename Ry::type& ry = Ry::get(y);
+ if (ry.divisor == 0)
+ return set_unrestricted(to);
+ Result r;
+ PPL_DIRTY_TEMP(T, mul);
+ if (is_singleton(x)) {
+ if (is_singleton(y))
+ return set_integer(to);
+ PPL_DIRTY_TEMP(typename Boundary_Value<From1>::type, n);
+ r = abs_assign_r(n, f_lower(x), ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = assign_r(mul, n, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = mul_assign_r(to.remainder, mul, ry.remainder, ROUND_NOT_NEEDED);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = mul_assign_r(to.divisor, mul, ry.divisor, ROUND_NOT_NEEDED);
+ if (r != V_EQ)
+ return set_integer(to);
+ }
+ else if (is_singleton(y)) {
+ PPL_DIRTY_TEMP(typename Boundary_Value<From2>::type, n);
+ r = abs_assign_r(n, f_lower(y), ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = assign_r(mul, n, ROUND_CHECK);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = mul_assign_r(to.remainder, rx.remainder, mul, ROUND_NOT_NEEDED);
+ if (r != V_EQ)
+ return set_integer(to);
+ r = mul_assign_r(to.divisor, rx.divisor, mul, ROUND_NOT_NEEDED);
+ if (r != V_EQ)
+ return set_integer(to);
+ }
+ else {
+ r = gcd_assign_r(to.divisor, rx.divisor, ry.divisor, ROUND_NOT_NEEDED);
+ PPL_ASSERT(r == V_EQ);
+ mulmod(to.remainder, rx.remainder, ry.remainder, to.divisor);
+ }
+ return true;
+}
+
+template <typename T, typename Base, typename From1, typename From2>
+inline bool
+div_restriction(Interval_Restriction_Integer_Modulo<T, Base>& to,
+ const From1& x, const From2& y) {
+ if (is_singleton(y)) {
+ if (is_singleton(x)) {
+ // FIXME: to be written
+ }
+ }
+ return set_unrestricted(to);
+}
+
+template <typename T, typename Base>
+inline void
+output_restriction(std::ostream& s, const Interval_Restriction_Integer_Modulo<T, Base>& x) {
+ if (x.divisor == 1)
+ s << "i";
+ else if (x.divisor != 0)
+ s << "{" << x.remainder << "%" << x.divisor << "}";
+}
+
+}
+
+#endif // !defined(PPL_Interval_Info_defs_hh)