From beab34006a43ba74d462fe85e68d8d41b3c3c0a4 Mon Sep 17 00:00:00 2001 From: couriersud Date: Wed, 30 Oct 2019 19:10:40 +0100 Subject: netlist: code maintenance. (nw) Simplification, remove some trampolines. --- src/devices/machine/netlist.cpp | 2 +- src/lib/netlist/devices/nld_2102A.cpp | 2 +- src/lib/netlist/devices/nld_82S16.cpp | 2 +- src/lib/netlist/devices/nld_am2847.cpp | 2 +- src/lib/netlist/devices/nlid_proxy.cpp | 10 +- src/lib/netlist/devices/nlid_system.h | 4 +- src/lib/netlist/nl_base.cpp | 23 ++-- src/lib/netlist/nl_base.h | 168 +++++++++++++-------------- src/lib/netlist/nl_config.h | 7 -- src/lib/netlist/plib/pstate.h | 6 +- src/lib/netlist/solver/nld_matrix_solver.cpp | 32 ++--- src/lib/netlist/solver/nld_matrix_solver.h | 19 ++- src/lib/netlist/solver/nld_solver.h | 4 - 13 files changed, 141 insertions(+), 140 deletions(-) diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index e94b4517890..fcf94d6e3f7 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -522,7 +522,7 @@ public: if (i != m_num_channels) state().log().fatal("sound input numbering has to be sequential!"); m_num_channels++; - m_channels[i].m_param = dynamic_cast(setup().find_param((*m_channels[i].m_param_name)(), true)); + m_channels[i].m_param = dynamic_cast(state().setup().find_param((*m_channels[i].m_param_name)(), true)); } } } diff --git a/src/lib/netlist/devices/nld_2102A.cpp b/src/lib/netlist/devices/nld_2102A.cpp index 54922ad71cf..342c35312f0 100644 --- a/src/lib/netlist/devices/nld_2102A.cpp +++ b/src/lib/netlist/devices/nld_2102A.cpp @@ -41,7 +41,7 @@ namespace netlist logic_output_t m_DO; - state_array m_ram; // 1024x1 bits + state_container> m_ram; // 1024x1 bits param_ptr_t m_RAM; nld_power_pins m_power_pins; }; diff --git a/src/lib/netlist/devices/nld_82S16.cpp b/src/lib/netlist/devices/nld_82S16.cpp index cce10063061..631e75bdc14 100644 --- a/src/lib/netlist/devices/nld_82S16.cpp +++ b/src/lib/netlist/devices/nld_82S16.cpp @@ -76,7 +76,7 @@ namespace netlist logic_input_t m_DIN; logic_output_t m_DOUTQ; - state_array m_ram; // 256 bits + state_container> m_ram; // 256 bits state_var_u8 m_addr; // 256 bits state_var_sig m_enq; nld_power_pins m_power_pins; diff --git a/src/lib/netlist/devices/nld_am2847.cpp b/src/lib/netlist/devices/nld_am2847.cpp index 8153274e523..1a64767873c 100644 --- a/src/lib/netlist/devices/nld_am2847.cpp +++ b/src/lib/netlist/devices/nld_am2847.cpp @@ -32,7 +32,7 @@ namespace netlist logic_input_t m_RC; logic_input_t m_IN; - state_array m_buffer; + state_container> m_buffer; logic_output_t m_OUT; nld_power_pins m_power_pins; diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index fe42f5e8582..444d1c32540 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -92,9 +92,9 @@ namespace netlist for (auto & pwr_sym : power_syms) { pstring devname = out_proxied->device().name(); - auto tp_t = setup().find_terminal(devname + "." + pwr_sym.first, + auto tp_t = state().setup().find_terminal(devname + "." + pwr_sym.first, /*detail::terminal_type::INPUT,*/ false); - auto tn_t = setup().find_terminal(devname + "." + pwr_sym.second, + auto tn_t = state().setup().find_terminal(devname + "." + pwr_sym.second, /*detail::terminal_type::INPUT,*/ false); if (f && (tp_t != nullptr && tn_t != nullptr)) log().warning(MI_MULTIPLE_POWER_TERMINALS_ON_DEVICE(out_proxied->device().name(), @@ -113,9 +113,9 @@ namespace netlist if (!f) { if (logic_family()->fixed_V() == 0.0) - log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name()))); + log().error(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); else - log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(setup().de_alias(out_proxied->device().name()))); + log().info(MI_NO_POWER_TERMINALS_ON_DEVICE_1(state().setup().de_alias(out_proxied->device().name()))); m_GNDHack = plib::make_unique(*this, "_QGND"); m_VCCHack = plib::make_unique(*this, "_QVCC"); @@ -126,7 +126,7 @@ namespace netlist else { log().verbose("D/A Proxy: Found power terminals on device {1}", out_proxied->device().name()); - if (setup().is_extended_validation()) + if (state().setup().is_extended_validation()) { // During validation, don't connect to terminals found // This will cause terminals not connected to a rail net to diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h index bed4c2bb8d2..611a2eff6af 100644 --- a/src/lib/netlist/devices/nlid_system.h +++ b/src/lib/netlist/devices/nlid_system.h @@ -231,7 +231,7 @@ namespace devices /* make sure we get the family first */ , m_FAMILY(*this, "FAMILY", "FAMILY(TYPE=TTL)") { - set_logic_family(setup().family_from_model(m_FAMILY())); + set_logic_family(state().setup().family_from_model(m_FAMILY())); m_Q.set_logic_family(this->logic_family()); } @@ -438,7 +438,7 @@ namespace devices nld_power_pins(device_t &owner, const pstring &sVCC = "VCC", const pstring &sGND = "GND", bool force_analog_input = false) { - if (owner.setup().is_extended_validation() || force_analog_input) + if (owner.state().setup().is_extended_validation() || force_analog_input) { m_GND = plib::make_unique(owner, sGND, NETLIB_DELEGATE(power_pins, noop)); m_VCC = plib::make_unique(owner, sVCC, NETLIB_DELEGATE(power_pins, noop)); diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index d69f61df2db..209992d1562 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -561,7 +561,7 @@ namespace netlist : core_device_t(owner, name) { } - +#if 0 setup_t &device_t::setup() noexcept { return state().setup(); @@ -571,13 +571,14 @@ namespace netlist { return state().setup(); } +#endif void device_t::register_subalias(const pstring &name, detail::core_terminal_t &term) { pstring alias = this->name() + "." + name; // everything already fully qualified - setup().register_alias_nofqn(alias, term.name()); + state().setup().register_alias_nofqn(alias, term.name()); } void device_t::register_subalias(const pstring &name, const pstring &aliased) @@ -586,17 +587,17 @@ namespace netlist pstring aliased_fqn = this->name() + "." + aliased; // everything already fully qualified - setup().register_alias_nofqn(alias, aliased_fqn); + state().setup().register_alias_nofqn(alias, aliased_fqn); } void device_t::connect(detail::core_terminal_t &t1, detail::core_terminal_t &t2) { - setup().register_link_fqn(t1.name(), t2.name()); + state().setup().register_link_fqn(t1.name(), t2.name()); } void device_t::connect(const pstring &t1, const pstring &t2) { - setup().register_link_fqn(name() + "." + t1, name() + "." + t2); + state().setup().register_link_fqn(name() + "." + t1, name() + "." + t2); } /* FIXME: this is only used by solver code since matrix solvers are started in @@ -604,7 +605,7 @@ namespace netlist */ void device_t::connect_post_start(detail::core_terminal_t &t1, detail::core_terminal_t &t2) { - if (!setup().connect(t1, t2)) + if (!state().setup().connect(t1, t2)) log().fatal(MF_ERROR_CONNECTING_1_TO_2(t1.name(), t2.name())); } @@ -620,7 +621,7 @@ namespace netlist detail::family_setter_t::family_setter_t(core_device_t &dev, const pstring &desc) { - dev.set_logic_family(dev.setup().family_from_model(desc)); + dev.set_logic_family(dev.state().setup().family_from_model(desc)); } detail::family_setter_t::family_setter_t(core_device_t &dev, const logic_family_desc_t *desc) @@ -870,7 +871,7 @@ namespace netlist param_t::param_t(device_t &device, const pstring &name) : device_object_t(device, device.name() + "." + name) { - device.setup().register_param_t(this->name(), *this); + device.state().setup().register_param_t(this->name(), *this); } param_t::param_type_t param_t::param_type() const @@ -900,7 +901,7 @@ namespace netlist pstring param_t::get_initial(const device_t &dev, bool *found) { - pstring res = dev.setup().get_initial_param_val(this->name(), ""); + pstring res = dev.state().setup().get_initial_param_val(this->name(), ""); *found = (res != ""); return res; } @@ -913,7 +914,7 @@ namespace netlist param_str_t::param_str_t(device_t &device, const pstring &name, const pstring &val) : param_t(device, name) { - m_param = device.setup().get_initial_param_val(this->name(),val); + m_param = device.state().setup().get_initial_param_val(this->name(),val); } void param_str_t::changed() @@ -945,7 +946,7 @@ namespace netlist plib::unique_ptr param_data_t::stream() { - return device().setup().get_data_stream(str()); + return device().state().setup().get_data_stream(str()); } bool detail::core_terminal_t::is_logic() const NL_NOEXCEPT diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h index 93fb9ac64a3..54e6622799e 100644 --- a/src/lib/netlist/nl_base.h +++ b/src/lib/netlist/nl_base.h @@ -187,20 +187,13 @@ namespace netlist namespace devices { class matrix_solver_t; - class NETLIB_NAME(gnd); class NETLIB_NAME(solver); class NETLIB_NAME(mainclock); - class NETLIB_NAME(netlistparams); class NETLIB_NAME(base_proxy); class NETLIB_NAME(base_d_to_a_proxy); class NETLIB_NAME(base_a_to_d_proxy); } // namespace devices - namespace detail { - struct family_setter_t; - class queue_t; - } // namespace detail - class logic_output_t; class logic_input_t; class analog_net_t; @@ -210,7 +203,6 @@ namespace netlist class netlist_state_t; class core_device_t; class device_t; - class callbacks_t; //============================================================ // Exceptions @@ -351,24 +343,32 @@ namespace netlist * Use this state_var template to define an array whose contents are saved. * Please refer to \ref state_var. */ - template - struct state_array : public std::array + template + struct state_container : public C { public: + using value_type = typename C::value_type; //! Constructor. template - state_array(O &owner, //!< owner must have a netlist() method. - const pstring &name, //!< identifier/name for this state variable - const T &value //!< Initial value after construction + state_container(O &owner, //!< owner must have a netlist() method. + const pstring &name, //!< identifier/name for this state variable + const value_type &value //!< Initial value after construction + ); + //! Constructor. + template + state_container(O &owner, //!< owner must have a netlist() method. + const pstring &name, //!< identifier/name for this state variable + std::size_t n, //!< number of elements to allocate + const value_type &value //!< Initial value after construction ); //! Copy Constructor. - state_array(const state_array &rhs) noexcept = default; + state_container(const state_container &rhs) noexcept = default; //! Destructor. - ~state_array() noexcept = default; + ~state_container() noexcept = default; //! Move Constructor. - state_array(state_array &&rhs) noexcept = default; - state_array &operator=(const state_array &rhs) noexcept = default; - state_array &operator=(state_array &&rhs) noexcept = default; + state_container(state_container &&rhs) noexcept = default; + state_container &operator=(const state_container &rhs) noexcept = default; + state_container &operator=(state_container &&rhs) noexcept = default; }; // ----------------------------------------------------------------------------- @@ -471,9 +471,6 @@ namespace netlist netlist_state_t & state() noexcept; const netlist_state_t & state() const noexcept; - setup_t & setup() noexcept; - const setup_t & setup() const noexcept; - netlist_t & exec() noexcept { return m_netlist; } const netlist_t & exec() const noexcept { return m_netlist; } @@ -1244,9 +1241,6 @@ namespace netlist ~device_t() noexcept override = default; - setup_t &setup() noexcept; - const setup_t &setup() const noexcept; - template void create_and_register_subdevice(const pstring &name, unique_pool_ptr &dev, Args&&... args) { @@ -1271,62 +1265,66 @@ namespace netlist // family_setter_t // ----------------------------------------------------------------------------- - struct detail::family_setter_t - { - /* clang will complain about an unused private field if - * a defaulted constructor is used - */ - // NOLINTNEXTLINE(modernize-use-equals-default) - family_setter_t(); - family_setter_t(core_device_t &dev, const pstring &desc); - family_setter_t(core_device_t &dev, const logic_family_desc_t *desc); - }; + namespace detail { - template - using timed_queue = plib::timed_queue_linear; + struct family_setter_t + { + /* clang will complain about an unused private field if + * a defaulted constructor is used + */ + // NOLINTNEXTLINE(modernize-use-equals-default) + family_setter_t(); + family_setter_t(core_device_t &dev, const pstring &desc); + family_setter_t(core_device_t &dev, const logic_family_desc_t *desc); + }; - /* Use timed_queue_heap to use stdc++ heap functions instead of linear processing. - * This slows down processing by about 25% on a Kaby Lake. - */ + template + using timed_queue = plib::timed_queue_linear; - //template - //using timed_queue = timed_queue_heap; + /* Use timed_queue_heap to use stdc++ heap functions instead of linear processing. + * This slows down processing by about 25% on a Kaby Lake. + */ - // ----------------------------------------------------------------------------- - // queue_t - // ----------------------------------------------------------------------------- + //template + //using timed_queue = timed_queue_heap; - /* We don't need a thread-safe queue currently. Parallel processing of - * solvers will update inputs after parallel processing. - */ - class detail::queue_t : - //public timed_queue, false, NL_KEEP_STATISTICS>, - public timed_queue, false>, - public detail::netlist_ref, - public plib::state_manager_t::callback_t - { - public: - using base_queue = timed_queue, false>; - using entry_t = plib::pqentry_t; - explicit queue_t(netlist_state_t &nl); - virtual ~queue_t() noexcept = default; + // ----------------------------------------------------------------------------- + // queue_t + // ----------------------------------------------------------------------------- + + /* We don't need a thread-safe queue currently. Parallel processing of + * solvers will update inputs after parallel processing. + */ + class queue_t : + //public timed_queue, false, NL_KEEP_STATISTICS>, + public timed_queue, false>, + public netlist_ref, + public plib::state_manager_t::callback_t + { + public: + using base_queue = timed_queue, false>; + using entry_t = plib::pqentry_t; + explicit queue_t(netlist_state_t &nl); + virtual ~queue_t() noexcept = default; - queue_t(const queue_t &) = delete; - queue_t(queue_t &&) = delete; - queue_t &operator=(const queue_t &) = delete; - queue_t &operator=(queue_t &&) = delete; + queue_t(const queue_t &) = delete; + queue_t(queue_t &&) = delete; + queue_t &operator=(const queue_t &) = delete; + queue_t &operator=(queue_t &&) = delete; - protected: + protected: - void register_state(plib::state_manager_t &manager, const pstring &module) override; - void on_pre_save(plib::state_manager_t &manager) override; - void on_post_load(plib::state_manager_t &manager) override; + void register_state(plib::state_manager_t &manager, const pstring &module) override; + void on_pre_save(plib::state_manager_t &manager) override; + void on_post_load(plib::state_manager_t &manager) override; - private: - std::size_t m_qsize; - std::vector m_times; - std::vector m_net_ids; - }; + private: + std::size_t m_qsize; + std::vector m_times; + std::vector m_net_ids; + }; + + } // ----------------------------------------------------------------------------- // netlist_state__t @@ -1666,16 +1664,6 @@ namespace netlist return m_netlist.nlstate(); } - inline setup_t & detail::netlist_ref::setup() noexcept - { - return m_netlist.nlstate().setup(); - } - - inline const setup_t & detail::netlist_ref::setup() const noexcept - { - return m_netlist.nlstate().setup(); - } - template param_num_t::param_num_t(device_t &device, const pstring &name, const T val) : param_t(device, name) @@ -1909,15 +1897,25 @@ namespace netlist owner.state().save(owner, m_value, owner.name(), name); } - template + template template - state_array::state_array(O &owner, const pstring &name, const T & value) + state_container::state_container(O &owner, const pstring &name, + const state_container::value_type & value) { - owner.state().save(owner, *static_cast *>(this), owner.name(), name); - for (std::size_t i=0; i(this), owner.name(), name); + for (std::size_t i=0; i < this->size(); i++) (*this)[i] = value; } + template + template + state_container::state_container(O &owner, const pstring &name, + std::size_t n, const state_container::value_type & value) + : C(n, value) + { + owner.state().save(owner, *static_cast(this), owner.name(), name); + } + // ----------------------------------------------------------------------------- // Hot section // diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h index ae3d73a08b7..93fe10fbe08 100644 --- a/src/lib/netlist/nl_config.h +++ b/src/lib/netlist/nl_config.h @@ -94,15 +94,8 @@ // Use nano-second resolution - Sufficient for now static constexpr const auto NETLIST_INTERNAL_RES = 1000000000; -//static constexpr const auto NETLIST_INTERNAL_RES = 1000000000000; static constexpr const auto NETLIST_CLOCK = NETLIST_INTERNAL_RES; -//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000)) -//#define NETLIST_CLOCK (NETLIST_INTERNAL_RES) -//#define NETLIST_INTERNAL_RES (UINT64_C(1000000000000)) -//#define NETLIST_CLOCK (UINT64_C(1000000000)) - - //#define nl_double float using nl_double = double; diff --git a/src/lib/netlist/plib/pstate.h b/src/lib/netlist/plib/pstate.h index f595dbcba11..f0f9e49db20 100644 --- a/src/lib/netlist/plib/pstate.h +++ b/src/lib/netlist/plib/pstate.h @@ -83,7 +83,7 @@ public: state_manager_t() = default; - template + template //, typename std::enable_if::value || std::is_floating_point::value>::type> void save_item(const void *owner, C &state, const pstring &stname) { save_state_ptr( owner, stname, dtype(), 1, &state); @@ -101,8 +101,8 @@ public: save_state_ptr(owner, stname, dtype(), count, state); } - template - void save_item(const void *owner, std::vector &v, const pstring &stname) + template + void save_item(const void *owner, std::vector &v, const pstring &stname) { save_state_ptr(owner, stname, dtype(), v.size(), v.data()); } diff --git a/src/lib/netlist/solver/nld_matrix_solver.cpp b/src/lib/netlist/solver/nld_matrix_solver.cpp index 56f19fc7f4d..d76c2d2f5a3 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.cpp +++ b/src/lib/netlist/solver/nld_matrix_solver.cpp @@ -16,10 +16,7 @@ namespace devices { terms_for_net_t::terms_for_net_t(analog_net_t * net) - : m_last_V(0.0) - , m_DD_n_m_1(0.0) - , m_h_n_m_1(1e-12) - , m_net(net) + : m_net(net) , m_railstart(0) { } @@ -342,14 +339,19 @@ namespace devices /* * save states */ + + m_last_V.resize(iN, plib::constants::zero()); + m_DD_n_m_1.resize(iN, plib::constants::zero()); + m_h_n_m_1.resize(iN, plib::constants::zero()); + + 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"); + for (std::size_t k = 0; k < iN; k++) { pstring num = plib::pfmt("{1}")(k); - state().save(*this, m_terms[k].m_last_V, this->name(), "lastV." + num); - state().save(*this, m_terms[k].m_DD_n_m_1, this->name(), "m_DD_n_m_1." + num); - state().save(*this, m_terms[k].m_h_n_m_1, this->name(), "m_h_n_m_1." + num); - // FIXME: This shouldn't be necessary, recalculate on each entry ... state().save(*this, m_gonn[k],"GO" + num, this->name(), m_terms[k].count()); state().save(*this, m_gtn[k],"GT" + num, this->name(), m_terms[k].count()); @@ -559,19 +561,21 @@ namespace devices if (m_params.m_dynamic_ts) { - for (auto &t : m_terms) + for (std::size_t k = 0; k < m_terms.size(); k++) { + auto &t = m_terms[k]; //const nl_double DD_n = (n->Q_Analog() - t->m_last_V); // avoid floating point exceptions - const nl_double DD_n = std::max(-1e100, std::min(1e100,(t.getV() - t.m_last_V))); + + const nl_double DD_n = std::max(-1e100, std::min(1e100,(t.getV() - m_last_V[k]))); const nl_double hn = cur_ts; //printf("%g %g %g %g\n", DD_n, hn, t.m_DD_n_m_1, t.m_h_n_m_1); - nl_double DD2 = (DD_n / hn - t.m_DD_n_m_1 / t.m_h_n_m_1) / (hn + t.m_h_n_m_1); + nl_double DD2 = (DD_n / hn - m_DD_n_m_1[k] / m_h_n_m_1[k]) / (hn + m_h_n_m_1[k]); nl_double new_net_timestep(0); - t.m_h_n_m_1 = hn; - t.m_DD_n_m_1 = DD_n; + m_h_n_m_1[k] = hn; + m_DD_n_m_1[k] = DD_n; if (std::fabs(DD2) > plib::constants::cast(1e-60)) // avoid div-by-zero new_net_timestep = std::sqrt(m_params.m_dynamic_lte / std::fabs(plib::constants::cast(0.5)*DD2)); else @@ -580,7 +584,7 @@ namespace devices if (new_net_timestep < new_solver_timestep) new_solver_timestep = new_net_timestep; - t.m_last_V = t.getV(); + m_last_V[k] = t.getV(); } if (new_solver_timestep < m_params.m_min_timestep) { diff --git a/src/lib/netlist/solver/nld_matrix_solver.h b/src/lib/netlist/solver/nld_matrix_solver.h index a7d74c45004..7870be34ad7 100644 --- a/src/lib/netlist/solver/nld_matrix_solver.h +++ b/src/lib/netlist/solver/nld_matrix_solver.h @@ -136,11 +136,6 @@ namespace devices plib::aligned_vector m_nzrd; /* non zero right of the diagonal for elimination, may include RHS element */ plib::aligned_vector m_nzbd; /* non zero below of the diagonal for elimination */ - /* state */ - nl_double m_last_V; - nl_double m_DD_n_m_1; - nl_double m_h_n_m_1; - plib::aligned_vector m_connected_net_idx; private: analog_net_t * m_net; @@ -375,6 +370,17 @@ namespace devices plib::aligned_vector m_terms; plib::aligned_vector m_rails_temp; + /* state - variable time_stepping */ + plib::aligned_vector m_last_V; + plib::aligned_vector m_DD_n_m_1; + plib::aligned_vector m_h_n_m_1; + + // FIXME: it should be like this, however dimensions are determined + // in vsetup. + //state_container> m_last_V; + //state_container> m_DD_n_m_1; + //state_container> m_h_n_m_1; + std::vector> m_inps; const solver_parameters_t &m_params; @@ -385,6 +391,9 @@ namespace devices state_var m_iterative_fail; state_var m_iterative_total; + + + private: state_var m_last_step; diff --git a/src/lib/netlist/solver/nld_solver.h b/src/lib/netlist/solver/nld_solver.h index 9ee79a177f1..7e672d74738 100644 --- a/src/lib/netlist/solver/nld_solver.h +++ b/src/lib/netlist/solver/nld_solver.h @@ -24,10 +24,6 @@ namespace netlist { namespace devices { - class NETLIB_NAME(solver); - - class matrix_solver_t; - NETLIB_OBJECT(solver) { NETLIB_CONSTRUCTOR(solver) -- cgit v1.2.3