machine catches fire. Another quite important intent is to allow people
to fiddle around with optimization.
+By default, the only documentation that will be built is this tutorial
+in @file{.info} format. To build the GiNaC tutorial and reference manual
+in HTML, DVI, PostScript, or PDF formats, use one of
+
+@example
+$ make html
+$ make dvi
+$ make ps
+$ make pdf
+@end example
+
Generally, the top-level Makefile runs recursively to the
subdirectories. It is therefore safe to go into any subdirectory
(@code{doc/}, @code{ginsh/}, @dots{}) and simply type @code{make}
(or @file{@var{INCLUDEDIR}/ginac/}, if specified).
@item
-All documentation (HTML and Postscript) will be stuffed into
+All documentation (info) will be stuffed into
@file{@var{PREFIX}/share/doc/GiNaC/} (or
@file{@var{DATADIR}/doc/GiNaC/}, if @var{DATADIR} was specified).
@cindex hierarchy of classes
@cindex atom
-Symbols are for symbolic manipulation what atoms are for chemistry. You
-can declare objects of class @code{symbol} as any other object simply by
-saying @code{symbol x,y;}. There is, however, a catch in here having to
-do with the fact that C++ is a compiled language. The information about
-the symbol's name is thrown away by the compiler but at a later stage
-you may want to print expressions holding your symbols. In order to
-avoid confusion GiNaC's symbols are able to know their own name. This
-is accomplished by declaring its name for output at construction time in
-the fashion @code{symbol x("x");}. If you declare a symbol using the
-default constructor (i.e. without string argument) the system will deal
-out a unique name. That name may not be suitable for printing but for
-internal routines when no output is desired it is often enough. We'll
-come across examples of such symbols later in this tutorial.
-
-This implies that the strings passed to symbols at construction time may
-not be used for comparing two of them. It is perfectly legitimate to
-write @code{symbol x("x"),y("x");} but it is likely to lead into
-trouble. Here, @code{x} and @code{y} are different symbols and
-statements like @code{x-y} will not be simplified to zero although the
-output @code{x-x} looks funny. Such output may also occur when there
-are two different symbols in two scopes, for instance when you call a
-function that declares a symbol with a name already existent in a symbol
-in the calling function. Again, comparing them (using @code{operator==}
-for instance) will always reveal their difference. Watch out, please.
+Symbolic indeterminates, or @dfn{symbols} for short, are for symbolic
+manipulation what atoms are for chemistry.
+
+A typical symbol definition looks like this:
+@example
+symbol x("x");
+@end example
+
+This definition actually contains three very different things:
+@itemize
+@item a C++ variable named @code{x}
+@item a @code{symbol} object stored in this C++ variable; this object
+ represents the symbol in a GiNaC expression
+@item the string @code{"x"} which is the name of the symbol, used (almost)
+ exclusively for printing expressions holding the symbol
+@end itemize
+
+Symbols have an explicit name, supplied as a string during construction,
+because in C++, variable names can't be used as values, and the C++ compiler
+throws them away during compilation.
+
+It is possible to omit the symbol name in the definition:
+@example
+symbol x;
+@end example
+
+In this case, GiNaC will assign the symbol an internal, unique name of the
+form @code{symbolNNN}. This won't affect the usability of the symbol but
+the output of your calculations will become more readable if you give your
+symbols sensible names (for intermediate expressions that are only used
+internally such anonymous symbols can be quite useful, however).
+
+Now, here is one important property of GiNaC that differentiates it from
+other computer algebra programs you may have used: GiNaC does @emph{not} use
+the names of symbols to tell them apart, but a (hidden) serial number that
+is unique for each newly created @code{symbol} object. In you want to use
+one and the same symbol in different places in your program, you must only
+create one @code{symbol} object and pass that around. If you create another
+symbol, even if it has the same name, GiNaC will treat it as a different
+indeterminate.
+
+Observe:
+@example
+ex f(int n)
+@{
+ symbol x("x");
+ return pow(x, n);
+@}
+
+int main()
+@{
+ symbol x("x");
+ ex e = f(6);
+
+ cout << e << endl;
+ // prints "x^6" which looks right, but...
+
+ cout << e.degree(x) << endl;
+ // ...this doesn't work. The symbol "x" here is different from the one
+ // in f() and in the expression returned by f(). Consequently, it
+ // prints "0".
+@}
+@end example
+
+One possibility to ensure that @code{f()} and @code{main()} use the same
+symbol is to pass the symbol as an argument to @code{f()}:
+@example
+ex f(int n, const ex & x)
+@{
+ return pow(x, n);
+@}
+
+int main()
+@{
+ symbol x("x");
+
+ // Now, f() uses the same symbol.
+ ex e = f(6, x);
+
+ cout << e.degree(x) << endl;
+ // prints "6", as expected
+@}
+@end example
+
+Another possibility would be to define a global symbol @code{x} that is used
+by both @code{f()} and @code{main()}. If you are using global symbols and
+multiple compilation units you must take special care, however. Suppose
+that you have a header file @file{globals.h} in your program that defines
+a @code{symbol x("x");}. In this case, every unit that includes
+@file{globals.h} would also get its own definition of @code{x} (because
+header files are just inlined into the source code by the C++ preprocessor),
+and hence you would again end up with multiple equally-named, but different,
+symbols. Instead, the @file{globals.h} header should only contain a
+@emph{declaration} like @code{extern symbol x;}, with the definition of
+@code{x} moved into a C++ source file such as @file{globals.cpp}.
+
+A different approach to ensuring that symbols used in different parts of
+your program are identical is to create them with a @emph{factory} function
+like this one:
+@example
+const symbol & get_symbol(const string & s)
+@{
+ static map<string, symbol> directory;
+ map<string, symbol>::iterator i = directory.find(s);
+ if (i != directory.end())
+ return i->second;
+ else
+ return directory.insert(make_pair(s, symbol(s))).first->second;
+@}
+@end example
+
+This function returns one newly constructed symbol for each name that is
+passed in, and it returns the same symbol when called multiple times with
+the same name. Using this symbol factory, we can rewrite our example like
+this:
+@example
+ex f(int n)
+@{
+ return pow(get_symbol("x"), n);
+@}
+
+int main()
+@{
+ ex e = f(6);
+
+ // Both calls of get_symbol("x") yield the same symbol.
+ cout << e.degree(get_symbol("x")) << endl;
+ // prints "6"
+@}
+@end example
+
+Instead of creating symbols from strings we could also have
+@code{get_symbol()} take, for example, an integer number as its argument.
+In this case, we would probably want to give the generated symbols names
+that include this number, which can be accomplished with the help of an
+@code{ostringstream}.
+
+In general, if you're getting weird results from GiNaC such as an expression
+@samp{x-x} that is not simplified to zero, you should check your symbol
+definitions.
+
+As we said, the names of symbols primarily serve for purposes of expression
+output. But there are actually two instances where GiNaC uses the names for
+identifying symbols: When constructing an expression from a string, and when
+recreating an expression from an archive (@pxref{Input/Output}).
+
+In addition to its name, a symbol may contain a special string that is used
+in LaTeX output:
+@example
+symbol x("x", "\\Box");
+@end example
+
+This creates a symbol that is printed as "@code{x}" in normal output, but
+as "@code{\Box}" in LaTeX code (@xref{Input/Output}, for more
+information about the different output formats of expressions in GiNaC).
+GiNaC automatically creates proper LaTeX code for symbols having names of
+greek letters (@samp{alpha}, @samp{mu}, etc.).
+
+@cindex @code{subs()}
+Symbols in GiNaC can't be assigned values. If you need to store results of
+calculations and give them a name, use C++ variables of type @code{ex}.
+If you want to replace a symbol in an expression with something else, you
+can invoke the expression's @code{.subs()} method
+(@pxref{Substituting Expressions}).
@cindex @code{realsymbol()}
-Symbols are expected to stand in for complex values by default, i.e. they live
+By default, symbols are expected to stand in for complex values, i.e. they live
in the complex domain. As a consequence, operations like complex conjugation,
-for example (see @ref{Complex Conjugation}), do @emph{not} evaluate if applied
+for example (@pxref{Complex Conjugation}), do @emph{not} evaluate if applied
to such symbols. Likewise @code{log(exp(x))} does not evaluate to @code{x},
because of the unknown imaginary part of @code{x}.
On the other hand, if you are sure that your symbols will hold only real values, you
the domain of the symbol. Instead of @code{symbol x("x");} you can write
@code{realsymbol x("x");} to tell GiNaC that @code{x} stands in for real values.
-@cindex @code{subs()}
-Although symbols can be assigned expressions for internal reasons, you
-should not do it (and we are not going to tell you how it is done). If
-you want to replace a symbol with something else in an expression, you
-can use the expression's @code{.subs()} method (@pxref{Substituting Expressions}).
-
@node Numbers, Constants, Symbols, Basic Concepts
@c node-name, next, previous, up
@end multitable
@end cartouche
+@subsection Numeric functions
+
+The following functions can be applied to @code{numeric} objects and will be
+evaluated immediately:
+
+@cartouche
+@multitable @columnfractions .30 .70
+@item @strong{Name} @tab @strong{Function}
+@item @code{inverse(z)}
+@tab returns @math{1/z}
+@cindex @code{inverse()} (numeric)
+@item @code{pow(a, b)}
+@tab exponentiation @math{a^b}
+@item @code{abs(z)}
+@tab absolute value
+@item @code{real(z)}
+@tab real part
+@cindex @code{real()}
+@item @code{imag(z)}
+@tab imaginary part
+@cindex @code{imag()}
+@item @code{csgn(z)}
+@tab complex sign (returns an @code{int})
+@item @code{numer(z)}
+@tab numerator of rational or complex rational number
+@item @code{denom(z)}
+@tab denominator of rational or complex rational number
+@item @code{sqrt(z)}
+@tab square root
+@item @code{isqrt(n)}
+@tab integer square root
+@cindex @code{isqrt()}
+@item @code{sin(z)}
+@tab sine
+@item @code{cos(z)}
+@tab cosine
+@item @code{tan(z)}
+@tab tangent
+@item @code{asin(z)}
+@tab inverse sine
+@item @code{acos(z)}
+@tab inverse cosine
+@item @code{atan(z)}
+@tab inverse tangent
+@item @code{atan(y, x)}
+@tab inverse tangent with two arguments
+@item @code{sinh(z)}
+@tab hyperbolic sine
+@item @code{cosh(z)}
+@tab hyperbolic cosine
+@item @code{tanh(z)}
+@tab hyperbolic tangent
+@item @code{asinh(z)}
+@tab inverse hyperbolic sine
+@item @code{acosh(z)}
+@tab inverse hyperbolic cosine
+@item @code{atanh(z)}
+@tab inverse hyperbolic tangent
+@item @code{exp(z)}
+@tab exponential function
+@item @code{log(z)}
+@tab natural logarithm
+@item @code{Li2(z)}
+@tab dilogarithm
+@item @code{zeta(z)}
+@tab Riemann's zeta function
+@item @code{tgamma(z)}
+@tab gamma function
+@item @code{lgamma(z)}
+@tab logarithm of gamma function
+@item @code{psi(z)}
+@tab psi (digamma) function
+@item @code{psi(n, z)}
+@tab derivatives of psi function (polygamma functions)
+@item @code{factorial(n)}
+@tab factorial function @math{n!}
+@item @code{doublefactorial(n)}
+@tab double factorial function @math{n!!}
+@cindex @code{doublefactorial()}
+@item @code{binomial(n, k)}
+@tab binomial coefficients
+@item @code{bernoulli(n)}
+@tab Bernoulli numbers
+@cindex @code{bernoulli()}
+@item @code{fibonacci(n)}
+@tab Fibonacci numbers
+@cindex @code{fibonacci()}
+@item @code{mod(a, b)}
+@tab modulus in positive representation (in the range @code{[0, abs(b)-1]} with the sign of b, or zero)
+@cindex @code{mod()}
+@item @code{smod(a, b)}
+@tab modulus in symmetric representation (in the range @code{[-iquo(abs(b)-1, 2), iquo(abs(b), 2)]})
+@cindex @code{smod()}
+@item @code{irem(a, b)}
+@tab integer remainder (has the sign of @math{a}, or is zero)
+@cindex @code{irem()}
+@item @code{irem(a, b, q)}
+@tab integer remainder and quotient, @code{irem(a, b, q) == a-q*b}
+@item @code{iquo(a, b)}
+@tab integer quotient
+@cindex @code{iquo()}
+@item @code{iquo(a, b, r)}
+@tab integer quotient and remainder, @code{r == a-iquo(a, b)*b}
+@item @code{gcd(a, b)}
+@tab greatest common divisor
+@item @code{lcm(a, b)}
+@tab least common multiple
+@end multitable
+@end cartouche
+
+Most of these functions are also available as symbolic functions that can be
+used in expressions (@pxref{Mathematical functions}) or, like @code{gcd()},
+as polynomial algorithms.
+
@subsection Converting numbers
Sometimes it is desirable to convert a @code{numeric} object back to a
general.
The @code{matrix} class provides a couple of additional methods for
-computing determinants, traces, and characteristic polynomials:
+computing determinants, traces, characteristic polynomials and ranks:
@cindex @code{determinant()}
@cindex @code{trace()}
@cindex @code{charpoly()}
+@cindex @code{rank()}
@example
ex matrix::determinant(unsigned algo=determinant_algo::automatic) const;
ex matrix::trace() const;
ex matrix::charpoly(const ex & lambda) const;
+unsigned matrix::rank() const;
@end example
The @samp{algo} argument of @code{determinant()} allows to select
algorithm that is likely (but not guaranteed) to give the result most
quickly.
-@cindex @code{inverse()}
+@cindex @code{inverse()} (matrix)
@cindex @code{solve()}
Matrices may also be inverted using the @code{ex matrix::inverse()}
method and linear systems may be solved with:
arbitrary objects. Rather, non-commutativity in GiNaC is a property of the
classes of objects involved, and non-commutative products are formed with
the usual @samp{*} operator, as are ordinary products. GiNaC is capable of
-figuring out by itself which objects commute and will group the factors
+figuring out by itself which objects commutate and will group the factors
by their class. Consider this example:
@example
As can be seen, GiNaC pulls out the overall commutative factor @samp{-16} and
groups the non-commutative factors (the gammas and the su(3) generators)
together while preserving the order of factors within each class (because
-Clifford objects commute with color objects). The resulting expression is a
+Clifford objects commutate with color objects). The resulting expression is a
@emph{commutative} product with two factors that are themselves non-commutative
products (@samp{gamma~mu*gamma~nu} and @samp{T.a*T.b}). For clarification,
parentheses are placed around the non-commutative products in the output.
canonicalize themselves according to rules specified in the implementation
of the non-commutative classes. The drawback is that to work with other than
the built-in algebras you have to implement new classes yourself. Symbols
-always commute and it's not possible to construct non-commutative products
+always commutate and it's not possible to construct non-commutative products
using symbols to represent the algebra elements or generators. User-defined
functions can, however, be specified as being non-commutative.
expressions in GiNaC:
@itemize
-@item @code{return_types::commutative}: Commutes with everything. Most GiNaC
+@item @code{return_types::commutative}: Commutates with everything. Most GiNaC
classes are of this kind.
@item @code{return_types::noncommutative}: Non-commutative, belonging to a
certain class of non-commutative objects which can be determined with the
- @code{return_type_tinfo()} method. Expressions of this category commute
+ @code{return_type_tinfo()} method. Expressions of this category commutate
with everything except @code{noncommutative} expressions of the same
class.
@item @code{return_types::noncommutative_composite}: Non-commutative, composed
of non-commutative objects of different classes. Expressions of this
- category don't commute with any other @code{noncommutative} or
+ category don't commutate with any other @code{noncommutative} or
@code{noncommutative_composite} expressions.
@end itemize
which takes two arguments: the index and a @dfn{representation label} in the
range 0 to 255 which is used to distinguish elements of different Clifford
algebras (this is also called a @dfn{spin line index}). Gammas with different
-labels commute with each other. The dimension of the index can be 4 or (in
+labels commutate with each other. The dimension of the index can be 4 or (in
the framework of dimensional regularization) any symbolic value. Spinor
indices on Dirac gammas are not supported in GiNaC.
GiNaC will complain and/or produce incorrect results.
@cindex @code{dirac_gamma5()}
-There is a special element @samp{gamma5} that commutes with all other
+There is a special element @samp{gamma5} that commutates with all other
gammas, has a unit square, and in 4 dimensions equals
@samp{gamma~0 gamma~1 gamma~2 gamma~3}, provided by
@cindex @code{dirac_trace()}
To calculate the trace of an expression containing strings of Dirac gammas
-you use the function
+you use one of the functions
@example
+ex dirac_trace(const ex & e, const std::set<unsigned char> & rls, const ex & trONE = 4);
+ex dirac_trace(const ex & e, const lst & rll, const ex & trONE = 4);
ex dirac_trace(const ex & e, unsigned char rl = 0, const ex & trONE = 4);
@end example
-This function takes the trace of all gammas with the specified representation
-label; gammas with other labels are left standing. The last argument to
+These functions take the trace over all gammas in the specified set @code{rls}
+or list @code{rll} of representation labels, or the single label @code{rl};
+gammas with other labels are left standing. The last argument to
@code{dirac_trace()} is the value to be returned for the trace of the unity
-element, which defaults to 4. The @code{dirac_trace()} function is a linear
-functional that is equal to the usual trace only in @math{D = 4} dimensions.
-In particular, the functional is not cyclic in @math{D != 4} dimensions when
-acting on expressions containing @samp{gamma5}, so it's not a proper trace.
-This @samp{gamma5} scheme is described in greater detail in
+element, which defaults to 4.
+
+The @code{dirac_trace()} function is a linear functional that is equal to the
+ordinary matrix trace only in @math{D = 4} dimensions. In particular, the
+functional is not cyclic in @math{D != 4} dimensions when acting on
+expressions containing @samp{gamma5}, so it's not a proper trace. This
+@samp{gamma5} scheme is described in greater detail in
@cite{The Role of gamma5 in Dimensional Regularization}.
The value of the trace itself is also usually different in 4 and in
which takes two arguments: the index and a @dfn{representation label} in the
range 0 to 255 which is used to distinguish elements of different color
-algebras. Objects with different labels commute with each other. The
+algebras. Objects with different labels commutate with each other. The
dimension of the index must be exactly 8 and it should be of class @code{idx},
not @code{varidx}.
@end example
@cindex @code{color_trace()}
-To calculate the trace of an expression containing color objects you use the
-function
+To calculate the trace of an expression containing color objects you use one
+of the functions
@example
+ex color_trace(const ex & e, const std::set<unsigned char> & rls);
+ex color_trace(const ex & e, const lst & rll);
ex color_trace(const ex & e, unsigned char rl = 0);
@end example
-This function takes the trace of all color @samp{T} objects with the
-specified representation label; @samp{T}s with other labels are left
-standing. For example:
+These functions take the trace over all color @samp{T} objects in the
+specified set @code{rls} or list @code{rll} of representation labels, or the
+single label @code{rl}; @samp{T}s with other labels are left standing. For
+example:
@example
...
@multitable @columnfractions .30 .70
@item @strong{Flag} @tab @strong{Returns true if the object is@dots{}}
@item @code{numeric}
-@tab @dots{}a number (same as @code{is_<numeric>(...)})
+@tab @dots{}a number (same as @code{is_a<numeric>(...)})
@item @code{real}
@tab @dots{}a real integer, rational or float (i.e. is not complex)
@item @code{rational}
@end cartouche
To determine whether an expression is commutative or non-commutative and if
-so, with which other expressions it would commute, you use the methods
+so, with which other expressions it would commutate, you use the methods
@code{return_type()} and @code{return_type_tinfo()}. @xref{Non-commutative objects},
for an explanation of these.
@example
@{
- symbol a("a"), b("b"), c("c");
+ symbol a("a"), b("b"), c("c"), x("x");
idx i(symbol("i"), 3);
ex e = pow(sin(x) - cos(x), 4);
original polynomial.
-@subsection GCD and LCM
+@subsection GCD, LCM and resultant
@cindex GCD
@cindex LCM
@cindex @code{gcd()}
@}
@end example
+@cindex resultant
+@cindex @code{resultant()}
+
+The resultant of two expressions only makes sense with polynomials.
+It is always computed with respect to a specific symbol within the
+expressions. The function has the interface
+
+@example
+ex resultant(const ex & a, const ex & b, const ex & s);
+@end example
+
+Resultants are symmetric in @code{a} and @code{b}. The following example
+computes the resultant of two expressions with respect to @code{x} and
+@code{y}, respectively:
+
+@example
+#include <ginac/ginac.h>
+using namespace GiNaC;
+
+int main()
+@{
+ symbol x("x"), y("y");
+
+ ex e1 = x+pow(y,2), e2 = 2*pow(x,3)-1; // x+y^2, 2*x^3-1
+ ex r;
+
+ r = resultant(e1, e2, x);
+ // -> 1+2*y^6
+ r = resultant(e1, e2, y);
+ // -> 1-4*x^3+4*x^6
+@}
+@end example
@subsection Square-free decomposition
@cindex square-free decomposition
@item @code{psi(n, x)}
@tab derivatives of psi function (polygamma functions)
@item @code{factorial(n)}
-@tab factorial function
+@tab factorial function @math{n!}
@cindex @code{factorial()}
-@item @code{binomial(n, m)}
+@item @code{binomial(n, k)}
@tab binomial coefficients
@cindex @code{binomial()}
@item @code{Order(x)}
option which is explained in the next section.
+@subsection Functions with a variable number of arguments
+
+The @code{DECLARE_FUNCTION} and @code{REGISTER_FUNCTION} macros define
+functions with a fixed number of arguments. Sometimes, though, you may need
+to have a function that accepts a variable number of expressions. One way to
+accomplish this is to pass variable-length lists as arguments. The
+@code{Li()} function uses this method for multiple polylogarithms.
+
+It is also possible to define functions that accept a different number of
+parameters under the same function name, such as the @code{psi()} function
+which can be called either as @code{psi(z)} (the digamma function) or as
+@code{psi(n, z)} (polygamma functions). These are actually two different
+functions in GiNaC that, however, have the same name. Defining such
+functions is not possible with the macros but requires manually fiddling
+with GiNaC internals. If you are interested, please consult the GiNaC source
+code for the @code{psi()} function (@file{inifcns.h} and
+@file{inifcns_gamma.cpp}).
+
@node Printing, Structures, Symbolic functions, Extending GiNaC
@c node-name, next, previous, up