summaryrefslogtreecommitdiff
path: root/core/pla_apply.hpp
diff options
context:
space:
mode:
authorJan Huwald <jh@sotun.de>2012-05-07 20:01:51 (GMT)
committerJan Huwald <jh@sotun.de>2012-05-07 20:01:51 (GMT)
commit420d2ef464d4a741028e132e662d5626806a41f5 (patch)
tree1aca6eb512e4ed0fb5f3c10c528cb998b6ffd695 /core/pla_apply.hpp
Initial commitHEADmaster
Diffstat (limited to 'core/pla_apply.hpp')
-rw-r--r--core/pla_apply.hpp276
1 files changed, 276 insertions, 0 deletions
diff --git a/core/pla_apply.hpp b/core/pla_apply.hpp
new file mode 100644
index 0000000..f9ab3f6
--- /dev/null
+++ b/core/pla_apply.hpp
@@ -0,0 +1,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
contact: Jan Huwald // Impressum