PROPOSAL: Dynamic creation of functions
Pearu Peterson
pearu at cens.ioc.ee
Mon Aug 20 18:56:54 CEST 2001
On Mon, 20 Aug 2001, Pearu Peterson wrote:
> What do you think? Can I can implement/test these modifications and send
> you them as a patch?
Meanwhile I implemented these hooks, and it works perfectly.
Please find the patch attached to this message.
To apply it, 'cd ginac/' and hit 'patch -p0 < function.pl.diff-0.9.3'.
As a result, I can now construct GiNaC functions directly in Python. Here
is an example of the corresponding Python session:
import ginac
class mysin:
nparams = 1
def eval(self, x):
return self(x, hold=1)
def derivative(self, x, diff_param):
return ginac.cos(x)
f = ginac.build_function(mysin)
x = ginac.symbol('x')
print f(x) # outputs: mysin(x)
print f(x).diff(x) # outputs: cos(x)
I hope that you find my patch useful for creating interfaces between GiNaC
and various scripting languages.
Regards,
Pearu
-------------- next part --------------
--- function.pl.orig Mon Aug 20 13:33:50 2001
+++ function.pl Mon Aug 20 15:15:12 2001
@@ -239,6 +239,10 @@
$typedef_derivative_funcp
$typedef_series_funcp
// end of generated lines
+typedef ex (* eval_funcp_v)(const exvector &);
+typedef ex (* evalf_funcp_v)(const exvector &);
+typedef ex (* derivative_funcp_v)(const exvector &, unsigned);
+typedef ex (* series_funcp_v)(const exvector &, const relational &, int, unsigned);
class function_options
{
@@ -257,6 +261,11 @@
$derivative_func_interface
$series_func_interface
// end of generated lines
+ function_options& function_options::eval_func(eval_funcp_v e);
+ function_options& function_options::evalf_func(evalf_funcp_v ef);
+ function_options& function_options::derivative_func(derivative_funcp_v d);
+ function_options& function_options::series_func(series_funcp_v s);
+
function_options & set_return_type(unsigned rt, unsigned rtt=0);
function_options & do_not_evalf_params(void);
function_options & remember(unsigned size, unsigned assoc_size=0,
@@ -290,6 +299,11 @@
unsigned remember_assoc_size;
unsigned remember_strategy;
+ bool eval_use_vector_args;
+ bool evalf_use_vector_args;
+ bool derivative_use_vector_args;
+ bool series_use_vector_args;
+
unsigned functions_with_same_name;
ex symtree;
@@ -354,10 +368,10 @@
void store_remember_table(ex const & result) const;
public:
static unsigned register_new(function_options const & opt);
+ static unsigned current_serial;
static unsigned find_function(const std::string &name, unsigned nparams);
unsigned get_serial(void) const {return serial;}
std::string get_name(void) const;
-
// member variables
protected:
@@ -433,6 +447,8 @@
namespace GiNaC {
+unsigned function::current_serial = 0;
+
//////////
// helper class function_options
//////////
@@ -461,6 +477,10 @@
evalf_params_first = true;
use_return_type = false;
use_remember = false;
+ eval_use_vector_args = false;
+ evalf_use_vector_args = false;
+ derivative_use_vector_args = false;
+ series_use_vector_args = false;
functions_with_same_name = 1;
symtree = 0;
}
@@ -488,6 +508,30 @@
$derivative_func_implementation
$series_func_implementation
// end of generated lines
+function_options& function_options::eval_func(eval_funcp_v e)
+{
+ eval_use_vector_args = true;
+ eval_f = eval_funcp(e);
+ return *this;
+}
+function_options& function_options::evalf_func(evalf_funcp_v ef)
+{
+ evalf_use_vector_args = true;
+ evalf_f = evalf_funcp(ef);
+ return *this;
+}
+function_options& function_options::derivative_func(derivative_funcp_v d)
+{
+ derivative_use_vector_args = true;
+ derivative_f = derivative_funcp(d);
+ return *this;
+}
+function_options& function_options::series_func(series_funcp_v s)
+{
+ series_use_vector_args = true;
+ series_f = series_funcp(s);
+ return *this;
+}
function_options & function_options::set_return_type(unsigned rt, unsigned rtt)
{
@@ -756,7 +800,11 @@
if (use_remember && lookup_remember_table(eval_result)) {
return eval_result;
}
-
+ current_serial = serial;
+ if (registered_functions()[serial].eval_use_vector_args) {
+ eval_result = ((eval_funcp_v)(registered_functions()[serial].eval_f))(seq);
+ }
+ else
switch (opt.nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${eval_switch_statement}
@@ -792,6 +840,9 @@
if (registered_functions()[serial].evalf_f==0) {
return function(serial,eseq).hold();
}
+ current_serial = serial;
+ if (registered_functions()[serial].evalf_use_vector_args)
+ return ((evalf_funcp_v)(registered_functions()[serial].evalf_f))(seq);
switch (registered_functions()[serial].nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${evalf_switch_statement}
@@ -835,6 +886,15 @@
return basic::series(r, order);
}
ex res;
+ current_serial = serial;
+ if (registered_functions()[serial].series_use_vector_args) {
+ try {
+ res = ((series_funcp_v)(registered_functions()[serial].series_f))(seq, r, order, options);
+ } catch (do_taylor) {
+ res = basic::series(r, order, options);
+ }
+ return res;
+ }
switch (registered_functions()[serial].nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${series_switch_statement}
@@ -938,7 +998,9 @@
// No derivative defined? Then return abstract derivative object
if (registered_functions()[serial].derivative_f == NULL)
return fderivative(serial, diff_param, seq);
-
+ current_serial = serial;
+ if (registered_functions()[serial].derivative_use_vector_args)
+ return ((derivative_funcp_v)(registered_functions()[serial].derivative_f))(seq, diff_param);
switch (registered_functions()[serial].nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${diff_switch_statement}
More information about the GiNaC-devel
mailing list