00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef PPL_OR_Matrix_inlines_hh
00026 #define PPL_OR_Matrix_inlines_hh 1
00027
00028 #include "globals.defs.hh"
00029 #include "Checked_Number.defs.hh"
00030 #include "C_Polyhedron.defs.hh"
00031 #include "distances.defs.hh"
00032 #include "assert.hh"
00033 #include <algorithm>
00034 #include "checked.defs.hh"
00035
00036 namespace Parma_Polyhedra_Library {
00037
00038 template <typename T>
00039 inline dimension_type
00040 OR_Matrix<T>::row_first_element_index(const dimension_type k) {
00041 return ((k + 1)*(k + 1))/2;
00042 }
00043
00044 template <typename T>
00045 inline dimension_type
00046 OR_Matrix<T>::row_size(const dimension_type k) {
00047 return k + 2 - k%2;
00048 }
00049
00050 #if PPL_OR_MATRIX_EXTRA_DEBUG
00051
00052 template <typename T>
00053 template <typename U>
00054 inline dimension_type
00055 OR_Matrix<T>::Pseudo_Row<U>::size() const {
00056 return size_;
00057 }
00058
00059 #endif // PPL_OR_MATRIX_EXTRA_DEBUG
00060
00061 template <typename T>
00062 template <typename U>
00063 inline
00064 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row()
00065 : first(0)
00066 #if PPL_OR_MATRIX_EXTRA_DEBUG
00067 , size_(0)
00068 #endif
00069 {
00070 }
00071
00072 template <typename T>
00073 template <typename U>
00074 inline
00075 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(U& y
00076 #if PPL_OR_MATRIX_EXTRA_DEBUG
00077 , dimension_type s
00078 #endif
00079 )
00080 : first(&y)
00081 #if PPL_OR_MATRIX_EXTRA_DEBUG
00082 , size_(s)
00083 #endif
00084 {
00085 }
00086
00087 template <typename T>
00088 template <typename U>
00089 template <typename V>
00090 inline
00091 OR_Matrix<T>::Pseudo_Row<U>::Pseudo_Row(const Pseudo_Row<V>& y)
00092 : first(y.first)
00093 #if PPL_OR_MATRIX_EXTRA_DEBUG
00094 , size_(y.size_)
00095 #endif
00096 {
00097 }
00098
00099 template <typename T>
00100 template <typename U>
00101 inline OR_Matrix<T>::Pseudo_Row<U>&
00102 OR_Matrix<T>::Pseudo_Row<U>::operator=(const Pseudo_Row& y) {
00103 first = y.first;
00104 #if PPL_OR_MATRIX_EXTRA_DEBUG
00105 size_ = y.size_;
00106 #endif
00107 return *this;
00108 }
00109
00110 template <typename T>
00111 template <typename U>
00112 inline
00113 OR_Matrix<T>::Pseudo_Row<U>::~Pseudo_Row() {
00114 }
00115
00116 template <typename T>
00117 template <typename U>
00118 inline U&
00119 OR_Matrix<T>::Pseudo_Row<U>::operator[](const dimension_type k) const {
00120 #if PPL_OR_MATRIX_EXTRA_DEBUG
00121 PPL_ASSERT(k < size_);
00122 #endif
00123 return *(first + k);
00124 }
00125
00126 template <typename T>
00127 template <typename U>
00128 inline
00129 OR_Matrix<T>::any_row_iterator<U>
00130 ::any_row_iterator(const dimension_type n_rows)
00131 : value(),
00132 e(n_rows)
00133
00134 {
00135 #if PPL_OR_MATRIX_EXTRA_DEBUG
00136
00137 value.size_ = OR_Matrix::row_size(e);
00138 #endif
00139 }
00140
00141 template <typename T>
00142 template <typename U>
00143 inline
00144 OR_Matrix<T>::any_row_iterator<U>::any_row_iterator(U& base)
00145 : value(base
00146 #if PPL_OR_MATRIX_EXTRA_DEBUG
00147 , OR_Matrix<T>::row_size(0)
00148 #endif
00149 ),
00150 e(0),
00151 i(0) {
00152 }
00153
00154 template <typename T>
00155 template <typename U>
00156 template <typename V>
00157 inline
00158 OR_Matrix<T>::any_row_iterator<U>
00159 ::any_row_iterator(const any_row_iterator<V>& y)
00160 : value(y.value),
00161 e(y.e),
00162 i(y.i) {
00163 }
00164
00165 template <typename T>
00166 template <typename U>
00167 template <typename V>
00168 inline typename OR_Matrix<T>::template any_row_iterator<U>&
00169 OR_Matrix<T>::any_row_iterator<U>::operator=(const any_row_iterator<V>& y) {
00170 value = y.value;
00171 e = y.e;
00172 i = y.i;
00173 return *this;
00174 }
00175
00176 template <typename T>
00177 template <typename U>
00178 inline typename OR_Matrix<T>::template any_row_iterator<U>::reference
00179 OR_Matrix<T>::any_row_iterator<U>::operator*() const {
00180 return value;
00181 }
00182
00183 template <typename T>
00184 template <typename U>
00185 inline typename OR_Matrix<T>::template any_row_iterator<U>::pointer
00186 OR_Matrix<T>::any_row_iterator<U>::operator->() const {
00187 return &value;
00188 }
00189
00190 template <typename T>
00191 template <typename U>
00192 inline typename OR_Matrix<T>::template any_row_iterator<U>&
00193 OR_Matrix<T>::any_row_iterator<U>::operator++() {
00194 ++e;
00195 dimension_type increment = e;
00196 if (e % 2 != 0)
00197 ++increment;
00198 #if PPL_OR_MATRIX_EXTRA_DEBUG
00199 else {
00200 value.size_ += 2;
00201 }
00202 #endif
00203 i += increment;
00204 value.first += increment;
00205 return *this;
00206 }
00207
00208 template <typename T>
00209 template <typename U>
00210 inline typename OR_Matrix<T>::template any_row_iterator<U>
00211 OR_Matrix<T>::any_row_iterator<U>::operator++(int) {
00212 any_row_iterator old = *this;
00213 ++(*this);
00214 return old;
00215 }
00216
00217 template <typename T>
00218 template <typename U>
00219 inline typename OR_Matrix<T>::template any_row_iterator<U>&
00220 OR_Matrix<T>::any_row_iterator<U>::operator--() {
00221 dimension_type decrement = e + 1;
00222 --e;
00223 if (e % 2 != 0) {
00224 ++decrement;
00225 #if PPL_OR_MATRIX_EXTRA_DEBUG
00226 value.size_ -= 2;
00227 #endif
00228 }
00229 i -= decrement;
00230 value.first -= decrement;
00231 return *this;
00232 }
00233
00234 template <typename T>
00235 template <typename U>
00236 inline typename OR_Matrix<T>::template any_row_iterator<U>
00237 OR_Matrix<T>::any_row_iterator<U>::operator--(int) {
00238 any_row_iterator old = *this;
00239 --(*this);
00240 return old;
00241 }
00242
00243 template <typename T>
00244 template <typename U>
00245 inline typename OR_Matrix<T>::template any_row_iterator<U>&
00246 OR_Matrix<T>::any_row_iterator<U>::operator+=(const difference_type m) {
00247 difference_type increment = m + m*m/2 + m*e;
00248 if (e % 2 == 0 && m % 2 != 0)
00249 ++increment;
00250 e += m;
00251 i += increment;
00252 value.first += increment;
00253 #if PPL_OR_MATRIX_EXTRA_DEBUG
00254 value.size_ += (m - m%2);
00255 #endif
00256 return *this;
00257 }
00258
00259 template <typename T>
00260 template <typename U>
00261 inline typename OR_Matrix<T>::template any_row_iterator<U>&
00262 OR_Matrix<T>::any_row_iterator<U>::operator-=(difference_type m) {
00263 return *this += -m;
00264 }
00265
00266 template <typename T>
00267 template <typename U>
00268 inline typename OR_Matrix<T>::template any_row_iterator<U>::difference_type
00269 OR_Matrix<T>::any_row_iterator<U>::operator-(const any_row_iterator& y) const {
00270 return e - y.e;
00271 }
00272
00273 template <typename T>
00274 template <typename U>
00275 inline typename OR_Matrix<T>::template any_row_iterator<U>
00276 OR_Matrix<T>::any_row_iterator<U>::operator+(difference_type m) const {
00277 any_row_iterator r = *this;
00278 r += m;
00279 return r;
00280 }
00281
00282 template <typename T>
00283 template <typename U>
00284 inline typename OR_Matrix<T>::template any_row_iterator<U>
00285 OR_Matrix<T>::any_row_iterator<U>::operator-(const difference_type m) const {
00286 any_row_iterator r = *this;
00287 r -= m;
00288 return r;
00289 }
00290
00291 template <typename T>
00292 template <typename U>
00293 inline bool
00294 OR_Matrix<T>::any_row_iterator<U>
00295 ::operator==(const any_row_iterator& y) const {
00296 return e == y.e;
00297 }
00298
00299 template <typename T>
00300 template <typename U>
00301 inline bool
00302 OR_Matrix<T>::any_row_iterator<U>
00303 ::operator!=(const any_row_iterator& y) const {
00304 return e != y.e;
00305 }
00306
00307 template <typename T>
00308 template <typename U>
00309 inline bool
00310 OR_Matrix<T>::any_row_iterator<U>::operator<(const any_row_iterator& y) const {
00311 return e < y.e;
00312 }
00313
00314 template <typename T>
00315 template <typename U>
00316 inline bool
00317 OR_Matrix<T>::any_row_iterator<U>
00318 ::operator<=(const any_row_iterator& y) const {
00319 return e <= y.e;
00320 }
00321
00322 template <typename T>
00323 template <typename U>
00324 inline bool
00325 OR_Matrix<T>::any_row_iterator<U>::operator>(const any_row_iterator& y) const {
00326 return e > y.e;
00327 }
00328
00329 template <typename T>
00330 template <typename U>
00331 inline bool
00332 OR_Matrix<T>::any_row_iterator<U>
00333 ::operator>=(const any_row_iterator& y) const {
00334 return e >= y.e;
00335 }
00336
00337 template <typename T>
00338 template <typename U>
00339 inline dimension_type
00340 OR_Matrix<T>::any_row_iterator<U>::row_size() const {
00341 return OR_Matrix::row_size(e);
00342 }
00343
00344 template <typename T>
00345 template <typename U>
00346 inline dimension_type
00347 OR_Matrix<T>::any_row_iterator<U>::index() const {
00348 return e;
00349 }
00350
00351 template <typename T>
00352 inline typename OR_Matrix<T>::row_iterator
00353 OR_Matrix<T>::row_begin() {
00354 return num_rows() == 0 ? row_iterator(0) : row_iterator(vec[0]);
00355 }
00356
00357 template <typename T>
00358 inline typename OR_Matrix<T>::row_iterator
00359 OR_Matrix<T>::row_end() {
00360 return row_iterator(num_rows());
00361 }
00362
00363 template <typename T>
00364 inline typename OR_Matrix<T>::const_row_iterator
00365 OR_Matrix<T>::row_begin() const {
00366 return num_rows() == 0 ? const_row_iterator(0) : const_row_iterator(vec[0]);
00367 }
00368
00369 template <typename T>
00370 inline typename OR_Matrix<T>::const_row_iterator
00371 OR_Matrix<T>::row_end() const {
00372 return const_row_iterator(num_rows());
00373 }
00374
00375 template <typename T>
00376 inline typename OR_Matrix<T>::element_iterator
00377 OR_Matrix<T>::element_begin() {
00378 return vec.begin();
00379 }
00380
00381 template <typename T>
00382 inline typename OR_Matrix<T>::element_iterator
00383 OR_Matrix<T>::element_end() {
00384 return vec.end();
00385 }
00386
00387 template <typename T>
00388 inline typename OR_Matrix<T>::const_element_iterator
00389 OR_Matrix<T>::element_begin() const {
00390 return vec.begin();
00391 }
00392
00393 template <typename T>
00394 inline typename OR_Matrix<T>::const_element_iterator
00395 OR_Matrix<T>::element_end() const {
00396 return vec.end();
00397 }
00398
00399 template <typename T>
00400 inline void
00401 OR_Matrix<T>::swap(OR_Matrix& y) {
00402 std::swap(vec, y.vec);
00403 std::swap(space_dim, y.space_dim);
00404 std::swap(vec_capacity, y.vec_capacity);
00405 }
00406
00408 inline unsigned long
00409 isqrt(unsigned long x) {
00410 unsigned long r = 0;
00411 for (unsigned long t = 0x40000000; t; t >>= 2) {
00412 unsigned long s = r + t;
00413 if (s <= x) {
00414 x -= s;
00415 r = s + t;
00416 }
00417 r >>= 1;
00418 }
00419 return r;
00420 }
00421
00422 template <typename T>
00423 inline dimension_type
00424 OR_Matrix<T>::max_num_rows() {
00425
00426
00427 dimension_type k = isqrt(2*DB_Row<T>::max_size() + 1);
00428 return (k - 1) - (k - 1)%2;
00429 }
00430
00431 template <typename T>
00432 inline memory_size_type
00433 OR_Matrix<T>::total_memory_in_bytes() const {
00434 return sizeof(*this) + external_memory_in_bytes();
00435 }
00436
00437 template <typename T>
00438 inline
00439 OR_Matrix<T>::OR_Matrix(const dimension_type dim)
00440 : vec(2*dim*(dim+1)),
00441 space_dim(dim),
00442 vec_capacity(vec.size()) {
00443 }
00444
00445 template <typename T>
00446 inline
00447 OR_Matrix<T>::~OR_Matrix() {
00448 }
00449
00450 template <typename T>
00451 inline typename OR_Matrix<T>::row_reference_type
00452 OR_Matrix<T>::operator[](dimension_type k) {
00453 return row_reference_type(vec[row_first_element_index(k)]
00454 #if PPL_OR_MATRIX_EXTRA_DEBUG
00455 , row_size(k)
00456 #endif
00457 );
00458 }
00459
00460 template <typename T>
00461 inline typename OR_Matrix<T>::const_row_reference_type
00462 OR_Matrix<T>::operator[](dimension_type k) const {
00463 return const_row_reference_type(vec[row_first_element_index(k)]
00464 #if PPL_OR_MATRIX_EXTRA_DEBUG
00465 , row_size(k)
00466 #endif
00467 );
00468 }
00469
00470 template <typename T>
00471 inline dimension_type
00472 OR_Matrix<T>::space_dimension() const {
00473 return space_dim;
00474 }
00475
00476 template <typename T>
00477 inline dimension_type
00478 OR_Matrix<T>::num_rows() const {
00479 return 2*space_dimension();
00480 }
00481
00482 template <typename T>
00483 inline void
00484 OR_Matrix<T>::clear() {
00485 OR_Matrix<T>(0).swap(*this);
00486 }
00487
00488 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00489
00490 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00491 template <typename T>
00492 inline bool
00493 operator==(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
00494 return x.space_dim == y.space_dim && x.vec == y.vec;
00495 }
00496
00497 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00498
00499 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00500 template <typename T>
00501 inline bool
00502 operator!=(const OR_Matrix<T>& x, const OR_Matrix<T>& y) {
00503 return !(x == y);
00504 }
00505
00506 template <typename T>
00507 inline
00508 OR_Matrix<T>::OR_Matrix(const OR_Matrix& y)
00509 : vec(y.vec),
00510 space_dim(y.space_dim),
00511 vec_capacity(compute_capacity(y.vec.size(),
00512 DB_Row<T>::max_size())) {
00513 }
00514
00515 template <typename T>
00516 template <typename U>
00517 inline
00518 OR_Matrix<T>::OR_Matrix(const OR_Matrix<U>& y)
00519 : vec(),
00520 space_dim(y.space_dim),
00521 vec_capacity(compute_capacity(y.vec.size(),
00522 DB_Row<T>::max_size())) {
00523 vec.construct_upward_approximation(y.vec, vec_capacity);
00524 PPL_ASSERT(OK());
00525 }
00526
00527 template <typename T>
00528 inline OR_Matrix<T>&
00529 OR_Matrix<T>::operator=(const OR_Matrix& y) {
00530 vec = y.vec;
00531 space_dim = y.space_dim;
00532 vec_capacity = compute_capacity(y.vec.size(), DB_Row<T>::max_size());
00533 return *this;
00534 }
00535
00536 template <typename T>
00537 inline void
00538 OR_Matrix<T>::grow(const dimension_type new_dim) {
00539 PPL_ASSERT(new_dim >= space_dim);
00540 if (new_dim > space_dim) {
00541 const dimension_type new_size = 2*new_dim*(new_dim + 1);
00542 if (new_size <= vec_capacity) {
00543
00544 vec.expand_within_capacity(new_size);
00545 space_dim = new_dim;
00546 }
00547 else {
00548
00549 OR_Matrix<T> new_matrix(new_dim);
00550 element_iterator j = new_matrix.element_begin();
00551 for (element_iterator i = element_begin(),
00552 mend = element_end(); i != mend; ++i, ++j)
00553 assign_or_swap(*j, *i);
00554 swap(new_matrix);
00555 }
00556 }
00557 }
00558
00559 template <typename T>
00560 inline void
00561 OR_Matrix<T>::shrink(const dimension_type new_dim) {
00562 PPL_ASSERT(new_dim <= space_dim);
00563 const dimension_type new_size = 2*new_dim*(new_dim + 1);
00564 vec.shrink(new_size);
00565 space_dim = new_dim;
00566 }
00567
00568 template <typename T>
00569 inline void
00570 OR_Matrix<T>::resize_no_copy(const dimension_type new_dim) {
00571 if (new_dim > space_dim) {
00572 const dimension_type new_size = 2*new_dim*(new_dim + 1);
00573 if (new_size <= vec_capacity) {
00574
00575 vec.expand_within_capacity(new_size);
00576 space_dim = new_dim;
00577 }
00578 else {
00579
00580 OR_Matrix<T> new_matrix(new_dim);
00581 swap(new_matrix);
00582 }
00583 }
00584 else if (new_dim < space_dim)
00585 shrink(new_dim);
00586 }
00587
00588 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00589
00590 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00591 template <typename Specialization, typename Temp, typename To, typename T>
00592 inline bool
00593 l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00594 const OR_Matrix<T>& x,
00595 const OR_Matrix<T>& y,
00596 const Rounding_Dir dir,
00597 Temp& tmp0,
00598 Temp& tmp1,
00599 Temp& tmp2) {
00600 if (x.num_rows() != y.num_rows())
00601 return false;
00602 assign_r(tmp0, 0, ROUND_NOT_NEEDED);
00603 for (typename OR_Matrix<T>::const_element_iterator
00604 i = x.element_begin(), j = y.element_begin(),
00605 mat_end = x.element_end(); i != mat_end; ++i, ++j) {
00606 const T& x_i = *i;
00607 const T& y_i = *j;
00608 if (is_plus_infinity(x_i)) {
00609 if (is_plus_infinity(y_i))
00610 continue;
00611 else {
00612 pinf:
00613 assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
00614 return true;
00615 }
00616 }
00617 else if (is_plus_infinity(y_i))
00618 goto pinf;
00619
00620 const Temp* tmp1p;
00621 const Temp* tmp2p;
00622 if (x_i > y_i) {
00623 maybe_assign(tmp1p, tmp1, x_i, dir);
00624 maybe_assign(tmp2p, tmp2, y_i, inverse(dir));
00625 }
00626 else {
00627 maybe_assign(tmp1p, tmp1, y_i, dir);
00628 maybe_assign(tmp2p, tmp2, x_i, inverse(dir));
00629 }
00630 sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
00631 PPL_ASSERT(sgn(tmp1) >= 0);
00632 Specialization::combine(tmp0, tmp1, dir);
00633 }
00634
00635 Specialization::finalize(tmp0, dir);
00636 assign_r(r, tmp0, dir);
00637 return true;
00638 }
00639
00640
00641 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00642
00643 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00644 template <typename Temp, typename To, typename T>
00645 inline bool
00646 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00647 const OR_Matrix<T>& x,
00648 const OR_Matrix<T>& y,
00649 const Rounding_Dir dir,
00650 Temp& tmp0,
00651 Temp& tmp1,
00652 Temp& tmp2) {
00653 return
00654 l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
00655 dir,
00656 tmp0,
00657 tmp1,
00658 tmp2);
00659 }
00660
00661 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00662
00663 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00664 template <typename Temp, typename To, typename T>
00665 inline bool
00666 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00667 const OR_Matrix<T>& x,
00668 const OR_Matrix<T>& y,
00669 const Rounding_Dir dir,
00670 Temp& tmp0,
00671 Temp& tmp1,
00672 Temp& tmp2) {
00673 return
00674 l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
00675 dir,
00676 tmp0,
00677 tmp1,
00678 tmp2);
00679 }
00680
00681 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
00682
00683 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
00684 template <typename Temp, typename To, typename T>
00685 inline bool
00686 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
00687 const OR_Matrix<T>& x,
00688 const OR_Matrix<T>& y,
00689 const Rounding_Dir dir,
00690 Temp& tmp0,
00691 Temp& tmp1,
00692 Temp& tmp2) {
00693 return
00694 l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
00695 dir,
00696 tmp0,
00697 tmp1,
00698 tmp2);
00699 }
00700
00701 }
00702
00703 namespace std {
00704
00706 template <typename T>
00707 inline void
00708 swap(Parma_Polyhedra_Library::OR_Matrix<T>& x,
00709 Parma_Polyhedra_Library::OR_Matrix<T>& y) {
00710 x.swap(y);
00711 }
00712
00713 }
00714
00715
00716 #endif // !defined(PPL_OR_Matrix_inlines_hh)