Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:54:11

0001 /*
0002  * SPDX-PackageName: "covfie, a part of the ACTS project"
0003  * SPDX-FileCopyrightText: 2022 CERN
0004  * SPDX-License-Identifier: MPL-2.0
0005  */
0006 
0007 #pragma once
0008 
0009 #include <iostream>
0010 #include <memory>
0011 #include <numeric>
0012 #include <type_traits>
0013 
0014 #include <covfie/core/backend/primitive/array.hpp>
0015 #include <covfie/core/concepts.hpp>
0016 #include <covfie/core/parameter_pack.hpp>
0017 #include <covfie/core/qualifiers.hpp>
0018 #include <covfie/core/utility/binary_io.hpp>
0019 #include <covfie/core/utility/nd_map.hpp>
0020 #include <covfie/core/utility/nd_size.hpp>
0021 #include <covfie/core/vector.hpp>
0022 
0023 namespace covfie::backend {
0024 template <
0025     concepts::vector_descriptor _input_vector_t,
0026     concepts::field_backend _storage_t>
0027 struct strided {
0028     using this_t = strided<_input_vector_t, _storage_t>;
0029     static constexpr bool is_initial = false;
0030 
0031     using backend_t = _storage_t;
0032 
0033     using contravariant_input_t =
0034         covfie::vector::array_vector_d<_input_vector_t>;
0035     using contravariant_output_t = typename backend_t::contravariant_input_t;
0036     using covariant_input_t = typename backend_t::covariant_output_t;
0037     using covariant_output_t = covariant_input_t;
0038 
0039     using coordinate_t = typename contravariant_input_t::vector_t;
0040     using array_t = backend_t;
0041 
0042     using configuration_t = utility::nd_size<contravariant_input_t::dimensions>;
0043 
0044     static constexpr uint32_t IO_MAGIC_HEADER = 0xAB020010;
0045 
0046     template <typename T>
0047     static std::unique_ptr<
0048         std::decay_t<typename backend_t::covariant_output_t::vector_t>[]>
0049     make_strided_copy(const T & other)
0050     {
0051         configuration_t sizes = other.get_configuration();
0052         std::unique_ptr<
0053             std::decay_t<typename backend_t::covariant_output_t::vector_t>[]>
0054             res = std::make_unique<std::decay_t<
0055                 typename backend_t::covariant_output_t::vector_t>[]>(
0056                 std::accumulate(
0057                     std::begin(sizes),
0058                     std::end(sizes),
0059                     1ul,
0060                     std::multiplies<std::size_t>()
0061                 )
0062             );
0063         typename T::parent_t::non_owning_data_t nother(other);
0064 
0065         utility::nd_map<decltype(sizes)>(
0066             [&sizes, &nother, &res](decltype(sizes) t) {
0067                 typename contravariant_input_t::scalar_t idx = 0;
0068 
0069                 for (std::size_t k = 0; k < contravariant_input_t::dimensions;
0070                      ++k) {
0071                     typename contravariant_input_t::scalar_t tmp = t[k];
0072 
0073                     for (std::size_t l = k + 1;
0074                          l < contravariant_input_t::dimensions;
0075                          ++l)
0076                     {
0077                         tmp *= sizes[l];
0078                     }
0079 
0080                     idx += tmp;
0081                 }
0082 
0083                 for (std::size_t i = 0; i < covariant_output_t::dimensions; ++i)
0084                 {
0085                     if constexpr (covariant_output_t::dimensions == 1 && !std::unsigned_integral<std::decay_t<decltype(t)>>)
0086                     {
0087                         res[idx][i] = nother.at(t[0])[i];
0088                     } else {
0089                         res[idx][i] = nother.at(t)[i];
0090                     }
0091                 }
0092             },
0093             sizes
0094         );
0095 
0096         return res;
0097     }
0098 
0099     struct owning_data_t {
0100         using parent_t = this_t;
0101 
0102         owning_data_t()
0103             : owning_data_t(configuration_t{})
0104         {
0105         }
0106 
0107         owning_data_t(const owning_data_t &) = default;
0108         owning_data_t(owning_data_t &&) = default;
0109         owning_data_t & operator=(const owning_data_t &) = default;
0110         owning_data_t & operator=(owning_data_t &&) = default;
0111 
0112         template <typename T>
0113         requires(std::same_as<
0114                  typename T::parent_t::configuration_t,
0115                  configuration_t> &&
0116                      std::constructible_from<
0117                          typename backend_t::owning_data_t,
0118                          std::size_t,
0119                          std::add_rvalue_reference_t<std::unique_ptr<std::decay_t<
0120                              typename backend_t::covariant_output_t::
0121                                  vector_t>[]>>>) explicit owning_data_t(const T &
0122                                                                             o)
0123             : m_sizes(o.get_configuration())
0124             , m_storage(
0125                   std::accumulate(
0126                       std::begin(m_sizes),
0127                       std::end(m_sizes),
0128                       1ul,
0129                       std::multiplies<std::size_t>()
0130                   ),
0131                   make_strided_copy(o)
0132               )
0133         {
0134         }
0135 
0136         explicit owning_data_t(configuration_t conf
0137         ) requires(std::constructible_from<typename backend_t::owning_data_t, std::size_t> && !std::constructible_from<typename backend_t::owning_data_t, utility::nd_size<1>>)
0138             : m_sizes(conf)
0139             , m_storage(std::accumulate(
0140                   std::begin(m_sizes),
0141                   std::end(m_sizes),
0142                   static_cast<std::size_t>(1),
0143                   std::multiplies<std::size_t>()
0144               ))
0145         {
0146         }
0147 
0148         explicit owning_data_t(configuration_t conf)
0149             requires(std::constructible_from<
0150                      typename backend_t::owning_data_t,
0151                      utility::nd_size<1>>)
0152             : m_sizes(conf)
0153             , m_storage(utility::nd_size<1>{std::accumulate(
0154                   std::begin(m_sizes),
0155                   std::end(m_sizes),
0156                   static_cast<std::size_t>(1),
0157                   std::multiplies<std::size_t>()
0158               )})
0159         {
0160         }
0161 
0162         template <typename... Args>
0163         requires(sizeof...(Args) > 0) explicit owning_data_t(
0164             parameter_pack<configuration_t, Args...> && args
0165         )
0166             : m_sizes(args.x)
0167             , m_storage(std::move(args.xs))
0168         {
0169         }
0170 
0171         template <typename T>
0172         requires(std::constructible_from<
0173                  owning_data_t,
0174                  T>) explicit owning_data_t(parameter_pack<T> && args)
0175             : owning_data_t(args.x)
0176         {
0177         }
0178 
0179         explicit owning_data_t(
0180             const configuration_t & c, typename backend_t::owning_data_t && b
0181         )
0182             : m_sizes(c)
0183             , m_storage(std::forward<typename backend_t::owning_data_t>(b))
0184         {
0185         }
0186 
0187         typename backend_t::owning_data_t & get_backend(void)
0188         {
0189             return m_storage;
0190         }
0191 
0192         const typename backend_t::owning_data_t & get_backend(void) const
0193         {
0194             return m_storage;
0195         }
0196 
0197         configuration_t get_configuration(void) const
0198         {
0199             return m_sizes;
0200         }
0201 
0202         static owning_data_t read_binary(std::istream & fs)
0203         {
0204             utility::read_io_header(fs, IO_MAGIC_HEADER);
0205 
0206             auto sizes = utility::read_binary<decltype(m_sizes)>(fs);
0207             auto be = backend_t::owning_data_t::read_binary(fs);
0208 
0209             utility::read_io_footer(fs, IO_MAGIC_HEADER);
0210 
0211             return owning_data_t(sizes, std::move(be));
0212         }
0213 
0214         static void write_binary(std::ostream & fs, const owning_data_t & o)
0215         {
0216             utility::write_io_header(fs, IO_MAGIC_HEADER);
0217 
0218             fs.write(
0219                 reinterpret_cast<const char *>(&o.m_sizes),
0220                 sizeof(decltype(o.m_sizes))
0221             );
0222 
0223             backend_t::owning_data_t::write_binary(fs, o.m_storage);
0224 
0225             utility::write_io_footer(fs, IO_MAGIC_HEADER);
0226         }
0227 
0228         configuration_t m_sizes;
0229         typename backend_t::owning_data_t m_storage;
0230     };
0231 
0232     struct non_owning_data_t {
0233         using parent_t = this_t;
0234 
0235         non_owning_data_t(const owning_data_t & o)
0236             : m_sizes(o.m_sizes)
0237             , m_storage(o.m_storage)
0238         {
0239         }
0240 
0241         COVFIE_HOST_DEVICE typename covariant_output_t::vector_t
0242         at(coordinate_t c) const
0243         {
0244             typename contravariant_input_t::scalar_t idx = 0;
0245 
0246 #ifndef NDEBUG
0247             for (std::size_t i = 0; i < contravariant_input_t::dimensions; ++i)
0248             {
0249                 assert(c[i] < m_sizes[i]);
0250             }
0251 #endif
0252 
0253             for (std::size_t k = 0; k < contravariant_input_t::dimensions; ++k)
0254             {
0255                 typename contravariant_input_t::scalar_t tmp = c[k];
0256 
0257                 for (std::size_t l = k + 1;
0258                      l < contravariant_input_t::dimensions;
0259                      ++l)
0260                 {
0261                     tmp *=
0262                         static_cast<typename contravariant_input_t::scalar_t>(
0263                             m_sizes[l]
0264                         );
0265                 }
0266 
0267                 idx += tmp;
0268             }
0269 
0270             return m_storage.at({idx});
0271         }
0272 
0273         typename backend_t::non_owning_data_t & get_backend(void)
0274         {
0275             return m_storage;
0276         }
0277 
0278         const typename backend_t::non_owning_data_t & get_backend(void) const
0279         {
0280             return m_storage;
0281         }
0282 
0283         configuration_t m_sizes;
0284         typename backend_t::non_owning_data_t m_storage;
0285     };
0286 };
0287 }