1 /* Inline functions for the Interval class and its constituents.
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_Interval_inlines_hh
25 #define PPL_Interval_inlines_hh 1
26 
27 namespace Parma_Polyhedra_Library {
28 
29 template <typename Boundary, typename Info>
30 inline memory_size_type
external_memory_in_bytes() const31 Interval<Boundary, Info>::external_memory_in_bytes() const {
32   return Parma_Polyhedra_Library::external_memory_in_bytes(lower())
33     + Parma_Polyhedra_Library::external_memory_in_bytes(upper());
34 }
35 
36 template <typename Boundary, typename Info>
37 inline memory_size_type
total_memory_in_bytes() const38 Interval<Boundary, Info>::total_memory_in_bytes() const {
39   return sizeof(*this) + external_memory_in_bytes();
40 }
41 
42 template <typename Boundary, typename Info>
43 inline void
m_swap(Interval<Boundary,Info> & y)44 Interval<Boundary, Info>::m_swap(Interval<Boundary, Info>& y) {
45   using std::swap;
46   swap(lower(), y.lower());
47   swap(upper(), y.upper());
48   swap(info(), y.info());
49 }
50 
51 template <typename Boundary, typename Info>
52 inline bool
f_is_empty(const Interval<Boundary,Info> & x)53 f_is_empty(const Interval<Boundary, Info>& x) {
54   return x.is_empty();
55 }
56 template <typename Boundary, typename Info>
57 inline bool
f_is_singleton(const Interval<Boundary,Info> & x)58 f_is_singleton(const Interval<Boundary, Info>& x) {
59   return x.is_singleton();
60 }
61 template <typename Boundary, typename Info>
62 inline int
infinity_sign(const Interval<Boundary,Info> & x)63 infinity_sign(const Interval<Boundary, Info>& x) {
64   return x.infinity_sign();
65 }
66 
67 namespace Interval_NS {
68 
69 template <typename Boundary, typename Info>
70 inline const Boundary&
f_lower(const Interval<Boundary,Info> & x)71 f_lower(const Interval<Boundary, Info>& x) {
72   return x.lower();
73 }
74 template <typename Boundary, typename Info>
75 inline const Boundary&
f_upper(const Interval<Boundary,Info> & x)76 f_upper(const Interval<Boundary, Info>& x) {
77   return x.upper();
78 }
79 template <typename Boundary, typename Info>
80 inline const Info&
f_info(const Interval<Boundary,Info> & x)81 f_info(const Interval<Boundary, Info>& x) {
82   return x.info();
83 }
84 
85 struct Scalar_As_Interval_Policy {
86   const_bool_nodef(may_be_empty, true);
87   const_bool_nodef(may_contain_infinity, true);
88   const_bool_nodef(check_inexact, false);
89 };
90 
91 typedef Interval_Info_Null<Scalar_As_Interval_Policy>
92 Scalar_As_Interval_Info;
93 
94 const Scalar_As_Interval_Info SCALAR_INFO;
95 
96 typedef Interval_Info_Null_Open<Scalar_As_Interval_Policy>
97 Scalar_As_Interval_Info_Open;
98 
99 template <typename T>
100 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
f_lower(const T & x)101 f_lower(const T& x) {
102   return x;
103 }
104 template <typename T>
105 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
f_upper(const T & x)106 f_upper(const T& x) {
107   return x;
108 }
109 template <typename T>
110 inline typename Enable_If<Is_Singleton<T>::value,
111                           const Scalar_As_Interval_Info&>::type
f_info(const T &)112 f_info(const T&) {
113   return SCALAR_INFO;
114 }
115 template <typename T>
116 inline typename Enable_If<Is_Singleton<T>::value,
117                           Scalar_As_Interval_Info_Open>::type
f_info(const T &,bool open)118 f_info(const T&, bool open) {
119   return Scalar_As_Interval_Info_Open(open);
120 }
121 
122 template <typename T>
123 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
f_is_empty(const T & x)124 f_is_empty(const T& x) {
125   return is_not_a_number(x);
126 }
127 
128 template <typename T>
129 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
f_is_singleton(const T & x)130 f_is_singleton(const T& x) {
131   return !f_is_empty(x);
132 }
133 
134 } // namespace Interval_NS
135 
136 template <typename T>
137 inline typename Enable_If<Is_Singleton<T>::value
138                           || Is_Interval<T>::value, bool>::type
is_singleton_integer(const T & x)139 is_singleton_integer(const T& x) {
140   return is_singleton(x) && is_integer(f_lower(x));
141 }
142 
143 template <typename T>
144 inline typename Enable_If<Is_Singleton<T>::value
145                           || Is_Interval<T>::value, bool>::type
check_empty_arg(const T & x)146 check_empty_arg(const T& x) {
147   if (f_info(x).may_be_empty) {
148     return f_is_empty(x);
149   }
150   else {
151     PPL_ASSERT(!f_is_empty(x));
152     return false;
153   }
154 }
155 
156 template <typename T1, typename T2>
157 inline typename Enable_If<((Is_Singleton<T1>::value
158                             || Is_Interval<T1>::value)
159                            && (Is_Singleton<T2>::value
160                                || Is_Interval<T2>::value)
161                            && (Is_Interval<T1>::value
162                                || Is_Interval<T2>::value)),
163                           bool>::type
operator ==(const T1 & x,const T2 & y)164 operator==(const T1& x, const T2& y) {
165   PPL_ASSERT(f_OK(x));
166   PPL_ASSERT(f_OK(y));
167   if (check_empty_arg(x)) {
168     return check_empty_arg(y);
169   }
170   else if (check_empty_arg(y)) {
171     return false;
172   }
173   return eq(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y))
174     && eq(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
175 }
176 
177 template <typename T1, typename T2>
178 inline typename Enable_If<((Is_Singleton<T1>::value
179                             || Is_Interval<T1>::value)
180                            && (Is_Singleton<T2>::value
181                                || Is_Interval<T2>::value)
182                            && (Is_Interval<T1>::value
183                                || Is_Interval<T2>::value)),
184                           bool>::type
operator !=(const T1 & x,const T2 & y)185 operator!=(const T1& x, const T2& y) {
186   return !(x == y);
187 }
188 
189 template <typename Boundary, typename Info>
190 template <typename T>
191 inline typename Enable_If<Is_Singleton<T>::value
192                           || Is_Interval<T>::value, bool>::type
contains(const T & y) const193 Interval<Boundary, Info>::contains(const T& y) const {
194   PPL_ASSERT(OK());
195   PPL_ASSERT(f_OK(y));
196   if (check_empty_arg(y)) {
197     return true;
198   }
199   if (check_empty_arg(*this)) {
200     return false;
201   }
202   return le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
203     && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y));
204 }
205 
206 template <typename Boundary, typename Info>
207 template <typename T>
208 inline typename Enable_If<Is_Singleton<T>::value
209                           || Is_Interval<T>::value, bool>::type
strictly_contains(const T & y) const210 Interval<Boundary, Info>::strictly_contains(const T& y) const {
211   PPL_ASSERT(OK());
212   PPL_ASSERT(f_OK(y));
213   if (check_empty_arg(y)) {
214     return !check_empty_arg(*this);
215   }
216   if (check_empty_arg(*this)) {
217     return false;
218   }
219   return (lt(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
220           && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)))
221     || (le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
222         && gt(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)));
223 }
224 
225 template <typename Boundary, typename Info>
226 template <typename T>
227 inline typename Enable_If<Is_Singleton<T>::value
228                           || Is_Interval<T>::value, bool>::type
is_disjoint_from(const T & y) const229 Interval<Boundary, Info>::is_disjoint_from(const T& y) const {
230   PPL_ASSERT(OK());
231   PPL_ASSERT(f_OK(y));
232   if (check_empty_arg(*this) || check_empty_arg(y)) {
233     return true;
234   }
235   return gt(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y))
236     || lt(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
237 }
238 
239 template <typename To_Boundary, typename To_Info>
240 template <typename From>
241 inline typename Enable_If<Is_Singleton<From>::value
242                           || Is_Interval<From>::value, I_Result>::type
assign(const From & x)243 Interval<To_Boundary, To_Info>::assign(const From& x) {
244   PPL_ASSERT(f_OK(x));
245   if (check_empty_arg(x)) {
246     return assign(EMPTY);
247   }
248   PPL_DIRTY_TEMP(To_Info, to_info);
249   to_info.clear();
250   const Result rl = Boundary_NS::assign(LOWER, lower(), to_info,
251                                         LOWER, f_lower(x), f_info(x));
252   const Result ru = Boundary_NS::assign(UPPER, upper(), to_info,
253                                         UPPER, f_upper(x), f_info(x));
254   assign_or_swap(info(), to_info);
255   PPL_ASSERT(OK());
256   return combine(rl, ru);
257 }
258 
259 template <typename To_Boundary, typename To_Info>
260 template <typename From>
261 inline typename Enable_If<Is_Singleton<From>::value
262                           || Is_Interval<From>::value, I_Result>::type
join_assign(const From & x)263 Interval<To_Boundary, To_Info>::join_assign(const From& x) {
264   PPL_ASSERT(f_OK(x));
265   if (check_empty_arg(*this)) {
266     return assign(x);
267   }
268   if (check_empty_arg(x)) {
269     return combine(V_EQ, V_EQ);
270   }
271   Result rl;
272   Result ru;
273   rl = min_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
274   ru = max_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
275   PPL_ASSERT(OK());
276   return combine(rl, ru);
277 }
278 
279 template <typename To_Boundary, typename To_Info>
280 template <typename From1, typename From2>
281 inline typename Enable_If<((Is_Singleton<From1>::value
282                             || Is_Interval<From1>::value)
283                            && (Is_Singleton<From2>::value
284                                || Is_Interval<From2>::value)), I_Result>::type
join_assign(const From1 & x,const From2 & y)285 Interval<To_Boundary, To_Info>::join_assign(const From1& x, const From2& y) {
286   PPL_ASSERT(f_OK(x));
287   PPL_ASSERT(f_OK(y));
288   if (check_empty_arg(x)) {
289     return assign(y);
290   }
291   if (check_empty_arg(y)) {
292     return assign(x);
293   }
294   PPL_DIRTY_TEMP(To_Info, to_info);
295   to_info.clear();
296   Result rl;
297   Result ru;
298   rl = min_assign(LOWER, lower(), to_info,
299                   LOWER, f_lower(x), f_info(x),
300                   LOWER, f_lower(y), f_info(y));
301   ru = max_assign(UPPER, upper(), to_info,
302                   UPPER, f_upper(x), f_info(x),
303                   UPPER, f_upper(y), f_info(y));
304   assign_or_swap(info(), to_info);
305   PPL_ASSERT(OK());
306   return combine(rl, ru);
307 }
308 
309 template <typename Boundary, typename Info>
310 template <typename Type>
311 inline typename Enable_If<Is_Singleton<Type>::value
312                           || Is_Interval<Type>::value, bool>::type
can_be_exactly_joined_to(const Type & x) const313 Interval<Boundary, Info>::can_be_exactly_joined_to(const Type& x) const {
314   PPL_DIRTY_TEMP(Boundary, b);
315   if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
316     b = lower();
317     return eq(LOWER, b, info(), UPPER, f_upper(x), f_info(x));
318   }
319   else if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
320     b = upper();
321     return eq(UPPER, b, info(), LOWER, f_lower(x), f_info(x));
322   }
323   return true;
324 }
325 
326 
327 template <typename To_Boundary, typename To_Info>
328 template <typename From>
329 inline typename Enable_If<Is_Singleton<From>::value
330                           || Is_Interval<From>::value, I_Result>::type
intersect_assign(const From & x)331 Interval<To_Boundary, To_Info>::intersect_assign(const From& x) {
332   PPL_ASSERT(f_OK(x));
333   max_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
334   min_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
335   PPL_ASSERT(OK());
336   return I_ANY;
337 }
338 
339 template <typename To_Boundary, typename To_Info>
340 template <typename From1, typename From2>
341 inline typename Enable_If<((Is_Singleton<From1>::value
342                             || Is_Interval<From1>::value)
343                            && (Is_Singleton<From2>::value
344                                || Is_Interval<From2>::value)), I_Result>::type
intersect_assign(const From1 & x,const From2 & y)345 Interval<To_Boundary, To_Info>::intersect_assign(const From1& x,
346                                                  const From2& y) {
347   PPL_ASSERT(f_OK(x));
348   PPL_ASSERT(f_OK(y));
349   PPL_DIRTY_TEMP(To_Info, to_info);
350   to_info.clear();
351   max_assign(LOWER, lower(), to_info,
352              LOWER, f_lower(x), f_info(x),
353              LOWER, f_lower(y), f_info(y));
354   min_assign(UPPER, upper(), to_info,
355              UPPER, f_upper(x), f_info(x),
356              UPPER, f_upper(y), f_info(y));
357   assign_or_swap(info(), to_info);
358   PPL_ASSERT(OK());
359   return I_NOT_EMPTY;
360 }
361 
362 template <typename To_Boundary, typename To_Info>
363 template <typename From>
364 inline typename Enable_If<Is_Singleton<From>::value
365                           || Is_Interval<From>::value, I_Result>::type
difference_assign(const From & x)366 Interval<To_Boundary, To_Info>::difference_assign(const From& x) {
367   PPL_ASSERT(f_OK(x));
368   if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))
369       || gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
370     return combine(V_EQ, V_EQ);
371   }
372   bool nl = ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
373   bool nu = le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
374   Result rl = V_EQ;
375   Result ru = V_EQ;
376   if (nl) {
377     if (nu) {
378       return assign(EMPTY);
379     }
380     else {
381       info().clear_boundary_properties(LOWER);
382       rl = complement(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x));
383     }
384   }
385   else if (nu) {
386     info().clear_boundary_properties(UPPER);
387     ru = complement(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x));
388   }
389   PPL_ASSERT(OK());
390   return combine(rl, ru);
391 }
392 
393 template <typename To_Boundary, typename To_Info>
394 template <typename From1, typename From2>
395 inline typename Enable_If<((Is_Singleton<From1>::value
396                             || Is_Interval<From1>::value)
397                            && (Is_Singleton<From2>::value
398                                || Is_Interval<From2>::value)), I_Result>::type
difference_assign(const From1 & x,const From2 & y)399 Interval<To_Boundary, To_Info>::difference_assign(const From1& x,
400                                                   const From2& y) {
401   PPL_ASSERT(f_OK(x));
402   PPL_ASSERT(f_OK(y));
403   PPL_DIRTY_TEMP(To_Info, to_info);
404   to_info.clear();
405   if (lt(UPPER, f_upper(x), f_info(x), LOWER, f_lower(y), f_info(y))
406       || gt(LOWER, f_lower(x), f_info(x), UPPER, f_upper(y), f_info(y))) {
407     return assign(x);
408   }
409   bool nl = ge(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y));
410   bool nu = le(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
411   Result rl = V_EQ;
412   Result ru = V_EQ;
413   if (nl) {
414     if (nu) {
415       return assign(EMPTY);
416     }
417     else {
418       rl = complement(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y));
419       ru = Boundary_NS::assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
420     }
421   }
422   else if (nu) {
423     ru = complement(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
424     rl = Boundary_NS::assign(LOWER, lower(), info(),
425                              LOWER, f_lower(x), f_info(x));
426   }
427   assign_or_swap(info(), to_info);
428   PPL_ASSERT(OK());
429   return combine(rl, ru);
430 }
431 
432 template <typename To_Boundary, typename To_Info>
433 template <typename From>
434 inline typename Enable_If<Is_Singleton<From>::value
435                           || Is_Interval<From>::value, I_Result>::type
436 Interval<To_Boundary, To_Info>
refine_existential(Relation_Symbol rel,const From & x)437 ::refine_existential(Relation_Symbol rel, const From& x) {
438   PPL_ASSERT(OK());
439   PPL_ASSERT(f_OK(x));
440   if (check_empty_arg(x)) {
441     return assign(EMPTY);
442   }
443   switch (rel) {
444   case LESS_THAN:
445     {
446       if (lt(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
447         return combine(V_EQ, V_EQ);
448       }
449       info().clear_boundary_properties(UPPER);
450       Boundary_NS::assign(UPPER, upper(), info(),
451                           UPPER, f_upper(x), f_info(x), true);
452       return I_ANY;
453     }
454   case LESS_OR_EQUAL:
455     {
456       if (le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
457         return combine(V_EQ, V_EQ);
458       }
459       info().clear_boundary_properties(UPPER);
460       Boundary_NS::assign(UPPER, upper(), info(),
461                           UPPER, f_upper(x), f_info(x));
462       return I_ANY;
463     }
464   case GREATER_THAN:
465     {
466       if (gt(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
467         return combine(V_EQ, V_EQ);
468       }
469       info().clear_boundary_properties(LOWER);
470       Boundary_NS::assign(LOWER, lower(), info(),
471                           LOWER, f_lower(x), f_info(x), true);
472       return I_ANY;
473     }
474   case GREATER_OR_EQUAL:
475     {
476       if (ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
477         return combine(V_EQ, V_EQ);
478       }
479       info().clear_boundary_properties(LOWER);
480       Boundary_NS::assign(LOWER, lower(), info(),
481                           LOWER, f_lower(x), f_info(x));
482       return I_ANY;
483     }
484   case EQUAL:
485     return intersect_assign(x);
486   case NOT_EQUAL:
487     {
488       if (!f_is_singleton(x)) {
489         return combine(V_EQ, V_EQ);
490       }
491       if (check_empty_arg(*this)) {
492         return I_EMPTY;
493       }
494       if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
495         remove_inf();
496       }
497       if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
498         remove_sup();
499       }
500       return I_ANY;
501     }
502   default:
503     PPL_UNREACHABLE;
504     return I_EMPTY;
505   }
506 }
507 
508 template <typename To_Boundary, typename To_Info>
509 template <typename From>
510 inline typename Enable_If<Is_Singleton<From>::value
511                           || Is_Interval<From>::value, I_Result>::type
refine_universal(Relation_Symbol rel,const From & x)512 Interval<To_Boundary, To_Info>::refine_universal(Relation_Symbol rel,
513                                                  const From& x) {
514   PPL_ASSERT(OK());
515   PPL_ASSERT(f_OK(x));
516   if (check_empty_arg(x)) {
517     return combine(V_EQ, V_EQ);
518   }
519   switch (rel) {
520   case LESS_THAN:
521     {
522       if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
523         return combine(V_EQ, V_EQ);
524       }
525       info().clear_boundary_properties(UPPER);
526       Result ru = Boundary_NS::assign(UPPER, upper(), info(),
527                                       LOWER, f_lower(x), SCALAR_INFO,
528                                       !is_open(LOWER, f_lower(x), f_info(x)));
529       PPL_USED(ru);
530       return I_ANY;
531     }
532   case LESS_OR_EQUAL:
533     {
534       if (le(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
535         return combine(V_EQ, V_EQ);
536       }
537       info().clear_boundary_properties(UPPER);
538       Result ru = Boundary_NS::assign(UPPER, upper(), info(),
539                                       LOWER, f_lower(x), SCALAR_INFO);
540       PPL_USED(ru);
541       return I_ANY;
542     }
543   case GREATER_THAN:
544     {
545       if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
546         return combine(V_EQ, V_EQ);
547       }
548       info().clear_boundary_properties(LOWER);
549       Result rl = Boundary_NS::assign(LOWER, lower(), info(),
550                                       UPPER, f_upper(x), SCALAR_INFO,
551                                       !is_open(UPPER, f_upper(x), f_info(x)));
552       PPL_USED(rl);
553       return I_ANY;
554     }
555   case GREATER_OR_EQUAL:
556     {
557       if (ge(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
558         return combine(V_EQ, V_EQ);
559       }
560       info().clear_boundary_properties(LOWER);
561       Result rl = Boundary_NS::assign(LOWER, lower(), info(),
562                                       UPPER, f_upper(x), SCALAR_INFO);
563       PPL_USED(rl);
564       return I_ANY;
565     }
566   case EQUAL:
567     if (!f_is_singleton(x)) {
568       return assign(EMPTY);
569     }
570     return intersect_assign(x);
571   case NOT_EQUAL:
572     {
573       if (check_empty_arg(*this)) {
574         return I_EMPTY;
575       }
576       if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
577         remove_inf();
578       }
579       if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
580         remove_sup();
581       }
582       return I_ANY;
583     }
584   default:
585     PPL_UNREACHABLE;
586     return I_EMPTY;
587   }
588 }
589 
590 template <typename To_Boundary, typename To_Info>
591 template <typename From>
592 inline typename Enable_If<Is_Singleton<From>::value
593                           || Is_Interval<From>::value, I_Result>::type
neg_assign(const From & x)594 Interval<To_Boundary, To_Info>::neg_assign(const From& x) {
595   PPL_ASSERT(f_OK(x));
596   if (check_empty_arg(x)) {
597     return assign(EMPTY);
598   }
599   PPL_DIRTY_TEMP(To_Info, to_info);
600   to_info.clear();
601   Result rl;
602   Result ru;
603   PPL_DIRTY_TEMP(To_Boundary, to_lower);
604   rl = Boundary_NS::neg_assign(LOWER, to_lower, to_info, UPPER, f_upper(x), f_info(x));
605   ru = Boundary_NS::neg_assign(UPPER, upper(), to_info, LOWER, f_lower(x), f_info(x));
606   assign_or_swap(lower(), to_lower);
607   assign_or_swap(info(), to_info);
608   PPL_ASSERT(OK());
609   return combine(rl, ru);
610 }
611 
612 template <typename To_Boundary, typename To_Info>
613 template <typename From1, typename From2>
614 inline typename Enable_If<((Is_Singleton<From1>::value
615                             || Is_Interval<From1>::value)
616                            && (Is_Singleton<From2>::value
617                                || Is_Interval<From2>::value)), I_Result>::type
add_assign(const From1 & x,const From2 & y)618 Interval<To_Boundary, To_Info>::add_assign(const From1& x, const From2& y) {
619   PPL_ASSERT(f_OK(x));
620   PPL_ASSERT(f_OK(y));
621   if (check_empty_arg(x) || check_empty_arg(y)) {
622     return assign(EMPTY);
623   }
624   int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
625   if (inf_sign != 0) {
626     if (Parma_Polyhedra_Library::infinity_sign(y) == -inf_sign) {
627       return assign(EMPTY);
628     }
629   }
630   else {
631     inf_sign = Parma_Polyhedra_Library::infinity_sign(y);
632   }
633   if (inf_sign < 0) {
634     return assign(MINUS_INFINITY);
635   }
636   else if (inf_sign > 0) {
637     return assign(PLUS_INFINITY);
638   }
639   PPL_DIRTY_TEMP(To_Info, to_info);
640   to_info.clear();
641   Result rl = Boundary_NS::add_assign(LOWER, lower(), to_info,
642                                       LOWER, f_lower(x), f_info(x),
643                                       LOWER, f_lower(y), f_info(y));
644   Result ru = Boundary_NS::add_assign(UPPER, upper(), to_info,
645                                       UPPER, f_upper(x), f_info(x),
646                                       UPPER, f_upper(y), f_info(y));
647   assign_or_swap(info(), to_info);
648   PPL_ASSERT(OK());
649   return combine(rl, ru);
650 }
651 
652 template <typename To_Boundary, typename To_Info>
653 template <typename From1, typename From2>
654 inline typename Enable_If<((Is_Singleton<From1>::value
655                             || Is_Interval<From1>::value)
656                            && (Is_Singleton<From2>::value
657                                || Is_Interval<From2>::value)), I_Result>::type
sub_assign(const From1 & x,const From2 & y)658 Interval<To_Boundary, To_Info>::sub_assign(const From1& x, const From2& y) {
659   PPL_ASSERT(f_OK(x));
660   PPL_ASSERT(f_OK(y));
661   if (check_empty_arg(x) || check_empty_arg(y)) {
662     return assign(EMPTY);
663   }
664   int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
665   if (inf_sign != 0) {
666     if (Parma_Polyhedra_Library::infinity_sign(y) == inf_sign) {
667       return assign(EMPTY);
668     }
669   }
670   else {
671     inf_sign = -Parma_Polyhedra_Library::infinity_sign(y);
672   }
673   if (inf_sign < 0) {
674     return assign(MINUS_INFINITY);
675   }
676   else if (inf_sign > 0) {
677     return assign(PLUS_INFINITY);
678   }
679   PPL_DIRTY_TEMP(To_Info, to_info);
680   to_info.clear();
681   Result rl;
682   Result ru;
683   PPL_DIRTY_TEMP(To_Boundary, to_lower);
684   rl = Boundary_NS::sub_assign(LOWER, to_lower, to_info,
685                                LOWER, f_lower(x), f_info(x),
686                                UPPER, f_upper(y), f_info(y));
687   ru = Boundary_NS::sub_assign(UPPER, upper(), to_info,
688                                UPPER, f_upper(x), f_info(x),
689                                LOWER, f_lower(y), f_info(y));
690   assign_or_swap(lower(), to_lower);
691   assign_or_swap(info(), to_info);
692   PPL_ASSERT(OK());
693   return combine(rl, ru);
694 }
695 
696 /**
697 +---------+-----------+-----------+-----------------+
698 |    *    |  yl > 0   |  yu < 0   |  yl < 0, yu > 0 |
699 +---------+-----------+-----------+-----------------+
700 | xl > 0  |xl*yl,xu*yu|xu*yl,xl*yu|   xu*yl,xu*yu   |
701 +---------+-----------+-----------+-----------------+
702 | xu < 0  |xl*yu,xu*yl|xu*yu,xl*yl|   xl*yu,xl*yl   |
703 +---------+-----------+-----------+-----------------+
704 |xl<0 xu>0|xl*yu,xu*yu|xu*yl,xl*yl|min(xl*yu,xu*yl),|
705 |         |           |           |max(xl*yl,xu*yu) |
706 +---------+-----------+-----------+-----------------+
707 **/
708 template <typename To_Boundary, typename To_Info>
709 template <typename From1, typename From2>
710 inline typename Enable_If<((Is_Singleton<From1>::value
711                             || Is_Interval<From1>::value)
712                            && (Is_Singleton<From2>::value
713                                || Is_Interval<From2>::value)), I_Result>::type
mul_assign(const From1 & x,const From2 & y)714 Interval<To_Boundary, To_Info>::mul_assign(const From1& x, const From2& y) {
715   PPL_ASSERT(f_OK(x));
716   PPL_ASSERT(f_OK(y));
717   if (check_empty_arg(x) || check_empty_arg(y)) {
718     return assign(EMPTY);
719   }
720   int xls = sgn_b(LOWER, f_lower(x), f_info(x));
721   int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
722   int yls = sgn_b(LOWER, f_lower(y), f_info(y));
723   int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
724   int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
725   int ls;
726   int us;
727   if (inf_sign != 0) {
728     ls = yls;
729     us = yus;
730     goto inf;
731   }
732   else {
733     inf_sign = Parma_Polyhedra_Library::infinity_sign(y);
734     if (inf_sign != 0) {
735       ls = xls;
736       us = xus;
737     inf:
738       if (ls == 0 && us == 0) {
739         return assign(EMPTY);
740       }
741       if (ls == -us) {
742         return set_infinities();
743       }
744       if (ls < 0 || us < 0) {
745         inf_sign = -inf_sign;
746       }
747       if (inf_sign < 0) {
748         return assign(MINUS_INFINITY);
749       }
750       else {
751         return assign(PLUS_INFINITY);
752       }
753     }
754   }
755 
756   PPL_DIRTY_TEMP(To_Info, to_info);
757   to_info.clear();
758   Result rl;
759   Result ru;
760   PPL_DIRTY_TEMP(To_Boundary, to_lower);
761 
762   if (xls >= 0) {
763     if (yls >= 0) {
764       // 0 <= xl <= xu, 0 <= yl <= yu
765       rl = mul_assign_z(LOWER, to_lower, to_info,
766                         LOWER, f_lower(x), f_info(x), xls,
767                         LOWER, f_lower(y), f_info(y), yls);
768       ru = mul_assign_z(UPPER, upper(), to_info,
769                         UPPER, f_upper(x), f_info(x), xus,
770                         UPPER, f_upper(y), f_info(y), yus);
771     }
772     else if (yus <= 0) {
773       // 0 <= xl <= xu, yl <= yu <= 0
774       rl = mul_assign_z(LOWER, to_lower, to_info,
775                         UPPER, f_upper(x), f_info(x), xus,
776                         LOWER, f_lower(y), f_info(y), yls);
777       ru = mul_assign_z(UPPER, upper(), to_info,
778                         LOWER, f_lower(x), f_info(x), xls,
779                         UPPER, f_upper(y), f_info(y), yus);
780     }
781     else {
782       // 0 <= xl <= xu, yl < 0 < yu
783       rl = mul_assign_z(LOWER, to_lower, to_info,
784                         UPPER, f_upper(x), f_info(x), xus,
785                         LOWER, f_lower(y), f_info(y), yls);
786       ru = mul_assign_z(UPPER, upper(), to_info,
787                         UPPER, f_upper(x), f_info(x), xus,
788                         UPPER, f_upper(y), f_info(y), yus);
789     }
790   }
791   else if (xus <= 0) {
792     if (yls >= 0) {
793       // xl <= xu <= 0, 0 <= yl <= yu
794       rl = mul_assign_z(LOWER, to_lower, to_info,
795                         LOWER, f_lower(x), f_info(x), xls,
796                         UPPER, f_upper(y), f_info(y), yus);
797       ru = mul_assign_z(UPPER, upper(), to_info,
798                         UPPER, f_upper(x), f_info(x), xus,
799                         LOWER, f_lower(y), f_info(y), yls);
800     }
801     else if (yus <= 0) {
802       // xl <= xu <= 0, yl <= yu <= 0
803       rl = mul_assign_z(LOWER, to_lower, to_info,
804                         UPPER, f_upper(x), f_info(x), xus,
805                         UPPER, f_upper(y), f_info(y), yus);
806       ru = mul_assign_z(UPPER, upper(), to_info,
807                         LOWER, f_lower(x), f_info(x), xls,
808                         LOWER, f_lower(y), f_info(y), yls);
809     }
810     else {
811       // xl <= xu <= 0, yl < 0 < yu
812       rl = mul_assign_z(LOWER, to_lower, to_info,
813                         LOWER, f_lower(x), f_info(x), xls,
814                         UPPER, f_upper(y), f_info(y), yus);
815       ru = mul_assign_z(UPPER, upper(), to_info,
816                         LOWER, f_lower(x), f_info(x), xls,
817                         LOWER, f_lower(y), f_info(y), yls);
818     }
819   }
820   else if (yls >= 0) {
821     // xl < 0 < xu, 0 <= yl <= yu
822     rl = mul_assign_z(LOWER, to_lower, to_info,
823                       LOWER, f_lower(x), f_info(x), xls,
824                       UPPER, f_upper(y), f_info(y), yus);
825     ru = mul_assign_z(UPPER, upper(), to_info,
826                       UPPER, f_upper(x), f_info(x), xus,
827                       UPPER, f_upper(y), f_info(y), yus);
828   }
829   else if (yus <= 0) {
830     // xl < 0 < xu, yl <= yu <= 0
831     rl = mul_assign_z(LOWER, to_lower, to_info,
832                       UPPER, f_upper(x), f_info(x), xus,
833                       LOWER, f_lower(y), f_info(y), yls);
834     ru = mul_assign_z(UPPER, upper(), to_info,
835                       LOWER, f_lower(x), f_info(x), xls,
836                       LOWER, f_lower(y), f_info(y), yls);
837   }
838   else {
839     // xl < 0 < xu, yl < 0 < yu
840     PPL_DIRTY_TEMP(To_Boundary, tmp);
841     PPL_DIRTY_TEMP(To_Info, tmp_info);
842     tmp_info.clear();
843     Result tmp_r;
844     tmp_r = Boundary_NS::mul_assign(LOWER, tmp, tmp_info,
845                                     UPPER, f_upper(x), f_info(x),
846                                     LOWER, f_lower(y), f_info(y));
847     rl = Boundary_NS::mul_assign(LOWER, to_lower, to_info,
848                                  LOWER, f_lower(x), f_info(x),
849                                  UPPER, f_upper(y), f_info(y));
850     if (gt(LOWER, to_lower, to_info, LOWER, tmp, tmp_info)) {
851       to_lower = tmp;
852       rl = tmp_r;
853     }
854     tmp_info.clear();
855     tmp_r = Boundary_NS::mul_assign(UPPER, tmp, tmp_info,
856                                     UPPER, f_upper(x), f_info(x),
857                                     UPPER, f_upper(y), f_info(y));
858     ru = Boundary_NS::mul_assign(UPPER, upper(), to_info,
859                                  LOWER, f_lower(x), f_info(x),
860                                  LOWER, f_lower(y), f_info(y));
861     if (lt(UPPER, upper(), to_info, UPPER, tmp, tmp_info)) {
862       upper() = tmp;
863       ru = tmp_r;
864     }
865   }
866   assign_or_swap(lower(), to_lower);
867   assign_or_swap(info(), to_info);
868   PPL_ASSERT(OK());
869   return combine(rl, ru);
870 }
871 
872 /**
873 +-----------+-----------+-----------+
874 |     /     |  yu < 0   |  yl > 0   |
875 +-----------+-----------+-----------+
876 |   xu<=0   |xu/yl,xl/yu|xl/yl,xu/yu|
877 +-----------+-----------+-----------+
878 |xl<=0 xu>=0|xu/yu,xl/yu|xl/yl,xu/yl|
879 +-----------+-----------+-----------+
880 |   xl>=0   |xu/yu,xl/yl|xl/yu,xu/yl|
881 +-----------+-----------+-----------+
882 **/
883 template <typename To_Boundary, typename To_Info>
884 template <typename From1, typename From2>
885 inline typename Enable_If<((Is_Singleton<From1>::value
886                             || Is_Interval<From1>::value)
887                            && (Is_Singleton<From2>::value
888                                || Is_Interval<From2>::value)), I_Result>::type
div_assign(const From1 & x,const From2 & y)889 Interval<To_Boundary, To_Info>::div_assign(const From1& x, const From2& y) {
890   PPL_ASSERT(f_OK(x));
891   PPL_ASSERT(f_OK(y));
892   if (check_empty_arg(x) || check_empty_arg(y)) {
893     return assign(EMPTY);
894   }
895   int yls = sgn_b(LOWER, f_lower(y), f_info(y));
896   int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
897   if (yls == 0 && yus == 0) {
898     return assign(EMPTY);
899   }
900   int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
901   if (inf_sign != 0) {
902     if (Parma_Polyhedra_Library::infinity_sign(y) != 0) {
903       return assign(EMPTY);
904     }
905     if (yls == -yus) {
906       return set_infinities();
907     }
908     if (yls < 0 || yus < 0) {
909       inf_sign = -inf_sign;
910     }
911     if (inf_sign < 0) {
912       return assign(MINUS_INFINITY);
913     }
914     else {
915       return assign(PLUS_INFINITY);
916     }
917   }
918   int xls = sgn_b(LOWER, f_lower(x), f_info(x));
919   int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
920 
921   PPL_DIRTY_TEMP(To_Info, to_info);
922   to_info.clear();
923   Result rl;
924   Result ru;
925   PPL_DIRTY_TEMP(To_Boundary, to_lower);
926   if (yls >= 0) {
927     if (xls >= 0) {
928       rl = div_assign_z(LOWER, to_lower, to_info,
929                         LOWER, f_lower(x), f_info(x), xls,
930                         UPPER, f_upper(y), f_info(y), yus);
931       ru = div_assign_z(UPPER, upper(), to_info,
932                         UPPER, f_upper(x), f_info(x), xus,
933                         LOWER, f_lower(y), f_info(y), yls);
934     }
935     else if (xus <= 0) {
936       rl = div_assign_z(LOWER, to_lower, to_info,
937                         LOWER, f_lower(x), f_info(x), xls,
938                         LOWER, f_lower(y), f_info(y), yls);
939       ru = div_assign_z(UPPER, upper(), to_info,
940                         UPPER, f_upper(x), f_info(x), xus,
941                         UPPER, f_upper(y), f_info(y), yus);
942     }
943     else {
944       rl = div_assign_z(LOWER, to_lower, to_info,
945                         LOWER, f_lower(x), f_info(x), xls,
946                         LOWER, f_lower(y), f_info(y), yls);
947       ru = div_assign_z(UPPER, upper(), to_info,
948                         UPPER, f_upper(x), f_info(x), xus,
949                         LOWER, f_lower(y), f_info(y), yls);
950     }
951   }
952   else if (yus <= 0) {
953     if (xls >= 0) {
954       rl = div_assign_z(LOWER, to_lower, to_info,
955                         UPPER, f_upper(x), f_info(x), xus,
956                         UPPER, f_upper(y), f_info(y), yus);
957       ru = div_assign_z(UPPER, upper(), to_info,
958                         LOWER, f_lower(x), f_info(x), xls,
959                         LOWER, f_lower(y), f_info(y), yls);
960     }
961     else if (xus <= 0) {
962       rl = div_assign_z(LOWER, to_lower, to_info,
963                         UPPER, f_upper(x), f_info(x), xus,
964                         LOWER, f_lower(y), f_info(y), yls);
965       ru = div_assign_z(UPPER, upper(), to_info,
966                         LOWER, f_lower(x), f_info(x), xls,
967                         UPPER, f_upper(y), f_info(y), yus);
968     }
969     else {
970       rl = div_assign_z(LOWER, to_lower, to_info,
971                         UPPER, f_upper(x), f_info(x), xus,
972                         UPPER, f_upper(y), f_info(y), yus);
973       ru = div_assign_z(UPPER, upper(), to_info,
974                         LOWER, f_lower(x), f_info(x), xls,
975                         UPPER, f_upper(y), f_info(y), yus);
976     }
977   }
978   else {
979     return static_cast<I_Result>(assign(UNIVERSE) | I_SINGULARITIES);
980   }
981   assign_or_swap(lower(), to_lower);
982   assign_or_swap(info(), to_info);
983   PPL_ASSERT(OK());
984   return combine(rl, ru);
985 }
986 
987 template <typename B, typename Info, typename T>
988 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator +(const Interval<B,Info> & x,const T & y)989 operator+(const Interval<B, Info>& x, const T& y) {
990   Interval<B, Info> z;
991   z.add_assign(x, y);
992   return z;
993 }
994 
995 template <typename B, typename Info, typename T>
996 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator +(const T & x,const Interval<B,Info> & y)997 operator+(const T& x, const Interval<B, Info>& y) {
998   Interval<B, Info> z;
999   z.add_assign(x, y);
1000   return z;
1001 }
1002 
1003 template <typename B, typename Info>
1004 inline Interval<B, Info>
operator +(const Interval<B,Info> & x,const Interval<B,Info> & y)1005 operator+(const Interval<B, Info>& x, const Interval<B, Info>& y) {
1006   Interval<B, Info> z;
1007   z.add_assign(x, y);
1008   return z;
1009 }
1010 
1011 template <typename B, typename Info, typename T>
1012 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator -(const Interval<B,Info> & x,const T & y)1013 operator-(const Interval<B, Info>& x, const T& y) {
1014   Interval<B, Info> z;
1015   z.sub_assign(x, y);
1016   return z;
1017 }
1018 
1019 template <typename B, typename Info, typename T>
1020 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator -(const T & x,const Interval<B,Info> & y)1021 operator-(const T& x, const Interval<B, Info>& y) {
1022   Interval<B, Info> z;
1023   z.sub_assign(x, y);
1024   return z;
1025 }
1026 
1027 template <typename B, typename Info>
1028 inline Interval<B, Info>
operator -(const Interval<B,Info> & x,const Interval<B,Info> & y)1029 operator-(const Interval<B, Info>& x, const Interval<B, Info>& y) {
1030   Interval<B, Info> z;
1031   z.sub_assign(x, y);
1032   return z;
1033 }
1034 
1035 template <typename B, typename Info, typename T>
1036 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator *(const Interval<B,Info> & x,const T & y)1037 operator*(const Interval<B, Info>& x, const T& y) {
1038   Interval<B, Info> z;
1039   z.mul_assign(x, y);
1040   return z;
1041 }
1042 
1043 template <typename B, typename Info, typename T>
1044 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator *(const T & x,const Interval<B,Info> & y)1045 operator*(const T& x, const Interval<B, Info>& y) {
1046   Interval<B, Info> z;
1047   z.mul_assign(x, y);
1048   return z;
1049 }
1050 
1051 template <typename B, typename Info>
1052 inline Interval<B, Info>
operator *(const Interval<B,Info> & x,const Interval<B,Info> & y)1053 operator*(const Interval<B, Info>& x, const Interval<B, Info>& y) {
1054   Interval<B, Info> z;
1055   z.mul_assign(x, y);
1056   return z;
1057 }
1058 
1059 template <typename B, typename Info, typename T>
1060 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator /(const Interval<B,Info> & x,const T & y)1061 operator/(const Interval<B, Info>& x, const T& y) {
1062   Interval<B, Info> z;
1063   z.div_assign(x, y);
1064   return z;
1065 }
1066 
1067 template <typename B, typename Info, typename T>
1068 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
operator /(const T & x,const Interval<B,Info> & y)1069 operator/(const T& x, const Interval<B, Info>& y) {
1070   Interval<B, Info> z;
1071   z.div_assign(x, y);
1072   return z;
1073 }
1074 
1075 template <typename B, typename Info>
1076 inline Interval<B, Info>
operator /(const Interval<B,Info> & x,const Interval<B,Info> & y)1077 operator/(const Interval<B, Info>& x, const Interval<B, Info>& y) {
1078   Interval<B, Info> z;
1079   z.div_assign(x, y);
1080   return z;
1081 }
1082 
1083 template <typename Boundary, typename Info>
1084 inline std::ostream&
operator <<(std::ostream & os,const Interval<Boundary,Info> & x)1085 operator<<(std::ostream& os, const Interval<Boundary, Info>& x) {
1086   if (check_empty_arg(x)) {
1087     return os << "[]";
1088   }
1089   if (x.is_singleton()) {
1090     output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
1091     return os;
1092   }
1093   os << (x.lower_is_open() ? "(" : "[");
1094   if (x.info().get_boundary_property(LOWER, SPECIAL)) {
1095     os << "-inf";
1096   }
1097   else {
1098     output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
1099   }
1100   os << ", ";
1101   if (x.info().get_boundary_property(UPPER, SPECIAL)) {
1102     os << "+inf";
1103   }
1104   else {
1105     output(os, x.upper(), Numeric_Format(), ROUND_NOT_NEEDED);
1106   }
1107   os << (x.upper_is_open() ? ")" : "]");
1108   return os;
1109 }
1110 
1111 template <typename Boundary, typename Info>
1112 inline void
ascii_dump(std::ostream & s) const1113 Interval<Boundary, Info>::ascii_dump(std::ostream& s) const {
1114   using Parma_Polyhedra_Library::ascii_dump;
1115   s << "info ";
1116   info().ascii_dump(s);
1117   s << " lower ";
1118   ascii_dump(s, lower());
1119   s << " upper ";
1120   ascii_dump(s, upper());
1121   s << '\n';
1122 }
1123 
1124 template <typename Boundary, typename Info>
1125 inline bool
ascii_load(std::istream & s)1126 Interval<Boundary, Info>::ascii_load(std::istream& s) {
1127   using Parma_Polyhedra_Library::ascii_load;
1128   std::string str;
1129   if (!(s >> str) || str != "info") {
1130     return false;
1131   }
1132   if (!info().ascii_load(s)) {
1133     return false;
1134   }
1135   if (!(s >> str) || str != "lower") {
1136     return false;
1137   }
1138   if (!ascii_load(s, lower())) {
1139     return false;
1140   }
1141   if (!(s >> str) || str != "upper") {
1142     return false;
1143   }
1144   if (!ascii_load(s, upper())) {
1145     return false;
1146   }
1147   PPL_ASSERT(OK());
1148   return true;
1149 }
1150 
1151 /*! \brief
1152   Helper class to select the appropriate numerical type to perform
1153   boundary computations so as to reduce the chances of overflow without
1154   incurring too much overhead.
1155 */
1156 template <typename Interval_Boundary_Type> struct Select_Temp_Boundary_Type;
1157 
1158 template <typename Interval_Boundary_Type>
1159 struct Select_Temp_Boundary_Type {
1160   typedef Interval_Boundary_Type type;
1161 };
1162 
1163 #if PPL_SUPPORTED_DOUBLE
1164 template <>
1165 struct Select_Temp_Boundary_Type<float> {
1166   typedef double type;
1167 };
1168 #endif
1169 
1170 template <>
1171 struct Select_Temp_Boundary_Type<char> {
1172   typedef signed long long type;
1173 };
1174 
1175 template <>
1176 struct Select_Temp_Boundary_Type<signed char> {
1177   typedef signed long long type;
1178 };
1179 
1180 template <>
1181 struct Select_Temp_Boundary_Type<unsigned char> {
1182   typedef signed long long type;
1183 };
1184 
1185 template <>
1186 struct Select_Temp_Boundary_Type<signed short> {
1187   typedef signed long long type;
1188 };
1189 
1190 template <>
1191 struct Select_Temp_Boundary_Type<unsigned short> {
1192   typedef signed long long type;
1193 };
1194 
1195 template <>
1196 struct Select_Temp_Boundary_Type<signed int> {
1197   typedef signed long long type;
1198 };
1199 
1200 template <>
1201 struct Select_Temp_Boundary_Type<unsigned int> {
1202   typedef signed long long type;
1203 };
1204 
1205 template <>
1206 struct Select_Temp_Boundary_Type<signed long> {
1207   typedef signed long long type;
1208 };
1209 
1210 template <>
1211 struct Select_Temp_Boundary_Type<unsigned long> {
1212   typedef signed long long type;
1213 };
1214 
1215 template <>
1216 struct Select_Temp_Boundary_Type<unsigned long long> {
1217   typedef signed long long type;
1218 };
1219 
1220 /*! \relates Interval */
1221 template <typename Boundary, typename Info>
1222 inline void
swap(Interval<Boundary,Info> & x,Interval<Boundary,Info> & y)1223 swap(Interval<Boundary, Info>& x, Interval<Boundary, Info>& y) {
1224   x.m_swap(y);
1225 }
1226 
1227 } // namespace Parma_Polyhedra_Library
1228 
1229 #endif // !defined(PPL_Interval_inlines_hh)
1230