]> www.ginac.de Git - ginac.git/blobdiff - ginac/function.pl
function_options::do_not_evalf_params() now actually works
[ginac.git] / ginac / function.pl
index d75e8f645ebf3e359d565067837b31ba60d7a174..b72a62c1ca111f52bc125d26e2e894148958827c 100755 (executable)
@@ -164,7 +164,7 @@ $interface=<<END_OF_INTERFACE;
  *  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
@@ -383,7 +383,7 @@ $implementation=<<END_OF_IMPLEMENTATION;
  *  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
@@ -504,7 +504,6 @@ function_options& function_options::series_func(series_funcp_exvector s)
        return *this;
 }
 
-
 function_options & function_options::set_return_type(unsigned rt, unsigned rtt)
 {
        use_return_type = true;
@@ -770,28 +769,31 @@ ex function::evalf(int level) const
 {
        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
@@ -913,18 +915,36 @@ bool function::match_same_type(const basic & other) const
 
 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();
+       }
 }
 
 //////////