Reputation: 2669
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?
Upvotes: 10
Views: 886
Reputation: 1726
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())
{
typedef exprtk::results_context<T> results_context_t;
typedef typename results_context_t::type_store_t type_t;
typedef typename type_t::scalar_view scalar_t;
typedef typename type_t::vector_view vector_t;
typedef typename type_t::string_view string_t;
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)
{
...
}
Upvotes: 7
Reputation: 1188
I've found a method that does work, but hopefully there is a simpler 'one-line' method
std::string expression_string = "var w[2] := { x, y }; z := w";
This creates an expression local vector w
([SECTION 13 - VARIABLE, VECTOR & STRING DEFINITION]), and then assigns the value to z
As @NathanOliver mentioned, std::vector<T> z(2);
is also needed
"var z[2] := { x, y };"
doesn't work as it is an illegal redefinition of the z
variable, due to the use of the var
statement.
Note that "z := {x, y}"
will also not work as this does not appear to be a valid assignment expression for a vector
Output (with debug enabled):
prev[var] --> curr[var]
prev[var] --> curr[w]
prev[2] --> curr[]]
prev[x] --> curr[,]
prev[y] --> curr[}]
parse_define_vector_statement() - INFO - Added new local vector: w[2]
activate_side_effect() - caller: parse_define_vector_statement()
parse_corpus(00) Subexpr: var w[2] := { x, y };
parse_corpus(00) - Side effect present: true
-------------------------------------------------
prev[z] --> curr[:=]
prev[:=] --> curr[w]
prev[w] --> curr[]
activate_side_effect() - caller: lodge_assignment()
parse_corpus(01) Subexpr: z := w
parse_corpus(01) - Side effect present: true
-------------------------------------------------
5.3
5.3
Upvotes: 0