summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib
diff options
context:
space:
mode:
authorGravatarGravatar couriersud <couriersud@gmx.org>2019-11-03 15:08:41 +0100
committerGravatarGravatar couriersud <couriersud@gmx.org>2019-11-03 15:25:01 +0100
commit34ccb11c536056deeb8ec3b2c36aeb064f70f844 (patch)
tree6ab710fb000703517636b78d1024809994d5e224 /src/lib
parent36c17abc7993de82454ac45d7193ae6e6f2f9455 (diff)
netlist: Completed __float128 support. [Couriersud]
Both compiling the core and the shaders with __float128 now work. The support was added to be ready to deal with academic edge cases. Performance drops to 10% of double - thus disabled by default.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/netlist/analog/nld_bjt.cpp6
-rw-r--r--src/lib/netlist/analog/nld_generic_models.h12
-rw-r--r--src/lib/netlist/analog/nld_mosfet.cpp18
-rw-r--r--src/lib/netlist/analog/nld_opamps.cpp2
-rw-r--r--src/lib/netlist/analog/nlid_fourterm.cpp6
-rw-r--r--src/lib/netlist/analog/nlid_twoterm.cpp8
-rw-r--r--src/lib/netlist/build/makefile4
-rw-r--r--src/lib/netlist/devices/nld_74123.cpp2
-rw-r--r--src/lib/netlist/nl_config.h22
-rw-r--r--src/lib/netlist/nl_setup.cpp6
-rw-r--r--src/lib/netlist/nl_setup.h8
-rw-r--r--src/lib/netlist/plib/pfmtlog.h5
-rw-r--r--src/lib/netlist/plib/pfunction.cpp11
-rw-r--r--src/lib/netlist/plib/pfunction.h4
-rw-r--r--src/lib/netlist/plib/ptime.h20
-rw-r--r--src/lib/netlist/plib/putil.h196
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.cpp2
-rw-r--r--src/lib/netlist/solver/nld_matrix_solver.h4
-rw-r--r--src/lib/netlist/solver/nld_ms_sor.h2
19 files changed, 281 insertions, 57 deletions
diff --git a/src/lib/netlist/analog/nld_bjt.cpp b/src/lib/netlist/analog/nld_bjt.cpp
index d96754daede..6a314c919f7 100644
--- a/src/lib/netlist/analog/nld_bjt.cpp
+++ b/src/lib/netlist/analog/nld_bjt.cpp
@@ -37,9 +37,9 @@ namespace analog
m_VT = nlconst::magic(0.0258) * n;
m_VT_inv = plib::reciprocal(m_VT);
}
- nl_fptype I(const nl_fptype V) const { return m_Is * std::exp(V * m_VT_inv) - m_Is; }
- nl_fptype g(const nl_fptype V) const { return m_Is * m_VT_inv * std::exp(V * m_VT_inv); }
- nl_fptype V(const nl_fptype I) const { return std::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
+ nl_fptype I(const nl_fptype V) const { return m_Is * plib::exp(V * m_VT_inv) - m_Is; }
+ nl_fptype g(const nl_fptype V) const { return m_Is * m_VT_inv * plib::exp(V * m_VT_inv); }
+ nl_fptype V(const nl_fptype I) const { return plib::log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
nl_fptype gI(const nl_fptype I) const { return m_VT_inv * (I + m_Is); }
private:
diff --git a/src/lib/netlist/analog/nld_generic_models.h b/src/lib/netlist/analog/nld_generic_models.h
index b7412641d5e..5eac70b6ed4 100644
--- a/src/lib/netlist/analog/nld_generic_models.h
+++ b/src/lib/netlist/analog/nld_generic_models.h
@@ -163,8 +163,8 @@ namespace analog
if (nVd > m_Vcrit)
{
const nl_fptype d = std::min(+fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd - m_Vd);
- const nl_fptype a = std::abs(d) * m_VtInv;
- m_Vd = m_Vd + nlconst::magic(d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt;
+ const nl_fptype a = plib::abs(d) * m_VtInv;
+ m_Vd = m_Vd + nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(a) * m_Vt;
}
else
m_Vd = std::max(-fp_constants<nl_fptype>::DIODE_MAXDIFF(), nVd);
@@ -177,7 +177,7 @@ namespace analog
}
else
{
- IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
+ IseVDVt = plib::exp(m_logIs + m_Vd * m_VtInv);
m_Id = IseVDVt - m_Is;
m_G = IseVDVt * m_VtInv + m_gmin;
}
@@ -193,7 +193,7 @@ namespace analog
else /* log stepping should already be done in mosfet */
{
m_Vd = nVd;
- IseVDVt = std::exp(std::min(+fp_constants<nl_fptype>::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv));
+ IseVDVt = plib::exp(std::min(+fp_constants<nl_fptype>::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv));
m_Id = IseVDVt - m_Is;
m_G = IseVDVt * m_VtInv + m_gmin;
}
@@ -203,7 +203,7 @@ namespace analog
void set_param(const nl_fptype Is, const nl_fptype n, nl_fptype gmin, nl_fptype temp)
{
m_Is = Is;
- m_logIs = std::log(Is);
+ m_logIs = plib::log(Is);
m_n = n;
m_gmin = gmin;
@@ -211,7 +211,7 @@ namespace analog
m_Vmin = nlconst::magic(-5.0) * m_Vt;
- m_Vcrit = m_Vt * std::log(m_Vt / m_Is / nlconst::sqrt2());
+ m_Vcrit = m_Vt * plib::log(m_Vt / m_Is / nlconst::sqrt2());
m_VtInv = nlconst::one() / m_Vt;
//printf("%g %g\n", m_Vmin, m_Vcrit);
}
diff --git a/src/lib/netlist/analog/nld_mosfet.cpp b/src/lib/netlist/analog/nld_mosfet.cpp
index da73b129e88..5780c598ac5 100644
--- a/src/lib/netlist/analog/nld_mosfet.cpp
+++ b/src/lib/netlist/analog/nld_mosfet.cpp
@@ -263,7 +263,7 @@ namespace analog
else if (m_model.m_NSUB > nlconst::zero())
{
nl_assert_always(m_model.m_NSUB * nlconst::magic(1e6) >= constants::NiSi(), "Error calculating phi for model " + m_model.name());
- m_phi = nlconst::two() * Vt * std::log (m_model.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
+ m_phi = nlconst::two() * Vt * plib::log (m_model.m_NSUB * nlconst::magic(1e6) / constants::NiSi());
}
else
m_phi = nlconst::magic(0.6);
@@ -274,7 +274,7 @@ namespace analog
else
{
if (Cox > nlconst::zero() && m_model.m_NSUB > nlconst::zero())
- m_gamma = std::sqrt (nlconst::two()
+ m_gamma = plib::sqrt (nlconst::two()
* constants::Q_e() * constants::eps_Si() * constants::eps_0()
* m_model.m_NSUB * nlconst::magic(1e6)) / Cox;
else
@@ -418,8 +418,8 @@ namespace analog
else
{
// linear
- const nl_fptype Sqr1 = static_cast<nl_fptype>(std::pow(Vdsat - Vds, 2));
- const nl_fptype Sqr2 = static_cast<nl_fptype>(std::pow(nlconst::two() * Vdsat - Vds, 2));
+ const nl_fptype Sqr1 = static_cast<nl_fptype>(plib::pow(Vdsat - Vds, 2));
+ const nl_fptype Sqr2 = static_cast<nl_fptype>(plib::pow(nlconst::two() * Vdsat - Vds, 2));
Cgb = 0;
Cgs = m_CoxWL * (nlconst::one() - Sqr1 / Sqr2) * nlconst::magic(2.0 / 3.0);
Cgd = m_CoxWL * (nlconst::one() - Vdsat * Vdsat / Sqr2) * nlconst::magic(2.0 / 3.0);
@@ -452,9 +452,9 @@ namespace analog
const nl_fptype k = nlconst::magic(3.5); // see "Circuit Simulation", page 185
nl_fptype d = (Vgs - m_Vgs);
- Vgs = m_Vgs + plib::reciprocal(k) * nlconst::magic(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
+ Vgs = m_Vgs + plib::reciprocal(k) * nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(k * plib::abs(d));
d = (Vgd - m_Vgd);
- Vgd = m_Vgd + plib::reciprocal(k) * nlconst::magic(d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
+ Vgd = m_Vgd + plib::reciprocal(k) * nlconst::magic(d < 0 ? -1.0 : 1.0) * plib::log1p(k * plib::abs(d));
m_Vgs = Vgs;
m_Vgd = Vgd;
@@ -475,13 +475,13 @@ namespace analog
// calculate Vth
const nl_fptype Vbulk = is_forward ? Vbs : Vbd;
- const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? std::sqrt(m_phi - Vbulk) : nlconst::zero();
- const nl_fptype Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - std::sqrt(m_phi));
+ const nl_fptype phi_m_Vbulk = (m_phi > Vbulk) ? plib::sqrt(m_phi - Vbulk) : nlconst::zero();
+ const nl_fptype Vth = m_vto * m_polarity + m_gamma * (phi_m_Vbulk - plib::sqrt(m_phi));
const nl_fptype Vctrl = (is_forward ? Vgs : Vgd) - Vth;
nl_fptype Ids(0), gm(0), gds(0), gmb(0);
- const nl_fptype absVds = std::abs(Vds);
+ const nl_fptype absVds = plib::abs(Vds);
if (Vctrl <= nlconst::zero())
{
diff --git a/src/lib/netlist/analog/nld_opamps.cpp b/src/lib/netlist/analog/nld_opamps.cpp
index 2756262cc4a..692fea19931 100644
--- a/src/lib/netlist/analog/nld_opamps.cpp
+++ b/src/lib/netlist/analog/nld_opamps.cpp
@@ -199,7 +199,7 @@ namespace netlist
{
const nl_fptype cVt = nlconst::magic(0.0258 * 1.0); // * m_n;
const nl_fptype cId = m_model.m_DAB; // 3 mA
- const nl_fptype cVd = cVt * std::log(cId / nlconst::magic(1e-15) + nlconst::one());
+ const nl_fptype cVd = cVt * plib::log(cId / nlconst::magic(1e-15) + nlconst::one());
m_VH.push(m_VCC() - m_model.m_VLH - cVd);
m_VL.push(m_GND() + m_model.m_VLL + cVd);
diff --git a/src/lib/netlist/analog/nlid_fourterm.cpp b/src/lib/netlist/analog/nlid_fourterm.cpp
index c4fdedbe1a9..73fc2d53c8d 100644
--- a/src/lib/netlist/analog/nlid_fourterm.cpp
+++ b/src/lib/netlist/analog/nlid_fourterm.cpp
@@ -69,13 +69,13 @@ NETLIB_UPDATE_TERMINALS(LVCCS)
const nl_fptype vi = m_IP.net().Q_Analog() - m_IN.net().Q_Analog();
const auto c1(nlconst::magic(0.2));
- if (std::abs(m_mult / m_cur_limit() * vi) > nlconst::half())
- m_vi = m_vi + c1 * std::tanh((vi - m_vi) / c1);
+ if (plib::abs(m_mult / m_cur_limit() * vi) > nlconst::half())
+ m_vi = m_vi + c1 * plib::tanh((vi - m_vi) / c1);
else
m_vi = vi;
const nl_fptype x = m_mult / m_cur_limit() * m_vi;
- const nl_fptype X = std::tanh(x);
+ const nl_fptype X = plib::tanh(x);
const nl_fptype beta = m_mult * (nlconst::one() - X*X);
const nl_fptype I = m_cur_limit() * X - beta * m_vi;
diff --git a/src/lib/netlist/analog/nlid_twoterm.cpp b/src/lib/netlist/analog/nlid_twoterm.cpp
index 2234afd5cd6..073e657d369 100644
--- a/src/lib/netlist/analog/nlid_twoterm.cpp
+++ b/src/lib/netlist/analog/nlid_twoterm.cpp
@@ -64,7 +64,7 @@ NETLIB_RESET(POT)
{
nl_fptype v = m_Dial();
if (m_DialIsLog())
- v = (std::exp(v) - nlconst::one()) / (std::exp(nlconst::one()) - nlconst::one());
+ v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one());
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
m_R2.set_R(std::max(m_R() * (nlconst::one() - v), exec().gmin()));
@@ -77,7 +77,7 @@ NETLIB_UPDATE_PARAM(POT)
nl_fptype v = m_Dial();
if (m_DialIsLog())
- v = (std::exp(v) - nlconst::one()) / (std::exp(nlconst::one()) - nlconst::one());
+ v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one());
if (m_Reverse())
v = nlconst::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
@@ -94,7 +94,7 @@ NETLIB_RESET(POT2)
nl_fptype v = m_Dial();
if (m_DialIsLog())
- v = (std::exp(v) - nlconst::one()) / (std::exp(nlconst::one()) - nlconst::one());
+ v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one());
if (m_Reverse())
v = nlconst::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
@@ -108,7 +108,7 @@ NETLIB_UPDATE_PARAM(POT2)
nl_fptype v = m_Dial();
if (m_DialIsLog())
- v = (std::exp(v) - nlconst::one()) / (std::exp(nlconst::one()) - nlconst::one());
+ v = (plib::exp(v) - nlconst::one()) / (plib::exp(nlconst::one()) - nlconst::one());
if (m_Reverse())
v = nlconst::one() - v;
m_R1.set_R(std::max(m_R() * v, exec().gmin()));
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index 072192860e0..51f43550a8d 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -52,7 +52,7 @@ endif
CFLAGS = $(LTO) -g -O3 -std=c++14 -I$(CURDIR)/.. -I$(CURDIR)/../.. $(CEXTRAFLAGS)
LDFLAGS = $(LTO) -g -O3 -std=c++14 $(LDEXTRAFLAGS)
-LIBS = -lpthread -ldl
+LIBS = -lpthread -ldl $(EXTRALIBS)
CC = g++
LD = @g++
@@ -235,7 +235,7 @@ native:
$(MAKE) CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
gcc9:
- $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra "
+ $(MAKE) CC=g++-9 LD=g++-9 CEXTRAFLAGS="-march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra" EXTRALIBS="-lquadmath"
clang:
$(MAKE) CC=clang++-10 LD=clang++-10 CEXTRAFLAGS="-march=native -msse4.2 -Weverything -Werror -Wno-padded -Wno-weak-vtables -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"
diff --git a/src/lib/netlist/devices/nld_74123.cpp b/src/lib/netlist/devices/nld_74123.cpp
index e601a792a8c..a80e8c5fd0d 100644
--- a/src/lib/netlist/devices/nld_74123.cpp
+++ b/src/lib/netlist/devices/nld_74123.cpp
@@ -255,7 +255,7 @@ namespace netlist
NETLIB_RESET(74123)
{
- m_KP = plib::reciprocal(nlconst::one() + std::exp(m_K()));
+ m_KP = plib::reciprocal(nlconst::one() + plib::exp(m_K()));
m_RP.reset();
m_RN.reset();
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 9baad43ac44..1add7136dcc 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -107,13 +107,17 @@
static constexpr const auto NETLIST_INTERNAL_RES = 1000000000;
static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES;
-//============================================================
-// Floating point types used
-//
-// Don't change this. Simple analog circuits like pong
-// work with float. Kidniki just doesn't work at all
-// due to numeric issues
-//============================================================
+/*! Floating point types used
+ *
+ * nl_fptype is the floating point type used throughout the
+ * netlist core.
+ *
+ * Don't change this! Simple analog circuits like pong
+ * work with float. Kidniki just doesn't work at all.
+ *
+ * FIXME: More work needed. Review magic numbers.
+ *
+ */
using nl_fptype = double;
@@ -162,8 +166,8 @@ namespace netlist
template <>
struct fp_constants<float>
{
- static inline constexpr float DIODE_MAXDIFF() noexcept { return 1e2; }
- static inline constexpr float DIODE_MAXVOLT() noexcept { return 20.0; }
+ static inline constexpr float DIODE_MAXDIFF() noexcept { return 1e20; }
+ static inline constexpr float DIODE_MAXVOLT() noexcept { return 90.0; }
static inline constexpr float TIMESTEP_MAXDIFF() noexcept { return 1e30f; }
static inline constexpr float TIMESTEP_MINDIV() noexcept { return 1e-8f; }
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 5c8936a9bca..efc503069e9 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -121,8 +121,8 @@ namespace netlist
void nlparse_t::register_param_x(const pstring &param, const nl_fptype value)
{
- if (std::abs(value - std::floor(value)) > nlconst::magic(1e-30)
- || std::abs(value) > nlconst::magic(1e9))
+ if (plib::abs(value - plib::floor(value)) > nlconst::magic(1e-30)
+ || plib::abs(value) > nlconst::magic(1e9))
register_param(param, plib::pfmt("{1:.9}").e(value));
else
register_param(param, plib::pfmt("{1}")(static_cast<long>(value)));
@@ -1126,7 +1126,7 @@ void setup_t::prepare_to_run()
//FIXME: check for errors ...
bool err(false);
auto v = plib::pstonum_ne<nl_fptype>(p->second, err);
- if (err || std::abs(v - std::floor(v)) > nlconst::magic(1e-6) )
+ if (err || plib::abs(v - plib::floor(v)) > nlconst::magic(1e-6) )
log().fatal(MF_HND_VAL_NOT_SUPPORTED(p->second));
// FIXME comparison with zero
d.second->set_hint_deactivate(v == nlconst::zero());
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 7d34f66d91a..9c6e91e68dc 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -247,6 +247,7 @@ namespace netlist
// FIXME: quick hack
void register_param_x(const pstring &param, const nl_fptype value);
+
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value || std::is_integral<T>::value>::type
register_param(const pstring &param, T value)
@@ -254,6 +255,13 @@ namespace netlist
register_param_x(param, static_cast<nl_fptype>(value));
}
+#if PUSE_FLOAT128
+ void register_param(const pstring &param, __float128 value)
+ {
+ register_param_x(param, static_cast<nl_fptype>(value));
+ }
+#endif
+
void register_lib_entry(const pstring &name, const pstring &sourcefile);
void register_frontier(const pstring &attach, const nl_fptype r_IN, const nl_fptype r_OUT);
diff --git a/src/lib/netlist/plib/pfmtlog.h b/src/lib/netlist/plib/pfmtlog.h
index fd1f073cb73..df0463cbb61 100644
--- a/src/lib/netlist/plib/pfmtlog.h
+++ b/src/lib/netlist/plib/pfmtlog.h
@@ -192,6 +192,11 @@ public:
typename std::enable_if<std::is_floating_point<T>::value, pfmt &>::type
e(const T &x) {return format_element('e', x); }
+#if PUSE_FLOAT128
+ // FIXME: not what we want
+ pfmt & e(const __float128 &x) {return format_element('e', static_cast<long double>(x)); }
+#endif
+
template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, pfmt &>::type
g(const T &x) {return format_element('g', x); }
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index 48939c8236a..db6e491e988 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -206,10 +206,10 @@ namespace plib {
OP(MULT, 1, ST2 * ST1)
OP(SUB, 1, ST2 - ST1)
OP(DIV, 1, ST2 / ST1)
- OP(POW, 1, std::pow(ST2, ST1))
- OP(SIN, 0, std::sin(ST2))
- OP(COS, 0, std::cos(ST2))
- OP(TRUNC, 0, std::trunc(ST2))
+ OP(POW, 1, plib::pow(ST2, ST1))
+ OP(SIN, 0, plib::sin(ST2))
+ OP(COS, 0, plib::cos(ST2))
+ OP(TRUNC, 0, plib::trunc(ST2))
case RAND:
stack[ptr++] = lfsr_random();
break;
@@ -227,5 +227,8 @@ namespace plib {
template class pfunction<float>;
template class pfunction<double>;
template class pfunction<long double>;
+#if (PUSE_FLOAT128)
+ template class pfunction<__float128>;
+#endif
} // namespace plib
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index d1f4d8c3da4..b2a42a54e14 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -118,7 +118,9 @@ namespace plib {
extern template class pfunction<float>;
extern template class pfunction<double>;
extern template class pfunction<long double>;
-
+#if (PUSE_FLOAT128)
+ extern template class pfunction<__float128>;
+#endif
} // namespace plib
#endif /* PEXCEPTION_H_ */
diff --git a/src/lib/netlist/plib/ptime.h b/src/lib/netlist/plib/ptime.h
index f6972d9f41e..9f253a269bd 100644
--- a/src/lib/netlist/plib/ptime.h
+++ b/src/lib/netlist/plib/ptime.h
@@ -100,13 +100,21 @@ namespace plib
constexpr internal_type as_raw() const noexcept { return m_time; }
- template <typename FT>
- constexpr typename std::enable_if<std::is_floating_point<FT>::value, FT>::type
+ template <typename FT, typename = std::enable_if<std::is_floating_point<FT>::value, FT>>
+ constexpr FT
as_fp() const noexcept
{
return static_cast<FT>(m_time) * inv_res<FT>();
}
+#if PUSE_FLOAT128
+ constexpr __float128
+ as_fp() const noexcept
+ {
+ return static_cast<__float128>(m_time) * inv_res<__float128>();
+ }
+#endif
+
constexpr double as_double() const noexcept { return as_fp<double>(); }
constexpr double as_float() const noexcept { return as_fp<float>(); }
constexpr double as_long_double() const noexcept { return as_fp<long double>(); }
@@ -122,8 +130,12 @@ namespace plib
static constexpr const ptime from_raw(const internal_type raw) noexcept { return ptime(raw); }
template <typename FT>
- static constexpr const typename std::enable_if<std::is_floating_point<FT>::value, ptime>::type
- from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(std::floor(t * static_cast<FT>(RES) + static_cast<FT>(0.5))), RES); }
+ static constexpr const typename std::enable_if<std::is_floating_point<FT>::value
+#if PUSE_FLOAT128
+ || std::is_same<FT, __float128>::value
+#endif
+ , ptime>::type
+ from_fp(const FT t) noexcept { return ptime(static_cast<internal_type>(plib::floor(t * static_cast<FT>(RES) + static_cast<FT>(0.5))), RES); }
static constexpr const ptime from_double(const double t) noexcept
{ return from_fp<double>(t); }
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index e575a9adc73..7cd54f2f43f 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -314,9 +314,10 @@ namespace plib
/*! hypot function
*
- * @tparam T type of the argument
- * @param v argument
- * @return absolute value of argument
+ * @tparam T type of the arguments
+ * @param v1 first argument
+ * @param v1 second argument
+ * @return sqrt(v1*v1+v2*v2)
*/
template <typename T>
static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
@@ -325,6 +326,127 @@ namespace plib
return std::hypot(v1, v2);
}
+ /*! exp function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return exp(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ exp(T v) noexcept
+ {
+ return std::exp(v);
+ }
+
+ /*! log function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return log(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ log(T v) noexcept
+ {
+ return std::log(v);
+ }
+
+ /*! tanh function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return tanh(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ tanh(T v) noexcept
+ {
+ return std::tanh(v);
+ }
+
+ /*! floor function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return floor(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ floor(T v) noexcept
+ {
+ return std::floor(v);
+ }
+
+ /*! log1p function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return log(1 + v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ log1p(T v) noexcept
+ {
+ return std::log1p(v);
+ }
+
+ /*! sin function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return sin(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ sin(T v) noexcept
+ {
+ return std::sin(v);
+ }
+
+ /*! cos function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return cos(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ cos(T v) noexcept
+ {
+ return std::cos(v);
+ }
+
+ /*! trunc function
+ *
+ * @tparam T type of the argument
+ * @param v argument
+ * @return trunc(v)
+ */
+ template <typename T>
+ static inline constexpr typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ trunc(T v) noexcept
+ {
+ return std::trunc(v);
+ }
+
+ /*! pow function
+ *
+ * @tparam T1 type of the first argument
+ * @tparam T2 type of the second argument
+ * @param v argument
+ * @param p power
+ * @return v^p
+ *
+ * FIXME: limited implementation
+ */
+ template <typename T1, typename T2>
+ static inline T1
+ pow(T1 v, T2 p) noexcept
+ {
+ return std::pow(v, p);
+ }
+
#if (PUSE_FLOAT128)
static inline constexpr __float128 reciprocal(__float128 v) noexcept
{
@@ -345,6 +467,61 @@ namespace plib
{
return hypotq(v1, v2);
}
+
+ static inline __float128 exp(__float128 v) noexcept
+ {
+ return expq(v);
+ }
+
+ static inline __float128 log(__float128 v) noexcept
+ {
+ return logq(v);
+ }
+
+ static inline __float128 tanh(__float128 v) noexcept
+ {
+ return tanhq(v);
+ }
+
+ static inline __float128 floor(__float128 v) noexcept
+ {
+ return floorq(v);
+ }
+
+ static inline __float128 log1p(__float128 v) noexcept
+ {
+ return log1pq(v);
+ }
+
+ static inline __float128 sin(__float128 v) noexcept
+ {
+ return sinq(v);
+ }
+
+ static inline __float128 cos(__float128 v) noexcept
+ {
+ return cosq(v);
+ }
+
+ static inline __float128 trunc(__float128 v) noexcept
+ {
+ return truncq(v);
+ }
+
+ template <typename T>
+ static inline __float128 pow(__float128 v, T p) noexcept
+ {
+ return powq(v, static_cast<__float128>(p));
+ }
+
+ static inline __float128 pow(__float128 v, int p) noexcept
+ {
+ if (p==2)
+ return v*v;
+ else
+ return powq(v, static_cast<__float128>(p));
+ }
+
#endif
static_assert(noexcept(constants<double>::one()) == true, "Not evaluated as constexpr");
@@ -430,6 +607,19 @@ namespace plib
}
};
+#if PUSE_FLOAT128
+ template<>
+ struct pstonum_helper<__float128>
+ {
+ // FIXME: use strtoflt128 from quadmath.h
+ template <typename S>
+ __float128 operator()(std::locale loc, const S &arg, std::size_t *idx)
+ {
+ return static_cast<__float128>(pstonum_locale<long double>(loc, arg, idx));
+ }
+ };
+#endif
+
template<typename T, typename S>
T pstonum(const S &arg, const std::locale &loc = std::locale::classic())
{
diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp
index e33421d08b8..a9ae7ec82a1 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.cpp
+++ b/src/lib/netlist/solver/nld_matrix_solver.cpp
@@ -514,7 +514,7 @@ namespace solver
if (colu==row) colu = static_cast<unsigned>(diag);
else if (colu==diag) colu = static_cast<unsigned>(row);
- weight = weight + std::abs(static_cast<nl_fptype>(colu) - static_cast<nl_fptype>(diag));
+ weight = weight + plib::abs(static_cast<nl_fptype>(colu) - static_cast<nl_fptype>(diag));
touched[colu] = true;
}
}
diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h
index 26f6ea149a7..ffa58979289 100644
--- a/src/lib/netlist/solver/nld_matrix_solver.h
+++ b/src/lib/netlist/solver/nld_matrix_solver.h
@@ -476,8 +476,8 @@ namespace solver
m_h_n_m_1[k] = hn;
m_DD_n_m_1[k] = DD_n;
- if (std::fabs(DD2) > fp_constants<nl_fptype>::TIMESTEP_MINDIV()) // avoid div-by-zero
- new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(nlconst::magic(0.5)*DD2));
+ 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::magic(0.5)*DD2));
else
new_net_timestep = m_params.m_max_timestep;
diff --git a/src/lib/netlist/solver/nld_ms_sor.h b/src/lib/netlist/solver/nld_ms_sor.h
index 56075fa090e..7ee7dea6742 100644
--- a/src/lib/netlist/solver/nld_ms_sor.h
+++ b/src/lib/netlist/solver/nld_ms_sor.h
@@ -96,7 +96,7 @@ namespace solver
if (this->m_params.m_use_gabs)
{
for (std::size_t i = 0; i < term_count; i++)
- gabs_t = gabs_t + std::abs(go[i]);
+ gabs_t = gabs_t + plib::abs(go[i]);
gabs_t *= nlconst::magic(0.5); // derived by try and error
if (gabs_t <= gtot_t)