1 /* Octagonal_Shape class implementation: inline functions.
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_Octagonal_Shape_inlines_hh
25 #define PPL_Octagonal_Shape_inlines_hh 1
26 
27 #include "Constraint_System_defs.hh"
28 #include "Constraint_System_inlines.hh"
29 #include "C_Polyhedron_defs.hh"
30 #include "Grid_defs.hh"
31 #include "BD_Shape_defs.hh"
32 #include "Poly_Con_Relation_defs.hh"
33 #include "Poly_Gen_Relation_defs.hh"
34 #include "wrap_assign.hh"
35 #include "assertions.hh"
36 #include <algorithm>
37 
38 namespace Parma_Polyhedra_Library {
39 
40 namespace Implementation {
41 
42 namespace Octagonal_Shapes {
43 
44 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
45 //! Returns the index coherent to \p i.
46 /*! \relates Parma_Polyhedra_Library::Octagonal_Shape */
47 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
48 inline dimension_type
coherent_index(const dimension_type i)49 coherent_index(const dimension_type i) {
50   return (i % 2 != 0) ? (i-1) : (i+1);
51 }
52 
53 } // namespace Octagonal_Shapes
54 
55 } // namespace Implementation
56 
57 template <typename T>
58 inline dimension_type
max_space_dimension()59 Octagonal_Shape<T>::max_space_dimension() {
60   return OR_Matrix<N>::max_num_rows()/2;
61 }
62 
63 template <typename T>
64 inline bool
marked_zero_dim_univ() const65 Octagonal_Shape<T>::marked_zero_dim_univ() const {
66   return status.test_zero_dim_univ();
67 }
68 
69 template <typename T>
70 inline bool
marked_strongly_closed() const71 Octagonal_Shape<T>::marked_strongly_closed() const {
72   return status.test_strongly_closed();
73 }
74 
75 template <typename T>
76 inline bool
marked_empty() const77 Octagonal_Shape<T>::marked_empty() const {
78   return status.test_empty();
79 }
80 
81 template <typename T>
82 inline void
set_zero_dim_univ()83 Octagonal_Shape<T>::set_zero_dim_univ() {
84   status.set_zero_dim_univ();
85 }
86 
87 template <typename T>
88 inline void
set_empty()89 Octagonal_Shape<T>::set_empty() {
90   status.set_empty();
91 }
92 
93 template <typename T>
94 inline void
set_strongly_closed()95 Octagonal_Shape<T>::set_strongly_closed() {
96   status.set_strongly_closed();
97 }
98 
99 template <typename T>
100 inline void
reset_strongly_closed()101 Octagonal_Shape<T>::reset_strongly_closed() {
102   status.reset_strongly_closed();
103 }
104 
105 template <typename T>
106 inline
Octagonal_Shape(const dimension_type num_dimensions,const Degenerate_Element kind)107 Octagonal_Shape<T>::Octagonal_Shape(const dimension_type num_dimensions,
108                                     const Degenerate_Element kind)
109   : matrix(num_dimensions), space_dim(num_dimensions), status() {
110   if (kind == EMPTY) {
111     set_empty();
112   }
113   else if (num_dimensions > 0) {
114     // A (non zero-dim) universe octagon is strongly closed.
115     set_strongly_closed();
116   }
117   PPL_ASSERT(OK());
118 }
119 
120 template <typename T>
121 inline
Octagonal_Shape(const Octagonal_Shape & y,Complexity_Class)122 Octagonal_Shape<T>::Octagonal_Shape(const Octagonal_Shape& y, Complexity_Class)
123   : matrix(y.matrix), space_dim(y.space_dim), status(y.status) {
124 }
125 
126 template <typename T>
127 template <typename U>
128 inline
Octagonal_Shape(const Octagonal_Shape<U> & y,Complexity_Class)129 Octagonal_Shape<T>::Octagonal_Shape(const Octagonal_Shape<U>& y,
130                                     Complexity_Class)
131   // For maximum precision, enforce shortest-path closure
132   // before copying the DB matrix.
133   : matrix((y.strong_closure_assign(), y.matrix)),
134     space_dim(y.space_dim),
135     status() {
136   // TODO: handle flags properly, possibly taking special cases into account.
137   if (y.marked_empty()) {
138     set_empty();
139   }
140   else if (y.marked_zero_dim_univ()) {
141     set_zero_dim_univ();
142   }
143 }
144 
145 template <typename T>
146 inline
Octagonal_Shape(const Constraint_System & cs)147 Octagonal_Shape<T>::Octagonal_Shape(const Constraint_System& cs)
148   : matrix(cs.space_dimension()),
149     space_dim(cs.space_dimension()),
150     status() {
151   if (cs.space_dimension() > 0) {
152     // A (non zero-dim) universe octagon is strongly closed.
153     set_strongly_closed();
154   }
155   add_constraints(cs);
156 }
157 
158 template <typename T>
159 inline
Octagonal_Shape(const Congruence_System & cgs)160 Octagonal_Shape<T>::Octagonal_Shape(const Congruence_System& cgs)
161   : matrix(cgs.space_dimension()),
162     space_dim(cgs.space_dimension()),
163     status() {
164   if (cgs.space_dimension() > 0) {
165     // A (non zero-dim) universe octagon is strongly closed.
166     set_strongly_closed();
167   }
168   add_congruences(cgs);
169 }
170 
171 template <typename T>
172 template <typename Interval>
173 inline
Octagonal_Shape(const Box<Interval> & box,Complexity_Class)174 Octagonal_Shape<T>::Octagonal_Shape(const Box<Interval>& box,
175                                     Complexity_Class)
176   : matrix(box.space_dimension()),
177     space_dim(box.space_dimension()),
178     status() {
179   // Check for emptiness for maximum precision.
180   if (box.is_empty()) {
181     set_empty();
182   }
183   else if (box.space_dimension() > 0) {
184     // A (non zero-dim) universe OS is strongly closed.
185     set_strongly_closed();
186     refine_with_constraints(box.constraints());
187   }
188 }
189 
190 template <typename T>
191 inline
Octagonal_Shape(const Grid & grid,Complexity_Class)192 Octagonal_Shape<T>::Octagonal_Shape(const Grid& grid,
193                                     Complexity_Class)
194   : matrix(grid.space_dimension()),
195     space_dim(grid.space_dimension()),
196     status() {
197   if (grid.space_dimension() > 0) {
198     // A (non zero-dim) universe OS is strongly closed.
199     set_strongly_closed();
200   }
201   // Taking minimized congruences ensures maximum precision.
202   refine_with_congruences(grid.minimized_congruences());
203 }
204 
205 template <typename T>
206 template <typename U>
207 inline
Octagonal_Shape(const BD_Shape<U> & bd,Complexity_Class)208 Octagonal_Shape<T>::Octagonal_Shape(const BD_Shape<U>& bd,
209                                     Complexity_Class)
210   : matrix(bd.space_dimension()),
211     space_dim(bd.space_dimension()),
212     status() {
213   // Check for emptiness for maximum precision.
214   if (bd.is_empty()) {
215     set_empty();
216   }
217   else if (bd.space_dimension() > 0) {
218     // A (non zero-dim) universe OS is strongly closed.
219     set_strongly_closed();
220     refine_with_constraints(bd.constraints());
221   }
222 }
223 
224 template <typename T>
225 inline Congruence_System
congruences() const226 Octagonal_Shape<T>::congruences() const {
227   return minimized_congruences();
228 }
229 
230 template <typename T>
231 inline Octagonal_Shape<T>&
operator =(const Octagonal_Shape & y)232 Octagonal_Shape<T>::operator=(const Octagonal_Shape& y) {
233   matrix = y.matrix;
234   space_dim = y.space_dim;
235   status = y.status;
236   return *this;
237 }
238 
239 template <typename T>
240 inline
~Octagonal_Shape()241 Octagonal_Shape<T>::~Octagonal_Shape() {
242 }
243 
244 template <typename T>
245 inline void
m_swap(Octagonal_Shape & y)246 Octagonal_Shape<T>::m_swap(Octagonal_Shape& y) {
247   using std::swap;
248   swap(matrix, y.matrix);
249   swap(space_dim, y.space_dim);
250   swap(status, y.status);
251 }
252 
253 template <typename T>
254 inline dimension_type
space_dimension() const255 Octagonal_Shape<T>::space_dimension() const {
256   return space_dim;
257 }
258 
259 template <typename T>
260 inline bool
is_discrete() const261 Octagonal_Shape<T>::is_discrete() const {
262   return affine_dimension() == 0;
263 }
264 
265 template <typename T>
266 inline bool
is_empty() const267 Octagonal_Shape<T>::is_empty() const {
268   strong_closure_assign();
269   return marked_empty();
270 }
271 
272 template <typename T>
273 inline bool
bounds_from_above(const Linear_Expression & expr) const274 Octagonal_Shape<T>::bounds_from_above(const Linear_Expression& expr) const {
275   return bounds(expr, true);
276 }
277 
278 template <typename T>
279 inline bool
bounds_from_below(const Linear_Expression & expr) const280 Octagonal_Shape<T>::bounds_from_below(const Linear_Expression& expr) const {
281   return bounds(expr, false);
282 }
283 
284 template <typename T>
285 inline bool
maximize(const Linear_Expression & expr,Coefficient & sup_n,Coefficient & sup_d,bool & maximum) const286 Octagonal_Shape<T>::maximize(const Linear_Expression& expr,
287                              Coefficient& sup_n, Coefficient& sup_d,
288                              bool& maximum) const {
289   return max_min(expr, true, sup_n, sup_d, maximum);
290 }
291 
292 template <typename T>
293 inline bool
maximize(const Linear_Expression & expr,Coefficient & sup_n,Coefficient & sup_d,bool & maximum,Generator & g) const294 Octagonal_Shape<T>::maximize(const Linear_Expression& expr,
295                              Coefficient& sup_n, Coefficient& sup_d,
296                              bool& maximum,
297                              Generator& g) const {
298   return max_min(expr, true, sup_n, sup_d, maximum, g);
299 }
300 
301 template <typename T>
302 inline bool
minimize(const Linear_Expression & expr,Coefficient & inf_n,Coefficient & inf_d,bool & minimum) const303 Octagonal_Shape<T>::minimize(const Linear_Expression& expr,
304                              Coefficient& inf_n, Coefficient& inf_d,
305                              bool& minimum) const {
306   return max_min(expr, false, inf_n, inf_d, minimum);
307 }
308 
309 template <typename T>
310 inline bool
minimize(const Linear_Expression & expr,Coefficient & inf_n,Coefficient & inf_d,bool & minimum,Generator & g) const311 Octagonal_Shape<T>::minimize(const Linear_Expression& expr,
312                              Coefficient& inf_n, Coefficient& inf_d,
313                              bool& minimum,
314                              Generator& g) const {
315   return max_min(expr, false, inf_n, inf_d, minimum, g);
316 }
317 
318 template <typename T>
319 inline bool
is_topologically_closed() const320 Octagonal_Shape<T>::is_topologically_closed() const {
321   return true;
322 }
323 
324 template <typename T>
325 inline void
topological_closure_assign()326 Octagonal_Shape<T>::topological_closure_assign() {
327 }
328 
329 /*! \relates Octagonal_Shape */
330 template <typename T>
331 inline bool
operator ==(const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y)332 operator==(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y) {
333   if (x.space_dim != y.space_dim) {
334     // Dimension-incompatible OSs are different.
335     return false;
336   }
337   // Zero-dim OSs are equal if and only if they are both empty or universe.
338   if (x.space_dim == 0) {
339     if (x.marked_empty()) {
340       return y.marked_empty();
341     }
342     else {
343       return !y.marked_empty();
344     }
345   }
346 
347   x.strong_closure_assign();
348   y.strong_closure_assign();
349   // If one of two octagons is empty, then they are equal if and only if
350   // the other octagon is empty too.
351   if (x.marked_empty()) {
352     return y.marked_empty();
353   }
354   if (y.marked_empty()) {
355     return false;
356   }
357   // Strong closure is a canonical form.
358   return x.matrix == y.matrix;
359 }
360 
361 /*! \relates Octagonal_Shape */
362 template <typename T>
363 inline bool
operator !=(const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y)364 operator!=(const Octagonal_Shape<T>& x, const Octagonal_Shape<T>& y) {
365   return !(x == y);
366 }
367 
368 template <typename T>
369 inline const typename Octagonal_Shape<T>::coefficient_type&
matrix_at(const dimension_type i,const dimension_type j) const370 Octagonal_Shape<T>::matrix_at(const dimension_type i,
371                               const dimension_type j) const {
372   PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
373   using namespace Implementation::Octagonal_Shapes;
374   return (j < matrix.row_size(i))
375     ? matrix[i][j]
376     : matrix[coherent_index(j)][coherent_index(i)];
377 }
378 
379 template <typename T>
380 inline typename Octagonal_Shape<T>::coefficient_type&
matrix_at(const dimension_type i,const dimension_type j)381 Octagonal_Shape<T>::matrix_at(const dimension_type i,
382                               const dimension_type j) {
383   PPL_ASSERT(i < matrix.num_rows() && j < matrix.num_rows());
384   using namespace Implementation::Octagonal_Shapes;
385   return (j < matrix.row_size(i))
386     ? matrix[i][j]
387     : matrix[coherent_index(j)][coherent_index(i)];
388 }
389 
390 template <typename T>
391 inline Constraint_System
minimized_constraints() const392 Octagonal_Shape<T>::minimized_constraints() const {
393   strong_reduction_assign();
394   return constraints();
395 }
396 
397 template <typename T>
398 inline void
add_octagonal_constraint(const dimension_type i,const dimension_type j,const N & k)399 Octagonal_Shape<T>::add_octagonal_constraint(const dimension_type i,
400                                              const dimension_type j,
401                                              const N& k) {
402   // Private method: the caller has to ensure the following.
403 #ifndef NDEBUG
404   PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
405   typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
406   PPL_ASSERT(j < m_i.row_size());
407 #endif
408   N& r_i_j = matrix[i][j];
409   if (r_i_j > k) {
410     r_i_j = k;
411     if (marked_strongly_closed()) {
412       reset_strongly_closed();
413     }
414   }
415 }
416 
417 template <typename T>
418 inline void
419 Octagonal_Shape<T>
add_octagonal_constraint(const dimension_type i,const dimension_type j,Coefficient_traits::const_reference numer,Coefficient_traits::const_reference denom)420 ::add_octagonal_constraint(const dimension_type i,
421                            const dimension_type j,
422                            Coefficient_traits::const_reference numer,
423                            Coefficient_traits::const_reference denom) {
424 #ifndef NDEBUG
425   // Private method: the caller has to ensure the following.
426   PPL_ASSERT(i < 2*space_dim && j < 2*space_dim && i != j);
427   typename OR_Matrix<N>::row_iterator m_i = matrix.row_begin() + i;
428   PPL_ASSERT(j < m_i.row_size());
429   PPL_ASSERT(denom != 0);
430 #endif
431   PPL_DIRTY_TEMP(N, k);
432   div_round_up(k, numer, denom);
433   add_octagonal_constraint(i, j, k);
434 }
435 
436 template <typename T>
437 inline void
add_constraints(const Constraint_System & cs)438 Octagonal_Shape<T>::add_constraints(const Constraint_System& cs) {
439   for (Constraint_System::const_iterator i = cs.begin(),
440          i_end = cs.end(); i != i_end; ++i) {
441     add_constraint(*i);
442   }
443 }
444 
445 template <typename T>
446 inline void
add_recycled_constraints(Constraint_System & cs)447 Octagonal_Shape<T>::add_recycled_constraints(Constraint_System& cs) {
448   add_constraints(cs);
449 }
450 
451 template <typename T>
452 inline void
add_recycled_congruences(Congruence_System & cgs)453 Octagonal_Shape<T>::add_recycled_congruences(Congruence_System& cgs) {
454   add_congruences(cgs);
455 }
456 
457 template <typename T>
458 inline void
add_congruences(const Congruence_System & cgs)459 Octagonal_Shape<T>::add_congruences(const Congruence_System& cgs) {
460   for (Congruence_System::const_iterator i = cgs.begin(),
461          cgs_end = cgs.end(); i != cgs_end; ++i) {
462     add_congruence(*i);
463   }
464 }
465 
466 template <typename T>
467 inline void
refine_with_constraint(const Constraint & c)468 Octagonal_Shape<T>::refine_with_constraint(const Constraint& c) {
469   // Dimension-compatibility check.
470   if (c.space_dimension() > space_dimension()) {
471     throw_dimension_incompatible("refine_with_constraint(c)", c);
472   }
473 
474   if (!marked_empty()) {
475     refine_no_check(c);
476   }
477 }
478 
479 template <typename T>
480 inline void
refine_with_constraints(const Constraint_System & cs)481 Octagonal_Shape<T>::refine_with_constraints(const Constraint_System& cs) {
482   // Dimension-compatibility check.
483   if (cs.space_dimension() > space_dimension()) {
484     throw_invalid_argument("refine_with_constraints(cs)",
485                            "cs and *this are space-dimension incompatible");
486   }
487 
488   for (Constraint_System::const_iterator i = cs.begin(),
489          cs_end = cs.end(); !marked_empty() && i != cs_end; ++i) {
490     refine_no_check(*i);
491   }
492 }
493 
494 template <typename T>
495 inline void
refine_with_congruence(const Congruence & cg)496 Octagonal_Shape<T>::refine_with_congruence(const Congruence& cg) {
497   const dimension_type cg_space_dim = cg.space_dimension();
498   // Dimension-compatibility check.
499   if (cg_space_dim > space_dimension()) {
500     throw_dimension_incompatible("refine_with_congruence(cg)", cg);
501   }
502   if (!marked_empty()) {
503     refine_no_check(cg);
504   }
505 }
506 
507 template <typename T>
508 void
refine_with_congruences(const Congruence_System & cgs)509 Octagonal_Shape<T>::refine_with_congruences(const Congruence_System& cgs) {
510   // Dimension-compatibility check.
511   if (cgs.space_dimension() > space_dimension()) {
512     throw_invalid_argument("refine_with_congruences(cgs)",
513                            "cgs and *this are space-dimension incompatible");
514   }
515 
516   for (Congruence_System::const_iterator i = cgs.begin(),
517          cgs_end = cgs.end(); !marked_empty() && i != cgs_end; ++i) {
518     refine_no_check(*i);
519   }
520 }
521 
522 template <typename T>
523 inline void
refine_no_check(const Congruence & cg)524 Octagonal_Shape<T>::refine_no_check(const Congruence& cg) {
525   PPL_ASSERT(!marked_empty());
526   PPL_ASSERT(cg.space_dimension() <= space_dimension());
527 
528   if (cg.is_proper_congruence()) {
529     if (cg.is_inconsistent()) {
530       set_empty();
531     }
532     // Other proper congruences are just ignored.
533     return;
534   }
535 
536   PPL_ASSERT(cg.is_equality());
537   Constraint c(cg);
538   refine_no_check(c);
539 }
540 
541 template <typename T>
542 inline bool
can_recycle_constraint_systems()543 Octagonal_Shape<T>::can_recycle_constraint_systems() {
544   return false;
545 }
546 
547 template <typename T>
548 inline bool
can_recycle_congruence_systems()549 Octagonal_Shape<T>::can_recycle_congruence_systems() {
550   return false;
551 }
552 
553 template <typename T>
554 inline void
555 Octagonal_Shape<T>
remove_higher_space_dimensions(const dimension_type new_dimension)556 ::remove_higher_space_dimensions(const dimension_type new_dimension) {
557   // Dimension-compatibility check.
558   if (new_dimension > space_dim) {
559     throw_dimension_incompatible("remove_higher_space_dimension(nd)",
560                                  new_dimension);
561   }
562   // The removal of no dimensions from any octagon is a no-op.
563   // Note that this case also captures the only legal removal of
564   // dimensions from an octagon in a 0-dim space.
565   if (new_dimension == space_dim) {
566     PPL_ASSERT(OK());
567     return;
568   }
569 
570   strong_closure_assign();
571   matrix.shrink(new_dimension);
572   // When we remove all dimensions from a non-empty octagon,
573   // we obtain the zero-dimensional universe octagon.
574   if (new_dimension == 0 && !marked_empty()) {
575     set_zero_dim_univ();
576   }
577   space_dim = new_dimension;
578   PPL_ASSERT(OK());
579 }
580 
581 template <typename T>
582 void
wrap_assign(const Variables_Set & vars,Bounded_Integer_Type_Width w,Bounded_Integer_Type_Representation r,Bounded_Integer_Type_Overflow o,const Constraint_System * cs_p,unsigned complexity_threshold,bool wrap_individually)583 Octagonal_Shape<T>::wrap_assign(const Variables_Set& vars,
584                                 Bounded_Integer_Type_Width w,
585                                 Bounded_Integer_Type_Representation r,
586                                 Bounded_Integer_Type_Overflow o,
587                                 const Constraint_System* cs_p,
588                                 unsigned complexity_threshold,
589                                 bool wrap_individually) {
590   Implementation::wrap_assign(*this,
591                               vars, w, r, o, cs_p,
592                               complexity_threshold, wrap_individually,
593                               "Octagonal_Shape");
594 }
595 
596 template <typename T>
597 inline void
widening_assign(const Octagonal_Shape & y,unsigned * tp)598 Octagonal_Shape<T>::widening_assign(const Octagonal_Shape& y, unsigned* tp) {
599   BHMZ05_widening_assign(y, tp);
600 }
601 
602 template <typename T>
603 inline void
CC76_extrapolation_assign(const Octagonal_Shape & y,unsigned * tp)604 Octagonal_Shape<T>::CC76_extrapolation_assign(const Octagonal_Shape& y,
605                                               unsigned* tp) {
606   static N stop_points[] = {
607     N(-2, ROUND_UP),
608     N(-1, ROUND_UP),
609     N( 0, ROUND_UP),
610     N( 1, ROUND_UP),
611     N( 2, ROUND_UP)
612   };
613   CC76_extrapolation_assign(y,
614                             stop_points,
615                             stop_points
616                             + sizeof(stop_points)/sizeof(stop_points[0]),
617                             tp);
618 }
619 
620 template <typename T>
621 inline void
time_elapse_assign(const Octagonal_Shape & y)622 Octagonal_Shape<T>::time_elapse_assign(const Octagonal_Shape& y) {
623   // Dimension-compatibility check.
624   if (space_dimension() != y.space_dimension()) {
625     throw_dimension_incompatible("time_elapse_assign(y)", y);
626   }
627   // Compute time-elapse on polyhedra.
628   // TODO: provide a direct implementation.
629   C_Polyhedron ph_x(constraints());
630   C_Polyhedron ph_y(y.constraints());
631   ph_x.time_elapse_assign(ph_y);
632   Octagonal_Shape<T> x(ph_x);
633   m_swap(x);
634   PPL_ASSERT(OK());
635 }
636 
637 template <typename T>
638 inline bool
strictly_contains(const Octagonal_Shape & y) const639 Octagonal_Shape<T>::strictly_contains(const Octagonal_Shape& y) const {
640   const Octagonal_Shape<T>& x = *this;
641   return x.contains(y) && !y.contains(x);
642 }
643 
644 template <typename T>
645 template <typename Interval_Info>
646 inline void
generalized_refine_with_linear_form_inequality(const Linear_Form<Interval<T,Interval_Info>> & left,const Linear_Form<Interval<T,Interval_Info>> & right,const Relation_Symbol relsym)647 Octagonal_Shape<T>::generalized_refine_with_linear_form_inequality(
648                     const Linear_Form< Interval<T, Interval_Info> >& left,
649                     const Linear_Form< Interval<T, Interval_Info> >& right,
650                     const Relation_Symbol relsym) {
651   switch (relsym) {
652   case EQUAL:
653     // TODO: see if we can handle this case more efficiently.
654     refine_with_linear_form_inequality(left, right);
655     refine_with_linear_form_inequality(right, left);
656     break;
657   case LESS_THAN:
658   case LESS_OR_EQUAL:
659     refine_with_linear_form_inequality(left, right);
660     break;
661   case GREATER_THAN:
662   case GREATER_OR_EQUAL:
663     refine_with_linear_form_inequality(right, left);
664     break;
665   case NOT_EQUAL:
666     break;
667   default:
668     PPL_UNREACHABLE;
669     break;
670   }
671 }
672 
673 template <typename T>
674 template <typename Interval_Info>
675 inline void
676 Octagonal_Shape<T>::
refine_fp_interval_abstract_store(Box<Interval<T,Interval_Info>> & store) const677 refine_fp_interval_abstract_store(
678           Box< Interval<T, Interval_Info> >& store) const {
679 
680   // Check that T is a floating point type.
681   PPL_COMPILE_TIME_CHECK(!std::numeric_limits<T>::is_exact,
682                      "Octagonal_Shape<T>::refine_fp_interval_abstract_store:"
683                      " T not a floating point type.");
684 
685   typedef Interval<T, Interval_Info> FP_Interval_Type;
686   store.intersection_assign(Box<FP_Interval_Type>(*this));
687 
688 }
689 
690 /*! \relates Octagonal_Shape */
691 template <typename Temp, typename To, typename T>
692 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)693 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
694                             const Octagonal_Shape<T>& x,
695                             const Octagonal_Shape<T>& y,
696                             const Rounding_Dir dir,
697                             Temp& tmp0,
698                             Temp& tmp1,
699                             Temp& tmp2) {
700   // Dimension-compatibility check.
701   if (x.space_dim != y.space_dim) {
702     return false;
703   }
704   // Zero-dim OSs are equal if and only if they are both empty or universe.
705   if (x.space_dim == 0) {
706     if (x.marked_empty() == y.marked_empty()) {
707       assign_r(r, 0, ROUND_NOT_NEEDED);
708     }
709     else {
710       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
711     }
712     return true;
713   }
714 
715   // The distance computation requires strong closure.
716   x.strong_closure_assign();
717   y.strong_closure_assign();
718 
719   // If one of two OSs is empty, then they are equal if and only if
720   // the other OS is empty too.
721   if (x.marked_empty() ||  y.marked_empty()) {
722     if (x.marked_empty() == y.marked_empty()) {
723       assign_r(r, 0, ROUND_NOT_NEEDED);
724     }
725     else {
726       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
727     }
728     return true;
729   }
730 
731   return rectilinear_distance_assign(r, x.matrix, y.matrix, dir,
732                                      tmp0, tmp1, tmp2);
733 }
734 
735 /*! \relates Octagonal_Shape */
736 template <typename Temp, typename To, typename T>
737 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)738 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
739                             const Octagonal_Shape<T>& x,
740                             const Octagonal_Shape<T>& y,
741                             const Rounding_Dir dir) {
742   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
743   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
744   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
745   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
746   return rectilinear_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
747 }
748 
749 /*! \relates Octagonal_Shape */
750 template <typename To, typename T>
751 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)752 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
753                             const Octagonal_Shape<T>& x,
754                             const Octagonal_Shape<T>& y,
755                             const Rounding_Dir dir) {
756   return rectilinear_distance_assign<To, To, T>(r, x, y, dir);
757 }
758 
759 /*! \relates Octagonal_Shape */
760 template <typename Temp, typename To, typename T>
761 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)762 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
763                           const Octagonal_Shape<T>& x,
764                           const Octagonal_Shape<T>& y,
765                           const Rounding_Dir dir,
766                           Temp& tmp0,
767                           Temp& tmp1,
768                           Temp& tmp2) {
769   // Dimension-compatibility check.
770   if (x.space_dim != y.space_dim) {
771     return false;
772   }
773 
774   // Zero-dim OSs are equal if and only if they are both empty or universe.
775   if (x.space_dim == 0) {
776     if (x.marked_empty() == y.marked_empty()) {
777       assign_r(r, 0, ROUND_NOT_NEEDED);
778     }
779     else {
780       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
781     }
782     return true;
783   }
784 
785   // The distance computation requires strong closure.
786   x.strong_closure_assign();
787   y.strong_closure_assign();
788 
789   // If one of two OSs is empty, then they are equal if and only if
790   // the other OS is empty too.
791   if (x.marked_empty() ||  y.marked_empty()) {
792     if (x.marked_empty() == y.marked_empty()) {
793       assign_r(r, 0, ROUND_NOT_NEEDED);
794     }
795     else {
796       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
797     }
798     return true;
799   }
800 
801   return euclidean_distance_assign(r, x.matrix, y.matrix, dir,
802                                    tmp0, tmp1, tmp2);
803 }
804 
805 /*! \relates Octagonal_Shape */
806 template <typename Temp, typename To, typename T>
807 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)808 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
809                           const Octagonal_Shape<T>& x,
810                           const Octagonal_Shape<T>& y,
811                           const Rounding_Dir dir) {
812   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
813   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
814   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
815   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
816   return euclidean_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
817 }
818 
819 /*! \relates Octagonal_Shape */
820 template <typename To, typename T>
821 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)822 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
823                           const Octagonal_Shape<T>& x,
824                           const Octagonal_Shape<T>& y,
825                           const Rounding_Dir dir) {
826   return euclidean_distance_assign<To, To, T>(r, x, y, dir);
827 }
828 
829 /*! \relates Octagonal_Shape */
830 template <typename Temp, typename To, typename T>
831 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)832 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
833                            const Octagonal_Shape<T>& x,
834                            const Octagonal_Shape<T>& y,
835                            const Rounding_Dir dir,
836                            Temp& tmp0,
837                            Temp& tmp1,
838                            Temp& tmp2) {
839   // Dimension-compatibility check.
840   if (x.space_dim != y.space_dim) {
841     return false;
842   }
843   // Zero-dim OSs are equal if and only if they are both empty or universe.
844   if (x.space_dim == 0) {
845     if (x.marked_empty() == y.marked_empty()) {
846       assign_r(r, 0, ROUND_NOT_NEEDED);
847     }
848     else {
849       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
850     }
851     return true;
852   }
853 
854   // The distance computation requires strong closure.
855   x.strong_closure_assign();
856   y.strong_closure_assign();
857 
858   // If one of two OSs is empty, then they are equal if and only if
859   // the other OS is empty too.
860   if (x.marked_empty() ||  y.marked_empty()) {
861     if (x.marked_empty() == y.marked_empty()) {
862       assign_r(r, 0, ROUND_NOT_NEEDED);
863     }
864     else {
865       assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
866     }
867     return true;
868   }
869 
870   return l_infinity_distance_assign(r, x.matrix, y.matrix, dir,
871                                     tmp0, tmp1, tmp2);
872 }
873 
874 /*! \relates Octagonal_Shape */
875 template <typename Temp, typename To, typename T>
876 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)877 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
878                            const Octagonal_Shape<T>& x,
879                            const Octagonal_Shape<T>& y,
880                            const Rounding_Dir dir) {
881   typedef Checked_Number<Temp, Extended_Number_Policy> Checked_Temp;
882   PPL_DIRTY_TEMP(Checked_Temp, tmp0);
883   PPL_DIRTY_TEMP(Checked_Temp, tmp1);
884   PPL_DIRTY_TEMP(Checked_Temp, tmp2);
885   return l_infinity_distance_assign(r, x, y, dir, tmp0, tmp1, tmp2);
886 }
887 
888 /*! \relates Octagonal_Shape */
889 template <typename To, typename T>
890 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const Octagonal_Shape<T> & x,const Octagonal_Shape<T> & y,const Rounding_Dir dir)891 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
892                            const Octagonal_Shape<T>& x,
893                            const Octagonal_Shape<T>& y,
894                            const Rounding_Dir dir) {
895   return l_infinity_distance_assign<To, To, T>(r, x, y, dir);
896 }
897 
898 template <typename T>
899 inline memory_size_type
total_memory_in_bytes() const900 Octagonal_Shape<T>::total_memory_in_bytes() const {
901   return sizeof(*this) + external_memory_in_bytes();
902 }
903 
904 template <typename T>
905 inline int32_t
hash_code() const906 Octagonal_Shape<T>::hash_code() const {
907   return hash_code_from_dimension(space_dimension());
908 }
909 
910 template <typename T>
911 inline void
drop_some_non_integer_points_helper(N & elem)912 Octagonal_Shape<T>::drop_some_non_integer_points_helper(N& elem) {
913   if (!is_integer(elem)) {
914 #ifndef NDEBUG
915     Result r =
916 #endif
917     floor_assign_r(elem, elem, ROUND_DOWN);
918     PPL_ASSERT(r == V_EQ);
919     reset_strongly_closed();
920   }
921 }
922 
923 /*! \relates Octagonal_Shape */
924 template <typename T>
925 inline void
swap(Octagonal_Shape<T> & x,Octagonal_Shape<T> & y)926 swap(Octagonal_Shape<T>& x, Octagonal_Shape<T>& y) {
927   x.m_swap(y);
928 }
929 
930 } // namespace Parma_Polyhedra_Library
931 
932 #endif // !defined(PPL_Octagonal_Shape_inlines_hh)
933