@include version.texi
+@dircategory Mathematics
@direntry
* ginac: (ginac). C++ library for symbolic computation.
@end direntry
This is a tutorial that documents GiNaC @value{VERSION}, an open
framework for symbolic computation within the C++ programming language.
-Copyright (C) 1999-2007 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-2007 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-2007 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
warning levels. If omitted, it defaults to @option{-g
-O2}.@footnote{The @command{configure} script is itself generated from
the file @file{configure.ac}. It is only distributed in packaged
-releases of GiNaC. If you got the naked sources, e.g. from CVS, you
+releases of GiNaC. If you got the naked sources, e.g. from git, you
must generate @command{configure} along with the various
@file{Makefile.in} by using the @command{autoreconf} utility. This will
require a fair amount of support from your local toolchain, though.}
have a look at the most important classes in the class hierarchy and
some of the relations among the classes:
+@ifnotinfo
@image{classhierarchy}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
The abstract classes shown here (the ones without drop-shadow) are of no
interest for the user. They are used internally in order to avoid code
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
+is unique for each newly created @code{symbol} object. If 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
@cindex @code{possymbol()}
Furthermore, it is also possible to declare a symbol as positive. This will,
for instance, enable the automatic simplification of @code{abs(x)} into
-@code{x}. This is done by declaying the symbol as @code{possymbol x("x");}.
+@code{x}. This is done by declaring the symbol as @code{possymbol x("x");}.
@node Numbers, Constants, Symbols, Basic concepts
@end example
Note that the variable @code{answer} is constructed here as an integer
-by @code{numeric}'s copy constructor but in an intermediate step it
+by @code{numeric}'s copy constructor, but in an intermediate step it
holds a rational number represented as integer numerator and integer
denominator. When multiplied by 10, the denominator becomes unity and
the result is automatically converted to a pure integer again.
@tab @dots{}equal to zero
@item @code{.is_positive()}
@tab @dots{}not complex and greater than 0
+@item @code{.is_negative()}
+@tab @dots{}not complex and smaller than 0
@item @code{.is_integer()}
@tab @dots{}a (non-complex) integer
@item @code{.is_pos_integer()}
@end multitable
@end cartouche
+@page
+
@subsection Numeric functions
The following functions can be applied to @code{numeric} objects and will be
@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)]})
+@tab modulus in symmetric representation (in the range @code{[-iquo(abs(b), 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)
The predefined known constants are:
@cartouche
-@multitable @columnfractions .14 .30 .56
+@multitable @columnfractions .14 .32 .54
@item @strong{Name} @tab @strong{Common Name} @tab @strong{Numerical Value (to 35 digits)}
@item @code{Pi}
@tab Archimedes' constant
evaluation, is also available as
@example
ex adaptivesimpson(const ex & x, const ex & a, const ex & b, const ex & f,
-const ex & error)
+ const ex & error)
@end example
This function will throw an exception if the maximum depth is exceeded. The
last parameter of the function is optional and defaults to the
anything useful with it.
@cindex @code{get_value()}
-@cindex @code{get_dimension()}
+@cindex @code{get_dim()}
The methods
@example
ex idx::get_value();
-ex idx::get_dimension();
+ex idx::get_dim();
@end example
return the value and dimension of an @code{idx} object. If you have an index
that performs some more expensive operations:
-@itemize
+@itemize @bullet
@item it checks the consistency of free indices in sums in the same way
@code{get_free_indices()} does
@item it tries to give dummy indices that appear in different terms of a sum
obtained with the two member functions
@example
-unsigned ex::return_type() const;
-unsigned ex::return_type_tinfo() const;
+unsigned ex::return_type() const;
+return_type_t ex::return_type_tinfo() const;
@end example
The @code{return_type()} function returns one of three values (defined in
the header file @file{flags.h}), corresponding to three categories of
expressions in GiNaC:
-@itemize
+@itemize @bullet
@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
@code{noncommutative_composite} expressions.
@end itemize
-The value returned by the @code{return_type_tinfo()} method is valid only
-when the return type of the expression is @code{noncommutative}. It is a
-value that is unique to the class of the object and usually one of the
-constants in @file{tinfos.h}, or derived therefrom.
+The @code{return_type_tinfo()} method returns an object of type
+@code{return_type_t} that contains information about the type of the expression
+and, if given, its representation label (see section on dirac gamma matrices for
+more details). The objects of type @code{return_type_t} can be tested for
+equality to test whether two expressions belong to the same category and
+therefore may not commute.
Here are a couple of examples:
@cartouche
-@multitable @columnfractions 0.33 0.33 0.34
-@item @strong{Expression} @tab @strong{@code{return_type()}} @tab @strong{@code{return_type_tinfo()}}
-@item @code{42} @tab @code{commutative} @tab -
-@item @code{2*x-y} @tab @code{commutative} @tab -
-@item @code{dirac_ONE()} @tab @code{noncommutative} @tab @code{TINFO_clifford}
-@item @code{dirac_gamma(mu)*dirac_gamma(nu)} @tab @code{noncommutative} @tab @code{TINFO_clifford}
-@item @code{2*color_T(a)} @tab @code{noncommutative} @tab @code{TINFO_color}
-@item @code{dirac_ONE()*color_T(a)} @tab @code{noncommutative_composite} @tab -
+@multitable @columnfractions .6 .4
+@item @strong{Expression} @tab @strong{@code{return_type()}}
+@item @code{42} @tab @code{commutative}
+@item @code{2*x-y} @tab @code{commutative}
+@item @code{dirac_ONE()} @tab @code{noncommutative}
+@item @code{dirac_gamma(mu)*dirac_gamma(nu)} @tab @code{noncommutative}
+@item @code{2*color_T(a)} @tab @code{noncommutative}
+@item @code{dirac_ONE()*color_T(a)} @tab @code{noncommutative_composite}
@end multitable
@end cartouche
-Note: the @code{return_type_tinfo()} of Clifford objects is only equal to
-@code{TINFO_clifford} for objects with a representation label of zero.
-Other representation labels yield a different @code{return_type_tinfo()},
-but it's the same for any two objects with the same label. This is also true
-for color objects.
-
A last note: With the exception of matrices, positive integer powers of
non-commutative objects are automatically expanded in GiNaC. For example,
@code{pow(a*b, 2)} becomes @samp{a*b*a*b} if @samp{a} and @samp{b} are
functional is not cyclic in
@tex $D \ne 4$
@end tex
+@ifnottex
+@math{D != 4}
+@end ifnottex
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}.
+@samp{gamma5} scheme is described in greater detail in the article
+@cite{The Role of gamma5 in Dimensional Regularization} (@ref{Bibliography}).
The value of the trace itself is also usually different in 4 and in
@tex $D \ne 4$
@end tex
+@ifnottex
+@math{D != 4}
+@end ifnottex
dimensions:
@example
@subsubsection A generic Clifford algebra
A generic Clifford algebra, i.e. a
-@tex
-$2^n$
+@tex $2^n$
@end tex
+@ifnottex
+2^n
+@end ifnottex
dimensional algebra with
generators
@tex $e_k$
@end tex
+@ifnottex
+e_k
+@end ifnottex
satisfying the identities
@tex
-$e_i e_j + e_j e_i = M(i, j) + M(j, i) $
+$e_i e_j + e_j e_i = M(i, j) + M(j, i)$
@end tex
@ifnottex
e~i e~j + e~j e~i = M(i, j) + M(j, i)
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.
with @samp{e.k}
directly supplied in the second form of the procedure. In the first form
the Clifford unit @samp{e.k} is generated by the call of
-@code{clifford_unit(mu, metr, rl)}. The previous code may be rewritten
-with the help of @code{lst_to_clifford()} as follows
+@code{clifford_unit(mu, metr, rl)}.
+@cindex pseudo-vector
+If the number of components supplied
+by @code{v} exceeds the dimensionality of the Clifford unit @code{e} by
+1 then function @code{lst_to_clifford()} uses the following
+pseudo-vector representation:
+@tex
+$v^0 {\bf 1} + v^1 e_0 + v^2 e_1 + ... + v^{n+1} e_n$
+@end tex
+@ifnottex
+@samp{v~0 ONE + v~1 e.0 + v~2 e.1 + ... + v~[n+1] e.n}
+@end ifnottex
+
+The previous code may be rewritten with the help of @code{lst_to_clifford()} as follows
@example
@{
@ifnottex
@samp{v = (v~0, v~1, ..., v~n)}
@end ifnottex
-such that
+such that the expression is either vector
@tex
$e = v^0 c_0 + v^1 c_1 + ... + v^n c_n$
@end tex
@ifnottex
@samp{e = v~0 c.0 + v~1 c.1 + ... + v~n c.n}
@end ifnottex
-with respect to the given Clifford units @code{c} and with none of the
-@samp{v~k} containing Clifford units @code{c} (of course, this
+or pseudo-vector
+@tex
+$v^0 {\bf 1} + v^1 e_0 + v^2 e_1 + ... + v^{n+1} e_n$
+@end tex
+@ifnottex
+@samp{v~0 ONE + v~1 e.0 + v~2 e.1 + ... + v~[n+1] e.n}
+@end ifnottex
+with respect to the given Clifford units @code{c}. Here none of the
+@samp{v~k} should contain Clifford units @code{c} (of course, this
may be impossible). This function can use an @code{algebraic} method
-(default) or a symbolic one. With the @code{algebraic} method the @samp{v~k} are calculated as
+(default) or a symbolic one. With the @code{algebraic} method the
+@samp{v~k} are calculated as
@tex
$(e c_k + c_k e)/c_k^2$. If $c_k^2$
@end tex
@code{\clifford[1]@{e@}^@{@{\nu@}@}}, where @code{1} is the
@code{representation_label} and @code{\nu} is the index of the
corresponding unit. This provides a flexible typesetting with a suitable
-defintion of the @code{\clifford} command. For example, the definition
+definition of the @code{\clifford} command. For example, the definition
@example
\newcommand@{\clifford@}[1][]@{@}
@end example
bool is_exactly_a<T>(const ex & e);
bool ex::info(unsigned flag);
unsigned ex::return_type() const;
-unsigned ex::return_type_tinfo() const;
+return_type_t ex::return_type_tinfo() const;
@end example
When the test made by @code{is_a<T>()} returns true, it is safe to call
@{
symbol x("x"), y("y");
- ex e1 = 2*x^2-4*x+3;
+ ex e1 = 2*x*x-4*x+3;
cout << "e1(7) = " << e1.subs(x == 7) << endl;
// -> 73
large @code{subs()} operations significantly faster if you are not using
patterns. The second option, @code{subs_options::algebraic} enables
algebraic substitutions in products and powers.
-@ref{Pattern matching and advanced substitutions}, for more information
+@xref{Pattern matching and advanced substitutions}, for more information
about patterns and algebraic substitutions. The third option,
@code{subs_options::no_index_renaming} disables the feature that dummy
-indices are renamed if the subsitution could give a result in which a
+indices are renamed if the substitution could give a result in which a
dummy index occurs more than two times. This is sometimes necessary if
you want to use @code{subs()} to rename your dummy indices.
Notes:
-@itemize
+@itemize @bullet
@item Wildcards behave like symbols and are subject to the same algebraic
rules. E.g., @samp{$0+2*$0} is automatically transformed to @samp{3*$0}.
@item As shown in the last example, to use wildcards for indices you have to
@example
bool ex::match(const ex & pattern);
-bool ex::match(const ex & pattern, lst & repls);
+bool ex::match(const ex & pattern, exmap& repls);
@end example
This function returns @code{true} when the expression matches the pattern
and @code{false} if it doesn't. If used in the second form, the actual
-subexpressions matched by the wildcards get returned in the @code{repls}
-object as a list of relations of the form @samp{wildcard == expression}.
-If @code{match()} returns false, the state of @code{repls} is undefined.
-For reproducible results, the list should be empty when passed to
-@code{match()}, but it is also possible to find similarities in multiple
-expressions by passing in the result of a previous match.
+subexpressions matched by the wildcards get returned in the associative
+array @code{repls} with @samp{wildcard} as a key. If @code{match()}
+returns false, @code{repls} remains unmodified.
The matching algorithm works as follows:
> match((a+b)*(a+c),($1+b)*($1+c));
@{$1==a@}
> match((a+b)*(a+c),(a+$1)*(a+$2));
-@{$1==c,$2==b@}
+@{$1==b,$2==c@}
(Unpredictable. The result might also be [$1==c,$2==b].)
> match((a+b)*(a+c),($1+$2)*($1+$3));
(The result is undefined. Due to the sequential nature of the algorithm
The method
@example
-bool ex::find(const ex & pattern, lst & found);
+bool ex::find(const ex & pattern, exset& found);
@end example
works a bit like @code{has()} but it doesn't stop upon finding the first
Both @code{has()} and @code{subs()} take an optional argument to pass them
extra options. This section describes what happens if you give the former
the option @code{has_options::algebraic} or the latter
-@code{subs:options::algebraic}. In that case the matching condition for
+@code{subs_options::algebraic}. In that case the matching condition for
powers and multiplications is changed in such a way that they become
more intuitive. Intuition says that @code{x*y} is a part of @code{x*y*z}.
If you use these options you will find that
@code{(x^5*y^2*z).subs(x^2*y^2==c, subs_options::algebraic)} will return
@code{x*c^2*z}. This also works with negative powers:
@code{(x^(-3)*y^(-2)*z).subs(1/(x*y)==c, subs_options::algebraic)} will
-return @code{x^(-1)*c^2*z}. Note that this only works for multiplications
+return @code{x^(-1)*c^2*z}.
+
+@strong{Please notice:} this only works for multiplications
and not for locating @code{x+y} within @code{x+y+z}.
@cindex factorization
@cindex @code{sqrfree()}
-GiNaC still lacks proper factorization support. Some form of
-factorization is, however, easily implemented by noting that factors
-appearing in a polynomial with power two or more also appear in the
-derivative and hence can easily be found by computing the GCD of the
-original polynomial and its derivatives. Any decent system has an
-interface for this so called square-free factorization. So we provide
-one, too:
+Square-free decomposition is available in GiNaC:
@example
ex sqrfree(const ex & a, const lst & l = lst());
@end example
Note also, how factors with the same exponents are not fully factorized
with this method.
+@subsection Polynomial factorization
+@cindex factorization
+@cindex polynomial factorization
+@cindex @code{factor()}
+
+Polynomials can also be fully factored with a call to the function
+@example
+ex factor(const ex & a, unsigned int options = 0);
+@end example
+The factorization works for univariate and multivariate polynomials with
+rational coefficients. The following code snippet shows its capabilities:
+@example
+ ...
+ cout << factor(pow(x,2)-1) << endl;
+ // -> (1+x)*(-1+x)
+ cout << factor(expand((x-y*z)*(x-pow(y,2)-pow(z,3))*(x+y+z))) << endl;
+ // -> (y+z+x)*(y*z-x)*(y^2-x+z^3)
+ cout << factor(pow(x,2)-1+sin(pow(x,2)-1)) << endl;
+ // -> -1+sin(-1+x^2)+x^2
+ ...
+@end example
+The results are as expected except for the last one where no factorization
+seems to have been done. This is due to the default option
+@command{factor_options::polynomial} (equals zero) to @command{factor()}, which
+tells GiNaC to try a factorization only if the expression is a valid polynomial.
+In the shown example this is not the case, because one term is a function.
+
+There exists a second option @command{factor_options::all}, which tells GiNaC to
+ignore non-polynomial parts of an expression and also to look inside function
+arguments. With this option the example gives:
+@example
+ ...
+ cout << factor(pow(x,2)-1+sin(pow(x,2)-1), factor_options::all)
+ << endl;
+ // -> (-1+x)*(1+x)+sin((-1+x)*(1+x))
+ ...
+@end example
+GiNaC's factorization functions cannot handle algebraic extensions. Therefore
+the following example does not factor:
+@example
+ ...
+ cout << factor(pow(x,2)-2) << endl;
+ // -> -2+x^2 and not (x-sqrt(2))*(x+sqrt(2))
+ ...
+@end example
+Factorization is useful in many applications. A lot of algorithms in computer
+algebra depend on the ability to factor a polynomial. Of course, factorization
+can also be used to simplify expressions, but it is costly and applying it to
+complicated expressions (high degrees or many terms) may consume far too much
+time. So usually, looking for a GCD at strategic points in a calculation is the
+cheaper and more appropriate alternative.
@node Rational expressions, Symbolic differentiation, Polynomial arithmetic, Methods and functions
@c node-name, next, previous, up
@tex
$\pi$
@end tex
+@ifnottex
+@math{Pi}
+@end ifnottex
(for which there already exists the built-in constant @code{Pi})
using John Machin's amazing formula
@tex
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
+@page
+
@node Built-in functions, Multiple polylogarithms, Symmetrization, Methods and functions
@c node-name, next, previous, up
@section Predefined mathematical functions
@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()}
@end cartouche
@cindex branch cut
-For functions that have a branch cut in the complex plane GiNaC follows
-the conventions for C++ as defined in the ANSI standard as far as
-possible. In particular: the natural logarithm (@code{log}) and the
-square root (@code{sqrt}) both have their branch cuts running along the
-negative real axis where the points on the axis itself belong to the
-upper part (i.e. continuous with quadrant II). The inverse
-trigonometric and hyperbolic functions are not defined for complex
-arguments by the C++ standard, however. In GiNaC we follow the
-conventions used by CLN, which in turn follow the carefully designed
-definitions in the Common Lisp standard. It should be noted that this
-convention is identical to the one used by the C99 standard and by most
-serious CAS. It is to be expected that future revisions of the C++
-standard incorporate these functions in the complex domain in a manner
-compatible with C99.
+For functions that have a branch cut in the complex plane, GiNaC
+follows the conventions of C/C++ for systems that do not support a
+signed zero. In particular: the natural logarithm (@code{log}) and
+the square root (@code{sqrt}) both have their branch cuts running
+along the negative real axis. The @code{asin}, @code{acos}, and
+@code{atanh} functions all have two branch cuts starting at +/-1 and
+running away towards infinity along the real axis. The @code{atan} and
+@code{asinh} functions have two branch cuts starting at +/-i and
+running away towards infinity along the imaginary axis. The
+@code{acosh} function has one branch cut starting at +1 and running
+towards -infinity. These functions are continuous as the branch cut
+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
@tex
$\zeta(m_1,m_2,\ldots,m_k)$.
@end tex
+@ifnottex
+@command{\mbox@{Li@}_@{m_1,m_2,...,m_k@}(x_1,x_2,...,x_k)},
+@command{\mbox@{S@}_@{n,p@}(x)},
+@command{\mbox@{H@}_@{m_1,m_2,...,m_k@}(x)} and
+@command{\zeta(m_1,m_2,...,m_k)} (with the dots replaced by actual parameters).
+@end ifnottex
If @code{zeta} is an alternating zeta sum, i.e. @code{zeta(m,s)}, the indices with negative sign
are printed with a line above, e.g.
@tex
$\zeta(5,\overline{2})$.
@end tex
+@ifnottex
+@command{\zeta(5,\overline@{2@})}.
+@end ifnottex
The order of indices and arguments in the GiNaC @code{lst}s and in the output is the same.
Definitions and analytical as well as numerical properties of multiple polylogarithms
@tex
$\zeta(1,2)$ evaluates to infinity.
@end tex
-So in comparison to the referenced publications the order of indices and arguments for @code{Li}
-is reversed.
+@ifnottex
+@code{Li_@{m_1,m_2,m_3@}(x,1,1) = H_@{m_1,m_2,m_3@}(x)} and
+@code{Li_@{2,1@}(1,1) = zeta(2,1) = zeta(3)}, but
+@code{zeta(1,2)} evaluates to infinity.
+@end ifnottex
+So in comparison to the older ones of the referenced publications the order of
+indices and arguments for @code{Li} is reversed.
The functions only evaluate if the indices are integers greater than zero, except for the indices
@code{s} in @code{zeta} and @code{G} as well as @code{m} in @code{H}. Since @code{s}
@tex
$\zeta(\overline{3},4)$
@end tex
+@ifnottex
+@command{zeta(\overline@{3@},4)}
+@end ifnottex
and
@code{G(lst(a,b), lst(-1,1), c)} means
@tex
$G(a-0\epsilon,b+0\epsilon;c)$.
@end tex
+@ifnottex
+@command{G(a-0\epsilon,b+0\epsilon;c)}.
+@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
@tex
$\zeta(1)$.
@end tex
+@ifnottex
+@command{zeta(1)}.
+@end ifnottex
In long expressions this helps a lot with debugging, because you can easily spot
the divergencies. But on the other hand, you have to make sure for yourself, that no illegal
cancellations of divergencies happen.
that return respectively the complex conjugate, the real part and the
imaginary part of an expression. Complex conjugation works as expected
-for all built-in functinos and objects. Taking real and imaginary
+for all built-in functions and objects. Taking real and imaginary
parts has not yet been implemented for all built-in functions. In cases where
it is not known how to conjugate or take a real/imaginary part one
of the functions @code{conjugate}, @code{real_part} or @code{imag_part}
@}
@end example
-If you declare your own GiNaC functions, then they will conjugate themselves
-by conjugating their arguments. This is the default strategy. If you want to
-change this behavior, you have to supply a specialized conjugation method
-for your function (see @ref{Symbolic functions} and the GiNaC source-code
-for @code{abs} as an example). Also, specialized methods can be provided
-to take real and imaginary parts of user-defined functions.
+If you declare your own GiNaC functions and you want to conjugate them, you
+will have to supply a specialized conjugation method for them (see
+@ref{Symbolic functions} and the GiNaC source-code for @code{abs} as an
+example). GiNaC does not automatically conjugate user-supplied functions
+by conjugating their arguments because this would be incorrect on branch
+cuts. Also, specialized methods can be provided to take real and imaginary
+parts of user-defined functions.
@node Solving linear systems of equations, Input/output, Complex expressions, Methods and functions
@c node-name, next, previous, up
@code{y} you defined in your program and there is no way to specify the
desired symbols to the @code{>>} stream input operator.
-Instead, GiNaC lets you construct an expression from a string, specifying the
-list of symbols to be used:
+Instead, GiNaC lets you read an expression from a stream or a string,
+specifying the mapping between the input strings and symbols to be used:
@example
@{
- symbol x("x"), y("y");
- ex e("2*x+sin(y)", lst(x, y));
+ symbol x, y;
+ symtab table;
+ table["x"] = x;
+ table["y"] = y;
+ parser reader(table);
+ ex e = reader("2*x+sin(y)");
@}
@end example
The input syntax is the same as that used by @command{ginsh} and the stream
-output operator @code{<<}. The symbols in the string are matched by name to
-the symbols in the list and if GiNaC encounters a symbol not specified in
-the list it will throw an exception.
+output operator @code{<<}. Matching between the input strings and expressions
+is given by @samp{table}. The @samp{table} in this example instructs GiNaC
+to substitute any input substring ``x'' with symbol @code{x}. Likewise,
+the substring ``y'' will be replaced with symbol @code{y}. It's also possible
+to map input (sub)strings to arbitrary expressions:
-With this constructor, it's also easy to implement interactive GiNaC programs:
+@example
+@{
+ symbol x, y;
+ symtab table;
+ 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
+@}
+@end example
+
+If no mapping is specified for a particular string GiNaC will create a symbol
+with corresponding name. Later on you can obtain all parser generated symbols
+with @code{get_syms()} method:
+
+@example
+@{
+ parser reader;
+ ex e = reader("2*x+sin(y)");
+ symtab table = reader.get_syms();
+ symbol x = ex_to<symbol>(table["x"]);
+ symbol y = ex_to<symbol>(table["y"]);
+@}
+@end example
+
+Sometimes you might want to prevent GiNaC from inserting these extra symbols
+(for example, you want treat an unexpected string in the input as an error).
+
+@example
+@{
+ symtab table;
+ table["x"] = symbol();
+ parser reader(table);
+ parser.strict = true;
+ ex e;
+ try @{
+ e = reader("2*x+sin(y)");
+ @} catch (parse_error& err) @{
+ cerr << err.what() << endl;
+ // prints "unknown symbol "y" in the input"
+ @}
+@}
+@end example
+
+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>
int main()
@{
- symbol x("x");
- string s;
-
- cout << "Enter an expression containing 'x': ";
- getline(cin, s);
-
- try @{
- ex e(s, lst(x));
- cout << "The derivative of " << e << " with respect to x is ";
- cout << e.diff(x) << ".\n";
- @} catch (exception &p) @{
- cerr << p.what() << endl;
- @}
+ cout << "Enter an expression containing 'x': " << flush;
+ parser reader;
+
+ try @{
+ ex e = reader(cin);
+ symtab table = reader.get_syms();
+ symbol x = table.find("x") != table.end() ?
+ ex_to<symbol>(table["x"]) : symbol("x");
+ cout << "The derivative of " << e << " with respect to x is ";
+ cout << e.diff(x) << "." << endl;
+ @} catch (exception &p) @{
+ cerr << p.what() << endl;
+ @}
@}
@end example
@cindex Monte Carlo integration
@code{FUNCP_2P} allows for two variables in the expression. @code{FUNCP_CUBA} is
the correct type to be used with the CUBA library
-(@uref{http://www.feynarts/cuba}) for numerical integrations. The details for the
+(@uref{http://www.feynarts.de/cuba}) for numerical integrations. The details for the
parameters of @code{FUNCP_CUBA} are explained in the CUBA manual.
@cindex compile_ex
@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.
function before calling the @code{evalf_func()}.
@example
-set_return_type(unsigned return_type, unsigned return_type_tinfo)
+set_return_type(unsigned return_type, const return_type_t * return_type_tinfo)
@end example
This allows you to explicitly specify the commutation properties of the
function (@xref{Non-commutative objects}, for an explanation of
-(non)commutativity in GiNaC). For example, you can use
-@code{set_return_type(return_types::noncommutative, TINFO_matrix)} to make
-GiNaC treat your function like a matrix. By default, functions inherit the
-commutation properties of their first argument.
+(non)commutativity in GiNaC). For example, with an object of type
+@code{return_type_t} created like
+
+@example
+return_type_t my_type = make_return_type_t<matrix>();
+@end example
+
+you can use @code{set_return_type(return_types::noncommutative, &my_type)} to
+make GiNaC treat your function like a matrix. By default, functions inherit the
+commutation properties of their first argument. The utilized template function
+@code{make_return_type_t<>()}
+
+@example
+template<typename T> inline return_type_t make_return_type_t(const unsigned rl = 0)
+@end example
+
+can also be called with an argument specifying the representation label of the
+non-commutative function (see section on dirac gamma matrices for more
+details).
@example
set_symmetry(const symmetry & s)
you enough information so you can consult the source to GiNaC's predefined
classes if you want to implement something more complicated.
-@subsection GiNaC's run-time type information system
+@subsection Hierarchy of algebraic classes.
@cindex hierarchy of classes
-@cindex RTTI
All algebraic classes (that is, all classes that can appear in expressions)
in GiNaC are direct or indirect subclasses of the class @code{basic}. So a
-@code{basic *} (which is essentially what an @code{ex} is) represents a
-generic pointer to an algebraic class. Occasionally it is necessary to find
-out what the class of an object pointed to by a @code{basic *} really is.
-Also, for the unarchiving of expressions it must be possible to find the
-@code{unarchive()} function of a class given the class name (as a string). A
-system that provides this kind of information is called a run-time type
-information (RTTI) system. The C++ language provides such a thing (see the
-standard header file @file{<typeinfo>}) but for efficiency reasons GiNaC
-implements its own, simpler RTTI.
-
-The RTTI in GiNaC is based on two mechanisms:
-
+@code{basic *} represents a generic pointer to an algebraic class. Working
+with such pointers directly is cumbersome (think of memory management), hence
+GiNaC wraps them into @code{ex} (@pxref{Expressions are reference counted}).
+To make such wrapping possible every algebraic class has to implement several
+methods. Visitors (@pxref{Visitors and tree traversal}), printing, and
+(un)archiving (@pxref{Input/output}) require helper methods too. But don't
+worry, most of the work is simplified by the following macros (defined
+in @file{registrar.h}):
@itemize @bullet
+@item @code{GINAC_DECLARE_REGISTERED_CLASS}
+@item @code{GINAC_IMPLEMENT_REGISTERED_CLASS}
+@item @code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT}
+@end itemize
-@item
-The @code{basic} class declares a member variable @code{tinfo_key} which
-holds a variable of @code{tinfo_t} type (which is actually just
-@code{const void*}) that identifies the object's class.
-
-@item
-By means of some clever tricks with static members, GiNaC maintains a list
-of information for all classes derived from @code{basic}. The information
-available includes the class names, the @code{tinfo_key}s, and pointers
-to the unarchiving functions. This class registry is defined in the
-@file{registrar.h} header file.
+The @code{GINAC_DECLARE_REGISTERED_CLASS} macro inserts declarations
+required for memory management, visitors, printing, and (un)archiving.
+It takes the name of the class and its direct superclass as arguments.
+The @code{GINAC_DECLARE_REGISTERED_CLASS} should be the first line after
+the opening brace of the class definition.
-@end itemize
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} takes the same arguments as
+@code{GINAC_DECLARE_REGISTERED_CLASS}. It initializes certain static
+members of a class so that printing and (un)archiving works. The
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} may appear anywhere else in
+the source (at global scope, of course, not inside a function).
-The disadvantage of this proprietary RTTI implementation is that there's
-a little more to do when implementing new classes (C++'s RTTI works more
-or less automatically) but don't worry, most of the work is simplified by
-macros.
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT} is a variant of
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS}. It allows specifying additional
+options, such as custom printing functions.
@subsection A minimalistic example
placing character strings in algebraic expressions (this is not very useful,
but it's just an example). This class will be a direct subclass of
@code{basic}. You can use this sample implementation as a starting point
-for your own classes.
+for your own classes @footnote{The self-contained source for this example is
+included in GiNaC, see the @file{doc/examples/mystring.cpp} file.}.
The code snippets given here assume that you have included some header files
as follows:
Now we can write down the class declaration. The class stores a C++
@code{string} and the user shall be able to construct a @code{mystring}
-object from a C or C++ string:
+object from a string:
@example
class mystring : public basic
GINAC_DECLARE_REGISTERED_CLASS(mystring, basic)
public:
- mystring(const string &s);
- mystring(const char *s);
+ mystring(const string & s);
private:
string str;
GINAC_IMPLEMENT_REGISTERED_CLASS(mystring, basic)
@end example
-The @code{GINAC_DECLARE_REGISTERED_CLASS} and @code{GINAC_IMPLEMENT_REGISTERED_CLASS}
-macros are defined in @file{registrar.h}. They take the name of the class
-and its direct superclass as arguments and insert all required declarations
-for the RTTI system. The @code{GINAC_DECLARE_REGISTERED_CLASS} should be
-the first line after the opening brace of the class definition. The
-@code{GINAC_IMPLEMENT_REGISTERED_CLASS} may appear anywhere else in the
-source (at global scope, of course, not inside a function).
-
-@code{GINAC_DECLARE_REGISTERED_CLASS} contains, among other things the
-declarations of the default constructor and a couple of other functions that
-are required. It also defines a type @code{inherited} which refers to the
-superclass so you don't have to modify your code every time you shuffle around
-the class hierarchy. @code{GINAC_IMPLEMENT_REGISTERED_CLASS} registers the
-class with the GiNaC RTTI (there is also a
-@code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT} which allows specifying additional
-options for the class, and which we will be using instead in a few minutes).
-
-Now there are seven member functions we have to implement to get a working
+The @code{GINAC_DECLARE_REGISTERED_CLASS} macro insert declarations required
+for memory management, visitors, printing, and (un)archiving.
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} initializes certain static members
+of a class so that printing and (un)archiving works.
+
+Now there are three member functions we have to implement to get a working
class:
@itemize
@item
@code{mystring()}, the default constructor.
-@item
-@code{void archive(archive_node &n)}, the archiving function. This stores all
-information needed to reconstruct an object of this class inside an
-@code{archive_node}.
-
-@item
-@code{mystring(const archive_node &n, lst &sym_lst)}, the unarchiving
-constructor. This constructs an instance of the class from the information
-found in an @code{archive_node}.
-
-@item
-@code{ex unarchive(const archive_node &n, lst &sym_lst)}, the static
-unarchiving function. It constructs a new instance by calling the unarchiving
-constructor.
-
@item
@cindex @code{compare_same_type()}
-@code{int compare_same_type(const basic &other)}, which is used internally
+@code{int compare_same_type(const basic & other)}, which is used internally
by GiNaC to establish a canonical sort order for terms. It returns 0, +1 or
-1, depending on the relative order of this object and the @code{other}
object. If it returns 0, the objects are considered equal.
defined.
@item
-And, of course, @code{mystring(const string &s)} and @code{mystring(const char *s)}
-which are the two constructors we declared.
+And, of course, @code{mystring(const string& s)} which is the constructor
+we declared.
@end itemize
Let's proceed step-by-step. The default constructor looks like this:
@example
-mystring::mystring() : inherited(&mystring::tinfo_static) @{@}
+mystring::mystring() @{ @}
@end example
-The golden rule is that in all constructors you have to set the
-@code{tinfo_key} member to the @code{&your_class_name::tinfo_static}
-@footnote{Each GiNaC class has a static member called tinfo_static.
-This member is declared by the GINAC_DECLARE_REGISTERED_CLASS macros
-and defined by the GINAC_IMPLEMENT_REGISTERED_CLASS macros.}. Otherwise
-it will be set by the constructor of the superclass and all hell will break
-loose in the RTTI. For your convenience, the @code{basic} class provides
-a constructor that takes a @code{tinfo_key} value, which we are using here
-(remember that in our case @code{inherited == basic}). If the superclass
-didn't have such a constructor, we would have to set the @code{tinfo_key}
-to the right value manually.
-
In the default constructor you should set all other member variables to
reasonable default values (we don't need that here since our @code{str}
member gets set to an empty string automatically).
-Next are the three functions for archiving. You have to implement them even
-if you don't plan to use archives, but the minimum required implementation
-is really simple. First, the archiving function:
-
-@example
-void mystring::archive(archive_node &n) const
-@{
- inherited::archive(n);
- n.add_string("string", str);
-@}
-@end example
-
-The only thing that is really required is calling the @code{archive()}
-function of the superclass. Optionally, you can store all information you
-deem necessary for representing the object into the passed
-@code{archive_node}. We are just storing our string here. For more
-information on how the archiving works, consult the @file{archive.h} header
-file.
-
-The unarchiving constructor is basically the inverse of the archiving
-function:
-
-@example
-mystring::mystring(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst)
-@{
- n.find_string("string", str);
-@}
-@end example
-
-If you don't need archiving, just leave this function empty (but you must
-invoke the unarchiving constructor of the superclass). Note that we don't
-have to set the @code{tinfo_key} here because it is done automatically
-by the unarchiving constructor of the @code{basic} class.
-
-Finally, the unarchiving function:
-
-@example
-ex mystring::unarchive(const archive_node &n, lst &sym_lst)
-@{
- return (new mystring(n, sym_lst))->setflag(status_flags::dynallocated);
-@}
-@end example
-
-You don't have to understand how exactly this works. Just copy these
-four lines into your code literally (replacing the class name, of
-course). It calls the unarchiving constructor of the class and unless
-you are doing something very special (like matching @code{archive_node}s
-to global objects) you don't need a different implementation. For those
-who are interested: setting the @code{dynallocated} flag puts the object
-under the control of GiNaC's garbage collection. It will get deleted
-automatically once it is no longer referenced.
-
Our @code{compare_same_type()} function uses a provided function to compare
the string members:
@example
-int mystring::compare_same_type(const basic &other) const
+int mystring::compare_same_type(const basic & other) const
@{
const mystring &o = static_cast<const mystring &>(other);
int cmpval = str.compare(o.str);
are considered equal (in the sense that @math{A-B=0}), so you should compare
all relevant member variables.
-Now the only thing missing is our two new constructors:
+Now the only thing missing is our constructor:
@example
-mystring::mystring(const string &s) : inherited(&mystring::tinfo_static), str(s) @{@}
-mystring::mystring(const char *s) : inherited(&mystring::tinfo_static), str(s) @{@}
+mystring::mystring(const string& s) : str(s) @{ @}
@end example
-No surprises here. We set the @code{str} member from the argument and
-remember to pass the right @code{tinfo_key} to the @code{basic} constructor.
+No surprises here. We set the @code{str} member from the argument.
That's it! We now have a minimal working GiNaC class that can store
strings in algebraic expressions. Let's confirm that the RTTI works:
@{
...
protected:
- void do_print(const print_context &c, unsigned level = 0) const;
+ void do_print(const print_context & c, unsigned level = 0) const;
...
@};
-void mystring::do_print(const print_context &c, unsigned level) const
+void mystring::do_print(const print_context & c, unsigned level) const
@{
// print_context::s is a reference to an ostream
c.s << '\"' << str << '\"';
@cindex @code{is_equal_same_type()}
@example
unsigned calchash() const;
-bool is_equal_same_type(const basic &other) const;
+bool is_equal_same_type(const basic & other) const;
@end example
The @code{calchash()} method returns an @code{unsigned} hash value for the
@subsection Upgrading extension classes from older version of GiNaC
-If you got some extension classes for GiNaC 1.3.X some changes are
-necessary in order to make your code work with GiNaC 1.4.
-
-@itemize @bullet
-@item constructors which set @code{tinfo_key} such as
+GiNaC used to use a custom run time type information system (RTTI). It was
+removed from GiNaC. Thus, one needs to rewrite constructors which set
+@code{tinfo_key} (which does not exist any more). For example,
@example
-myclass::myclass() : inherited(TINFO_myclass) @{@}
+myclass::myclass() : inherited(&myclass::tinfo_static) @{@}
@end example
-need to be rewritten as
+needs to be rewritten as
@example
-myclass::myclass() : inherited(&myclass::tinfo_static) @{@}
+myclass::myclass() @{@}
@end example
-@item TINO_myclass is not necessary any more and can be removed.
-
-@end itemize
-
-
@node A comparison with other CAS, Advantages, Adding classes, Top
@c node-name, next, previous, up
@chapter A Comparison With Other CAS
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
advanced features: GiNaC cannot compete with a program like
@emph{Reduce} which exists for more than 30 years now or @emph{Maple}
which grows since 1981 by the work of dozens of programmers, with
-respect to mathematical features. Integration, factorization,
+respect to mathematical features. Integration,
non-trivial simplifications, limits etc. are missing in GiNaC (and are
not planned for the near future).
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
and exponent and some atomic leaves of symbols and numbers in this
fashion:
+@ifnotinfo
@image{repnaive}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
@cindex pair-wise representation
However, doing so results in a rather deeply nested tree which will
having a numeric exponent and a possibly complicated base, the tree
becomes much more flat:
+@ifnotinfo
@image{reppair}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
The number @code{3} above the symbol @code{d} shows that @code{mul}
objects are treated similarly where the coefficients are interpreted as
@math{2*d^3*(4*a+5*b-3)}:
@end ifnottex
+@ifnotinfo
@image{repreal}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
@cindex radical
This also allows for a better handling of numeric radicals, since
@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}