Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2021-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/data/CollectionBuilder.hh
0007 //---------------------------------------------------------------------------//
0008 #pragma once
0009 
0010 #include <initializer_list>
0011 #include <limits>
0012 
0013 #include "corecel/Config.hh"
0014 
0015 #include "Collection.hh"
0016 
0017 #include "detail/FillInvalid.hh"
0018 
0019 namespace celeritas
0020 {
0021 //---------------------------------------------------------------------------//
0022 /*!
0023  * Helper class for constructing Collection objects.
0024  *
0025  * This is intended for use with host data but can also be used to resize
0026  * device collections. It's constructed with a reference to the host
0027  * collection, and it provides vector-like methods for extending it. The size
0028  * *cannot* be decreased because that would invalidate previously created \c
0029  * ItemRange items.
0030  *
0031  * \code
0032     auto cb = make_builder(&myintcol.host);
0033     cb.reserve(100);
0034     ItemRange<int> insertion
0035         = cb.insert_back(local_ints.begin(), local_ints.end());
0036     cb.push_back(123);
0037    \endcode
0038 
0039  * The CollectionBuilder can also be used to resize device-value collections
0040  * without having to allocate a host version and copy to device. (This is
0041  * useful for state allocations.) When resizing values with debugging
0042  * assertions enabled on host memory, it will assign garbage values to aid in
0043  * reproducible debugging.)
0044  */
0045 template<class T, MemSpace M = MemSpace::host, class I = ItemId<T>>
0046 class CollectionBuilder
0047 {
0048   public:
0049     //!@{
0050     //! \name Type aliases
0051     using CollectionT = Collection<T, Ownership::value, M, I>;
0052     using value_type = T;
0053     using size_type = typename CollectionT::size_type;
0054     using ItemIdT = typename CollectionT::ItemIdT;
0055     using ItemRangeT = typename CollectionT::ItemRangeT;
0056     //!@}
0057 
0058   public:
0059     //! Construct from a collection
0060     explicit CollectionBuilder(CollectionT* collection) : col_(*collection)
0061     {
0062         CELER_EXPECT(collection);
0063     }
0064 
0065     // Increase size to this capacity
0066     inline void resize(std::size_t count);
0067 
0068     // Reserve space
0069     inline void reserve(std::size_t count);
0070 
0071     // Extend with a series of elements, returning the range inserted
0072     template<class InputIterator>
0073     inline ItemRangeT insert_back(InputIterator first, InputIterator last);
0074 
0075     // Extend with a series of elements from an initializer list
0076     inline ItemRangeT insert_back(std::initializer_list<value_type> init);
0077 
0078     // Append a single element
0079     inline ItemIdT push_back(value_type const& element);
0080 
0081     //! Number of elements in the collection
0082     size_type size() const { return col_.size(); }
0083 
0084     //! Get the size as an ID type
0085     ItemIdT size_id() const { return ItemIdT{size()}; }
0086 
0087   private:
0088     //!@{
0089     //! Access storage
0090     using StorageT = typename CollectionT::StorageT;
0091     StorageT& storage() { return col_.storage(); }
0092     StorageT const& storage() const { return col_.storage(); }
0093     //!@}
0094 
0095     //! Maximum elements in a Collection
0096     static constexpr std::size_t max_size()
0097     {
0098         return std::numeric_limits<size_type>::max();
0099     }
0100 
0101     CollectionT& col_;
0102 };
0103 
0104 //---------------------------------------------------------------------------//
0105 // DEDUCTION GUIDES
0106 //---------------------------------------------------------------------------//
0107 
0108 template<class T, MemSpace M, class I>
0109 CollectionBuilder(Collection<T, Ownership::value, M, I>*)
0110     -> CollectionBuilder<T, M, I>;
0111 
0112 //---------------------------------------------------------------------------//
0113 // INLINE DEFINITIONS
0114 //---------------------------------------------------------------------------//
0115 /*!
0116  * Reserve space for the given number of elements.
0117  */
0118 template<class T, MemSpace M, class I>
0119 void CollectionBuilder<T, M, I>::reserve(std::size_t count)
0120 {
0121     CELER_EXPECT(count <= max_size());
0122     static_assert(M == MemSpace::host,
0123                   "Reserve currently works only for host memory");
0124     this->storage().reserve(count);
0125 }
0126 
0127 //---------------------------------------------------------------------------//
0128 /*!
0129  * Insert the given elements at the end of the allocation.
0130  */
0131 template<class T, MemSpace M, class I>
0132 template<class InputIterator>
0133 auto CollectionBuilder<T, M, I>::insert_back(InputIterator first,
0134                                              InputIterator last) -> ItemRangeT
0135 {
0136     CELER_EXPECT(std::distance(first, last) + this->storage().size()
0137                  <= this->max_size());
0138     static_assert(M == MemSpace::host,
0139                   "Insertion currently works only for host memory");
0140     auto start = this->size_id();
0141     this->storage().insert(this->storage().end(), first, last);
0142     return {start, this->size_id()};
0143 }
0144 
0145 //---------------------------------------------------------------------------//
0146 /*!
0147  * Insert the given list of elements at the end of the allocation.
0148  */
0149 template<class T, MemSpace M, class I>
0150 auto CollectionBuilder<T, M, I>::insert_back(std::initializer_list<T> init)
0151     -> ItemRangeT
0152 {
0153     return this->insert_back(init.begin(), init.end());
0154 }
0155 
0156 //---------------------------------------------------------------------------//
0157 /*!
0158  * Add a new element to the end of the allocation.
0159  */
0160 template<class T, MemSpace M, class I>
0161 auto CollectionBuilder<T, M, I>::push_back(T const& el) -> ItemIdT
0162 {
0163     CELER_EXPECT(this->storage().size() + 1 <= this->max_size());
0164     static_assert(M == MemSpace::host,
0165                   "Insertion currently works only for host memory");
0166     auto result = this->size_id();
0167     this->storage().push_back(el);
0168     return result;
0169 }
0170 
0171 //---------------------------------------------------------------------------//
0172 /*!
0173  * Increase the size to the given number of elements.
0174  */
0175 template<class T, MemSpace M, class I>
0176 void CollectionBuilder<T, M, I>::resize(std::size_t count)
0177 {
0178     CELER_EXPECT(this->storage().empty());
0179     CELER_EXPECT(count <= max_size());
0180     this->storage() = StorageT(count);
0181     if constexpr (CELERITAS_DEBUG && M == MemSpace::host)
0182     {
0183         // Fill with invalid values to help with debugging on host
0184         detail::fill_invalid(&col_);
0185     }
0186 }
0187 
0188 //---------------------------------------------------------------------------//
0189 /*!
0190  * Helper function for constructing collection builders.
0191  *
0192  * (Will not be needed under C++17's template argument deduction).
0193  */
0194 template<class T, MemSpace M, class I>
0195 CollectionBuilder<T, M, I>
0196 make_builder(Collection<T, Ownership::value, M, I>* collection)
0197 {
0198     CELER_EXPECT(collection);
0199     return CollectionBuilder<T, M, I>(collection);
0200 }
0201 
0202 //---------------------------------------------------------------------------//
0203 /*!
0204  * Helper function for resizing a single collection.
0205  *
0206  * This is useful for analogy to the resize method defined for states.
0207  */
0208 template<class T, MemSpace M, class I>
0209 void resize(Collection<T, Ownership::value, M, I>* collection, std::size_t size)
0210 {
0211     CELER_EXPECT(collection);
0212     CollectionBuilder<T, M, I>(collection).resize(size);
0213 }
0214 
0215 //---------------------------------------------------------------------------//
0216 }  // namespace celeritas