$interface=<<END_OF_INTERFACE;
/** \@file function.h
*
- * Interface to abstract class function (new function concept). */
+ * Interface to class of symbolic functions. */
/*
* This file was generated automatically by function.pl.
const unsigned function_index_##NAME= \\
GiNaC::function::register_new(GiNaC::function_options(#NAME).OPT);
+// The TYPECHECK-macros were used inside the _evalf() functions. They are
+// considered obsolete now: (FIXME: remove them)
+
#define BEGIN_TYPECHECK \\
bool automatic_typecheck=true;
$typedef_series_funcp
// end of generated lines
+// Alternatively, an exvector may be passed into the static function, instead
+// of individual ex objects. Then, the number of arguments is not limited.
+typedef ex (* eval_funcp_exvector)(const exvector &);
+typedef ex (* evalf_funcp_exvector)(const exvector &);
+typedef ex (* derivative_funcp_exvector)(const exvector &, unsigned);
+typedef ex (* series_funcp_exvector)(const exvector &, const relational &, int, unsigned);
+
class function_options
{
friend class function;
+ friend class fderivative;
public:
function_options();
function_options(std::string const & n, std::string const & tn=std::string());
$derivative_func_interface
$series_func_interface
// end of generated lines
+ function_options & eval_func(eval_funcp_exvector e);
+ function_options & evalf_func(evalf_funcp_exvector ef);
+ function_options & derivative_func(derivative_funcp_exvector d);
+ function_options & series_func(series_funcp_exvector 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,
unsigned remember_assoc_size;
unsigned remember_strategy;
+ bool eval_use_exvector_args;
+ bool evalf_use_exvector_args;
+ bool derivative_use_exvector_args;
+ bool series_use_exvector_args;
+
unsigned functions_with_same_name;
ex symtree;
friend class remember_table_entry;
// friend class remember_table_list;
// friend class remember_table;
- friend ex Derivative_eval(const ex &, const ex &);
// member functions
function(unsigned ser, const exvector & v, bool discardable = false);
function(unsigned ser, exvector * vp); // vp will be deleted
- // functions overriding virtual functions from bases classes
+ // functions overriding virtual functions from base classes
public:
void print(const print_context & c, unsigned level = 0) const;
unsigned precedence(void) const {return 70;}
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:
};
// utility functions/macros
-/** Return the object of type function handled by an ex.
- * This is unsafe: you need to check the type first. */
-inline const function &ex_to_function(const ex &e)
-{
- return static_cast<const function &>(*e.bp);
-}
/** Specialization of is_exactly_a<function>(obj) for objects of type function. */
template<> inline bool is_exactly_a<function>(const basic & obj)
}
#define is_ex_the_function(OBJ, FUNCNAME) \\
- (is_ex_exactly_of_type(OBJ, function) && static_cast<GiNaC::function *>(OBJ.bp)->get_serial() == function_index_##FUNCNAME)
+ (is_exactly_a<GiNaC::function>(OBJ) && ex_to<GiNaC::function>(OBJ).get_serial() == function_index_##FUNCNAME)
} // namespace GiNaC
$implementation=<<END_OF_IMPLEMENTATION;
/** \@file function.cpp
*
- * Implementation of class function. */
+ * Implementation of class of symbolic functions. */
/*
* This file was generated automatically by function.pl.
#include <list>
#include "function.h"
+#include "fderivative.h"
#include "ex.h"
#include "lst.h"
#include "symmetry.h"
#include "print.h"
#include "archive.h"
#include "inifcns.h"
+#include "tostring.h"
#include "utils.h"
#include "debugmsg.h"
#include "remember.h"
eval_f = evalf_f = derivative_f = series_f = 0;
evalf_params_first = true;
use_return_type = false;
+ eval_use_exvector_args = false;
+ evalf_use_exvector_args = false;
+ derivative_use_exvector_args = false;
+ series_use_exvector_args = false;
use_remember = false;
functions_with_same_name = 1;
symtree = 0;
function_options & function_options::set_name(std::string const & n,
std::string const & tn)
{
- name=n;
+ name = n;
if (tn==std::string())
TeX_name = "\\\\mbox{"+name+"}";
else
function_options & function_options::latex_name(std::string const & tn)
{
- TeX_name=tn;
+ TeX_name = tn;
return *this;
}
$series_func_implementation
// end of generated lines
+function_options& function_options::eval_func(eval_funcp_exvector e)
+{
+ eval_use_exvector_args = true;
+ eval_f = eval_funcp(e);
+ return *this;
+}
+function_options& function_options::evalf_func(evalf_funcp_exvector ef)
+{
+ evalf_use_exvector_args = true;
+ evalf_f = evalf_funcp(ef);
+ return *this;
+}
+function_options& function_options::derivative_func(derivative_funcp_exvector d)
+{
+ derivative_use_exvector_args = true;
+ derivative_f = derivative_funcp(d);
+ return *this;
+}
+function_options& function_options::series_func(series_funcp_exvector s)
+{
+ series_use_exvector_args = true;
+ series_f = series_funcp(s);
+ return *this;
+}
+
+
function_options & function_options::set_return_type(unsigned rt, unsigned rtt)
{
use_return_type = true;
}
}
+/** This can be used as a hook for external applications. */
+unsigned function::current_serial = 0;
+
+
GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq)
//////////
}
//////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
//////////
// public
int function::degree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
int function::ldegree(const ex & s) const
{
- return is_equal(*s.bp) ? 1 : 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
ex function::coeff(const ex & s, int n) const
{
- if (is_equal(*s.bp))
+ if (is_equal(ex_to<basic>(s)))
return n==1 ? _ex1() : _ex0();
else
return n==0 ? ex(*this) : _ex0();
// Canonicalize argument order according to the symmetry properties
if (seq.size() > 1 && !(opt.symtree.is_zero())) {
exvector v = seq;
- GINAC_ASSERT(is_ex_exactly_of_type(opt.symtree, symmetry));
+ GINAC_ASSERT(is_a<symmetry>(opt.symtree));
int sig = canonicalize(v.begin(), ex_to<symmetry>(opt.symtree));
if (sig != INT_MAX) {
// Something has changed while sorting arguments, more evaluations later
if (use_remember && lookup_remember_table(eval_result)) {
return eval_result;
}
-
+ current_serial = serial;
+ if (registered_functions()[serial].eval_use_exvector_args)
+ eval_result = ((eval_funcp_exvector)(registered_functions()[serial].eval_f))(seq);
+ else
switch (opt.nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${eval_switch_statement}
if (registered_functions()[serial].evalf_f==0) {
return function(serial,eseq).hold();
}
+ current_serial = serial;
+ if (registered_functions()[serial].evalf_use_exvector_args)
+ return ((evalf_funcp_exvector)(registered_functions()[serial].evalf_f))(seq);
switch (registered_functions()[serial].nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${evalf_switch_statement}
return basic::series(r, order);
}
ex res;
+ current_serial = serial;
+ if (registered_functions()[serial].series_use_exvector_args) {
+ try {
+ res = ((series_funcp_exvector)(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}
ex function::derivative(const symbol & s) const
{
ex result;
-
+
if (serial == function_index_Order) {
// Order Term function only differentiates the argument
return Order(seq[0].diff(s));
- } else if (serial == function_index_Derivative) {
- // Inert derivative performs chain rule on the first argument only, and
- // adds differentiation parameter to list (second argument)
- GINAC_ASSERT(is_ex_exactly_of_type(seq[0], function));
- GINAC_ASSERT(is_ex_exactly_of_type(seq[1], function));
- ex fcn = seq[0];
- ex arg_diff;
- for (unsigned i=0; i!=fcn.nops(); i++) {
- arg_diff = fcn.op(i).diff(s);
- if (!arg_diff.is_zero()) {
- lst new_lst = ex_to<lst>(seq[1]);
- new_lst.append(i);
- result += arg_diff * Derivative(fcn, new_lst);
- }
- }
} else {
// Chain rule
ex arg_diff;
{
GINAC_ASSERT(serial<registered_functions().size());
- if (registered_functions()[serial].derivative_f==0) {
- return Derivative(*this, lst(ex(diff_param)));
- }
+ // 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_exvector_args)
+ return ((derivative_funcp_exvector)(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}