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