This commit is contained in:
Roberto Fresca 2020-06-13 15:58:27 +02:00
commit 284f196df1
68 changed files with 16761 additions and 11255 deletions

View File

@ -53,6 +53,7 @@ project "netlist"
MAME_DIR .. "src/lib/netlist/plib/pconfig.h", MAME_DIR .. "src/lib/netlist/plib/pconfig.h",
MAME_DIR .. "src/lib/netlist/plib/palloc.h", MAME_DIR .. "src/lib/netlist/plib/palloc.h",
MAME_DIR .. "src/lib/netlist/plib/pchrono.h", MAME_DIR .. "src/lib/netlist/plib/pchrono.h",
MAME_DIR .. "src/lib/netlist/plib/pgsl.h",
MAME_DIR .. "src/lib/netlist/plib/penum.h", MAME_DIR .. "src/lib/netlist/plib/penum.h",
MAME_DIR .. "src/lib/netlist/plib/pexception.cpp", MAME_DIR .. "src/lib/netlist/plib/pexception.cpp",
MAME_DIR .. "src/lib/netlist/plib/pexception.h", MAME_DIR .. "src/lib/netlist/plib/pexception.h",

View File

@ -127,7 +127,7 @@ protected:
netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override
{ {
//return plib::make_unique<plib::dynlib_static>(nullptr); //return plib::make_unique<plib::dynlib_static>(nullptr);
return netlist::host_arena::make_unique<plib::dynlib_static>(nl_static_solver_syms); return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nl_static_solver_syms);
} }
private: private:
@ -169,7 +169,7 @@ protected:
netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const noexcept override
{ {
return netlist::host_arena::make_unique<plib::dynlib_static>(nullptr); return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nullptr);
} }
private: private:
@ -181,7 +181,7 @@ class netlist_mame_device::netlist_mame_t : public netlist::netlist_state_t
public: public:
netlist_mame_t(netlist_mame_device &parent, const pstring &name) netlist_mame_t(netlist_mame_device &parent, const pstring &name)
: netlist::netlist_state_t(name, netlist::host_arena::make_unique<netlist_mame_device::netlist_mame_callbacks_t>(parent)) : netlist::netlist_state_t(name, plib::make_unique<netlist_mame_device::netlist_mame_callbacks_t, netlist::host_arena>(parent))
, m_parent(parent) , m_parent(parent)
{ {
} }
@ -978,7 +978,8 @@ netlist::host_arena::unique_ptr<netlist::netlist_state_t> netlist_mame_device::b
{ {
try try
{ {
auto lnetlist = netlist::host_arena::make_unique<netlist::netlist_state_t>("netlist", netlist::host_arena::make_unique<netlist_validate_callbacks_t>()); auto lnetlist = plib::make_unique<netlist::netlist_state_t, netlist::host_arena>("netlist",
plib::make_unique<netlist_validate_callbacks_t, netlist::host_arena>());
// enable validation mode // enable validation mode
lnetlist->set_extended_validation(true); lnetlist->set_extended_validation(true);
common_dev_start(lnetlist.get()); common_dev_start(lnetlist.get());

View File

@ -415,8 +415,8 @@ namespace analog
else else
{ {
// linear // linear
const auto Sqr1(static_cast<nl_fptype>(plib::pow(Vdsat - Vds, 2))); const auto Sqr1(plib::narrow_cast<nl_fptype>(plib::pow(Vdsat - Vds, 2)));
const auto Sqr2(static_cast<nl_fptype>(plib::pow(nlconst::two() * Vdsat - Vds, 2))); const auto Sqr2(plib::narrow_cast<nl_fptype>(plib::pow(nlconst::two() * Vdsat - Vds, 2)));
Cgb = 0; Cgb = 0;
Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) * nlconst::two_thirds(); Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) * nlconst::two_thirds();
Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) * nlconst::two_thirds(); Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) * nlconst::two_thirds();

View File

@ -115,7 +115,7 @@ namespace netlist
, m_VL(*this, "VL") , m_VL(*this, "VL")
, m_VREF(*this, "VREF") , m_VREF(*this, "VREF")
{ {
m_type = static_cast<int>(m_modacc.m_TYPE); m_type = plib::narrow_cast<int>(m_modacc.m_TYPE);
if (m_type < 1 || m_type > 3) if (m_type < 1 || m_type > 3)
{ {
log().fatal(MF_OPAMP_UNKNOWN_TYPE(m_type)); log().fatal(MF_OPAMP_UNKNOWN_TYPE(m_type));

View File

@ -561,11 +561,11 @@ namespace analog
{ {
register_subalias("P", P()); register_subalias("P", P());
register_subalias("N", N()); register_subalias("N", N());
if (m_func() != "") if (!m_func().empty())
m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}}));
} }
NETLIB_IS_TIMESTEP(m_func() != "") NETLIB_IS_TIMESTEP(!m_func().empty())
NETLIB_TIMESTEPI() NETLIB_TIMESTEPI()
{ {
@ -609,11 +609,11 @@ namespace analog
{ {
register_subalias("P", P()); register_subalias("P", P());
register_subalias("N", N()); register_subalias("N", N());
if (m_func() != "") if (!m_func().empty())
m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}}));
} }
NETLIB_IS_TIMESTEP(m_func() != "") NETLIB_IS_TIMESTEP(!m_func().empty())
NETLIB_TIMESTEPI() NETLIB_TIMESTEPI()
{ {
m_t += step; m_t += step;

View File

@ -25,11 +25,13 @@ VSBUILD = $(SRC)/buildVS
DOC = $(SRC)/documentation DOC = $(SRC)/documentation
TIDY_FLAGSX = -checks=*,-google*,-hicpp*,readability*,-fuchsia*,cert-*,-android-*, TIDY_FLAGSX = -checks=*,-google*,-hicpp*,readability*,-fuchsia*,cert-*,-android-*,
TIDY_FLAGSX += -llvm-header-guard,-cppcoreguidelines-pro-type-reinterpret-cast, TIDY_FLAGSX += -llvm-header-guard,
# TIDY_FLAGSX += -cppcoreguidelines-pro-type-reinterpret-cast,
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-pointer-arithmetic, TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-pointer-arithmetic,
#TIDY_FLAGSX += -cppcoreguidelines-owning-memory, #TIDY_FLAGSX += -cppcoreguidelines-owning-memory,
TIDY_FLAGSX += -modernize-use-default-member-init,-cppcoreguidelines-pro-bounds-constant-array-index, TIDY_FLAGSX += -modernize-use-default-member-init,-cppcoreguidelines-pro-bounds-constant-array-index,
TIDY_FLAGSX += -modernize-pass-by-value,-cppcoreguidelines-pro-type-static-cast-downcast, TIDY_FLAGSX += -modernize-pass-by-value,
#TIDY_FLAGSX += -cppcoreguidelines-pro-type-static-cast-downcast,
TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers, TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers,
TIDY_FLAGSX += -cppcoreguidelines-macro-usage, TIDY_FLAGSX += -cppcoreguidelines-macro-usage,
TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes, TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,
@ -37,7 +39,7 @@ TIDY_FLAGSX += -bugprone-macro-parentheses,
#TIDY_FLAGSX += -misc-macro-parentheses, #TIDY_FLAGSX += -misc-macro-parentheses,
TIDY_FLAGSX += -bugprone-too-small-loop-variable, TIDY_FLAGSX += -bugprone-too-small-loop-variable,
TIDY_FLAGSX += -modernize-use-trailing-return-type, TIDY_FLAGSX += -modernize-use-trailing-return-type,
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay, #TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
TIDY_FLAGSX += -readability-magic-numbers,-readability-braces-around-statements, TIDY_FLAGSX += -readability-magic-numbers,-readability-braces-around-statements,
TIDY_FLAGSX += -readability-implicit-bool-conversion, TIDY_FLAGSX += -readability-implicit-bool-conversion,
TIDY_FLAGSX += -readability-named-parameter,-readability-function-size, TIDY_FLAGSX += -readability-named-parameter,-readability-function-size,
@ -85,7 +87,7 @@ CC = g++
LD = @g++ LD = @g++
MD = @mkdir MD = @mkdir
RM = @rm RM = @rm
CLANG_TIDY = clang-tidy-10 CLANG_TIDY = clang-tidy-11
DEPENDCC=$(CC) DEPENDCC=$(CC)
@ -132,6 +134,8 @@ POBJS := \
PMAIN := $(POBJ)/pmain.o PMAIN := $(POBJ)/pmain.o
NLOBJS := \ NLOBJS := \
$(NLOBJ)/solver/nld_solver.o \
$(NLOBJ)/solver/nld_matrix_solver.o \
$(NLOBJ)/nl_base.o \ $(NLOBJ)/nl_base.o \
$(NLOBJ)/nl_parser.o \ $(NLOBJ)/nl_parser.o \
$(NLOBJ)/nl_setup.o \ $(NLOBJ)/nl_setup.o \
@ -142,8 +146,6 @@ NLOBJS := \
$(NLOBJ)/analog/nld_switches.o \ $(NLOBJ)/analog/nld_switches.o \
$(NLOBJ)/analog/nlid_twoterm.o \ $(NLOBJ)/analog/nlid_twoterm.o \
$(NLOBJ)/analog/nld_opamps.o \ $(NLOBJ)/analog/nld_opamps.o \
$(NLOBJ)/solver/nld_solver.o \
$(NLOBJ)/solver/nld_matrix_solver.o \
$(NLOBJ)/tools/nl_convert.o \ $(NLOBJ)/tools/nl_convert.o \
$(NLOBJ)/generated/static_solvers.o \ $(NLOBJ)/generated/static_solvers.o \
$(NLOBJ)/devices/nld_2102A.o \ $(NLOBJ)/devices/nld_2102A.o \
@ -287,27 +289,32 @@ native:
$(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra " $(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
gcc9: gcc9:
$(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -fext-numeric-literals -Wall -pedantic -Wpedantic -Wsign-compare -Wextra" EXTRALIBS="-lquadmath" $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -Wall -pedantic -Wpedantic -fext-numeric-literals -Wsign-compare -Wextra" EXTRALIBS="-lquadmath"
clang: clang:
#$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" #$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors"
$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native \ $(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native \
-mllvm -inline-threshold=2000 \ -mllvm -inline-threshold=2000 \
-Wunknown-warning-option \
-Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \ -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \
-Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \ -Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \
-Wno-missing-variable-declarations -Wno-float-equal -Wconversion \ -Wmissing-variable-declarations -Wno-float-equal -Wconversion \
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \ -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \
-Wno-exit-time-destructors -Winconsistent-missing-destructor-override" -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \
-Wno-return-std-move-in-c++11 -Wno-unreachable-code"
clang-libc: clang-libc:
#clang-11 currently broken
#$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors" #$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field -Wno-padded -Wno-unused-template -Wno-missing-variable-declarations -Wno-float-equal -Wconversion -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral -Wno-exit-time-destructors"
$(MAKE) CC=clang++-11 LD=clang++-11 OBJ=obj/clang-libc CEXTRAFLAGS="-march=native \ $(MAKE) CC=clang++-10 LD=clang++-10 OBJ=obj/clang-libc CEXTRAFLAGS="-march=native \
-stdlib=libc++ -mllvm -inline-threshold=2000 \ -stdlib=libc++ -mllvm -inline-threshold=2000 \
-Wunknown-warning-option \
-Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \ -Weverything -Wall -pedantic -Wpedantic -Wunused-private-field \
-Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \ -Werror -Wno-padded -Wno-weak-vtables -Wno-weak-template-vtables -Wno-unused-template \
-Wno-missing-variable-declarations -Wno-float-equal -Wconversion \ -Wmissing-variable-declarations -Wno-float-equal -Wconversion \
-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \ -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-format-nonliteral \
-Wno-exit-time-destructors -Winconsistent-missing-destructor-override" \ -Wno-exit-time-destructors -Winconsistent-missing-destructor-override \
-Wno-return-std-move-in-c++11 -Wno-unreachable-code"
LDEXTRAFLAGS=-stdlib=libc++ LDEXTRAFLAGS=-stdlib=libc++
clang-5: clang-5:

View File

@ -9,6 +9,8 @@
#include "nl_errstr.h" #include "nl_errstr.h"
#include "solver/nld_solver.h" #include "solver/nld_solver.h"
#include <array>
namespace netlist namespace netlist
{ {
namespace devices namespace devices
@ -18,6 +20,8 @@ namespace netlist
// nld_base_proxy // nld_base_proxy
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static const std::array<std::pair<const char *, const char *>, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}};
nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name, nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name,
const logic_t *inout_proxied) const logic_t *inout_proxied)
: device_t(anetlist, name, inout_proxied->logic_family()) : device_t(anetlist, name, inout_proxied->logic_family())
@ -29,16 +33,15 @@ namespace netlist
throw nl_exception(MF_NULLPTR_FAMILY_NP("nld_base_proxy")); throw nl_exception(MF_NULLPTR_FAMILY_NP("nld_base_proxy"));
} }
const std::vector<std::pair<pstring, pstring>> power_syms = { {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}};
bool f = false; bool f = false;
for (const auto & pwr_sym : power_syms) for (const auto & pwr_sym : power_syms)
{ {
pstring devname = inout_proxied->device().name(); pstring devname = inout_proxied->device().name();
auto *tp_ct(anetlist.setup().find_terminal(devname + "." + pwr_sym.first, auto *tp_ct(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.first),
/*detail::terminal_type::INPUT,*/ false)); /*detail::terminal_type::INPUT,*/ false));
auto *tp_cn(anetlist.setup().find_terminal(devname + "." + pwr_sym.second, auto *tp_cn(anetlist.setup().find_terminal(devname + "." + pstring(pwr_sym.second),
/*detail::terminal_type::INPUT,*/ false)); /*detail::terminal_type::INPUT,*/ false));
if ((tp_ct != nullptr) && (tp_cn != nullptr)) if ((tp_ct != nullptr) && (tp_cn != nullptr))
{ {
@ -47,8 +50,8 @@ namespace netlist
if (!tp_cn->is_analog()) if (!tp_cn->is_analog())
throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_cn->name())); throw nl_exception(plib::pfmt("Not an analog terminal: {1}")(tp_cn->name()));
auto *tp_t = static_cast<analog_t* >(tp_ct); auto *tp_t = dynamic_cast<analog_t* >(tp_ct);
auto *tn_t = static_cast<analog_t *>(tp_cn); auto *tn_t = dynamic_cast<analog_t *>(tp_cn);
if (f && (tp_t != nullptr && tn_t != nullptr)) if (f && (tp_t != nullptr && tn_t != nullptr))
log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(), log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(inout_proxied->device().name(),
m_tp->name(), m_tn->name(), m_tp->name(), m_tn->name(),

View File

@ -93,7 +93,7 @@ namespace devices
, m_compiled(*this, "m_compiled") , m_compiled(*this, "m_compiled")
, m_funcparam({nlconst::zero()}) , m_funcparam({nlconst::zero()})
{ {
if (m_func() != "") if (!m_func().empty())
m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}})); m_compiled->compile(m_func(), std::vector<pstring>({{pstring("T")}}));
connect(m_feedback, m_Q); connect(m_feedback, m_Q);
} }

View File

@ -440,7 +440,7 @@ namespace devices
if (!m_ttbl) if (!m_ttbl)
{ {
m_ttbl = pool.make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(); m_ttbl = plib::make_unique<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t>(pool);
truthtable_parser desc_s(m_NO, m_NI, truthtable_parser desc_s(m_NO, m_NI,
packed_int(m_ttbl->m_out_state.data(), sizeof(m_ttbl->m_out_state[0]) * 8), packed_int(m_ttbl->m_out_state.data(), sizeof(m_ttbl->m_out_state[0]) * 8),
m_ttbl->m_timing_index.data(), m_ttbl->m_timing_nt.data()); m_ttbl->m_timing_index.data(), m_ttbl->m_timing_nt.data());
@ -448,7 +448,7 @@ namespace devices
desc_s.parse(m_desc); desc_s.parse(m_desc);
} }
return pool.make_unique<tt_type>(anetlist, name, m_family_name, *m_ttbl, m_desc); return plib::make_unique<tt_type>(pool, anetlist, name, m_family_name, *m_ttbl, m_desc);
} }
private: private:
device_arena::unique_ptr<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t> m_ttbl; device_arena::unique_ptr<typename nld_truthtable_t<m_NI, m_NO>::truthtable_t> m_ttbl;
@ -578,7 +578,7 @@ void truthtable_parser::parse(const std::vector<pstring> &truthtable)
for (int j=0; j < 16; j++) for (int j=0; j < 16; j++)
m_timing_nt[j] = netlist_time::zero(); m_timing_nt[j] = netlist_time::zero();
while (!(ttline == "")) while (!ttline.empty())
{ {
std::vector<pstring> io(plib::psplit(ttline,"|")); std::vector<pstring> io(plib::psplit(ttline,"|"));
// checks // checks
@ -670,7 +670,7 @@ namespace factory
#define ENTRYY(n, m, s) case (n * 100 + m): \ #define ENTRYY(n, m, s) case (n * 100 + m): \
{ using xtype = devices::netlist_factory_truthtable_t<n, m>; \ { using xtype = devices::netlist_factory_truthtable_t<n, m>; \
auto cs=s; \ auto cs=s; \
ret = host_arena::make_unique<xtype>(desc.name, std::move(cs)); } \ ret = plib::make_unique<xtype, host_arena>(desc.name, std::move(cs)); } \
break break
#define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \ #define ENTRY(n, s) ENTRYY(n, 1, s); ENTRYY(n, 2, s); ENTRYY(n, 3, s); \
@ -700,7 +700,7 @@ namespace factory
nl_assert_always(false, msg.c_str()); nl_assert_always(false, msg.c_str());
} }
ret->m_desc = desc.desc; ret->m_desc = desc.desc;
ret->m_family_name = (desc.family != "" ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY())); ret->m_family_name = (!desc.family.empty() ? desc.family : pstring(config::DEFAULT_LOGIC_FAMILY()));
return ret; return ret;
} }

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ namespace netlist
host_arena::unique_ptr<plib::dynlib_base> callbacks_t:: static_solver_lib() const host_arena::unique_ptr<plib::dynlib_base> callbacks_t:: static_solver_lib() const
{ {
return host_arena::make_unique<plib::dynlib_static>(nullptr); return plib::make_unique<plib::dynlib_static, host_arena>(nullptr);
} }
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
@ -129,9 +129,9 @@ namespace netlist
m_lib = m_callbacks->static_solver_lib(); m_lib = m_callbacks->static_solver_lib();
m_setup = host_arena::make_unique<setup_t>(*this); m_setup = plib::make_unique<setup_t, host_arena>(*this);
// create the run interface // create the run interface
m_netlist = m_pool.make_unique<netlist_t>(*this, name); m_netlist = plib::make_unique<netlist_t>(m_pool, *this, name);
// Make sure save states are invalidated when a new version is deployed // Make sure save states are invalidated when a new version is deployed
@ -313,7 +313,7 @@ namespace netlist
case 0: case 0:
{ {
std::vector<core_device_t *> d; std::vector<core_device_t *> d;
std::vector<nldelegate *> t; std::vector<const nldelegate *> t;
log().verbose("Using default startup strategy"); log().verbose("Using default startup strategy");
for (auto &n : m_nets) for (auto &n : m_nets)
for (auto & term : n->core_terms()) for (auto & term : n->core_terms())
@ -402,7 +402,7 @@ namespace netlist
} }
log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count, log().verbose("Total calls : {1:12} {2:12} {3:12}", total_count,
total_time, total_time / static_cast<decltype(total_time)>((total_count > 0) ? total_count : 1)); total_time, total_time / gsl::narrow<decltype(total_time)>((total_count > 0) ? total_count : 1));
log().verbose("Total loop {1:15}", si.m_stat_mainloop()); log().verbose("Total loop {1:15}", si.m_stat_mainloop());
log().verbose("Total time {1:15}", total_time); log().verbose("Total time {1:15}", total_time);
@ -424,8 +424,8 @@ namespace netlist
} }
plib::pperftime_t<true>::type total_overhead = overhead() plib::pperftime_t<true>::type total_overhead = overhead()
* static_cast<plib::pperftime_t<true>::type>(total_count) * gsl::narrow<plib::pperftime_t<true>::type>(total_count)
/ static_cast<plib::pperftime_t<true>::type>(200000); / gsl::narrow<plib::pperftime_t<true>::type>(200000);
log().verbose("Queue Pushes {1:15}", si.m_queue.m_prof_call()); log().verbose("Queue Pushes {1:15}", si.m_queue.m_prof_call());
log().verbose("Queue Moves {1:15}", si.m_queue.m_prof_sortmove()); log().verbose("Queue Moves {1:15}", si.m_queue.m_prof_sortmove());
@ -436,7 +436,7 @@ namespace netlist
log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation."); log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
log().verbose("Total overhead {1:15}", total_overhead); log().verbose("Total overhead {1:15}", total_overhead);
plib::pperftime_t<true>::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead)) plib::pperftime_t<true>::type overhead_per_pop = (si.m_stat_mainloop()-2*total_overhead - (total_time - total_overhead))
/ static_cast<plib::pperftime_t<true>::type>(si.m_queue.m_prof_call()); / gsl::narrow<plib::pperftime_t<true>::type>(si.m_queue.m_prof_call());
log().verbose("Overhead per pop {1:11}", overhead_per_pop ); log().verbose("Overhead per pop {1:11}", overhead_per_pop );
log().verbose(""); log().verbose("");
} }
@ -450,7 +450,7 @@ namespace netlist
if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count() if (stats->m_stat_inc_active() > 3 * stats->m_stat_total_time.count()
&& stats->m_stat_inc_active() > trigger) && stats->m_stat_inc_active() > trigger)
log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(), log().verbose("HINT({}, NO_DEACTIVATE) // {} {} {}", ep->name(),
static_cast<nl_fptype>(stats->m_stat_inc_active()) / static_cast<nl_fptype>(stats->m_stat_total_time.count()), gsl::narrow<nl_fptype>(stats->m_stat_inc_active()) / gsl::narrow<nl_fptype>(stats->m_stat_total_time.count()),
stats->m_stat_inc_active(), stats->m_stat_total_time.count()); stats->m_stat_inc_active(), stats->m_stat_total_time.count());
} }
log().verbose(""); log().verbose("");
@ -831,10 +831,8 @@ namespace netlist
device.state().setup().register_param_t(*this); device.state().setup().register_param_t(*this);
} }
param_t::~param_t() noexcept // placed here to avoid weak vtable warnings
{ param_t::~param_t() noexcept = default;
// placed here to avoid weak vtable warnings
}
param_t::param_type_t param_t::param_type() const noexcept(false) param_t::param_type_t param_t::param_type() const noexcept(false)
{ {
@ -858,14 +856,14 @@ namespace netlist
pstring param_t::get_initial(const core_device_t *dev, bool *found) const pstring param_t::get_initial(const core_device_t *dev, bool *found) const
{ {
pstring res = dev->state().setup().get_initial_param_val(this->name(), ""); pstring res = dev->state().setup().get_initial_param_val(this->name(), "");
*found = (res != ""); *found = (!res.empty());
return res; return res;
} }
param_str_t::param_str_t(core_device_t &device, const pstring &name, const pstring &val) param_str_t::param_str_t(core_device_t &device, const pstring &name, const pstring &val)
: param_t(device, name) : param_t(device, name)
{ {
m_param = host_arena::make_unique<pstring>(val); m_param = plib::make_unique<pstring, host_arena>(val);
*m_param = device.state().setup().get_initial_param_val(this->name(),val); *m_param = device.state().setup().get_initial_param_val(this->name(),val);
} }
@ -873,7 +871,7 @@ namespace netlist
: param_t(name) : param_t(name)
{ {
// deviceless parameter, no registration, owner is responsible // deviceless parameter, no registration, owner is responsible
m_param = host_arena::make_unique<pstring>(val); m_param = plib::make_unique<pstring, host_arena>(val);
*m_param = state.setup().get_initial_param_val(this->name(),val); *m_param = state.setup().get_initial_param_val(this->name(),val);
} }

View File

@ -708,9 +708,8 @@ namespace netlist
#endif #endif
void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; } void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; }
nldelegate &delegate() noexcept { return m_delegate; }
const nldelegate &delegate() const noexcept { return m_delegate; } const nldelegate &delegate() const noexcept { return m_delegate; }
inline void run_delegate() noexcept { m_delegate(); } inline void run_delegate() noexcept { return m_delegate(); }
private: private:
nldelegate m_delegate; nldelegate m_delegate;
net_t * m_net; net_t * m_net;
@ -997,7 +996,7 @@ namespace netlist
{ {
public: public:
using list_t = std::vector<analog_net_t *>; using list_t = plib::aligned_vector<analog_net_t *>;
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr); analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *railterminal = nullptr);
@ -1209,7 +1208,7 @@ namespace netlist
pstring valstr() const override pstring valstr() const override
{ {
return plib::pfmt("{}").e(static_cast<nl_fptype>(m_param)); return plib::pfmt("{}").e(gsl::narrow<nl_fptype>(m_param));
} }
private: private:
@ -1309,7 +1308,7 @@ namespace netlist
public: public:
template <typename P, typename Y=T, typename DUMMY = std::enable_if_t<plib::is_arithmetic<Y>::value>> template <typename P, typename Y=T, typename DUMMY = std::enable_if_t<plib::is_arithmetic<Y>::value>>
value_base_t(P &param, const pstring &name) value_base_t(P &param, const pstring &name)
: m_value(static_cast<T>(param.value(name))) : m_value(gsl::narrow<T>(param.value(name)))
{ {
} }
template <typename P, typename Y=T, std::enable_if_t<!plib::is_arithmetic<Y>::value, int> = 0> template <typename P, typename Y=T, std::enable_if_t<!plib::is_arithmetic<Y>::value, int> = 0>
@ -1513,7 +1512,8 @@ namespace netlist
~device_t() noexcept override = default; ~device_t() noexcept override = default;
nldelegate default_delegate() { return nldelegate(&device_t::update, this); } //nldelegate default_delegate() { return nldelegate(&device_t::update, this); }
nldelegate default_delegate() { return { &device_t::update, this }; }
protected: protected:
NETLIB_UPDATEI() { } NETLIB_UPDATEI() { }
@ -1757,7 +1757,7 @@ namespace netlist
template<typename T, typename... Args> template<typename T, typename... Args>
device_arena::unique_ptr<T> make_pool_object(Args&&... args) device_arena::unique_ptr<T> make_pool_object(Args&&... args)
{ {
return m_pool.make_unique<T>(std::forward<Args>(args)...); return plib::make_unique<T>(m_pool, std::forward<Args>(args)...);
} }
// memory pool - still needed in some places // memory pool - still needed in some places
device_arena &pool() noexcept { return m_pool; } device_arena &pool() noexcept { return m_pool; }
@ -2302,6 +2302,7 @@ namespace netlist
inline void detail::net_t::remove_from_active_list(core_terminal_t &term) noexcept inline void detail::net_t::remove_from_active_list(core_terminal_t &term) noexcept
{ {
gsl_Expects(!m_list_active.empty());
m_list_active.remove(&term); m_list_active.remove(&term);
if (m_list_active.empty()) if (m_list_active.empty())
railterminal().device().do_dec_active(); railterminal().device().do_dec_active();
@ -2309,24 +2310,24 @@ namespace netlist
inline const analog_net_t & analog_t::net() const noexcept inline const analog_net_t & analog_t::net() const noexcept
{ {
return static_cast<const analog_net_t &>(core_terminal_t::net()); return plib::downcast<const analog_net_t &>(core_terminal_t::net());
} }
inline analog_net_t & analog_t::net() noexcept inline analog_net_t & analog_t::net() noexcept
{ {
return static_cast<analog_net_t &>(core_terminal_t::net()); return plib::downcast<analog_net_t &>(core_terminal_t::net());
} }
inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); } inline nl_fptype terminal_t::operator ()() const noexcept { return net().Q_Analog(); }
inline logic_net_t & logic_t::net() noexcept inline logic_net_t & logic_t::net() noexcept
{ {
return static_cast<logic_net_t &>(core_terminal_t::net()); return plib::downcast<logic_net_t &>(core_terminal_t::net());
} }
inline const logic_net_t & logic_t::net() const noexcept inline const logic_net_t & logic_t::net() const noexcept
{ {
return static_cast<const logic_net_t &>(core_terminal_t::net()); return plib::downcast<const logic_net_t &>(core_terminal_t::net());
} }
inline netlist_sig_t logic_input_t::operator()() const noexcept inline netlist_sig_t logic_input_t::operator()() const noexcept
@ -2516,7 +2517,7 @@ namespace netlist
if (plib::is_integral<T>::value) if (plib::is_integral<T>::value)
if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6)) if (plib::abs(valx - plib::trunc(valx)) > nlconst::magic(1e-6))
throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p)); throw nl_exception(MF_INVALID_NUMBER_CONVERSION_1_2(device.name() + "." + name, p));
m_param = static_cast<T>(valx); m_param = plib::narrow_cast<T>(valx);
} }
device.state().save(*this, m_param, this->name(), "m_param"); device.state().save(*this, m_param, this->name(), "m_param");
@ -2599,7 +2600,7 @@ namespace netlist
state_container<C>::state_container(O &owner, const pstring &name, state_container<C>::state_container(O &owner, const pstring &name,
const state_container<C>::value_type & value) const state_container<C>::value_type & value)
{ {
owner.state().save(owner, *static_cast<C *>(this), owner.name(), name); owner.state().save(owner, static_cast<C &>(*this), owner.name(), name);
for (std::size_t i=0; i < this->size(); i++) for (std::size_t i=0; i < this->size(); i++)
(*this)[i] = value; (*this)[i] = value;
} }
@ -2610,7 +2611,7 @@ namespace netlist
std::size_t n, const state_container<C>::value_type & value) std::size_t n, const state_container<C>::value_type & value)
: C(n, value) : C(n, value)
{ {
owner.state().save(owner, *static_cast<C *>(this), owner.name(), name); owner.state().save(owner, static_cast<C &>(*this), owner.name(), name);
} }
extern template struct state_var<std::uint8_t>; extern template struct state_var<std::uint8_t>;

View File

@ -200,6 +200,12 @@ namespace netlist
/// ///
using MAX_QUEUE_SIZE = std::integral_constant<std::size_t, 512>; // NOLINT using MAX_QUEUE_SIZE = std::integral_constant<std::size_t, 512>; // NOLINT
using use_float_matrix = std::integral_constant<bool, NL_USE_FLOAT_MATRIX>;
using use_long_double_matrix = std::integral_constant<bool, NL_USE_LONG_DOUBLE_MATRIX>;
using use_float128_matrix = std::integral_constant<bool, NL_USE_FLOAT128>;
using use_mempool = std::integral_constant<bool, NL_USE_MEMPOOL>;
/// \brief Floating point types used /// \brief Floating point types used
/// ///
/// nl_fptype is the floating point type used throughout the /// nl_fptype is the floating point type used throughout the

View File

@ -76,7 +76,7 @@ namespace factory {
device_arena::unique_ptr<core_device_t> library_element_t::make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name) device_arena::unique_ptr<core_device_t> library_element_t::make_device(device_arena &pool, netlist_state_t &anetlist, const pstring &name)
{ {
return pool.make_unique<NETLIB_NAME(wrapper)>(anetlist, name); return plib::make_unique<NETLIB_NAME(wrapper)>(pool, anetlist, name);
} }

View File

@ -129,7 +129,7 @@ namespace factory {
netlist_state_t &anetlist, netlist_state_t &anetlist,
const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>) const pstring &name, std::tuple<Args...>& args, std::index_sequence<Is...>)
{ {
return pool.make_unique<C>(anetlist, name, std::forward<Args>(std::get<Is>(args))...); return plib::make_unique<C>(pool, anetlist, name, std::forward<Args>(std::get<Is>(args))...);
} }
dev_uptr make_device(device_arena &pool, dev_uptr make_device(device_arena &pool,
@ -149,7 +149,7 @@ namespace factory {
static uptr create(const pstring &name, properties &&props, Args&&... args) static uptr create(const pstring &name, properties &&props, Args&&... args)
{ {
return host_arena::make_unique<device_element_t<C, Args...>>(name, return plib::make_unique<device_element_t<C, Args...>, host_arena>(name,
std::move(props), std::forward<Args>(args)...); std::move(props), std::forward<Args>(args)...);
} }
private: private:
@ -194,7 +194,7 @@ namespace factory {
template <typename T> template <typename T>
element_t::uptr constructor_t(const pstring &name, properties &&props) element_t::uptr constructor_t(const pstring &name, properties &&props)
{ {
return host_arena::make_unique<device_element_t<T>>(name, std::move(props)); return plib::make_unique<device_element_t<T>, host_arena>(name, std::move(props));
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -83,7 +83,7 @@ bool parser_t::parse(const pstring &nlname)
require_token(m_tok_paren_left); require_token(m_tok_paren_left);
token_t name = get_token(); token_t name = get_token();
require_token(m_tok_paren_right); require_token(m_tok_paren_right);
if (name.str() == nlname || nlname == "") if (name.str() == nlname || nlname.empty())
{ {
parse_netlist(name.str()); parse_netlist(name.str());
return true; return true;
@ -164,8 +164,8 @@ void parser_t::net_truthtable_start(const pstring &nlname)
netlist::tt_desc desc; netlist::tt_desc desc;
desc.name = name; desc.name = name;
desc.ni = static_cast<unsigned long>(ni); desc.ni = gsl::narrow<unsigned long>(ni);
desc.no = static_cast<unsigned long>(no); desc.no = gsl::narrow<unsigned long>(no);
desc.family = ""; desc.family = "";
while (true) while (true)

View File

@ -200,7 +200,7 @@ namespace netlist
|| plib::abs(value) > nlconst::magic(1e9)) || plib::abs(value) > nlconst::magic(1e9))
register_param(param, plib::pfmt("{1:.9}").e(value)); register_param(param, plib::pfmt("{1:.9}").e(value));
else else
register_param(param, plib::pfmt("{1}")(static_cast<long>(value))); register_param(param, plib::pfmt("{1}")(gsl::narrow<long>(value)));
} }
void nlparse_t::register_param(const pstring &param, const pstring &value) void nlparse_t::register_param(const pstring &param, const pstring &value)
@ -248,7 +248,7 @@ namespace netlist
void nlparse_t::register_lib_entry(const pstring &name, factory::properties &&props) void nlparse_t::register_lib_entry(const pstring &name, factory::properties &&props)
{ {
m_factory.add(host_arena::make_unique<factory::library_element_t>(name, std::move(props))); m_factory.add(plib::make_unique<factory::library_element_t, host_arena>(name, std::move(props)));
} }
void nlparse_t::register_frontier(const pstring &attach, const pstring &r_IN, void nlparse_t::register_frontier(const pstring &attach, const pstring &r_IN,
@ -508,7 +508,7 @@ pstring setup_t::resolve_alias(const pstring &name) const
ret = temp; ret = temp;
auto p = m_abstract.m_alias.find(ret); auto p = m_abstract.m_alias.find(ret);
temp = (p != m_abstract.m_alias.end() ? p->second : ""); temp = (p != m_abstract.m_alias.end() ? p->second : "");
} while (temp != "" && temp != ret); } while (!temp.empty() && temp != ret);
log().debug("{1}==>{2}\n", name, ret); log().debug("{1}==>{2}\n", name, ret);
return ret; return ret;
@ -532,7 +532,7 @@ pstring setup_t::de_alias(const pstring &alias) const
break; break;
} }
} }
} while (temp != "" && temp != ret); } while (!temp.empty() && temp != ret);
log().debug("{1}==>{2}\n", alias, ret); log().debug("{1}==>{2}\n", alias, ret);
return ret; return ret;
@ -650,7 +650,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(const detail::core_terminal_t &o
{ {
nl_assert(out.is_logic()); nl_assert(out.is_logic());
const auto &out_cast = static_cast<const logic_output_t &>(out); const auto &out_cast = dynamic_cast<const logic_output_t &>(out);
auto iter_proxy(m_proxies.find(&out)); auto iter_proxy(m_proxies.find(&out));
if (iter_proxy != m_proxies.end()) if (iter_proxy != m_proxies.end())
@ -878,7 +878,7 @@ void setup_t::connect_terminals(detail::core_terminal_t &t1,detail::core_termina
{ {
log().debug("adding analog net ...\n"); log().debug("adding analog net ...\n");
// FIXME: Nets should have a unique name // FIXME: Nets should have a unique name
auto anet = nlstate().pool().make_owned<analog_net_t>(m_nlstate,"net." + t1.name()); auto anet = plib::make_owned<analog_net_t>(nlstate().pool(), m_nlstate,"net." + t1.name());
auto *anetp = anet.get(); auto *anetp = anet.get();
m_nlstate.register_net(std::move(anet)); m_nlstate.register_net(std::move(anet));
t1.set_net(anetp); t1.set_net(anetp);
@ -1043,7 +1043,7 @@ void setup_t::resolve_inputs()
detail::core_terminal_t *t1 = find_terminal(t1s); detail::core_terminal_t *t1 = find_terminal(t1s);
detail::core_terminal_t *t2 = find_terminal(t2s); detail::core_terminal_t *t2 = find_terminal(t2s);
if (connect(*t1, *t2)) if (connect(*t1, *t2))
m_abstract.m_links.erase(m_abstract.m_links.begin() + static_cast<std::ptrdiff_t>(i)); m_abstract.m_links.erase(m_abstract.m_links.begin() + plib::narrow_cast<std::ptrdiff_t>(i));
else else
i++; i++;
} }
@ -1104,16 +1104,16 @@ void setup_t::resolve_inputs()
detail::core_terminal_t *term = i.second; detail::core_terminal_t *term = i.second;
if (term->is_tristate_output()) if (term->is_tristate_output())
{ {
const auto *tri(static_cast<tristate_output_t *>(term)); const auto &tri(dynamic_cast<tristate_output_t &>(*term));
// check if we are connected to a proxy // check if we are connected to a proxy
const auto iter_proxy(m_proxies.find(tri)); const auto iter_proxy(m_proxies.find(&tri));
if (iter_proxy == m_proxies.end() && !tri->is_force_logic()) if (iter_proxy == m_proxies.end() && !tri.is_force_logic())
{ {
log().error(ME_TRISTATE_NO_PROXY_FOUND_2(term->name(), term->device().name())); log().error(ME_TRISTATE_NO_PROXY_FOUND_2(term->name(), term->device().name()));
err = true; err = true;
} }
else if (iter_proxy != m_proxies.end() && tri->is_force_logic()) else if (iter_proxy != m_proxies.end() && tri.is_force_logic())
{ {
log().error(ME_TRISTATE_PROXY_FOUND_2(term->name(), term->device().name())); log().error(ME_TRISTATE_PROXY_FOUND_2(term->name(), term->device().name()));
err = true; err = true;
@ -1256,7 +1256,7 @@ nl_fptype models_t::model_t::value(const pstring &entity) const
pstring tmp = value_str(entity); pstring tmp = value_str(entity);
nl_fptype factor = nlconst::one(); nl_fptype factor = nlconst::one();
auto p = std::next(tmp.begin(), static_cast<pstring::difference_type>(tmp.size() - 1)); auto p = std::next(tmp.begin(), plib::narrow_cast<pstring::difference_type>(tmp.size() - 1));
switch (*p) switch (*p)
{ {
case 'M': factor = nlconst::magic(1e6); break; // NOLINT case 'M': factor = nlconst::magic(1e6); break; // NOLINT
@ -1390,7 +1390,7 @@ const logic_family_desc_t *setup_t::family_from_model(const pstring &model)
if (it != m_nlstate.family_cache().end()) if (it != m_nlstate.family_cache().end())
return it->second.get(); return it->second.get();
auto ret = host_arena::make_unique<logic_family_std_proxy_t>(ft); auto ret = plib::make_unique<logic_family_std_proxy_t, host_arena>(ft);
ret->m_low_thresh_PCNT = modv.m_IVL(); ret->m_low_thresh_PCNT = modv.m_IVL();
ret->m_high_thresh_PCNT = modv.m_IVH(); ret->m_high_thresh_PCNT = modv.m_IVH();
@ -1434,7 +1434,7 @@ void setup_t::prepare_to_run()
{ {
pstring envlog = plib::util::environment("NL_LOGS", ""); pstring envlog = plib::util::environment("NL_LOGS", "");
if (envlog != "") if (!envlog.empty())
{ {
std::vector<pstring> loglist(plib::psplit(envlog, ":")); std::vector<pstring> loglist(plib::psplit(envlog, ":"));
m_parser.register_dynamic_log_devices(loglist); m_parser.register_dynamic_log_devices(loglist);
@ -1444,7 +1444,7 @@ void setup_t::prepare_to_run()
for (auto & e : m_abstract.m_defparams) for (auto & e : m_abstract.m_defparams)
{ {
auto param(host_arena::make_unique<param_str_t>(nlstate(), e.first, e.second)); auto param(plib::make_unique<param_str_t, host_arena>(nlstate(), e.first, e.second));
register_param_t(*param); register_param_t(*param);
m_defparam_lifetime.push_back(std::move(param)); m_defparam_lifetime.push_back(std::move(param));
} }
@ -1597,7 +1597,7 @@ source_string_t::stream_ptr source_string_t::stream(const pstring &name)
plib::unused_var(name); plib::unused_var(name);
auto ret(std::make_unique<std::istringstream>(m_str)); auto ret(std::make_unique<std::istringstream>(m_str));
ret->imbue(std::locale::classic()); ret->imbue(std::locale::classic());
return std::move(ret); // FIXME: for c++11 clang builds return ret;
} }
source_mem_t::stream_ptr source_mem_t::stream(const pstring &name) source_mem_t::stream_ptr source_mem_t::stream(const pstring &name)
@ -1605,7 +1605,7 @@ source_mem_t::stream_ptr source_mem_t::stream(const pstring &name)
plib::unused_var(name); plib::unused_var(name);
auto ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary)); auto ret(std::make_unique<std::istringstream>(m_str, std::ios_base::binary));
ret->imbue(std::locale::classic()); ret->imbue(std::locale::classic());
return std::move(ret); // FIXME: for c++11 clang builds return ret;
} }
source_file_t::stream_ptr source_file_t::stream(const pstring &name) source_file_t::stream_ptr source_file_t::stream(const pstring &name)

View File

@ -307,10 +307,10 @@ namespace netlist
void register_param(const pstring &param, nl_fptype value); void register_param(const pstring &param, nl_fptype value);
template <typename T> template <typename T>
std::enable_if_t<plib::is_floating_point<T>::value || plib::is_integral<T>::value> std::enable_if_t<plib::is_arithmetic<T>::value>
register_param_val(const pstring &param, T value) register_param_val(const pstring &param, T value)
{ {
register_param(param, static_cast<nl_fptype>(value)); register_param(param, plib::narrow_cast<nl_fptype>(value));
} }
void register_lib_entry(const pstring &name, factory::properties &&props); void register_lib_entry(const pstring &name, factory::properties &&props);

View File

@ -78,9 +78,9 @@ namespace netlist
/// \note This is not the right location yet. /// \note This is not the right location yet.
/// ///
using device_arena = std::conditional<NL_USE_MEMPOOL, using device_arena = std::conditional_t<config::use_mempool::value,
plib::mempool_arena<plib::aligned_arena>, plib::mempool_arena<plib::aligned_arena>,
plib::aligned_arena>::type; plib::aligned_arena>;
using host_arena = plib::aligned_arena; using host_arena = plib::aligned_arena;
/// \brief Interface definition for netlist callbacks into calling code /// \brief Interface definition for netlist callbacks into calling code
@ -187,7 +187,7 @@ namespace netlist
} }
}; };
/// \brief: used define a constant in device description struct /// \brief: used to define a constant in device description struct
/// ///
/// See the 74125 implementation /// See the 74125 implementation
/// ///

View File

@ -38,9 +38,9 @@ namespace plib
mat_precondition_ILU(std::size_t size, std::size_t ilu_scale = 4 mat_precondition_ILU(std::size_t size, std::size_t ilu_scale = 4
, std::size_t bw = plib::pmatrix_cr_t<FT, SIZE>::FILL_INFINITY) , std::size_t bw = plib::pmatrix_cr_t<FT, SIZE>::FILL_INFINITY)
: m_mat(static_cast<typename mat_type::index_type>(size)) : m_mat(narrow_cast<typename mat_type::index_type>(size))
, m_LU(static_cast<typename mat_type::index_type>(size)) , m_LU(narrow_cast<typename mat_type::index_type>(size))
, m_ILU_scale(static_cast<std::size_t>(ilu_scale)) , m_ILU_scale(narrow_cast<std::size_t>(ilu_scale))
, m_band_width(bw) , m_band_width(bw)
{ {
} }
@ -103,7 +103,7 @@ namespace plib
if (m_mat.col_idx[k] == i && k < m_mat.row_idx[j+1]) if (m_mat.col_idx[k] == i && k < m_mat.row_idx[j+1])
nzcol[i].push_back(k); nzcol[i].push_back(k);
} }
nzcol[i].push_back(static_cast<std::size_t>(-1)); nzcol[i].push_back(narrow_cast<std::size_t>(-1));
} }
} }
@ -139,7 +139,7 @@ namespace plib
const auto &nz = nzcol[i]; const auto &nz = nzcol[i];
std::size_t j; std::size_t j;
while ((j = nz[nzcolp++])!=static_cast<std::size_t>(-1)) // NOLINT(bugprone-infinite-loop) while ((j = nz[nzcolp++])!=narrow_cast<std::size_t>(-1)) // NOLINT(bugprone-infinite-loop)
{ {
v += m_mat.A[j] * m_mat.A[j]; v += m_mat.A[j] * m_mat.A[j];
} }
@ -209,14 +209,12 @@ namespace plib
// FIXME: hardcoding RESTART to 20 becomes an issue on very large // FIXME: hardcoding RESTART to 20 becomes an issue on very large
// systems. // systems.
template <typename FT, int SIZE, int RESTART = 80> template <typename FT, int SIZE, int RESTART = 16>
struct gmres_t struct gmres_t
{ {
public: public:
using float_type = FT; using float_type = FT;
// FIXME: dirty hack to make this compile
static constexpr const std::size_t storage_N = plib::sizeabs<FT, SIZE>::ABS();
explicit gmres_t(std::size_t size) explicit gmres_t(std::size_t size)
: residual(size) : residual(size)
@ -236,7 +234,7 @@ namespace plib
g1 = s * g0_last + c * g1; g1 = s * g0_last + c * g1;
} }
std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); } std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast<std::size_t>(SIZE); }
template <int k, typename OPS, typename VT> template <int k, typename OPS, typename VT>
bool do_k(OPS &ops, VT &x, std::size_t &itr_used, FT rho_delta, bool dummy) bool do_k(OPS &ops, VT &x, std::size_t &itr_used, FT rho_delta, bool dummy)
@ -360,7 +358,7 @@ namespace plib
rho_delta = accuracy * rho_to_accuracy; rho_delta = accuracy * rho_to_accuracy;
} }
else else
rho_delta = accuracy * plib::sqrt(static_cast<FT>(n)); rho_delta = accuracy * plib::sqrt(narrow_cast<FT>(n));
// //
// Using // Using
@ -407,8 +405,6 @@ namespace plib
private: private:
//typedef typename plib::mat_cr_t<FT, SIZE>::index_type mattype;
plib::parray<float_type, SIZE> residual; plib::parray<float_type, SIZE> residual;
plib::parray<float_type, SIZE> Ax; plib::parray<float_type, SIZE> Ax;
@ -423,8 +419,6 @@ namespace plib
std::size_t m_size; std::size_t m_size;
bool m_use_more_precise_stop_condition; bool m_use_more_precise_stop_condition;
}; };
@ -454,7 +448,7 @@ namespace plib
{ {
} }
std::size_t size() const { return (SIZE<=0) ? m_size : static_cast<std::size_t>(SIZE); } std::size_t size() const { return (SIZE<=0) ? m_size : narrow_cast<std::size_t>(SIZE); }
template <typename OPS, typename VT, typename VRHS> template <typename OPS, typename VT, typename VRHS>
std::size_t solve(OPS &ops, VT &x0, const VRHS & rhs, const std::size_t iter_max, float_type accuracy) std::size_t solve(OPS &ops, VT &x0, const VRHS & rhs, const std::size_t iter_max, float_type accuracy)
@ -478,7 +472,7 @@ namespace plib
ops.calc_rhs(Ax, x); ops.calc_rhs(Ax, x);
vec_sub(size(), rhs, Ax, residual); vec_sub(size(), rhs, Ax, residual);
FT rho_delta = accuracy * std::sqrt(static_cast<FT>(size())); FT rho_delta = accuracy * std::sqrt(narrow_cast<FT>(size()));
rho_delta = 1e-9; rho_delta = 1e-9;

View File

@ -73,7 +73,7 @@ namespace plib
~pmatrix_cr_t() = default; ~pmatrix_cr_t() = default;
constexpr std::size_t size() const noexcept { return (N>0) ? static_cast<std::size_t>(N) : m_size; } constexpr std::size_t size() const noexcept { return (N>0) ? narrow_cast<std::size_t>(N) : m_size; }
void clear() noexcept void clear() noexcept
{ {
@ -132,9 +132,9 @@ namespace plib
row_idx[k] = nz; row_idx[k] = nz;
for (std::size_t j=0; j < size(); j++) for (std::size_t j=0; j < size(); j++)
if (f[k][j] <= max_fill && plib::abs(static_cast<int>(k)-static_cast<int>(j)) <= static_cast<int>(band_width)) if (f[k][j] <= max_fill && plib::abs(narrow_cast<int>(k)-narrow_cast<int>(j)) <= narrow_cast<int>(band_width))
{ {
col_idx[nz] = static_cast<C>(j); col_idx[nz] = narrow_cast<C>(j);
if (j == k) if (j == k)
diag[k] = nz; diag[k] = nz;
nz++; nz++;
@ -150,7 +150,7 @@ namespace plib
{ {
for (std::size_t j=k + 1; j < size(); j++) for (std::size_t j=k + 1; j < size(); j++)
if (f[j][k] < FILL_INFINITY) if (f[j][k] < FILL_INFINITY)
nzbd[k].push_back(static_cast<C>(j)); nzbd[k].push_back(narrow_cast<C>(j));
nzbd[k].push_back(0); // end of sequence nzbd[k].push_back(0); // end of sequence
} }
@ -343,7 +343,7 @@ namespace plib
{ {
for (std::size_t i = 0; i < m_ge_par.size(); i++) for (std::size_t i = 0; i < m_ge_par.size(); i++)
if (plib::container::contains( m_ge_par[i], k)) if (plib::container::contains( m_ge_par[i], k))
return static_cast<int>(i); return narrow_cast<int>(i);
return -1; return -1;
} }
@ -525,7 +525,7 @@ namespace plib
} }
} }
if (found) if (found)
ilu_rows[p++] = static_cast<index_type>(i); ilu_rows[p++] = narrow_cast<index_type>(i);
} }
ilu_rows[p] = 0; // end of array ilu_rows[p] = 0; // end of array
this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2) this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2)

View File

@ -9,6 +9,7 @@
/// ///
#include "pconfig.h" #include "pconfig.h"
#include "pgsl.h"
#include "pmath.h" #include "pmath.h"
#include "pstring.h" #include "pstring.h"
#include "ptypes.h" #include "ptypes.h"
@ -26,28 +27,52 @@
namespace plib { namespace plib {
//============================================================
// aligned types
//============================================================
#if 0
#if (PUSE_ALIGNED_HINTS)
template <typename T, std::size_t A>
using aligned_type __attribute__((aligned(A))) = T;
#else
template <typename T, std::size_t A>
using aligned_type = T;
#endif
template <typename T, std::size_t A>
using aligned_pointer = aligned_type<T, A> *;
template <typename T, std::size_t A>
using const_aligned_pointer = const aligned_type<T, A> *;
template <typename T, std::size_t A>
using aligned_reference = aligned_type<T, A> &;
template <typename T, std::size_t A>
using const_aligned_reference = const aligned_type<T, A> &;
#endif
//============================================================ //============================================================
// Standard arena_deleter // Standard arena_deleter
//============================================================ //============================================================
template <typename P, typename T, typename A = void> template <typename P, typename T, bool X>
struct arena_deleter struct arena_deleter_base
{ {
}; };
template <typename P, typename T> template <typename P, typename T>
struct arena_deleter<P, T, std::enable_if_t<!P::has_static_deallocator>> struct arena_deleter_base<P, T, false>
{ {
using arena_storage_type = P; using arena_storage_type = P;
constexpr arena_deleter(arena_storage_type *a = nullptr) noexcept constexpr arena_deleter_base(arena_storage_type *a = nullptr) noexcept
: m_a(a) { } : m_a(a) { }
template<typename U, typename = template<typename U, typename =
std::enable_if_t<std::is_convertible< U*, T*>::value>> std::enable_if_t<std::is_convertible< U*, T*>::value>>
arena_deleter(const arena_deleter<P, U> &rhs) noexcept arena_deleter_base(const arena_deleter_base<P, U, false> &rhs) noexcept
: m_a(rhs.m_a) { } : m_a(rhs.m_a) { }
void operator()(T *p) noexcept void operator()(T *p) noexcept
@ -61,18 +86,18 @@ namespace plib {
}; };
template <typename P, typename T> template <typename P, typename T>
struct arena_deleter<P, T, std::enable_if_t<P::has_static_deallocator>> struct arena_deleter_base<P, T, true>
{ {
using arena_storage_type = P; using arena_storage_type = P;
constexpr arena_deleter(arena_storage_type *a = nullptr) noexcept constexpr arena_deleter_base(arena_storage_type *a = nullptr) noexcept
{ {
plib::unused_var(a); plib::unused_var(a);
} }
template<typename U, typename = typename template<typename U, typename = typename
std::enable_if<std::is_convertible< U*, T*>::value>::type> std::enable_if<std::is_convertible< U*, T*>::value>::type>
arena_deleter(const arena_deleter<P, U> &rhs) noexcept arena_deleter_base(const arena_deleter_base<P, U, true> &rhs) noexcept
{ {
plib::unused_var(rhs); plib::unused_var(rhs);
} }
@ -85,6 +110,13 @@ namespace plib {
} }
}; };
template <typename P, typename T>
struct arena_deleter : public arena_deleter_base<P, T, P::has_static_deallocator>
{
using base_type = arena_deleter_base<P, T, P::has_static_deallocator>;
using base_type::base_type;
};
//============================================================ //============================================================
// owned_ptr: smart pointer with ownership information // owned_ptr: smart pointer with ownership information
//============================================================ //============================================================
@ -209,7 +241,8 @@ namespace plib {
{ {
public: public:
using value_type = T; using value_type = T;
static constexpr const std::size_t align_size = ALIGN; using pointer = T *;
static /*constexpr*/ const std::size_t align_size = ALIGN;
using arena_type = ARENA; using arena_type = ARENA;
static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0, static_assert(align_size >= alignof(T) && (align_size % alignof(T)) == 0,
@ -237,14 +270,14 @@ namespace plib {
using other = arena_allocator<ARENA, U, ALIGN>; using other = arena_allocator<ARENA, U, ALIGN>;
}; };
T* allocate(std::size_t n) pointer allocate(std::size_t n)
{ {
return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n)); //NOLINT return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n)); //NOLINT
} }
void deallocate(T* p, std::size_t n) noexcept void deallocate(pointer p, std::size_t n) noexcept
{ {
m_a.deallocate(p, n); m_a.deallocate(p, sizeof(T) * n);
} }
template<typename U, typename... Args> template<typename U, typename... Args>
@ -296,171 +329,88 @@ namespace plib {
// The previous code compiled with gcc and clang on all platforms and // The previous code compiled with gcc and clang on all platforms and
// compilers apart from MSVC. // compilers apart from MSVC.
template <typename P, bool HSD> template <typename P, bool HSD, bool HSA>
struct arena_base;
template <typename P, bool HSD, bool HSA>
struct arena_core struct arena_core
{ {
static constexpr const bool has_static_deallocator = HSD; static constexpr const bool has_static_deallocator = HSD;
static constexpr const bool has_static_allocator = HSA;
using size_type = std::size_t; using size_type = std::size_t;
template <class T, size_type ALIGN = alignof(T)> template <class T, size_type ALIGN = alignof(T)>
using allocator_type = arena_allocator<P, T, ALIGN>; using allocator_type = arena_allocator<P, T, ALIGN>;
template <class T>
using deleter_type = arena_deleter<P, T>;
template <typename T>
using unique_ptr = std::unique_ptr<T, deleter_type<T>>;
template <typename T>
using owned_ptr = plib::owned_ptr<T, deleter_type<T>>;
static inline P &instance() noexcept static inline P &instance() noexcept
{ {
static P s_arena; static P s_arena;
return s_arena; return s_arena;
} }
size_type cur_alloc() const noexcept { return m_stat_cur_alloc(); } // NOLINT(readability-convert-member-functions-to-static) friend struct arena_base<P, HSD, HSA>;
size_type max_alloc() const noexcept { return m_stat_max_alloc(); } // NOLINT(readability-convert-member-functions-to-static) private:
protected: size_t m_stat_cur_alloc = 0;
static size_t &m_stat_cur_alloc() noexcept { static size_t val = 0; return val; } size_t m_stat_max_alloc = 0;
static size_t &m_stat_max_alloc() noexcept { static size_t val = 0; return val; }
}; };
template <typename P, bool HSD> template <typename P, bool HSD, bool HSA>
struct arena_hsd : public arena_core<P, HSD> struct arena_base : public arena_core<P, HSD, HSA>
{ {
template<typename T> using base_type = arena_core<P, HSD, HSA>;
inline void free(T *ptr) noexcept using size_type = typename base_type::size_type;
static size_type cur_alloc() noexcept { return base_type::instance().m_stat_cur_alloc; }
static size_type max_alloc() noexcept { return base_type::instance().m_stat_max_alloc; }
static inline void inc_alloc_stat(size_type size)
{ {
ptr->~T(); auto &i = base_type::instance();
static_cast<P *>(this)->deallocate(ptr, sizeof(T)); i.m_stat_cur_alloc += size;
if (i.m_stat_max_alloc <i.m_stat_cur_alloc)
i.m_stat_max_alloc = i.m_stat_cur_alloc;
}
static inline void dec_alloc_stat(size_type size)
{
base_type::instance().m_stat_cur_alloc -= size;
} }
}; };
template <typename P> template <typename P>
struct arena_hsd<P, true> : public arena_core<P, true> struct arena_base<P, false, false> : public arena_core<P, false, false>
{ {
template<typename T> using size_type = typename arena_core<P, false, false>::size_type;
static inline void free(T *ptr) noexcept
size_type cur_alloc() const noexcept { return this->m_stat_cur_alloc; }
size_type max_alloc() const noexcept { return this->m_stat_max_alloc; }
inline void inc_alloc_stat(size_type size)
{ {
ptr->~T(); this->m_stat_cur_alloc += size;
P::deallocate(ptr, sizeof(T)); if (this->m_stat_max_alloc < this->m_stat_cur_alloc)
this->m_stat_max_alloc = this->m_stat_cur_alloc;
}
inline void dec_alloc_stat(size_type size)
{
this->m_stat_cur_alloc -= size;
} }
}; };
template <typename P, bool HSD, bool HSA>
struct arena_base : public arena_hsd<P, HSD>
{
template <class T>
using deleter_type = arena_deleter<P, T>;
template <typename T>
using unique_ptr = std::unique_ptr<T, deleter_type<T>>;
template <typename T>
using owned_ptr = plib::owned_ptr<T, deleter_type<T>>;
template<typename T, typename... Args>
inline unique_ptr<T> make_unique(Args&&... args)
{
auto *mem = static_cast<P *>(this)->allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
auto *mema = new (mem) T(std::forward<Args>(args)...);
return unique_ptr<T>(mema, deleter_type<T>());
}
catch (...)
{
static_cast<P *>(this)->deallocate(mem, sizeof(T));
throw;
}
}
template<typename T, typename... Args>
inline owned_ptr<T> make_owned(Args&&... args)
{
auto *mem = static_cast<P *>(this)->allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
auto *mema = new (mem) T(std::forward<Args>(args)...);
return owned_ptr<T>(mema, true, deleter_type<T>());
}
catch (...)
{
static_cast<P *>(this)->deallocate(mem, sizeof(T));
throw;
}
}
template<typename T, typename... Args>
inline T * alloc(Args&&... args)
{
auto *p = static_cast<P *>(this)->allocate(alignof(T), sizeof(T));
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return new(p) T(std::forward<Args>(args)...);
}
};
template <typename P, bool HSD>
struct arena_base<P, HSD, true> : public arena_hsd<P, HSD>
{
template <class T>
using deleter_type = arena_deleter<P, T>;
template <typename T>
using unique_ptr = std::unique_ptr<T, deleter_type<T>>;
template <typename T>
using owned_ptr = plib::owned_ptr<T, deleter_type<T>>;
template<typename T, typename... Args>
static inline unique_ptr<T> make_unique(Args&&... args)
{
auto *mem = P::allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
auto *mema = new (mem) T(std::forward<Args>(args)...);
return unique_ptr<T>(mema, deleter_type<T>());
}
catch (...)
{
P::deallocate(mem, sizeof(T));
throw;
}
}
template<typename T, typename... Args>
static inline owned_ptr<T> make_owned(Args&&... args)
{
auto *mem = P::allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
auto *mema = new (mem) T(std::forward<Args>(args)...);
return owned_ptr<T>(mema, true, deleter_type<T>());
}
catch (...)
{
P::deallocate(mem, sizeof(T));
throw;
}
}
template<typename T, typename... Args>
static inline T * alloc(Args&&... args)
{
auto *p = P::allocate(alignof(T), sizeof(T));
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return new(p) T(std::forward<Args>(args)...);
}
};
struct aligned_arena : public arena_base<aligned_arena, true, true> struct aligned_arena : public arena_base<aligned_arena, true, true>
{ {
static inline void *allocate( size_t alignment, size_t size ) static inline gsl::owner<void *> allocate( size_t alignment, size_t size )
{ {
m_stat_cur_alloc() += size; inc_alloc_stat(size);
if (m_stat_max_alloc() < m_stat_cur_alloc())
m_stat_max_alloc() = m_stat_cur_alloc();
#if (PUSE_ALIGNED_ALLOCATION) #if (PUSE_ALIGNED_ALLOCATION)
#if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER) #if defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)
@ -472,7 +422,7 @@ namespace plib {
} }
return p; return p;
#else #else
return aligned_alloc(alignment, size); return static_cast<gsl::owner<void *>>(aligned_alloc(alignment, size));
#endif #endif
#else #else
unused_var(alignment); unused_var(alignment);
@ -480,10 +430,10 @@ namespace plib {
#endif #endif
} }
static inline void deallocate( void *ptr, size_t size ) noexcept static inline void deallocate(gsl::owner<void *> ptr, size_t size ) noexcept
{ {
//unused_var(size); //unused_var(size);
m_stat_cur_alloc() -= size; dec_alloc_stat(size);
#if (PUSE_ALIGNED_ALLOCATION) #if (PUSE_ALIGNED_ALLOCATION)
// NOLINTNEXTLINE(cppcoreguidelines-no-malloc) // NOLINTNEXTLINE(cppcoreguidelines-no-malloc)
::free(ptr); ::free(ptr);
@ -504,14 +454,14 @@ namespace plib {
{ {
static inline void *allocate( size_t alignment, size_t size ) static inline void *allocate( size_t alignment, size_t size )
{ {
m_stat_cur_alloc() += size; inc_alloc_stat(size);
unused_var(alignment); unused_var(alignment);
return ::operator new(size); return ::operator new(size);
} }
static inline void deallocate( void *ptr, size_t size ) noexcept static inline void deallocate( void *ptr, size_t size ) noexcept
{ {
m_stat_cur_alloc() -= size; dec_alloc_stat(size);
::operator delete(ptr); ::operator delete(ptr);
} }
@ -522,31 +472,116 @@ namespace plib {
} }
}; };
template <typename T, std::size_t ALIGN> namespace detail
constexpr T *assume_aligned_ptr(T *p) noexcept
{ {
static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); template<typename T, typename ARENA, typename... Args>
static_assert(is_pow2(ALIGN), "Alignment must be a power of 2"); static inline T * alloc(Args&&... args)
{
auto *mem = ARENA::allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return new (mem) T(std::forward<Args>(args)...);
}
catch (...)
{
ARENA::deallocate(mem, sizeof(T));
throw;
}
}
#if (PUSE_ALIGNED_HINTS) template<typename ARENA, typename T>
return reinterpret_cast<T *>(__builtin_assume_aligned(p, ALIGN)); static inline void free(T *ptr) noexcept
#else {
return p; ptr->~T();
#endif ARENA::deallocate(ptr, sizeof(T));
}
template<typename T, typename ARENA, typename... Args>
static inline T * alloc(ARENA &arena, Args&&... args)
{
auto *mem = arena.allocate(alignof(T), sizeof(T));
try
{
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
return new (mem) T(std::forward<Args>(args)...);
}
catch (...)
{
arena.deallocate(mem, sizeof(T));
throw;
}
}
template<typename ARENA, typename T>
static inline void free(ARENA &arena, T *ptr) noexcept
{
ptr->~T();
arena.deallocate(ptr, sizeof(T));
}
} // namespace detail
template<typename T, typename ARENA, typename... Args>
static inline
std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>>
make_unique(Args&&... args)
{
using up_type = typename ARENA::template unique_ptr<T>;
using deleter_type = typename ARENA::template deleter_type<T>;
auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...);
return up_type(mem, deleter_type());
} }
template <typename T, std::size_t ALIGN> template<typename T, typename ARENA, typename... Args>
constexpr const T *assume_aligned_ptr(const T *p) noexcept static inline
std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template unique_ptr<T>>
make_unique(Args&&... args)
{ {
static_assert(ALIGN >= alignof(T), "Alignment must be greater or equal to alignof(T)"); return make_unique<T>(ARENA::instance(), std::forward<Args>(args)...);
static_assert(is_pow2(ALIGN), "Alignment must be a power of 2");
#if (PUSE_ALIGNED_HINTS)
return reinterpret_cast<const T *>(__builtin_assume_aligned(p, ALIGN));
#else
return p;
#endif
} }
template<typename T, typename ARENA, typename... Args>
static inline
typename ARENA::template unique_ptr<T>
make_unique(ARENA &arena, Args&&... args)
{
using up_type = typename ARENA::template unique_ptr<T>;
using deleter_type = typename ARENA::template deleter_type<T>;
auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...);
return up_type(mem, deleter_type(&arena));
}
template<typename T, typename ARENA, typename... Args>
static inline
std::enable_if_t<ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>>
make_owned(Args&&... args)
{
using op_type = typename ARENA::template owned_ptr<T>;
using deleter_type = typename ARENA::template deleter_type<T>;
auto *mem = detail::alloc<T, ARENA>(std::forward<Args>(args)...);
return op_type(mem, true, deleter_type());
}
template<typename T, typename ARENA, typename... Args>
static inline
std::enable_if_t<!ARENA::has_static_allocator, typename ARENA::template owned_ptr<T>>
make_owned(Args&&... args)
{
return make_owned<T>(ARENA::instance(), std::forward<Args>(args)...);
}
template<typename T, typename ARENA, typename... Args>
static inline typename ARENA::template owned_ptr<T> make_owned(ARENA &arena, Args&&... args)
{
using op_type = typename ARENA::template owned_ptr<T>;
using deleter_type = typename ARENA::template deleter_type<T>;
auto *mem = detail::alloc<T>(arena, std::forward<Args>(args)...);
return op_type(mem, true, deleter_type(&arena));
}
template <class T, std::size_t ALIGN = alignof(T)> template <class T, std::size_t ALIGN = alignof(T)>
using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>; using aligned_allocator = aligned_arena::allocator_type<T, ALIGN>;
@ -557,57 +592,72 @@ namespace plib {
PDEFINE_HAS_MEMBER(has_align, align_size); PDEFINE_HAS_MEMBER(has_align, align_size);
template <typename T, typename X = void> template <typename T, bool X>
struct align_traits struct align_traits_base
{ {
static_assert(!has_align<T>::value, "no align");
static constexpr const std::size_t align_size = alignof(std::max_align_t); static constexpr const std::size_t align_size = alignof(std::max_align_t);
static constexpr const std::size_t value_size = sizeof(typename T::value_type); static constexpr const std::size_t value_size = sizeof(typename T::value_type);
static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
}; };
template <typename T> template <typename T>
struct align_traits<T, std::enable_if_t<has_align<T>::value, void>> struct align_traits_base<T, true>
{ {
static_assert(has_align<T>::value, "no align");
static constexpr const std::size_t align_size = T::align_size; static constexpr const std::size_t align_size = T::align_size;
static constexpr const std::size_t value_size = sizeof(typename T::value_type); static constexpr const std::size_t value_size = sizeof(typename T::value_type);
static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size; static constexpr const std::size_t stride_size = lcm(align_size, value_size) / value_size;
}; };
template <typename T>
struct align_traits : public align_traits_base<T, has_align<T>::value>
{};
template <typename BASEARENA = aligned_arena, std::size_t PAGESIZE = 1024>
class paged_arena : public arena_base<paged_arena<BASEARENA, PAGESIZE>, true, true>
{
public:
paged_arena()
{
}
PCOPYASSIGNMOVE(paged_arena, delete)
~paged_arena() = default;
static void *allocate(size_t align, size_t size)
{
plib::unused_var(align);
//size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE;
return arena().allocate(PAGESIZE, size);
}
static void deallocate(void *ptr, size_t size) noexcept
{
//size = ((size + PAGESIZE - 1) / PAGESIZE) * PAGESIZE;
arena().deallocate(ptr, size);
}
bool operator ==(const paged_arena &rhs) const noexcept { return this == &rhs; }
static BASEARENA &arena() noexcept { static BASEARENA m_arena; return m_arena; }
private:
};
//============================================================ //============================================================
// Aligned vector // Aligned vector
//============================================================ //============================================================
// FIXME: needs a separate file // FIXME: needs a separate file
template <typename T, std::size_t ALIGN = PALIGN_VECTOROPT, typename A = aligned_allocator<T, ALIGN>> template <typename T, std::size_t ALIGN = PALIGN_VECTOROPT, typename A = paged_arena<>>//aligned_arena>
class aligned_vector : public std::vector<T, A> class aligned_vector : public std::vector<T, typename A::template allocator_type<T, ALIGN>>
{ {
public: public:
using base = std::vector<T, A>; using base = std::vector<T, typename A::template allocator_type<T, ALIGN>>;
using reference = typename base::reference;
using const_reference = typename base::const_reference;
using pointer = typename base::pointer;
using const_pointer = typename base::const_pointer;
using size_type = typename base::size_type;
using base::base; using base::base;
base & as_base() noexcept { return *this; }
const base & as_base() const noexcept { return *this; }
constexpr reference operator[](size_type i) noexcept
{
return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
}
constexpr const_reference operator[](size_type i) const noexcept
{
return assume_aligned_ptr<T, ALIGN>(&(base::operator[](0)))[i];
}
pointer data() noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
const_pointer data() const noexcept { return assume_aligned_ptr<T, ALIGN>(base::data()); }
}; };
} // namespace plib } // namespace plib

View File

@ -21,19 +21,20 @@
namespace plib { namespace plib {
template <typename FT, int SIZE> template <typename FT, int SIZE, typename ARENA>
struct sizeabs struct sizeabs
{ {
static constexpr std::size_t ABS() noexcept { 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()> ; using container = typename std::array<FT, ABS()> ;
}; };
template <typename FT> template <typename FT, typename ARENA>
struct sizeabs<FT, 0> struct sizeabs<FT, 0, ARENA>
{ {
static constexpr std::size_t ABS() noexcept { return 0; } 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, arena_allocator<mempool, FT, 64>>;
using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>; using container = typename std::vector<FT, allocator_type>;
}; };
/// \brief Array with preallocated or dynamic allocation. /// \brief Array with preallocated or dynamic allocation.
@ -51,17 +52,20 @@ namespace plib {
/// I consider > 10% performance difference to be a use case. /// I consider > 10% performance difference to be a use case.
/// ///
template <typename FT, int SIZE> template <typename FT, int SIZE, typename ARENA = aligned_arena>
struct parray struct parray
{ {
public: public:
static constexpr std::size_t SIZEABS() noexcept { return sizeabs<FT, SIZE>::ABS(); } static constexpr std::size_t SIZEABS() noexcept { return sizeabs<FT, SIZE, ARENA>::ABS(); }
using base_type = typename sizeabs<FT, SIZE>::container; using base_type = typename sizeabs<FT, SIZE, ARENA>::container;
using size_type = typename base_type::size_type; using size_type = typename base_type::size_type;
using reference = typename base_type::reference; using value_type = FT;
using const_reference = typename base_type::const_reference; using reference = FT &;
using value_type = typename base_type::value_type; using const_reference = const FT &;
using pointer = FT *;
using const_pointer = const FT *;
template <int X = SIZE > template <int X = SIZE >
parray(size_type size, std::enable_if_t<(X==0), int> = 0) parray(size_type size, std::enable_if_t<(X==0), int> = 0)
@ -70,7 +74,7 @@ namespace plib {
} }
template <int X = SIZE > template <int X = SIZE >
parray(size_type size, FT val, std::enable_if_t<(X==0), int> = 0) parray(size_type size, const FT &val, std::enable_if_t<(X==0), int> = 0)
: m_a(size, val), m_size(size) : m_a(size, val), m_size(size)
{ {
} }
@ -85,7 +89,7 @@ namespace plib {
} }
template <int X = SIZE > template <int X = SIZE >
parray(size_type size, FT val, std::enable_if_t<(X != 0), int> = 0) noexcept(false) parray(size_type size, const FT &val, std::enable_if_t<(X != 0), int> = 0) noexcept(false)
: m_size(size) : m_size(size)
{ {
if ((SIZE < 0 && size > SIZEABS()) if ((SIZE < 0 && size > SIZEABS())
@ -131,20 +135,19 @@ namespace plib {
constexpr reference operator[](size_type i) noexcept constexpr reference operator[](size_type i) noexcept
{ {
return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; return data()[i];
} }
constexpr const_reference operator[](size_type i) const noexcept constexpr const_reference operator[](size_type i) const noexcept
{ {
return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(&m_a[0])[i]; return data()[i];
} }
FT * data() noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } pointer data() noexcept { return m_a.data(); }
const FT * data() const noexcept { return assume_aligned_ptr<FT, PALIGN_VECTOROPT>(m_a.data()); } const_pointer data() const noexcept { return m_a.data(); }
private: private:
PALIGNAS_VECTOROPT() PALIGNAS_VECTOROPT()
base_type m_a; base_type m_a;
PALIGNAS_CACHELINE()
size_type m_size; size_type m_size;
}; };

View File

@ -9,6 +9,7 @@
/// ///
#include "pconfig.h" #include "pconfig.h"
#include "pgsl.h"
#include "ptypes.h" #include "ptypes.h"
#include <chrono> #include <chrono>
@ -212,8 +213,8 @@ namespace plib {
ctype count() const noexcept { return m_count; } ctype count() const noexcept { return m_count; }
template <typename S> template <typename S>
S as_seconds() const noexcept { return static_cast<S>(total()) S as_seconds() const noexcept { return narrow_cast<S>(total())
/ static_cast<S>(T::per_second()); } / narrow_cast<S>(T::per_second()); }
guard_t guard() noexcept { return guard_t(*this); } guard_t guard() noexcept { return guard_t(*this); }
private: private:
@ -244,7 +245,7 @@ namespace plib {
constexpr type total() const noexcept { return 0; } constexpr type total() const noexcept { return 0; }
constexpr ctype count() const noexcept { return 0; } constexpr ctype count() const noexcept { return 0; }
template <typename S> template <typename S>
S as_seconds() const noexcept { return static_cast<S>(0.0); } S as_seconds() const noexcept { return narrow_cast<S>(0); }
constexpr static bool enabled = false; constexpr static bool enabled = false;
guard_t guard() { return guard_t(); } guard_t guard() { return guard_t(); }
}; };

View File

@ -72,10 +72,11 @@
#define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE) #define PALIGNAS_CACHELINE() PALIGNAS(PALIGN_CACHELINE)
#define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT) #define PALIGNAS_VECTOROPT() PALIGNAS(PALIGN_VECTOROPT)
// FIXME: Breaks mame build on windows due to -Wattribute // FIXME: Breaks mame build on windows mingw due to -Wattribute
// also triggers -Wattribute on ARM // also triggers -Wattribute on ARM
// This is fixed on mingw version 10
// FIXME: no error on cross-compile - need further checks // FIXME: no error on cross-compile - need further checks
#if defined(__GNUC__) && (defined(_WIN32) || defined(__arm__) || defined(__ARMEL__)) #if defined(__GNUC__) && ((defined(_WIN32) && __GNUC__ < 10) || defined(__arm__) || defined(__ARMEL__))
#define PALIGNAS(x) #define PALIGNAS(x)
#else #else
#define PALIGNAS(x) alignas(x) #define PALIGNAS(x) alignas(x)
@ -83,7 +84,7 @@
/// \brief nvcc build flag. /// \brief nvcc build flag.
/// ///
/// Set this to 1 if you are building with NVIDIA nvcc /// Set this to 101 if you are building with NVIDIA nvcc 10.1
/// ///
#ifndef NVCCBUILD #ifndef NVCCBUILD
#define NVCCBUILD (0) #define NVCCBUILD (0)
@ -166,5 +167,15 @@ typedef __float128 FLOAT128;
#endif #endif
#endif #endif
#if (PUSE_FLOAT128)
#if defined(__has_include)
#if !__has_include(<quadmath.h>)
//#pragma message "disabling PUSE_FLOAT128 due to missing quadmath.h"
#undef PUSE_FLOAT128
#define PUSE_FLOAT128 (0)
#endif
#endif
#endif
#endif // PCONFIG_H_ #endif // PCONFIG_H_

View File

@ -31,6 +31,7 @@ namespace plib {
template <typename T> template <typename T>
T getsym(const pstring &name) const noexcept T getsym(const pstring &name) const noexcept
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return reinterpret_cast<T>(getsym_p(name)); return reinterpret_cast<T>(getsym_p(name));
} }

View File

@ -24,7 +24,7 @@ namespace plib
// Implementation in putil.cpp. // Implementation in putil.cpp.
// Putting the code here leads to a performance decrease. // Putting the code here leads to a performance decrease.
static int from_string_int(const pstring &str, const pstring &x); static int from_string_int(const pstring &str, const pstring &x);
static pstring nthstr(int n, const pstring &str); static pstring nthstr(std::size_t n, const pstring &str);
}; };
} // namespace plib } // namespace plib
@ -34,7 +34,6 @@ namespace plib
enum E { __VA_ARGS__ }; \ enum E { __VA_ARGS__ }; \
constexpr ename (const E &v) : m_v(v) { } \ constexpr ename (const E &v) : m_v(v) { } \
template <typename T> explicit constexpr ename(const T &val) { m_v = static_cast<E>(val); } \ template <typename T> explicit constexpr ename(const T &val) { m_v = static_cast<E>(val); } \
template <typename T> explicit constexpr ename(T && val) { m_v = static_cast<E>(val); } \
bool set_from_string (const pstring &s) { \ bool set_from_string (const pstring &s) { \
int f = from_string_int(strings(), s); \ int f = from_string_int(strings(), s); \
if (f>=0) { m_v = static_cast<E>(f); return true; } \ if (f>=0) { m_v = static_cast<E>(f); return true; } \
@ -44,7 +43,7 @@ namespace plib
constexpr bool operator==(const ename &rhs) const noexcept {return m_v == rhs.m_v;} \ constexpr bool operator==(const ename &rhs) const noexcept {return m_v == rhs.m_v;} \
constexpr bool operator==(const E &rhs) const noexcept {return m_v == rhs;} \ constexpr bool operator==(const E &rhs) const noexcept {return m_v == rhs;} \
pstring name() const { \ pstring name() const { \
return nthstr(static_cast<int>(m_v), strings()); \ return nthstr(m_v, strings()); \
} \ } \
private: E m_v; \ private: E m_v; \
static pstring strings() {\ static pstring strings() {\

View File

@ -5,8 +5,8 @@
#include "pfmtlog.h" #include "pfmtlog.h"
#include <cfenv> #include <cfenv>
#include <iostream>
#include <cfloat> #include <cfloat>
#include <iostream>
#if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__) #if (defined(__x86_64__) || defined(__i386__)) && defined(__linux__)
#define HAS_FEENABLE_EXCEPT (1) #define HAS_FEENABLE_EXCEPT (1)

View File

@ -92,7 +92,7 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec)
// a.b format here ... // a.b format here ...
char32_t pend(0); char32_t pend(0);
int width(0); int width(0);
if (fmt != "" && pstring("duxofge").find(static_cast<pstring::value_type>(cfmt_spec)) != pstring::npos) if (!fmt.empty() && pstring("duxofge").find(static_cast<pstring::value_type>(cfmt_spec)) != pstring::npos)
{ {
pend = static_cast<char32_t>(fmt.at(fmt.size() - 1)); pend = static_cast<char32_t>(fmt.at(fmt.size() - 1));
if (pstring("duxofge").find(static_cast<pstring::value_type>(pend)) == pstring::npos) if (pstring("duxofge").find(static_cast<pstring::value_type>(pend)) == pstring::npos)
@ -113,7 +113,7 @@ pfmt::rtype pfmt::setfmt(std::stringstream &strm, char32_t cfmt_spec)
strm << std::setprecision(pstonum_ne_def<int>(fmt.substr(pdot + 1), 6)); strm << std::setprecision(pstonum_ne_def<int>(fmt.substr(pdot + 1), 6));
width = pstonum_ne_def<int>(left(fmt,pdot), 0); width = pstonum_ne_def<int>(left(fmt,pdot), 0);
} }
else if (fmt != "") else if (!fmt.empty())
width = pstonum_ne_def<int>(fmt, 0); width = pstonum_ne_def<int>(fmt, 0);
auto aw(plib::abs(width)); auto aw(plib::abs(width));

View File

@ -55,7 +55,7 @@ namespace plib {
static char32_t fmt_spec() { return 'f'; } static char32_t fmt_spec() { return 'f'; }
static inline void streamify(std::ostream &s, const FLOAT128 &v) static inline void streamify(std::ostream &s, const FLOAT128 &v)
{ {
s << static_cast<long double>(v); s << narrow_cast<long double>(v);
} }
}; };
#endif #endif
@ -322,7 +322,7 @@ namespace plib {
if (build_enabled && enabled && m_enabled) if (build_enabled && enabled && m_enabled)
{ {
pfmt pf(fmt); pfmt pf(fmt);
static_cast<T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); dynamic_cast<T &>(*this).vdowrite(xlog(pf, std::forward<Args>(args)...));
} }
} }
@ -332,7 +332,7 @@ namespace plib {
if (build_enabled && m_enabled) if (build_enabled && m_enabled)
{ {
pfmt pf(fmt); pfmt pf(fmt);
static_cast<const T *>(this)->vdowrite(xlog(pf, std::forward<Args>(args)...)); static_cast<const T &>(*this).vdowrite(xlog(pf, std::forward<Args>(args)...));
} }
} }

View File

@ -25,26 +25,26 @@ namespace plib {
{ {
static std::map<pstring, F> units_si_stat = static std::map<pstring, F> units_si_stat =
{ {
//{ "Y", static_cast<F>(1e24) }, // NOLINT: Yotta //{ "Y", narrow_cast<F>(1e24) }, // NOLINT: Yotta
//{ "Z", static_cast<F>(1e21) }, // NOLINT: Zetta //{ "Z", narrow_cast<F>(1e21) }, // NOLINT: Zetta
//{ "E", static_cast<F>(1e18) }, // NOLINT: Exa //{ "E", narrow_cast<F>(1e18) }, // NOLINT: Exa
{ "P", static_cast<F>(1e15) }, // NOLINT: Peta { "P", narrow_cast<F>(1e15) }, // NOLINT: Peta
{ "T", static_cast<F>(1e12) }, // NOLINT: Tera { "T", narrow_cast<F>(1e12) }, // NOLINT: Tera
{ "G", static_cast<F>( 1e9) }, // NOLINT: Giga { "G", narrow_cast<F>( 1e9) }, // NOLINT: Giga
{ "M", static_cast<F>( 1e6) }, // NOLINT: Mega { "M", narrow_cast<F>( 1e6) }, // NOLINT: Mega
{ "k", static_cast<F>( 1e3) }, // NOLINT: Kilo { "k", narrow_cast<F>( 1e3) }, // NOLINT: Kilo
{ "h", static_cast<F>( 1e2) }, // NOLINT: Hekto { "h", narrow_cast<F>( 1e2) }, // NOLINT: Hekto
//{ "da", static_cast<F>(1e1) }, // NOLINT: Deka //{ "da", narrow_cast<F>(1e1) }, // NOLINT: Deka
{ "d", static_cast<F>(1e-1) }, // NOLINT: Dezi { "d", narrow_cast<F>(1e-1) }, // NOLINT: Dezi
{ "c", static_cast<F>(1e-2) }, // NOLINT: Zenti { "c", narrow_cast<F>(1e-2) }, // NOLINT: Zenti
{ "m", static_cast<F>(1e-3) }, // NOLINT: Milli { "m", narrow_cast<F>(1e-3) }, // NOLINT: Milli
{ "μ", static_cast<F>(1e-6) }, // NOLINT: Mikro { "μ", narrow_cast<F>(1e-6) }, // NOLINT: Mikro
{ "n", static_cast<F>(1e-9) }, // NOLINT: Nano { "n", narrow_cast<F>(1e-9) }, // NOLINT: Nano
{ "p", static_cast<F>(1e-12) }, // NOLINT: Piko { "p", narrow_cast<F>(1e-12) }, // NOLINT: Piko
{ "f", static_cast<F>(1e-15) }, // NOLINT: Femto { "f", narrow_cast<F>(1e-15) }, // NOLINT: Femto
{ "a", static_cast<F>(1e-18) }, // NOLINT: Atto { "a", narrow_cast<F>(1e-18) }, // NOLINT: Atto
{ "z", static_cast<F>(1e-21) }, // NOLINT: Zepto { "z", narrow_cast<F>(1e-21) }, // NOLINT: Zepto
{ "y", static_cast<F>(1e-24) }, // NOLINT: Yokto { "y", narrow_cast<F>(1e-24) }, // NOLINT: Yokto
}; };
return units_si_stat; return units_si_stat;
} }
@ -105,7 +105,7 @@ namespace plib {
if (inputs[i] == cmd) if (inputs[i] == cmd)
{ {
rc.m_cmd = PUSH_INPUT; rc.m_cmd = PUSH_INPUT;
rc.m_param = static_cast<NT>(i); rc.m_param = narrow_cast<NT>(i);
stk += 1; stk += 1;
break; break;
} }
@ -128,7 +128,7 @@ namespace plib {
} }
if (stk < 1) if (stk < 1)
throw pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr)); throw pexception(plib::pfmt("pfunction: stack underflow on token <{1}> in <{2}>")(cmd)(expr));
if (stk >= static_cast<int>(MAX_STACK)) if (stk >= narrow_cast<int>(MAX_STACK))
throw pexception(plib::pfmt("pfunction: stack overflow on token <{1}> in <{2}>")(cmd)(expr)); throw pexception(plib::pfmt("pfunction: stack overflow on token <{1}> in <{2}>")(cmd)(expr));
m_precompiled.push_back(rc); m_precompiled.push_back(rc);
} }
@ -286,7 +286,7 @@ namespace plib {
lfsr >>= 1; lfsr >>= 1;
if (lsb) if (lsb)
lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10 lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10
return static_cast<NT>(lfsr) / static_cast<NT>(0xffffU); // NOLINT return narrow_cast<NT>(lfsr) / narrow_cast<NT>(0xffffU); // NOLINT
} }
template <typename NT> template <typename NT>
@ -297,7 +297,7 @@ namespace plib {
lfsr >>= 1; lfsr >>= 1;
if (lsb) if (lsb)
lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10 lfsr ^= 0xB400U; // NOLINT: taps 15, 13, 12, 10
return static_cast<NT>(lfsr); return narrow_cast<NT>(lfsr);
} }
#define ST1 stack[ptr] #define ST1 stack[ptr]
@ -333,7 +333,7 @@ namespace plib {
stack[ptr++] = lfsr_random<value_type>(m_lfsr); stack[ptr++] = lfsr_random<value_type>(m_lfsr);
break; break;
case PUSH_INPUT: case PUSH_INPUT:
stack[ptr++] = values[static_cast<unsigned>(rc.m_param)]; stack[ptr++] = values[narrow_cast<unsigned>(rc.m_param)];
break; break;
case PUSH_CONST: case PUSH_CONST:
stack[ptr++] = rc.m_param; stack[ptr++] = rc.m_param;

105
src/lib/netlist/plib/pgsl.h Normal file
View File

@ -0,0 +1,105 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#ifndef PGSL_H_
#define PGSL_H_
///
/// \file pgsl.h
///
/// This core guidelines gsl implementation currently provides only enough
/// functionality to syntactically support a very limited number of the
/// gsl specification.
///
/// Going forward this approach may be extended.
///
#include "pconfig.h"
#include "pexception.h"
#include "ptypes.h"
#include <exception>
#include <type_traits>
#include <utility>
#if defined(__has_builtin) // clang and gcc 10
#if __has_builtin(__builtin_unreachable)
#define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable())
#endif
#elif defined(__GNUC__) && !(defined( __CUDACC__ ) && defined( __CUDA_ARCH__ ))
#define gsl_Expects(e) ((e) ? static_cast<void>(0) : __builtin_unreachable())
#elif defined(_MSC_VER)
#define gsl_Expects(e) __assume(e)
#else
#define gsl_Expects(e) ((e) ? static_cast<void>(0) : static_cast<void>(0))
#endif
#undef gsl_Expects
#define gsl_Expects(e) do {} while (0)
#define gsl_Ensures(e) gsl_Expects(e)
namespace plib {
namespace pgsl {
struct narrowing_error : public std::exception {};
template <typename T>
using owner = T;
template <typename T>
using not_null = T;
/// \brief perform a narrowing cast without checks
///
template <typename T, typename O>
inline constexpr T narrow_cast(O && v) noexcept
{
static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types");
return static_cast<T>(std::forward<O>(v));
}
/// \brief perform a narrowing cast terminating if loss of precision
///
/// The c++ core guidelines require the narrow function to raise an error
/// This will make narrow noexcept(false). This has shown to have a
/// measurable impact on performance and thus we deviate we deviate from
/// the standard here.
///
template <typename T, typename O>
inline T narrow(O && v) noexcept
{
static_assert(plib::is_arithmetic<T>::value && std::is_convertible<std::remove_reference_t<O>, T>::value, "narrow cast expects conversion between arithmetic types");
const auto val = static_cast<T>(std::forward<O>(v));
if( v == static_cast<std::remove_reference_t<O>>(val))
{
return val;
}
plib::terminate("narrowing_error");
// throw narrowing_error();
}
} // namespace pgsl
/// \brief downcast from base tpye to derived type
///
/// The cpp core guidelines require a very careful use of static cast
/// for downcast operations. This template is used to identify these uses
/// and later for debug builds use dynamic_cast.
///
template <typename D, typename B>
inline constexpr D downcast(B && b) noexcept
{
static_assert(std::is_pointer<D>::value || std::is_reference<D>::value, "downcast only supports pointers or reference for derived");
static_assert(std::is_pointer<B>::value || std::is_reference<B>::value, "downcast only supports pointers or reference for base");
return static_cast<D>(std::forward<B>(b));
}
using pgsl::narrow_cast;
} // namespace plib
//FIXME: This is the place to use more complete implementations
namespace gsl = plib::pgsl;
#endif // PGSL_H_

View File

@ -62,11 +62,13 @@ namespace plib {
reference operator[](size_type index) noexcept reference operator[](size_type index) noexcept
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return reinterpret_cast<reference>(m_buf[index]); return reinterpret_cast<reference>(m_buf[index]);
} }
constexpr const_reference operator[](size_type index) const noexcept constexpr const_reference operator[](size_type index) const noexcept
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return reinterpret_cast<const_reference>(m_buf[index]); return reinterpret_cast<const_reference>(m_buf[index]);
} }
@ -78,13 +80,19 @@ namespace plib {
new (&m_buf[index]) C(std::forward<Args>(args)...); new (&m_buf[index]) C(std::forward<Args>(args)...);
} }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); } iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); } iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); } iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); } iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); } const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); }
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); } const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); }
protected: protected:

View File

@ -29,8 +29,8 @@ namespace plib {
int app::main_utfX(int argc, char *argv[]) int app::main_utfX(int argc, char *argv[])
{ {
std::vector<putf8string> arg; std::vector<putf8string> arg;
for (std::size_t i = 0; i < static_cast<std::size_t>(argc); i++) for (std::size_t i = 0; i < narrow_cast<std::size_t>(argc); i++)
arg.push_back(putf8string(argv[i])); arg.emplace_back(putf8string(argv[i]));
return main_utfX(arg); return main_utfX(arg);
} }
@ -38,8 +38,8 @@ namespace plib {
int app::main_utfX(int argc, wchar_t *argv[]) int app::main_utfX(int argc, wchar_t *argv[])
{ {
std::vector<putf8string> arg; std::vector<putf8string> arg;
for (std::size_t i = 0; i < static_cast<std::size_t>(argc); i++) for (std::size_t i = 0; i < narrow_cast<std::size_t>(argc); i++)
arg.push_back(putf8string(pwstring(argv[i]))); arg.emplace_back(putf8string(pwstring(argv[i])));
return main_utfX(arg); return main_utfX(arg);
} }

View File

@ -15,9 +15,7 @@
#include <cmath> #include <cmath>
#include <type_traits> #include <type_traits>
#if (PUSE_FLOAT128) // quadmath.h included by ptypes.h
#include <quadmath.h>
#endif
namespace plib namespace plib
{ {

164
src/lib/netlist/plib/pmatrix2d.h Normal file → Executable file
View File

@ -17,51 +17,182 @@
namespace plib namespace plib
{ {
template<typename T, typename A = aligned_allocator<T>> template<typename T, typename A = aligned_arena>
class pmatrix2d class pmatrix2d
{ {
public: public:
using size_type = std::size_t; using size_type = std::size_t;
using value_type = T; using arena_type = A;
using allocator_type = A; using allocator_type = typename A::template allocator_type<T>;
static constexpr const size_type align_size = align_traits<allocator_type>::align_size;
static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size;
using value_type = T;
using reference = T &;
using const_reference = const T &;
using pointer = T *;
using const_pointer = const T *;
static constexpr const size_type align_size = align_traits<A>::align_size;
static constexpr const size_type stride_size = align_traits<A>::stride_size;
pmatrix2d() noexcept pmatrix2d() noexcept
: m_N(0), m_M(0), m_stride(8), m_v() : m_N(0), m_M(0), m_stride(8), m_v(nullptr)
{ {
} }
pmatrix2d(size_type N, size_type M) pmatrix2d(size_type N, size_type M)
: m_N(N), m_M(M), m_v() : m_N(N), m_M(M), m_v()
{ {
gsl_Expects(N>0);
gsl_Expects(M>0);
m_stride = ((M + stride_size-1) / stride_size) * stride_size; m_stride = ((M + stride_size-1) / stride_size) * stride_size;
m_v.resize(N * m_stride); m_v = m_a.allocate(N * m_stride);
for (std::size_t i = 0; i < N * m_stride; i++)
::new(&m_v[i]) T();
}
~pmatrix2d()
{
if (m_v != nullptr)
{
for (std::size_t i = 0; i < m_N * m_stride; i++)
(&m_v[i])->~T();
m_a.deallocate(m_v, m_N * m_stride);
}
}
void resize(size_type N, size_type M)
{
gsl_Expects(N>0);
gsl_Expects(M>0);
if (m_v != nullptr)
{
for (std::size_t i = 0; i < N * m_stride; i++)
(&m_v[i])->~T();
m_a.deallocate(m_v, N * m_stride);
}
m_N = N;
m_M = M;
m_stride = ((M + stride_size-1) / stride_size) * stride_size;
m_v = m_a.allocate(N * m_stride);
for (std::size_t i = 0; i < N * m_stride; i++)
::new(&m_v[i]) T();
}
constexpr pointer operator[] (size_type row) noexcept
{
return &m_v[m_stride * row];
}
constexpr const_pointer operator[] (size_type row) const noexcept
{
return &m_v[m_stride * row];
}
reference operator()(size_type r, size_type c) noexcept
{
return (*this)[r][c];
}
const_reference operator()(size_type r, size_type c) const noexcept
{
return (*this)[r][c];
}
// for compatibility with vrl variant
void set(size_type r, size_type c, const value_type &v) noexcept
{
(*this)[r][c] = v;
}
pointer data() noexcept
{
return m_v;
}
const_pointer data() const noexcept
{
return m_v;
}
size_type didx(size_type r, size_type c) const noexcept
{
return m_stride * r + c;
}
private:
size_type m_N;
size_type m_M;
size_type m_stride;
T * __restrict m_v;
allocator_type m_a;
};
// variable row length matrix
template<typename T, typename A = aligned_arena>
class pmatrix2d_vrl
{
public:
using size_type = std::size_t;
using value_type = T;
using arena_type = A;
using allocator_type = typename A::template allocator_type<T>;
static constexpr const size_type align_size = align_traits<allocator_type>::align_size;
static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size;
pmatrix2d_vrl() noexcept
: m_N(0), m_M(0), m_v()
{
}
pmatrix2d_vrl(size_type N, size_type M)
: m_N(N), m_M(M), m_v()
{
m_row.resize(N + 1, 0);
m_v.resize(N); //FIXME
} }
void resize(size_type N, size_type M) void resize(size_type N, size_type M)
{ {
m_N = N; m_N = N;
m_M = M; m_M = M;
m_stride = ((M + stride_size-1) / stride_size) * stride_size; m_row.resize(N + 1);
m_v.resize(N * m_stride); for (std::size_t i = 0; i < m_N; i++)
m_row[i] = 0;
m_v.resize(N); //FIXME
} }
constexpr T * operator[] (size_type row) noexcept constexpr T * operator[] (size_type row) noexcept
{ {
return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]); return &(m_v[m_row[row]]);
} }
constexpr const T * operator[] (size_type row) const noexcept constexpr const T * operator[] (size_type row) const noexcept
{ {
return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]); return &(m_v[m_row[row]]);
} }
//FIXME: no check!
T & operator()(size_type r, size_type c) noexcept T & operator()(size_type r, size_type c) noexcept
{ {
return (*this)[r][c]; return (*this)[r][c];
} }
void set(size_type r, size_type c, const T &v) noexcept
{
if (c + m_row[r] >= m_row[r + 1])
{
m_v.insert(m_v.begin() + narrow_cast<std::ptrdiff_t>(m_row[r+1]), v);
for (size_type i = r + 1; i <= m_N; i++)
m_row[i] = m_row[i] + 1;
}
else
(*this)[r][c] = v;
}
//FIXME: no check!
const T & operator()(size_type r, size_type c) const noexcept const T & operator()(size_type r, size_type c) const noexcept
{ {
return (*this)[r][c]; return (*this)[r][c];
@ -77,19 +208,22 @@ namespace plib
return m_v.data(); return m_v.data();
} }
//FIXME: no check!
size_type didx(size_type r, size_type c) const noexcept size_type didx(size_type r, size_type c) const noexcept
{ {
return m_stride * r + c; return m_row[r] + c;
} }
std::size_t tx() const { return m_v.size(); }
private: private:
size_type m_N; size_type m_N;
size_type m_M; size_type m_M;
size_type m_stride; std::vector<size_type, typename A::template allocator_type<size_type>> m_row;
std::vector<T, allocator_type> m_v;
std::vector<T, A> m_v;
}; };
} // namespace plib } // namespace plib
#endif // PMATRIX2D_H_ #endif // PMATRIX2D_H_

View File

@ -40,31 +40,26 @@ namespace plib {
mempool_arena(size_t min_alloc = (1<<21), size_t min_align = PALIGN_CACHELINE) mempool_arena(size_t min_alloc = (1<<21), size_t min_align = PALIGN_CACHELINE)
: m_min_alloc(min_alloc) : m_min_alloc(min_alloc)
, m_min_align(min_align) , m_min_align(min_align)
, m_block_align(1024)
, m_blocks(base_allocator_type<block *>(m_arena)) , m_blocks(base_allocator_type<block *>(m_arena))
{ {
icount()++;
} }
PCOPYASSIGNMOVE(mempool_arena, delete) PCOPYASSIGNMOVE(mempool_arena, delete)
~mempool_arena() ~mempool_arena()
{ {
for (auto & b : m_blocks) for (auto & b : m_blocks)
{ {
if (b->m_num_alloc != 0) if (b->m_num_alloc != 0)
{ {
plib::perrlogger("Found {} info blocks\n", sinfo().size()); plib::perrlogger("Found {} info blocks\n", m_info.size());
plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc); plib::perrlogger("Found block with {} dangling allocations\n", b->m_num_alloc);
} }
m_arena.free(b); detail::free(m_arena, b);
//::operator delete(b->m_data);
}
if (icount()-- == 1)
{
if (!sinfo().empty())
plib::perrlogger("Still found {} info blocks after last mempool deleted\n", sinfo().size());
} }
if (!m_info.empty())
plib::perrlogger("Still found {} info blocks after mempool deleted\n", m_info.size());
} }
void *allocate(size_t align, size_t size) void *allocate(size_t align, size_t size)
@ -92,21 +87,18 @@ namespace plib {
void *ret = reinterpret_cast<void *>(b->m_data + b->m_cur); void *ret = reinterpret_cast<void *>(b->m_data + b->m_cur);
auto capacity(rs); auto capacity(rs);
ret = std::align(align, size, ret, capacity); ret = std::align(align, size, ret, capacity);
sinfo().insert({ ret, info(b, b->m_cur)}); m_info.insert({ ret, info(b, b->m_cur)});
rs -= (capacity - size); rs -= (capacity - size);
b->m_cur += rs; b->m_cur += rs;
base_type::m_stat_cur_alloc() += size; this->inc_alloc_stat(size);
if (base_type::m_stat_max_alloc() < base_type::m_stat_cur_alloc())
base_type::m_stat_max_alloc() = base_type::m_stat_cur_alloc();
return ret; return ret;
} }
/*static */ void deallocate(void *ptr, size_t size) noexcept void deallocate(void *ptr, size_t size) noexcept
{ {
auto it = m_info.find(ptr);
auto it = sinfo().find(ptr); if (it == m_info.end())
if (it == sinfo().end())
plib::terminate("mempool::free - pointer not found"); plib::terminate("mempool::free - pointer not found");
block *b = it->second.m_block; block *b = it->second.m_block;
if (b->m_num_alloc == 0) if (b->m_num_alloc == 0)
@ -115,7 +107,7 @@ namespace plib {
{ {
mempool_arena &mp = b->m_mempool; mempool_arena &mp = b->m_mempool;
b->m_num_alloc--; b->m_num_alloc--;
mp.m_stat_cur_alloc() -= size; mp.dec_alloc_stat(size);
if (b->m_num_alloc == 0) if (b->m_num_alloc == 0)
{ {
auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b); auto itb = std::find(mp.m_blocks.begin(), mp.m_blocks.end(), b);
@ -123,14 +115,15 @@ namespace plib {
plib::terminate("mempool::free - block not found"); plib::terminate("mempool::free - block not found");
mp.m_blocks.erase(itb); mp.m_blocks.erase(itb);
m_arena.free(b); detail::free(mp.base_arena(), b);
} }
sinfo().erase(it); m_info.erase(it);
} }
} }
bool operator ==(const mempool_arena &rhs) const noexcept { return this == &rhs; } bool operator ==(const mempool_arena &rhs) const noexcept { return this == &rhs; }
BASEARENA &base_arena() noexcept { return m_arena; }
private: private:
struct block struct block
{ {
@ -142,17 +135,19 @@ namespace plib {
{ {
min_bytes = std::max(mp.m_min_alloc, min_bytes); min_bytes = std::max(mp.m_min_alloc, min_bytes);
m_free = min_bytes; m_free = min_bytes;
size_type alloc_bytes = (min_bytes + mp.m_min_align); // - 1); // & ~(mp.m_min_align - 1); m_bytes_allocated = (min_bytes + mp.m_block_align); // - 1); // & ~(mp.m_min_align - 1);
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
m_data_allocated = new std::uint8_t[alloc_bytes]; //m_data_allocated = new std::uint8_t[alloc_bytes];
m_data_allocated = static_cast<std::uint8_t *>(mp.base_arena().allocate(mp.m_block_align, m_bytes_allocated));
void *r = m_data_allocated; void *r = m_data_allocated;
std::align(mp.m_min_align, min_bytes, r, alloc_bytes); std::align(mp.m_block_align, min_bytes, r, m_bytes_allocated);
m_data = reinterpret_cast<std::uint8_t *>(r); m_data = reinterpret_cast<std::uint8_t *>(r);
} }
~block() ~block()
{ {
//::operator delete(m_data_allocated); //::operator delete(m_data_allocated);
delete [] m_data_allocated; //delete [] m_data_allocated;
m_mempool.base_arena().deallocate(m_data_allocated, m_bytes_allocated);
} }
block(const block &) = delete; block(const block &) = delete;
@ -163,6 +158,7 @@ namespace plib {
size_type m_num_alloc; size_type m_num_alloc;
size_type m_free; size_type m_free;
size_type m_cur; size_type m_cur;
size_type m_bytes_allocated;
std::uint8_t *m_data; std::uint8_t *m_data;
std::uint8_t *m_data_allocated; std::uint8_t *m_data_allocated;
mempool_arena &m_mempool; mempool_arena &m_mempool;
@ -180,27 +176,20 @@ namespace plib {
block * new_block(size_type min_bytes) block * new_block(size_type min_bytes)
{ {
auto *b = m_arena.template alloc<block>(*this, min_bytes); auto *b = detail::alloc<block>(m_arena, *this, min_bytes);
m_blocks.push_back(b); m_blocks.push_back(b);
return b; return b;
} }
static std::unordered_map<void *, info> &sinfo()
{
static std::unordered_map<void *, info> spinfo;
return spinfo;
}
static std::size_t &icount()
{
static std::size_t count = 0;
return count;
}
size_t m_min_alloc; size_t m_min_alloc;
size_t m_min_align; size_t m_min_align;
size_t m_block_align;
BASEARENA m_arena; BASEARENA m_arena;
using base_allocator_typex = typename BASEARENA::template allocator_type<std::pair<void * const, info>>;
std::unordered_map<void *, info, std::hash<void *>, std::equal_to<void *>,
base_allocator_typex> m_info;
// std::unordered_map<void *, info> m_info;
std::vector<block *, typename BASEARENA::template allocator_type<block *>> m_blocks; std::vector<block *, typename BASEARENA::template allocator_type<block *>> m_blocks;
}; };

View File

@ -68,7 +68,7 @@ namespace plib {
auto *o = dynamic_cast<option *>(opt); auto *o = dynamic_cast<option *>(opt);
if (o != nullptr) if (o != nullptr)
{ {
if (o->short_opt() == "" && o->long_opt() == "") if (o->short_opt().empty() && o->long_opt().empty())
{ {
auto *ov = dynamic_cast<option_args *>(o); auto *ov = dynamic_cast<option_args *>(o);
if (ov != nullptr) if (ov != nullptr)
@ -103,7 +103,7 @@ namespace plib {
if (!seen_other_args && plib::startsWith(arg, "--")) if (!seen_other_args && plib::startsWith(arg, "--"))
{ {
auto v = psplit(arg.substr(2),"="); auto v = psplit(arg.substr(2),"=");
if (!v.empty() && v[0] != "") if (!v.empty() && !v[0].empty())
{ {
opt = getopt_long(v[0]); opt = getopt_long(v[0]);
has_equal_arg = (v.size() > 1); has_equal_arg = (v.size() > 1);
@ -210,11 +210,11 @@ namespace plib {
if (auto * const opt = dynamic_cast<option *>(optbase)) if (auto * const opt = dynamic_cast<option *>(optbase))
{ {
pstring line = ""; pstring line = "";
if (opt->short_opt() != "") if (!opt->short_opt().empty())
line += " -" + opt->short_opt(); line += " -" + opt->short_opt();
if (opt->long_opt() != "") if (!opt->long_opt().empty())
{ {
if (line != "") if (!line.empty())
line += ", "; line += ", ";
else else
line = " "; line = " ";
@ -248,7 +248,8 @@ namespace plib {
else if (auto *grp = dynamic_cast<option_group *>(optbase)) else if (auto *grp = dynamic_cast<option_group *>(optbase))
{ {
ret += "\n" + grp->group() + ":\n"; ret += "\n" + grp->group() + ":\n";
if (grp->help() != "") ret += split_paragraphs(grp->help(), width, 4, 4) + "\n\n"; if (!grp->help().empty())
ret += split_paragraphs(grp->help(), width, 4, 4) + "\n\n";
} }
} }
// FIXME: other help ... // FIXME: other help ...
@ -274,7 +275,7 @@ namespace plib {
for (const auto & optbase : m_opts) for (const auto & optbase : m_opts)
{ {
auto *opt = dynamic_cast<option *>(optbase); auto *opt = dynamic_cast<option *>(optbase);
if (opt != nullptr && arg != "" && opt->short_opt() == arg) if (opt != nullptr && !arg.empty() && opt->short_opt() == arg)
return opt; return opt;
} }
return nullptr; return nullptr;
@ -284,7 +285,7 @@ namespace plib {
for (const auto & optbase : m_opts) for (const auto & optbase : m_opts)
{ {
auto *opt = dynamic_cast<option *>(optbase); auto *opt = dynamic_cast<option *>(optbase);
if (opt != nullptr && arg !="" && opt->long_opt() == arg) if (opt != nullptr && !arg.empty() && opt->long_opt() == arg)
return opt; return opt;
} }
return nullptr; return nullptr;

View File

@ -136,7 +136,7 @@ namespace plib {
if (raw != plib::container::npos) if (raw != plib::container::npos)
{ {
m_val = static_cast<T>(raw); m_val = narrow_cast<T>(raw);
return 0; return 0;
} }

View File

@ -159,32 +159,43 @@ namespace plib {
if (PMFINTERNAL == 1) if (PMFINTERNAL == 1)
{ {
// apply the "this" delta to the object first // apply the "this" delta to the object first
// NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult) // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult,cppcoreguidelines-pro-type-reinterpret-cast)
generic_class *o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); generic_class *o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// if the low bit of the vtable index is clear, then it is just a raw function pointer // if the low bit of the vtable index is clear, then it is just a raw function pointer
if ((m_function & 1) == 0) if ((m_function & 1) == 0)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(m_function); func = reinterpret_cast<generic_function>(m_function);
}
else else
{ {
// otherwise, it is the byte index into the vtable where the actual function lives // otherwise, it is the byte index into the vtable where the actual function lives
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta); std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(o_p_delta);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1); func = *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
} }
object = o_p_delta; object = o_p_delta;
} }
else if (PMFINTERNAL == 2) else if (PMFINTERNAL == 2)
{ {
if ((m_this_delta & 1) == 0) { if ((m_this_delta & 1) == 0)
{
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(m_function); func = reinterpret_cast<generic_function>(m_function);
} }
else else
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object)); object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object));
// otherwise, it is the byte index into the vtable where the actual function lives // otherwise, it is the byte index into the vtable where the actual function lives
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object); std::uint8_t *vtable_base = *reinterpret_cast<std::uint8_t **>(object);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1); func = *reinterpret_cast<generic_function *>(vtable_base + m_function + m_this_delta - 1);
} }
} }
@ -192,8 +203,10 @@ namespace plib {
{ {
const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)()); const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (generic_class::*)());
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
func = reinterpret_cast<generic_function>(m_function); func = reinterpret_cast<generic_function>(m_function);
if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int)) if (m_size == SINGLE_MEMFUNCPTR_SIZE + sizeof(int))
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta); object = reinterpret_cast<generic_class *>(reinterpret_cast<std::uint8_t *>(object) + m_this_delta);
} }
} }
@ -231,8 +244,10 @@ namespace plib {
{ {
raw_type mfpo(mftp); raw_type mfpo(mftp);
generic_function_storage rfunc(nullptr); generic_function_storage rfunc(nullptr);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto *robject = reinterpret_cast<generic_class *>(object); auto *robject = reinterpret_cast<generic_class *>(object);
mfpo.convert_to_generic(rfunc, robject); mfpo.convert_to_generic(rfunc, robject);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return std::make_pair(reinterpret_cast<FunctionType>(rfunc), reinterpret_cast<ObjectType *>(robject)); return std::make_pair(reinterpret_cast<FunctionType>(rfunc), reinterpret_cast<ObjectType *>(robject));
} }
template<typename O> template<typename O>
@ -259,6 +274,7 @@ namespace plib {
template<typename FunctionType, typename MemberFunctionType, typename ObjectType> template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object) static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return std::make_pair(reinterpret_cast<FunctionType>(mftp), reinterpret_cast<ObjectType *>(object)); return std::make_pair(reinterpret_cast<FunctionType>(mftp), reinterpret_cast<ObjectType *>(object));
} }
@ -286,6 +302,7 @@ namespace plib {
template<typename FunctionType, typename MemberFunctionType, typename ObjectType> template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object) static std::pair<FunctionType, ObjectType *> get(MemberFunctionType mftp, ObjectType *object)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return std::make_pair(reinterpret_cast<FunctionType>(object->*mftp), reinterpret_cast<ObjectType *>(object)); return std::make_pair(reinterpret_cast<FunctionType>(object->*mftp), reinterpret_cast<ObjectType *>(object));
} }
template<typename O> template<typename O>
@ -315,6 +332,7 @@ namespace plib {
pmfp_base() pmfp_base()
: m_obj(nullptr) : m_obj(nullptr)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved); auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved);
std::fill(s, s + sizeof(m_resolved), 0); std::fill(s, s + sizeof(m_resolved), 0);
} }
@ -323,6 +341,7 @@ namespace plib {
pmfp_base(specific_member_function<O> mftp, O *object) pmfp_base(specific_member_function<O> mftp, O *object)
: m_obj(nullptr) : m_obj(nullptr)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved); auto *s = reinterpret_cast<std::uint8_t *>(&m_resolved);
std::fill(s, s + sizeof(m_resolved), 0); std::fill(s, s + sizeof(m_resolved), 0);
bind(object, &mftp); bind(object, &mftp);
@ -351,6 +370,7 @@ namespace plib {
//auto pFunc = *reinterpret_cast<specific_member_function<O> *>(fraw); // mftp; //auto pFunc = *reinterpret_cast<specific_member_function<O> *>(fraw); // mftp;
specific_member_function<O> pFunc; specific_member_function<O> pFunc;
static_assert(sizeof(pFunc) >= sizeof(MF), "size error"); static_assert(sizeof(pFunc) >= sizeof(MF), "size error");
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
*reinterpret_cast<MF *>(&pFunc) = *fraw; *reinterpret_cast<MF *>(&pFunc) = *fraw;
auto r = helper::template get<member_abi_function<O>>(pFunc, object); auto r = helper::template get<member_abi_function<O>>(pFunc, object);
@ -360,18 +380,21 @@ namespace plib {
//*reinterpret_cast<member_abi_function<O> *>(&m_resolved) = r.first; //*reinterpret_cast<member_abi_function<O> *>(&m_resolved) = r.first;
reinterpret_copy(r.first, m_resolved); reinterpret_copy(r.first, m_resolved);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
m_obj = reinterpret_cast<generic_class *>(r.second); m_obj = reinterpret_cast<generic_class *>(r.second);
} }
template<typename O> template<typename O>
R call(O *obj, Targs&&... args) const noexcept(true) R call(O *obj, Targs&&... args) const noexcept(true)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return helper::call(reinterpret_cast<member_abi_function<O> *>(&m_resolved), return helper::call(reinterpret_cast<member_abi_function<O> *>(&m_resolved),
obj, std::forward<Targs>(args)...); obj, std::forward<Targs>(args)...);
} }
R call(Targs&&... args) const noexcept(true) R call(Targs&&... args) const noexcept(true)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return helper::call(reinterpret_cast<const member_abi_function<generic_class> *>(&m_resolved), return helper::call(reinterpret_cast<const member_abi_function<generic_class> *>(&m_resolved),
m_obj, std::forward<Targs>(args)...); m_obj, std::forward<Targs>(args)...);
} }
@ -414,12 +437,13 @@ namespace plib {
using static_creator = return_type (*)(const generic_member_function *, generic_class *); using static_creator = return_type (*)(const generic_member_function *, generic_class *);
late_pmfp() {} late_pmfp() = default;
template<typename O> template<typename O>
late_pmfp(specific_member_function<O> mftp) late_pmfp(specific_member_function<O> mftp)
{ {
static_assert(sizeof(m_raw) >= sizeof(specific_member_function<O>), "size issue"); static_assert(sizeof(m_raw) >= sizeof(specific_member_function<O>), "size issue");
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
*reinterpret_cast<specific_member_function<O> *>(&m_raw) = mftp; *reinterpret_cast<specific_member_function<O> *>(&m_raw) = mftp;
m_creator = creator<O>; m_creator = creator<O>;
} }
@ -427,6 +451,7 @@ namespace plib {
template<typename O> template<typename O>
return_type operator()(O *object) const return_type operator()(O *object) const
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return m_creator(&m_raw, reinterpret_cast<generic_class *>(object)); return m_creator(&m_raw, reinterpret_cast<generic_class *>(object));
} }
@ -435,7 +460,9 @@ namespace plib {
template <typename O> template <typename O>
static return_type creator(const generic_member_function *raw, generic_class *obj) static return_type creator(const generic_member_function *raw, generic_class *obj)
{ {
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto p = reinterpret_cast<const specific_member_function<O> *>(raw); auto p = reinterpret_cast<const specific_member_function<O> *>(raw);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto o = reinterpret_cast<O *>(obj); auto o = reinterpret_cast<O *>(obj);
return return_type(*p, o); return return_type(*p, o);
} }

View File

@ -461,7 +461,7 @@ namespace plib {
m_if_level++; m_if_level++;
lt = replace_macros(lt); lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true)); simple_iter<ppreprocessor> t(this, tokenize(lt.substr(3), m_expr_sep, true, true));
auto val = static_cast<int>(prepro_expr(t, 255)); auto val = narrow_cast<int>(prepro_expr(t, 255));
t.skip_ws(); t.skip_ws();
if (!t.eod()) if (!t.eod())
error("found unprocessed content at end of line"); error("found unprocessed content at end of line");
@ -489,7 +489,7 @@ namespace plib {
m_if_flag ^= (1 << m_if_level); m_if_flag ^= (1 << m_if_level);
lt = replace_macros(lt); lt = replace_macros(lt);
simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true)); simple_iter<ppreprocessor> t(this, tokenize(lt.substr(5), m_expr_sep, true, true));
auto val = static_cast<int>(prepro_expr(t, 255)); auto val = narrow_cast<int>(prepro_expr(t, 255));
t.skip_ws(); t.skip_ws();
if (!t.eod()) if (!t.eod())
error("found unprocessed content at end of line"); error("found unprocessed content at end of line");
@ -559,7 +559,7 @@ namespace plib {
auto *prevdef = get_define(n); auto *prevdef = get_define(n);
if (lti.size() == 2) if (lti.size() == 2)
{ {
if (prevdef != nullptr && prevdef->m_replace != "") if (prevdef != nullptr && !prevdef->m_replace.empty())
error("redefinition of " + n); error("redefinition of " + n);
m_defines.insert({n, define_t(n, "")}); m_defines.insert({n, define_t(n, "")});
} }

View File

@ -95,14 +95,14 @@ namespace plib {
if (this->gptr() == this->egptr()) if (this->gptr() == this->egptr())
{ {
// clang reports sign error - weird // clang reports sign error - weird
std::size_t bytes = m_strm->m_outbuf.size() - static_cast<std::size_t>(m_strm->m_pos); std::size_t bytes = m_strm->m_outbuf.size() - narrow_cast<std::size_t>(m_strm->m_pos);
if (bytes > m_buf.size()) if (bytes > m_buf.size())
bytes = m_buf.size(); bytes = m_buf.size();
std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data()); std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data());
this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes); this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
m_strm->m_pos += static_cast<long>(bytes); m_strm->m_pos += narrow_cast<long>(bytes);
} }
return this->gptr() == this->egptr() return this->gptr() == this->egptr()

View File

@ -9,6 +9,7 @@
/// ///
#include "pconfig.h" #include "pconfig.h"
#include "pgsl.h"
#include "pmath.h" #include "pmath.h"
#include "ptypes.h" #include "ptypes.h"
@ -50,7 +51,7 @@ namespace plib
seed(5489); seed(5489);
} }
static constexpr T min() noexcept { return static_cast<T>(0); } static constexpr T min() noexcept { return T(0); }
static constexpr T max() noexcept { return ~T(0) >> (sizeof(T)*8 - w); } static constexpr T max() noexcept { return ~T(0) >> (sizeof(T)*8 - w); }
template <typename ST> template <typename ST>
@ -103,7 +104,7 @@ namespace plib
void twist() void twist()
{ {
const T lowest_w(~T(0) >> (sizeof(T)*8 - w)); const T lowest_w(~T(0) >> (sizeof(T)*8 - w));
const T lower_mask((static_cast<T>(1) << r) - 1); // That is, the binary number of r 1's const T lower_mask((T(1) << r) - 1); // That is, the binary number of r 1's
const T upper_mask((~lower_mask) & lowest_w); const T upper_mask((~lower_mask) & lowest_w);
for (std::size_t i=0; i<N; i++) for (std::size_t i=0; i<N; i++)
@ -122,10 +123,10 @@ namespace plib
template <typename FT, typename T> template <typename FT, typename T>
FT normalize_uniform(T &p, FT m = constants<FT>::one(), FT b = constants<FT>::zero()) FT normalize_uniform(T &p, FT m = constants<FT>::one(), FT b = constants<FT>::zero())
{ {
const auto mmin(static_cast<FT>(p.min())); const auto mmin(narrow_cast<FT>(p.min()));
const auto mmax(static_cast<FT>(p.max())); const auto mmax(narrow_cast<FT>(p.max()));
// -> 0 to a // -> 0 to a
return (static_cast<FT>(p())- mmin) / (mmax - mmin) * m - b; return (narrow_cast<FT>(p())- mmin) / (mmax - mmin) * m - b;
} }
template<typename FT> template<typename FT>

View File

@ -10,6 +10,7 @@
#include "pconfig.h" #include "pconfig.h"
#include "pexception.h" #include "pexception.h"
#include "pgsl.h"
#include "pmath.h" // for pstonum #include "pmath.h" // for pstonum
#include "pstring.h" #include "pstring.h"
@ -36,9 +37,9 @@ namespace plib
if (ss >> x) if (ss >> x)
{ {
auto pos(ss.tellg()); auto pos(ss.tellg());
if (pos == static_cast<decltype(pos)>(-1)) if (pos == decltype(pos)(-1))
pos = len; pos = len;
*idx = static_cast<std::size_t>(pos); *idx = narrow_cast<std::size_t>(pos);
} }
else else
*idx = constants<std::size_t>::zero(); *idx = constants<std::size_t>::zero();
@ -88,7 +89,7 @@ namespace plib
template <typename S> template <typename S>
FLOAT128 operator()(std::locale loc, const S &arg, std::size_t *idx) FLOAT128 operator()(std::locale loc, const S &arg, std::size_t *idx)
{ {
return static_cast<FLOAT128>(pstonum_locale<long double>(loc, arg, idx)); return narrow_cast<FLOAT128>(pstonum_locale<long double>(loc, arg, idx));
} }
}; };
#endif #endif
@ -100,8 +101,8 @@ namespace plib
std::size_t idx(0); std::size_t idx(0);
auto ret = pstonum_helper<T>()(loc, cstr, &idx); auto ret = pstonum_helper<T>()(loc, cstr, &idx);
using ret_type = decltype(ret); using ret_type = decltype(ret);
if (ret >= static_cast<ret_type>(plib::numeric_limits<T>::lowest()) if (ret >= narrow_cast<ret_type>(plib::numeric_limits<T>::lowest())
&& ret <= static_cast<ret_type>(plib::numeric_limits<T>::max())) && ret <= narrow_cast<ret_type>(plib::numeric_limits<T>::max()))
{ {
if (cstr[idx] != 0) if (cstr[idx] != 0)
throw pexception(pstring("Continuation after numeric value ends: ") + pstring(cstr)); throw pexception(pstring("Continuation after numeric value ends: ") + pstring(cstr));
@ -110,7 +111,7 @@ namespace plib
{ {
throw pexception(pstring("Out of range: ") + pstring(cstr)); throw pexception(pstring("Out of range: ") + pstring(cstr));
} }
return static_cast<T>(ret); return narrow_cast<T>(ret);
} }
template<typename R, typename T> template<typename R, typename T>

View File

@ -18,10 +18,10 @@
#include <array> #include <array>
#include <fstream> #include <fstream>
#include <fstream>
#include <ios> #include <ios>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <fstream>
#include <type_traits> #include <type_traits>
#include <vector> #include <vector>
@ -204,7 +204,7 @@ public:
{ {
const auto sz(static_cast<std::streamsize>(val.size())); const auto sz(static_cast<std::streamsize>(val.size()));
write(sz); write(sz);
m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * static_cast<std::streamsize>(sizeof(T))); m_strm.write(reinterpret_cast<const std::ostream::char_type *>(val.data()), sz * gsl::narrow<std::streamsize>(sizeof(T)));
} }
private: private:
@ -225,7 +225,7 @@ public:
template <typename T> template <typename T>
void read(T &val) void read(T &val)
{ {
m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), sizeof(T)); m_strm.read(reinterpret_cast<std::istream::char_type *>(&val), gsl::narrow<std::streamsize>(sizeof(T)));
} }
void read( pstring &s) void read( pstring &s)
@ -244,7 +244,7 @@ public:
std::size_t sz = 0; std::size_t sz = 0;
read(sz); read(sz);
val.resize(sz); val.resize(sz);
m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), static_cast<std::streamsize>(sizeof(T) * sz)); m_strm.read(reinterpret_cast<std::istream::char_type *>(val.data()), gsl::narrow<std::streamsize>(sizeof(T) * sz));
} }
private: private:
@ -289,7 +289,7 @@ public:
pstring_t<pwchar_traits>, pstring_t<putf8_traits>>::type; pstring_t<pwchar_traits>, pstring_t<putf8_traits>>::type;
template <typename T> template <typename T>
explicit ofstream(const pstring_t<T> name, ios_base::openmode mode = ios_base::in) explicit ofstream(const pstring_t<T> name, ios_base::openmode mode = ios_base::out | ios_base::trunc)
: std::ofstream(filename_type(name).c_str(), mode) : std::ofstream(filename_type(name).c_str(), mode)
{ {
} }

View File

@ -27,7 +27,7 @@ int pstring_t<F>::compare(const pstring_t &right) const noexcept
} }
if (si != this->end() && ri != right.end()) if (si != this->end() && ri != right.end())
return static_cast<int>(*si) - static_cast<int>(*ri); return plib::narrow_cast<int>(*si) - plib::narrow_cast<int>(*ri);
if (this->mem_t_size() > right.mem_t_size()) if (this->mem_t_size() > right.mem_t_size())
return 1; return 1;
if (this->mem_t_size() < right.mem_t_size()) if (this->mem_t_size() < right.mem_t_size())
@ -45,8 +45,8 @@ pstring_t<F> pstring_t<F>::substr(size_type start, size_type nlen) const
{ {
if (nlen == npos || start + nlen > l) if (nlen == npos || start + nlen > l)
nlen = l - start; nlen = l - start;
auto ps = std::next(begin(), static_cast<difference_type>(start)); auto ps = std::next(begin(), plib::narrow_cast<difference_type>(start));
auto pe = std::next(ps, static_cast<difference_type>(nlen)); auto pe = std::next(ps, plib::narrow_cast<difference_type>(nlen));
ret.m_str.assign(ps.p, pe.p); ret.m_str.assign(ps.p, pe.p);
} }
return ret; return ret;

View File

@ -8,6 +8,7 @@
/// \file pstrutil.h /// \file pstrutil.h
/// ///
#include "pgsl.h"
#include "pstring.h" #include "pstring.h"
#include "ptypes.h" #include "ptypes.h"
@ -157,13 +158,13 @@ namespace plib
template<typename T, typename TA> template<typename T, typename TA>
bool startsWith(const T &str, const TA &arg) bool startsWith(const T &str, const TA &arg)
{ {
return startsWith(str, static_cast<pstring>(arg)); return startsWith(str, static_cast<T>(arg));
} }
template<typename T, typename TA> template<typename T, typename TA>
bool endsWith(const T &str, const TA &arg) bool endsWith(const T &str, const TA &arg)
{ {
return endsWith(str, static_cast<pstring>(arg)); return endsWith(str, static_cast<T>(arg));
} }
template<typename T> template<typename T>
@ -172,7 +173,7 @@ namespace plib
const T *p = str; const T *p = str;
while (*p != 0) while (*p != 0)
p++; p++;
return static_cast<std::size_t>(p - str); return narrow_cast<std::size_t>(p - str);
} }
template<typename T> template<typename T>

View File

@ -210,7 +210,7 @@ namespace plib {
// save state support & mame disasm // save state support & mame disasm
const T *listptr() const noexcept { return &m_list[1]; } const T *listptr() const noexcept { return &m_list[1]; }
std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); } std::size_t size() const noexcept { return narrow_cast<std::size_t>(m_end - &m_list[1]); }
const T & operator[](std::size_t index) const noexcept { return m_list[ 1 + index]; } const T & operator[](std::size_t index) const noexcept { return m_list[ 1 + index]; }
private: private:
using mutex_type = pspin_mutex<TS>; using mutex_type = pspin_mutex<TS>;

View File

@ -15,8 +15,12 @@
#include <type_traits> #include <type_traits>
#if (PUSE_FLOAT128) #if (PUSE_FLOAT128)
#if defined(__has_include)
#if __has_include(<quadmath.h>)
#include <quadmath.h> #include <quadmath.h>
#endif #endif
#endif
#endif
// noexcept on move operator -> issue with macosx clang // noexcept on move operator -> issue with macosx clang
#define PCOPYASSIGNMOVE(name, def) \ #define PCOPYASSIGNMOVE(name, def) \
@ -273,7 +277,7 @@ namespace plib
template <typename T> class name \ template <typename T> class name \
{ \ { \
template <typename U> static long test(decltype(&U:: member)); \ template <typename U> static long test(decltype(&U:: member)); \
template <typename U> static char test(...); \ template <typename U> static char test(...); \
public: \ public: \
static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long); \ static constexpr const bool value = sizeof(test<T>(nullptr)) == sizeof(long); \
} }

View File

@ -3,9 +3,9 @@
#include "putil.h" #include "putil.h"
#include "penum.h" #include "penum.h"
#include "pstream.h"
#include "pstrutil.h" #include "pstrutil.h"
#include "ptypes.h" #include "ptypes.h"
#include "pstream.h"
#include <algorithm> #include <algorithm>
#include <cstdlib> // needed for getenv ... #include <cstdlib> // needed for getenv ...
@ -22,7 +22,7 @@ namespace plib
{ {
auto p=find_last_of(filename, pstring(PATH_SEPS)); auto p=find_last_of(filename, pstring(PATH_SEPS));
pstring ret = (p == pstring::npos) ? filename : filename.substr(p+1); pstring ret = (p == pstring::npos) ? filename : filename.substr(p+1);
if (suffix != "" && endsWith(ret, suffix)) if (!suffix.empty() && endsWith(ret, suffix))
return ret.substr(0, ret.length() - suffix.length()); return ret.substr(0, ret.length() - suffix.length());
return ret; return ret;
} }
@ -49,7 +49,7 @@ namespace plib
pstring ret = ""; pstring ret = "";
for( const auto &elem : list ) for( const auto &elem : list )
{ {
if (ret == "") if (ret.empty())
ret = elem; ret = elem;
else else
ret += (PATH_SEP + elem); ret += (PATH_SEP + elem);
@ -126,7 +126,7 @@ namespace plib
auto i = str.begin(); auto i = str.begin();
while (i != str.end()) while (i != str.end())
{ {
auto p = static_cast<std::size_t>(-1); auto p = pstring::npos;
for (std::size_t j=0; j < onstrl.size(); j++) for (std::size_t j=0; j < onstrl.size(); j++)
{ {
if (std::equal(onstrl[j].begin(), onstrl[j].end(), i)) if (std::equal(onstrl[j].begin(), onstrl[j].end(), i))
@ -135,14 +135,14 @@ namespace plib
break; break;
} }
} }
if (p != static_cast<std::size_t>(-1)) if (p != pstring::npos)
{ {
if (col != "") if (!col.empty())
ret.push_back(col); ret.push_back(col);
col = ""; col = "";
ret.push_back(onstrl[p]); ret.push_back(onstrl[p]);
i = std::next(i, static_cast<pstring::difference_type>(onstrl[p].length())); i = std::next(i, narrow_cast<pstring::difference_type>(onstrl[p].length()));
} }
else else
{ {
@ -151,7 +151,7 @@ namespace plib
i++; i++;
} }
} }
if (col != "") if (!col.empty())
ret.push_back(col); ret.push_back(col);
return ret; return ret;
@ -170,8 +170,8 @@ namespace plib
return -1; return -1;
} }
pstring penum_base::nthstr(int n, const pstring &str) pstring penum_base::nthstr(std::size_t n, const pstring &str)
{ {
return psplit(str, ",", false)[static_cast<std::size_t>(n)]; return psplit(str, ",", false)[n];
} }
} // namespace plib } // namespace plib

View File

@ -14,8 +14,8 @@
#include <algorithm> #include <algorithm>
#include <initializer_list> #include <initializer_list>
#include <vector>
#include <sstream> #include <sstream>
#include <vector>
#define PSTRINGIFY_HELP(y) # y #define PSTRINGIFY_HELP(y) # y
#define PSTRINGIFY(x) PSTRINGIFY_HELP(x) #define PSTRINGIFY(x) PSTRINGIFY_HELP(x)
@ -262,7 +262,9 @@ namespace plib
void reinterpret_copy(S &s, D &d) void reinterpret_copy(S &s, D &d)
{ {
static_assert(sizeof(D) >= sizeof(S), "size mismatch"); static_assert(sizeof(D) >= sizeof(S), "size mismatch");
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
auto *dp = reinterpret_cast<std::uint8_t *>(&d); auto *dp = reinterpret_cast<std::uint8_t *>(&d);
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
const auto *sp = reinterpret_cast<std::uint8_t *>(&s); const auto *sp = reinterpret_cast<std::uint8_t *>(&s);
std::copy(sp, sp + sizeof(S), dp); std::copy(sp, sp + sizeof(S), dp);
} }
@ -290,14 +292,14 @@ namespace plib
{ {
auto it = std::find(con.begin(), con.end(), elem); auto it = std::find(con.begin(), con.end(), elem);
if (it != con.end()) if (it != con.end())
return static_cast<std::size_t>(it - con.begin()); return narrow_cast<std::size_t>(it - con.begin());
return npos; return npos;
} }
template <class C> template <class C>
void insert_at(C &con, const std::size_t index, const typename C::value_type &elem) void insert_at(C &con, const std::size_t index, const typename C::value_type &elem)
{ {
con.insert(con.begin() + static_cast<std::ptrdiff_t>(index), elem); con.insert(con.begin() + narrow_cast<std::ptrdiff_t>(index), elem);
} }
template <class C> template <class C>
@ -336,7 +338,7 @@ namespace plib
{ {
std::size_t result = 5381; // NOLINT std::size_t result = 5381; // NOLINT
for (const T* p = buf; p != buf + size; p++) for (const T* p = buf; p != buf + size; p++)
result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ static_cast<std::size_t>(*p); // NOLINT result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ narrow_cast<std::size_t>(*p); // NOLINT
return result; return result;
} }

View File

@ -206,7 +206,7 @@ public:
return stream_ptr(nullptr); return stream_ptr(nullptr);
strm->imbue(std::locale::classic()); strm->imbue(std::locale::classic());
return std::move(strm); // FIXME: for c++11 clang builds; return strm;
} }
private: private:
@ -225,14 +225,14 @@ public:
netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const override netlist::host_arena::unique_ptr<plib::dynlib_base> static_solver_lib() const override
{ {
if (m_boostlib == "builtin") if (m_boostlib == "builtin")
return netlist::host_arena::make_unique<plib::dynlib_static>(nl_static_solver_syms); return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nl_static_solver_syms);
if (m_boostlib == "generic") if (m_boostlib == "generic")
return netlist::host_arena::make_unique<plib::dynlib_static>(nullptr); return plib::make_unique<plib::dynlib_static, netlist::host_arena>(nullptr);
if (NL_DISABLE_DYNAMIC_LOAD) if (NL_DISABLE_DYNAMIC_LOAD)
throw netlist::nl_exception("Dynamic library loading not supported due to project security concerns."); throw netlist::nl_exception("Dynamic library loading not supported due to project security concerns.");
//pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"})); //pstring libpath = plib::util::environment("NL_BOOSTLIB", plib::util::buildpath({".", "nlboost.so"}));
return netlist::host_arena::make_unique<plib::dynlib>(m_boostlib); return plib::make_unique<plib::dynlib, netlist::host_arena>(m_boostlib);
} }
private: private:
@ -245,7 +245,7 @@ class netlist_tool_t : public netlist::netlist_state_t
public: public:
netlist_tool_t(tool_app_t &app, const pstring &name, const pstring &boostlib) netlist_tool_t(tool_app_t &app, const pstring &name, const pstring &boostlib)
: netlist::netlist_state_t(name, netlist::host_arena::make_unique<netlist_tool_callbacks_t>(app, boostlib)) : netlist::netlist_state_t(name, plib::make_unique<netlist_tool_callbacks_t, netlist::host_arena>(app, boostlib))
{ {
} }
@ -364,13 +364,13 @@ struct input_t
case netlist::param_t::POINTER: case netlist::param_t::POINTER:
throw netlist::nl_exception(plib::pfmt("param {1} is not numeric\n")(m_param.param().name())); throw netlist::nl_exception(plib::pfmt("param {1} is not numeric\n")(m_param.param().name()));
case netlist::param_t::DOUBLE: case netlist::param_t::DOUBLE:
static_cast<netlist::param_fp_t*>(&m_param.param())->set(m_value); plib::downcast<netlist::param_fp_t &>(m_param.param()).set(m_value);
break; break;
case netlist::param_t::INTEGER: case netlist::param_t::INTEGER:
static_cast<netlist::param_int_t*>(&m_param.param())->set(static_cast<int>(m_value)); plib::downcast<netlist::param_int_t &>(m_param.param()).set(static_cast<int>(m_value));
break; break;
case netlist::param_t::LOGIC: case netlist::param_t::LOGIC:
static_cast<netlist::param_logic_t*>(&m_param.param())->set(static_cast<bool>(m_value)); plib::downcast<netlist::param_logic_t &>(m_param.param()).set(static_cast<bool>(m_value));
break; break;
} }
} }
@ -383,7 +383,7 @@ struct input_t
static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstring &fname) static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstring &fname)
{ {
std::vector<input_t> ret; std::vector<input_t> ret;
if (fname != "") if (!fname.empty())
{ {
plib::putf8_reader r = plib::putf8_reader(std::make_unique<plib::ifstream>(plib::filesystem::u8path(fname))); plib::putf8_reader r = plib::putf8_reader(std::make_unique<plib::ifstream>(plib::filesystem::u8path(fname)));
if (r.stream().fail()) if (r.stream().fail())
@ -392,7 +392,7 @@ static std::vector<input_t> read_input(const netlist::setup_t &setup, const pstr
pstring l; pstring l;
while (r.readline(l)) while (r.readline(l))
{ {
if (l != "") if (!l.empty())
{ {
input_t inp(setup, l); input_t inp(setup, l);
ret.push_back(inp); ret.push_back(inp);
@ -659,6 +659,8 @@ void tool_app_t::static_compile()
} }
} }
plib::ofstream sout(opt_out()); plib::ofstream sout(opt_out());
if (sout.fail())
throw netlist::nl_exception(netlist::MF_FILE_OPEN_ERROR(opt_out()));
sout << "#include \"plib/pdynlib.h\"\n\n"; sout << "#include \"plib/pdynlib.h\"\n\n";
for (auto &e : map) for (auto &e : map)
@ -666,6 +668,7 @@ void tool_app_t::static_compile()
sout << "// " << e.second.m_module << "\n"; sout << "// " << e.second.m_module << "\n";
sout << e.second.m_code; sout << e.second.m_code;
} }
sout << "extern plib::dynlib_static_sym nl_static_solver_syms[];\n";
sout << "plib::dynlib_static_sym nl_static_solver_syms[] = {\n"; sout << "plib::dynlib_static_sym nl_static_solver_syms[] = {\n";
for (auto &e : map) for (auto &e : map)
{ {
@ -721,7 +724,7 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id)
if (plib::startsWith(l, "//-")) if (plib::startsWith(l, "//-"))
{ {
l = plib::trim(l.substr(3)); l = plib::trim(l.substr(3));
if (l != "") if (!l.empty())
{ {
auto a(plib::psplit(l, ":", true)); auto a(plib::psplit(l, ":", true));
if (a.empty() || (a.size() > 2)) if (a.empty() || (a.size() > 2))
@ -761,7 +764,7 @@ static doc_ext read_docsrc(const pstring &fname, const pstring &id)
else if (n == "FunctionTable") else if (n == "FunctionTable")
ret.functiontable = v; ret.functiontable = v;
else if (n == "Param") else if (n == "Param")
ret.params.push_back(std::pair<pstring, pstring>(v2, plib::trim(v.substr(v2.length())))); ret.params.emplace_back(v2, plib::trim(v.substr(v2.length())));
else if (n == "Example") else if (n == "Example")
{ {
ret.example = plib::psplit(plib::trim(v),",",true); ret.example = plib::psplit(plib::trim(v),",",true);
@ -818,7 +821,7 @@ void tool_app_t::header_entry(const netlist::factory::element_t *e)
avs += ", " + s.substr(1); avs += ", " + s.substr(1);
mac_out("// usage : " + e->name() + "(name" + vs + ")", false); mac_out("// usage : " + e->name() + "(name" + vs + ")", false);
if (avs != "") if (!avs.empty())
mac_out("// auto connect: " + avs.substr(2), false); mac_out("// auto connect: " + avs.substr(2), false);
mac_out("#define " + e->name() + "(...)"); mac_out("#define " + e->name() + "(...)");
@ -942,7 +945,7 @@ void tool_app_t::create_docheader()
{ {
auto d(read_docsrc(e->source().file_name(), e->name())); auto d(read_docsrc(e->source().file_name(), e->name()));
if (d.id != "") if (!d.id.empty())
{ {
pout("//! [{1} csynopsis]\n", e->name()); pout("//! [{1} csynopsis]\n", e->name());
header_entry(e.get()); header_entry(e.get());
@ -964,7 +967,7 @@ void tool_app_t::create_docheader()
{ {
//auto d(read_docsrc(e->source().file_name(), e->name())); //auto d(read_docsrc(e->source().file_name(), e->name()));
if (d.id != "") if (!d.id.empty())
{ {
poutprefix("///", ""); poutprefix("///", "");
@ -1017,7 +1020,7 @@ void tool_app_t::create_docheader()
poutprefix("///", ""); poutprefix("///", "");
poutprefix("///", " @section {}_4 Function Table", d.id); poutprefix("///", " @section {}_4 Function Table", d.id);
poutprefix("///", ""); poutprefix("///", "");
if (d.functiontable == "") if (!d.functiontable.empty())
poutprefix("///", " Please refer to the datasheet."); poutprefix("///", " Please refer to the datasheet.");
else else
poutprefix("///", " {}", d.functiontable); poutprefix("///", " {}", d.functiontable);

View File

@ -655,10 +655,10 @@ void nlwav_app::convert_wav(std::ostream &ostrm, wav_t::format fmt)
double dt = plib::reciprocal(static_cast<double>(opt_rate())); double dt = plib::reciprocal(static_cast<double>(opt_rate()));
auto nchan = m_instrms.size(); auto nchan = m_instrms.size();
auto wo = arena::make_unique<wavwriter>(ostrm, opt_out() != "-", fmt, nchan, opt_rate(), opt_amp()); auto wo = plib::make_unique<wavwriter, arena>(ostrm, opt_out() != "-", fmt, nchan, opt_rate(), opt_amp());
auto ago = arena::make_unique<aggregator>(nchan, dt, aggregator::callback_type(&wavwriter::process, wo.get())); auto ago = plib::make_unique<aggregator, arena>(nchan, dt, aggregator::callback_type(&wavwriter::process, wo.get()));
auto fgo_hp = arena::make_unique<filter_hp>(opt_highpass(), opt_hpboost(), nchan, filter_hp::callback_type(&aggregator::process, ago.get())); auto fgo_hp = plib::make_unique<filter_hp, arena>(opt_highpass(), opt_hpboost(), nchan, filter_hp::callback_type(&aggregator::process, ago.get()));
auto fgo_lp = arena::make_unique<filter_lp>(opt_lowpass(), nchan, filter_lp::callback_type(&filter_hp::process, fgo_hp.get())); auto fgo_lp = plib::make_unique<filter_lp, arena>(opt_lowpass(), nchan, filter_lp::callback_type(&filter_hp::process, fgo_hp.get()));
auto topcb = log_processor::callback_type(&filter_lp::process, fgo_lp.get()); auto topcb = log_processor::callback_type(&filter_lp::process, fgo_lp.get());
@ -680,7 +680,7 @@ void nlwav_app::convert_wav(std::ostream &ostrm, wav_t::format fmt)
void nlwav_app::convert_vcd(std::ostream &ostrm, vcdwriter::format_e format) void nlwav_app::convert_vcd(std::ostream &ostrm, vcdwriter::format_e format)
{ {
arena::unique_ptr<vcdwriter> wo = arena::make_unique<vcdwriter>(ostrm, opt_args(), arena::unique_ptr<vcdwriter> wo = plib::make_unique<vcdwriter, arena>(ostrm, opt_args(),
format, opt_high(), opt_low()); format, opt_high(), opt_low());
log_processor::callback_type agcb = log_processor::callback_type(&vcdwriter::process, wo.get()); log_processor::callback_type agcb = log_processor::callback_type(&vcdwriter::process, wo.get());
@ -702,7 +702,7 @@ void nlwav_app::convert_vcd(std::ostream &ostrm, vcdwriter::format_e format)
void nlwav_app::convert_tab(std::ostream &ostrm) void nlwav_app::convert_tab(std::ostream &ostrm)
{ {
auto wo = arena::make_unique<tabwriter>(ostrm, opt_args(), auto wo = plib::make_unique<tabwriter, arena>(ostrm, opt_args(),
opt_start(), opt_inc(), opt_samples()); opt_start(), opt_inc(), opt_samples());
log_processor::callback_type agcb = log_processor::callback_type(&tabwriter::process, wo.get()); log_processor::callback_type agcb = log_processor::callback_type(&tabwriter::process, wo.get());

View File

@ -121,7 +121,7 @@ namespace solver
{ {
pstring nname(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size()))); pstring nname(this->name() + "." + pstring(plib::pfmt("m{1}")(m_inps.size())));
nl_assert(p->net().is_analog()); nl_assert(p->net().is_analog());
auto net_proxy_output_u = state().make_pool_object<proxied_analog_output_t>(*this, nname, static_cast<analog_net_t *>(&p->net())); auto net_proxy_output_u = state().make_pool_object<proxied_analog_output_t>(*this, nname, &dynamic_cast<analog_net_t &>(p->net()));
net_proxy_output = net_proxy_output_u.get(); net_proxy_output = net_proxy_output_u.get();
m_inps.emplace_back(std::move(net_proxy_output_u)); m_inps.emplace_back(std::move(net_proxy_output_u));
} }
@ -375,6 +375,17 @@ namespace solver
m_Idrn.resize(iN, max_count); m_Idrn.resize(iN, max_count);
m_connected_net_Vn.resize(iN, max_count); m_connected_net_Vn.resize(iN, max_count);
// Initialize arrays to 0 (in case the vrl one is used
for (std::size_t k = 0; k < iN; k++)
for (std::size_t j = 0; j < m_terms[k].count(); j++)
{
m_gtn.set(k,j, nlconst::zero());
m_gonn.set(k,j, nlconst::zero());
m_Idrn.set(k,j, nlconst::zero());
m_connected_net_Vn.set(k, j, nullptr);
}
for (std::size_t k = 0; k < iN; k++) for (std::size_t k = 0; k < iN; k++)
{ {
auto count = m_terms[k].count(); auto count = m_terms[k].count();
@ -421,7 +432,7 @@ namespace solver
void matrix_solver_t::step(netlist_time delta) noexcept void matrix_solver_t::step(netlist_time delta) noexcept
{ {
const auto dd(delta.as_fp<nl_fptype>()); const auto dd(delta.as_fp<fptype>());
for (auto &d : m_step_funcs) for (auto &d : m_step_funcs)
d(dd); d(dd);
} }
@ -478,7 +489,7 @@ namespace solver
if (m_params.m_dynamic_ts) if (m_params.m_dynamic_ts)
return compute_next_timestep(delta.as_fp<nl_fptype>(), m_params.m_max_timestep); return compute_next_timestep(delta.as_fp<fptype>(), m_params.m_max_timestep);
return netlist_time::from_fp(m_params.m_max_timestep); return netlist_time::from_fp(m_params.m_max_timestep);
} }
@ -523,7 +534,7 @@ namespace solver
return {colmax, colmin}; return {colmax, colmin};
} }
nl_fptype matrix_solver_t::get_weight_around_diag(std::size_t row, std::size_t diag) matrix_solver_t::fptype matrix_solver_t::get_weight_around_diag(std::size_t row, std::size_t diag)
{ {
{ {
// //
@ -532,7 +543,7 @@ namespace solver
std::vector<bool> touched(1024, false); // FIXME! std::vector<bool> touched(1024, false); // FIXME!
nl_fptype weight = nlconst::zero(); fptype weight = nlconst::zero();
auto &term = m_terms[row]; auto &term = m_terms[row];
for (std::size_t i = 0; i < term.count(); i++) for (std::size_t i = 0; i < term.count(); i++)
{ {
@ -545,7 +556,7 @@ namespace solver
if (colu==row) colu = static_cast<unsigned>(diag); if (colu==row) colu = static_cast<unsigned>(diag);
else if (colu==diag) colu = static_cast<unsigned>(row); else if (colu==diag) colu = static_cast<unsigned>(row);
weight = weight + plib::abs(static_cast<nl_fptype>(colu) - static_cast<nl_fptype>(diag)); weight = weight + plib::abs(static_cast<fptype>(colu) - static_cast<fptype>(diag));
touched[colu] = true; touched[colu] = true;
} }
} }
@ -585,14 +596,14 @@ namespace solver
log().verbose(" has {1} dynamic elements", this->dynamic_device_count()); log().verbose(" has {1} dynamic elements", this->dynamic_device_count());
log().verbose(" has {1} timestep elements", this->timestep_device_count()); log().verbose(" has {1} timestep elements", this->timestep_device_count());
log().verbose(" {1:6.3} average newton raphson loops", log().verbose(" {1:6.3} average newton raphson loops",
static_cast<nl_fptype>(this->m_stat_newton_raphson) / static_cast<nl_fptype>(this->m_stat_vsolver_calls)); static_cast<fptype>(this->m_stat_newton_raphson) / static_cast<fptype>(this->m_stat_vsolver_calls));
log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average", log().verbose(" {1:10} invocations ({2:6.0} Hz) {3:10} gs fails ({4:6.2} %) {5:6.3} average",
this->m_stat_calculations, this->m_stat_calculations,
static_cast<nl_fptype>(this->m_stat_calculations) / this->exec().time().as_fp<nl_fptype>(), static_cast<fptype>(this->m_stat_calculations) / this->exec().time().as_fp<fptype>(),
this->m_iterative_fail, this->m_iterative_fail,
nlconst::hundred() * static_cast<nl_fptype>(this->m_iterative_fail) nlconst::hundred() * static_cast<fptype>(this->m_iterative_fail)
/ static_cast<nl_fptype>(this->m_stat_calculations), / static_cast<fptype>(this->m_stat_calculations),
static_cast<nl_fptype>(this->m_iterative_total) / static_cast<nl_fptype>(this->m_stat_calculations)); static_cast<fptype>(this->m_iterative_total) / static_cast<fptype>(this->m_stat_calculations));
} }
} }

View File

@ -14,6 +14,7 @@
#include "netlist/plib/palloc.h" #include "netlist/plib/palloc.h"
#include "netlist/plib/penum.h" #include "netlist/plib/penum.h"
#include "netlist/plib/pmatrix2d.h" #include "netlist/plib/pmatrix2d.h"
#include "netlist/plib/pmempool.h"
#include "netlist/plib/putil.h" #include "netlist/plib/putil.h"
#include "netlist/plib/vector_ops.h" #include "netlist/plib/vector_ops.h"
@ -183,6 +184,8 @@ namespace solver
{ {
public: public:
using list_t = std::vector<matrix_solver_t *>; using list_t = std::vector<matrix_solver_t *>;
using fptype = nl_fptype;
using arena_type = plib::mempool_arena<plib::aligned_arena>;
// after every call to solve, update inputs must be called. // after every call to solve, update inputs must be called.
// this can be done as well as a batch to ease parallel processing. // this can be done as well as a batch to ease parallel processing.
@ -259,51 +262,32 @@ namespace solver
} }
// return number of floating point operations for solve // return number of floating point operations for solve
std::size_t ops() const { return m_ops; } constexpr std::size_t ops() const { return m_ops; }
protected: protected:
template <typename T>
using aligned_alloc = plib::aligned_allocator<T, PALIGN_VECTOROPT>;
matrix_solver_t(netlist_state_t &anetlist, const pstring &name, matrix_solver_t(netlist_state_t &anetlist, const pstring &name,
const analog_net_t::list_t &nets, const analog_net_t::list_t &nets,
const solver_parameters_t *params); const solver_parameters_t *params);
virtual void vsolve_non_dynamic() = 0; virtual void vsolve_non_dynamic() = 0;
virtual netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) = 0; virtual netlist_time compute_next_timestep(fptype cur_ts, fptype max_ts) = 0;
virtual bool check_err() = 0; virtual bool check_err() const = 0;
virtual void store() = 0; virtual void store() = 0;
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gonn; plib::pmatrix2d_vrl<fptype, arena_type> m_gonn;
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gtn; plib::pmatrix2d_vrl<fptype, arena_type> m_gtn;
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn; plib::pmatrix2d_vrl<fptype, arena_type> m_Idrn;
plib::pmatrix2d<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn; plib::pmatrix2d_vrl<fptype *, arena_type> m_connected_net_Vn;
plib::aligned_vector<terms_for_net_t> m_terms;
const solver_parameters_t &m_params; const solver_parameters_t &m_params;
state_var<std::size_t> m_iterative_fail; state_var<std::size_t> m_iterative_fail;
state_var<std::size_t> m_iterative_total; state_var<std::size_t> m_iterative_total;
plib::aligned_vector<terms_for_net_t> m_terms; // setup only
private: private:
plib::aligned_vector<terms_for_net_t> m_rails_temp;
std::vector<device_arena::unique_ptr<proxied_analog_output_t>> m_inps;
state_var<std::size_t> m_stat_calculations;
state_var<std::size_t> m_stat_newton_raphson;
state_var<std::size_t> m_stat_vsolver_calls;
state_var<netlist_time_ext> m_last_step;
plib::aligned_vector<nldelegate_ts> m_step_funcs;
plib::aligned_vector<nldelegate_dyn> m_dynamic_funcs;
logic_input_t m_fb_sync;
logic_output_t m_Q_sync;
std::size_t m_ops;
// base setup - called from constructor // base setup - called from constructor
void setup_base(setup_t &setup, const analog_net_t::list_t &nets) noexcept(false); void setup_base(setup_t &setup, const analog_net_t::list_t &nets) noexcept(false);
@ -314,7 +298,7 @@ namespace solver
int get_net_idx(const analog_net_t *net) const noexcept; int get_net_idx(const analog_net_t *net) const noexcept;
std::pair<int, int> get_left_right_of_diag(std::size_t irow, std::size_t idiag); std::pair<int, int> get_left_right_of_diag(std::size_t irow, std::size_t idiag);
nl_fptype get_weight_around_diag(std::size_t row, std::size_t diag); fptype get_weight_around_diag(std::size_t row, std::size_t diag);
void add_term(std::size_t net_idx, terminal_t *term) noexcept(false); void add_term(std::size_t net_idx, terminal_t *term) noexcept(false);
@ -325,272 +309,21 @@ namespace solver
analog_net_t *get_connected_net(terminal_t *term); analog_net_t *get_connected_net(terminal_t *term);
}; state_var<std::size_t> m_stat_calculations;
state_var<std::size_t> m_stat_newton_raphson;
state_var<std::size_t> m_stat_vsolver_calls;
template <typename FT, int SIZE> state_var<netlist_time_ext> m_last_step;
class matrix_solver_ext_t: public matrix_solver_t plib::aligned_vector<nldelegate_ts> m_step_funcs;
{ plib::aligned_vector<nldelegate_dyn> m_dynamic_funcs;
public: plib::aligned_vector<device_arena::unique_ptr<proxied_analog_output_t>> m_inps;
using float_type = FT; logic_input_t m_fb_sync;
logic_output_t m_Q_sync;
matrix_solver_ext_t(netlist_state_t &anetlist, const pstring &name, std::size_t m_ops;
const analog_net_t::list_t &nets,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, nets, params)
, m_dim(size)
, m_new_V(size)
, m_RHS(size)
, m_mat_ptr(size, this->max_railstart() + 1)
, m_last_V(size, nlconst::zero())
, m_DD_n_m_1(size, nlconst::zero())
, m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here
{
//
// save states
//
state().save(*this, m_last_V.as_base(), this->name(), "m_last_V");
state().save(*this, m_DD_n_m_1.as_base(), this->name(), "m_DD_n_m_1");
state().save(*this, m_h_n_m_1.as_base(), this->name(), "m_h_n_m_1");
}
plib::aligned_vector<terms_for_net_t> m_rails_temp; // setup only
private:
const std::size_t m_dim;
protected:
static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS();
static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8;
PALIGNAS_VECTOROPT()
plib::parray<float_type, SIZE> m_new_V;
PALIGNAS_VECTOROPT()
plib::parray<float_type, SIZE> m_RHS;
PALIGNAS_VECTOROPT()
plib::pmatrix2d<float_type *> m_mat_ptr;
// FIXME: below should be private
// state - variable time_stepping
PALIGNAS_VECTOROPT()
plib::parray<nl_fptype, SIZE> m_last_V;
PALIGNAS_VECTOROPT()
plib::parray<nl_fptype, SIZE> m_DD_n_m_1;
PALIGNAS_VECTOROPT()
plib::parray<nl_fptype, SIZE> m_h_n_m_1;
std::size_t max_railstart() const noexcept
{
std::size_t max_rail = 0;
for (std::size_t k = 0; k < m_terms.size(); k++)
max_rail = std::max(max_rail, m_terms[k].railstart());
return max_rail;
}
template <typename T, typename M>
void log_fill(const T &fill, M &mat)
{
const std::size_t iN = fill.size();
// FIXME: Not yet working, mat_cr.h needs some more work
#if 0
auto mat_GE = dynamic_cast<plib::pGEmatrix_cr_t<typename M::base> *>(&mat);
#else
plib::unused_var(mat);
#endif
std::vector<unsigned> levL(iN, 0);
std::vector<unsigned> levU(iN, 0);
// parallel scheme for L x = y
for (std::size_t k = 0; k < iN; k++)
{
unsigned lm=0;
for (std::size_t j = 0; j<k; j++)
if (fill[k][j] < M::FILL_INFINITY)
lm = std::max(lm, levL[j]);
levL[k] = 1+lm;
}
// parallel scheme for U x = y
for (std::size_t k = iN; k-- > 0; )
{
unsigned lm=0;
for (std::size_t j = iN; --j > k; )
if (fill[k][j] < M::FILL_INFINITY)
lm = std::max(lm, levU[j]);
levU[k] = 1+lm;
}
for (std::size_t k = 0; k < iN; k++)
{
unsigned fm = 0;
pstring ml = "";
for (std::size_t j = 0; j < iN; j++)
{
ml += fill[k][j] == 0 ? 'X' : fill[k][j] < M::FILL_INFINITY ? '+' : '.';
if (fill[k][j] < M::FILL_INFINITY)
if (fill[k][j] > fm)
fm = fill[k][j];
}
#if 0
this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml,
levL[k], levU[k], mat_GE ? mat_GE->get_parallel_level(k) : 0, fm);
#else
this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml,
levL[k], levU[k], 0, fm);
#endif
}
}
constexpr std::size_t size() const noexcept
{
return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim;
}
#if 1
void store() override
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
this->m_terms[i].setV(static_cast<nl_fptype>(m_new_V[i]));
}
#else
// global tanh damping (4.197)
// partially cures the symptoms but not the cause
void store() override
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
{
auto oldV = this->m_terms[i].template getV<nl_fptype>();
this->m_terms[i].setV(oldV + 0.02 * plib::tanh((m_new_V[i]-oldV)*50.0));
}
}
#endif
bool check_err() override
{
// NOTE: Ideally we should also include currents (RHS) here. This would
// need a reevaluation of the right hand side after voltages have been updated
// and thus belong into a different calculation. This applies to all solvers.
const std::size_t iN = size();
const auto reltol(static_cast<float_type>(m_params.m_reltol));
const auto vntol(static_cast<float_type>(m_params.m_vntol));
for (std::size_t i = 0; i < iN; i++)
{
const auto vold(static_cast<float_type>(this->m_terms[i].getV()));
const auto vnew(m_new_V[i]);
const auto tol(vntol + reltol * std::max(plib::abs(vnew),plib::abs(vold)));
if (plib::abs(vnew - vold) > tol)
return true;
}
return false;
}
netlist_time compute_next_timestep(nl_fptype cur_ts, nl_fptype max_ts) override
{
nl_fptype new_solver_timestep(max_ts);
for (std::size_t k = 0; k < size(); k++)
{
const auto &t = m_terms[k];
const auto v(static_cast<nl_fptype>(t.getV()));
// avoid floating point exceptions
const nl_fptype DD_n = std::max(-fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(),
std::min(+fp_constants<nl_fptype>::TIMESTEP_MAXDIFF(),(v - m_last_V[k])));
m_last_V[k] = v;
const nl_fptype hn = cur_ts;
nl_fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
nl_fptype new_net_timestep(0);
m_h_n_m_1[k] = hn;
m_DD_n_m_1[k] = DD_n;
if (plib::abs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero
new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::half()*DD2));
else
new_net_timestep = m_params.m_max_timestep;
new_solver_timestep = std::min(new_net_timestep, new_solver_timestep);
}
new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep);
// FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
return std::max(netlist_time::from_fp(new_solver_timestep), netlist_time::quantum() * 2);
}
template <typename M>
void build_mat_ptr(M &mat)
{
const std::size_t iN = size();
for (std::size_t k=0; k<iN; k++)
{
std::size_t cnt(0);
// build pointers into the compressed row format matrix for each terminal
for (std::size_t j=0; j< this->m_terms[k].railstart();j++)
{
int other = this->m_terms[k].m_connected_net_idx[j];
if (other >= 0)
{
m_mat_ptr[k][j] = &(mat[k][static_cast<std::size_t>(other)]);
cnt++;
}
}
nl_assert_always(cnt == this->m_terms[k].railstart(), "Count and railstart mismatch");
m_mat_ptr[k][this->m_terms[k].railstart()] = &(mat[k][k]);
}
}
template <typename M>
void clear_square_mat(M &m)
{
const std::size_t n = size();
for (std::size_t k=0; k < n; k++)
{
auto *p = &(m[k][0]);
using mat_elem_type = typename std::decay<decltype(*p)>::type;
for (std::size_t i=0; i < n; i++)
p[i] = plib::constants<mat_elem_type>::zero();
}
}
void fill_matrix_and_rhs()
{
const std::size_t N = size();
for (std::size_t k = 0; k < N; k++)
{
auto &net = m_terms[k];
auto **tcr_r = &(m_mat_ptr[k][0]);
using source_type = typename decltype(m_gtn)::value_type;
const std::size_t term_count = net.count();
const std::size_t railstart = net.railstart();
const auto &go = m_gonn[k];
const auto &gt = m_gtn[k];
const auto &Idr = m_Idrn[k];
const auto &cnV = m_connected_net_Vn[k];
// FIXME: gonn, gtn and Idr - which float types should they have?
auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<source_type>::zero());
// update diagonal element ...
*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
for (std::size_t i = 0; i < railstart; i++)
*tcr_r[i] += static_cast<FT>(go[i]);
auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<source_type>::zero()));
for (std::size_t i = railstart; i < term_count; i++)
RHS_t += (- go[i]) * *cnV[i];
m_RHS[k] = static_cast<FT>(RHS_t);
}
}
}; };

View File

@ -0,0 +1,288 @@
// license:GPL-2.0+
// copyright-holders:Couriersud
#ifndef NLD_MATRIX_SOLVER_EXT_H_
#define NLD_MATRIX_SOLVER_EXT_H_
///
/// \file nld_matrix_solver.h
///
#include "nld_matrix_solver.h"
#include <numeric>
namespace netlist
{
namespace solver
{
template <typename FT, int SIZE>
class matrix_solver_ext_t: public matrix_solver_t
{
public:
using float_type = FT;
matrix_solver_ext_t(netlist_state_t &anetlist, const pstring &name,
const analog_net_t::list_t &nets,
const solver_parameters_t *params, const std::size_t size)
: matrix_solver_t(anetlist, name, nets, params)
, m_new_V(size)
, m_RHS(size)
, m_mat_ptr(size, this->max_railstart() + 1)
, m_last_V(size, nlconst::zero())
, m_DD_n_m_1(size, nlconst::zero())
, m_h_n_m_1(size, nlconst::magic(1e-6)) // we need a non zero value here
, m_dim(size)
{
//
// save states
//
state().save(*this, m_last_V.as_base(), this->name(), "m_last_V");
state().save(*this, m_DD_n_m_1.as_base(), this->name(), "m_DD_n_m_1");
state().save(*this, m_h_n_m_1.as_base(), this->name(), "m_h_n_m_1");
}
protected:
static constexpr const std::size_t SIZEABS = plib::parray<FT, SIZE>::SIZEABS();
static constexpr const std::size_t m_pitch_ABS = (((SIZEABS + 0) + 7) / 8) * 8;
//PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray<float_type, SIZE> m_new_V;
//PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray<float_type, SIZE> m_RHS;
//PALIGNAS_VECTOROPT() parrays define alignment already
plib::pmatrix2d<float_type *> m_mat_ptr;
std::size_t max_railstart() const noexcept
{
std::size_t max_rail = 0;
for (std::size_t k = 0; k < m_terms.size(); k++)
max_rail = std::max(max_rail, m_terms[k].railstart());
return max_rail;
}
template <typename T, typename M>
void log_fill(const T &fill, M &mat)
{
const std::size_t iN = fill.size();
// FIXME: Not yet working, mat_cr.h needs some more work
#if 0
auto mat_GE = dynamic_cast<plib::pGEmatrix_cr_t<typename M::base> *>(&mat);
#else
plib::unused_var(mat);
#endif
std::vector<unsigned> levL(iN, 0);
std::vector<unsigned> levU(iN, 0);
// parallel scheme for L x = y
for (std::size_t k = 0; k < iN; k++)
{
unsigned lm=0;
for (std::size_t j = 0; j<k; j++)
if (fill[k][j] < M::FILL_INFINITY)
lm = std::max(lm, levL[j]);
levL[k] = 1+lm;
}
// parallel scheme for U x = y
for (std::size_t k = iN; k-- > 0; )
{
unsigned lm=0;
for (std::size_t j = iN; --j > k; )
if (fill[k][j] < M::FILL_INFINITY)
lm = std::max(lm, levU[j]);
levU[k] = 1+lm;
}
for (std::size_t k = 0; k < iN; k++)
{
unsigned fm = 0;
pstring ml = "";
for (std::size_t j = 0; j < iN; j++)
{
ml += fill[k][j] == 0 ? 'X' : fill[k][j] < M::FILL_INFINITY ? '+' : '.';
if (fill[k][j] < M::FILL_INFINITY)
if (fill[k][j] > fm)
fm = fill[k][j];
}
#if 0
this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml,
levL[k], levU[k], mat_GE ? mat_GE->get_parallel_level(k) : 0, fm);
#else
this->log().verbose("{1:4} {2} {3:4} {4:4} {5:4} {6:4}", k, ml,
levL[k], levU[k], 0, fm);
#endif
}
}
constexpr std::size_t size() const noexcept
{
return (SIZE > 0) ? static_cast<std::size_t>(SIZE) : m_dim;
}
#if 1
void store() override
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
this->m_terms[i].setV(static_cast<fptype>(m_new_V[i]));
}
#else
// global tanh damping (4.197)
// partially cures the symptoms but not the cause
void store() override
{
const std::size_t iN = size();
for (std::size_t i = 0; i < iN; i++)
{
auto oldV = this->m_terms[i].template getV<fptype>();
this->m_terms[i].setV(oldV + 0.02 * plib::tanh((m_new_V[i]-oldV)*50.0));
}
}
#endif
bool check_err() const override
{
// NOTE: Ideally we should also include currents (RHS) here. This would
// need a reevaluation of the right hand side after voltages have been updated
// and thus belong into a different calculation. This applies to all solvers.
const std::size_t iN = size();
const auto reltol(static_cast<float_type>(m_params.m_reltol));
const auto vntol(static_cast<float_type>(m_params.m_vntol));
for (std::size_t i = 0; i < iN; i++)
{
const auto vold(static_cast<float_type>(this->m_terms[i].getV()));
const auto vnew(m_new_V[i]);
const auto tol(vntol + reltol * std::max(plib::abs(vnew),plib::abs(vold)));
if (plib::abs(vnew - vold) > tol)
return true;
}
return false;
}
netlist_time compute_next_timestep(fptype cur_ts, fptype max_ts) override
{
fptype new_solver_timestep(max_ts);
for (std::size_t k = 0; k < size(); k++)
{
const auto &t = m_terms[k];
const auto v(static_cast<fptype>(t.getV()));
// avoid floating point exceptions
const fptype DD_n = std::max(-fp_constants<fptype>::TIMESTEP_MAXDIFF(),
std::min(+fp_constants<fptype>::TIMESTEP_MAXDIFF(),(v - m_last_V[k])));
m_last_V[k] = v;
const fptype hn = cur_ts;
fptype DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]);
fptype new_net_timestep(0);
m_h_n_m_1[k] = hn;
m_DD_n_m_1[k] = DD_n;
if (plib::abs(DD2) > fp_constants<fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero
new_net_timestep = plib::sqrt(m_params.m_dynamic_lte / plib::abs(nlconst::half()*DD2));
else
new_net_timestep = m_params.m_max_timestep;
new_solver_timestep = std::min(new_net_timestep, new_solver_timestep);
}
new_solver_timestep = std::max(new_solver_timestep, m_params.m_min_timestep);
// FIXME: Factor 2 below is important. Without, we get timing issues. This must be a bug elsewhere.
return std::max(netlist_time::from_fp(new_solver_timestep), netlist_time::quantum() * 2);
}
template <typename M>
void build_mat_ptr(M &mat)
{
const std::size_t iN = size();
for (std::size_t k=0; k<iN; k++)
{
std::size_t cnt(0);
// build pointers into the compressed row format matrix for each terminal
for (std::size_t j=0; j< this->m_terms[k].railstart();j++)
{
int other = this->m_terms[k].m_connected_net_idx[j];
if (other >= 0)
{
m_mat_ptr[k][j] = &(mat[k][static_cast<std::size_t>(other)]);
cnt++;
}
}
nl_assert_always(cnt == this->m_terms[k].railstart(), "Count and railstart mismatch");
m_mat_ptr[k][this->m_terms[k].railstart()] = &(mat[k][k]);
}
}
template <typename M>
void clear_square_mat(M &m)
{
const std::size_t n = size();
for (std::size_t k=0; k < n; k++)
{
auto *p = &(m[k][0]);
using mat_elem_type = typename std::decay<decltype(*p)>::type;
for (std::size_t i=0; i < n; i++)
p[i] = plib::constants<mat_elem_type>::zero();
}
}
void fill_matrix_and_rhs()
{
const std::size_t N = size();
for (std::size_t k = 0; k < N; k++)
{
auto &net = m_terms[k];
auto **tcr_r = &(m_mat_ptr[k][0]);
using source_type = typename decltype(m_gtn)::value_type;
const std::size_t term_count = net.count();
const std::size_t railstart = net.railstart();
const auto &go = m_gonn[k];
const auto &gt = m_gtn[k];
const auto &Idr = m_Idrn[k];
const auto &cnV = m_connected_net_Vn[k];
// FIXME: gonn, gtn and Idr - which float types should they have?
auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<source_type>::zero());
// update diagonal element ...
*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
for (std::size_t i = 0; i < railstart; i++)
*tcr_r[i] += static_cast<FT>(go[i]);
auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<source_type>::zero()));
for (std::size_t i = railstart; i < term_count; i++)
RHS_t += (- go[i]) * *cnV[i];
m_RHS[k] = static_cast<FT>(RHS_t);
}
}
private:
// state - variable time_stepping
//PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray<fptype, SIZE> m_last_V;
// PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray<fptype, SIZE> m_DD_n_m_1;
// PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray<fptype, SIZE> m_h_n_m_1;
const std::size_t m_dim;
};
} // namespace solver
} // namespace netlist
#endif // NLD_MATRIX_SOLVER_EXT_H_

View File

@ -13,6 +13,8 @@
#include "plib/parray.h" #include "plib/parray.h"
#include "plib/vector_ops.h" #include "plib/vector_ops.h"
#include "nld_matrix_solver_ext.h"
#include <algorithm> #include <algorithm>
namespace netlist namespace netlist
@ -49,7 +51,7 @@ namespace solver
template <typename T> template <typename T>
void LE_back_subst(T & x); void LE_back_subst(T & x);
PALIGNAS_VECTOROPT() // PALIGNAS_VECTOROPT() parrays define alignment already
plib::parray2D<FT, SIZE, m_pitch_ABS> m_A; plib::parray2D<FT, SIZE, m_pitch_ABS> m_A;
}; };

View File

@ -8,6 +8,7 @@
/// \file nld_ms_direct1.h /// \file nld_ms_direct1.h
/// ///
#include "nld_matrix_solver_ext.h"
#include "nld_ms_direct.h" #include "nld_ms_direct.h"
#include "nld_solver.h" #include "nld_solver.h"

View File

@ -8,6 +8,7 @@
/// \file nld_ms_direct2.h /// \file nld_ms_direct2.h
/// ///
#include "nld_matrix_solver_ext.h"
#include "nld_ms_direct.h" #include "nld_ms_direct.h"
#include "nld_solver.h" #include "nld_solver.h"

View File

@ -12,7 +12,8 @@
#include "plib/mat_cr.h" #include "plib/mat_cr.h"
#include "nld_ms_direct.h" //#include "nld_ms_direct.h"
#include "nld_matrix_solver_ext.h"
#include "nld_solver.h" #include "nld_solver.h"
#include "plib/pdynlib.h" #include "plib/pdynlib.h"
#include "plib/pstream.h" #include "plib/pstream.h"
@ -31,6 +32,8 @@ namespace solver
public: public:
using mat_type = plib::pGEmatrix_cr_t<plib::pmatrix_cr_t<FT, SIZE>>; using mat_type = plib::pGEmatrix_cr_t<plib::pmatrix_cr_t<FT, SIZE>>;
using base_type = matrix_solver_ext_t<FT, SIZE>;
using fptype = typename base_type::fptype;
matrix_solver_GCR_t(netlist_state_t &anetlist, const pstring &name, matrix_solver_GCR_t(netlist_state_t &anetlist, const pstring &name,
const analog_net_t::list_t &nets, const analog_net_t::list_t &nets,
@ -85,9 +88,9 @@ namespace solver
anetlist.log().verbose("maximum fill: {1}", gr.first); anetlist.log().verbose("maximum fill: {1}", gr.first);
anetlist.log().verbose("Post elimination occupancy ratio: {2} Ops: {1}", gr.second, anetlist.log().verbose("Post elimination occupancy ratio: {2} Ops: {1}", gr.second,
static_cast<nl_fptype>(mat.nz_num) / static_cast<nl_fptype>(iN * iN)); static_cast<fptype>(mat.nz_num) / static_cast<fptype>(iN * iN));
anetlist.log().verbose(" Pre elimination occupancy ratio: {2}", anetlist.log().verbose(" Pre elimination occupancy ratio: {2}",
static_cast<nl_fptype>(raw_elements) / static_cast<nl_fptype>(iN * iN)); static_cast<fptype>(raw_elements) / static_cast<fptype>(iN * iN));
// FIXME: Move me // FIXME: Move me
// //
@ -123,7 +126,7 @@ namespace solver
pstring static_compile_name(); pstring static_compile_name();
mat_type mat; mat_type mat;
plib::dynproc<void, FT *, nl_fptype *, nl_fptype *, nl_fptype *, nl_fptype ** > m_proc; plib::dynproc<void, FT *, fptype *, fptype *, fptype *, fptype ** > m_proc;
}; };
@ -139,7 +142,7 @@ namespace solver
pstring fpsuffix(fp_constants<FT>::suffix()); pstring fpsuffix(fp_constants<FT>::suffix());
for (std::size_t i = 0; i < mat.nz_num; i++) for (std::size_t i = 0; i < mat.nz_num; i++)
strm("{1} m_A{2}(0.0);\n", fptype, i, i); strm("\t{1} m_A{2}(0.0);\n", fptype, i, i);
for (std::size_t k = 0; k < iN; k++) for (std::size_t k = 0; k < iN; k++)
{ {
@ -150,23 +153,27 @@ namespace solver
//auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<FT>::zero()); //auto gtot_t = std::accumulate(gt, gt + term_count, plib::constants<FT>::zero());
//*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t; //*tcr_r[railstart] = static_cast<FT>(gtot_t); //mat.A[mat.diag[k]] += gtot_t;
auto pd = this->m_mat_ptr[k][net.railstart()] - &this->mat.A[0]; auto pd = this->m_mat_ptr[k][net.railstart()] - &this->mat.A[0];
#if 0
pstring terms = plib::pfmt("m_A{1} = gt[{2}]")(pd, this->m_gtn.didx(k,0)); pstring terms = plib::pfmt("m_A{1} = gt[{2}]")(pd, this->m_gtn.didx(k,0));
for (std::size_t i=1; i < net.count(); i++) for (std::size_t i=1; i < net.count(); i++)
terms += plib::pfmt(" + gt[{1}]")(this->m_gtn.didx(k,i)); terms += plib::pfmt(" + gt[{1}]")(this->m_gtn.didx(k,i));
strm("\t{1};\n", terms); strm("\t{1};\n", terms);
#else
for (std::size_t i=0; i < net.count(); i++)
strm("\tm_A{1} += gt[{2}];\n", pd, this->m_gtn.didx(k,i));
#endif
//for (std::size_t i = 0; i < railstart; i++) //for (std::size_t i = 0; i < railstart; i++)
// *tcr_r[i] += static_cast<FT>(go[i]); // *tcr_r[i] += static_cast<FT>(go[i]);
for (std::size_t i = 0; i < net.railstart(); i++) for (std::size_t i = 0; i < net.railstart(); i++)
{ {
auto p = this->m_mat_ptr[k][i] - &this->mat.A[0]; auto p = this->m_mat_ptr[k][i] - &this->mat.A[0];
strm("\tm_A{1} = m_A{1} + go[{2}];\n", p, this->m_gonn.didx(k,i)); strm("\tm_A{1} += go[{2}];\n", p, this->m_gonn.didx(k,i));
} }
#if 0
//auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<FT>::zero())); //auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<FT>::zero()));
terms = plib::pfmt("{1} RHS{2} = Idr[{3}]")(fptype, k, this->m_Idrn.didx(k,0)); terms = plib::pfmt("{1} RHS{2} = Idr[{3}]")(fptype, k, this->m_Idrn.didx(k,0));
for (std::size_t i=1; i < net.count(); i++) for (std::size_t i=1; i < net.count(); i++)
terms += plib::pfmt(" + Idr[{1}]")(this->m_Idrn.didx(k,i)); terms += plib::pfmt(" + Idr[{1}]")(this->m_Idrn.didx(k,i));
@ -174,9 +181,21 @@ namespace solver
// RHS_t += (- go[i]) * *cnV[i]; // RHS_t += (- go[i]) * *cnV[i];
for (std::size_t i = net.railstart(); i < net.count(); i++) for (std::size_t i = net.railstart(); i < net.count(); i++)
terms += plib::pfmt(" - go[{1}] * *cnV[{1}]")(this->m_gonn.didx(k,i), this->m_connected_net_Vn.didx(k,i)); terms += plib::pfmt(" - go[{1}] * *cnV[{2}]")(this->m_gonn.didx(k,i), this->m_connected_net_Vn.didx(k,i));
strm("\t{1};\n", terms); strm("\t{1};\n", terms);
#else
//auto RHS_t(std::accumulate(Idr, Idr + term_count, plib::constants<FT>::zero()));
strm("\t{1} RHS{2} = Idr[{3}];\n", fptype, k, this->m_Idrn.didx(k,0));
for (std::size_t i=1; i < net.count(); i++)
strm("\tRHS{1} += Idr[{2}];\n", k, this->m_Idrn.didx(k,i));
//for (std::size_t i = railstart; i < term_count; i++)
// RHS_t += (- go[i]) * *cnV[i];
for (std::size_t i = net.railstart(); i < net.count(); i++)
strm("\tRHS{1} -= go[{2}] * *cnV[{3}];\n", k, this->m_gonn.didx(k,i), this->m_connected_net_Vn.didx(k,i));
#endif
} }
for (std::size_t i = 0; i < iN - 1; i++) for (std::size_t i = 0; i < iN - 1; i++)
@ -188,7 +207,7 @@ namespace solver
std::size_t pi = mat.diag[i]; std::size_t pi = mat.diag[i];
//const FT f = 1.0 / m_A[pi++]; //const FT f = 1.0 / m_A[pi++];
strm("const {1} f{2} = 1.0{3} / m_A{4};\n", fptype, i, fpsuffix, pi); strm("\tconst {1} f{2} = 1.0{3} / m_A{4};\n", fptype, i, fpsuffix, pi);
pi++; pi++;
const std::size_t piie = mat.row_idx[i+1]; const std::size_t piie = mat.row_idx[i+1];
@ -224,6 +243,7 @@ namespace solver
strm("\tV[{1}] = RHS{2} / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]); strm("\tV[{1}] = RHS{2} / m_A{3};\n", iN - 1, iN - 1, mat.diag[iN - 1]);
for (std::size_t j = iN - 1; j-- > 0;) for (std::size_t j = iN - 1; j-- > 0;)
{ {
#if 1
strm("\t{1} tmp{2} = 0.0{3};\n", fptype, j, fpsuffix); strm("\t{1} tmp{2} = 0.0{3};\n", fptype, j, fpsuffix);
const std::size_t e = mat.row_idx[j+1]; const std::size_t e = mat.row_idx[j+1];
for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++) for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
@ -231,6 +251,24 @@ namespace solver
strm("\ttmp{1} += m_A{2} * V[{3}];\n", j, pk, mat.col_idx[pk]); strm("\ttmp{1} += m_A{2} * V[{3}];\n", j, pk, mat.col_idx[pk]);
} }
strm("\tV[{1}] = (RHS{1} - tmp{1}) / m_A{4};\n", j, j, j, mat.diag[j]); strm("\tV[{1}] = (RHS{1} - tmp{1}) / m_A{4};\n", j, j, j, mat.diag[j]);
#else
pstring tmp;
const std::size_t e = mat.row_idx[j+1];
for (std::size_t pk = mat.diag[j] + 1; pk < e; pk++)
{
tmp = tmp + plib::pfmt(" + m_A{2} * V[{3}]")(j, pk, mat.col_idx[pk]);
}
if (tmp.empty())
{
strm("\tV[{1}] = RHS{1} / m_A{2};\n", j, mat.diag[j]);
}
else
{
//strm("\tconst {1} tmp{2} = {3};\n", fptype, j, tmp.substr(3));
//strm("\tV[{1}] = (RHS{1} - tmp{1}) / m_A{2};\n", j, mat.diag[j]);
strm("\tV[{1}] = (RHS{1} - ({2})) / m_A{3};\n", j, tmp.substr(3), mat.diag[j]);
}
#endif
} }
} }
@ -238,7 +276,7 @@ namespace solver
pstring matrix_solver_GCR_t<FT, SIZE>::static_compile_name() pstring matrix_solver_GCR_t<FT, SIZE>::static_compile_name()
{ {
pstring str_floattype(fp_constants<FT>::name()); pstring str_floattype(fp_constants<FT>::name());
pstring str_fptype(fp_constants<nl_fptype>::name()); pstring str_fptype(fp_constants<fptype>::name());
std::stringstream t; std::stringstream t;
t.imbue(std::locale::classic()); t.imbue(std::locale::classic());
plib::putf8_fmt_writer w(&t); plib::putf8_fmt_writer w(&t);
@ -255,7 +293,7 @@ namespace solver
plib::putf8_fmt_writer strm(&t); plib::putf8_fmt_writer strm(&t);
pstring name = static_compile_name(); pstring name = static_compile_name();
pstring str_floattype(fp_constants<FT>::name()); pstring str_floattype(fp_constants<FT>::name());
pstring str_fptype(fp_constants<nl_fptype>::name()); pstring str_fptype(fp_constants<fptype>::name());
pstring extqual; pstring extqual;
if (target == CXX_EXTERNAL_C) if (target == CXX_EXTERNAL_C)
@ -263,8 +301,8 @@ namespace solver
else if (target == CXX_STATIC) else if (target == CXX_STATIC)
extqual = "static"; extqual = "static";
strm.writeline(plib::pfmt("{1} void {2}({3} * __restrict V, " strm.writeline(plib::pfmt("{1} void {2}({3} * __restrict V, "
"{4} * __restrict go, {4} * __restrict gt, " "const {4} * __restrict go, const {4} * __restrict gt, "
"{4} * __restrict Idr, {4} ** __restrict cnV)\n")(extqual, name, str_floattype, str_fptype)); "const {4} * __restrict Idr, const {4} * const * __restrict cnV)\n")(extqual, name, str_floattype, str_fptype));
strm.writeline("{\n"); strm.writeline("{\n");
generate_code(strm); generate_code(strm);
strm.writeline("}\n"); strm.writeline("}\n");

View File

@ -8,6 +8,7 @@
/// \file nld_ms_gmres.h /// \file nld_ms_gmres.h
/// ///
#include "nld_matrix_solver_ext.h"
#include "nld_ms_direct.h" #include "nld_ms_direct.h"
#include "nld_solver.h" #include "nld_solver.h"
#include "plib/gmres.h" #include "plib/gmres.h"

View File

@ -33,6 +33,7 @@
/// ///
#include "nld_matrix_solver.h" #include "nld_matrix_solver.h"
#include "nld_matrix_solver_ext.h"
#include "nld_solver.h" #include "nld_solver.h"
#include "plib/vector_ops.h" #include "plib/vector_ops.h"

View File

@ -12,8 +12,8 @@
/// Fow w==1 we will do the classic Gauss-Seidel approach. /// Fow w==1 we will do the classic Gauss-Seidel approach.
/// ///
#include "nld_matrix_solver_ext.h"
#include "nld_ms_direct.h" #include "nld_ms_direct.h"
#include "nld_solver.h"
#include <algorithm> #include <algorithm>
@ -70,16 +70,19 @@ namespace solver
for (std::size_t k = 0; k < iN; k++) for (std::size_t k = 0; k < iN; k++)
{ {
nl_fptype gtot_t = nlconst::zero();
nl_fptype gabs_t = nlconst::zero();
nl_fptype RHS_t = nlconst::zero();
const std::size_t term_count = this->m_terms[k].count(); const std::size_t term_count = this->m_terms[k].count();
const nl_fptype * const gt = this->m_gtn[k]; const auto * const gt = this->m_gtn[k];
const nl_fptype * const go = this->m_gonn[k]; const auto * const go = this->m_gonn[k];
const nl_fptype * const Idr = this->m_Idrn[k]; const auto * const Idr = this->m_Idrn[k];
auto other_cur_analog = this->m_connected_net_Vn[k]; auto other_cur_analog = this->m_connected_net_Vn[k];
using fpaggtype = std::remove_reference_t<std::remove_cv_t<decltype(this->m_gtn[0][0])>>;
fpaggtype gtot_t = nlconst_base<fpaggtype>::zero();
fpaggtype gabs_t = nlconst_base<fpaggtype>::zero();
fpaggtype RHS_t = nlconst_base<fpaggtype>::zero();
this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV()); this->m_new_V[k] = static_cast<float_type>(this->m_terms[k].getV());
for (std::size_t i = 0; i < term_count; i++) for (std::size_t i = 0; i < term_count; i++)
@ -126,7 +129,7 @@ namespace solver
{ {
const int * net_other = this->m_terms[k].m_connected_net_idx.data(); const int * net_other = this->m_terms[k].m_connected_net_idx.data();
const std::size_t railstart = this->m_terms[k].railstart(); const std::size_t railstart = this->m_terms[k].railstart();
const nl_fptype * go = this->m_gonn[k]; const auto * go = this->m_gonn[k];
float_type Idrive = plib::constants<float_type>::zero(); float_type Idrive = plib::constants<float_type>::zero();
for (std::size_t i = 0; i < railstart; i++) for (std::size_t i = 0; i < railstart; i++)

View File

@ -12,9 +12,8 @@
/// For w==1 we will do the classic Gauss-Seidel approach /// For w==1 we will do the classic Gauss-Seidel approach
/// ///
#include "nld_matrix_solver.h" #include "nld_matrix_solver_ext.h"
#include "nld_ms_direct.h" #include "nld_ms_direct.h"
#include "nld_solver.h"
#include <algorithm> #include <algorithm>

View File

@ -40,8 +40,7 @@
/// introduces numerical instability. /// introduces numerical instability.
/// ///
#include "nld_matrix_solver.h" #include "nld_matrix_solver_ext.h"
#include "nld_solver.h"
#include "plib/vector_ops.h" #include "plib/vector_ops.h"
#include <algorithm> #include <algorithm>

View File

@ -87,7 +87,7 @@ namespace devices
analog_net_t::list_t &nets, analog_net_t::list_t &nets,
solver::solver_parameters_t &params, std::size_t size) solver::solver_parameters_t &params, std::size_t size)
{ {
return host_arena::make_unique<C>(nl, name, nets, &params, size); return plib::make_unique<C, host_arena>(nl, name, nets, &params, size);
} }
template <typename FT, int SIZE> template <typename FT, int SIZE>
@ -136,29 +136,21 @@ namespace devices
switch (net_count) switch (net_count)
{ {
case 1: case 1:
return host_arena::make_unique<solver::matrix_solver_direct1_t<FT>>(state(), sname, nets, &m_params); return plib::make_unique<solver::matrix_solver_direct1_t<FT>, host_arena>(state(), sname, nets, &m_params);
break;
case 2: case 2:
return host_arena::make_unique<solver::matrix_solver_direct2_t<FT>>(state(), sname, nets, &m_params); return plib::make_unique<solver::matrix_solver_direct2_t<FT>, host_arena>(state(), sname, nets, &m_params);
break;
case 3: case 3:
return create_solver<FT, 3>(3, sname, nets); return create_solver<FT, 3>(3, sname, nets);
break;
case 4: case 4:
return create_solver<FT, 4>(4, sname, nets); return create_solver<FT, 4>(4, sname, nets);
break;
case 5: case 5:
return create_solver<FT, 5>(5, sname, nets); return create_solver<FT, 5>(5, sname, nets);
break;
case 6: case 6:
return create_solver<FT, 6>(6, sname, nets); return create_solver<FT, 6>(6, sname, nets);
break;
case 7: case 7:
return create_solver<FT, 7>(7, sname, nets); return create_solver<FT, 7>(7, sname, nets);
break;
case 8: case 8:
return create_solver<FT, 8>(8, sname, nets); return create_solver<FT, 8>(8, sname, nets);
break;
default: default:
log().info(MI_NO_SPECIFIC_SOLVER(net_count)); log().info(MI_NO_SPECIFIC_SOLVER(net_count));
if (net_count <= 16) if (net_count <= 16)
@ -186,7 +178,6 @@ namespace devices
return create_solver<FT, -512>(net_count, sname, nets); return create_solver<FT, -512>(net_count, sname, nets);
} }
return create_solver<FT, 0>(net_count, sname, nets); return create_solver<FT, 0>(net_count, sname, nets);
break;
} }
} }
@ -201,7 +192,7 @@ namespace devices
{ {
netlist.log().verbose(" ==> not a rail net"); netlist.log().verbose(" ==> not a rail net");
// Must be an analog net // Must be an analog net
auto &n = *static_cast<analog_net_t *>(net.get()); auto &n = dynamic_cast<analog_net_t &>(*net);
if (!already_processed(n)) if (!already_processed(n))
{ {
groupspre.emplace_back(analog_net_t::list_t()); groupspre.emplace_back(analog_net_t::list_t());
@ -273,9 +264,9 @@ namespace devices
// only process analog terminals // only process analog terminals
if (term->is_type(detail::terminal_type::TERMINAL)) if (term->is_type(detail::terminal_type::TERMINAL))
{ {
auto *pt = static_cast<terminal_t *>(term); auto &pt = dynamic_cast<terminal_t &>(*term);
// check the connected terminal // check the connected terminal
analog_net_t &connected_net = netlist.setup().get_connected_terminal(*pt)->net(); analog_net_t &connected_net = netlist.setup().get_connected_terminal(pt)->net();
netlist.log().verbose(" Connected net {}", connected_net.name()); netlist.log().verbose(" Connected net {}", connected_net.name());
if (!check_if_processed_and_join(connected_net)) if (!check_if_processed_and_join(connected_net))
process_net(netlist, connected_net); process_net(netlist, connected_net);
@ -306,17 +297,17 @@ namespace devices
switch (m_params.m_fp_type()) switch (m_params.m_fp_type())
{ {
case solver::matrix_fp_type_e::FLOAT: case solver::matrix_fp_type_e::FLOAT:
if (!NL_USE_FLOAT_MATRIX) if (!config::use_float_matrix())
log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name()); log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name());
ms = create_solvers<std::conditional_t<NL_USE_FLOAT_MATRIX,float, double>>(sname, grp); ms = create_solvers<std::conditional_t<config::use_float_matrix::value, float, double>>(sname, grp);
break; break;
case solver::matrix_fp_type_e::DOUBLE: case solver::matrix_fp_type_e::DOUBLE:
ms = create_solvers<double>(sname, grp); ms = create_solvers<double>(sname, grp);
break; break;
case solver::matrix_fp_type_e::LONGDOUBLE: case solver::matrix_fp_type_e::LONGDOUBLE:
if (!NL_USE_LONG_DOUBLE_MATRIX) if (!config::use_long_double_matrix())
log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name()); log().info("FPTYPE {1} not supported. Using DOUBLE", m_params.m_fp_type().name());
ms = create_solvers<std::conditional_t<NL_USE_LONG_DOUBLE_MATRIX, long double, double>>(sname, grp); ms = create_solvers<std::conditional_t<config::use_long_double_matrix::value, long double, double>>(sname, grp);
break; break;
case solver::matrix_fp_type_e::FLOATQ128: case solver::matrix_fp_type_e::FLOATQ128:
#if (NL_USE_FLOAT128) #if (NL_USE_FLOAT128)
@ -355,7 +346,7 @@ namespace devices
for (auto & s : m_mat_solvers) for (auto & s : m_mat_solvers)
{ {
auto r = s->create_solver_code(target); auto r = s->create_solver_code(target);
if (r.first != "") // ignore solvers not supporting static compile if (!r.first.empty()) // ignore solvers not supporting static compile
mp.push_back(r); mp.push_back(r);
} }
return mp; return mp;

View File

@ -39,7 +39,7 @@ namespace devices
void post_start(); void post_start();
void stop(); void stop();
nl_fptype gmin() const { return m_params.m_gmin(); } auto gmin() const -> decltype(solver::solver_parameters_t::m_gmin()) { return m_params.m_gmin(); }
solver::static_compile_container create_solver_code(solver::static_compile_target target); solver::static_compile_container create_solver_code(solver::static_compile_target target);

View File

@ -112,7 +112,7 @@ nl_convert_base_t::~nl_convert_base_t()
void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias) void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias)
{ {
pstring pname = devname + "." + name; pstring pname = devname + "." + name;
m_pins.emplace(pname, arena::make_unique<pin_alias_t>(pname, devname + "." + alias)); m_pins.emplace(pname, plib::make_unique<pin_alias_t, arena>(pname, devname + "." + alias));
} }
void nl_convert_base_t::add_ext_alias(const pstring &alias) void nl_convert_base_t::add_ext_alias(const pstring &alias)
@ -138,15 +138,15 @@ void nl_convert_base_t::add_device(arena::unique_ptr<dev_t> dev)
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel) void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel)
{ {
add_device(arena::make_unique<dev_t>(atype, aname, amodel)); add_device(plib::make_unique<dev_t, arena>(atype, aname, amodel));
} }
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval) void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval)
{ {
add_device(arena::make_unique<dev_t>(atype, aname, aval)); add_device(plib::make_unique<dev_t, arena>(atype, aname, aval));
} }
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname) void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
{ {
add_device(arena::make_unique<dev_t>(atype, aname)); add_device(plib::make_unique<dev_t, arena>(atype, aname));
} }
void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname) void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname)
@ -161,7 +161,7 @@ void nl_convert_base_t::add_term(const pstring &netname, const pstring &termname
net = m_nets[netname].get(); net = m_nets[netname].get();
else else
{ {
auto nets = arena::make_unique<net_t>(netname); auto nets = plib::make_unique<net_t, arena>(netname);
net = nets.get(); net = nets.get();
m_nets.emplace(netname, std::move(nets)); m_nets.emplace(netname, std::move(nets));
} }
@ -245,6 +245,7 @@ void nl_convert_base_t::dump_nl()
} }
std::vector<size_t> sorted; std::vector<size_t> sorted;
sorted.reserve(m_devs.size());
for (size_t i=0; i < m_devs.size(); i++) for (size_t i=0; i < m_devs.size(); i++)
sorted.push_back(i); sorted.push_back(i);
std::sort(sorted.begin(), sorted.end(), std::sort(sorted.begin(), sorted.end(),
@ -436,7 +437,7 @@ static int npoly(const pstring &s)
void nl_convert_spice_t::process_line(const pstring &line) void nl_convert_spice_t::process_line(const pstring &line)
{ {
if (line != "") if (!line.empty())
{ {
//printf("// %s\n", line.c_str()); //printf("// %s\n", line.c_str());
std::vector<pstring> tt(plib::psplit(line, " ", true)); std::vector<pstring> tt(plib::psplit(line, " ", true));
@ -976,7 +977,7 @@ void nl_convert_rinf_t::convert(const pstring &contents)
pstring sim = attr["Simulation"]; pstring sim = attr["Simulation"];
pstring val = attr["Value"]; pstring val = attr["Value"];
pstring com = attr["Comment"]; pstring com = attr["Comment"];
if (val == "") if (val.empty())
val = com; val = com;
if (sim == "CAP") if (sim == "CAP")