function::function(unsigned ser, ${SEQ1})
: exprseq(${SEQ2}), serial(ser)
{
- debugmsg(\"function ctor from unsigned,${N}*ex\",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
END_OF_CONSTRUCTORS_IMPLEMENTATION
$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);
-#define BEGIN_TYPECHECK \\
-bool automatic_typecheck=true;
-
-#define TYPECHECK(VAR,TYPE) \\
-if (!is_exactly_a<TYPE>(VAR)) { \\
- automatic_typecheck=false; \\
-} else
-
-#define TYPECHECK_INTEGER(VAR) \\
-if (!(VAR).info(GiNaC::info_flags::integer)) { \\
- automatic_typecheck=false; \\
-} else
-
-#define END_TYPECHECK(RV) \\
-{} \\
-if (!automatic_typecheck) { \\
- return RV.hold(); \\
-}
-
namespace GiNaC {
class function;
$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.
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <iostream>
#include <string>
#include <stdexcept>
#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"
namespace GiNaC {
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)
//////////
-// default ctor, dtor, copy ctor assignment operator and helpers
+// default ctor, dtor, copy ctor, assignment operator and helpers
//////////
// public
function::function() : serial(0)
{
- debugmsg("function default ctor",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser) : serial(ser)
{
- debugmsg("function ctor from unsigned",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser)
{
- debugmsg("function ctor from unsigned,exprseq",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, const exvector & v, bool discardable)
: exprseq(v,discardable), serial(ser)
{
- debugmsg("function ctor from string,exvector,bool",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, exvector * vp)
: exprseq(vp), serial(ser)
{
- debugmsg("function ctor from unsigned,exvector *",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
/** Construct object from archive_node. */
function::function(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
{
- debugmsg("function ctor from archive_node", LOGLEVEL_CONSTRUCT);
-
// Find serial number by function name
std::string s;
if (n.find_string("name", s)) {
}
//////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
//////////
// public
void function::print(const print_context & c, unsigned level) const
{
- debugmsg("function print", LOGLEVEL_PRINT);
-
GINAC_ASSERT(serial<registered_functions().size());
if (is_of_type(c, print_tree)) {
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))
- return n==1 ? _ex1() : _ex0();
+ if (is_equal(ex_to<basic>(s)))
+ return n==1 ? _ex1 : _ex0;
else
- return n==0 ? ex(*this) : _ex0();
+ return n==0 ? ex(*this) : _ex0;
}
ex function::eval(int level) const
// 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 (sig == 0)
- return _ex0();
+ return _ex0;
return ex(sig) * thisexprseq(v);
}
}
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}