Netlist: code maintenance and bug fixes. [Couriersud]

- optimized the core queue dispatching logic. Minor performance
increase.
- fixed a number of bugs in parray. Now parray<double, 0> will be purely
dynamic allocation with the number of elements passed in the
constructor.
- Added noexpr where appropriate.
- Simplified the queue

Checked with gcc-7 (ubuntu), gcc-9, clang-10, macosx clang 10, mingw
cross compile on linux.
This commit is contained in:
couriersud 2019-10-15 23:36:48 +02:00
parent 88f544f02f
commit e5cceda218
18 changed files with 215 additions and 179 deletions

View File

@ -1184,7 +1184,7 @@ ATTR_COLD void netlist_mame_device::device_pre_save()
netlist().run_state_manager().pre_save();
}
void netlist_mame_device::update_icount(netlist::netlist_time time)
void netlist_mame_device::update_icount(netlist::netlist_time time) noexcept
{
const netlist::netlist_time newt(time);
const netlist::netlist_time delta(newt - m_old + m_rem);
@ -1194,7 +1194,7 @@ void netlist_mame_device::update_icount(netlist::netlist_time time)
m_icount -= d;
}
void netlist_mame_device::check_mame_abort_slice()
void netlist_mame_device::check_mame_abort_slice() noexcept
{
if (m_icount <= 0)
netlist().abort_current_queue_slice();

View File

@ -72,11 +72,11 @@ public:
void set_setup_func(func_type &&func) { m_setup_func = std::move(func); }
ATTR_HOT inline netlist::setup_t &setup();
ATTR_HOT inline netlist_mame_t &netlist() { return *m_netlist; }
netlist::setup_t &setup();
netlist_mame_t &netlist() noexcept { return *m_netlist; }
ATTR_HOT void update_icount(netlist::netlist_time time);
ATTR_HOT void check_mame_abort_slice();
void update_icount(netlist::netlist_time time) noexcept;
void check_mame_abort_slice() noexcept;
static void register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name);

View File

@ -26,6 +26,7 @@ TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses,
TIDY_FLAGSX += -modernize-use-trailing-return-type
TIDY_FLAGSX += -bugprone-too-small-loop-variable
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay
TIDY_FLAGSX += -modernize-use-trailing-return-type
space :=
space +=

View File

@ -34,7 +34,7 @@ namespace netlist
NETLIB_UPDATEI();
public:
void update_outputs(const unsigned cnt);
void update_outputs(const unsigned cnt) NL_NOEXCEPT;
logic_input_t m_IP;
object_array_t<logic_output_t, 14> m_Q;

View File

@ -36,7 +36,7 @@ namespace netlist
NETLIB_UPDATEI();
public:
void update_outputs(unsigned v);
void update_outputs(unsigned v) NL_NOEXCEPT;
logic_input_t m_A;
logic_input_t m_B;

View File

@ -34,7 +34,7 @@ namespace netlist
NETLIB_UPDATEI();
NETLIB_RESETI();
void update_outputs();
void update_outputs() NL_NOEXCEPT;
logic_input_t m_A;
logic_input_t m_B;

View File

@ -27,7 +27,7 @@ namespace netlist
NETLIB_UPDATEI();
public:
void shift();
void shift() NL_NOEXCEPT;
logic_input_t m_RC;
logic_input_t m_IN;

View File

@ -107,7 +107,7 @@ const logic_family_desc_t *family_CD4XXX()
// ----------------------------------------------------------------------------------------
detail::queue_t::queue_t(netlist_state_t &nl)
: timed_queue<pqentry_t<net_t *, netlist_time>, false, true>(512)
: timed_queue<pqentry_t<net_t *, netlist_time>, false>(512)
, netlist_ref(nl)
, m_qsize(0)
, m_times(512)
@ -142,7 +142,7 @@ void detail::queue_t::on_post_load(plib::state_manager_t &manager)
for (std::size_t i = 0; i < m_qsize; i++ )
{
detail::net_t *n = state().nets()[m_net_ids[i]].get();
this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
this->push<false>(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
}
}
@ -740,7 +740,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT
{
case core_terminal_t::STATE_INP_HL:
case core_terminal_t::STATE_INP_LH:
process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q);
process<KEEP_STATS>(mask, new_Q);
break;
default:
/* do nothing */
@ -749,20 +749,10 @@ void detail::net_t::update_devs() NL_NOEXCEPT
#else
nl_assert(this->isRailNet());
const unsigned int mask((m_new_Q << core_terminal_t::INP_LH_SHIFT)
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
m_in_queue = queue_status::DELIVERED; /* mark as taken ... */
switch (mask)
{
case core_terminal_t::STATE_INP_HL:
case core_terminal_t::STATE_INP_LH:
process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, m_new_Q);
break;
default:
/* do nothing */
break;
}
if (m_new_Q ^ m_cur_Q)
process<KEEP_STATS>((m_new_Q << core_terminal_t::INP_LH_SHIFT)
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q);
#endif
}
@ -791,7 +781,7 @@ void detail::net_t::reset()
}
}
void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
void detail::net_t::add_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT
{
for (auto &t : m_core_terms)
if (t == &terminal)
@ -802,7 +792,7 @@ void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
m_core_terms.push_back(&terminal);
}
void detail::net_t::remove_terminal(detail::core_terminal_t &terminal)
void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT
{
if (plib::container::contains(m_core_terms, &terminal))
{
@ -1002,7 +992,7 @@ param_t::param_type_t param_t::param_type() const
}
void param_t::update_param()
void param_t::update_param() NL_NOEXCEPT
{
device().update_param();
}

View File

@ -98,7 +98,7 @@ class NETLIB_NAME(name) : public device_t
* device a dynamic device if parameter m_func is set.
*/
#define NETLIB_IS_DYNAMIC(expr) \
public: virtual bool is_dynamic() const override { return expr; }
public: virtual bool is_dynamic() const NL_NOEXCEPT override { return expr; }
/*! Add this to a device definition to mark the device as a time-stepping device.
*
@ -122,26 +122,26 @@ class NETLIB_NAME(name) : public device_t
*
*/
#define NETLIB_IS_TIMESTEP(expr) \
public: virtual bool is_timestep() const override { return expr; }
public: virtual bool is_timestep() const NL_NOEXCEPT override { return expr; }
/*! Used to implement the time stepping code.
*
* Please see NETLIB_IS_TIMESTEP for an example.
*/
#define NETLIB_TIMESTEPI() \
public: virtual void timestep(const nl_double step) override
public: virtual void timestep(const nl_double step) NL_NOEXCEPT override
#define NETLIB_FAMILY(family) , m_famsetter(*this, family)
#define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this)
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() override
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() NL_NOEXCEPT override
#define NETLIB_HANDLERI(name) virtual void name() NL_NOEXCEPT
#define NETLIB_UPDATEI() virtual void update() NL_NOEXCEPT override
#define NETLIB_UPDATE_PARAMI() virtual void update_param() override
#define NETLIB_UPDATE_PARAMI() virtual void update_param() NL_NOEXCEPT override
#define NETLIB_RESETI() virtual void reset() override
#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step)
#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(nl_double step) NL_NOEXCEPT
#define NETLIB_SUB(chip) nld_ ## chip
#define NETLIB_SUBXX(ns, chip) unique_pool_ptr< ns :: nld_ ## chip >
@ -151,10 +151,10 @@ class NETLIB_NAME(name) : public device_t
#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param()
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params
#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() NL_NOEXCEPT
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params NL_NOEXCEPT
#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals()
#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() NL_NOEXCEPT
//============================================================
// Asserts
@ -254,13 +254,13 @@ namespace netlist
virtual unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name,
logic_input_t *proxied) const = 0;
double fixed_V() const { return m_fixed_V; }
double low_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_low_thresh_PCNT; }
double high_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_high_thresh_PCNT; }
double low_offset_V() const { return m_low_VO; }
double high_offset_V() const { return m_high_VO; }
double R_low() const { return m_R_low; }
double R_high() const { return m_R_high; }
double fixed_V() const noexcept{ return m_fixed_V; }
double low_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_low_thresh_PCNT; }
double high_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_high_thresh_PCNT; }
double low_offset_V() const noexcept{ return m_low_VO; }
double high_offset_V() const noexcept{ return m_high_VO; }
double R_low() const noexcept{ return m_R_low; }
double R_high() const noexcept{ return m_R_high; }
double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */
double m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled
@ -285,11 +285,9 @@ namespace netlist
class logic_family_t
{
public:
logic_family_t() : m_logic_family(nullptr) {}
COPYASSIGNMOVE(logic_family_t, delete)
const logic_family_desc_t *logic_family() const { return m_logic_family; }
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
@ -321,7 +319,7 @@ namespace netlist
template <typename O>
//! Constructor.
state_var(O &owner, //!< owner must have a netlist() method.
const pstring &name, //!< identifier/name for this state variable
const pstring &name, //!< identifier/name for this state variable
const T &value //!< Initial value after construction
);
@ -332,7 +330,7 @@ namespace netlist
//! Move Constructor.
constexpr state_var(state_var &&rhs) noexcept = default;
//! Assignment operator to assign value of a state var.
C14CONSTEXPR state_var &operator=(const state_var &rhs) = default;
C14CONSTEXPR state_var &operator=(const state_var &rhs) /*noexcept*/ = default; // OSX doesn't like noexcept
//! Assignment move operator to assign value of a state var.
C14CONSTEXPR state_var &operator=(state_var &&rhs) noexcept = default;
//! Assignment operator to assign value of type T.
@ -355,7 +353,7 @@ namespace netlist
* Please refer to \ref state_var.
*/
template <typename T, std::size_t N>
struct state_array
struct state_array : public std::array<T, N>
{
public:
//! Constructor.
@ -372,12 +370,6 @@ namespace netlist
state_array(state_array &&rhs) noexcept = default;
state_array &operator=(const state_array &rhs) noexcept = default;
state_array &operator=(state_array &&rhs) noexcept = default;
state_array &operator=(const T &rhs) noexcept { m_value = rhs; return *this; }
T & operator[](const std::size_t i) noexcept { return m_value[i]; }
constexpr const T & operator[](const std::size_t i) const noexcept { return m_value[i]; }
private:
std::array<T, N> m_value;
};
// -----------------------------------------------------------------------------
@ -401,22 +393,22 @@ namespace netlist
template <typename C, typename T>
struct property_store_t
{
static void add(const C *obj, const T &aname)
static void add(const C *obj, const T &aname) noexcept
{
store().insert({obj, aname});
}
static const T get(const C *obj)
static const T get(const C *obj) noexcept
{
return store().find(obj)->second;
}
static void remove(const C *obj)
static void remove(const C *obj) noexcept
{
store().erase(store().find(obj));
}
static std::unordered_map<const C *, T> &store()
static std::unordered_map<const C *, T> &store() noexcept
{
static std::unordered_map<const C *, T> lstore;
return lstore;
@ -453,7 +445,7 @@ namespace netlist
*
* \returns name of the object.
*/
pstring name() const
pstring name() const noexcept
{
return props::get(this);
}
@ -549,17 +541,14 @@ namespace netlist
{
public:
using list_t = std::vector<core_terminal_t *>;
static constexpr const unsigned int INP_HL_SHIFT = 0;
static constexpr const unsigned int INP_LH_SHIFT = 1;
static constexpr const unsigned int INP_ACTIVE_SHIFT = 2;
enum state_e {
STATE_INP_PASSIVE = 0,
STATE_INP_HL = (1 << INP_HL_SHIFT),
STATE_INP_LH = (1 << INP_LH_SHIFT),
STATE_INP_ACTIVE = (1 << INP_ACTIVE_SHIFT),
STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH,
STATE_OUT = 128,
STATE_BIDIR = 256
};
@ -669,8 +658,8 @@ namespace netlist
/* setup stuff */
void add_terminal(core_terminal_t &terminal);
void remove_terminal(core_terminal_t &terminal);
void add_terminal(core_terminal_t &terminal) NL_NOEXCEPT;
void remove_terminal(core_terminal_t &terminal) NL_NOEXCEPT;
bool is_logic() const NL_NOEXCEPT;
bool is_analog() const NL_NOEXCEPT;
@ -730,7 +719,7 @@ namespace netlist
* FIXME: get rid of this and implement export/import in MAME
*/
/* only used for logic nets */
netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
netlist_sig_t *Q_state_ptr() noexcept { return m_cur_Q.ptr(); }
private:
state_var<netlist_sig_t> m_new_Q;
@ -989,12 +978,12 @@ namespace netlist
protected:
virtual ~param_t() noexcept = default; /* not intended to be destroyed */
void update_param();
void update_param() NL_NOEXCEPT;
pstring get_initial(const device_t &dev, bool *found);
template<typename C>
void set(C &p, const C v)
void set(C &p, const C v) noexcept
{
if (p != v)
{
@ -1018,7 +1007,7 @@ namespace netlist
T operator()() const NL_NOEXCEPT { return m_param; }
operator T() const NL_NOEXCEPT { return m_param; }
void setTo(const T &param) { set(m_param, param); }
void setTo(const T &param) noexcept { set(m_param, param); }
private:
T m_param;
};
@ -1031,7 +1020,7 @@ namespace netlist
T operator()() const NL_NOEXCEPT { return T(m_param); }
operator T() const NL_NOEXCEPT { return T(m_param); }
void setTo(const T &param) { set(m_param, static_cast<int>(param)); }
void setTo(const T &param) noexcept { set(m_param, static_cast<int>(param)); }
private:
int m_param;
};
@ -1050,7 +1039,7 @@ namespace netlist
public:
param_ptr_t(device_t &device, const pstring &name, std::uint8_t* val);
std::uint8_t * operator()() const NL_NOEXCEPT { return m_param; }
void setTo(std::uint8_t *param) { set(m_param, param); }
void setTo(std::uint8_t *param) noexcept { set(m_param, param); }
private:
std::uint8_t* m_param;
};
@ -1200,10 +1189,10 @@ namespace netlist
}
}
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
bool get_hint_deactivate() { return m_hint_deactivate; }
void set_hint_deactivate(bool v) noexcept { m_hint_deactivate = v; }
bool get_hint_deactivate() const noexcept { return m_hint_deactivate; }
/* Has to be set in device reset */
void set_active_outputs(int n) { m_active_outputs = n; }
void set_active_outputs(int n) noexcept { m_active_outputs = n; }
void set_default_delegate(detail::core_terminal_t &term);
@ -1229,12 +1218,12 @@ namespace netlist
log_type & log();
public:
virtual void timestep(const nl_double st) { plib::unused_var(st); }
virtual void update_terminals() { }
virtual void timestep(const nl_double st) NL_NOEXCEPT { plib::unused_var(st); }
virtual void update_terminals() NL_NOEXCEPT { }
virtual void update_param() {}
virtual bool is_dynamic() const { return false; }
virtual bool is_timestep() const { return false; }
virtual void update_param() NL_NOEXCEPT {}
virtual bool is_dynamic() const NL_NOEXCEPT { return false; }
virtual bool is_timestep() const NL_NOEXCEPT { return false; }
private:
bool m_hint_deactivate;
@ -1303,12 +1292,12 @@ namespace netlist
*/
class detail::queue_t :
//public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
public timed_queue<pqentry_t<net_t *, netlist_time>, false, true>,
public timed_queue<pqentry_t<net_t *, netlist_time>, false>,
public detail::netlist_ref,
public plib::state_manager_t::callback_t
{
public:
using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false, true>;
using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false>;
using entry_t = pqentry_t<net_t *, netlist_time>;
explicit queue_t(netlist_state_t &nl);
virtual ~queue_t() noexcept = default;
@ -1550,25 +1539,31 @@ namespace netlist
netlist_time time() const NL_NOEXCEPT { return m_time; }
void process_queue(netlist_time delta) NL_NOEXCEPT;
void abort_current_queue_slice() NL_NOEXCEPT { m_queue.retime(detail::queue_t::entry_t(m_time, nullptr)); }
void abort_current_queue_slice() NL_NOEXCEPT
{
if (!USE_QUEUE_STATS || !m_use_stats)
m_queue.retime<false>(detail::queue_t::entry_t(m_time, nullptr));
else
m_queue.retime<true>(detail::queue_t::entry_t(m_time, nullptr));
}
const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
void qpush(detail::queue_t::entry_t && e) noexcept
{
if (!USE_QUEUE_STATS || !m_use_stats)
m_queue.push_nostats(std::move(e)); // NOLINT(performance-move-const-arg)
m_queue.push<false>(std::move(e)); // NOLINT(performance-move-const-arg)
else
m_queue.push(std::move(e)); // NOLINT(performance-move-const-arg)
m_queue.push<true>(std::move(e)); // NOLINT(performance-move-const-arg)
}
template <class R>
void qremove(const R &elem) noexcept
{
if (!USE_QUEUE_STATS || !m_use_stats)
m_queue.remove_nostats(elem);
m_queue.remove<false>(elem);
else
m_queue.remove(elem);
m_queue.remove<true>(elem);
}
/* Control functions */
@ -1905,9 +1900,9 @@ namespace netlist
template <typename O>
state_array<T,N>::state_array(O &owner, const pstring &name, const T & value)
{
owner.state().save(owner, m_value, owner.name(), name);
owner.state().save(owner, *static_cast<std::array<T, N> *>(this), owner.name(), name);
for (std::size_t i=0; i<N; i++)
m_value[i] = value;
(*this)[i] = value;
}
} // namespace netlist

View File

@ -50,7 +50,7 @@
* This approach is stricter and should identify bugs in
* the netlist core faster.
* By default it is disabled since it is not as fast as
* the default approach. It is up to 5% slower.
* the default approach. It is up to 10% slower.
*
*/
#ifndef USE_COPY_INSTEAD_OF_REFERENCE

View File

@ -125,9 +125,6 @@ namespace netlist
// nld_solver.cpp
//PERRMSGV(MF_UNKNOWN_SOLVER_TYPE, 1, "Unknown solver type: {1}")
PERRMSGV(MF_NETGROUP_SIZE_EXCEEDED_1, 1, "Encountered netgroup with > {1} nets")
PERRMSGV(MI_NO_SPECIFIC_SOLVER, 1, "No specific solver found for netlist of size {1}")
// nld_mm5837.cpp

View File

@ -69,37 +69,34 @@ namespace netlist
std::swap(m_object, other.m_object);
}
#endif
struct QueueOp
inline bool operator ==(const pqentry_t &rhs) const noexcept
{
inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time < rhs.m_exec_time);
}
return m_object == rhs.m_object;
}
inline static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return (lhs.m_exec_time <= rhs.m_exec_time);
}
inline bool operator ==(const Element &rhs) const noexcept
{
return m_object == rhs;
}
inline static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
{
return lhs.m_object == rhs.m_object;
}
inline bool operator <=(const pqentry_t &rhs) const noexcept
{
return (m_exec_time <= rhs.m_exec_time);
}
inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
{
return lhs.m_object == rhs;
}
inline bool operator <(const pqentry_t &rhs) const noexcept
{
return (m_exec_time < rhs.m_exec_time);
}
inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
};
inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
Time m_exec_time;
Element m_object;
};
/* Use TS = true for a threadsafe queue */
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
template <class T, bool TS>
class timed_queue_linear : plib::nocopyassignmove
{
public:
@ -113,28 +110,31 @@ namespace netlist
std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
bool empty() const noexcept { return (m_end == &m_list[1]); }
template<bool KEEPSTAT>
void push(T && e) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
T * i(m_end-1);
for (; QueueOp::less(*(i), e); --i)
for (; *i < e; --i)
{
*(i+1) = *(i);
m_prof_sortmove.inc();
if (KEEPSTAT)
m_prof_sortmove.inc();
}
*(i+1) = std::move(e);
++m_end;
m_prof_call.inc();
if (KEEPSTAT)
m_prof_call.inc();
}
void push_nostats(T && e) noexcept
void push_nostatsx(T && e) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
#if 1
T * i(m_end-1);
for (; QueueOp::less(*(i), e); --i)
for (; *i < e; --i)
{
*(i+1) = *(i);
}
@ -153,22 +153,18 @@ namespace netlist
T pop() noexcept { return *(--m_end); }
const T &top() const noexcept { return *(m_end-1); }
template <class R>
template <bool KEEPSTAT, class R>
void remove(const R &elem) noexcept
{
m_prof_remove.inc();
remove_nostats(elem);
}
template <class R>
void remove_nostats(const R &elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
if (KEEPSTAT)
m_prof_remove.inc();
#if 1
for (T * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem))
// == operator ignores time!
if (*i == elem)
{
std::copy(i+1, m_end--, i);
return;
@ -186,23 +182,25 @@ namespace netlist
#endif
}
void retime(T && elem) noexcept
template <bool KEEPSTAT, class R>
void retime(R && elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
m_prof_retime.inc();
if (KEEPSTAT)
m_prof_retime.inc();
for (T * i = m_end - 1; i > &m_list[0]; --i)
for (R * i = m_end - 1; i > &m_list[0]; --i)
{
if (QueueOp::equal(*i, elem)) // partial equal!
if (*i == elem) // partial equal!
{
*i = std::move(elem);
while (QueueOp::less(*(i-1), *i))
while (*(i-1) < *i)
{
std::swap(*(i-1), *i);
--i;
}
while (i < m_end && QueueOp::less(*i, *(i+1)))
while (i < m_end && *i < *(i+1))
{
std::swap(*(i+1), *i);
++i;
@ -220,7 +218,7 @@ namespace netlist
* the insert algo above will run into this element and doesn't
* need a comparison with queue start.
*/
m_list[0] = QueueOp::never();
m_list[0] = T::never();
m_end++;
}
@ -241,20 +239,20 @@ namespace netlist
public:
// profiling
nperfcount_t<KEEPSTAT> m_prof_sortmove;
nperfcount_t<KEEPSTAT> m_prof_call;
nperfcount_t<KEEPSTAT> m_prof_remove;
nperfcount_t<KEEPSTAT> m_prof_retime;
nperfcount_t<true> m_prof_sortmove;
nperfcount_t<true> m_prof_call;
nperfcount_t<true> m_prof_remove;
nperfcount_t<true> m_prof_retime;
};
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
template <class T, bool TS>
class timed_queue_heap : plib::nocopyassignmove
{
public:
struct compare
{
constexpr bool operator()(const T &a, const T &b) const { return QueueOp::lessequal(b,a); }
constexpr bool operator()(const T &a, const T &b) const { return b <= a; }
};
explicit timed_queue_heap(const std::size_t list_size)
@ -266,13 +264,15 @@ namespace netlist
std::size_t capacity() const noexcept { return m_list.capacity(); }
bool empty() const noexcept { return &m_list[0] == m_end; }
template <bool KEEPSTAT>
void push(T &&e) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
*m_end++ = e;
std::push_heap(&m_list[0], m_end, compare());
m_prof_call.inc();
if (KEEPSTAT)
m_prof_call.inc();
}
T pop() noexcept
@ -285,14 +285,16 @@ namespace netlist
const T &top() const noexcept { return m_list[0]; }
template <class R>
template <bool KEEPSTAT, class R>
void remove(const R &elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
if (KEEPSTAT)
m_prof_remove.inc();
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem))
if (*i == elem)
{
m_end--;
for (;i < m_end; i++)
@ -303,13 +305,16 @@ namespace netlist
}
}
template <bool KEEPSTAT>
void retime(const T &elem) noexcept
{
/* Lock */
lock_guard_type lck(m_lock);
if (KEEPSTAT)
m_prof_retime.inc();
for (T * i = m_end - 1; i >= &m_list[0]; i--)
{
if (QueueOp::equal(*i, elem)) // partial equal!
if (*i == elem) // partial equal!
{
*i = elem;
std::make_heap(&m_list[0], m_end, compare());
@ -340,18 +345,23 @@ namespace netlist
public:
// profiling
nperfcount_t<KEEPSTAT> m_prof_sortmove;
nperfcount_t<KEEPSTAT> m_prof_call;
nperfcount_t<true> m_prof_sortmove;
nperfcount_t<true> m_prof_call;
nperfcount_t<true> m_prof_remove;
nperfcount_t<true> m_prof_retime;
};
template <class T, bool TS>
using timed_queue = timed_queue_linear<T, TS>;
/*
* Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
*
* This slows down processing by about 25% on a Kaby Lake.
*/
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
using timed_queue = timed_queue_linear<T, TS, KEEPSTAT, QueueOp>;
//template <class T, bool TS>
//using timed_queue = timed_queue_heap<T, TS>;
} // namespace netlist

View File

@ -223,6 +223,8 @@ namespace plib
gmres_t(std::size_t size)
: residual(size)
, Ax(size)
, m_ht(RESTART +1, RESTART)
, m_v(RESTART + 1, size)
, m_size(size)
, m_use_more_precise_stop_condition(false)
{
@ -416,12 +418,12 @@ namespace plib
plib::parray<float_type, RESTART + 1> m_c; /* mr + 1 */
plib::parray<float_type, RESTART + 1> m_g; /* mr + 1 */
plib::parray<plib::parray<float_type, RESTART>, RESTART + 1> m_ht; /* (mr + 1), mr */
plib::parray2D<float_type, RESTART + 1, RESTART> m_ht; /* (mr + 1), mr */
plib::parray<float_type, RESTART + 1> m_s; /* mr + 1 */
plib::parray<float_type, RESTART + 1> m_y; /* mr + 1 */
//plib::parray<float_type, SIZE> m_v[RESTART + 1]; /* mr + 1, n */
plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
//plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
plib::parray2D<float_type, RESTART + 1, SIZE> m_v; /* mr + 1, n */
std::size_t m_size;

View File

@ -36,7 +36,7 @@ namespace plib
using index_type = C;
using value_type = T;
static constexpr const int NSQ = (N > 0 ? -N * N : N * N);
static constexpr const int NSQ = (N < 0 ? -N * N : N * N);
static constexpr const int Np1 = (N == 0) ? 0 : (N < 0 ? N - 1 : N + 1);
COPYASSIGNMOVE(pmatrix_cr_t, default)
@ -64,7 +64,9 @@ namespace plib
, m_size(n)
{
for (index_type i=0; i<n+1; i++)
{
row_idx[i] = 0;
}
}
~pmatrix_cr_t() = default;
@ -495,19 +497,18 @@ namespace plib
{
index_type p(0);
/* build ilu_rows */
for (index_type i=1; i < fill.size(); i++)
for (decltype(fill.size()) i=1; i < fill.size(); i++)
{
bool found(false);
for (index_type k = 0; k < i; k++)
for (decltype(fill.size()) k = 0; k < i; k++)
{
// if (fill[i][k] < base::FILL_INFINITY)
if (fill[i][k] <= ilup)
{
// assume A[k][k]!=0
for (index_type j=k+1; j < fill.size(); j++)
for (decltype(fill.size()) j=k+1; j < fill.size(); j++)
{
auto f = std::min(fill[i][j], 1 + fill[i][k] + fill[k][j]);
//if (f < base::FILL_INFINITY)
if (f <= ilup)
{
#if 0
@ -522,7 +523,7 @@ namespace plib
}
}
if (found)
ilu_rows[p++] = i;
ilu_rows[p++] = static_cast<index_type>(i);
}
ilu_rows[p] = 0; // end of array
this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2)

View File

@ -30,8 +30,9 @@ namespace plib {
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>>;
static constexpr std::size_t ABS() { return 0; }
//using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
using container = typename std::vector<FT>;
};
/**
@ -63,27 +64,35 @@ namespace plib {
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)
parray(size_type size, typename std::enable_if<(X==0), int>::type = 0)
: m_a(size), m_size(size)
{
}
#if 1
#if 0
struct tag {};
/* allow construction in fixed size arrays */
template <int X = SIZE >
parray(typename std::enable_if<(X > 0), int>::type = 0)
parray(tag A = tag(), typename std::enable_if<(X >= 0), int>::type = 0)
: m_size(X)
{
}
#else
/* allow construction in fixed size arrays */
parray()
: m_size(SIZEABS())
{
}
#endif
#endif
template <int X = SIZE >
parray(size_type size, typename std::enable_if<X!=0, int>::type = 0)
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");
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(); }
@ -122,6 +131,27 @@ namespace plib {
PALIGNAS_CACHELINE()
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;
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);
}
}
};
} // namespace plib
#endif /* PARRAY_H_ */

View File

@ -209,7 +209,7 @@ public:
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
iter_t& operator=(const iter_t &rhs) noexcept { iter_t t(rhs); std::swap(*this, t); return *this; }
iter_t& operator=(const iter_t &rhs) noexcept { p = rhs.p; return *this; }
iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
iter_t& operator++() noexcept {p = p->next();return *this;}
// NOLINTNEXTLINE(cert-dcl21-cpp)
@ -219,8 +219,8 @@ public:
constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;}
constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;}
/* constexpr */ LC& operator*() noexcept {return *p;}
/* constexpr */ LC* operator->() noexcept {return p;}
constexpr LC& operator*() noexcept {return *p;}
constexpr LC* operator->() noexcept {return p;}
constexpr LC& operator*() const noexcept {return *p;}
constexpr LC* operator->() const noexcept {return p;}
@ -269,8 +269,19 @@ public:
}
LC *front() const noexcept { return m_head; }
void clear() noexcept { m_head = nullptr; }
constexpr bool empty() const noexcept { return (m_head == nullptr); }
void clear() noexcept
{
LC *p(m_head);
while (p != nullptr)
{
LC *n(p->m_next);
p->m_next = nullptr;
p->m_prev = nullptr;
p = n;
}
m_head = nullptr;
}
private:
LC *m_head;

View File

@ -176,13 +176,13 @@ namespace plib {
*reinterpret_cast<function_ptr *>(&m_func) = t;
}
template<typename O>
inline R call(O *obj, Targs... args)
inline R call(O *obj, Targs... args) const noexcept(true)
{
using function_ptr = R (O::*)(Targs...);
function_ptr t = *reinterpret_cast<function_ptr *>(&m_func);
return (obj->*t)(std::forward<Targs>(args)...);
}
bool is_set() {
bool is_set() const {
#if defined(_MSC_VER) || (defined (__INTEL_COMPILER) && defined (_M_X64))
int *p = reinterpret_cast<int *>(&m_func);
int *e = p + sizeof(generic_function) / sizeof(int);
@ -225,12 +225,12 @@ namespace plib {
#endif
}
template<typename O>
R call(O *obj, Targs... args) const
R call(O *obj, Targs... args) const noexcept(true)
{
using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
}
bool is_set() noexcept { return m_func != nullptr; }
bool is_set() const noexcept { return m_func != nullptr; }
generic_function get_function() const noexcept { return m_func; }
private:
generic_function m_func;
@ -244,7 +244,7 @@ namespace plib {
class generic_class;
template <class C>
using MemberFunctionType = R (C::*)(Targs...);
using MemberFunctionType = R (C::*)(Targs...); // noexcept(true) --> c++-17
pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
@ -263,7 +263,7 @@ namespace plib {
m_obj = reinterpret_cast<generic_class *>(object);
}
inline R operator()(Targs ... args)
inline R operator()(Targs ... args) const noexcept(true)
{
return this->call(m_obj, std::forward<Targs>(args)...);
}

View File

@ -319,8 +319,7 @@ namespace devices
}
else
{
log().fatal(MF_NETGROUP_SIZE_EXCEEDED_1(128));
return; /* tease compilers */
ms = create_solver<double, 0>(net_count, sname);
}
break;
}