PPL  1.2
DB_Matrix_templates.hh
Go to the documentation of this file.
1 /* DB_Matrix class implementation: non-inline template 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_templates_hh
25 #define PPL_DB_Matrix_templates_hh 1
26 
27 namespace Parma_Polyhedra_Library {
28 
29 template <typename T>
31  : rows(n_rows),
32  row_size(n_rows),
33  row_capacity(compute_capacity(n_rows, max_num_columns())) {
34  // Construct in direct order: will destroy in reverse order.
35  for (dimension_type i = 0; i < n_rows; ++i) {
36  rows[i].construct(n_rows, row_capacity);
37  }
38  PPL_ASSERT(OK());
39 }
40 
41 template <typename T>
42 template <typename U>
44  : rows(y.rows.size()),
45  row_size(y.row_size),
46  row_capacity(compute_capacity(y.row_size, max_num_columns())) {
47  // Construct in direct order: will destroy in reverse order.
48  for (dimension_type i = 0, n_rows = rows.size(); i < n_rows; ++i) {
49  rows[i].construct_upward_approximation(y[i], row_capacity);
50  }
51  PPL_ASSERT(OK());
52 }
53 
54 template <typename T>
55 void
57  const dimension_type old_n_rows = rows.size();
58  PPL_ASSERT(new_n_rows >= old_n_rows);
59 
60  if (new_n_rows > old_n_rows) {
61  if (new_n_rows <= row_capacity) {
62  // We can recycle the old rows.
63  if (rows.capacity() < new_n_rows) {
64  // Reallocation will take place.
65  std::vector<DB_Row<T> > new_rows;
66  new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
67  new_rows.insert(new_rows.end(), new_n_rows, DB_Row<T>());
68  // Construct the new rows.
69  dimension_type i = new_n_rows;
70  while (i-- > old_n_rows) {
71  new_rows[i].construct(new_n_rows, row_capacity);
72  }
73  // Steal the old rows.
74  ++i;
75  while (i-- > 0) {
76  swap(new_rows[i], rows[i]);
77  }
78  // Put the new vector into place.
79  using std::swap;
80  swap(rows, new_rows);
81  }
82  else {
83  // Reallocation will NOT take place.
84  rows.insert(rows.end(), new_n_rows - old_n_rows, DB_Row<T>());
85  for (dimension_type i = new_n_rows; i-- > old_n_rows; ) {
86  rows[i].construct(new_n_rows, row_capacity);
87  }
88  }
89  }
90  else {
91  // We cannot even recycle the old rows.
92  DB_Matrix new_matrix;
93  new_matrix.rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
94  new_matrix.rows.insert(new_matrix.rows.end(), new_n_rows, DB_Row<T>());
95  // Construct the new rows.
96  new_matrix.row_size = new_n_rows;
97  new_matrix.row_capacity = compute_capacity(new_n_rows,
98  max_num_columns());
99  dimension_type i = new_n_rows;
100  while (i-- > old_n_rows) {
101  new_matrix.rows[i].construct(new_matrix.row_size,
102  new_matrix.row_capacity);
103  }
104  // Copy the old rows.
105  ++i;
106  while (i-- > 0) {
107  // FIXME: copying may be unnecessarily costly.
108  DB_Row<T> new_row(rows[i],
109  new_matrix.row_size,
110  new_matrix.row_capacity);
111  swap(new_matrix.rows[i], new_row);
112  }
113  // Put the new vector into place.
114  m_swap(new_matrix);
115  return;
116  }
117  }
118  // Here we have the right number of rows.
119  if (new_n_rows > row_size) {
120  // We need more columns.
121  if (new_n_rows <= row_capacity) {
122  // But we have enough capacity: we resize existing rows.
123  for (dimension_type i = old_n_rows; i-- > 0; ) {
124  rows[i].expand_within_capacity(new_n_rows);
125  }
126  }
127  else {
128  // Capacity exhausted: we must reallocate the rows and
129  // make sure all the rows have the same capacity.
130  const dimension_type new_row_capacity
131  = compute_capacity(new_n_rows, max_num_columns());
132  for (dimension_type i = old_n_rows; i-- > 0; ) {
133  // FIXME: copying may be unnecessarily costly.
134  DB_Row<T> new_row(rows[i], new_n_rows, new_row_capacity);
135  swap(rows[i], new_row);
136  }
137  row_capacity = new_row_capacity;
138  }
139  // Rows have grown or shrunk.
140  row_size = new_n_rows;
141  }
142 }
143 
144 template <typename T>
145 void
147  dimension_type old_n_rows = rows.size();
148 
149  if (new_n_rows > old_n_rows) {
150  // Rows will be inserted.
151  if (new_n_rows <= row_capacity) {
152  // We can recycle the old rows.
153  if (rows.capacity() < new_n_rows) {
154  // Reallocation (of vector `rows') will take place.
155  std::vector<DB_Row<T> > new_rows;
156  new_rows.reserve(compute_capacity(new_n_rows, max_num_rows()));
157  new_rows.insert(new_rows.end(), new_n_rows, DB_Row<T>());
158  // Construct the new rows (be careful: each new row must have
159  // the same capacity as each one of the old rows).
160  dimension_type i = new_n_rows;
161  while (i-- > old_n_rows) {
162  new_rows[i].construct(new_n_rows, row_capacity);
163  // Steal the old rows.
164  }
165  ++i;
166  while (i-- > 0) {
167  swap(new_rows[i], rows[i]);
168  }
169  // Put the new vector into place.
170  using std::swap;
171  swap(rows, new_rows);
172  }
173  else {
174  // Reallocation (of vector `rows') will NOT take place.
175  rows.insert(rows.end(), new_n_rows - old_n_rows, DB_Row<T>());
176  // Be careful: each new row must have
177  // the same capacity as each one of the old rows.
178  for (dimension_type i = new_n_rows; i-- > old_n_rows; ) {
179  rows[i].construct(new_n_rows, row_capacity);
180  }
181  }
182  }
183  else {
184  // We cannot even recycle the old rows: allocate a new matrix and swap.
185  DB_Matrix new_matrix(new_n_rows);
186  m_swap(new_matrix);
187  return;
188  }
189  }
190  else if (new_n_rows < old_n_rows) {
191  // Drop some rows.
192  rows.resize(new_n_rows);
193  // Shrink the existing rows.
194  for (dimension_type i = new_n_rows; i-- > 0; ) {
195  rows[i].shrink(new_n_rows);
196  }
197  old_n_rows = new_n_rows;
198  }
199  // Here we have the right number of rows.
200  if (new_n_rows > row_size) {
201  // We need more columns.
202  if (new_n_rows <= row_capacity) {
203  // But we have enough capacity: we resize existing rows.
204  for (dimension_type i = old_n_rows; i-- > 0; ) {
205  rows[i].expand_within_capacity(new_n_rows);
206  }
207  }
208  else {
209  // Capacity exhausted: we must reallocate the rows and
210  // make sure all the rows have the same capacity.
211  const dimension_type new_row_capacity
212  = compute_capacity(new_n_rows, max_num_columns());
213  for (dimension_type i = old_n_rows; i-- > 0; ) {
214  DB_Row<T> new_row(new_n_rows, new_row_capacity);
215  swap(rows[i], new_row);
216  }
217  row_capacity = new_row_capacity;
218  }
219  }
220  // DB_Rows have grown or shrunk.
221  row_size = new_n_rows;
222 }
223 
224 template <typename T>
225 void
226 DB_Matrix<T>::ascii_dump(std::ostream& s) const {
227  const DB_Matrix<T>& x = *this;
228  const char separator = ' ';
229  const dimension_type nrows = x.num_rows();
230  s << nrows << separator << "\n";
231  for (dimension_type i = 0; i < nrows; ++i) {
232  for (dimension_type j = 0; j < nrows; ++j) {
233  using namespace IO_Operators;
234  s << x[i][j] << separator;
235  }
236  s << "\n";
237  }
238 }
239 
241 
242 template <typename T>
243 bool
244 DB_Matrix<T>::ascii_load(std::istream& s) {
245  dimension_type nrows;
246  if (!(s >> nrows)) {
247  return false;
248  }
249  resize_no_copy(nrows);
250  DB_Matrix& x = *this;
251  for (dimension_type i = 0; i < nrows; ++i) {
252  for (dimension_type j = 0; j < nrows; ++j) {
253  Result r = input(x[i][j], s, ROUND_CHECK);
254  if (result_relation(r) != VR_EQ || is_minus_infinity(x[i][j])) {
255  return false;
256  }
257  }
258  }
259 
260  // Check invariants.
261  PPL_ASSERT(OK());
262  return true;
263 }
264 
265 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
266 
267 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
268 template <typename T>
269 bool
270 operator==(const DB_Matrix<T>& x, const DB_Matrix<T>& y) {
271  const dimension_type x_num_rows = x.num_rows();
272  if (x_num_rows != y.num_rows()) {
273  return false;
274  }
275  for (dimension_type i = x_num_rows; i-- > 0; ) {
276  if (x[i] != y[i]) {
277  return false;
278  }
279  }
280  return true;
281 }
282 
283 template <typename T>
286  memory_size_type n = rows.capacity() * sizeof(DB_Row<T>);
287  for (dimension_type i = num_rows(); i-- > 0; ) {
288  n += rows[i].external_memory_in_bytes(row_capacity);
289  }
290  return n;
291 }
292 
293 template <typename T>
294 bool
296 #ifndef NDEBUG
297  using std::endl;
298  using std::cerr;
299 #endif
300 
301  // The matrix must be square.
302  if (num_rows() != row_size) {
303 #ifndef NDEBUG
304  cerr << "DB_Matrix has fewer columns than rows:\n"
305  << "row_size is " << row_size
306  << ", num_rows() is " << num_rows() << "!"
307  << endl;
308 #endif
309  return false;
310  }
311 
312  const DB_Matrix& x = *this;
313  const dimension_type n_rows = x.num_rows();
314  for (dimension_type i = 0; i < n_rows; ++i) {
315  if (!x[i].OK(row_size, row_capacity)) {
316  return false;
317  }
318  }
319 
320  // All checks passed.
321  return true;
322 }
323 
324 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
325 
326 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
327 template <typename T>
328 std::ostream&
329 IO_Operators::operator<<(std::ostream& s, const DB_Matrix<T>& c) {
330  const dimension_type n = c.num_rows();
331  for (dimension_type i = 0; i < n; ++i) {
332  for (dimension_type j = 0; j < n; ++j) {
333  s << c[i][j] << " ";
334  }
335  s << "\n";
336  }
337  return s;
338 }
339 
340 } // namespace Parma_Polyhedra_Library
341 
342 #endif // !defined(PPL_DB_Matrix_templates_hh)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_minus_infinity(const T &x)
void swap(CO_Tree &x, CO_Tree &y)
size_t dimension_type
An unsigned integral type for representing space dimensions.
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
The standard C++ namespace.
#define PPL_OUTPUT_TEMPLATE_DEFINITIONS(type_symbol, class_prefix)
std::vector< DB_Row< T > > rows
The rows of the matrix.
void grow(dimension_type new_n_rows)
Makes the matrix grow by adding more rows and more columns.
Result_Relation result_relation(Result r)
DB_Matrix()
Builds an empty matrix.
void resize_no_copy(dimension_type new_n_rows)
Resizes the matrix without worrying about the old contents.
The base class for the single rows of matrices.
Definition: DB_Row_defs.hh:120
dimension_type compute_capacity(dimension_type requested_size, dimension_type maximum_size)
Speculative allocation function.
bool OK() const
Checks if all the invariants are satisfied.
dimension_type row_size
Size of the initialized part of each row.
Equal. This need to be accompanied by a value.
Definition: Result_defs.hh:51
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
bool operator==(const DB_Matrix< T > &x, const DB_Matrix< T > &y)
dimension_type num_rows() const
Returns the number of rows in the matrix.
dimension_type row_capacity
Capacity allocated for each row, i.e., number of long objects that each row can contain.
The entire library is confined to this namespace.
Definition: version.hh:61
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
Coefficient c
Definition: PIP_Tree.cc:64
The base class for the square matrices.
void ascii_dump() const
Writes to std::cerr an ASCII representation of *this.