Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:23

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Project include(s).
0010 #include "detray/propagator/actor_chain.hpp"
0011 
0012 #include "detray/definitions/units.hpp"
0013 #include "detray/propagator/base_actor.hpp"
0014 #include "detray/propagator/concepts.hpp"
0015 
0016 // GTest include(s).
0017 #include <gtest/gtest.h>
0018 
0019 // System include(s).
0020 #include <sstream>
0021 #include <string>
0022 
0023 using namespace detray;
0024 
0025 /// Actor that prints its call chain and subject data
0026 struct print_actor : public detray::base_actor {
0027   /// State keeps an internal string representation
0028   struct state {
0029     std::stringstream stream{};
0030 
0031     state() = default;
0032     state(state &&) noexcept = default;
0033     state(const state &) = delete;
0034     state &operator=(state const &) = delete;
0035     state &operator=(state &&) noexcept = default;
0036 
0037     std::string to_string() const { return stream.str(); }
0038   };
0039 
0040   // Actor result: status code
0041   using result = detray::actor::result;
0042 
0043   /// Actor implementation: append call notification to internal string
0044   template <typename propagator_state_t>
0045   result operator()(state &printer_state,
0046                     const propagator_state_t & /*p_state*/) const {
0047     printer_state.stream << "[print actor]:";
0048 
0049     return {detray::actor::status::e_notify};
0050   }
0051 
0052   /// Observing actor implementation: append call notification to internal
0053   /// string
0054   template <typename subj_result_t, typename propagator_state_t>
0055   result operator()(state &printer_state,
0056                     const propagator_state_t & /*p_state*/,
0057                     const subj_result_t &res) const {
0058     printer_state.stream << "[print actor obs " << res.buffer->back() << "]:";
0059 
0060     return {detray::actor::status::e_notify};
0061   }
0062 };
0063 
0064 /// Example actor that couts the number of elements in its buffer
0065 template <template <typename...> class vector_t>
0066 struct example_actor : public detray::base_actor {
0067   /// Actor state
0068   struct state {
0069     // Keep dynamic data per propagation stream
0070     vector_t<float> buffer = {};
0071   };
0072 
0073   // Actor result
0074   struct result : detray::actor::result {
0075     vector_t<float> *buffer{nullptr};
0076   };
0077 
0078   /// Actor implementation: Counts vector elements
0079   template <typename propagator_state_t>
0080   result operator()(state &example_state,
0081                     const propagator_state_t & /*p_state*/) const {
0082     example_state.buffer.push_back(
0083         static_cast<float>(example_state.buffer.size()));
0084 
0085     return {{detray::actor::status::e_notify}, &example_state.buffer};
0086   }
0087 
0088   /// Observing actor implementation: Counts vector elements (division)
0089   template <typename propagator_state_t>
0090   result operator()(state &example_state,
0091                     const propagator_state_t & /*p_state*/,
0092                     const result &res) const {
0093     example_state.buffer.push_back(static_cast<float>(res.buffer->size()) *
0094                                    0.1f);
0095 
0096     return {{detray::actor::status::e_notify}, &example_state.buffer};
0097   }
0098 
0099   /// Observing actor implementation to printer: do nothing
0100   template <typename subj_result_t, typename propagator_state_t>
0101     requires(!std::is_same_v<subj_result_t, state>)
0102   result operator()(state &example_state,
0103                     const propagator_state_t & /*p_state*/,
0104                     const subj_result_t & /*subject_result*/) const {
0105     return {{detray::actor::status::e_notify}, &example_state.buffer};
0106   }
0107 };
0108 
0109 using example_actor_t = example_actor<std::vector>;
0110 // Implements example_actor with two print observers
0111 using composite1 = composite_actor<example_actor_t, print_actor, print_actor>;
0112 // Implements example_actor with one print observer
0113 using composite2 = composite_actor<example_actor_t, print_actor>;
0114 // Implements example_actor through composite2 and has composite1 as observer
0115 using composite3 = composite_actor<example_actor_t, composite1>;
0116 // Implements example_actor through composite2<-composite3 with composite1 obs.
0117 using composite4 = composite_actor<example_actor_t, composite1>;
0118 
0119 /* Test chaining of multiple actors
0120  * The chain goes as follows (depth first):
0121  *                          example_actor1
0122  *                              1.|
0123  *                          observer_lvl1 (print)
0124  *                              2.|
0125  *                          observer_lvl2 (example_actor observing print actor)
0126  *                      3./     5.|     6.\
0127  *            observer_lvl3 example_actor2 print
0128  *          (example_actor3)
0129  *               4.|
0130  *               print
0131  */
0132 using observer_lvl3 = composite_actor<example_actor_t, print_actor>;
0133 using observer_lvl2 = composite_actor<example_actor_t, observer_lvl3,
0134                                       example_actor_t, print_actor>;
0135 using observer_lvl1 = composite_actor<print_actor, observer_lvl2>;
0136 using chain = composite_actor<example_actor_t, observer_lvl1>;
0137 
0138 // Test the actor chain on some dummy actor types
0139 GTEST_TEST(detray_propagator, actor_chain) {
0140   static_assert(detray::concepts::actor<print_actor>);
0141   static_assert(detray::concepts::actor<example_actor_t>);
0142   static_assert(detray::concepts::actor<composite1>);
0143   static_assert(detray::concepts::actor<composite2>);
0144   static_assert(detray::concepts::actor<composite3>);
0145   static_assert(detray::concepts::actor<composite4>);
0146   static_assert(detray::concepts::actor<observer_lvl3>);
0147   static_assert(detray::concepts::actor<observer_lvl2>);
0148   static_assert(detray::concepts::actor<observer_lvl1>);
0149 
0150   static_assert(!detray::concepts::composite_actor<print_actor>);
0151   static_assert(!detray::concepts::composite_actor<example_actor_t>);
0152   static_assert(detray::concepts::composite_actor<composite1>);
0153   static_assert(detray::concepts::composite_actor<composite2>);
0154   static_assert(detray::concepts::composite_actor<composite3>);
0155   static_assert(detray::concepts::composite_actor<composite4>);
0156   static_assert(detray::concepts::composite_actor<observer_lvl3>);
0157   static_assert(detray::concepts::composite_actor<observer_lvl2>);
0158   static_assert(detray::concepts::composite_actor<observer_lvl1>);
0159 
0160   // The actor states (can be reused between actors)
0161   example_actor_t::state example_state{};
0162   print_actor::state printer_state{};
0163 
0164   // Aggregate actor states to be able to pass them through the chain
0165   auto actor_states = detray::tie(example_state, printer_state);
0166 
0167   // Propagator state
0168   struct empty_prop_state {};
0169   empty_prop_state prop_state{};
0170 
0171   // Chain of actors
0172   using actor_chain_t = actor_chain<example_actor_t, composite1, composite2,
0173                                     composite3, composite4>;
0174 
0175   static_assert(detray::concepts::actor_chain<actor_chain<>>);
0176   static_assert(detray::concepts::actor_chain<actor_chain_t>);
0177 
0178   // Run
0179   actor_chain_t run_actors{};
0180   run_actors(actor_states, prop_state);
0181 
0182   ASSERT_TRUE(printer_state.to_string().compare(
0183                   "[print actor obs 1]:[print actor obs 1]:[print actor obs "
0184                   "2]:[print actor obs 0.4]:[print actor obs 0.4]:[print "
0185                   "actor obs 0.6]:[print actor obs 0.6]:") == 0)
0186       << "Printer call chain: " << printer_state.to_string() << std::endl;
0187 
0188   // Test chaining of multiple actors
0189 
0190   // Reset example actor state
0191   example_state.buffer.clear();
0192   printer_state.stream.str("");
0193   printer_state.stream.clear();
0194 
0195   // Run the chain
0196   actor_chain<chain> run_chain{};
0197   run_chain(actor_states, prop_state);
0198 
0199   ASSERT_TRUE(printer_state.to_string().compare(
0200                   "[print actor obs 0]:[print actor obs 0.1]:[print actor "
0201                   "obs 0.2]:") == 0)
0202       << "Printer call chain: " << printer_state.to_string() << std::endl;
0203 }