1 /* DB_Row 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_Row_templates_hh
25 #define PPL_DB_Row_templates_hh 1
26 
27 #include "globals_defs.hh"
28 
29 namespace Parma_Polyhedra_Library {
30 
31 template <typename T>
32 template <typename U>
33 void
construct_upward_approximation(const U & y)34 DB_Row_Impl_Handler<T>::Impl::construct_upward_approximation(const U& y) {
35   const dimension_type y_size = y.size();
36 #if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
37   // Construct in direct order: will destroy in reverse order.
38   for (dimension_type i = 0; i < y_size; ++i) {
39     construct(vec_[i], y[i], ROUND_UP);
40     bump_size();
41   }
42 #else // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
43   if (y_size > 0) {
44     assign_r(vec_[0], y[0], ROUND_UP);
45     bump_size();
46     // Construct in direct order: will destroy in reverse order.
47     for (dimension_type i = 1; i < y_size; ++i) {
48       construct(vec_[i], y[i], ROUND_UP);
49       bump_size();
50     }
51   }
52 #endif // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
53 }
54 
55 template <typename T>
56 void
57 DB_Row_Impl_Handler<T>::
expand_within_capacity(const dimension_type new_size)58 Impl::expand_within_capacity(const dimension_type new_size) {
59   PPL_ASSERT(size() <= new_size && new_size <= max_size());
60 #if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
61   if (size() == 0 && new_size > 0) {
62     // vec_[0] is already constructed: we just need to assign +infinity.
63     assign_r(vec_[0], PLUS_INFINITY, ROUND_NOT_NEEDED);
64     bump_size();
65   }
66 #endif
67   // Construct in direct order: will destroy in reverse order.
68   for (dimension_type i = size(); i < new_size; ++i) {
69     new(&vec_[i]) T(PLUS_INFINITY, ROUND_NOT_NEEDED);
70     bump_size();
71   }
72 }
73 
74 template <typename T>
75 void
shrink(dimension_type new_size)76 DB_Row_Impl_Handler<T>::Impl::shrink(dimension_type new_size) {
77   const dimension_type old_size = size();
78   PPL_ASSERT(new_size <= old_size);
79   // Since ~T() does not throw exceptions, nothing here does.
80   set_size(new_size);
81 #if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
82   // Make sure we do not try to destroy vec_[0].
83   if (new_size == 0) {
84     ++new_size;
85   }
86 #endif
87   // We assume construction was done "forward".
88   // We thus perform destruction "backward".
89   for (dimension_type i = old_size; i-- > new_size; ) {
90     vec_[i].~T();
91   }
92 }
93 
94 template <typename T>
95 void
copy_construct_coefficients(const Impl & y)96 DB_Row_Impl_Handler<T>::Impl::copy_construct_coefficients(const Impl& y) {
97   const dimension_type y_size = y.size();
98 #if PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
99   // Construct in direct order: will destroy in reverse order.
100   for (dimension_type i = 0; i < y_size; ++i) {
101     new(&vec_[i]) T(y.vec_[i]);
102     bump_size();
103   }
104 #else // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
105   if (y_size > 0) {
106     vec_[0] = y.vec_[0];
107     bump_size();
108     // Construct in direct order: will destroy in reverse order.
109     for (dimension_type i = 1; i < y_size; ++i) {
110       new(&vec_[i]) T(y.vec_[i]);
111       bump_size();
112     }
113   }
114 #endif // PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
115 }
116 
117 template <typename T>
118 memory_size_type
external_memory_in_bytes() const119 DB_Row_Impl_Handler<T>::Impl::external_memory_in_bytes() const {
120   memory_size_type n = 0;
121   for (dimension_type i = size(); i-- > 0; ) {
122     n += Parma_Polyhedra_Library::external_memory_in_bytes(vec_[i]);
123   }
124   return n;
125 }
126 
127 template <typename T>
128 bool
OK(const dimension_type row_size,const dimension_type row_capacity) const129 DB_Row<T>::OK(const dimension_type row_size,
130               const dimension_type
131 #if PPL_DB_ROW_EXTRA_DEBUG
132               row_capacity
133 #endif
134               ) const {
135 #ifndef NDEBUG
136   using std::endl;
137   using std::cerr;
138 #endif
139 
140   const DB_Row<T>& x = *this;
141   bool is_broken = false;
142 
143 #if PPL_DB_ROW_EXTRA_DEBUG
144 # if !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
145   if (x.capacity_ == 0) {
146     cerr << "Illegal row capacity: is 0, should be at least 1"
147          << endl;
148     is_broken = true;
149   }
150   else if (x.capacity_ == 1 && row_capacity == 0)
151     // This is fine.
152     ;
153   else
154 # endif // !PPL_CXX_SUPPORTS_ZERO_LENGTH_ARRAYS
155   if (x.capacity_ != row_capacity) {
156     cerr << "DB_Row capacity mismatch: is " << x.capacity_
157          << ", should be " << row_capacity << "."
158          << endl;
159     is_broken = true;
160   }
161 #endif // PPL_DB_ROW_EXTRA_DEBUG
162 
163   if (x.size() != row_size) {
164 #ifndef NDEBUG
165     cerr << "DB_Row size mismatch: is " << x.size()
166          << ", should be " << row_size << "."
167          << endl;
168 #endif
169     is_broken = true;
170   }
171 
172 #if PPL_DB_ROW_EXTRA_DEBUG
173   if (x.capacity_ < x.size()) {
174 #ifndef NDEBUG
175     cerr << "DB_Row is completely broken: capacity is " << x.capacity_
176          << ", size is " << x.size() << "."
177          << endl;
178 #endif
179     is_broken = true;
180   }
181 #endif // PPL_DB_ROW_EXTRA_DEBUG
182 
183   for (dimension_type i = x.size(); i-- > 0; ) {
184     const T& element = x[i];
185     // Not OK is bad.
186     if (!element.OK()) {
187       is_broken = true;
188       break;
189     }
190     // In addition, nans should never occur.
191     if (is_not_a_number(element)) {
192 #ifndef NDEBUG
193       cerr << "Not-a-number found in DB_Row."
194            << endl;
195 #endif
196       is_broken = true;
197       break;
198     }
199   }
200 
201   return !is_broken;
202 }
203 
204 /*! \relates DB_Row */
205 template <typename T>
206 bool
operator ==(const DB_Row<T> & x,const DB_Row<T> & y)207 operator==(const DB_Row<T>& x, const DB_Row<T>& y) {
208   if (x.size() != y.size()) {
209     return false;
210   }
211   for (dimension_type i = x.size(); i-- > 0; ) {
212     if (x[i] != y[i]) {
213       return false;
214     }
215   }
216   return true;
217 }
218 
219 } // namespace Parma_Polyhedra_Library
220 
221 #endif // !defined(PPL_DB_Row_templates_hh)
222