netlist: Performance improvement and refactoring. [Couriersud]
Kidniki now achieves up to 910% when run with static solvers and with nltool. That is significant better than the 860% we have seen previously. This increase is driven by using a global memory pool in the solver code. In addition the following refactoring and code maintenance work is included. Please excuse the large commit, some of this took interfered with other work and the detail development steps were ugly. - gsl support: This commit adds pgsl.h which implements a very limited number of the functionality of the gsl header described in the c++ core guidelines. - clang-tidy fixes - A significant refactoring of palloc.h. Aligned hints were removed, they added complexity without a significant performance gain. Vector operations should better be done on special spans/views. The code has been tested on linux with g++-7, g++-9, clang-11. On Windows mingw-10 and VS2019, OSX clang-11.
This commit is contained in:
parent
75681d760c
commit
e949e9c29d
@ -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",
|
||||||
|
@ -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());
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
|
@ -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;
|
||||||
|
@ -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:
|
||||||
|
@ -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(),
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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("");
|
||||||
@ -856,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -871,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 ¶m, const pstring &name)
|
value_base_t(P ¶m, 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>;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
@ -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)
|
||||||
|
@ -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 ¶m, const pstring &value)
|
void nlparse_t::register_param(const pstring ¶m, 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)
|
||||||
|
@ -307,10 +307,10 @@ namespace netlist
|
|||||||
void register_param(const pstring ¶m, nl_fptype value);
|
void register_param(const pstring ¶m, 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 ¶m, T value)
|
register_param_val(const pstring ¶m, 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);
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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(); }
|
||||||
};
|
};
|
||||||
|
@ -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_
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -43,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() {\
|
||||||
|
@ -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)
|
||||||
|
@ -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));
|
||||||
|
@ -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)...));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
105
src/lib/netlist/plib/pgsl.h
Normal 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_
|
@ -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:
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
95
src/lib/netlist/plib/pmatrix2d.h
Normal file → Executable file
95
src/lib/netlist/plib/pmatrix2d.h
Normal file → Executable file
@ -17,70 +17,102 @@
|
|||||||
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)
|
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_N = N;
|
||||||
m_M = M;
|
m_M = M;
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr T * operator[] (size_type row) noexcept
|
constexpr pointer operator[] (size_type row) noexcept
|
||||||
{
|
{
|
||||||
return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
|
return &m_v[m_stride * row];
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const T * operator[] (size_type row) const noexcept
|
constexpr const_pointer operator[] (size_type row) const noexcept
|
||||||
{
|
{
|
||||||
return assume_aligned_ptr<T, align_size>(&m_v[m_stride * row]);
|
return &m_v[m_stride * row];
|
||||||
}
|
}
|
||||||
|
|
||||||
T & operator()(size_type r, size_type c) noexcept
|
reference operator()(size_type r, size_type c) noexcept
|
||||||
{
|
{
|
||||||
return (*this)[r][c];
|
return (*this)[r][c];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T & operator()(size_type r, size_type c) const noexcept
|
const_reference operator()(size_type r, size_type c) const noexcept
|
||||||
{
|
{
|
||||||
return (*this)[r][c];
|
return (*this)[r][c];
|
||||||
}
|
}
|
||||||
|
|
||||||
// for compatibility with vrl variant
|
// for compatibility with vrl variant
|
||||||
void set(size_type r, size_type c, const T &v) noexcept
|
void set(size_type r, size_type c, const value_type &v) noexcept
|
||||||
{
|
{
|
||||||
(*this)[r][c] = v;
|
(*this)[r][c] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
T * data() noexcept
|
pointer data() noexcept
|
||||||
{
|
{
|
||||||
return m_v.data();
|
return m_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T * data() const noexcept
|
const_pointer data() const noexcept
|
||||||
{
|
{
|
||||||
return m_v.data();
|
return m_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_type didx(size_type r, size_type c) const noexcept
|
size_type didx(size_type r, size_type c) const noexcept
|
||||||
@ -93,20 +125,23 @@ namespace plib
|
|||||||
size_type m_M;
|
size_type m_M;
|
||||||
size_type m_stride;
|
size_type m_stride;
|
||||||
|
|
||||||
std::vector<T, A> m_v;
|
T * __restrict m_v;
|
||||||
|
|
||||||
|
allocator_type m_a;
|
||||||
};
|
};
|
||||||
|
|
||||||
// variable row length matrix
|
// variable row length matrix
|
||||||
template<typename T, typename A = aligned_allocator<T>>
|
template<typename T, typename A = aligned_arena>
|
||||||
class pmatrix2d_vrl
|
class pmatrix2d_vrl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using size_type = std::size_t;
|
using size_type = std::size_t;
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
using allocator_type = A;
|
using arena_type = A;
|
||||||
|
using allocator_type = typename A::template allocator_type<T>;
|
||||||
|
|
||||||
static constexpr const size_type align_size = align_traits<A>::align_size;
|
static constexpr const size_type align_size = align_traits<allocator_type>::align_size;
|
||||||
static constexpr const size_type stride_size = align_traits<A>::stride_size;
|
static constexpr const size_type stride_size = align_traits<allocator_type>::stride_size;
|
||||||
pmatrix2d_vrl() noexcept
|
pmatrix2d_vrl() noexcept
|
||||||
: m_N(0), m_M(0), m_v()
|
: m_N(0), m_M(0), m_v()
|
||||||
{
|
{
|
||||||
@ -139,24 +174,24 @@ namespace plib
|
|||||||
return &(m_v[m_row[row]]);
|
return &(m_v[m_row[row]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
//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];
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
void set(size_type r, size_type c, const T &v) noexcept
|
void set(size_type r, size_type c, const T &v) noexcept
|
||||||
{
|
{
|
||||||
if (c + m_row[r] >= m_row[r + 1])
|
if (c + m_row[r] >= m_row[r + 1])
|
||||||
{
|
{
|
||||||
m_v.insert(m_v.begin() + m_row[r+1], v);
|
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++)
|
for (size_type i = r + 1; i <= m_N; i++)
|
||||||
m_row[i] = m_row[i] + 1;
|
m_row[i] = m_row[i] + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(*this)[r][c] = v;
|
(*this)[r][c] = v;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
//FIXME: no check!
|
//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
|
||||||
{
|
{
|
||||||
@ -184,8 +219,8 @@ namespace plib
|
|||||||
|
|
||||||
size_type m_N;
|
size_type m_N;
|
||||||
size_type m_M;
|
size_type m_M;
|
||||||
std::vector<size_type, A> m_row;
|
std::vector<size_type, typename A::template allocator_type<size_type>> m_row;
|
||||||
std::vector<T, A> m_v;
|
std::vector<T, allocator_type> m_v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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, "")});
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
|
@ -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>;
|
||||||
|
@ -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); \
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
@ -724,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))
|
||||||
@ -821,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() + "(...)");
|
||||||
@ -945,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());
|
||||||
@ -967,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("///", "");
|
||||||
@ -1020,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);
|
||||||
|
@ -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());
|
||||||
|
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
@ -432,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);
|
||||||
}
|
}
|
||||||
@ -489,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);
|
||||||
}
|
}
|
||||||
@ -534,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)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
@ -543,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++)
|
||||||
{
|
{
|
||||||
@ -556,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,58 +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;
|
||||||
|
|
||||||
#if 0
|
plib::pmatrix2d_vrl<fptype, arena_type> m_gonn;
|
||||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gonn;
|
plib::pmatrix2d_vrl<fptype, arena_type> m_gtn;
|
||||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_gtn;
|
plib::pmatrix2d_vrl<fptype, arena_type> m_Idrn;
|
||||||
plib::pmatrix2d<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn;
|
plib::pmatrix2d_vrl<fptype *, arena_type> m_connected_net_Vn;
|
||||||
plib::pmatrix2d<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn;
|
|
||||||
#else
|
|
||||||
plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_gonn;
|
|
||||||
plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_gtn;
|
|
||||||
plib::pmatrix2d_vrl<nl_fptype, aligned_alloc<nl_fptype>> m_Idrn;
|
|
||||||
plib::pmatrix2d_vrl<nl_fptype *, aligned_alloc<nl_fptype *>> m_connected_net_Vn;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@ -321,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);
|
||||||
|
|
||||||
@ -332,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 > = 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
288
src/lib/netlist/solver/nld_matrix_solver_ext.h
Normal file
288
src/lib/netlist/solver/nld_matrix_solver_ext.h
Normal 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 > = 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_
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -273,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);
|
||||||
@ -290,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)
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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++)
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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>
|
||||||
|
@ -87,7 +87,7 @@ namespace devices
|
|||||||
analog_net_t::list_t &nets,
|
analog_net_t::list_t &nets,
|
||||||
solver::solver_parameters_t ¶ms, std::size_t size)
|
solver::solver_parameters_t ¶ms, std::size_t size)
|
||||||
{
|
{
|
||||||
return host_arena::make_unique<C>(nl, name, nets, ¶ms, size);
|
return plib::make_unique<C, host_arena>(nl, name, nets, ¶ms, 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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
Loading…
Reference in New Issue
Block a user