1
#ifndef BOOST_PP_IS_ITERATING
2
#ifndef _RHEOLEF_POLYMORPHIC_DATA_MAP_H
3
#define _RHEOLEF_POLYMORPHIC_DATA_MAP_H
5
/// This file is part of Rheolef.
7
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
9
/// Rheolef is free software; you can redistribute it and/or modify
10
/// it under the terms of the GNU General Public License as published by
11
/// the Free Software Foundation; either version 2 of the License, or
12
/// (at your option) any later version.
14
/// Rheolef is distributed in the hope that it will be useful,
15
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
/// GNU General Public License for more details.
19
/// You should have received a copy of the GNU General Public License
20
/// along with Rheolef; if not, write to the Free Software
21
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
/// =========================================================================
25
#include "rheolef/polymorphic_data_vector.h"
29
#include <boost/array.hpp>
30
#include <boost/mpl/vector.hpp>
31
#include <boost/mpl/size.hpp>
32
#include <boost/mpl/for_each.hpp>
33
#include <boost/mpl/at.hpp>
36
namespace mpl = boost::mpl;
38
// -----------------------------------------------------------------------
39
// some auxilliary functions
40
// -----------------------------------------------------------------------
41
/// @brief transform a map::iterator into a void*
42
template <class MapTk>
44
to_pointer (typename MapTk::iterator iter_tk)
46
return static_cast<void*>(iter_tk._M_node); // WARNING: depend upon GNU C++ STL (HP & SGI)
48
/// @brief transform a void* into a map::iterator
49
template <class MapTk>
50
typename MapTk::iterator
51
to_iterator (void* ptr)
53
typedef typename MapTk::iterator iterator;
54
typedef typename iterator::_Link_type link_type;
55
return iterator (static_cast<link_type>(ptr));
57
// -----------------------------------------------------------------------
58
// Advantage of this class: allows replacement of a i-th element in the table
59
// by another that could have a different derived type.
60
// possible application: replace a triangle by a curvilinear triangle
61
// on the boundary. Suitable for P2 boundary transformation.
63
/// @brief dynamic memory area handler for polymorphic_array
64
template <class T, class V, int NV>
65
struct polymorphic_data_map {};
67
// --------------------------------------------------------------------------------
68
// new_entry<Tk>() returns a pointer Tk* newly allocated into the data structure
69
// via a push_back. We need a specialisation of a template member function
70
// into a template class. This is not allowed... So, we use the same trick as
71
// for the "reserve(n)" member: we use a template class-function, with specialisation.
73
template <class Tk, class T, class V, int NV>
74
struct my_new_entry_map_t {
75
Tk* operator() (polymorphic_data_map<T,V,NV>& x) {
76
error_macro ("unexpected type " << typename_macro(Tk));
80
// ----------------------------------------------------------
81
// run here the recursive inclusion of this file:
82
// ----------------------------------------------------------
83
// _RHEOLEF_POLYMORPHIC_MAX_SIZE was defined by "polymorphic_data_vector.h"
84
#define BOOST_PP_ITERATION_LIMITS (0, _RHEOLEF_POLYMORPHIC_MAX_SIZE)
85
#define BOOST_PP_FILENAME_1 "rheolef/polymorphic_data_map.h" // this file
86
#include BOOST_PP_ITERATE()
88
} // namespace rheolef
89
#endif // _RHEOLEF_POLYMORPHIC_DATA_MAP_H
90
#else // BOOST_PP_IS_ITERATING
91
// ----------------------------------------------------------
92
// here, this file is recursively included with growing "N" :
93
// ----------------------------------------------------------
94
#define N BOOST_PP_ITERATION()
96
template <class T, class V>
97
struct polymorphic_data_map<T,V,N> {
101
static const size_t _n_variant = mpl::size<V>::value; // should be = N
102
typedef typename std::vector<int>::size_type size_type;
104
#define _RHEOLEF_typedef(z,k,unused) \
105
typedef typename mpl::at_c<V,k>::type T##k; \
106
typedef std::map <size_type, T##k, std::less<size_type>, \
107
heap_allocator<std::pair<size_type, T##k> > > map##k##_type;
108
BOOST_PP_REPEAT(N, _RHEOLEF_typedef, ~)
109
#undef _RHEOLEF_typedef
113
#define _RHEOLEF_stack_initializer(z,k,unused) \
116
polymorphic_data_map(size_type n=0) :
117
BOOST_PP_REPEAT(N, _RHEOLEF_stack_initializer, ~)
122
std::fill (_counter.begin(), _counter.end(), 0);
124
void resize (size_type n) {
128
#undef _RHEOLEF_stack_initializer
130
// accessors & modifiers:
133
size_type size () const { return _max_size; }
134
size_type size (size_type k) const { return _counter[k]; }
135
const size_type* begin_sizes () const { return _counter.begin(); }
137
void erase (size_type index);
139
#define _RHEOLEF_assign(z,k,unused) \
140
void assign (size_type index, const T##k& value);
141
BOOST_PP_REPEAT(N, _RHEOLEF_assign, ~)
142
#undef _RHEOLEF_assign
146
#define _RHEOLEF_stack_clear(z,k,unused) \
148
BOOST_PP_REPEAT(N, _RHEOLEF_stack_clear, ~)
149
#undef _RHEOLEF_stack_clear
151
std::fill (_counter.begin(), _counter.end(), 0);
154
void update_sizes () {
156
#define _RHEOLEF_stack_set_counter(z,k,unused) \
157
_counter[k] = _stack_##k.size();
158
BOOST_PP_REPEAT(N, _RHEOLEF_stack_set_counter, ~)
159
#undef _RHEOLEF_stack_set_counter
162
for (size_type k = 0; k < _n_variant; k++) {
163
_size += _counter[k];
167
template <class Tk> Tk* new_entry ();
171
#define _RHEOLEF_stack_declare(z,k,unused) \
172
map##k##_type _stack_##k;
173
BOOST_PP_REPEAT(N, _RHEOLEF_stack_declare, ~)
174
#undef _RHEOLEF_stack_declare
176
boost::array<size_type,_n_variant> _counter;
181
// asignment: x[i] = value
182
// it's more complex: if value is of type Tk, and x[i] points to a Tl != Tk
183
// then, we have to clear the old x[i] object from the l-eme map structure,
184
// en ayant avant sauvegarde' son index (qui doit etre egal a i..)
185
// et inserer valeur dans la Tk-stack avec cet index
186
template <class T, class V>
188
polymorphic_data_map<T,V,N>::erase (size_type global_index) {
189
#define _RHEOLEF_erase(z,k,unused) \
190
typename map##k##_type::iterator iter_##k = _stack_##k.find(global_index); \
191
if (iter_##k != _stack_##k.end()) { \
192
_stack_##k.erase (iter_##k); \
196
BOOST_PP_REPEAT(N, _RHEOLEF_erase, ~)
197
#undef _RHEOLEF_erase
200
#define _RHEOLEF_assign(z,k,unused) \
201
template <class T, class V> \
203
polymorphic_data_map<T,V,N>::assign (size_type global_index, const T##k& value) { \
204
/* erase any value with the same index */ \
205
erase (global_index); \
206
/* here, the location is empty: insert */ \
207
typedef typename map##k##_type::iterator iterator; \
208
std::pair<iterator,bool> status \
209
= _stack_##k.insert (std::pair<size_type,T##k>(global_index,value)); \
210
check_macro (status.second, "insert failed"); \
214
BOOST_PP_REPEAT(N, _RHEOLEF_assign, ~)
215
#undef _RHEOLEF_assign
217
// convert a data_map into a data(vector)
218
template <class T, class V>
220
polymorphic_data_vector<T,V,N>::build (const class polymorphic_data_map<T,V,N>& pool)
222
#define _RHEOLEF_stack_copy(z,k,unused) \
223
_stack_##k.resize (pool._stack_##k.size()); \
224
copy (pool._stack_##k.begin(), pool._stack_##k.end(), _stack_##k.begin());
226
BOOST_PP_REPEAT(N, _RHEOLEF_stack_copy, ~)
227
std::copy (pool._counter.begin(), pool._counter.end(), _counter.begin());
230
#undef _RHEOLEF_stack_copy
232
// specialization for each Tk:
233
#define _RHEOLEF_new_entry(z,k,unused) \
234
template <class T, class V> \
235
struct my_new_entry_map_t <typename polymorphic_data_map<T,V,N>::T##k, T,V,N> { \
236
typedef typename polymorphic_data_map<T,V,N>::T##k T##k; \
237
typedef typename polymorphic_data_map<T,V,N>::size_type size_type; \
238
T##k* operator() (polymorphic_data_map<T,V,N>& x) { \
239
typedef typename polymorphic_data_map<T,V,N>::map##k##_type map_type; \
240
typedef typename map_type::iterator iterator; \
241
check_macro (x._size < x._max_size, "too many entries"); \
242
const size_type variant = k; \
243
std::pair<iterator,bool> status \
244
= x._stack_##k.insert (std::pair<size_type,T##k> (x._size, T##k())); \
245
check_macro (status.second, "insert failed"); \
246
iterator iter = status.first; \
247
x._counter[variant]++; \
249
T##k* p = &((*iter).second); \
253
BOOST_PP_REPEAT(N, _RHEOLEF_new_entry, ~)
254
#undef _RHEOLEF_new_entry
256
template <class T, class V>
260
polymorphic_data_map<T,V,N>::new_entry ()
262
my_new_entry_map_t<Tk,T,V,N> new_entry_f;
263
return new_entry_f (*this);
266
#endif // BOOST_PP_IS_ITERATING