1 /* OR_Matrix 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_OR_Matrix_inlines_hh
25 #define PPL_OR_Matrix_inlines_hh 1
26 
27 #include "globals_defs.hh"
28 #include "Checked_Number_defs.hh"
29 #include "C_Polyhedron_defs.hh"
30 #include "distances_defs.hh"
31 #include "assertions.hh"
32 #include "checked_defs.hh"
33 #include <algorithm>
34 
35 namespace Parma_Polyhedra_Library {
36 
37 template <typename T>
38 inline dimension_type
row_first_element_index(const dimension_type k)39 OR_Matrix<T>::row_first_element_index(const dimension_type k) {
40   return ((k + 1)*(k + 1))/2;
41 }
42 
43 template <typename T>
44 inline dimension_type
row_size(const dimension_type k)45 OR_Matrix<T>::row_size(const dimension_type k) {
46   return k + 2 - k % 2;
47 }
48 
49 #if PPL_OR_MATRIX_EXTRA_DEBUG
50 
51 template <typename T>
52 template <typename U>
53 inline dimension_type
size() const54 OR_Matrix<T>::Pseudo_Row<U>::size() const {
55   return size_;
56 }
57 
58 #endif // PPL_OR_MATRIX_EXTRA_DEBUG
59 
60 template <typename T>
61 template <typename U>
62 inline
Pseudo_Row()63 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row()
64   : first(0)
65 #if PPL_OR_MATRIX_EXTRA_DEBUG
66   , size_(0)
67 #endif
68 {
69 }
70 
71 template <typename T>
72 template <typename U>
73 inline
Pseudo_Row(U & y,dimension_type s)74 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(U& y
75 #if PPL_OR_MATRIX_EXTRA_DEBUG
76                 , dimension_type s
77 #endif
78                 )
79   : first(&y)
80 #if PPL_OR_MATRIX_EXTRA_DEBUG
81   , size_(s)
82 #endif
83 {
84 }
85 
86 template <typename T>
87 template <typename U>
88 template <typename V>
89 inline
Pseudo_Row(const Pseudo_Row<V> & y)90 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(const Pseudo_Row<V>& y)
91   : first(y.first)
92 #if PPL_OR_MATRIX_EXTRA_DEBUG
93     , size_(y.size_)
94 #endif
95 {
96 }
97 
98 template <typename T>
99 template <typename U>
100 inline typename OR_Matrix<T>::template Pseudo_Row<U>&
operator =(const Pseudo_Row & y)101 OR_Matrix<T>::Pseudo_Row<U>::operator=(const Pseudo_Row& y) {
102   first = y.first;
103 #if PPL_OR_MATRIX_EXTRA_DEBUG
104   size_ = y.size_;
105 #endif
106   return *this;
107 }
108 
109 template <typename T>
110 template <typename U>
111 inline
~Pseudo_Row()112 OR_Matrix<T>::Pseudo_Row<U>::~Pseudo_Row() {
113 }
114 
115 template <typename T>
116 template <typename U>
117 inline U&
operator [](const dimension_type k) const118 OR_Matrix<T>::Pseudo_Row<U>::operator[](const dimension_type k) const {
119 #if PPL_OR_MATRIX_EXTRA_DEBUG
120   PPL_ASSERT(k < size_);
121 #endif
122   return *(first + k);
123 }
124 
125 template <typename T>
126 template <typename U>
127 inline
128 OR_Matrix<T>::any_row_iterator<U>
any_row_iterator(const dimension_type n_rows)129 ::any_row_iterator(const dimension_type n_rows)
130   : value(),
131     e(n_rows)
132     // Field `i' is intentionally not initialized here.
133 {
134 #if PPL_OR_MATRIX_EXTRA_DEBUG
135   // Turn `value' into a valid object.
136   value.size_ = OR_Matrix::row_size(e);
137 #endif
138 }
139 
140 template <typename T>
141 template <typename U>
142 inline
any_row_iterator(U & base)143 OR_Matrix<T>::any_row_iterator<U>::any_row_iterator(U& base)
144   :  value(base
145 #if PPL_OR_MATRIX_EXTRA_DEBUG
146            , OR_Matrix<T>::row_size(0)
147 #endif
148            ),
149      e(0),
150      i(0) {
151 }
152 
153 template <typename T>
154 template <typename U>
155 template <typename V>
156 inline
157 OR_Matrix<T>::any_row_iterator<U>
any_row_iterator(const any_row_iterator<V> & y)158 ::any_row_iterator(const any_row_iterator<V>& y)
159   : value(y.value),
160     e(y.e),
161     i(y.i) {
162 }
163 
164 template <typename T>
165 template <typename U>
166 template <typename V>
167 inline typename OR_Matrix<T>::template any_row_iterator<U>&
operator =(const any_row_iterator<V> & y)168 OR_Matrix<T>::any_row_iterator<U>::operator=(const any_row_iterator<V>& y) {
169   value = y.value;
170   e = y.e;
171   i = y.i;
172   return *this;
173 }
174 
175 template <typename T>
176 template <typename U>
177 inline typename OR_Matrix<T>::template any_row_iterator<U>::reference
operator *() const178 OR_Matrix<T>::any_row_iterator<U>::operator*() const {
179   return value;
180 }
181 
182 template <typename T>
183 template <typename U>
184 inline typename OR_Matrix<T>::template any_row_iterator<U>::pointer
operator ->() const185 OR_Matrix<T>::any_row_iterator<U>::operator->() const {
186   return &value;
187 }
188 
189 template <typename T>
190 template <typename U>
191 inline typename OR_Matrix<T>::template any_row_iterator<U>&
operator ++()192 OR_Matrix<T>::any_row_iterator<U>::operator++() {
193   ++e;
194   dimension_type increment = e;
195   if (e % 2 != 0) {
196     ++increment;
197   }
198 #if PPL_OR_MATRIX_EXTRA_DEBUG
199   else {
200     value.size_ += 2;
201   }
202 #endif
203   i += increment;
204   value.first += increment;
205   return *this;
206 }
207 
208 template <typename T>
209 template <typename U>
210 inline typename OR_Matrix<T>::template any_row_iterator<U>
operator ++(int)211 OR_Matrix<T>::any_row_iterator<U>::operator++(int) {
212   any_row_iterator old = *this;
213   ++(*this);
214   return old;
215 }
216 
217 template <typename T>
218 template <typename U>
219 inline typename OR_Matrix<T>::template any_row_iterator<U>&
operator --()220 OR_Matrix<T>::any_row_iterator<U>::operator--() {
221   dimension_type decrement = e + 1;
222   --e;
223   if (e % 2 != 0) {
224     ++decrement;
225 #if PPL_OR_MATRIX_EXTRA_DEBUG
226     value.size_ -= 2;
227 #endif
228   }
229   i -= decrement;
230   value.first -= decrement;
231   return *this;
232 }
233 
234 template <typename T>
235 template <typename U>
236 inline typename OR_Matrix<T>::template any_row_iterator<U>
operator --(int)237 OR_Matrix<T>::any_row_iterator<U>::operator--(int) {
238   any_row_iterator old = *this;
239   --(*this);
240   return old;
241 }
242 
243 template <typename T>
244 template <typename U>
245 inline typename OR_Matrix<T>::template any_row_iterator<U>&
operator +=(const difference_type m)246 OR_Matrix<T>::any_row_iterator<U>::operator+=(const difference_type m) {
247   difference_type e_dt = static_cast<difference_type>(e);
248   difference_type i_dt = static_cast<difference_type>(i);
249   difference_type increment = m + (m * m) / 2 + m * e_dt;
250   if (e_dt % 2 == 0 && m % 2 != 0) {
251     ++increment;
252   }
253   e_dt += m;
254   i_dt += increment;
255   e = static_cast<dimension_type>(e_dt);
256   i = static_cast<dimension_type>(i_dt);
257   value.first += increment;
258 #if PPL_OR_MATRIX_EXTRA_DEBUG
259   difference_type value_size_dt = static_cast<difference_type>(value.size_);
260   value_size_dt += (m - m % 2);
261   value.size_ = static_cast<dimension_type>(value_size_dt);
262 #endif
263   return *this;
264 }
265 
266 template <typename T>
267 template <typename U>
268 template <typename Unsigned>
269 inline typename
270 Enable_If<(static_cast<Unsigned>(-1) > 0),
271             typename OR_Matrix<T>::template any_row_iterator<U>& >::type
operator +=(Unsigned m)272 OR_Matrix<T>::any_row_iterator<U>::operator+=(Unsigned m) {
273   dimension_type n = m;
274   dimension_type increment = n + (n*n)/2 + n*e;
275   if (e % 2 == 0 && n % 2 != 0) {
276     ++increment;
277   }
278   e += n;
279   i += increment;
280   value.first += increment;
281 #if PPL_OR_MATRIX_EXTRA_DEBUG
282   value.size_ = value.size_ + n - n % 2;
283 #endif
284   return *this;
285 }
286 
287 template <typename T>
288 template <typename U>
289 inline typename OR_Matrix<T>::template any_row_iterator<U>&
operator -=(difference_type m)290 OR_Matrix<T>::any_row_iterator<U>::operator-=(difference_type m) {
291   return *this += -m;
292 }
293 
294 template <typename T>
295 template <typename U>
296 inline typename OR_Matrix<T>::template any_row_iterator<U>::difference_type
operator -(const any_row_iterator & y) const297 OR_Matrix<T>::any_row_iterator<U>::operator-(const any_row_iterator& y) const {
298   return e - y.e;
299 }
300 
301 template <typename T>
302 template <typename U>
303 inline typename OR_Matrix<T>::template any_row_iterator<U>
operator +(difference_type m) const304 OR_Matrix<T>::any_row_iterator<U>::operator+(difference_type m) const {
305   any_row_iterator r = *this;
306   r += m;
307   return r;
308 }
309 
310 template <typename T>
311 template <typename U>
312 template <typename Unsigned>
313 inline typename
314 Enable_If<(static_cast<Unsigned>(-1) > 0),
315             typename OR_Matrix<T>::template any_row_iterator<U> >::type
operator +(Unsigned m) const316 OR_Matrix<T>::any_row_iterator<U>::operator+(Unsigned m) const {
317   any_row_iterator r = *this;
318   r += m;
319   return r;
320 }
321 
322 template <typename T>
323 template <typename U>
324 inline typename OR_Matrix<T>::template any_row_iterator<U>
operator -(const difference_type m) const325 OR_Matrix<T>::any_row_iterator<U>::operator-(const difference_type m) const {
326   any_row_iterator r = *this;
327   r -= m;
328   return r;
329 }
330 
331 template <typename T>
332 template <typename U>
333 inline bool
334 OR_Matrix<T>::any_row_iterator<U>
operator ==(const any_row_iterator & y) const335 ::operator==(const any_row_iterator& y) const {
336   return e == y.e;
337 }
338 
339 template <typename T>
340 template <typename U>
341 inline bool
342 OR_Matrix<T>::any_row_iterator<U>
operator !=(const any_row_iterator & y) const343 ::operator!=(const any_row_iterator& y) const {
344   return e != y.e;
345 }
346 
347 template <typename T>
348 template <typename U>
349 inline bool
operator <(const any_row_iterator & y) const350 OR_Matrix<T>::any_row_iterator<U>::operator<(const any_row_iterator& y) const {
351   return e < y.e;
352 }
353 
354 template <typename T>
355 template <typename U>
356 inline bool
357 OR_Matrix<T>::any_row_iterator<U>
operator <=(const any_row_iterator & y) const358 ::operator<=(const any_row_iterator& y) const {
359   return e <= y.e;
360 }
361 
362 template <typename T>
363 template <typename U>
364 inline bool
operator >(const any_row_iterator & y) const365 OR_Matrix<T>::any_row_iterator<U>::operator>(const any_row_iterator& y) const {
366   return e > y.e;
367 }
368 
369 template <typename T>
370 template <typename U>
371 inline bool
372 OR_Matrix<T>::any_row_iterator<U>
operator >=(const any_row_iterator & y) const373 ::operator>=(const any_row_iterator& y) const {
374   return e >= y.e;
375 }
376 
377 template <typename T>
378 template <typename U>
379 inline dimension_type
row_size() const380 OR_Matrix<T>::any_row_iterator<U>::row_size() const {
381   return OR_Matrix::row_size(e);
382 }
383 
384 template <typename T>
385 template <typename U>
386 inline dimension_type
index() const387 OR_Matrix<T>::any_row_iterator<U>::index() const {
388   return e;
389 }
390 
391 template <typename T>
392 inline typename OR_Matrix<T>::row_iterator
row_begin()393 OR_Matrix<T>::row_begin() {
394   return num_rows() == 0 ? row_iterator(0) : row_iterator(vec[0]);
395 }
396 
397 template <typename T>
398 inline typename OR_Matrix<T>::row_iterator
row_end()399 OR_Matrix<T>::row_end() {
400   return row_iterator(num_rows());
401 }
402 
403 template <typename T>
404 inline typename OR_Matrix<T>::const_row_iterator
row_begin() const405 OR_Matrix<T>::row_begin() const {
406   return num_rows() == 0 ? const_row_iterator(0) : const_row_iterator(vec[0]);
407 }
408 
409 template <typename T>
410 inline typename OR_Matrix<T>::const_row_iterator
row_end() const411 OR_Matrix<T>::row_end() const {
412   return const_row_iterator(num_rows());
413 }
414 
415 template <typename T>
416 inline typename OR_Matrix<T>::element_iterator
element_begin()417 OR_Matrix<T>::element_begin() {
418   return vec.begin();
419 }
420 
421 template <typename T>
422 inline typename OR_Matrix<T>::element_iterator
element_end()423 OR_Matrix<T>::element_end() {
424   return vec.end();
425 }
426 
427 template <typename T>
428 inline typename OR_Matrix<T>::const_element_iterator
element_begin() const429 OR_Matrix<T>::element_begin() const {
430   return vec.begin();
431 }
432 
433 template <typename T>
434 inline typename OR_Matrix<T>::const_element_iterator
element_end() const435 OR_Matrix<T>::element_end() const {
436   return vec.end();
437 }
438 
439 template <typename T>
440 inline void
m_swap(OR_Matrix & y)441 OR_Matrix<T>::m_swap(OR_Matrix& y) {
442   using std::swap;
443   swap(vec, y.vec);
444   swap(space_dim, y.space_dim);
445   swap(vec_capacity, y.vec_capacity);
446 }
447 
448 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
449 //! Returns the integer square root of \p x.
450 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
451 inline dimension_type
isqrt(dimension_type x)452 isqrt(dimension_type x) {
453   dimension_type r = 0;
454   const dimension_type FIRST_BIT_MASK = 0x40000000U;
455   for (dimension_type t = FIRST_BIT_MASK; t != 0; t >>= 2) {
456     const dimension_type s = r + t;
457     if (s <= x) {
458       x -= s;
459       r = s + t;
460     }
461     r >>= 1;
462   }
463   return r;
464 }
465 
466 template <typename T>
467 inline dimension_type
max_num_rows()468 OR_Matrix<T>::max_num_rows() {
469   // Compute the maximum number of rows that are contained in a DB_Row
470   // that allocates a pseudo-triangular matrix.
471   const dimension_type k = isqrt(2*DB_Row<T>::max_size() + 1);
472   return (k - 1) - (k - 1) % 2;
473 }
474 
475 template <typename T>
476 inline memory_size_type
total_memory_in_bytes() const477 OR_Matrix<T>::total_memory_in_bytes() const {
478   return sizeof(*this) + external_memory_in_bytes();
479 }
480 
481 template <typename T>
482 inline
OR_Matrix(const dimension_type num_dimensions)483 OR_Matrix<T>::OR_Matrix(const dimension_type num_dimensions)
484   : vec(2*num_dimensions*(num_dimensions + 1)),
485     space_dim(num_dimensions),
486     vec_capacity(vec.size()) {
487 }
488 
489 template <typename T>
490 inline
~OR_Matrix()491 OR_Matrix<T>::~OR_Matrix() {
492 }
493 
494 template <typename T>
495 inline typename OR_Matrix<T>::row_reference_type
operator [](dimension_type k)496 OR_Matrix<T>::operator[](dimension_type k) {
497   return row_reference_type(vec[row_first_element_index(k)]
498 #if PPL_OR_MATRIX_EXTRA_DEBUG
499                             , row_size(k)
500 #endif
501                             );
502 }
503 
504 template <typename T>
505 inline typename OR_Matrix<T>::const_row_reference_type
operator [](dimension_type k) const506 OR_Matrix<T>::operator[](dimension_type k) const {
507   return const_row_reference_type(vec[row_first_element_index(k)]
508 #if PPL_OR_MATRIX_EXTRA_DEBUG
509                                   , row_size(k)
510 #endif
511                                   );
512 }
513 
514 template <typename T>
515 inline dimension_type
space_dimension() const516 OR_Matrix<T>::space_dimension() const {
517   return space_dim;
518 }
519 
520 template <typename T>
521 inline dimension_type
num_rows() const522 OR_Matrix<T>::num_rows() const {
523   return 2*space_dimension();
524 }
525 
526 template <typename T>
527 inline void
clear()528 OR_Matrix<T>::clear() {
529   OR_Matrix<T>(0).m_swap(*this);
530 }
531 
532 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
533 /*! \relates OR_Matrix */
534 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
535 template <typename T>
536 inline bool
operator ==(const OR_Matrix<T> & x,const OR_Matrix<T> & y)537 operator==(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
538   return x.space_dim == y.space_dim && x.vec == y.vec;
539 }
540 
541 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
542 /*! \relates OR_Matrix */
543 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
544 template <typename T>
545 inline bool
operator !=(const OR_Matrix<T> & x,const OR_Matrix<T> & y)546 operator!=(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
547   return !(x == y);
548 }
549 
550 template <typename T>
551 inline
OR_Matrix(const OR_Matrix & y)552 OR_Matrix<T>::OR_Matrix(const OR_Matrix& y)
553   : vec(y.vec),
554     space_dim(y.space_dim),
555     vec_capacity(compute_capacity(y.vec.size(),
556                                   DB_Row<T>::max_size())) {
557 }
558 
559 template <typename T>
560 template <typename U>
561 inline
OR_Matrix(const OR_Matrix<U> & y)562 OR_Matrix<T>::OR_Matrix(const OR_Matrix<U>& y)
563   : vec(),
564     space_dim(y.space_dim),
565     vec_capacity(compute_capacity(y.vec.size(),
566                                   DB_Row<T>::max_size())) {
567   vec.construct_upward_approximation(y.vec, vec_capacity);
568   PPL_ASSERT(OK());
569 }
570 
571 template <typename T>
572 inline OR_Matrix<T>&
operator =(const OR_Matrix & y)573 OR_Matrix<T>::operator=(const OR_Matrix& y) {
574   vec = y.vec;
575   space_dim = y.space_dim;
576   vec_capacity = compute_capacity(y.vec.size(), DB_Row<T>::max_size());
577   return *this;
578 }
579 
580 template <typename T>
581 inline void
grow(const dimension_type new_dim)582 OR_Matrix<T>::grow(const dimension_type new_dim) {
583   PPL_ASSERT(new_dim >= space_dim);
584   if (new_dim > space_dim) {
585     const dimension_type new_size = 2*new_dim*(new_dim + 1);
586     if (new_size <= vec_capacity) {
587       // We can recycle the old vec.
588       vec.expand_within_capacity(new_size);
589       space_dim = new_dim;
590     }
591     else {
592       // We cannot recycle the old vec.
593       OR_Matrix<T> new_matrix(new_dim);
594       element_iterator j = new_matrix.element_begin();
595       for (element_iterator i = element_begin(),
596              mend = element_end(); i != mend; ++i, ++j) {
597         assign_or_swap(*j, *i);
598       }
599       m_swap(new_matrix);
600     }
601   }
602 }
603 
604 template <typename T>
605 inline void
shrink(const dimension_type new_dim)606 OR_Matrix<T>::shrink(const dimension_type new_dim) {
607   PPL_ASSERT(new_dim <= space_dim);
608   const dimension_type new_size = 2*new_dim*(new_dim + 1);
609   vec.shrink(new_size);
610   space_dim = new_dim;
611 }
612 
613 template <typename T>
614 inline void
resize_no_copy(const dimension_type new_dim)615 OR_Matrix<T>::resize_no_copy(const dimension_type new_dim) {
616   if (new_dim > space_dim) {
617     const dimension_type new_size = 2*new_dim*(new_dim + 1);
618     if (new_size <= vec_capacity) {
619       // We can recycle the old vec.
620       vec.expand_within_capacity(new_size);
621       space_dim = new_dim;
622     }
623     else {
624       // We cannot recycle the old vec.
625       OR_Matrix<T> new_matrix(new_dim);
626       m_swap(new_matrix);
627     }
628   }
629   else if (new_dim < space_dim) {
630     shrink(new_dim);
631   }
632 }
633 
634 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
635 /*! \relates OR_Matrix */
636 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
637 template <typename Specialization, typename Temp, typename To, typename T>
638 inline bool
l_m_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const OR_Matrix<T> & x,const OR_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)639 l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
640                     const OR_Matrix<T>& x,
641                     const OR_Matrix<T>& y,
642                     const Rounding_Dir dir,
643                     Temp& tmp0,
644                     Temp& tmp1,
645                     Temp& tmp2) {
646   if (x.num_rows() != y.num_rows()) {
647     return false;
648   }
649   assign_r(tmp0, 0, ROUND_NOT_NEEDED);
650   for (typename OR_Matrix<T>::const_element_iterator
651          i = x.element_begin(), j = y.element_begin(),
652          mat_end = x.element_end(); i != mat_end; ++i, ++j) {
653     const T& x_i = *i;
654     const T& y_i = *j;
655     if (is_plus_infinity(x_i)) {
656       if (is_plus_infinity(y_i)) {
657         continue;
658       }
659       else {
660       pinf:
661         assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
662         return true;
663       }
664     }
665     else if (is_plus_infinity(y_i)) {
666       goto pinf;
667     }
668     const Temp* tmp1p;
669     const Temp* tmp2p;
670     if (x_i > y_i) {
671       maybe_assign(tmp1p, tmp1, x_i, dir);
672       maybe_assign(tmp2p, tmp2, y_i, inverse(dir));
673     }
674     else {
675       maybe_assign(tmp1p, tmp1, y_i, dir);
676       maybe_assign(tmp2p, tmp2, x_i, inverse(dir));
677     }
678     sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
679     PPL_ASSERT(sgn(tmp1) >= 0);
680     Specialization::combine(tmp0, tmp1, dir);
681   }
682 
683   Specialization::finalize(tmp0, dir);
684   assign_r(r, tmp0, dir);
685   return true;
686 }
687 
688 
689 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
690 /*! \relates OR_Matrix */
691 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
692 template <typename Temp, typename To, typename T>
693 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const OR_Matrix<T> & x,const OR_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)694 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
695                             const OR_Matrix<T>& x,
696                             const OR_Matrix<T>& y,
697                             const Rounding_Dir dir,
698                             Temp& tmp0,
699                             Temp& tmp1,
700                             Temp& tmp2) {
701   return
702     l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
703                                                                     dir,
704                                                                     tmp0,
705                                                                     tmp1,
706                                                                     tmp2);
707 }
708 
709 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
710 /*! \relates OR_Matrix */
711 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
712 template <typename Temp, typename To, typename T>
713 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const OR_Matrix<T> & x,const OR_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)714 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
715                           const OR_Matrix<T>& x,
716                           const OR_Matrix<T>& y,
717                           const Rounding_Dir dir,
718                           Temp& tmp0,
719                           Temp& tmp1,
720                           Temp& tmp2) {
721   return
722     l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
723                                                                   dir,
724                                                                   tmp0,
725                                                                   tmp1,
726                                                                   tmp2);
727 }
728 
729 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
730 /*! \relates OR_Matrix */
731 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
732 template <typename Temp, typename To, typename T>
733 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const OR_Matrix<T> & x,const OR_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)734 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
735                            const OR_Matrix<T>& x,
736                            const OR_Matrix<T>& y,
737                            const Rounding_Dir dir,
738                            Temp& tmp0,
739                            Temp& tmp1,
740                            Temp& tmp2) {
741   return
742     l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
743                                                                    dir,
744                                                                    tmp0,
745                                                                    tmp1,
746                                                                    tmp2);
747 }
748 
749 /*! \relates OR_Matrix */
750 template <typename T>
751 inline void
swap(OR_Matrix<T> & x,OR_Matrix<T> & y)752 swap(OR_Matrix<T>& x, OR_Matrix<T>& y) {
753   x.m_swap(y);
754 }
755 
756 } // namespace Parma_Polyhedra_Library
757 
758 #endif // !defined(PPL_OR_Matrix_inlines_hh)
759