Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-15 08:55:04

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file corecel/data/HyperslabIndexer.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include "corecel/Assert.hh"
0010 #include "corecel/Types.hh"
0011 #include "corecel/cont/Array.hh"
0012 
0013 #include "detail/HyperslabIndexerImpl.hh"
0014 
0015 namespace celeritas
0016 {
0017 //---------------------------------------------------------------------------//
0018 /*!
0019  * Class for indexing into flattened N-dimensional data (N-D coords to index)
0020  *
0021  * Indexing is in standard C iteration order, such that final dimension
0022  * "changes fastest". For example, when indexing into a 3D grid (N=3) with
0023  * coords (i=0, j=0, k=1) the resulting index will be 1.
0024  *
0025  * \todo
0026  * https://github.com/celeritas-project/celeritas/pull/1518#discussion_r1856614365
0027  */
0028 template<size_type N>
0029 class HyperslabIndexer
0030 {
0031   public:
0032     //!@{
0033     //! \name Type aliases
0034     using Coords = Array<size_type, N>;
0035     //!@}
0036 
0037   public:
0038     // Construct with an array denoting the size of each dimension
0039     explicit inline CELER_FUNCTION
0040     HyperslabIndexer(Array<size_type, N> const& dims);
0041 
0042     //// METHODS ////
0043 
0044     //! Convert N-dimensional coordinates to an index
0045     inline CELER_FUNCTION size_type operator()(Coords const& coords) const;
0046 
0047     //! Convert N-dimensional coordinates to an index
0048     template<typename... Args>
0049     inline CELER_FUNCTION size_type operator()(Args... args) const;
0050 
0051   private:
0052     //// DATA ////
0053 
0054     Array<size_type, N> const& dims_;
0055 };
0056 
0057 //---------------------------------------------------------------------------//
0058 /*!
0059  * Class for indexing into flattened N-dimensional data (index to N-D coords)
0060  *
0061  * Indexing is in standard C iteration order, such that final dimension
0062  * "changes fastest". For example, when indexing into a 3D grid (N=3), index 1
0063  * will result in coords (i=0, j=0, k=1).
0064  */
0065 template<size_type N>
0066 class HyperslabInverseIndexer
0067 {
0068   public:
0069     //!@{
0070     //! \name Type aliases
0071     using Coords = Array<size_type, N>;
0072     //!@}
0073 
0074   public:
0075     // Construct with an array denoting the size of each dimension
0076     explicit inline CELER_FUNCTION
0077     HyperslabInverseIndexer(Array<size_type, N> const& dims);
0078 
0079     //// METHODS ////
0080 
0081     //! Convert an index to N-dimensional coordinates
0082     inline CELER_FUNCTION Coords operator()(size_type index) const;
0083 
0084   private:
0085     //// DATA ////
0086 
0087     Array<size_type, N> const& dims_;
0088 };
0089 
0090 //---------------------------------------------------------------------------//
0091 // INLINE DEFINITIONS
0092 //---------------------------------------------------------------------------//
0093 /*!
0094  * Construct from array denoting the sizes of each dimension.
0095  */
0096 template<size_type N>
0097 CELER_FUNCTION HyperslabIndexer<N>::HyperslabIndexer(Coords const& dims)
0098     : dims_(dims)
0099 {
0100     for (auto dim : dims_)
0101     {
0102         CELER_EXPECT(dim > 0);
0103     }
0104 }
0105 
0106 //---------------------------------------------------------------------------//
0107 /*!
0108  * Convert N-dimensional coordinates to an index.
0109  */
0110 template<size_type N>
0111 CELER_FUNCTION size_type HyperslabIndexer<N>::operator()(Coords const& coords) const
0112 {
0113     CELER_EXPECT(coords[0] < dims_[0]);
0114     size_type result = coords[0];
0115 
0116     for (size_type i = 1; i < N; ++i)
0117     {
0118         CELER_EXPECT(coords[i] < dims_[i]);
0119         result = dims_[i] * result + coords[i];
0120     }
0121     return result;
0122 }
0123 
0124 //---------------------------------------------------------------------------//
0125 /*!
0126  * Convert N-dimensional coordinates to an index.
0127  */
0128 template<size_type N>
0129 template<typename... Args>
0130 CELER_FUNCTION size_type HyperslabIndexer<N>::operator()(Args... args) const
0131 {
0132     static_assert(sizeof...(Args) == N,
0133                   "Number of coordinates must match number of dimensions");
0134 
0135     return this->operator()(Coords{static_cast<size_type>(args)...});
0136 }
0137 
0138 //---------------------------------------------------------------------------//
0139 /*!
0140  * Construct from array denoting the sizes of each dimension.
0141  */
0142 template<size_type N>
0143 CELER_FUNCTION HyperslabInverseIndexer<N>::HyperslabInverseIndexer(
0144     Array<size_type, N> const& dims)
0145     : dims_(dims)
0146 {
0147     for (auto dim : dims_)
0148     {
0149         CELER_EXPECT(dim > 0);
0150     }
0151 }
0152 
0153 //---------------------------------------------------------------------------//
0154 /*!
0155  * Convert an index into N-dimensional coordinates.
0156  */
0157 template<size_type N>
0158 CELER_FUNCTION typename HyperslabInverseIndexer<N>::Coords
0159 HyperslabInverseIndexer<N>::operator()(size_type index) const
0160 {
0161     CELER_EXPECT(index <= detail::hyperslab_size(dims_));
0162     Coords coords;
0163 
0164     for (size_type i = dims_.size() - 1; i > 0; i--)
0165     {
0166         coords[i] = index % dims_[i];
0167         index = (index - coords[i]) / dims_[i];
0168     }
0169 
0170     coords[0] = index;
0171 
0172     return coords;
0173 }
0174 
0175 //---------------------------------------------------------------------------//
0176 }  // namespace celeritas