Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-01 10:04:13

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<std::size_t 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 HyperslabIndexer(
0040         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<std::size_t 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 HyperslabInverseIndexer(
0077         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<std::size_t 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<std::size_t N>
0111 CELER_FUNCTION size_type HyperslabIndexer<N>::operator()(
0112     Coords const& coords) const
0113 {
0114     CELER_EXPECT(coords[0] < dims_[0]);
0115     size_type result = coords[0];
0116 
0117     for (size_type i = 1; i < N; ++i)
0118     {
0119         CELER_EXPECT(coords[i] < dims_[i]);
0120         result = dims_[i] * result + coords[i];
0121     }
0122     return result;
0123 }
0124 
0125 //---------------------------------------------------------------------------//
0126 /*!
0127  * Convert N-dimensional coordinates to an index.
0128  */
0129 template<std::size_t N>
0130 template<typename... Args>
0131 CELER_FUNCTION size_type HyperslabIndexer<N>::operator()(Args... args) const
0132 {
0133     static_assert(sizeof...(Args) == N,
0134                   "Number of coordinates must match number of dimensions");
0135 
0136     return this->operator()(Coords{static_cast<size_type>(args)...});
0137 }
0138 
0139 //---------------------------------------------------------------------------//
0140 /*!
0141  * Construct from array denoting the sizes of each dimension.
0142  */
0143 template<std::size_t N>
0144 CELER_FUNCTION HyperslabInverseIndexer<N>::HyperslabInverseIndexer(
0145     Array<size_type, N> const& dims)
0146     : dims_(dims)
0147 {
0148     for (auto dim : dims_)
0149     {
0150         CELER_EXPECT(dim > 0);
0151     }
0152 }
0153 
0154 //---------------------------------------------------------------------------//
0155 /*!
0156  * Convert an index into N-dimensional coordinates.
0157  */
0158 template<std::size_t N>
0159 CELER_FUNCTION typename HyperslabInverseIndexer<N>::Coords
0160 HyperslabInverseIndexer<N>::operator()(size_type index) const
0161 {
0162     CELER_EXPECT(index <= detail::hyperslab_size(dims_));
0163     Coords coords;
0164 
0165     for (size_type i = dims_.size() - 1; i > 0; i--)
0166     {
0167         coords[i] = index % dims_[i];
0168         index = (index - coords[i]) / dims_[i];
0169     }
0170 
0171     coords[0] = index;
0172 
0173     return coords;
0174 }
0175 
0176 //---------------------------------------------------------------------------//
0177 }  // namespace celeritas