From 34ccb11c536056deeb8ec3b2c36aeb064f70f844 Mon Sep 17 00:00:00 2001 From: couriersud Date: Sun, 3 Nov 2019 15:08:41 +0100 Subject: 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. --- src/lib/netlist/analog/nld_bjt.cpp | 6 +- src/lib/netlist/analog/nld_generic_models.h | 12 +- src/lib/netlist/analog/nld_mosfet.cpp | 18 +-- src/lib/netlist/analog/nld_opamps.cpp | 2 +- src/lib/netlist/analog/nlid_fourterm.cpp | 6 +- src/lib/netlist/analog/nlid_twoterm.cpp | 8 +- src/lib/netlist/build/makefile | 4 +- src/lib/netlist/devices/nld_74123.cpp | 2 +- src/lib/netlist/nl_config.h | 22 +-- src/lib/netlist/nl_setup.cpp | 6 +- src/lib/netlist/nl_setup.h | 8 ++ src/lib/netlist/plib/pfmtlog.h | 5 + src/lib/netlist/plib/pfunction.cpp | 11 +- src/lib/netlist/plib/pfunction.h | 4 +- src/lib/netlist/plib/ptime.h | 20 ++- src/lib/netlist/plib/putil.h | 196 ++++++++++++++++++++++++++- src/lib/netlist/solver/nld_matrix_solver.cpp | 2 +- src/lib/netlist/solver/nld_matrix_solver.h | 4 +- src/lib/netlist/solver/nld_ms_sor.h | 2 +- 19 files changed, 281 insertions(+), 57 deletions(-) (limited to 'src/lib') 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::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::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::DIODE_MAXVOLT(), m_logIs + m_Vd * m_VtInv)); + IseVDVt = plib::exp(std::min(+fp_constants::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(std::pow(Vdsat - Vds, 2)); - const nl_fptype Sqr2 = static_cast(std::pow(nlconst::two() * Vdsat - Vds, 2)); + const nl_fptype Sqr1 = static_cast(plib::pow(Vdsat - Vds, 2)); + const nl_fptype Sqr2 = static_cast(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 { - 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 ¶m, 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(value))); @@ -1126,7 +1126,7 @@ void setup_t::prepare_to_run() //FIXME: check for errors ... bool err(false); auto v = plib::pstonum_ne(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 ¶m, const nl_fptype value); + template typename std::enable_if::value || std::is_integral::value>::type register_param(const pstring ¶m, T value) @@ -254,6 +255,13 @@ namespace netlist register_param_x(param, static_cast(value)); } +#if PUSE_FLOAT128 + void register_param(const pstring ¶m, __float128 value) + { + register_param_x(param, static_cast(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::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(x)); } +#endif + template typename std::enable_if::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; template class pfunction; template class pfunction; +#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; extern template class pfunction; extern template class pfunction; - +#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 - constexpr typename std::enable_if::value, FT>::type + template ::value, FT>> + constexpr FT as_fp() const noexcept { return static_cast(m_time) * inv_res(); } +#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(); } constexpr double as_float() const noexcept { return as_fp(); } constexpr double as_long_double() const noexcept { return as_fp(); } @@ -122,8 +130,12 @@ namespace plib static constexpr const ptime from_raw(const internal_type raw) noexcept { return ptime(raw); } template - static constexpr const typename std::enable_if::value, ptime>::type - from_fp(const FT t) noexcept { return ptime(static_cast(std::floor(t * static_cast(RES) + static_cast(0.5))), RES); } + static constexpr const typename std::enable_if::value +#if PUSE_FLOAT128 + || std::is_same::value +#endif + , ptime>::type + from_fp(const FT t) noexcept { return ptime(static_cast(plib::floor(t * static_cast(RES) + static_cast(0.5))), RES); } static constexpr const ptime from_double(const double t) noexcept { return from_fp(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 static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + static inline constexpr typename std::enable_if::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 + 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 + 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::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 + __float128 operator()(std::locale loc, const S &arg, std::size_t *idx) + { + return static_cast<__float128>(pstonum_locale(loc, arg, idx)); + } + }; +#endif + template 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(diag); else if (colu==diag) colu = static_cast(row); - weight = weight + std::abs(static_cast(colu) - static_cast(diag)); + weight = weight + plib::abs(static_cast(colu) - static_cast(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::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::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) -- cgit v1.2.3