This is a tutorial that documents GiNaC @value{VERSION}, an open
framework for symbolic computation within the C++ programming language.
-Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1999-2011 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2015 Johannes Gutenberg University Mainz, Germany
@sp 2
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@section License
The GiNaC framework for symbolic computation within the C++ programming
-language is Copyright @copyright{} 1999-2011 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2015 Johannes Gutenberg
University Mainz, Germany.
This program is free software; you can redistribute it and/or
In order to install GiNaC on your system, some prerequisites need to be
met. First of all, you need to have a C++-compiler adhering to the
-ANSI-standard @cite{ISO/IEC 14882:1998(E)}. We used GCC for development
+ISO standard @cite{ISO/IEC 14882:2011(E)}. We used GCC for development
so if you have a different compiler you are on your own. For the
configuration to succeed you need a Posix compliant shell installed in
@file{/bin/sh}, GNU @command{bash} is fine. The pkg-config utility is
the same type to GiNaC methods such as @code{subs()} and some @code{matrix}
constructors, so you should have a basic understanding of them.
-Lists can be constructed by assigning a comma-separated sequence of
-expressions:
+Lists can be constructed from an initializer list of expressions:
@example
@{
symbol x("x"), y("y");
lst l;
- l = x, 2, y, x+y;
+ l = @{x, 2, y, x+y@};
// now, l is a list holding the expressions 'x', '2', 'y', and 'x+y',
// in that order
...
@end example
-There are also constructors that allow direct creation of lists of up to
-16 expressions, which is often more convenient but slightly less efficient:
-
-@example
- ...
- // This produces the same list 'l' as above:
- // lst l(x, 2, y, x+y);
- // lst l = lst(x, 2, y, x+y);
- ...
-@end example
-
Use the @code{nops()} method to determine the size (number of expressions) of
a list and the @code{op()} method or the @code{[]} operator to access
individual elements:
cout << M2 << endl;
// -> [[a,0],[0,b]]
- cout << matrix(2, 2, lst(a, 0, 0, b)) << endl;
+ cout << matrix(2, 2, lst@{a, 0, 0, b@}) << endl;
// -> [[a,0],[0,b]]
- cout << lst_to_matrix(lst(lst(a, 0), lst(0, b))) << endl;
+ cout << lst_to_matrix(lst@{lst@{a, 0@}, lst@{0, b@}@}) << endl;
// -> [[a,0],[0,b]]
- cout << diag_matrix(lst(a, b)) << endl;
+ cout << diag_matrix(lst@{a, b@}) << endl;
// -> [[a,0],[0,b]]
cout << unit_matrix(3) << endl;
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. Both
symbols and user-defined functions can be specified as being non-commutative.
+For symbols, this is done by subclassing class symbol; for functions,
+by explicitly setting the return type (@pxref{Symbolic functions}).
@cindex @code{return_type()}
@cindex @code{return_type_tinfo()}
dirac_gamma(mu.toggle_variance()) *
(dirac_slash(l, D) + m * dirac_ONE());
e = dirac_trace(e).simplify_indexed(sp);
- e = e.collect(lst(l, ldotq, m));
+ e = e.collect(lst@{l, ldotq, m@});
cout << e << endl;
// -> (8-4*D)*l^2+(8-4*D)*ldotq+4*D*m^2
@}
Note that the call @code{clifford_unit(mu, minkmetric())} creates
something very close to @code{dirac_gamma(mu)}, although
@code{dirac_gamma} have more efficient simplification mechanism.
-@cindex @code{clifford::get_metric()}
+@cindex @code{get_metric()}
The method @code{clifford::get_metric()} returns a metric defining this
Clifford number.
...
idx i(symbol("i"), 4);
realsymbol s("s");
- ex M = diag_matrix(lst(1, -1, 0, s));
+ ex M = diag_matrix(lst@{1, -1, 0, s@});
ex e = clifford_unit(i, M);
ex e0 = e.subs(i == 0);
ex e1 = e.subs(i == 1);
...
idx i(symbol("i"), 4);
realsymbol s("s");
- ex M = diag_matrix(lst(1, -1, 0, s));
- ex e0 = lst_to_clifford(lst(1, 0, 0, 0), i, M);
- ex e1 = lst_to_clifford(lst(0, 1, 0, 0), i, M);
- ex e2 = lst_to_clifford(lst(0, 0, 1, 0), i, M);
- ex e3 = lst_to_clifford(lst(0, 0, 0, 1), i, M);
+ ex M = diag_matrix(lst@{1, -1, 0, s@});
+ ex e0 = lst_to_clifford(lst@{1, 0, 0, 0@}, i, M);
+ ex e1 = lst_to_clifford(lst@{0, 1, 0, 0@}, i, M);
+ ex e2 = lst_to_clifford(lst@{0, 0, 1, 0@}, i, M);
+ ex e3 = lst_to_clifford(lst@{0, 0, 0, 1@}, i, M);
...
@}
@end example
@example
@{
symbol A("A"), B("B"), C("C");
- ex e = lst(lst(A, B), C);
+ ex e = lst@{lst@{A, B@}, C@};
std::copy(e.begin(), e.end(),
std::ostream_iterator<ex>(cout, "\n"));
// -> 73
ex e2 = x*y + x;
- cout << "e2(-2, 4) = " << e2.subs(lst(x == -2, y == 4)) << endl;
+ cout << "e2(-2, 4) = " << e2.subs(lst@{x == -2, y == 4@}) << endl;
// -> -10
@}
@end example
If you specify multiple substitutions, they are performed in parallel, so e.g.
-@code{subs(lst(x == y, y == x))} exchanges @samp{x} and @samp{y}.
+@code{subs(lst@{x == y, y == x@})} exchanges @samp{x} and @samp{y}.
The second form of @code{subs()} takes an @code{exmap} object which is a
pair associative container that maps expressions to expressions (currently
symbol x("x"), y("y");
ex e2 = x*y + x;
- cout << "e2(-2, 4) = " << e2.subs(lst(x, y), lst(-2, 4)) << endl;
+ cout << "e2(-2, 4) = " << e2.subs(lst@{x, y@}, lst@{-2, 4@}) << endl;
@}
@end example
@example
(x*y*sin(y)).is_polynomial(x) // Returns true.
-(x*y*sin(y)).is_polynomial(lst(x,y)) // Returns false.
+(x*y*sin(y)).is_polynomial(lst@{x,y@}) // Returns false.
@end example
@subsection Expanding and collecting
Square-free decomposition is available in GiNaC:
@example
-ex sqrfree(const ex & a, const lst & l = lst());
+ex sqrfree(const ex & a, const lst & l = lst@{@});
@end example
Here is an example that by the way illustrates how the exact form of the
result may slightly depend on the order of differentiation, calling for
symbol x("x"), y("y");
ex BiVarPol = expand(pow(2-2*y,3) * pow(1+x*y,2) * pow(x-2*y,2) * (x+y));
- cout << sqrfree(BiVarPol, lst(x,y)) << endl;
+ cout << sqrfree(BiVarPol, lst@{x,y@}) << endl;
// -> 8*(1-y)^3*(y*x^2-2*y+x*(1-2*y^2))^2*(y+x)
- cout << sqrfree(BiVarPol, lst(y,x)) << endl;
+ cout << sqrfree(BiVarPol, lst@{y,x@}) << endl;
// -> 8*(1-y)^3*(-y*x^2+2*y+x*(-1+2*y^2))^2*(y+x)
cout << sqrfree(BiVarPol) << endl;
idx i(symbol("i"), 3), j(symbol("j"), 3), k(symbol("k"), 3);
symbol A("A"), B("B"), a("a"), b("b"), c("c");
- cout << indexed(A, i, j).symmetrize() << endl;
+ cout << ex(indexed(A, i, j)).symmetrize() << endl;
// -> 1/2*A.j.i+1/2*A.i.j
- cout << indexed(A, i, j, k).antisymmetrize(lst(i, j)) << endl;
+ cout << ex(indexed(A, i, j, k)).antisymmetrize(lst@{i, j@}) << endl;
// -> -1/2*A.j.i.k+1/2*A.i.j.k
- cout << lst(a, b, c).symmetrize_cyclic(lst(a, b, c)) << endl;
+ cout << ex(lst@{a, b, c@}).symmetrize_cyclic(lst@{a, b, c@}) << endl;
// -> 1/3*@{a,b,c@}+1/3*@{b,c,a@}+1/3*@{c,a,b@}
@}
@end example
@item @code{log(x)}
@tab natural logarithm
@cindex @code{log()}
+@item @code{eta(x,y)}
+@tab Eta function: @code{eta(x,y) = log(x*y) - log(x) - log(y)}
+@cindex @code{eta()}
@item @code{Li2(x)}
@tab dilogarithm
@cindex @code{Li2()}
is approached coming around the finite endpoint of the cut in a
counter clockwise direction.
+@c
+@subsection Expanding functions
+@cindex expand trancedent functions
+@cindex @code{expand_options::expand_transcendental}
+@cindex @code{expand_options::expand_function_args}
+GiNaC knows several expansion laws for trancedent functions, e.g.
+@tex
+$e^{a+b}=e^a e^b$,
+$|zw|=|z|\cdot |w|$
+@end tex
+@ifnottex
+@command{exp(a+b)=exp(a) exp(b), |zw|=|z| |w|}
+@end ifnottex
+or
+@tex
+$\log(c*d)=\log(c)+\log(d)$,
+@end tex
+@ifnottex
+@command{log(cd)=log(c)+log(d)}
+@end ifnottex
+(for positive
+@tex
+$c,\ d$
+@end tex
+@ifnottex
+@command{c, d}
+@end ifnottex
+). In order to use these rules you need to call @code{expand()} method
+with the option @code{expand_options::expand_transcendental}. Another
+relevant option is @code{expand_options::expand_function_args}. Their
+usage and interaction can be seen from the following example:
+@example
+@{
+ symbol x("x"), y("y");
+ ex e=exp(pow(x+y,2));
+ cout << e.expand() << endl;
+ // -> exp((x+y)^2)
+ cout << e.expand(expand_options::expand_transcendental) << endl;
+ // -> exp((x+y)^2)
+ cout << e.expand(expand_options::expand_function_args) << endl;
+ // -> exp(2*x*y+x^2+y^2)
+ cout << e.expand(expand_options::expand_function_args
+ | expand_options::expand_transcendental) << endl;
+ // -> exp(y^2)*exp(2*x*y)*exp(x^2)
+@}
+@end example
+If both flags are set (as in the last call), then GiNaC tries to get
+the maximal expansion. For example, for the exponent GiNaC firstly expands
+the argument and then the function. For the logarithm and absolute value,
+GiNaC uses the opposite order: firstly expands the function and then its
+argument. Of course, a user can fine-tune this behaviour by sequential
+calls of several @code{expand()} methods with desired flags.
+
@node Multiple polylogarithms, Complex expressions, Built-in functions, Methods and functions
@c node-name, next, previous, up
@subsection Multiple polylogarithms
will be interpreted as the sequence of signs for the corresponding indices
@code{m} or the sign of the imaginary part for the
corresponding arguments @code{a}, it must contain 1 or -1, e.g.
-@code{zeta(lst(3,4), lst(-1,1))} means
+@code{zeta(lst@{3,4@}, lst@{-1,1@})} means
@tex
$\zeta(\overline{3},4)$
@end tex
@command{zeta(\overline@{3@},4)}
@end ifnottex
and
-@code{G(lst(a,b), lst(-1,1), c)} means
+@code{G(lst@{a,b@}, lst@{-1,1@}, c)} means
@tex
$G(a-0\epsilon,b+0\epsilon;c)$.
@end tex
@end ifnottex
The definition of @code{H} allows indices to be 0, 1 or -1 (in expanded notation) or equally to
be any integer (in compact notation). With GiNaC expanded and compact notation can be mixed,
-e.g. @code{lst(0,0,-1,0,1,0,0)}, @code{lst(0,0,-1,2,0,0)} and @code{lst(-3,2,0,0)} are equivalent as
+e.g. @code{lst@{0,0,-1,0,1,0,0@}}, @code{lst@{0,0,-1,2,0,0@}} and @code{lst@{-3,2,0,0@}} are equivalent as
indices. The anonymous evaluator @code{eval()} tries to reduce the functions, if possible, to
the least-generic multiple polylogarithm. If all arguments are unit, it returns @code{zeta}.
Arguments equal to zero get considered, too. Riemann's zeta function @code{zeta} (with depth one)
table["x"] = x+log(y)+1;
parser reader(table);
ex e = reader("5*x^3 - x^2");
- // e = 5*(x+log(y)+1)^3 + (x+log(y)+1)^2
+ // e = 5*(x+log(y)+1)^3 - (x+log(y)+1)^2
@}
@end example
parser reader;
ex e = reader("2*x+sin(y)");
symtab table = reader.get_syms();
- symbol x = reader["x"];
- symbol y = reader["y"];
+ symbol x = ex_to<symbol>(table["x"]);
+ symbol y = ex_to<symbol>(table["y"]);
@}
@end example
@}
@end example
-With this parser, it's also easy to implement interactive GiNaC programs:
+With this parser, it's also easy to implement interactive GiNaC programs.
+When running the following program interactively, remember to send an
+EOF marker after the input, e.g. by pressing Ctrl-D on an empty line:
@example
#include <iostream>
@code{compile_ex} uses the shell script @code{ginac-excompiler} to start the C
compiler and produce the object files. This shell script comes with GiNaC and
will be installed together with GiNaC in the configured @code{$PREFIX/bin}
-directory.
+directory. You can also export additional compiler flags via the $CXXFLAGS
+variable:
+
+@example
+setenv("CXXFLAGS", "-O3 -fomit-frame-pointer -ffast-math", 1);
+compile_ex(...);
+@end example
@subsection Archiving
@cindex @code{archive} (class)
case the function has more than one parameter, and its main application
is for correct handling of the chain rule.
+Derivatives of some functions, for example @code{abs()} and
+@code{Order()}, could not be evaluated through the chain rule. In such
+cases the full derivative may be specified as shown for @code{Order()}:
+
+@example
+static ex Order_expl_derivative(const ex & arg, const symbol & s)
+@{
+ return Order(arg.diff(s));
+@}
+@end example
+
+That is, we need to supply a procedure, which returns the expression of
+derivative with respect to the variable @code{s} for the argument
+@code{arg}. This procedure need to be registered with the function
+through the option @code{expl_derivative_func} (see the next
+Subsection). In contrast, a partial derivative, e.g. as was defined for
+@code{cos()} above, needs to be registered through the option
+@code{derivative_func}.
+
An implementation of the series expansion is not needed for @code{cos()} as
it doesn't have any poles and GiNaC can do Taylor expansion by itself (as
long as it knows what the derivative of @code{cos()} is). @code{tan()}, on
eval_func(<C++ function>)
evalf_func(<C++ function>)
derivative_func(<C++ function>)
+expl_derivative_func(<C++ function>)
series_func(<C++ function>)
conjugate_func(<C++ function>)
@end example
These specify the C++ functions that implement symbolic evaluation,
-numeric evaluation, partial derivatives, and series expansion, respectively.
-They correspond to the GiNaC methods @code{eval()}, @code{evalf()},
-@code{diff()} and @code{series()}.
+numeric evaluation, partial derivatives, explicit derivative, and series
+expansion, respectively. They correspond to the GiNaC methods
+@code{eval()}, @code{evalf()}, @code{diff()} and @code{series()}.
The @code{eval_func()} function needs to use @code{.hold()} if no further
automatic evaluation is desired or possible.
multiple interfaces: Though real GiNaC programs have to be written in
some editor, then be compiled, linked and executed, there are more ways
to work with the GiNaC engine. Many people want to play with
-expressions interactively, as in traditional CASs. Currently, two such
-windows into GiNaC have been implemented and many more are possible: the
-tiny @command{ginsh} that is part of the distribution exposes GiNaC's
-types to a command line and second, as a more consistent approach, an
-interactive interface to the Cint C++ interpreter has been put together
-(called GiNaC-cint) that allows an interactive scripting interface
-consistent with the C++ language. It is available from the usual GiNaC
-FTP-site.
+expressions interactively, as in traditional CASs: The tiny
+@command{ginsh} that comes with the distribution exposes many, but not
+all, of GiNaC's types to a command line.
@item
seamless integration: it is somewhere between difficult and impossible
occasionally used other compilers and may be able to give you advice.}
GiNaC uses recent language features like explicit constructors, mutable
members, RTTI, @code{dynamic_cast}s and STL, so ANSI compliance is meant
-literally. Recent GCC versions starting at 2.95.3, although itself not
-yet ANSI compliant, support all needed features.
+literally.
@end itemize
@node Configure script options, Example package, Package tools, Package tools
@c node-name, next, previous, up
-@subsection Configuring a package that uses GiNaC
+@appendixsection Configuring a package that uses GiNaC
The directory where the GiNaC libraries are installed needs
to be found by your system's dynamic linkers (both compile- and run-time
@node Example package, Bibliography, Configure script options, Package tools
@c node-name, next, previous, up
-@subsection Example of a package using GiNaC
+@appendixsection Example of a package using GiNaC
The following shows how to build a simple package using automake
and the @samp{PKG_CHECK_MODULES} macro. The program used here is @file{simple.cpp}:
@itemize @minus{}
@item
-@cite{ISO/IEC 14882:1998: Programming Languages: C++}
+@cite{ISO/IEC 14882:2011: Programming Languages: C++}
@item
@cite{CLN: A Class Library for Numbers}, @email{haible@@ilog.fr, Bruno Haible}