#ifndef QwJZ8toZywNt6ETv1SpnUMCaNRM #define QwJZ8toZywNt6ETv1SpnUMCaNRM #include #include #include #include #include #include #include #include #include #include #include #include #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::result, typename EnableTime = typename QuantHasVarDelay::result> struct Intent; template struct Intent<_Q1, _Q2, bool_, _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 struct Intent, bool_> : Intent, bool_> { inline Intent() : result(QuantEmitDefault::value) {} inline void combine(bool val) { if (QuantEmitDefault::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 struct Intent, bool_> : Intent, bool_> { 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 struct Transaction { /// 1st use: storage // filter props to store struct filter_f { template struct apply { typedef typename Pair::first prop; typedef typename and_< typename is_same::type, typename ContinuousProperty_ApplyChangesProp::type >::type type; }; }; // transform property list item into (property, property::type) struct transform_f { template struct apply { typedef typename Item::first prop; typedef pair 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, insert<_1, _2> > >::type map_t; // instance vars typename if_, TypeMap, TypeMap >::type instance; // access template void set(typename at::type val) { instance.template get() = val; } /// 2nd use: PLA typedef Void result_t; template 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 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::type::value) { pc.cast(PLA_Set (time, Ptr(context.template getptr()), instance.template get())); } } template inline void post(PC &pc, _Data &data, LocalState &state) { } }; /// apply action template< typename SrcQuant, // discrete typename DstQuant, // continuous typename PropComp, typename Context = DelieverContext > struct PLA_Apply { // map->intent transformation template struct intent_from_type { typedef pair> type; }; // action types & consts typedef Void result_t; template struct local_state_t { typedef ContextProp property_t; }; typedef Transaction transaction_t; typedef TypeMap< typename transform< DiscreteQuantorList, intent_from_type<_1>, inserter, 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 inline void pre(PC &pc, ContextData &data, LocalState &) { // call apply definition for every destination property if (boost::is_same::value) { ContinuousProperty_Apply< PC, typename LocalState::property_t, DstQuant, SrcQuant, Context, intentmap_t, transaction_t> ::eval(pc, context, time, intent, transaction); } } template 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() or generate() or generate() or generate(); } template inline bool generate() { return intent.template get().getResult(); } template inline Time getDelay() { return intent.template get().getDelay(); } template void computeDelay(PC &pc) { // TODO (beauty, optimize): compile time fold over discrete // quantor list #define GEN_CD(Q) \ if (QuantHasVarDelay::result::value \ && QuantMayEmit::result::value) \ intent.template get().setDelay \ (DiscreteProperty_ComputeDelay \ ::eval(pc, context, transaction, time)); GEN_CD(GlobalMsg) GEN_CD(Spike) GEN_CD(RandomSpike) GEN_CD(SpikeArrival) #undef GEN_CD } template void commit(PC &pc) { pc.call(transaction); } private: PLA_Apply(); }; } using PLA_ApplyImpl::PLA_Apply; #endif // QwJZ8toZywNt6ETv1SpnUMCaNRM