$declare_function_macro = generate(
<<'END_OF_DECLARE_FUNCTION_MACRO','typename T${N}','const T${N} & p${N}','GiNaC::ex(p${N})');
#define DECLARE_FUNCTION_${N}P(NAME) \\
$declare_function_macro = generate(
<<'END_OF_DECLARE_FUNCTION_MACRO','typename T${N}','const T${N} & p${N}','GiNaC::ex(p${N})');
#define DECLARE_FUNCTION_${N}P(NAME) \\
-extern const unsigned function_index_##NAME; \\
-template<${SEQ1}> \\
-inline const GiNaC::function NAME(${SEQ2}) { \\
- return GiNaC::function(function_index_##NAME, ${SEQ3}); \\
+class NAME##_SERIAL { public: static unsigned serial; }; \\
+template<${SEQ1}> const GiNaC::function NAME(${SEQ2}) { \\
+ return GiNaC::function(NAME##_SERIAL::serial, ${SEQ3}); \\
// end of generated lines
#define REGISTER_FUNCTION(NAME,OPT) \\
// end of generated lines
#define REGISTER_FUNCTION(NAME,OPT) \\
typedef ex (* derivative_funcp_exvector)(const exvector &, unsigned);
typedef ex (* series_funcp_exvector)(const exvector &, const relational &, int, unsigned);
typedef ex (* derivative_funcp_exvector)(const exvector &, unsigned);
typedef ex (* series_funcp_exvector)(const exvector &, const relational &, int, unsigned);
function_options & set_name(std::string const & n, std::string const & tn=std::string());
function_options & latex_name(std::string const & tn);
// the following lines have been generated for max. ${maxargs} parameters
function_options & set_name(std::string const & n, std::string const & tn=std::string());
function_options & latex_name(std::string const & tn);
// the following lines have been generated for max. ${maxargs} parameters
function_options & series_func(series_funcp_exvector s);
function_options & set_return_type(unsigned rt, unsigned rtt=0);
function_options & series_func(series_funcp_exvector s);
function_options & set_return_type(unsigned rt, unsigned rtt=0);
function_options & remember(unsigned size, unsigned assoc_size=0,
unsigned strategy=remember_strategies::delete_never);
function_options & overloaded(unsigned o);
function_options & set_symmetry(const symmetry & s);
void test_and_set_nparams(unsigned n);
function_options & remember(unsigned size, unsigned assoc_size=0,
unsigned strategy=remember_strategies::delete_never);
function_options & overloaded(unsigned o);
function_options & set_symmetry(const symmetry & s);
void test_and_set_nparams(unsigned n);
- std::string get_name(void) const { return name; }
- unsigned get_nparams(void) const { return nparams; }
- bool has_derivative(void) const { return derivative_f != NULL; }
+ std::string get_name() const { return name; }
+ unsigned get_nparams() const { return nparams; }
+ bool has_derivative() const { return derivative_f != NULL; }
/** The class function is used to implement builtin functions like sin, cos...
and user defined functions */
class function : public exprseq
/** The class function is used to implement builtin functions like sin, cos...
and user defined functions */
class function : public exprseq
// functions overriding virtual functions from base classes
public:
void print(const print_context & c, unsigned level = 0) const;
// functions overriding virtual functions from base classes
public:
void print(const print_context & c, unsigned level = 0) const;
ex expand(unsigned options=0) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
ex expand(unsigned options=0) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
protected:
ex derivative(const symbol & s) const;
bool is_equal_same_type(const basic & other) const;
bool match_same_type(const basic & other) const;
protected:
ex derivative(const symbol & s) const;
bool is_equal_same_type(const basic & other) const;
bool match_same_type(const basic & other) const;
// non-virtual functions in this class
protected:
ex pderivative(unsigned diff_param) const; // partial differentiation
// non-virtual functions in this class
protected:
ex pderivative(unsigned diff_param) const; // partial differentiation
bool lookup_remember_table(ex & result) const;
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);
bool lookup_remember_table(ex & result) const;
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);
-#define is_ex_the_function(OBJ, FUNCNAME) \\
- (GiNaC::is_exactly_a<GiNaC::function>(OBJ) && GiNaC::ex_to<GiNaC::function>(OBJ).get_serial() == function_index_##FUNCNAME)
+template <typename T>
+inline bool is_the_function(const ex & x)
+{
+ return is_exactly_a<function>(x)
+ && ex_to<function>(x).get_serial() == T::serial;
+}
+
+// Check whether OBJ is the specified symbolic function.
+#define is_ex_the_function(OBJ, FUNCNAME) (GiNaC::is_the_function<FUNCNAME##_SERIAL>(OBJ))
// we do not throw an exception here because this code is
// usually executed before main(), so the exception could not
// caught anyhow
// we do not throw an exception here because this code is
// usually executed before main(), so the exception could not
// caught anyhow
c.s << std::string(level, ' ') << class_name() << " "
<< registered_functions()[serial].name
c.s << std::string(level, ' ') << class_name() << " "
<< registered_functions()[serial].name
seq[i].print(c, level + delta_indent);
c.s << std::string(level + delta_indent, ' ') << "=====" << std::endl;
seq[i].print(c, level + delta_indent);
c.s << std::string(level + delta_indent, ' ') << "=====" << std::endl;
c.s << registered_functions()[serial].TeX_name;
printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence());
} else {
c.s << registered_functions()[serial].TeX_name;
printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence());
} else {
arg_diff = seq[i].diff(s);
// We apply the chain rule only when it makes sense. This is not
// just for performance reasons but also to allow functions to
arg_diff = seq[i].diff(s);
// We apply the chain rule only when it makes sense. This is not
// just for performance reasons but also to allow functions to