Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/corecel/cont/Array.hh was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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/cont/Array.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <cstddef>
0010 #include <type_traits>
0011 #include <utility>
0012 
0013 #include "corecel/Macros.hh"
0014 #include "corecel/Types.hh"
0015 
0016 namespace celeritas
0017 {
0018 //---------------------------------------------------------------------------//
0019 /*!
0020  * Fixed-size simple array for storage.
0021  *
0022  * The Array class is primarily used for point coordinates (e.g., \c Real3) but
0023  * is also used for other fixed-size data structures.
0024  *
0025  * This isn't fully standards-compliant with std::array: there's no support for
0026  * N=0 for example. Additionally it uses the native celeritas \c size_type,
0027  * even though this has \em no effect on generated code for values of N inside
0028  * the range of \c size_type. Arrays are also zero-initialized by default.
0029  *
0030  * \note For supplementary functionality, include:
0031  * - \c corecel/math/ArrayUtils.hh for real-number vector/matrix applications
0032  * - \c corecel/math/ArrayOperators.hh for mathematical operators
0033  * - \c ArrayIO.hh for streaming and string conversion
0034  * - \c ArrayIO.json.hh for JSON input and output
0035  */
0036 template<class T, ::celeritas::size_type N>
0037 class Array
0038 {
0039     static_assert(N > 0);
0040 
0041   public:
0042     //!@{
0043     //! \name Type aliases
0044     using value_type = T;
0045     using size_type = ::celeritas::size_type;
0046     using pointer = value_type*;
0047     using const_pointer = value_type const*;
0048     using reference = value_type&;
0049     using const_reference = value_type const&;
0050     using iterator = pointer;
0051     using const_iterator = const_pointer;
0052 
0053     using CArrayConstRef = T const (&)[N];
0054     //!@}
0055 
0056   public:
0057     //! Default construction initializes to zero
0058     CELER_CEF Array() : d_{T{}} {}
0059 
0060     //! Construct from an array for aggregate initialization of daughters
0061     CELER_CEF Array(CArrayConstRef values)
0062     {
0063         for (size_type i = 0; i < N; ++i)
0064         {
0065             d_[i] = values[i];
0066         }
0067     }
0068 
0069     //! Construct with C-style aggregate initialization
0070     CELER_CEF Array(T first) : d_{first} {}
0071 
0072     //! Construct with the array's data
0073     template<class... Us>
0074     CELER_CEF Array(T first, Us... rest) : d_{first, static_cast<T>(rest)...}
0075     {
0076         // Protect against leaving off an entry, e.g. Array<int, 2>(1)
0077         static_assert(sizeof...(rest) + 1 == N,
0078                       "All array entries must be explicitly specified");
0079     }
0080 
0081     //// ACCESSORS ////
0082 
0083     //!@{
0084     //! \name Element access
0085     CELER_CEF const_reference operator[](size_type i) const { return d_[i]; }
0086     CELER_CEF reference operator[](size_type i) { return d_[i]; }
0087     CELER_CEF const_reference front() const { return d_[0]; }
0088     CELER_CEF reference front() { return d_[0]; }
0089     CELER_CEF const_reference back() const { return d_[N - 1]; }
0090     CELER_CEF reference back() { return d_[N - 1]; }
0091     CELER_CEF const_pointer data() const { return d_; }
0092     CELER_CEF pointer data() { return d_; }
0093     //!@}
0094 
0095     //!@{
0096     //! Access for structured unpacking
0097     template<std::size_t I>
0098     CELER_CEF T& get()
0099     {
0100         static_assert(I < static_cast<std::size_t>(N));
0101         return d_[I];
0102     }
0103     template<std::size_t I>
0104     CELER_CEF T const& get() const
0105     {
0106         static_assert(I < static_cast<std::size_t>(N));
0107         return d_[I];
0108     }
0109     //!@}
0110 
0111     //!@{
0112     //! \name Iterators
0113     CELER_CEF iterator begin() { return d_; }
0114     CELER_CEF iterator end() { return d_ + N; }
0115     CELER_CEF const_iterator begin() const { return d_; }
0116     CELER_CEF const_iterator end() const { return d_ + N; }
0117     CELER_CEF const_iterator cbegin() const { return d_; }
0118     CELER_CEF const_iterator cend() const { return d_ + N; }
0119     //!@}
0120 
0121     //!@{
0122     //! \name Capacity
0123     CELER_CEF bool empty() const { return N == 0; }
0124     static CELER_CEF size_type size() { return N; }
0125     //!@}
0126 
0127     //!@{
0128     //! \name  Operations
0129 
0130     //! Fill the array with a constant value
0131     CELER_CEF void fill(const_reference value)
0132     {
0133         for (size_type i = 0; i != N; ++i)
0134         {
0135             d_[i] = value;
0136         }
0137     }
0138     //!@}
0139 
0140   private:
0141     T d_[N];  //!< Storage
0142 };
0143 
0144 //---------------------------------------------------------------------------//
0145 // DEDUCTION GUIDES
0146 //---------------------------------------------------------------------------//
0147 
0148 // Note: this differs from std::array, which deduces from T rather than the
0149 // common type
0150 template<class T, class... Us>
0151 CELER_FUNCTION Array(T, Us...)
0152     -> Array<std::common_type_t<T, Us...>, 1 + sizeof...(Us)>;
0153 
0154 //---------------------------------------------------------------------------//
0155 // INLINE DEFINITIONS
0156 //---------------------------------------------------------------------------//
0157 /*!
0158  * Test equality of two arrays.
0159  */
0160 template<class T, size_type N>
0161 CELER_CEF bool operator==(Array<T, N> const& lhs, Array<T, N> const& rhs)
0162 {
0163     for (size_type i = 0; i != N; ++i)
0164     {
0165         if (lhs[i] != rhs[i])
0166             return false;
0167     }
0168     return true;
0169 }
0170 
0171 //---------------------------------------------------------------------------//
0172 /*!
0173  * Test inequality of two arrays.
0174  */
0175 template<class T, size_type N>
0176 CELER_CEF bool operator!=(Array<T, N> const& lhs, Array<T, N> const& rhs)
0177 {
0178     return !(lhs == rhs);
0179 }
0180 
0181 //---------------------------------------------------------------------------//
0182 }  // namespace celeritas
0183 
0184 //---------------------------------------------------------------------------//
0185 //! \cond
0186 namespace std
0187 {
0188 //---------------------------------------------------------------------------//
0189 //! Support structured binding: array size
0190 template<class T, celeritas::size_type N>
0191 struct tuple_size<celeritas::Array<T, N>>
0192 {
0193     static constexpr std::size_t value = N;
0194 };
0195 
0196 //! Support structured binding: array element type
0197 template<std::size_t I, class T, celeritas::size_type N>
0198 struct tuple_element<I, celeritas::Array<T, N>>
0199 {
0200     static_assert(I < std::tuple_size<celeritas::Array<T, N>>::value);
0201     using type = T;
0202 };
0203 
0204 //---------------------------------------------------------------------------//
0205 }  // namespace std
0206 //! \endcond