LCOV - code coverage report
Current view: top level - src/qi - evaluator.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 67 64.2 %
Date: 2022-11-05 14:57:37 Functions: 12 24 50.0 %

          Line data    Source code
       1             : #define MATHEVAL_IMPLEMENTATION
       2             : 
       3             : #include "evaluator.hpp"
       4             : #include "ast.hpp"
       5             : 
       6             : namespace matheval {
       7             : 
       8             : namespace ast {
       9             : 
      10             : // Optimizer
      11             : 
      12             : template <typename T, typename U>
      13             : struct is_same {
      14             :     static const bool value = false;
      15             : };
      16             : 
      17             : template <typename T>
      18             : struct is_same<T, T> {
      19             :     static const bool value = true;
      20             : };
      21             : 
      22             : template <typename T>
      23             : struct holds_alternative_impl {
      24             :     typedef bool result_type;
      25             : 
      26             :     template <typename U>
      27           2 :     bool operator()(U const & /*unused*/) const {
      28           2 :         return is_same<U, T>::value;
      29             :     }
      30             : };
      31             : 
      32             : template <typename T>
      33           2 : bool holds_alternative(operand const &v) {
      34           2 :     return boost::apply_visitor(holds_alternative_impl<T>(), v);
      35             : }
      36             : 
      37           0 : ConstantFolder::result_type ConstantFolder::operator()(nil) const { return 0; }
      38             : 
      39           2 : ConstantFolder::result_type ConstantFolder::operator()(double n) const {
      40           2 :     return n;
      41             : }
      42             : 
      43           0 : ConstantFolder::result_type ConstantFolder::
      44             : operator()(std::string const &c) const {
      45           0 :     return c;
      46             : }
      47             : 
      48           1 : ConstantFolder::result_type ConstantFolder::
      49             : operator()(operation const &x, operand const &lhs) const {
      50           2 :     operand rhs = boost::apply_visitor(*this, x.rhs);
      51             : 
      52           1 :     if (holds_alternative<double>(lhs) && holds_alternative<double>(rhs)) {
      53           2 :         return x.op(boost::get<double>(lhs), boost::get<double>(rhs));
      54             :     }
      55           0 :     return binary_op(x.op, lhs, rhs);
      56             : }
      57             : 
      58           0 : ConstantFolder::result_type ConstantFolder::
      59             : operator()(unary_op const &x) const {
      60           0 :     operand rhs = boost::apply_visitor(*this, x.rhs);
      61             : 
      62             :     /// If the operand is known, we can directly evaluate the function.
      63           0 :     if (holds_alternative<double>(rhs)) {
      64           0 :         return x.op(boost::get<double>(rhs));
      65             :     }
      66           0 :     return unary_op(x.op, rhs);
      67             : }
      68             : 
      69           0 : ConstantFolder::result_type ConstantFolder::
      70             : operator()(binary_op const &x) const {
      71           0 :     operand lhs = boost::apply_visitor(*this, x.lhs);
      72           0 :     operand rhs = boost::apply_visitor(*this, x.rhs);
      73             : 
      74             :     /// If both operands are known, we can directly evaluate the function,
      75             :     /// else we just update the children with the new expressions.
      76           0 :     if (holds_alternative<double>(lhs) && holds_alternative<double>(rhs)) {
      77           0 :         return x.op(boost::get<double>(lhs), boost::get<double>(rhs));
      78             :     }
      79           0 :     return binary_op(x.op, lhs, rhs);
      80             : }
      81             : 
      82           0 : ConstantFolder::result_type ConstantFolder::
      83             : operator()(ternary_op const &x) const {
      84           0 :     operand cond = boost::apply_visitor(*this, x.cond);
      85           0 :     operand t = boost::apply_visitor(*this, x.t);
      86           0 :     operand f = boost::apply_visitor(*this, x.f);
      87             : 
      88             :     /// If both operands are known, we can directly evaluate the function,
      89             :     /// else we just update the children with the new expressions.
      90           0 :     if (holds_alternative<double>(cond) && holds_alternative<double>(t) && holds_alternative<double>(f)) {
      91           0 :         return x.op(boost::get<double>(cond), boost::get<double>(t), boost::get<double>(f));
      92             :     }
      93           0 :     return ternary_op(x.op, cond, t, f);
      94             : }
      95             : 
      96           8 : ConstantFolder::result_type ConstantFolder::
      97             : operator()(expression const &x) const {
      98           8 :     operand state = boost::apply_visitor(*this, x.lhs);
      99           9 :     for (std::list<operation>::const_iterator it = x.rhs.begin();
     100           9 :          it != x.rhs.end(); ++it) {
     101           1 :         state = (*this)(*it, state);
     102             :     }
     103           8 :     return state;
     104             : }
     105             : 
     106             : // Evaluator
     107             : 
     108           0 : double eval::operator()(nil) const {
     109           0 :     BOOST_ASSERT(0);
     110             :     return 0;
     111             : }
     112             : 
     113         203 : double eval::operator()(double n) const { return n; }
     114             : 
     115          17 : double eval::operator()(std::string const &c) const {
     116          17 :     std::map<std::string, double>::const_iterator it = st.find(c);
     117          17 :     if (it == st.end()) {
     118           2 :         throw std::invalid_argument("Unknown variable " + c); // NOLINT
     119             :     }
     120          15 :     return it->second;
     121             : }
     122             : 
     123         127 : double eval::operator()(operation const &x, double lhs) const {
     124         127 :     double rhs = boost::apply_visitor(*this, x.rhs);
     125         127 :     return x.op(lhs, rhs);
     126             : }
     127             : 
     128          28 : double eval::operator()(unary_op const &x) const {
     129          28 :     double rhs = boost::apply_visitor(*this, x.rhs);
     130          28 :     return x.op(rhs);
     131             : }
     132             : 
     133           3 : double eval::operator()(binary_op const &x) const {
     134           3 :     double lhs = boost::apply_visitor(*this, x.lhs);
     135           3 :     double rhs = boost::apply_visitor(*this, x.rhs);
     136           3 :     return x.op(lhs, rhs);
     137             : }
     138             : 
     139           2 : double eval::operator()(ternary_op const &x) const {
     140           2 :     double cond = boost::apply_visitor(*this, x.cond);
     141           2 :     double t = boost::apply_visitor(*this, x.t);
     142           2 :     double f = boost::apply_visitor(*this, x.f);
     143           2 :     return x.op(cond, t, f);
     144             : }
     145             : 
     146        1160 : double eval::operator()(expression const &x) const {
     147        1160 :     double state = boost::apply_visitor(*this, x.lhs);
     148        1275 :     for (std::list<operation>::const_iterator it = x.rhs.begin();
     149        1275 :          it != x.rhs.end(); ++it) {
     150         127 :         state = (*this)(*it, state);
     151             :     }
     152        1148 :     return state;
     153             : }
     154             : 
     155             : } // namespace ast
     156             : 
     157             : } // namespace matheval

Generated by: LCOV version 1.14