From a569b4748e266ce318602e7b6a9c1f19a8c75bdf Mon Sep 17 00:00:00 2001 From: Alexey Sheplyakov Date: Fri, 1 Jan 2021 20:09:47 +0400 Subject: [PATCH] bugfix: function: always pass evalf'ed arguments to evalf_funcp GiNaC passes unevaluted arguments to a function with evalf_funcp taking an exvector. Fixed that, and added a test case --- check/CMakeLists.txt | 4 +- check/Makefile.am | 4 ++ check/exam_function_exvector.cpp | 116 +++++++++++++++++++++++++++++++ ginac/function.cppy | 2 +- 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 check/exam_function_exvector.cpp diff --git a/check/CMakeLists.txt b/check/CMakeLists.txt index 9ef3a709..768b192b 100644 --- a/check/CMakeLists.txt +++ b/check/CMakeLists.txt @@ -27,7 +27,9 @@ set(ginac_exams exam_pgcd exam_mod_gcd exam_real_imag - exam_chinrem_gcd) + exam_chinrem_gcd + exam_function_exvector +) set(ginac_checks check_numeric diff --git a/check/Makefile.am b/check/Makefile.am index fd0fd126..9f8039ea 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -27,6 +27,7 @@ EXAMS = exam_paranoia \ exam_pgcd \ exam_mod_gcd \ exam_chinrem_gcd \ + exam_function_exvector \ exam_real_imag CHECKS = check_numeric \ @@ -149,6 +150,9 @@ exam_real_imag_LDADD = ../ginac/libginac.la exam_chinrem_gcd_SOURCES = exam_chinrem_gcd.cpp exam_chinrem_gcd_LDADD = ../ginac/libginac.la +exam_function_exvector_SOURCES = exam_function_exvector.cpp +exam_function_exvector_LDADD = ../ginac/libginac.la + check_numeric_SOURCES = check_numeric.cpp check_numeric_LDADD = ../ginac/libginac.la diff --git a/check/exam_function_exvector.cpp b/check/exam_function_exvector.cpp new file mode 100644 index 00000000..b5b5d0d7 --- /dev/null +++ b/check/exam_function_exvector.cpp @@ -0,0 +1,116 @@ +#ifdef IN_GINAC +#include "ginac.h" +#else +#include "ginac/ginac.h" +#endif + +#include +#include + +using namespace GiNaC; +using namespace std; + +DECLARE_FUNCTION_2P(foobar); + +static bool eval_called = false; +static exvector eval_called_with = {}; +static bool evalf_called = false; +static exvector evalf_called_with = {}; + +static void reset() { + eval_called_with.clear(); + evalf_called_with.clear(); + evalf_called = false; + eval_called = false; +} + +static ex foobar_eval(const exvector& args) { + eval_called = true; + for (auto const& v: args) + eval_called_with.push_back(v); + + return foobar(args[0], args[1]).hold(); +} + +static ex foobar_evalf(const exvector& args) { + evalf_called = true; + for (auto const& v: args) + evalf_called_with.push_back(v); + return foobar(args[0], args[1]).hold(); +} + + +REGISTER_FUNCTION(foobar, eval_func(foobar_eval). + evalf_func(foobar_evalf)); + +static int check_exvector_eval() { + symbol x("x"), y("y"); + int err = 1; + + reset(); + ex e = foobar(x, y); + if (!eval_called) { + clog << "*** Error: " << __func__ << ": foobar_eval hasn't been called" << endl; + err *= 2; + } + if (eval_called_with.size() != 2) { + clog << "*** Error: " << __func__ << ": fobar_eval: expected 2 arguments, got " << + eval_called_with.size() << endl; + err *= 3; + } + if (eval_called_with[0] != x) { + clog << "*** Error: " << __func__ << ": fobar_eval: wrong 1st argument, " + "expected " << x << ", got " << eval_called_with[0] << endl; + err *= 5; + } + if (eval_called_with[1] != y) { + clog << "*** Error: " << __func__ << ": fobar_eval: wrong 1st argument, " + "expected " << y << ", got " << eval_called_with[1] << endl; + err *= 7; + } + return err - 1; +} + +static int check_exvector_evalf() { + int err = 1; + + reset(); + ex e = foobar(Pi, Euler); + e = e.evalf(); + + if (!evalf_called) { + clog << "*** Error: " << __func__ << ": foobar_evalf hasn't been called" << endl; + err *= 2; + } + if (evalf_called_with.size() != 2) { + clog << __func__ << ": foobar_evalf: expected 2 arguments, got " << + evalf_called_with.size() << endl; + err *= 3; + } + if (!is_a(evalf_called_with[0])) { + clog << "*** Error: " << __func__ << ": wrong 1st argument of foobar_evalf: " + "expected a real number, got " << evalf_called_with[0] << endl; + err *= 5; + } + if (!is_a(evalf_called_with[1])) { + clog << "*** Error: " << __func__ << ": wrong 1st argument of foobar_evalf: " + "expected a real number, got " << evalf_called_with[0] << endl; + err *= 7; + } + return err - 1; +} + +int main(int argc, char** argv) { + int ret = 0; + auto err = check_exvector_evalf(); + if (err) { + ret |= 1; + clog << "*** Error " << (err + 1) << " (check_exvector_evalf)" << endl; + } + err = check_exvector_eval(); + if (err) { + ret |= 2; + clog << "*** Error " << (err + 1) << " (check_exvector_evalf)" << endl; + } + return ret; +} diff --git a/ginac/function.cppy b/ginac/function.cppy index a7f51acd..57af323d 100644 --- a/ginac/function.cppy +++ b/ginac/function.cppy @@ -437,7 +437,7 @@ ex function::evalf() const } current_serial = serial; if (opt.evalf_use_exvector_args) - return ((evalf_funcp_exvector)(opt.evalf_f))(seq); + return ((evalf_funcp_exvector)(opt.evalf_f))(eseq); switch (opt.nparams) { // the following lines have been generated for max. @maxargs@ parameters +++ for N in range(1, maxargs + 1): -- 2.47.0