summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist/plib/parray.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/netlist/plib/parray.h')
-rw-r--r--src/lib/netlist/plib/parray.h185
1 files changed, 121 insertions, 64 deletions
diff --git a/src/lib/netlist/plib/parray.h b/src/lib/netlist/plib/parray.h
index 1be37b908cd..94bb424998c 100644
--- a/src/lib/netlist/plib/parray.h
+++ b/src/lib/netlist/plib/parray.h
@@ -1,126 +1,183 @@
-// license:GPL-2.0+
+// license:BSD-3-Clause
// copyright-holders:Couriersud
-/*
- * parray.h
- *
- */
#ifndef PARRAY_H_
#define PARRAY_H_
+///
+/// \file parray.h
+///
+
#include "palloc.h"
#include "pconfig.h"
#include "pexception.h"
+#include "pfmtlog.h"
#include <array>
#include <memory>
+#include <string>
#include <type_traits>
#include <utility>
#include <vector>
namespace plib {
- template <typename FT, int SIZE>
- struct sizeabs
+ template <typename FT, int SIZE, typename ARENA>
+ struct parray_traits
{
- static constexpr std::size_t ABS() { return (SIZE < 0) ? static_cast<std::size_t>(0 - SIZE) : static_cast<std::size_t>(SIZE); }
+ static constexpr std::size_t ABS() noexcept { return (SIZE < 0) ? narrow_cast<std::size_t>(0 - SIZE) : narrow_cast<std::size_t>(SIZE); }
using container = typename std::array<FT, ABS()> ;
};
- template <typename FT>
- struct sizeabs<FT, 0>
+ template <typename FT, typename ARENA>
+ struct parray_traits<FT, 0, ARENA>
{
- static constexpr const std::size_t ABS = 0;
- using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
+ static constexpr std::size_t ABS() noexcept { return 0; }
+ using allocator_type = typename ARENA::template allocator_type<FT, PALIGN_VECTOROPT>;
+ //using container = typename std::vector<FT, arena_allocator<mempool, FT, 64>>;
+ using container = typename std::vector<FT, allocator_type>;
};
- /**
- * \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>
+ /// \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 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, typename ARENA = aligned_arena<>>
struct parray
{
public:
- static constexpr std::size_t SIZEABS() { return sizeabs<FT, SIZE>::ABS(); }
+ static constexpr std::size_t SIZEABS() noexcept { return parray_traits<FT, SIZE, ARENA>::ABS(); }
- using base_type = typename sizeabs<FT, SIZE>::container;
+ using base_type = typename parray_traits<FT, SIZE, ARENA>::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;
+ using value_type = FT;
+ using reference = FT &;
+ using const_reference = const FT &;
+
+ using pointer = FT *;
+ using const_pointer = const FT *;
template <int X = SIZE >
- parray(size_type size, typename std::enable_if<X==0, int>::type = 0)
+ parray(size_type size, std::enable_if_t<(X==0), int> = 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)
+ parray(size_type size, const FT &val, std::enable_if_t<(X==0), int> = 0)
+ : m_a(size, val), m_size(size)
{
}
-#endif
+
template <int X = SIZE >
- parray(size_type size, typename std::enable_if<X!=0, int>::type = 0)
+ parray(size_type size, std::enable_if_t<(X != 0), int> = 0) noexcept(false)
: 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");
+ if ((SIZE < 0 && size > SIZEABS())
+ || (SIZE > 0 && size != SIZEABS()))
+ throw pexception(pfmt("parray: size error: {1} > {2}")(size, 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(); }
+ template <int X = SIZE >
+ parray(size_type size, const FT &val, std::enable_if_t<(X != 0), int> = 0) noexcept(false)
+ : m_size(size)
+ {
+ if ((SIZE < 0 && size > SIZEABS())
+ || (SIZE > 0 && size != SIZEABS()))
+ throw pexception(pfmt("parray: size error: {1} > {2}")(size, SIZE));
+ m_a.fill(val);
+ }
- bool empty() const noexcept { return size() == 0; }
-#if 0
- reference operator[](size_type i) /*noexcept*/
+ // allow construction in fixed size arrays
+ parray()
+ : m_size(SIZEABS())
{
- 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*/
+
+ parray(const parray &rhs) : m_a(rhs.m_a), m_size(rhs.m_size) {}
+ parray(parray &&rhs) noexcept : m_a(std::move(rhs.m_a)), m_size(std::move(rhs.m_size)) {}
+
+ parray &operator=(const parray &rhs) noexcept // NOLINT(bugprone-unhandled-self-assignment, cert-oop54-cpp)
{
- if (i >= m_size) throw plib::pexception("limits error " + to_string(i) + ">=" + to_string(m_size));
- return m_a[i];
+ if (this == &rhs)
+ return *this;
+
+ m_a = rhs.m_a;
+ m_size = rhs.m_size;
+ return *this;
}
-#else
- C14CONSTEXPR reference operator[](size_type i) noexcept
+
+ parray &operator=(parray &&rhs) noexcept { std::swap(m_a,rhs.m_a); std::swap(m_size, rhs.m_size); return *this; }
+
+ ~parray() noexcept = default;
+
+ constexpr base_type &as_base() noexcept { return m_a; }
+
+ constexpr size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); }
+
+ constexpr size_type max_size() const noexcept { return base_type::max_size(); }
+
+ constexpr bool empty() const noexcept { return size() == 0; }
+
+ constexpr reference operator[](size_type i) noexcept
{
- return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
+ return m_a[i];
}
constexpr const_reference operator[](size_type i) const noexcept
{
- return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i];
+ return m_a[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()); }
+
+ constexpr pointer data() noexcept { return m_a.data(); }
+ constexpr const_pointer data() const noexcept { return m_a.data(); }
private:
PALIGNAS_VECTOROPT()
base_type m_a;
size_type m_size;
};
+
+ template <typename FT, int SIZE1, int SIZE2>
+ struct parray2D : public parray<parray<FT, SIZE2>, SIZE1>
+ {
+ public:
+
+ using size_type = std::size_t;
+ using base_type = parray<parray<FT, SIZE2>, SIZE1>;
+
+ parray2D(size_type size1, size_type size2)
+ : parray<parray<FT, SIZE2>, SIZE1>(size1)
+ {
+ if (SIZE2 <= 0)
+ {
+ for (size_type i=0; i < this->size(); i++)
+ (*this)[i] = parray<FT, SIZE2>(size2);
+ }
+ }
+
+ parray2D(const parray2D &) = default;
+ parray2D &operator=(const parray2D &) = default;
+ parray2D(parray2D &&) noexcept(std::is_nothrow_move_constructible<base_type>::value) = default;
+ parray2D &operator=(parray2D &&) noexcept(std::is_nothrow_move_assignable<base_type>::value) = default;
+
+ ~parray2D() noexcept = default;
+
+ };
+
} // namespace plib
-#endif /* PARRAY_H_ */
+
+
+#endif // PARRAY_H_