diff options
author | 2019-03-26 11:13:37 +1100 | |
---|---|---|
committer | 2019-03-26 11:13:37 +1100 | |
commit | 97b67170277437131adf6ed4d60139c172529e4f (patch) | |
tree | 7a5cbf608f191075f1612b1af15832c206a3fe2d /src/lib/netlist/plib/parray.h | |
parent | b380514764cf857469bae61c11143a19f79a74c5 (diff) |
(nw) Clean up the mess on master
This effectively reverts b380514764cf857469bae61c11143a19f79a74c5 and
c24473ddff715ecec2e258a6eb38960cf8c8e98e, restoring the state at
598cd5227223c3b04ca31f0dbc1981256d9ea3ff.
Before pushing, please check that what you're about to push is sane.
Check your local commit log and ensure there isn't anything out-of-place
before pushing to mainline. When things like this happen, it wastes
everyone's time. I really don't need this in a week when real work⢠is
busting my balls and I'm behind where I want to be with preparing for
MAME release.
Diffstat (limited to 'src/lib/netlist/plib/parray.h')
-rw-r--r-- | src/lib/netlist/plib/parray.h | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h new file mode 100644 index 00000000000..1be37b908cd --- /dev/null +++ b/src/lib/netlist/plib/parray.h @@ -0,0 +1,126 @@ +// 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 <array> +#include <memory> +#include <type_traits> +#include <utility> +#include <vector> + +namespace plib { + + template <typename FT, int SIZE> + struct sizeabs + { + static constexpr std::size_t ABS() { return (SIZE < 0) ? static_cast<std::size_t>(0 - SIZE) : static_cast<std::size_t>(SIZE); } + using container = typename std::array<FT, ABS()> ; + }; + + template <typename FT> + struct sizeabs<FT, 0> + { + static constexpr const std::size_t ABS = 0; + using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>; + }; + + /** + * \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 <typename FT, int SIZE> + struct parray + { + public: + static constexpr std::size_t SIZEABS() { return sizeabs<FT, SIZE>::ABS(); } + + using base_type = typename sizeabs<FT, SIZE>::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 <int X = SIZE > + parray(size_type size, typename std::enable_if<X==0, int>::type = 0) + : m_a(size), m_size(size) + { + } + +#if 1 + /* allow construction in fixed size arrays */ + template <int X = SIZE > + parray(typename std::enable_if<(X > 0), int>::type = 0) + : m_size(X) + { + } +#endif + template <int X = SIZE > + parray(size_type size, typename std::enable_if<X!=0, int>::type = 0) + : m_size(size) + { + if (SIZE < 0 && size > SIZEABS()) + throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZEABS())); + else if (SIZE > 0 && size != SIZEABS()) + throw plib::pexception("parray: size error"); + } + + 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; } + +#if 0 + reference operator[](size_type i) /*noexcept*/ + { + if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size)); + return m_a[i]; + } + const_reference operator[](size_type i) const /*noexcept*/ + { + if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size)); + return m_a[i]; + } +#else + C14CONSTEXPR reference operator[](size_type i) noexcept + { + return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; + } + constexpr const_reference operator[](size_type i) const noexcept + { + return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; + } +#endif + FT * data() noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } + const FT * data() const noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } + + private: + PALIGNAS_VECTOROPT() + base_type m_a; + size_type m_size; + }; +} // namespace plib + +#endif /* PARRAY_H_ */ |