Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:46

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2020-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file corecel/cont/Span.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <cstddef>
0011 #include <type_traits>
0012 
0013 #include "Array.hh"
0014 
0015 #include "detail/SpanImpl.hh"
0016 
0017 namespace celeritas
0018 {
0019 //---------------------------------------------------------------------------//
0020 //! Sentinel value for span of dynamic type
0021 constexpr std::size_t dynamic_extent = detail::dynamic_extent;
0022 
0023 //---------------------------------------------------------------------------//
0024 /*!
0025  * Non-owning reference to a contiguous span of data.
0026  * \tparam T value type
0027  * \tparam Extent fixed size; defaults to dynamic.
0028  *
0029  * This Span class is a modified backport of the C++20 \c std::span . In
0030  * Celeritas, it is often used as a return value from accessing elements in a
0031  * \c Collection.
0032  *
0033  * Like the \ref celeritas::Array , this class isn't 100% compatible
0034  * with the \c std::span class (partly of course because language features
0035  * are missing from C++14). The hope is that it will be complete and correct
0036  * for the use cases needed by Celeritas (and, as a bonus, it will be
0037  * device-compatible).
0038  *
0039  * Notably, only a subset of the functions (those having to do with size) are
0040  * \c constexpr. This is to allow debug assertions.
0041  *
0042  * Span can be instantiated with the special marker type \c LdgValue<T> to
0043  * optimize reading constant data on device memory. In that case, data returned
0044  * by \c front, \c back, \c operator[] and \c begin / \c end iterator use value
0045  * semantics instead of reference. \c data still returns a pointer to the data
0046  * and can be used to bypass using \c LdgIterator
0047  */
0048 template<class T, std::size_t Extent = dynamic_extent>
0049 class Span
0050 {
0051     using SpanTraitsT = detail::SpanTraits<T>;
0052 
0053   public:
0054     //!@{
0055     //! \name Type aliases
0056     using element_type = typename SpanTraitsT::element_type;
0057     using value_type = std::remove_cv_t<element_type>;
0058     using size_type = std::size_t;
0059     using pointer = typename SpanTraitsT::pointer;
0060     using const_pointer = typename SpanTraitsT::const_pointer;
0061     using reference = typename SpanTraitsT::reference;
0062     using const_reference = typename SpanTraitsT::const_reference;
0063     using iterator = typename SpanTraitsT::iterator;
0064     using const_iterator = typename SpanTraitsT::const_iterator;
0065     //!@}
0066 
0067     //! Size (may be dynamic)
0068     static constexpr std::size_t extent = Extent;
0069 
0070   public:
0071     //// CONSTRUCTION ////
0072 
0073     //! Construct with default null pointer and size zero
0074     constexpr Span() = default;
0075 
0076     //! Construct from data and size
0077     CELER_FORCEINLINE_FUNCTION Span(pointer d, size_type s) : s_(d, s) {}
0078 
0079     //! Construct from two contiguous random-access iterators
0080     template<class Iter>
0081     CELER_FORCEINLINE_FUNCTION Span(Iter first, Iter last)
0082         : s_(&(*first), static_cast<size_type>(last - first))
0083     {
0084     }
0085 
0086     //! Construct from a C array
0087     template<std::size_t N>
0088     CELER_CONSTEXPR_FUNCTION Span(element_type (&arr)[N]) : s_(arr, N)
0089     {
0090     }
0091 
0092     //! Construct from another span
0093     template<class U, std::size_t N>
0094     CELER_CONSTEXPR_FUNCTION Span(Span<U, N> const& other)
0095         : s_(other.data(), other.size())
0096     {
0097     }
0098 
0099     //! Copy constructor (same template parameters)
0100     Span(Span const&) noexcept = default;
0101 
0102     //! Assignment (same template parameters)
0103     Span& operator=(Span const&) noexcept = default;
0104 
0105     //// ACCESS ////
0106 
0107     //!@{
0108     //! \name Iterators
0109     CELER_CONSTEXPR_FUNCTION iterator begin() const { return s_.data; }
0110     CELER_CONSTEXPR_FUNCTION iterator end() const { return s_.data + s_.size; }
0111     //!@}
0112 
0113     //!@{
0114     //! \name Element access
0115     CELER_CONSTEXPR_FUNCTION reference operator[](size_type i) const
0116     {
0117         return s_.data[i];
0118     }
0119     CELER_CONSTEXPR_FUNCTION reference front() const { return s_.data[0]; }
0120     CELER_CONSTEXPR_FUNCTION reference back() const
0121     {
0122         return s_.data[s_.size - 1];
0123     }
0124     CELER_CONSTEXPR_FUNCTION pointer data() const
0125     {
0126         return static_cast<pointer>(s_.data);
0127     }
0128     //!@}
0129 
0130     //!@{
0131     //! \name Observers
0132     CELER_CONSTEXPR_FUNCTION bool empty() const { return s_.size == 0; }
0133     CELER_CONSTEXPR_FUNCTION size_type size() const { return s_.size; }
0134     CELER_CONSTEXPR_FUNCTION size_type size_bytes() const
0135     {
0136         return sizeof(element_type) * s_.size;
0137     }
0138     //!@}
0139 
0140     //!@{
0141     //! \name Subviews
0142     template<std::size_t Count>
0143     CELER_FUNCTION Span<T, Count> first() const
0144     {
0145         CELER_EXPECT(Count == 0 || Count <= this->size());
0146         return {this->data(), Count};
0147     }
0148     CELER_FUNCTION
0149     Span<T, dynamic_extent> first(std::size_t count) const
0150     {
0151         CELER_EXPECT(count <= this->size());
0152         return {this->data(), count};
0153     }
0154 
0155     template<std::size_t Offset, std::size_t Count = dynamic_extent>
0156     CELER_FUNCTION Span<T, detail::subspan_extent(Extent, Offset, Count)>
0157     subspan() const
0158     {
0159         CELER_EXPECT((Count == dynamic_extent) || (Offset == 0 && Count == 0)
0160                      || (Offset + Count <= this->size()));
0161         return {this->data() + Offset,
0162                 detail::subspan_size(this->size(), Offset, Count)};
0163     }
0164     CELER_FUNCTION
0165     Span<T, dynamic_extent>
0166     subspan(std::size_t offset, std::size_t count = dynamic_extent) const
0167     {
0168         CELER_EXPECT(offset + count <= this->size());
0169         return {this->data() + offset,
0170                 detail::subspan_size(this->size(), offset, count)};
0171     }
0172 
0173     template<std::size_t Count>
0174     CELER_FUNCTION Span<T, Count> last() const
0175     {
0176         CELER_EXPECT(Count == 0 || Count <= this->size());
0177         return {this->data() + this->size() - Count, Count};
0178     }
0179     CELER_FUNCTION
0180     Span<T, dynamic_extent> last(std::size_t count) const
0181     {
0182         CELER_EXPECT(count <= this->size());
0183         return {this->data() + this->size() - count, count};
0184     }
0185     //!@}
0186 
0187   private:
0188     //! Storage
0189     detail::SpanImpl<T, Extent> s_;
0190 };
0191 
0192 template<class T, std::size_t N>
0193 constexpr std::size_t Span<T, N>::extent;
0194 
0195 //---------------------------------------------------------------------------//
0196 // FREE FUNCTIONS
0197 //---------------------------------------------------------------------------//
0198 //! Get a mutable fixed-size view to an array
0199 template<class T, std::size_t N>
0200 CELER_CONSTEXPR_FUNCTION Span<T, N> make_span(Array<T, N>& x)
0201 {
0202     return {x.data(), N};
0203 }
0204 
0205 //---------------------------------------------------------------------------//
0206 //! Get a constant fixed-size view to an array
0207 template<class T, std::size_t N>
0208 CELER_CONSTEXPR_FUNCTION Span<T const, N> make_span(Array<T, N> const& x)
0209 {
0210     return {x.data(), N};
0211 }
0212 
0213 //---------------------------------------------------------------------------//
0214 //! Get a mutable fixed-size view to a C array
0215 template<class T, std::size_t N>
0216 CELER_CONSTEXPR_FUNCTION Span<T, N> make_span(T (&arr)[N])
0217 {
0218     return {arr};
0219 }
0220 
0221 //---------------------------------------------------------------------------//
0222 //! Get a mutable view to a generic container
0223 template<class T>
0224 CELER_FUNCTION Span<typename T::value_type> make_span(T& cont)
0225 {
0226     return {cont.data(), cont.size()};
0227 }
0228 
0229 //---------------------------------------------------------------------------//
0230 //! Get a const view to a generic container
0231 template<class T>
0232 CELER_FUNCTION Span<typename T::value_type const> make_span(T const& cont)
0233 {
0234     return {cont.data(), cont.size()};
0235 }
0236 
0237 //---------------------------------------------------------------------------//
0238 //! Construct an array from a fixed-size span
0239 template<class T, std::size_t N>
0240 CELER_CONSTEXPR_FUNCTION auto make_array(Span<T, N> const& s)
0241 {
0242     Array<std::remove_cv_t<T>, N> result{};
0243     for (std::size_t i = 0; i < N; ++i)
0244     {
0245         result[i] = s[i];
0246     }
0247     return result;
0248 }
0249 
0250 //---------------------------------------------------------------------------//
0251 }  // namespace celeritas