]> www.ginac.de Git - ginac.git/commitdiff
synced to HEAD
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Tue, 18 Nov 2003 20:13:27 +0000 (20:13 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Tue, 18 Nov 2003 20:13:27 +0000 (20:13 +0000)
doc/tutorial/ginac.texi
ginac/function.pl

index a4ecc2ff694b70cba6e680859baa3ec9c8d1a5cc..e3340e68a85ac6b60e9fd31cb64997d59d853b74 100644 (file)
@@ -5209,12 +5209,7 @@ that is not further evaluated:
 @example
 DECLARE_FUNCTION_2P(myfcn)
 
-static ex myfcn_eval(const ex & x, const ex & y)
-@{
-    return myfcn(x, y).hold();
-@}
-
-REGISTER_FUNCTION(myfcn, eval_func(myfcn_eval))
+REGISTER_FUNCTION(myfcn, dummy())
 @end example
 
 Any code that has seen the @code{DECLARE_FUNCTION} line can use @code{myfcn()}
@@ -5224,33 +5219,20 @@ in algebraic expressions:
 @{
     ...
     symbol x("x");
-    ex e = 2*myfcn(42, 3*x+1) - x;
-     // this calls myfcn_eval(42, 3*x+1), and inserts its return value into
-     // the actual expression
+    ex e = 2*myfcn(42, 1+3*x) - x;
     cout << e << endl;
      // prints '2*myfcn(42,1+3*x)-x'
     ...
 @}
 @end example
 
-@cindex @code{hold()}
-@cindex evaluation
-The @code{eval_func()} option specifies the C++ function that implements
-the @code{eval()} method, GiNaC's anonymous evaluator. This function takes
-the same number of arguments as the associated symbolic function (two in this
-case) and returns the (possibly transformed or in some way simplified)
-symbolically evaluated function (@xref{Automatic evaluation}, for a description
-of the automatic evaluation process). If no (further) evaluation is to take
-place, the @code{eval_func()} function must return the original function
-with @code{.hold()}, to avoid a potential infinite recursion. If your
-symbolic functions produce a segmentation fault or stack overflow when
-using them in expressions, you are probably missing a @code{.hold()}
-somewhere.
+The @code{dummy()} option in the @code{REGISTER_FUNCTION} line signifies
+"no options". A function with no options specified merely acts as a kind of
+container for its arguments. It is a pure "dummy" function with no associated
+logic (which is, however, sometimes perfectly sufficient).
 
-There is not much you can do with the @code{myfcn} function. It merely acts
-as a kind of container for its arguments (which is, however, sometimes
-perfectly sufficient). Let's have a look at the implementation of GiNaC's
-cosine function.
+Let's now have a look at the implementation of GiNaC's cosine function for an
+example of how to make an "intelligent" function.
 
 @subsection The cosine function
 
@@ -5264,9 +5246,38 @@ which declares to all programs using GiNaC that there is a function @samp{cos}
 that takes one @code{ex} as an argument. This is all they need to know to use
 this function in expressions.
 
-The implementation of the cosine function is in @file{inifcns_trans.cpp}. The
-@code{eval_func()} function looks something like this (actually, it doesn't
-look like this at all, but it should give you an idea what is going on):
+The implementation of the cosine function is in @file{inifcns_trans.cpp}. Here
+is its @code{REGISTER_FUNCTION} line:
+
+@example
+REGISTER_FUNCTION(cos, eval_func(cos_eval).
+                       evalf_func(cos_evalf).
+                       derivative_func(cos_deriv).
+                       latex_name("\\cos"));
+@end example
+
+There are four options defined for the cosine function. One of them
+(@code{latex_name}) gives the function a proper name for LaTeX output; the
+other three indicate the C++ functions in which the "brains" of the cosine
+function are defined.
+
+@cindex @code{hold()}
+@cindex evaluation
+The @code{eval_func()} option specifies the C++ function that implements
+the @code{eval()} method, GiNaC's anonymous evaluator. This function takes
+the same number of arguments as the associated symbolic function (one in this
+case) and returns the (possibly transformed or in some way simplified)
+symbolically evaluated function (@xref{Automatic evaluation}, for a description
+of the automatic evaluation process). If no (further) evaluation is to take
+place, the @code{eval_func()} function must return the original function
+with @code{.hold()}, to avoid a potential infinite recursion. If your
+symbolic functions produce a segmentation fault or stack overflow when
+using them in expressions, you are probably missing a @code{.hold()}
+somewhere.
+
+The @code{eval_func()} function for the cosine looks something like this
+(actually, it doesn't look like this at all, but it should give you an idea
+what is going on):
 
 @example
 static ex cos_eval(const ex & x)
@@ -5290,6 +5301,20 @@ static ex cos_eval(const ex & x)
 @}
 @end example
 
+This function is called every time the cosine is used in a symbolic expression:
+
+@example
+@{
+    ...
+    e = cos(Pi);
+     // this calls cos_eval(Pi), and inserts its return value into
+     // the actual expression
+    cout << e << endl;
+     // prints '-1'
+    ...
+@}
+@end example
+
 In this way, @code{cos(4*Pi)} automatically becomes @math{1},
 @code{cos(asin(a+b))} becomes @code{sqrt(1-(a+b)^2)}, etc. If no reasonable
 symbolic transformation can be done, the unmodified function is returned
@@ -5356,26 +5381,13 @@ static ex tan_series(const ex & x, const relational & rel,
 The @code{series()} implementation of a function @emph{must} return a
 @code{pseries} object, otherwise your code will crash.
 
-Now that all the ingredients have been set up, the @code{REGISTER_FUNCTION}
-macro is used to tell the system how the @code{cos()} function behaves:
-
-@example
-REGISTER_FUNCTION(cos, eval_func(cos_eval).
-                       evalf_func(cos_evalf).
-                       derivative_func(cos_deriv).
-                       latex_name("\\cos"));
-@end example
-
-This registers the @code{cos_eval()}, @code{cos_evalf()} and
-@code{cos_deriv()} C++ functions with the @code{cos()} function, and also
-gives it a proper LaTeX name.
-
 @subsection Function options
 
 GiNaC functions understand several more options which are always
 specified as @code{.option(params)}. None of them are required, but you
-need to specify at least one option to @code{REGISTER_FUNCTION()} (usually
-the @code{eval()} method).
+need to specify at least one option to @code{REGISTER_FUNCTION()}. There
+is a do-nothing option called @code{dummy()} which you can use to define
+functions without any special options.
 
 @example
 eval_func(<C++ function>)
index d3378e339294b050d2c61aed0e064dfa206cba84..cbf65eccb9e59fb1973c30e9016cc0ef142f240d 100755 (executable)
@@ -233,6 +233,8 @@ public:
        function_options(std::string const & n, std::string const & tn=std::string());
        ~function_options();
        void initialize(void);
+
+       function_options & dummy() { return *this; }
        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
@@ -445,7 +447,7 @@ function_options::function_options()
 function_options::function_options(std::string const & n, std::string const & tn)
 {
        initialize();
-       set_name(n,tn);
+       set_name(n, tn);
 }
 
 function_options::~function_options()
@@ -455,7 +457,7 @@ function_options::~function_options()
 
 void function_options::initialize(void)
 {
-       set_name("unnamed_function","\\\\mbox{unnamed}");
+       set_name("unnamed_function", "\\\\mbox{unnamed}");
        nparams = 0;
        eval_f = evalf_f = derivative_f = series_f = 0;
        evalf_params_first = true;