* Please do not modify it directly, edit the perl script instead!
* function.pl options: \$maxargs=${maxargs}
*
- * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
}
#define is_ex_the_function(OBJ, FUNCNAME) \\
- (is_exactly_a<GiNaC::function>(OBJ) && ex_to<GiNaC::function>(OBJ).get_serial() == function_index_##FUNCNAME)
+ (GiNaC::is_exactly_a<GiNaC::function>(OBJ) && GiNaC::ex_to<GiNaC::function>(OBJ).get_serial() == function_index_##FUNCNAME)
} // namespace GiNaC
* Please do not modify it directly, edit the perl script instead!
* function.pl options: \$maxargs=${maxargs}
*
- * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
return *this;
}
-
function_options & function_options::set_return_type(unsigned rt, unsigned rtt)
{
use_return_type = true;
function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser)
{
tinfo_key = TINFO_function;
+
+ // Force re-evaluation even if the exprseq was already evaluated
+ // (the exprseq copy constructor copies the flags)
+ clearflag(status_flags::evaluated);
}
function::function(unsigned ser, const exvector & v, bool discardable)
{
GINAC_ASSERT(serial<registered_functions().size());
+ const function_options &opt = registered_functions()[serial];
+
// Evaluate children first
exvector eseq;
- if (level == 1)
+ if (level == 1 || !(opt.evalf_params_first))
eseq = seq;
else if (level == -max_recursion_level)
throw(std::runtime_error("max recursion level reached"));
- else
+ else {
eseq.reserve(seq.size());
- --level;
- exvector::const_iterator it = seq.begin(), itend = seq.end();
- while (it != itend) {
- eseq.push_back(it->evalf(level));
- ++it;
+ --level;
+ exvector::const_iterator it = seq.begin(), itend = seq.end();
+ while (it != itend) {
+ eseq.push_back(it->evalf(level));
+ ++it;
+ }
}
-
- if (registered_functions()[serial].evalf_f==0) {
+
+ if (opt.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) {
+ if (opt.evalf_use_exvector_args)
+ return ((evalf_funcp_exvector)(opt.evalf_f))(seq);
+ switch (opt.nparams) {
// the following lines have been generated for max. ${maxargs} parameters
${evalf_switch_statement}
// end of generated lines
unsigned function::return_type(void) const
{
- if (seq.empty())
- return return_types::commutative;
- else
- return seq.begin()->return_type();
+ const function_options &opt = registered_functions()[serial];
+
+ if (opt.use_return_type) {
+ // Return type was explicitly specified
+ return opt.return_type;
+ } else {
+ // Default behavior is to use the return type of the first
+ // argument. Thus, exp() of a matrix behaves like a matrix, etc.
+ if (seq.empty())
+ return return_types::commutative;
+ else
+ return seq.begin()->return_type();
+ }
}
unsigned function::return_type_tinfo(void) const
{
- if (seq.empty())
- return tinfo_key;
- else
- return seq.begin()->return_type_tinfo();
+ const function_options &opt = registered_functions()[serial];
+
+ if (opt.use_return_type) {
+ // Return type was explicitly specified
+ return opt.return_type_tinfo;
+ } else {
+ // Default behavior is to use the return type of the first
+ // argument. Thus, exp() of a matrix behaves like a matrix, etc.
+ if (seq.empty())
+ return tinfo_key;
+ else
+ return seq.begin()->return_type_tinfo();
+ }
}
//////////