mirror of
https://github.com/holub/mame
synced 2025-06-30 07:58:56 +03:00
Netlist: Add global parameter to disable semi-conductor capacitance
modelling. [Couriersud] Added global NETLIST.DEFAULT_MOS_CAPMODEL parameter. Setting this to zero disables using capitance modelling in mos models. On a per mos device basis this can be achieved by adding CAPMODEL=0 to the model definition, e.g. MOSFET(X, "NMOS(CAPMODEL=0)") Improve MOSFET convergence by using log-stepping.
This commit is contained in:
parent
b8a104748e
commit
980dbcc693
@ -19,7 +19,7 @@ NETLIST_START(cmos_inverter_clk)
|
||||
//SOLVER(Solver, 100000000000)
|
||||
PARAM(Solver.ACCURACY, 1e-7 )
|
||||
PARAM(Solver.NR_LOOPS, 500000)
|
||||
PARAM(Solver.DYNAMIC_TS, 1)
|
||||
PARAM(Solver.DYNAMIC_TS, 0)
|
||||
PARAM(Solver.DYNAMIC_LTE, 1e-5)
|
||||
PARAM(Solver.DYNAMIC_MIN_TIMESTEP, 2e-8)
|
||||
ANALOG_INPUT(V5, 5)
|
||||
@ -28,6 +28,7 @@ NETLIST_START(cmos_inverter_clk)
|
||||
|
||||
#if (USE_CLOCK)
|
||||
CLOCK(V, 5000)
|
||||
PARAM(NETLIST.DEFAULT_MOS_CAPMODEL, 0) // Disable capacitance modeling
|
||||
//CLOCK(V, 500000)
|
||||
#else
|
||||
VS(V, 5)
|
||||
|
@ -37,11 +37,17 @@ namespace analog
|
||||
// nld_FET - Base classes
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
/*! Class representing the nmos model paramers.
|
||||
/*! Class representing the nmos/pmos model paramers.
|
||||
*
|
||||
* This is the model representation of the nmos model. Typically, SPICE uses
|
||||
* the following parameters. A "Y" in the first column indicates that the
|
||||
* parameter is actually used in netlist.
|
||||
* This is the model representation of the nmos model.
|
||||
*
|
||||
* Netlist has an additional parameter caller CAPMOD:
|
||||
*
|
||||
* CAPMOD=0: Capacitance model disabled
|
||||
* CAPMOD=2: Meyer capacitance model
|
||||
*
|
||||
* Typically, SPICE uses the following parameters. A "Y" in the first
|
||||
* column indicates that the parameter is actually used in netlist.
|
||||
*
|
||||
* | NL? |Name | Description|Units |Default |Example |
|
||||
* |:---:|------|-----------------------------------------------------------------------|-------|---------:|----------------:|
|
||||
@ -115,6 +121,7 @@ namespace analog
|
||||
, m_CGSO(*this, "CGSO")
|
||||
, m_CGDO(*this, "CGDO")
|
||||
, m_CGBO(*this, "CGBO")
|
||||
, m_CAPMOD(*this, "CAPMOD")
|
||||
{}
|
||||
|
||||
value_t m_VTO; //!< Threshold voltage [V]
|
||||
@ -136,6 +143,7 @@ namespace analog
|
||||
value_t m_CGSO; //!< Gate-source overlap capacitance per meter channel width
|
||||
value_t m_CGDO; //!< Gate-drain overlap capacitance per meter channel width
|
||||
value_t m_CGBO; //!< Gate-bulk overlap capacitance per meter channel width
|
||||
value_base_t<int> m_CAPMOD; //!< Capacitance model (0=no model 2=Meyer)
|
||||
};
|
||||
|
||||
// Have a common start for mosfets
|
||||
@ -198,7 +206,9 @@ namespace analog
|
||||
, m_Cgb(0.0)
|
||||
, m_Cgs(0.0)
|
||||
, m_Cgd(0.0)
|
||||
|
||||
, m_capmod(2)
|
||||
, m_Vgs(*this, "m_Vgs", 0.0)
|
||||
, m_Vgd(*this, "m_Vgd", 0.0)
|
||||
{
|
||||
register_subalias("S", m_SG.m_P); // Source
|
||||
register_subalias("G", m_SG.m_N); // Gate
|
||||
@ -209,34 +219,33 @@ namespace analog
|
||||
connect(m_SG.m_N, m_DG.m_N);
|
||||
connect(m_DG.m_P, m_SD.m_N);
|
||||
|
||||
#if 0
|
||||
if (m_model.m_CJE > 0.0)
|
||||
{
|
||||
create_and_register_subdevice("m_CJE", m_CJE);
|
||||
connect("B", "m_CJE.1");
|
||||
connect("E", "m_CJE.2");
|
||||
}
|
||||
if (m_model.m_CJC > 0.0)
|
||||
{
|
||||
create_and_register_subdevice("m_CJC", m_CJC);
|
||||
connect("B", "m_CJC.1");
|
||||
connect("C", "m_CJC.2");
|
||||
}
|
||||
#endif
|
||||
set_qtype((m_model.model_type() == "NMOS_DEFAULT") ? FET_NMOS : FET_PMOS);
|
||||
m_polarity = qtype() == FET_NMOS ? 1.0 : -1.0;
|
||||
|
||||
m_capmod = m_model.m_CAPMOD;
|
||||
// printf("capmod %d %g %g\n", m_capmod, (double)m_model.m_VTO, m_polarity);
|
||||
nl_assert_always(m_capmod == 0 || m_capmod == 2, "Error: CAPMODEL invalid value for " + m_model.name());
|
||||
|
||||
//printf("%g\n", exec().solver()->gmin());
|
||||
}
|
||||
|
||||
NETLIB_IS_TIMESTEP(true)
|
||||
NETLIB_IS_TIMESTEP(true || m_capmod != 0)
|
||||
|
||||
NETLIB_TIMESTEPI()
|
||||
{
|
||||
const nl_double Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
const nl_double Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
|
||||
const nl_double Ubs = 0.0; // Bulk - Source == 0 if connected
|
||||
const nl_double Ugb = Ugs - Ubs;
|
||||
if (m_capmod != 0)
|
||||
{
|
||||
//const nl_double Ugd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
//const nl_double Ugs = -m_SG.deltaV() * m_polarity; // Gate - Source
|
||||
const nl_double Ugd = m_Vgd; // Gate - Drain
|
||||
const nl_double Ugs = m_Vgs; // Gate - Source
|
||||
const nl_double Ubs = 0.0; // Bulk - Source == 0 if connected
|
||||
const nl_double Ugb = Ugs - Ubs;
|
||||
|
||||
m_cap_gb.timestep(m_Cgb, Ugb, step);
|
||||
m_cap_gs.timestep(m_Cgs, Ugs, step);
|
||||
m_cap_gd.timestep(m_Cgd, Ugd, step);
|
||||
m_cap_gb.timestep(m_Cgb, Ugb, step);
|
||||
m_cap_gs.timestep(m_Cgs, Ugs, step);
|
||||
m_cap_gd.timestep(m_Cgd, Ugd, step);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -261,7 +270,6 @@ namespace analog
|
||||
generic_capacitor<capacitor_e::VARIABLE_CAPACITY> m_cap_gs;
|
||||
generic_capacitor<capacitor_e::VARIABLE_CAPACITY> m_cap_gd;
|
||||
|
||||
|
||||
nl_double m_phi;
|
||||
nl_double m_gamma;
|
||||
nl_double m_vto;
|
||||
@ -279,6 +287,10 @@ namespace analog
|
||||
nl_double m_Cgs;
|
||||
nl_double m_Cgd;
|
||||
|
||||
int m_capmod;
|
||||
state_var<nl_double> m_Vgs;
|
||||
state_var<nl_double> m_Vgd;
|
||||
|
||||
void set_cap(generic_capacitor<capacitor_e::VARIABLE_CAPACITY> cap,
|
||||
nl_double capval, nl_double V,
|
||||
nl_double &g11, nl_double &g12, nl_double &g21, nl_double &g22,
|
||||
@ -313,7 +325,7 @@ namespace analog
|
||||
else if (Vctrl <= 0)
|
||||
{
|
||||
Cgb = -Vctrl * m_CoxWL / m_phi;
|
||||
Cgs = (Vctrl * m_CoxWL * (4.0 / 3.0) / m_phi + (2.0 / 3.0) * m_CoxWL);
|
||||
Cgs = Vctrl * m_CoxWL * (4.0 / 3.0) / m_phi + (2.0 / 3.0) * m_CoxWL;
|
||||
Cgd = 0.0;
|
||||
}
|
||||
else
|
||||
@ -361,11 +373,24 @@ namespace analog
|
||||
|
||||
NETLIB_UPDATE_TERMINALS(MOSFET)
|
||||
{
|
||||
const nl_double Vgd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
const nl_double Vgs = -m_SG.deltaV() * m_polarity; // Gate - Source
|
||||
nl_double Vgd = -m_DG.deltaV() * m_polarity; // Gate - Drain
|
||||
nl_double Vgs = -m_SG.deltaV() * m_polarity; // Gate - Source
|
||||
|
||||
// limit step sizes
|
||||
|
||||
const nl_double k = 3.5; // see "Circuit Simulation", page 185
|
||||
nl_double d = (Vgs - m_Vgs);
|
||||
Vgs = m_Vgs + 1.0/k * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
|
||||
d = (Vgd - m_Vgd);
|
||||
Vgd = m_Vgd + 1.0/k * (d < 0 ? -1.0 : 1.0) * std::log1p(k * std::abs(d));
|
||||
|
||||
m_Vgs = Vgs;
|
||||
m_Vgd = Vgd;
|
||||
|
||||
const nl_double Vbs = 0.0; // Bulk - Source == 0 if connected
|
||||
const nl_double Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain
|
||||
//const nl_double Vbd = m_SD.deltaV() * m_polarity; // Bulk - Drain = Source - Drain
|
||||
const nl_double Vds = Vgs - Vgd;
|
||||
const nl_double Vbd = -Vds; // Bulk - Drain = Source - Drain
|
||||
|
||||
#if (!BODY_CONNECTED_TO_SOURCE)
|
||||
m_D_BS.update_diode(Vbs);
|
||||
@ -425,6 +450,7 @@ namespace analog
|
||||
|
||||
const nl_double IeqBD = m_D_BD.Ieq();
|
||||
const nl_double gbd = m_D_BD.G();
|
||||
|
||||
#if (!BODY_CONNECTED_TO_SOURCE)
|
||||
const nl_double IeqBS = m_D_BS.Ieq();
|
||||
const nl_double gbs = m_D_BS.G();
|
||||
@ -466,16 +492,19 @@ namespace analog
|
||||
const nl_double gBS = -gbs;
|
||||
nl_double gBB = gbs + gbd;
|
||||
|
||||
const nl_double Vgb = Vgs - Vbs;
|
||||
if (m_capmod != 0)
|
||||
{
|
||||
const nl_double Vgb = Vgs - Vbs;
|
||||
|
||||
if (is_forward)
|
||||
calculate_caps(Vgs, Vgd, Vth, m_Cgs, m_Cgd, m_Cgb);
|
||||
else
|
||||
calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb);
|
||||
if (is_forward)
|
||||
calculate_caps(Vgs, Vgd, Vth, m_Cgs, m_Cgd, m_Cgb);
|
||||
else
|
||||
calculate_caps(Vgd, Vgs, Vth, m_Cgd, m_Cgs, m_Cgb);
|
||||
|
||||
set_cap(m_cap_gb, m_Cgb + m_model.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
|
||||
set_cap(m_cap_gs, m_Cgs + m_model.m_CGSO * m_model.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
|
||||
set_cap(m_cap_gd, m_Cgd + m_model.m_CGDO * m_model.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
|
||||
set_cap(m_cap_gb, m_Cgb + m_model.m_CGBO * m_Leff, Vgb, gGG, gGB, gBG, gBB, IG, IB);
|
||||
set_cap(m_cap_gs, m_Cgs + m_model.m_CGSO * m_model.m_W, Vgs, gGG, gGS, gSG, gSS, IG, IS);
|
||||
set_cap(m_cap_gd, m_Cgd + m_model.m_CGDO * m_model.m_W, Vgd, gGG, gGD, gDG, gDD, IG, ID);
|
||||
}
|
||||
|
||||
// Source connected to body, Diode S-B shorted!
|
||||
const nl_double gSSBB = gSS + gBB + gBS + gSB;
|
||||
@ -493,9 +522,6 @@ namespace analog
|
||||
|
||||
NETLIB_UPDATE_PARAM(MOSFET)
|
||||
{
|
||||
set_qtype((m_model.model_type() == "NMOS") ? FET_NMOS : FET_PMOS);
|
||||
m_polarity = qtype() == FET_NMOS ? 1.0 : -1.0;
|
||||
|
||||
/*
|
||||
* From http://ltwiki.org/LTspiceHelp/LTspiceHelp/M_MOSFET.htm :
|
||||
*
|
||||
|
@ -459,6 +459,7 @@ public:
|
||||
set_param(1e-15, 1, 1e-15, 300.0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void update_diode(const double nVd)
|
||||
{
|
||||
if (TYPE == diode_e::BIPOLAR && nVd < m_Vmin)
|
||||
@ -491,11 +492,48 @@ public:
|
||||
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void set_param(const double Is, const double n, double gmin, double temp)
|
||||
#else
|
||||
void update_diode(const nl_double nVd)
|
||||
{
|
||||
nl_double IseVDVt(0.0);
|
||||
|
||||
if (TYPE == diode_e::BIPOLAR && nVd < m_Vmin)
|
||||
{
|
||||
m_Vd = nVd;
|
||||
m_G = m_gmin;
|
||||
m_Id = - m_Is;
|
||||
}
|
||||
else if (TYPE == diode_e::MOS && nVd < constants::zero())
|
||||
{
|
||||
m_Vd = nVd;
|
||||
m_G = m_Is * m_VtInv + m_gmin;
|
||||
m_Id = m_G * m_Vd;
|
||||
}
|
||||
else if (/*TYPE == diode_e::MOS || */nVd < m_Vcrit)
|
||||
{
|
||||
m_Vd = nVd;
|
||||
IseVDVt = std::exp(std::min(300.0, m_logIs + m_Vd * m_VtInv));
|
||||
m_Id = IseVDVt - m_Is;
|
||||
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TYPE == diode_e::MOS && m_Vd < constants::zero())
|
||||
m_Vd = std::min(m_Vmin, nVd);
|
||||
|
||||
const nl_double d = (nVd - m_Vd);
|
||||
const nl_double a = std::abs(nVd - m_Vd) * m_VtInv;
|
||||
m_Vd = m_Vd + (d < 0 ? -1.0 : 1.0) * std::log1p(a) * m_Vt;
|
||||
IseVDVt = std::exp(m_logIs + m_Vd * m_VtInv);
|
||||
//const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
|
||||
m_Id = IseVDVt - m_Is;
|
||||
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_param(const nl_double Is, const nl_double n, nl_double gmin, nl_double temp)
|
||||
{
|
||||
static constexpr double csqrt2 = 1.414213562373095048801688724209; //std::sqrt(2.0);
|
||||
m_Is = Is;
|
||||
m_logIs = std::log(Is);
|
||||
m_n = n;
|
||||
@ -505,32 +543,33 @@ public:
|
||||
|
||||
m_Vmin = -5.0 * m_Vt;
|
||||
|
||||
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
|
||||
m_VtInv = 1.0 / m_Vt;
|
||||
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / constants::sqrt2());
|
||||
m_VtInv = constants::one() / m_Vt;
|
||||
//printf("%g %g\n", m_Vmin, m_Vcrit);
|
||||
}
|
||||
|
||||
|
||||
double I() const { return m_Id; }
|
||||
double G() const { return m_G; }
|
||||
double Ieq() const { return (m_Id - m_Vd * m_G); }
|
||||
double Vd() const { return m_Vd; }
|
||||
nl_double I() const { return m_Id; }
|
||||
nl_double G() const { return m_G; }
|
||||
nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
|
||||
nl_double Vd() const { return m_Vd; }
|
||||
|
||||
/* owning object must save those ... */
|
||||
|
||||
private:
|
||||
state_var<double> m_Vd;
|
||||
state_var<double> m_Id;
|
||||
state_var<double> m_G;
|
||||
state_var<nl_double> m_Vd;
|
||||
state_var<nl_double> m_Id;
|
||||
state_var<nl_double> m_G;
|
||||
|
||||
double m_Vt;
|
||||
double m_Vmin;
|
||||
double m_Is;
|
||||
double m_logIs;
|
||||
double m_n;
|
||||
double m_gmin;
|
||||
nl_double m_Vt;
|
||||
nl_double m_Vmin;
|
||||
nl_double m_Is;
|
||||
nl_double m_logIs;
|
||||
nl_double m_n;
|
||||
nl_double m_gmin;
|
||||
|
||||
double m_VtInv;
|
||||
double m_Vcrit;
|
||||
nl_double m_VtInv;
|
||||
nl_double m_Vcrit;
|
||||
};
|
||||
|
||||
/*! Class representing the diode model paramers.
|
||||
|
@ -29,6 +29,7 @@ namespace netlist
|
||||
NETLIB_CONSTRUCTOR(netlistparams)
|
||||
, m_use_deactivate(*this, "USE_DEACTIVATE", false)
|
||||
, m_startup_strategy(*this, "STARTUP_STRATEGY", 1)
|
||||
, m_mos_capmodel(*this, "DEFAULT_MOS_CAPMODEL", 2)
|
||||
{
|
||||
}
|
||||
NETLIB_UPDATEI() { }
|
||||
@ -37,6 +38,7 @@ namespace netlist
|
||||
public:
|
||||
param_logic_t m_use_deactivate;
|
||||
param_int_t m_startup_strategy;
|
||||
param_int_t m_mos_capmodel;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -28,16 +28,22 @@ static NETLIST_START(diode_models)
|
||||
NETLIST_END()
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* BJT Models
|
||||
* Mosfet Models
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
static NETLIST_START(mosfet_models)
|
||||
//NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
|
||||
//NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=2E-5 UO=600 PHI=0.6 LD=0.0 L=1.0 TOX=1E-7 W=1.0 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0)")
|
||||
NET_MODEL("NMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)")
|
||||
NET_MODEL("PMOS _(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)")
|
||||
|
||||
// NMOS_DEFAULT and PMOS_DEFAULT are created in nl_setup.cpp
|
||||
NET_MODEL("NMOS NMOS_DEFAULT(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)")
|
||||
NET_MODEL("PMOS PMOS_DEFAULT(VTO=0.0 N=1.0 IS=1E-14 KP=0.0 UO=600 PHI=0.0 LD=0.0 L=100e-6 TOX=1E-7 W=100e-6 NSUB=0.0 GAMMA=0.0 RD=0.0 RS=0.0 LAMBDA=0.0 CGSO=0 CGDO=0 CGBO=0)")
|
||||
NETLIST_END()
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* BJT Models
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
static NETLIST_START(bjt_models)
|
||||
NET_MODEL("NPN _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)")
|
||||
NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1 CJE=0 CJC=0)")
|
||||
|
@ -1036,20 +1036,24 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
|
||||
class value_t
|
||||
template <typename T>
|
||||
class value_base_t
|
||||
{
|
||||
public:
|
||||
value_t(param_model_t ¶m, const pstring &name)
|
||||
: m_value(param.model_value(name))
|
||||
value_base_t(param_model_t ¶m, const pstring &name)
|
||||
: m_value(static_cast<T>(param.model_value(name)))
|
||||
{
|
||||
}
|
||||
double operator()() const noexcept { return m_value; }
|
||||
operator double() const noexcept { return m_value; }
|
||||
T operator()() const noexcept { return m_value; }
|
||||
operator T() const noexcept { return m_value; }
|
||||
private:
|
||||
const double m_value;
|
||||
const T m_value;
|
||||
};
|
||||
|
||||
friend class value_t;
|
||||
using value_t = value_base_t<nl_double>;
|
||||
|
||||
template <typename T>
|
||||
friend class value_base_t;
|
||||
|
||||
param_model_t(device_t &device, const pstring &name, const pstring &val)
|
||||
: param_str_t(device, name, val) { }
|
||||
|
@ -1043,6 +1043,11 @@ void setup_t::prepare_to_run()
|
||||
auto solver = m_nlstate.get_single_device<devices::NETLIB_NAME(solver)>("solver");
|
||||
m_netlist_params = m_nlstate.get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
|
||||
|
||||
/* set default model parameters */
|
||||
|
||||
m_models.register_model(plib::pfmt("NMOS_DEFAULT _(CAPMOD={1})")(m_netlist_params->m_mos_capmodel()));
|
||||
m_models.register_model(plib::pfmt("PMOS_DEFAULT _(CAPMOD={1})")(m_netlist_params->m_mos_capmodel()));
|
||||
|
||||
/* create devices */
|
||||
|
||||
log().debug("Creating devices ...\n");
|
||||
|
@ -65,6 +65,7 @@ namespace plib
|
||||
static constexpr T zero() noexcept { return static_cast<T>(0); }
|
||||
static constexpr T one() noexcept { return static_cast<T>(1); }
|
||||
static constexpr T two() noexcept { return static_cast<T>(2); }
|
||||
static constexpr T sqrt2() noexcept { return static_cast<T>(1.414213562373095048801688724209); }
|
||||
|
||||
/*!
|
||||
* \brief Electric constant of vacuum
|
||||
|
Loading…
Reference in New Issue
Block a user