37 #ifndef BGEOT_SMALL_VECTOR_H
38 #define BGEOT_SMALL_VECTOR_H
42 #ifdef DEBUG_SMALL_VECTOR
44 # define SVEC_ASSERT(x) assert(x)
46 # define SVEC_ASSERT(x)
51 class APIDECL block_allocator {
53 typedef gmm::uint16_type uint16_type;
54 typedef gmm::uint32_type node_id;
57 enum { p2_BLOCKSZ = 8, BLOCKSZ = 1<<p2_BLOCKSZ };
58 enum { OBJ_SIZE_LIMIT = 129 };
59 enum { MAXREF = 256 };
66 uint16_type first_unused_chunk, count_unused_chunk;
80 data =
static_cast<unsigned char*
>(::operator
new(BLOCKSZ*objsz + BLOCKSZ));
82 memset(data, 0, BLOCKSZ);
87 if (data) { ::operator
delete(data); };
88 data = 0; first_unused_chunk = 0; count_unused_chunk = BLOCKSZ;
90 unsigned char& refcnt(
size_type pos) {
return data[pos]; }
91 bool empty()
const {
return data == 0; }
96 std::vector<block> blocks;
103 void * obj_data(node_id
id) {
104 return blocks[
id/BLOCKSZ].data + BLOCKSZ + (
id%BLOCKSZ)*blocks[
id/BLOCKSZ].objsz;
106 dim_type obj_sz(node_id
id) {
107 return dim_type(blocks[
id/BLOCKSZ].objsz);
110 unsigned char& refcnt(node_id
id) {
111 return blocks[
id/BLOCKSZ].refcnt(
id%BLOCKSZ);
113 node_id inc_ref(node_id
id) {
114 if (
id && ++refcnt(
id) == 0) {
120 void dec_ref(node_id
id) {
121 SVEC_ASSERT(
id==0 || refcnt(
id));
122 if (
id && --refcnt(
id) == 0) {
127 void duplicate_if_aliased(node_id&
id) {
128 if (refcnt(
id) != 1) {
130 id = duplicate(
id); SVEC_ASSERT(
id == 0 || refcnt(
id)==1);
136 void deallocate(node_id nid);
140 node_id duplicate(node_id
id) {
141 node_id id2 = allocate(obj_sz(
id));
142 memcpy(obj_data(id2),obj_data(
id),obj_sz(
id));
150 struct APIDECL static_block_allocator {
153 static block_allocator *palloc;
157 #ifdef GETFEM_HAS_OPENMP
160 template<
typename T>
class small_vector :
public std::vector<T>
163 using typename std::vector<T>::const_iterator;
164 using typename std::vector<T>::iterator;
165 const_iterator begin()
const {
return std::vector<T>::begin(); }
166 iterator begin() {
return std::vector<T>::begin(); }
167 const_iterator end()
const {
return std::vector<T>::end(); }
168 iterator end() {
return std::vector<T>::end(); }
170 const_iterator const_begin()
const {
return std::vector<T>::cbegin(); }
171 const_iterator const_end()
const {
return std::vector<T>::cend(); }
172 dim_type size()
const {
return dim_type(std::vector<T>::size()); }
174 const small_vector<T>& operator=(
const small_vector<T>& other) {
175 std::vector<T>::operator=(other);
179 small_vector() : std::vector<T>() {}
181 explicit small_vector(
size_type n) : std::vector<T>(n) {}
183 small_vector(
const small_vector<T>& v) : std::vector<T>(v) {}
185 small_vector(
const std::vector<T>& v) : std::vector<T>(v) {}
187 small_vector(T v1, T v2) : std::vector<T>(2)
188 { (*this)[0] = v1; (*this)[1] = v2; }
190 small_vector(T v1, T v2, T v3) : std::vector<T>(3)
191 { (*this)[0] = v1; (*this)[1] = v2; (*this)[2] = v3; }
193 template<
class UNOP> small_vector(
const small_vector<T>& a, UNOP op)
194 : std::vector<T>(a.size())
195 { std::transform(a.begin(), a.end(), begin(), op); }
197 template<
class BINOP> small_vector(
const small_vector<T>& a,
const small_vector<T>& b, BINOP op)
198 : std::vector<T>(a.size())
199 { std::transform(a.begin(), a.end(), b.begin(), begin(), op); }
205 template<
typename T>
class small_vector :
public static_block_allocator {
206 typedef block_allocator::node_id node_id;
211 typedef T value_type;
213 typedef const T * const_pointer;
214 typedef T& reference;
215 typedef const T & const_reference;
217 typedef const T * const_iterator;
220 { GMM_ASSERT2(l <=size(),
"out of range, l="<<l<<
"size="<<size());
return base()[l]; }
222 { GMM_ASSERT2(l <= size(),
"out of range, l="<<l<<
"size="<<size());
return const_base()[l]; }
223 value_type at(
size_type l)
const {
return const_base()[l]; }
224 iterator begin() {
return base(); }
225 const_iterator begin()
const {
return const_base(); }
226 const_iterator const_begin()
const {
return const_base(); }
227 iterator end() {
return base()+size(); }
228 const_iterator end()
const {
return const_base()+size(); }
229 const_iterator const_end()
const {
return const_base()+size(); }
231 if (n == size())
return;
234 memcpy(other.base(), const_base(), std::min(size(),other.size())*
sizeof(value_type));
235 SVEC_ASSERT(
id==0 || refcnt());
237 SVEC_ASSERT(refcnt()); SVEC_ASSERT(other.id == 0 || other.refcnt());
238 }
else { allocator().dec_ref(
id);
id=0; }
242 node_id id2 = allocator().inc_ref(other.id);
243 allocator().dec_ref(
id);
id = id2;
244 SVEC_ASSERT(
id == 0 || refcnt()); SVEC_ASSERT(other.id == 0 || other.refcnt());
251 explicit small_vector(
const std::vector<T>& v) : id(allocate(v.size())) {
252 std::copy(v.begin(),v.end(),begin());
259 if (!allocator_destroyed())
260 allocator().dec_ref(
id);
264 { begin()[0] = v1; begin()[1] = v2; }
266 { begin()[0] = v1; begin()[1] = v2; begin()[2] = v3; }
268 : id(allocate(a.size())) { std::transform(a.begin(), a.end(), begin(), op); }
270 : id(allocate(a.size())) { std::transform(a.begin(), a.end(), b.begin(), begin(), op); }
271 bool empty()
const {
return id==0; }
272 unsigned char refcnt()
const {
return allocator().refcnt(
id); }
273 dim_type size()
const
274 {
return dim_type(allocator().obj_sz(
id)/
sizeof(value_type)); }
284 {
return -1.*(*this); }
291 const_iterator b = other.begin(); iterator it = begin();
292 for (
size_type i=0; i < size(); ++i) *it++ += *b++;
299 const_iterator b = other.begin(); iterator it = begin();
300 for (
size_type i=0; i < size(); ++i) *it++ -= *b++;
305 iterator it = begin(), ite=end();
306 while(it < ite) *it++ *= v;
312 return std::lexicographical_compare(begin(), end(), other.begin(), other.end());
314 void fill(T v) {
for (iterator it=begin(); it != end(); ++it) *it = v; }
316 #ifdef GETFEM_HAS_OPENMP
317 size_type memsize()
const {
return (size()*
sizeof(T)) +
sizeof(*this); }
319 size_type memsize()
const {
return (size()*
sizeof(T) / refcnt()) +
sizeof(*this); }
321 void push_back(T x) { resize(size()+1); begin()[size()-1] = x; }
325 allocator().duplicate_if_aliased(
id);
326 return static_cast<pointer
>(allocator().obj_data(
id));
329 const_pointer const_base()
const {
330 SVEC_ASSERT(
id == 0 || refcnt());
return static_cast<pointer
>(allocator().obj_data(
id));
332 block_allocator& allocator()
const {
return *palloc; }
333 bool allocator_destroyed()
const {
return palloc == 0; }
335 return node_id(allocator().allocate(gmm::uint32_type(n*
sizeof(value_type)))); SVEC_ASSERT(refcnt() == 1);
342 const_iterator b = other.begin(); iterator it = begin();
343 for (
size_type i=0; i < size(); ++i) *it++ += v * *b++;
348 template<
class T> std::ostream& operator<<(std::ostream& os,
const small_vector<T>& v) {
349 os <<
"[";
for (
size_type i=0; i < v.size(); ++i) {
if (i) os <<
", "; os << v[i]; }
350 os <<
"]";
return os;
353 template<
class T>
inline small_vector<T> operator *(T x,
const small_vector<T>& m)
357 template <
class VEC_CONT>
358 void vectors_to_base_matrix(base_matrix &G,
const VEC_CONT &a) {
359 size_type P = (*(a.begin())).size(), NP = a.end() - a.begin();
360 G.base_resize(P, NP);
361 typename VEC_CONT::const_iterator it = a.begin(), ite = a.end();
362 base_matrix::iterator itm = G.begin();
363 for (; it != ite; ++it, itm += P)
364 std::copy((*it).begin(), (*it).end(), itm);
367 typedef small_vector<scalar_type> base_small_vector;
368 typedef base_small_vector base_node;