1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
|
#ifndef QwJZ8toZywNt6ETv1SpnUMCaNRM
#define QwJZ8toZywNt6ETv1SpnUMCaNRM
#include <assert.h>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/copy_if.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/has_key.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/type_traits/is_same.hpp>
#include "context.hpp"
#include "continuous_property.hpp"
#include "pla_set.hpp"
#include "quant_types.hpp"
#include "template_helpers.hpp"
#include "time.hpp"
#include "type_map.hpp"
#include "model.hpp" // to specialize QuantMayEmit and
// QuantHasVarDelay before instanciation
namespace PLA_ApplyImpl {
using namespace boost::mpl;
using boost::is_same;
/// event intent
template<
typename EmittingQuant,
typename EmittedQuant,
typename Enable = typename QuantMayEmit<EmittingQuant, EmittedQuant>::result,
typename EnableTime = typename QuantHasVarDelay<EmittedQuant>::result>
struct Intent;
template<typename _Q1, typename _Q2, typename _B>
struct Intent<_Q1, _Q2, bool_<false>, _B> {
inline void combine(bool) {}
inline bool getResult() const { return false; }
inline void setDelay(Time t) const { DO_NOT_CALL }
inline Time getDelay() const { return Time(0); }
};
// intent without variable delay
template<typename SrcCQ, typename DstDQ>
struct Intent<SrcCQ, DstDQ, bool_<true>, bool_<false>>
: Intent<SrcCQ, DstDQ, bool_<false>, bool_<false>> {
inline Intent() :
result(QuantEmitDefault<SrcCQ, DstDQ>::value)
{}
inline void combine(bool val) {
if (QuantEmitDefault<SrcCQ, DstDQ>::value) {
// default == true -> combine via and
result = result and val;
}else{
// default == false -> combine via or
result = result or val;
}
}
inline bool getResult() const { return result; }
bool result;
};
// intent with variable delay
template<typename SrcCQ, typename DstDQ>
struct Intent<SrcCQ, DstDQ, bool_<true>, bool_<true>>
: Intent<SrcCQ, DstDQ, bool_<true>, bool_<false>> {
inline Intent() :
delay(Time::never())
{}
inline void setDelay(Time t) { delay = t; }
inline Time getDelay() const {
assert(delay != Time::never()); // assure setDelay has been called
return delay;
}
bool result;
Time delay;
};
/// event transaction: store changed values (and apply them later);
/// it is a PLA itself, but is not exported
template<typename SrcDQ,
typename DstCQ,
typename PC,
typename Context>
struct Transaction {
/// 1st use: storage
// filter props to store
struct filter_f {
template<typename Pair>
struct apply {
typedef typename Pair::first prop;
typedef typename and_<
typename is_same<typename prop::quant, DstCQ>::type,
typename ContinuousProperty_ApplyChangesProp<prop, SrcDQ>::type
>::type type;
};
};
// transform property list item into (property, property::type)
struct transform_f {
template<typename Item>
struct apply {
typedef typename Item::first prop;
typedef pair<prop, typename prop::type> type;
};
};
// compute map of props to store (filter and transform)
typedef typename transform<
typename copy_if<
typename PC::properties_t,
filter_f
>::type,
transform_f,
inserter<map<>, insert<_1, _2> >
>::type map_t;
// instance vars
typename if_<empty<map_t>,
TypeMap<Void>,
TypeMap<map_t>
>::type instance;
// access
template<typename Q>
void set(typename at<map_t, Q>::type val) {
instance.template get<Q>() = val;
}
/// 2nd use: PLA
typedef Void result_t;
template<typename ContextProp, bool _aaa> struct local_state_t {
typedef ContextProp property_t;
};
Transaction(Context context, Time time) : context(context), time(time) {}
Context context;
Time time;
result_t result;
template<typename ContextData, typename LocalState>
inline void pre(PC &pc, ContextData &data, LocalState &state) {
typedef typename LocalState::property_t prop_t;
typedef typename prop_t::quant quant_t;
if (has_key<map_t, prop_t>::type::value) {
pc.cast(PLA_Set<prop_t>
(time, Ptr<quant_t>(context.template getptr<quant_t>()),
instance.template get<prop_t, typename prop_t::type>()));
}
}
template<typename _Data, typename LocalState>
inline void post(PC &pc, _Data &data, LocalState &state) {
}
};
/// apply action
template<
typename SrcQuant, // discrete
typename DstQuant, // continuous
typename PropComp,
typename Context = DelieverContext<SrcQuant, DstQuant>
>
struct PLA_Apply {
// map->intent transformation
template<typename T>
struct intent_from_type {
typedef pair<T, Intent<DstQuant, T>> type;
};
// action types & consts
typedef Void result_t;
template<typename ContextProp, bool _doWriteResults> struct local_state_t {
typedef ContextProp property_t;
};
typedef Transaction<SrcQuant, DstQuant, PropComp, Context> transaction_t;
typedef TypeMap<
typename transform<
DiscreteQuantorList,
intent_from_type<_1>,
inserter<map<>, insert<_1, _2> >
>::type
> intentmap_t;
// action state & constructor
Context context;
intentmap_t intent;
Time time;
result_t result;
transaction_t transaction;
inline PLA_Apply(Time time, Context context)
: context(context), intent(), time(time), transaction(context, time) {}
// action methods
template<typename PC, typename ContextData, typename LocalState>
inline void pre(PC &pc, ContextData &data, LocalState &) {
// call apply definition for every destination property
if (boost::is_same<typename LocalState::property_t::quant, DstQuant>::value) {
ContinuousProperty_Apply<
PC, typename LocalState::property_t,
DstQuant, SrcQuant, Context,
intentmap_t, transaction_t>
::eval(pc, context, time, intent, transaction);
}
}
template<typename _PC, typename _Data, typename LocalState>
inline void post(_PC &pc, _Data &data, LocalState &state) {
}
// after-use queries
inline bool generateAny() {
// TODO (beauty, optimize): compile time fold over discrete
// quantor list, removing queries of quants we do never emit
return generate<GlobalMsg>()
or generate<Spike>()
or generate<RandomSpike>()
or generate<SpikeArrival>();
}
template<typename Q>
inline bool generate() {
return intent.template get<Q>().getResult();
}
template<typename Q>
inline Time getDelay() {
return intent.template get<Q>().getDelay();
}
template<typename PC>
void computeDelay(PC &pc) {
// TODO (beauty, optimize): compile time fold over discrete
// quantor list
#define GEN_CD(Q) \
if (QuantHasVarDelay<Q>::result::value \
&& QuantMayEmit<DstQuant, Q>::result::value) \
intent.template get<Q>().setDelay \
(DiscreteProperty_ComputeDelay<Q, DstQuant> \
::eval(pc, context, transaction, time));
GEN_CD(GlobalMsg)
GEN_CD(Spike)
GEN_CD(RandomSpike)
GEN_CD(SpikeArrival)
#undef GEN_CD
}
template<typename PC>
void commit(PC &pc) {
pc.call(transaction);
}
private:
PLA_Apply();
};
}
using PLA_ApplyImpl::PLA_Apply;
#endif // QwJZ8toZywNt6ETv1SpnUMCaNRM
|