diff options
author | Jan Huwald <jh@sotun.de> | 2012-05-07 20:01:51 (GMT) |
---|---|---|
committer | Jan Huwald <jh@sotun.de> | 2012-05-07 20:01:51 (GMT) |
commit | 420d2ef464d4a741028e132e662d5626806a41f5 (patch) | |
tree | 1aca6eb512e4ed0fb5f3c10c528cb998b6ffd695 /core/pla_apply.hpp |
Diffstat (limited to 'core/pla_apply.hpp')
-rw-r--r-- | core/pla_apply.hpp | 276 |
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 |