@item @code{Li2(x)}
@tab Dilogarithm
@cindex @code{Li2()}
+@item @code{Li(n, x)}
+@tab classical polylogarithm as well as multiple polylogarithm
+@cindex @code{Li()}
+@item @code{S(n, p, x)}
+@tab Nielsen's generalized polylogarithm
+@cindex @code{S()}
+@item @code{H(n, x)}
+@tab harmonic polylogarithm
+@cindex @code{H()}
@item @code{zeta(x)}
-@tab Riemann's zeta function
+@tab Riemann's zeta function as well as multiple zeta value
@cindex @code{zeta()}
@item @code{zeta(n, x)}
@tab derivatives of Riemann's zeta function
@item @code{Order(x)}
@tab order term function in truncated power series
@cindex @code{Order()}
-@item @code{Li(n, x)}
-@tab polylogarithm
-@cindex @code{Li()}
-@item @code{S(n, p, x)}
-@tab Nielsen's generalized polylogarithm
-@cindex @code{S()}
-@item @code{H(m_lst, x)}
-@tab harmonic polylogarithm
-@cindex @code{H()}
-@item @code{Li(m_lst, x_lst)}
-@tab multiple polylogarithm
-@cindex @code{Li()}
-@item @code{mZeta(m_lst)}
-@tab multiple zeta value
-@cindex @code{mZeta()}
@end multitable
@end cartouche
standard incorporate these functions in the complex domain in a manner
compatible with C99.
+@cindex nested sums
+The functions @code{Li}, @code{S}, @code{H} and @code{zeta} share certain
+properties and are refered to as nested sums functions, because they all
+have a uniform representation as nested sums (for mathematical details and
+conventions see @emph{S.Moch, P.Uwer, S.Weinzierl hep-ph/0110083}).
+@code{Li} and @code{zeta} can take @code{lst}s as arguments, in which case
+they represent not classical polylogarithms or simple zeta functions but
+multiple polylogarithms or multiple zeta values respectively (note that the two
+@code{lst}s for @code{Li} must have the same length). The first parameter
+of the harmonic polylogarithm can also be a @code{lst}.
+For all these functions the arguments in the @code{lst}s are expected to be
+in the same order as they appear in the nested sums representation
+(note that this convention differs from the one in the aforementioned paper
+in the cases of @code{Li} and @code{zeta}).
+If you want to numerically evaluate the functions, the parameters @code{n}
+and @code{p} as well as @code{x} in the case of @code{zeta} must all be
+positive integers (or @code{lst}s containing them). The multiple polylogarithm
+has the additional restriction that the second parameter must only
+contain arguments with an absolute value smaller than one.
@node Solving Linear Systems of Equations, Input/Output, Built-in Functions, Methods and Functions
@c node-name, next, previous, up
@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()}
@{
...
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
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)
@}
@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
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>)
There is currently no equivalent of @code{set_print_func()} for functions.
+@subsection Adding new output formats
+
+Creating a new output format involves subclassing @code{print_context},
+which is somewhat similar to adding a new algebraic class
+(@pxref{Adding classes}). There is a macro @code{GINAC_DECLARE_PRINT_CONTEXT}
+that needs to go into the class definition, and a corresponding macro
+@code{GINAC_IMPLEMENT_PRINT_CONTEXT} that has to appear at global scope.
+Every @code{print_context} class needs to provide a default constructor
+and a constructor from an @code{std::ostream} and an @code{unsigned}
+options value.
+
+Here is an example for a user-defined @code{print_context} class:
+
+@example
+class print_myformat : public print_dflt
+@{
+ GINAC_DECLARE_PRINT_CONTEXT(print_myformat, print_dflt)
+public:
+ print_myformat(std::ostream & os, unsigned opt = 0)
+ : print_dflt(os, opt) @{@}
+@};
+
+print_myformat::print_myformat() : print_dflt(std::cout) @{@}
+
+GINAC_IMPLEMENT_PRINT_CONTEXT(print_myformat, print_dflt)
+@end example
+
+That's all there is to it. None of the actual expression output logic is
+implemented in this class. It merely serves as a selector for choosing
+a particular format. The algorithms for printing expressions in the new
+format are implemented as print methods, as described above.
+
+@code{print_myformat} is a subclass of @code{print_dflt}, so it behaves
+exactly like GiNaC's default output format:
+
+@example
+@{
+ symbol x("x");
+ ex e = pow(x, 2) + 1;
+
+ // this prints "1+x^2"
+ cout << e << endl;
+
+ // this also prints "1+x^2"
+ e.print(print_myformat()); cout << endl;
+
+ ...
+@}
+@end example
+
+To fill @code{print_myformat} with life, we need to supply appropriate
+print methods with @code{set_print_func()}, like this:
+
+@example
+// This prints powers with '**' instead of '^'. See the LaTeX output
+// example above for explanations.
+void print_power_as_myformat(const power & p,
+ const print_myformat & c,
+ unsigned level)
+@{
+ unsigned power_prec = p.precedence();
+ if (level >= power_prec)
+ c.s << '(';
+ p.op(0).print(c, power_prec);
+ c.s << "**";
+ p.op(1).print(c, power_prec);
+ if (level >= power_prec)
+ c.s << ')';
+@}
+
+@{
+ ...
+ // install a new print method for power objects
+ set_print_func<power, print_myformat>(print_power_as_myformat);
+
+ // now this prints "1+x**2"
+ e.print(print_myformat()); cout << endl;
+
+ // but the default format is still "1+x^2"
+ cout << e << endl;
+@}
+@end example
+
@node Structures, Adding classes, Printing, Extending GiNaC
@c node-name, next, previous, up
and the @samp{AM_PATH_GINAC} macro. The program used here is @file{simple.cpp}:
@example
+#include <iostream>
#include <ginac/ginac.h>
int main()