1 /* DB_Row 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_Row_inlines_hh
25 #define PPL_DB_Row_inlines_hh 1
26 
27 #include "checked_defs.hh"
28 #include "assertions.hh"
29 #include <cstddef>
30 #include <limits>
31 #include <algorithm>
32 #include <iostream>
33 
34 namespace Parma_Polyhedra_Library {
35 
36 template <typename T>
37 inline void*
operator new(const size_t fixed_size,const dimension_type capacity)38 DB_Row_Impl_Handler<T>::Impl::operator new(const size_t fixed_size,
39                                            const dimension_type capacity) {
40 #if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
41   return ::operator new(fixed_size + capacity*sizeof(T));
42 #else
43   PPL_ASSERT(capacity >= 1);
44   return ::operator new(fixed_size + (capacity-1)*sizeof(T));
45 #endif
46 }
47 
48 template <typename T>
49 inline void
operator delete(void * p)50 DB_Row_Impl_Handler<T>::Impl::operator delete(void* p) {
51   ::operator delete(p);
52 }
53 
54 template <typename T>
55 inline void
operator delete(void * p,dimension_type)56 DB_Row_Impl_Handler<T>::Impl::operator delete(void* p, dimension_type) {
57   ::operator delete(p);
58 }
59 
60 template <typename T>
61 inline memory_size_type
62 DB_Row_Impl_Handler<T>::Impl
total_memory_in_bytes(dimension_type capacity) const63 ::total_memory_in_bytes(dimension_type capacity) const {
64   return
65     sizeof(*this)
66     + capacity*sizeof(T)
67 #if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
68     - 1*sizeof(T)
69 #endif
70     + external_memory_in_bytes();
71 }
72 
73 template <typename T>
74 inline memory_size_type
total_memory_in_bytes() const75 DB_Row_Impl_Handler<T>::Impl::total_memory_in_bytes() const {
76   // In general, this is a lower bound, as the capacity of *this
77   // may be strictly greater than `size_'
78   return total_memory_in_bytes(size_);
79 }
80 
81 template <typename T>
82 inline dimension_type
max_size()83 DB_Row_Impl_Handler<T>::Impl::max_size() {
84   return std::numeric_limits<size_t>::max() / sizeof(T);
85 }
86 
87 template <typename T>
88 inline dimension_type
size() const89 DB_Row_Impl_Handler<T>::Impl::size() const {
90   return size_;
91 }
92 
93 template <typename T>
94 inline void
set_size(const dimension_type new_sz)95 DB_Row_Impl_Handler<T>::Impl::set_size(const dimension_type new_sz) {
96   size_ = new_sz;
97 }
98 
99 template <typename T>
100 inline void
bump_size()101 DB_Row_Impl_Handler<T>::Impl::bump_size() {
102   ++size_;
103 }
104 
105 template <typename T>
106 inline
Impl()107 DB_Row_Impl_Handler<T>::Impl::Impl()
108   : size_(0) {
109 }
110 
111 template <typename T>
112 inline
~Impl()113 DB_Row_Impl_Handler<T>::Impl::~Impl() {
114   shrink(0);
115 }
116 
117 template <typename T>
118 inline
DB_Row_Impl_Handler()119 DB_Row_Impl_Handler<T>::DB_Row_Impl_Handler()
120   : impl(0) {
121 #if PPL_DB_ROW_EXTRA_DEBUG
122   capacity_ = 0;
123 #endif
124 }
125 
126 template <typename T>
127 inline
~DB_Row_Impl_Handler()128 DB_Row_Impl_Handler<T>::~DB_Row_Impl_Handler() {
129   delete impl;
130 }
131 
132 template <typename T>
133 inline T&
operator [](const dimension_type k)134 DB_Row_Impl_Handler<T>::Impl::operator[](const dimension_type k) {
135   PPL_ASSERT(k < size());
136   return vec_[k];
137 }
138 
139 template <typename T>
140 inline const T&
operator [](const dimension_type k) const141 DB_Row_Impl_Handler<T>::Impl::operator[](const dimension_type k) const {
142   PPL_ASSERT(k < size());
143   return vec_[k];
144 }
145 
146 template <typename T>
147 inline dimension_type
max_size()148 DB_Row<T>::max_size() {
149   return DB_Row_Impl_Handler<T>::Impl::max_size();
150 }
151 
152 template <typename T>
153 inline dimension_type
size() const154 DB_Row<T>::size() const {
155   return this->impl->size();
156 }
157 
158 #if PPL_DB_ROW_EXTRA_DEBUG
159 template <typename T>
160 inline dimension_type
capacity() const161 DB_Row<T>::capacity() const {
162   return this->capacity_;
163 }
164 #endif // PPL_DB_ROW_EXTRA_DEBUG
165 
166 template <typename T>
167 inline
DB_Row()168 DB_Row<T>::DB_Row()
169   : DB_Row_Impl_Handler<T>() {
170 }
171 
172 template <typename T>
173 inline void
allocate(const dimension_type capacity)174 DB_Row<T>::allocate(
175 #if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
176                const
177 #endif
178                dimension_type capacity) {
179   DB_Row<T>& x = *this;
180   PPL_ASSERT(capacity <= max_size());
181 #if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
182   if (capacity == 0) {
183     ++capacity;
184   }
185 #endif
186   PPL_ASSERT(x.impl == 0);
187   x.impl = new(capacity) typename DB_Row_Impl_Handler<T>::Impl();
188 #if PPL_DB_ROW_EXTRA_DEBUG
189   PPL_ASSERT(x.capacity_ == 0);
190   x.capacity_ = capacity;
191 #endif
192 }
193 
194 template <typename T>
195 inline void
expand_within_capacity(const dimension_type new_size)196 DB_Row<T>::expand_within_capacity(const dimension_type new_size) {
197   DB_Row<T>& x = *this;
198   PPL_ASSERT(x.impl);
199 #if PPL_DB_ROW_EXTRA_DEBUG
200   PPL_ASSERT(new_size <= x.capacity_);
201 #endif
202   x.impl->expand_within_capacity(new_size);
203 }
204 
205 template <typename T>
206 inline void
copy_construct_coefficients(const DB_Row & y)207 DB_Row<T>::copy_construct_coefficients(const DB_Row& y) {
208   DB_Row<T>& x = *this;
209   PPL_ASSERT(x.impl && y.impl);
210 #if PPL_DB_ROW_EXTRA_DEBUG
211   PPL_ASSERT(y.size() <= x.capacity_);
212 #endif
213   x.impl->copy_construct_coefficients(*(y.impl));
214 }
215 
216 template <typename T>
217 template <typename U>
218 inline void
construct_upward_approximation(const DB_Row<U> & y,const dimension_type capacity)219 DB_Row<T>::construct_upward_approximation(const DB_Row<U>& y,
220                                           const dimension_type capacity) {
221   DB_Row<T>& x = *this;
222   PPL_ASSERT(y.size() <= capacity && capacity <= max_size());
223   allocate(capacity);
224   PPL_ASSERT(y.impl);
225   x.impl->construct_upward_approximation(*(y.impl));
226 }
227 
228 template <typename T>
229 inline void
construct(const dimension_type sz,const dimension_type capacity)230 DB_Row<T>::construct(const dimension_type sz,
231                      const dimension_type capacity) {
232   PPL_ASSERT(sz <= capacity && capacity <= max_size());
233   allocate(capacity);
234   expand_within_capacity(sz);
235 }
236 
237 template <typename T>
238 inline void
construct(const dimension_type sz)239 DB_Row<T>::construct(const dimension_type sz) {
240   construct(sz, sz);
241 }
242 
243 template <typename T>
244 inline
DB_Row(const dimension_type sz,const dimension_type capacity)245 DB_Row<T>::DB_Row(const dimension_type sz,
246                   const dimension_type capacity)
247   : DB_Row_Impl_Handler<T>() {
248   construct(sz, capacity);
249 }
250 
251 template <typename T>
252 inline
DB_Row(const dimension_type sz)253 DB_Row<T>::DB_Row(const dimension_type sz) {
254   construct(sz);
255 }
256 
257 template <typename T>
258 inline
DB_Row(const DB_Row & y)259 DB_Row<T>::DB_Row(const DB_Row& y)
260   : DB_Row_Impl_Handler<T>() {
261   if (y.impl != 0) {
262     allocate(compute_capacity(y.size(), max_size()));
263     copy_construct_coefficients(y);
264   }
265 }
266 
267 template <typename T>
268 inline
DB_Row(const DB_Row & y,const dimension_type capacity)269 DB_Row<T>::DB_Row(const DB_Row& y,
270                   const dimension_type capacity)
271   : DB_Row_Impl_Handler<T>() {
272   PPL_ASSERT(y.impl);
273   PPL_ASSERT(y.size() <= capacity && capacity <= max_size());
274   allocate(capacity);
275   copy_construct_coefficients(y);
276 }
277 
278 template <typename T>
279 inline
DB_Row(const DB_Row & y,const dimension_type sz,const dimension_type capacity)280 DB_Row<T>::DB_Row(const DB_Row& y,
281                   const dimension_type sz,
282                   const dimension_type capacity)
283   : DB_Row_Impl_Handler<T>() {
284   PPL_ASSERT(y.impl);
285   PPL_ASSERT(y.size() <= sz && sz <= capacity && capacity <= max_size());
286   allocate(capacity);
287   copy_construct_coefficients(y);
288   expand_within_capacity(sz);
289 }
290 
291 template <typename T>
292 inline
~DB_Row()293 DB_Row<T>::~DB_Row() {
294 }
295 
296 template <typename T>
297 inline void
shrink(const dimension_type new_size)298 DB_Row<T>::shrink(const dimension_type new_size) {
299   DB_Row<T>& x = *this;
300   PPL_ASSERT(x.impl);
301   x.impl->shrink(new_size);
302 }
303 
304 template <typename T>
305 inline void
m_swap(DB_Row & y)306 DB_Row<T>::m_swap(DB_Row& y) {
307   using std::swap;
308   DB_Row<T>& x = *this;
309   swap(x.impl, y.impl);
310 #if PPL_DB_ROW_EXTRA_DEBUG
311   swap(x.capacity_, y.capacity_);
312 #endif
313 }
314 
315 template <typename T>
316 inline void
assign(DB_Row & y)317 DB_Row<T>::assign(DB_Row& y) {
318   DB_Row<T>& x = *this;
319   x.impl = y.impl;
320 #if PPL_DB_ROW_EXTRA_DEBUG
321   x.capacity_ = y.capacity_;
322 #endif
323 }
324 
325 template <typename T>
326 inline DB_Row<T>&
operator =(const DB_Row & y)327 DB_Row<T>::operator=(const DB_Row& y) {
328   DB_Row tmp(y);
329   m_swap(tmp);
330   return *this;
331 }
332 
333 template <typename T>
334 inline T&
operator [](const dimension_type k)335 DB_Row<T>::operator[](const dimension_type k) {
336   DB_Row<T>& x = *this;
337   return (*x.impl)[k];
338 }
339 
340 template <typename T>
341 inline const T&
operator [](const dimension_type k) const342 DB_Row<T>::operator[](const dimension_type k) const {
343   const DB_Row<T>& x = *this;
344   return (*x.impl)[k];
345 }
346 
347 template <typename T>
348 inline typename DB_Row<T>::iterator
begin()349 DB_Row<T>::begin() {
350   DB_Row<T>& x = *this;
351   return iterator(x.impl->vec_);
352 }
353 
354 template <typename T>
355 inline typename DB_Row<T>::iterator
end()356 DB_Row<T>::end() {
357   DB_Row<T>& x = *this;
358   return iterator(x.impl->vec_ + x.impl->size_);
359 }
360 
361 template <typename T>
362 inline typename DB_Row<T>::const_iterator
begin() const363 DB_Row<T>::begin() const {
364   const DB_Row<T>& x = *this;
365   return const_iterator(x.impl->vec_);
366 }
367 
368 template <typename T>
369 inline typename DB_Row<T>::const_iterator
end() const370 DB_Row<T>::end() const {
371   const DB_Row<T>& x = *this;
372   return const_iterator(x.impl->vec_ + x.impl->size_);
373 }
374 
375 template <typename T>
376 inline memory_size_type
external_memory_in_bytes(dimension_type capacity) const377 DB_Row<T>::external_memory_in_bytes(dimension_type capacity) const {
378   const DB_Row<T>& x = *this;
379   return x.impl->total_memory_in_bytes(capacity);
380 }
381 
382 template <typename T>
383 inline memory_size_type
total_memory_in_bytes(dimension_type capacity) const384 DB_Row<T>::total_memory_in_bytes(dimension_type capacity) const {
385   return sizeof(*this) + external_memory_in_bytes(capacity);
386 }
387 
388 template <typename T>
389 inline memory_size_type
external_memory_in_bytes() const390 DB_Row<T>::external_memory_in_bytes() const {
391   const DB_Row<T>& x = *this;
392 #if PPL_DB_ROW_EXTRA_DEBUG
393   return x.impl->total_memory_in_bytes(x.capacity_);
394 #else
395   return x.impl->total_memory_in_bytes();
396 #endif
397 }
398 
399 template <typename T>
400 inline memory_size_type
total_memory_in_bytes() const401 DB_Row<T>::total_memory_in_bytes() const {
402   return sizeof(*this) + external_memory_in_bytes();
403 }
404 
405 /*! \relates DB_Row */
406 template <typename T>
407 inline bool
operator !=(const DB_Row<T> & x,const DB_Row<T> & y)408 operator!=(const DB_Row<T>& x, const DB_Row<T>& y) {
409   return !(x == y);
410 }
411 
412 /*! \relates DB_Row */
413 template <typename T>
414 inline void
swap(DB_Row<T> & x,DB_Row<T> & y)415 swap(DB_Row<T>& x, DB_Row<T>& y) {
416   x.m_swap(y);
417 }
418 
419 /*! \relates DB_Row */
420 template <typename T>
421 inline void
iter_swap(typename std::vector<DB_Row<T>>::iterator x,typename std::vector<DB_Row<T>>::iterator y)422 iter_swap(typename std::vector<DB_Row<T> >::iterator x,
423           typename std::vector<DB_Row<T> >::iterator y) {
424   swap(*x, *y);
425 }
426 
427 } // namespace Parma_Polyhedra_Library
428 
429 #endif // !defined(PPL_DB_Row_inlines_hh)
430