From df01ef8c1f623cd6e5efed5e321d84a7430b4c71 Mon Sep 17 00:00:00 2001
From: Olivier Coulaud <olivier.coulaud@inria.fr>
Date: Wed, 12 Feb 2025 12:46:06 +0100
Subject: [PATCH] Add a function (ptr_on_variables()) to access the tuple
 pointing to the first element of the variables in the particle block

---
 include/scalfmm/container/block.hpp | 32 ++++++++++++++++++--
 include/scalfmm/meta/utils.hpp      | 46 +++++++++++++++++++++++++++--
 2 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/include/scalfmm/container/block.hpp b/include/scalfmm/container/block.hpp
index 225dfefc..8543890b 100644
--- a/include/scalfmm/container/block.hpp
+++ b/include/scalfmm/container/block.hpp
@@ -89,6 +89,7 @@ namespace scalfmm::container
 
         static constexpr std::size_t variables_size = particle_type::variables_size;
         using variables_type = typename Particle::variables_type;
+        using pointer_variables_type = meta::ToPointerTuple_t<variables_type>;
 
         static constexpr std::size_t block_particle_raw = get_particle_raw_size();
 
@@ -414,6 +415,33 @@ namespace scalfmm::container
             return reinterpret_cast<outputs_value_type*>(std::get<dimension_size + inputs_size>(m_tuple_start));
         }
 
+        /**
+         * @brief Get the pointer of the variables inside the block
+         *
+         * This pointer allows to access the different variables as arrays.
+         * \code
+         *   auto variable_storage = pg->storage().ptr_on_variables();
+         *   auto first_varaible = std::get<0>(variable_storage);
+         *   auto second_varaible = std::get<1>(variable_storage);  
+         *   auto input_storage = pg->storage().ptr_on_input();
+         * 
+         *  for (auto i(0); i < pg->storage().size(); ++i)
+         *   {
+         *       input_storage[i] = Q[index[i]];
+         *   }       
+         * \endcode
+         *
+         * @returnvariables_value_type* const
+         **/
+        inline auto ptr_on_variables() const noexcept -> pointer_variables_type const
+        {
+            using range_variable =
+              meta::make_range_sequence<dimension_size + inputs_size + outputs_size,
+                                        dimension_size + inputs_size + outputs_size + variables_size>;
+            auto tuple_variables = meta::make_sub_tuple(m_tuple_start, range_variable{});
+
+            return tuple_variables;
+        }
         /**
          * @brief Sets all positions inside the block to zero.
          */
@@ -623,8 +651,8 @@ namespace scalfmm::container
          * @param nb_particles number of particles
          * @return tuple_ptr_type
          */
-        inline constexpr auto init_tuple_start(raw_type* const start_in,
-                                               std::size_t nb_particles) const noexcept -> tuple_ptr_type
+        inline constexpr auto init_tuple_start(raw_type* const start_in, std::size_t nb_particles) const noexcept
+          -> tuple_ptr_type
         {
             auto start{start_in};
             tuple_ptr_type tuple_start{};
diff --git a/include/scalfmm/meta/utils.hpp b/include/scalfmm/meta/utils.hpp
index 160101e1..194b6a0a 100644
--- a/include/scalfmm/meta/utils.hpp
+++ b/include/scalfmm/meta/utils.hpp
@@ -135,6 +135,46 @@ namespace scalfmm::meta
         }
     };
 
+    /**
+     *  @brief  Type deduction: Converts a std::tuple<Ts...> into a std::tuple<Ts*...>.
+     */
+    template<typename Tuple>
+    struct ToPointerTuple;
+
+    /**
+     *  @brief  Specialization for std::tuple<Ts...>
+     */
+    template<typename... Ts>
+    struct ToPointerTuple<std::tuple<Ts...>>
+    {
+        using type = std::tuple<typename std::add_pointer<Ts>::type...>;
+    };
+
+    /**
+     *  @brief   Aliases to simplify use
+     * 
+     *  How to use if
+     *  @code
+     *     // Define a tuple of values
+     *       using ValueTuple = std::tuple<int, float>;
+     *
+     *    // Automatic generation of the std::tuple<int*, float*> type
+     *   using PointerTuple = ToPointerTuple_t<ValueTuple>;
+     * @endcode
+     */
+    template<typename Tuple>
+    using ToPointerTuple_t = typename ToPointerTuple<Tuple>::type;
+
+    /// @brief   Function that takes a tuple of values and returns a tuple of pointers to its elements
+    /// @tparam ...Ts
+    /// @param values
+    /// @return a tuple of pointers to its elements
+    template<typename... Ts>
+    auto tupleToPointerTuple(std::tuple<Ts...>& values)
+    {
+        return std::apply([](auto&... args) { return std::make_tuple(&args...); }, values);
+    }
+
     /**
      * @brief
      *
@@ -396,9 +436,9 @@ namespace scalfmm::meta
      * std::make_index_sequence<meta::tuple_size<std::decay_t<T>>::value>()))
      */
     template<typename T>
-    inline constexpr auto
-    reverse(T&& t) -> decltype(reverse_impl(std::forward<T>(t),
-                                            std::make_index_sequence<meta::tuple_size<std::decay_t<T>>::value>()))
+    inline constexpr auto reverse(T&& t)
+      -> decltype(reverse_impl(std::forward<T>(t),
+                               std::make_index_sequence<meta::tuple_size<std::decay_t<T>>::value>()))
     {
         return reverse_impl(std::forward<T>(t), std::make_index_sequence<meta::tuple_size<std::decay_t<T>>::value>());
     }
-- 
GitLab