// license:GPL-2.0+ // copyright-holders:Couriersud /* * parray.h * */ #ifndef PARRAY_H_ #define PARRAY_H_ #include "palloc.h" #include "pconfig.h" #include "pexception.h" #include "pstrutil.h" #include #include #include #include #include namespace plib { template struct sizeabs { static constexpr std::size_t ABS() { return (SIZE < 0) ? static_cast(0 - SIZE) : static_cast(SIZE); } using container = typename std::array ; }; template struct sizeabs { static constexpr std::size_t ABS() { return 0; } using container = typename std::vector>; }; /** * \brief Array with preallocated or dynamic allocation * * Passing SIZE > 0 has the same functionality as a std::array. * SIZE = 0 is pure dynamic allocation, the actual array size is passed to the * constructor. * SIZE < 0 reserves std::abs(SIZE) elements statically in place allocated. The * actual size is passed in by the constructor. * This array is purely intended for HPC application where depending on the * architecture a preference dynamic/static has to be made. * * This struct is not intended to be a full replacement to std::array. * It is a subset to enable switching between dynamic and static allocation. * I consider > 10% performance difference to be a use case. */ template struct parray { public: static constexpr std::size_t SIZEABS() { return sizeabs::ABS(); } using base_type = typename sizeabs::container; using size_type = typename base_type::size_type; using reference = typename base_type::reference; using const_reference = typename base_type::const_reference; using value_type = typename base_type::value_type; template parray(size_type size, typename std::enable_if<(X==0), int>::type = 0) : m_a(size), m_size(size) { } /* allow construction in fixed size arrays */ parray() : m_size(SIZEABS()) { } template parray(size_type size, typename std::enable_if<(X != 0), int>::type = 0) : m_size(size) { if ((SIZE < 0 && size > SIZEABS()) || (SIZE > 0 && size != SIZEABS())) throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZE)); } inline size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); } constexpr size_type max_size() const noexcept { return base_type::max_size(); } bool empty() const noexcept { return size() == 0; } C14CONSTEXPR reference operator[](size_type i) noexcept { return assume_aligned_ptr(&m_a[0])[i]; } constexpr const_reference operator[](size_type i) const noexcept { return assume_aligned_ptr(&m_a[0])[i]; } FT * data() noexcept { return assume_aligned_ptr(m_a.data()); } const FT * data() const noexcept { return assume_aligned_ptr(m_a.data()); } private: PALIGNAS_VECTOROPT() base_type m_a; PALIGNAS_CACHELINE() size_type m_size; }; template struct parray2D : public parray, SIZE1> { public: using size_type = std::size_t; parray2D(size_type size1, size_type size2) : parray, SIZE1>(size1) { if (SIZE2 <= 0) { for (size_type i=0; i < this->size(); i++) (*this)[i] = parray(size2); } } }; } // namespace plib #endif /* PARRAY_H_ */