Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get vector from exprTk as output

Tags:

c++

exprtk

I can't seem to get a vector output from exprTk. I figure it should be relatively simple but in the manual I can only find how to input a vector and not how to output one.

What I currently have is the following:

typedef double T; // numeric type (float, double, mpfr etc...)
typedef exprtk::symbol_table<T> symbol_table_t;
typedef exprtk::expression<T>     expression_t;
typedef exprtk::parser<T>             parser_t;

std::string expression_string = "var z[2] := { x, y };";

T x = T(5.3);
T y = T(2.3);
std::vector<T> z;

symbol_table_t symbol_table;
symbol_table.add_variable("x", x);
symbol_table.add_variable("y", y);
symbol_table.add_vector("z", z);

expression_t expression;
expression.register_symbol_table(symbol_table);

//Check if expression is valid
parser_t parser;
if (!parser.compile(expression_string, expression))
{
    printf("Compilation error...\n");
    return;
}

T result = expression.value();
std::cout << result << std::endl;     \\returns: 5.3 as expected the first element of vector z.
std::cout << z[0] << std::endl;       \\Crashes the program 

What I want as output is just the vector z. How do I do this, or what am I doing wrong?

like image 733
D.J. Klomp Avatar asked Apr 10 '26 01:04

D.J. Klomp


1 Answers

As per Section 20 - Expression Return Values of the readme, One can immediately exit an expression returning any number of variables of any type simply by using the return statement.

The example provided in the documentation is as follows:

std::string expression_string =
   " if (x < y)                                   "
   "   return [x + 1,'return-call 1'];            "
   " else if (x > y)                              "
   "   return [y / 2, y + 1, 'return-call 2'];    "
   " else if (equal(x,y))                         "
   "   x + y;                                     "
   " return [x, y, x + y, x - y, 'return-call 3'] ";

using symbol_table_t = exprtk::symbol_table<double>;
using expression_t   = exprtk::expression<double>;
using parser_t       = exprtk::parser<double>;

symbol_table_t symbol_table;
expression_t   expression;
parser_t       parser;

double x = 0;
double y = 0;

symbol_table.add_variable("x",x);
symbol_table.add_variable("y",y);

expression.register_symbol_table(symbol_table);

parser.compile(expression_string,expression);

T result = expression.value();

if (expression.results().count())
{
   using results_context_t = exprtk::results_context<T>;
   using type_t            = typename results_context_t::type_store_t;
   using scalar_t          = typename type_t::scalar_view;
   using vector_t          = typename type_t::vector_view;
   using string_t          = typename type_t::string_view;

   const results_context_t& results = expression.results();

   for (std::size_t i = 0; i < results.count(); ++i)
   {
      type_t t = results[i];

      switch (t.type)
      {
         case type_t::e_scalar : ...
                                 break;

         case type_t::e_vector : ...
                                 break;

         case type_t::e_string : ...
                                 break;

         default               : continue;
      }
}

Note1: Your expression will become:

var z[2] := { x, y }; return [z];

Note2: In order to have your "one-line" method you could write a simple free function that wraps the boiler plate code after the conditional and extracts the vector of your choosing (i'th result given it's of vector type) from the results list.

template <typename T>
bool get_vector(const std::size_t index, 
                const results_context_t& results,
                std::vector<T>& v)
{
   ...
}
like image 198
ExprTk Developer Avatar answered Apr 11 '26 16:04

ExprTk Developer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!