]> 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 0b92e19320f032f0c9a087e911addb165fad6ecb..b72a62c1ca111f52bc125d26e2e894148958827c 100755 (executable)
@@ -80,7 +80,6 @@ $constructors_implementation=generate(
 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
@@ -165,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-2001 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
@@ -201,28 +200,6 @@ $declare_function_macro
 const unsigned function_index_##NAME= \\
        GiNaC::function::register_new(GiNaC::function_options(#NAME).OPT);
 
-// The TYPECHECK-macros were used inside the _evalf() functions.  They are
-// considered obsolete now:  (FIXME: remove them)
-
-#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;
@@ -343,9 +320,6 @@ $constructors_interface
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 70;}
-       int degree(const ex & s) const;
-       int ldegree(const ex & s) const;
-       ex coeff(const ex & s, int n = 1) const;
        ex expand(unsigned options=0) const;
        ex eval(int level=0) const;
        ex evalf(int level=0) const;
@@ -391,7 +365,7 @@ template<> inline bool is_exactly_a<function>(const basic & obj)
 }
 
 #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
 
@@ -409,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-2001 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
@@ -426,6 +400,7 @@ $implementation=<<END_OF_IMPLEMENTATION;
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <iostream>
 #include <string>
 #include <stdexcept>
 #include <list>
@@ -440,7 +415,6 @@ $implementation=<<END_OF_IMPLEMENTATION;
 #include "inifcns.h"
 #include "tostring.h"
 #include "utils.h"
-#include "debugmsg.h"
 #include "remember.h"
 
 namespace GiNaC {
@@ -530,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;
@@ -589,14 +562,13 @@ 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;
 }
 
@@ -622,7 +594,6 @@ void function::destroy(bool call_parent)
 
 function::function(unsigned ser) : serial(ser)
 {
-       debugmsg("function ctor from unsigned",LOGLEVEL_CONSTRUCT);
        tinfo_key = TINFO_function;
 }
 
@@ -632,21 +603,18 @@ $constructors_implementation
 
 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;
 }
 
@@ -657,8 +625,6 @@ function::function(unsigned ser, exvector * vp)
 /** 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)) {
@@ -698,8 +664,6 @@ void function::archive(archive_node &n) const
 
 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)) {
@@ -751,24 +715,6 @@ ex function::expand(unsigned options) const
                return (options == 0) ? setflag(status_flags::expanded) : *this;
 }
 
-int function::degree(const ex & s) const
-{
-       return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-int function::ldegree(const ex & s) const
-{
-       return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-ex function::coeff(const ex & s, int n) const
-{
-       if (is_equal(ex_to<basic>(s)))
-               return n==1 ? _ex1 : _ex0;
-       else
-               return n==0 ? ex(*this) : _ex0;
-}
-
 ex function::eval(int level) const
 {
        GINAC_ASSERT(serial<registered_functions().size());
@@ -823,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
@@ -966,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();
+       }
 }
 
 //////////