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();
+ }
}
//////////