diff options
Diffstat (limited to 'src/lib/netlist/plib/pfunction.h')
-rw-r--r-- | src/lib/netlist/plib/pfunction.h | 217 |
1 files changed, 140 insertions, 77 deletions
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h index bc81ef0c5a6..836c6f9c126 100644 --- a/src/lib/netlist/plib/pfunction.h +++ b/src/lib/netlist/plib/pfunction.h @@ -1,14 +1,14 @@ -// license:GPL-2.0+ +// license:BSD-3-Clause // copyright-holders:Couriersud -/* - * pfunction.h - * - */ #ifndef PFUNCTION_H_ #define PFUNCTION_H_ -#include "pstate.h" +/// +/// \file pfunction.h +/// + +#include "pmath.h" #include "pstring.h" #include <vector> @@ -19,100 +19,163 @@ namespace plib { // function evaluation //============================================================ - /*! Class providing support for evaluating expressions - * - */ + enum rpn_cmd + { + ADD, + MULT, + SUB, + DIV, + EQ, + NE, + LT, + GT, + LE, + GE, + IF, + NEG, // unary minus + POW, + LOG, + SIN, + COS, + MIN, + MAX, + RAND, /// random number between 0 and 1 + TRUNC, + + PUSH_CONST, + PUSH_INPUT, + + LP, // Left parenthesis - for infix parsing + RP // right parenthesis - for infix parsing + }; + + /// \brief Class providing support for evaluating expressions + /// + /// \tparam NT Number type, should be float or double + /// + template <typename NT> class pfunction { - enum rpn_cmd - { - ADD, - MULT, - SUB, - DIV, - POW, - SIN, - COS, - RAND, /* random number between 0 and 1 */ - TRUNC, - PUSH_CONST, - PUSH_INPUT - }; struct rpn_inst { - rpn_inst() : m_cmd(ADD), m_param(0.0) { } + constexpr rpn_inst() : m_cmd(ADD) + { + m_param.val = plib::constants<NT>::zero(); + } + constexpr rpn_inst(rpn_cmd cmd, std::size_t index = 0) + : m_cmd(cmd) + { + m_param.index = index; + } + constexpr rpn_inst(NT v) : m_cmd(PUSH_CONST) + { + m_param.val = v; + } + constexpr const rpn_cmd &cmd() const noexcept + { + return m_cmd; + } + constexpr const NT &value() const noexcept + { + return m_param.val; // NOLINT + } + constexpr const std::size_t &index() const noexcept + { + return m_param.index; // NOLINT + } + private: rpn_cmd m_cmd; - double m_param; + union + { + NT val; + std::size_t index; + } m_param; }; public: - /*! Constructor with state saving support - * - * @param name Name of this object - * @param owner Owner of this object - * @param state_manager State manager to handle saving object state - * - */ - pfunction(const pstring &name, const void *owner, state_manager_t &state_manager) - : m_lfsr(0xACE1u) + + using value_type = NT; + + using inputs_container = std::vector<pstring>; + using values_container = std::vector<value_type>; + + /// \brief Constructor + /// + pfunction() + : m_lfsr(0xace1U) // NOLINT { - state_manager.save_item(owner, m_lfsr, name + ".lfsr"); } - /*! Constructor without state saving support - * - */ - pfunction() - : m_lfsr(0xACE1u) + /// \brief Constructor with compile + /// + pfunction(const pstring &expr, const inputs_container &inputs = inputs_container()) + : m_lfsr(0xace1U) // NOLINT { + compile(expr, inputs); } - /*! Compile an expression - * - * @param inputs Vector of input variables, e.g. {"A","B"} - * @param expr infix or postfix expression. default is infix, postrix - * to be prefixed with rpn, e.g. "rpn:A B + 1.3 /" - */ - void compile(const std::vector<pstring> &inputs, const pstring &expr); - - /*! Compile a rpn expression - * - * @param inputs Vector of input variables, e.g. {"A","B"} - * @param expr Reverse polish notation expression, e.g. "A B + 1.3 /" - */ - void compile_postfix(const std::vector<pstring> &inputs, const pstring &expr); - /*! Compile an infix expression - * - * @param inputs Vector of input variables, e.g. {"A","B"} - * @param expr Infix expression, e.g. "(A+B)/1.3" - */ - void compile_infix(const std::vector<pstring> &inputs, const pstring &expr); - /*! Evaluate the expression - * - * @param values for input variables, e.g. {1.1, 2.2} - * @return value of expression - */ - double evaluate(const std::vector<double> &values); + /// \brief Evaluate the expression + /// + /// \param values for input variables, e.g. {1.1, 2.2} + /// \return value of expression + /// + value_type operator()(const values_container &values = values_container()) noexcept + { + return evaluate(values); + } + + /// \brief Compile an expression + /// + /// \param expr infix or postfix expression. default is infix, postfix + /// to be prefixed with rpn, e.g. "rpn:A B + 1.3 /" + /// \param inputs Vector of input variables, e.g. {"A","B"} + /// + void compile(const pstring &expr, const inputs_container &inputs = inputs_container()) noexcept(false); + + /// \brief Compile a rpn expression + /// + /// \param expr Reverse polish notation expression, e.g. "A B + 1.3 /" + /// \param inputs Vector of input variables, e.g. {"A","B"} + /// + void compile_postfix(const pstring &expr, const inputs_container &inputs = inputs_container()) noexcept(false); + + /// \brief Compile an infix expression + /// + /// \param expr Infix expression, e.g. "(A+B)/1.3" + /// \param inputs Vector of input variables, e.g. {"A","B"} + /// + void compile_infix(const pstring &expr, const inputs_container &inputs = inputs_container()) noexcept(false); + + /// \brief Evaluate the expression + /// + /// \param values for input variables, e.g. {1.1, 2.2} + /// \return value of expression + /// + value_type evaluate(const values_container &values = values_container()) noexcept; + + template <typename ST> + void save_state(ST &st) + { + st.save_item(m_lfsr, "m_lfsr"); + } private: - void compile_postfix(const std::vector<pstring> &inputs, + void compress(); + void compile_postfix(const inputs_container &inputs, const std::vector<pstring> &cmds, const pstring &expr); - double lfsr_random() - { - std::uint16_t lsb = m_lfsr & 1; - m_lfsr >>= 1; - if (lsb) - m_lfsr ^= 0xB400u; // taps 15, 13, 12, 10 - return static_cast<double>(m_lfsr) / static_cast<double>(0xffffu); - } - std::vector<rpn_inst> m_precompiled; //!< precompiled expression std::uint16_t m_lfsr; //!< lfsr used for generating random numbers }; + 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_ */ +#endif // PEXCEPTION_H_ |