1 /* DB_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_DB_Matrix_inlines_hh
25 #define PPL_DB_Matrix_inlines_hh 1
26 
27 #include "globals_defs.hh"
28 #include "Checked_Number_defs.hh"
29 #include "distances_defs.hh"
30 #include "assertions.hh"
31 #include <iostream>
32 
33 namespace Parma_Polyhedra_Library {
34 
35 template <typename T>
36 inline void
m_swap(DB_Matrix & y)37 DB_Matrix<T>::m_swap(DB_Matrix& y) {
38   using std::swap;
39   swap(rows, y.rows);
40   swap(row_size, y.row_size);
41   swap(row_capacity, y.row_capacity);
42 }
43 
44 template <typename T>
45 inline dimension_type
max_num_rows()46 DB_Matrix<T>::max_num_rows() {
47   return std::vector<DB_Row<T> >().max_size();
48 }
49 
50 template <typename T>
51 inline dimension_type
max_num_columns()52 DB_Matrix<T>::max_num_columns() {
53   return DB_Row<T>::max_size();
54 }
55 
56 template <typename T>
57 inline memory_size_type
total_memory_in_bytes() const58 DB_Matrix<T>::total_memory_in_bytes() const {
59   return sizeof(*this) + external_memory_in_bytes();
60 }
61 
62 template <typename T>
63 inline
const_iterator()64 DB_Matrix<T>::const_iterator::const_iterator()
65   : i(Iter()) {
66 }
67 
68 template <typename T>
69 inline
const_iterator(const Iter & b)70 DB_Matrix<T>::const_iterator::const_iterator(const Iter& b)
71   : i(b) {
72 }
73 
74 template <typename T>
75 inline
const_iterator(const const_iterator & y)76 DB_Matrix<T>::const_iterator::const_iterator(const const_iterator& y)
77   : i(y.i) {
78 }
79 
80 template <typename T>
81 inline typename DB_Matrix<T>::const_iterator&
operator =(const const_iterator & y)82 DB_Matrix<T>::const_iterator::operator=(const const_iterator& y) {
83   i = y.i;
84   return *this;
85 }
86 
87 template <typename T>
88 inline typename DB_Matrix<T>::const_iterator::reference
operator *() const89 DB_Matrix<T>::const_iterator::operator*() const {
90   return *i;
91 }
92 
93 template <typename T>
94 inline typename DB_Matrix<T>::const_iterator::pointer
operator ->() const95 DB_Matrix<T>::const_iterator::operator->() const {
96   return &*i;
97 }
98 
99 template <typename T>
100 inline typename DB_Matrix<T>::const_iterator&
operator ++()101 DB_Matrix<T>::const_iterator::operator++() {
102   ++i;
103   return *this;
104 }
105 
106 template <typename T>
107 inline typename DB_Matrix<T>::const_iterator
operator ++(int)108 DB_Matrix<T>::const_iterator::operator++(int) {
109   return const_iterator(i++);
110 }
111 
112 template <typename T>
113 inline bool
operator ==(const const_iterator & y) const114 DB_Matrix<T>::const_iterator::operator==(const const_iterator& y) const {
115   return i == y.i;
116 }
117 
118 template <typename T>
119 inline bool
operator !=(const const_iterator & y) const120 DB_Matrix<T>::const_iterator::operator!=(const const_iterator& y) const {
121   return !operator==(y);
122 }
123 
124 template <typename T>
125 inline typename DB_Matrix<T>::const_iterator
begin() const126 DB_Matrix<T>::begin() const {
127   return const_iterator(rows.begin());
128 }
129 
130 template <typename T>
131 inline typename DB_Matrix<T>::const_iterator
end() const132 DB_Matrix<T>::end() const {
133   return const_iterator(rows.end());
134 }
135 
136 template <typename T>
137 inline
DB_Matrix()138 DB_Matrix<T>::DB_Matrix()
139   : rows(),
140     row_size(0),
141     row_capacity(0) {
142 }
143 
144 template <typename T>
145 inline
~DB_Matrix()146 DB_Matrix<T>::~DB_Matrix() {
147 }
148 
149 template <typename T>
150 inline DB_Row<T>&
operator [](const dimension_type k)151 DB_Matrix<T>::operator[](const dimension_type k) {
152   PPL_ASSERT(k < rows.size());
153   return rows[k];
154 }
155 
156 template <typename T>
157 inline const DB_Row<T>&
operator [](const dimension_type k) const158 DB_Matrix<T>::operator[](const dimension_type k) const {
159   PPL_ASSERT(k < rows.size());
160   return rows[k];
161 }
162 
163 template <typename T>
164 inline dimension_type
num_rows() const165 DB_Matrix<T>::num_rows() const {
166   return rows.size();
167 }
168 
169 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
170 /*! \relates DB_Matrix */
171 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
172 template <typename T>
173 inline bool
operator !=(const DB_Matrix<T> & x,const DB_Matrix<T> & y)174 operator!=(const DB_Matrix<T>& x, const DB_Matrix<T>& y) {
175   return !(x == y);
176 }
177 
178 template <typename T>
179 inline
DB_Matrix(const DB_Matrix & y)180 DB_Matrix<T>::DB_Matrix(const DB_Matrix& y)
181   : rows(y.rows),
182     row_size(y.row_size),
183     row_capacity(compute_capacity(y.row_size, max_num_columns())) {
184 }
185 
186 template <typename T>
187 inline DB_Matrix<T>&
operator =(const DB_Matrix & y)188 DB_Matrix<T>::operator=(const DB_Matrix& y) {
189   // Without the following guard against auto-assignments we would
190   // recompute the row capacity based on row size, possibly without
191   // actually increasing the capacity of the rows.  This would lead to
192   // an inconsistent state.
193   if (this != &y) {
194     // The following assignment may do nothing on auto-assignments...
195     rows = y.rows;
196     row_size = y.row_size;
197     // ... hence the following assignment must not be done on
198     // auto-assignments.
199     row_capacity = compute_capacity(y.row_size, max_num_columns());
200   }
201   return *this;
202 }
203 
204 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
205 /*! \relates DB_Matrix */
206 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
207 template <typename Specialization, typename Temp, typename To, typename T>
208 inline bool
l_m_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const DB_Matrix<T> & x,const DB_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)209 l_m_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
210                     const DB_Matrix<T>& x,
211                     const DB_Matrix<T>& y,
212                     const Rounding_Dir dir,
213                     Temp& tmp0,
214                     Temp& tmp1,
215                     Temp& tmp2) {
216   const dimension_type x_num_rows = x.num_rows();
217   if (x_num_rows != y.num_rows()) {
218     return false;
219   }
220   assign_r(tmp0, 0, ROUND_NOT_NEEDED);
221   for (dimension_type i = x_num_rows; i-- > 0; ) {
222     const DB_Row<T>& x_i = x[i];
223     const DB_Row<T>& y_i = y[i];
224     for (dimension_type j = x_num_rows; j-- > 0; ) {
225       const T& x_i_j = x_i[j];
226       const T& y_i_j = y_i[j];
227       if (is_plus_infinity(x_i_j)) {
228         if (is_plus_infinity(y_i_j)) {
229           continue;
230         }
231         else {
232         pinf:
233           assign_r(r, PLUS_INFINITY, ROUND_NOT_NEEDED);
234           return true;
235         }
236       }
237       else if (is_plus_infinity(y_i_j)) {
238         goto pinf;
239       }
240       const Temp* tmp1p;
241       const Temp* tmp2p;
242       if (x_i_j > y_i_j) {
243         maybe_assign(tmp1p, tmp1, x_i_j, dir);
244         maybe_assign(tmp2p, tmp2, y_i_j, inverse(dir));
245       }
246       else {
247         maybe_assign(tmp1p, tmp1, y_i_j, dir);
248         maybe_assign(tmp2p, tmp2, x_i_j, inverse(dir));
249       }
250       sub_assign_r(tmp1, *tmp1p, *tmp2p, dir);
251       PPL_ASSERT(sgn(tmp1) >= 0);
252       Specialization::combine(tmp0, tmp1, dir);
253     }
254   }
255   Specialization::finalize(tmp0, dir);
256   assign_r(r, tmp0, dir);
257   return true;
258 }
259 
260 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
261 /*! \relates DB_Matrix */
262 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
263 template <typename Temp, typename To, typename T>
264 inline bool
rectilinear_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const DB_Matrix<T> & x,const DB_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)265 rectilinear_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
266                             const DB_Matrix<T>& x,
267                             const DB_Matrix<T>& y,
268                             const Rounding_Dir dir,
269                             Temp& tmp0,
270                             Temp& tmp1,
271                             Temp& tmp2) {
272   return
273     l_m_distance_assign<Rectilinear_Distance_Specialization<Temp> >(r, x, y,
274                                                                     dir,
275                                                                     tmp0,
276                                                                     tmp1,
277                                                                     tmp2);
278 }
279 
280 
281 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
282 /*! \relates DB_Matrix */
283 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
284 template <typename Temp, typename To, typename T>
285 inline bool
euclidean_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const DB_Matrix<T> & x,const DB_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)286 euclidean_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
287                           const DB_Matrix<T>& x,
288                           const DB_Matrix<T>& y,
289                           const Rounding_Dir dir,
290                           Temp& tmp0,
291                           Temp& tmp1,
292                           Temp& tmp2) {
293   return
294     l_m_distance_assign<Euclidean_Distance_Specialization<Temp> >(r, x, y,
295                                                                   dir,
296                                                                   tmp0,
297                                                                   tmp1,
298                                                                   tmp2);
299 }
300 
301 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
302 /*! \relates DB_Matrix */
303 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
304 template <typename Temp, typename To, typename T>
305 inline bool
l_infinity_distance_assign(Checked_Number<To,Extended_Number_Policy> & r,const DB_Matrix<T> & x,const DB_Matrix<T> & y,const Rounding_Dir dir,Temp & tmp0,Temp & tmp1,Temp & tmp2)306 l_infinity_distance_assign(Checked_Number<To, Extended_Number_Policy>& r,
307                            const DB_Matrix<T>& x,
308                            const DB_Matrix<T>& y,
309                            const Rounding_Dir dir,
310                            Temp& tmp0,
311                            Temp& tmp1,
312                            Temp& tmp2) {
313   return
314     l_m_distance_assign<L_Infinity_Distance_Specialization<Temp> >(r, x, y,
315                                                                    dir,
316                                                                    tmp0,
317                                                                    tmp1,
318                                                                    tmp2);
319 }
320 
321 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
322 /*! \relates DB_Matrix */
323 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
324 template <typename T>
325 inline void
swap(DB_Matrix<T> & x,DB_Matrix<T> & y)326 swap(DB_Matrix<T>& x, DB_Matrix<T>& y) {
327   x.m_swap(y);
328 }
329 
330 } // namespace Parma_Polyhedra_Library
331 
332 #endif // !defined(PPL_DB_Matrix_inlines_hh)
333