Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:46:52

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_HISTOGRAM_DETAIL_CHUNK_VECTOR_HPP
0008 #define BOOST_HISTOGRAM_DETAIL_CHUNK_VECTOR_HPP
0009 
0010 #include <boost/core/span.hpp>
0011 #include <boost/throw_exception.hpp>
0012 #include <stdexcept>
0013 #include <vector>
0014 
0015 namespace boost {
0016 namespace histogram {
0017 namespace detail {
0018 
0019 // Warning: this is not a proper container and is only used to
0020 // test the feasibility of using accumulators::collector with a
0021 // custom container type. If time permits, this will be expanded
0022 // into a proper container type.
0023 template <class ValueType>
0024 class chunk_vector {
0025 public:
0026   using base = std::vector<ValueType>;
0027   using allocator_type = typename base::allocator_type;
0028   using pointer = typename base::pointer;
0029   using const_pointer = typename base::const_pointer;
0030   using size_type = typename base::size_type;
0031   using const_reference = boost::span<const ValueType>;
0032   using reference = boost::span<ValueType>;
0033   // this is wrong and should make a copy; it is not a problem for
0034   // the current use-case, but a general purpose implementation cannot
0035   // violate concepts like this
0036   using value_type = const_reference;
0037 
0038   template <class Pointer>
0039   struct iterator_t {
0040     iterator_t& operator++() {
0041       ptr_ += chunk_;
0042       return *this;
0043     }
0044 
0045     iterator_t operator++(int) {
0046       iterator_t copy(*this);
0047       ptr_ += chunk_;
0048       return copy;
0049     }
0050 
0051     value_type operator*() const { return value_type(ptr_, ptr_ + chunk_); }
0052 
0053     Pointer ptr_;
0054     size_type chunk_;
0055   };
0056 
0057   using iterator = iterator_t<pointer>;
0058   using const_iterator = iterator_t<const_pointer>;
0059 
0060   // this creates an empty chunk_vector
0061   explicit chunk_vector(size_type chunk, const allocator_type& alloc = {})
0062       : chunk_(chunk), vec_(alloc) {}
0063 
0064   chunk_vector(std::initializer_list<value_type> list, size_type chunk,
0065                const allocator_type& alloc = {})
0066       : chunk_(chunk), vec_(list, alloc) {}
0067 
0068   allocator_type get_allocator() noexcept(noexcept(allocator_type())) {
0069     return vec_.get_allocator();
0070   }
0071 
0072   void push_back(const_reference x) {
0073     if (x.size() != chunk_)
0074       BOOST_THROW_EXCEPTION(std::runtime_error("argument has wrong size"));
0075     // we don't use std::vector::insert here to have amortized constant complexity
0076     for (auto&& elem : x) vec_.push_back(elem);
0077   }
0078 
0079   auto insert(const_iterator pos, const_iterator o_begin, const_iterator o_end) {
0080     if (std::distance(o_begin, o_end) % chunk_ == 0)
0081       BOOST_THROW_EXCEPTION(std::runtime_error("argument has wrong size"));
0082     return vec_.insert(pos, o_begin, o_end);
0083   }
0084 
0085   const_iterator begin() const noexcept { return {vec_.data(), chunk_}; }
0086   const_iterator end() const noexcept { return {vec_.data() + vec_.size(), chunk_}; }
0087 
0088   value_type operator[](size_type idx) const noexcept {
0089     return {vec_.data() + idx * chunk_, vec_.data() + (idx + 1) * chunk_};
0090   }
0091 
0092   size_type size() const noexcept { return vec_.size() / chunk_; }
0093 
0094 private:
0095   size_type chunk_;
0096   base vec_;
0097 };
0098 
0099 } // namespace detail
0100 } // namespace histogram
0101 } // namespace boost
0102 
0103 #endif