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