PPL  1.2
intervals_defs.hh
Go to the documentation of this file.
1 /* Helper classes for intervals.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_intervals_defs_hh
25 #define PPL_intervals_defs_hh 1
26 
27 #include "Checked_Number_defs.hh"
28 #include "assertions.hh"
29 #include <cstdlib>
30 
31 namespace Parma_Polyhedra_Library {
32 
33 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
34 
36 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
37 enum I_Result {
38 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
39 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
41  I_EMPTY = 1U,
42 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
43 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
46 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
47 
50 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
51  I_SOME = 4U,
52 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
53 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
55  I_UNIVERSE = 8U,
56 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
57 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
60 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
61 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
64 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
65 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
68 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
69 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
72 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
73 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
75  I_EXACT = 16,
76 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
77 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
79  I_INEXACT = 32,
80 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
81 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
83  I_CHANGED = 64,
84 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
85 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
87  I_UNCHANGED = 128,
88 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
89 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
92 };
93 
94 inline I_Result
96  return static_cast<I_Result>(static_cast<unsigned>(a)
97  | static_cast<unsigned>(b));
98 }
99 
100 inline I_Result
102  return static_cast<I_Result>(static_cast<unsigned>(a)
103  & static_cast<unsigned>(b));
104 }
105 
106 inline I_Result
108  return static_cast<I_Result>(static_cast<unsigned>(a)
109  & ~static_cast<unsigned>(b));
110 }
111 
112 template <typename Criteria, typename T>
113 struct Use_By_Ref;
114 
115 struct Use_Slow_Copy;
116 template <typename T>
117 struct Use_By_Ref<Use_Slow_Copy, T>
118  : public Bool<Slow_Copy<T>::value> {
119 };
120 
121 struct By_Value;
122 template <typename T>
123 struct Use_By_Ref<By_Value, T>
124  : public False {
125 };
126 
127 struct By_Ref;
128 template <typename T>
129 struct Use_By_Ref<By_Ref, T>
130  : public True {
131 };
132 
133 template <typename T, typename Criteria = Use_Slow_Copy, typename Enable = void>
135 
136 template <typename T, typename Criteria>
137 class Val_Or_Ref<T, Criteria,
138  typename Enable_If<!Use_By_Ref<Criteria, T>::value>::type> {
139  T value;
140 public:
141  typedef T Arg_Type;
142  typedef T Return_Type;
144  : value() {
145  }
146  explicit Val_Or_Ref(Arg_Type v, bool = false)
147  : value(v) {
148  }
149  Val_Or_Ref& operator=(Arg_Type v) {
150  value = v;
151  return *this;
152  }
153  void set(Arg_Type v, bool = false) {
154  value = v;
155  }
156  Return_Type get() const {
157  return value;
158  }
159  operator Return_Type() const {
160  return get();
161  }
162 };
163 
164 template <typename T, typename Criteria>
165 class Val_Or_Ref<T, Criteria,
166  typename Enable_If<Use_By_Ref<Criteria, T>::value>::type> {
167  const T* ptr;
168 public:
169  typedef T& Arg_Type;
170  typedef const T& Return_Type;
172  : ptr(0) {
173  }
174  explicit Val_Or_Ref(Arg_Type v)
175  : ptr(&v) {
176  }
177  Val_Or_Ref(const T& v, bool)
178  : ptr(&v) {
179  }
180  Val_Or_Ref& operator=(Arg_Type v) {
181  ptr = &v;
182  return *this;
183  }
184  void set(Arg_Type v) {
185  ptr = &v;
186  }
187  void set(const T& v, bool) {
188  ptr = &v;
189  }
190  Return_Type get() const {
191  return *ptr;
192  }
193  operator Return_Type() const {
194  return get();
195  }
196 };
197 
199 };
200 
201 template <typename Derived>
203 public:
204  template <typename T>
205  Result convert_real(T& to) const {
206  const Derived& c = static_cast<const Derived&>(*this);
207  Result r = c.rel();
208  switch (r) {
209  case V_EMPTY:
210  case V_LGE:
211  return r;
212  case V_LE:
213  r = assign_r(to, c.value(), (ROUND_UP | ROUND_STRICT_RELATION));
214  r = result_relation_class(r);
215  if (r == V_EQ) {
216  return V_LE;
217  }
218  goto lt;
219  case V_LT:
220  r = assign_r(to, c.value(), ROUND_UP);
221  r = result_relation_class(r);
222  lt:
223  switch (r) {
224  case V_EMPTY:
225  case V_LT_PLUS_INFINITY:
226  case V_EQ_MINUS_INFINITY:
227  return r;
228  case V_LT:
229  case V_LE:
230  case V_EQ:
231  return V_LT;
232  default:
233  break;
234  }
235  break;
236  case V_GE:
237  r = assign_r(to, c.value(), (ROUND_DOWN | ROUND_STRICT_RELATION));
238  r = result_relation_class(r);
239  if (r == V_EQ) {
240  return V_GE;
241  }
242  goto gt;
243  case V_GT:
244  r = assign_r(to, c.value(), ROUND_DOWN);
245  r = result_relation_class(r);
246  gt:
247  switch (r) {
248  case V_EMPTY:
249  case V_GT_MINUS_INFINITY:
250  case V_EQ_PLUS_INFINITY:
251  return r;
252  case V_LT:
253  case V_LE:
254  case V_EQ:
255  return V_GT;
256  default:
257  break;
258  }
259  break;
260  case V_EQ:
261  r = assign_r(to, c.value(), ROUND_CHECK);
262  r = result_relation_class(r);
263  PPL_ASSERT(r != V_LT && r != V_GT);
264  if (r == V_EQ) {
265  return V_EQ;
266  }
267  else {
268  return V_EMPTY;
269  }
270  case V_NE:
271  r = assign_r(to, c.value(), ROUND_CHECK);
272  r = result_relation_class(r);
273  if (r == V_EQ) {
274  return V_NE;
275  }
276  else {
277  return V_LGE;
278  }
279  default:
280  break;
281  }
282  PPL_UNREACHABLE;
283  return V_EMPTY;
284  }
285  template <typename T>
286  Result convert_real(T& to1, Result& rel2, T& to2) const {
287  const Derived& c = static_cast<const Derived&>(*this);
288  Result rel1;
289  if (c.rel() != V_EQ) {
290  rel2 = convert(to2);
291  return V_LGE;
292  }
293  rel2 = assign_r(to2, c.value(), ROUND_UP);
294  rel2 = result_relation_class(rel2);
295  switch (rel2) {
296  case V_EMPTY:
297  case V_EQ_MINUS_INFINITY:
298  case V_EQ:
299  return V_LGE;
300  default:
301  break;
302  }
303  rel1 = assign_r(to1, c.value(), ROUND_DOWN);
304  rel1 = result_relation_class(rel1);
305  switch (rel1) {
306  case V_EQ:
307  PPL_ASSERT(rel2 == V_LE);
308  goto eq;
309  case V_EQ_PLUS_INFINITY:
310  case V_EMPTY:
311  rel2 = rel1;
312  return V_LGE;
313  case V_GE:
314  if (rel2 == V_LE && to1 == to2) {
315  eq:
316  rel2 = V_EQ;
317  return V_LGE;
318  }
319  /* Fall through*/
320  case V_GT:
321  case V_GT_MINUS_INFINITY:
322  return rel1;
323  default:
324  PPL_UNREACHABLE;
325  return V_EMPTY;
326  }
327  switch (rel2) {
328  case V_LE:
329  case V_LT:
330  case V_LT_PLUS_INFINITY:
331  return rel1;
332  default:
333  PPL_UNREACHABLE;
334  return V_EMPTY;
335  }
336  }
337  template <typename T>
338  Result convert_integer(T& to) const {
339  Result rel = convert_real(to);
340  switch (rel) {
341  case V_LT:
342  if (is_integer(to)) {
343  rel = sub_assign_r(to, to, T(1), (ROUND_UP | ROUND_STRICT_RELATION));
344  rel = result_relation_class(rel);
345  return (rel == V_EQ) ? V_LE : rel;
346  }
347  /* Fall through */
348  case V_LE:
349  rel = floor_assign_r(to, to, ROUND_UP);
350  rel = result_relation_class(rel);
351  PPL_ASSERT(rel == V_EQ);
352  return V_LE;
353  case V_GT:
354  if (is_integer(to)) {
355  rel = add_assign_r(to, to, T(1), (ROUND_DOWN | ROUND_STRICT_RELATION));
356  rel = result_relation_class(rel);
357  return (rel == V_EQ) ? V_GE : rel;
358  }
359  /* Fall through */
360  case V_GE:
361  rel = ceil_assign_r(to, to, ROUND_DOWN);
362  rel = result_relation_class(rel);
363  PPL_ASSERT(rel == V_EQ);
364  return V_GE;
365  case V_EQ:
366  if (is_integer(to)) {
367  return V_EQ;
368  }
369  return V_EMPTY;
370  case V_NE:
371  if (is_integer(to)) {
372  return V_NE;
373  }
374  return V_LGE;
375  default:
376  return rel;
377  }
378  }
379 };
380 
384  : rel(r) {
385  PPL_ASSERT(result_relation_class(r) == r);
386  }
388  : rel(static_cast<Result>(r)) {
389  }
390  operator Result() const {
391  return rel;
392  }
393 };
394 
395 template <typename T, typename Val_Or_Ref_Criteria = Use_Slow_Copy,
396  bool extended = false>
398  : public I_Constraint_Common<I_Constraint<T, Val_Or_Ref_Criteria,
399  extended> > {
401  typedef typename Val_Ref::Arg_Type Arg_Type;
402  typedef typename Val_Ref::Return_Type Return_Type;
404  Val_Ref value_;
405 public:
406  typedef T value_type;
407  explicit I_Constraint()
408  : rel_(V_LGE) {
409  }
411  : rel_(r), value_(v) {
412  }
413  I_Constraint(I_Constraint_Rel r, const T& v, bool force)
414  : rel_(r), value_(v, force) {
415  }
416  template <typename U>
418  : rel_(r), value_(v) {
419  }
420  void set(I_Constraint_Rel r, Arg_Type v) {
421  rel_ = r;
422  value_.set(v);
423  }
424  void set(I_Constraint_Rel r, const T& v, bool force) {
425  rel_ = r;
426  value_.set(v, force);
427  }
428  template <typename U>
429  void set(I_Constraint_Rel r, const U& v) {
430  rel_ = r;
431  value_.set(v);
432  }
433  Return_Type value() const {
434  return value_;
435  }
436  Result rel() const {
437  return rel_;
438  }
439 };
440 
441 template <typename T>
442 inline I_Constraint<T>
443 i_constraint(I_Constraint_Rel rel, const T& v) {
444  return I_Constraint<T>(rel, v);
445 }
446 
447 template <typename T>
448 inline I_Constraint<T>
449 i_constraint(I_Constraint_Rel rel, const T& v, bool force) {
450  return I_Constraint<T>(rel, v, force);
451 }
452 
453 template <typename T>
454 inline I_Constraint<T>
456  return I_Constraint<T>(rel, v);
457 }
458 
459 template <typename T, typename Val_Or_Ref_Criteria>
460 inline I_Constraint<T, Val_Or_Ref_Criteria>
461 i_constraint(I_Constraint_Rel rel, const T& v, const Val_Or_Ref_Criteria&) {
463 }
464 
465 template <typename T, typename Val_Or_Ref_Criteria>
466 inline I_Constraint<T, Val_Or_Ref_Criteria>
467 i_constraint(I_Constraint_Rel rel, const T& v, bool force,
468  const Val_Or_Ref_Criteria&) {
469  return I_Constraint<T, Val_Or_Ref_Criteria>(rel, v, force);
470 }
471 
472 template <typename T, typename Val_Or_Ref_Criteria>
473 inline I_Constraint<T, Val_Or_Ref_Criteria>
474 i_constraint(I_Constraint_Rel rel, T& v, const Val_Or_Ref_Criteria&) {
476 }
477 
478 } // namespace Parma_Polyhedra_Library
479 
480 #endif // !defined(PPL_intervals_defs_hh)
Result may be empty or not empty.
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
I_Constraint< T > i_constraint(I_Constraint_Rel rel, const T &v)
Result is definitely inexact.
The computed result is exact.
Definition: Result_defs.hh:81
Result is neither empty nor the domain universe.
I_Result
The result of an operation on intervals.
Val_Or_Ref< T, Val_Or_Ref_Criteria > Val_Ref
Result convert_real(T &to1, Result &rel2, T &to2) const
void set(I_Constraint_Rel r, const T &v, bool force)
A positive integer overflow occurred (rounding up).
Definition: Result_defs.hh:111
bool lt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Result may be empty or not empty.
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
Result may have only one value.
bool gt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Operation is undefined for some combination of values.
Result may be the domain universe.
The computed result is inexact and rounded down.
Definition: Result_defs.hh:87
The exact result is not comparable.
Definition: Result_defs.hh:78
I_Result operator&(I_Result a, I_Result b)
Result may have more than one value, but it is not the domain universe.
Relation_Symbol
Relation symbols.
A class holding a constant called value that evaluates to true.
I_Result operator|(I_Result a, I_Result b)
bool eq(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
The computed result is inexact.
Definition: Result_defs.hh:90
Result result_relation_class(Result r)
Coefficient value
Definition: PIP_Tree.cc:618
Result is definitely exact.
The computed result may be inexact and rounded up.
Definition: Result_defs.hh:93
I_Constraint(I_Constraint_Rel r, const T &v, bool force)
The entire library is confined to this namespace.
Definition: version.hh:61
void set(I_Constraint_Rel r, const U &v)
Operation has definitely changed the set.
The computed result may be inexact and rounded down.
Definition: Result_defs.hh:96
I_Constraint(I_Constraint_Rel r, const U &v)
I_Constraint(I_Constraint_Rel r, Arg_Type v)
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator-(const Interval< B, Info > &x, const T &y)
A negative integer overflow occurred (rounding down).
Definition: Result_defs.hh:114
Coefficient c
Definition: PIP_Tree.cc:64
The computed result is inexact and rounded up.
Definition: Result_defs.hh:84
A class that provides a type member called type equivalent to T if and only if b is true...
Operation has left the set definitely unchanged.
The computed result may be inexact.
Definition: Result_defs.hh:99
A class holding a constant called value that evaluates to false.
void set(I_Constraint_Rel r, Arg_Type v)
A class holding a constant called value that evaluates to b.