This is a tutorial that documents GiNaC @value{VERSION}, an open
framework for symbolic computation within the C++ programming language.
-Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2003 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-2002 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2003 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-2002 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2003 Johannes Gutenberg
University Mainz, Germany.
This program is free software; you can redistribute it and/or
@cindex container
@cindex atom
-To get an idea about what kinds of symbolic composits may be built we
+To get an idea about what kinds of symbolic composites may be built we
have a look at the most important classes in the class hierarchy and
some of the relations among the classes:
For storing numerical things, GiNaC uses Bruno Haible's library CLN.
The classes therein serve as foundation classes for GiNaC. CLN stands
for Class Library for Numbers or alternatively for Common Lisp Numbers.
-In order to find out more about CLN's internals the reader is refered to
+In order to find out more about CLN's internals, the reader is referred to
the documentation of that library. @inforef{Introduction, , cln}, for
more information. Suffice to say that it is by itself build on top of
another library, the GNU Multiple Precision library GMP, which is an
numeric trott("1.0841015122311136151E-2");
std::cout << two*p << std::endl; // floating point 6.283...
+ ...
+@end example
+
+@cindex @code{I}
+@cindex complex numbers
+The imaginary unit in GiNaC is a predefined @code{numeric} object with the
+name @code{I}:
+
+@example
+ ...
+ numeric z1 = 2-3*I; // exact complex number 2-3i
+ numeric z2 = 5.9+1.6*I; // complex floating point number
@}
@end example
-It may be tempting to construct numbers writing @code{numeric r(3/2)}.
+It may be tempting to construct fractions by writing @code{numeric r(3/2)}.
This would, however, call C's built-in operator @code{/} for integers
first and result in a numeric holding a plain integer 1. @strong{Never
use the operator @code{/} on integers} unless you know exactly what you
that in both cases you got a couple of extra digits. This is because
numbers are internally stored by CLN as chunks of binary digits in order
to match your machine's word size and to not waste precision. Thus, on
-architectures with differnt word size, the above output might even
+architectures with different word size, the above output might even
differ with regard to actually computed digits.
It should be clear that objects of class @code{numeric} should be used
There are a couple of ways to construct matrices, with or without preset
elements:
+@cindex @code{lst_to_matrix()}
+@cindex @code{diag_matrix()}
+@cindex @code{unit_matrix()}
+@cindex @code{symbolic_matrix()}
@example
matrix::matrix(unsigned r, unsigned c);
matrix::matrix(unsigned r, unsigned c, const lst & l);
ex lst_to_matrix(const lst & l);
ex diag_matrix(const lst & l);
+ex unit_matrix(unsigned x);
+ex unit_matrix(unsigned r, unsigned c);
+ex symbolic_matrix(unsigned r, unsigned c, const string & base_name);
+ex symbolic_matrix(unsigned r, unsigned c, const string & base_name, const string & tex_base_name);
@end example
The first two functions are @code{matrix} constructors which create a matrix
with @samp{r} rows and @samp{c} columns. The matrix elements can be
initialized from a (flat) list of expressions @samp{l}. Otherwise they are
all set to zero. The @code{lst_to_matrix()} function constructs a matrix
-from a list of lists, each list representing a matrix row. Finally,
-@code{diag_matrix()} constructs a diagonal matrix given the list of diagonal
-elements. Note that the last two functions return expressions, not matrix
-objects.
+from a list of lists, each list representing a matrix row. @code{diag_matrix()}
+constructs a diagonal matrix given the list of diagonal elements.
+@code{unit_matrix()} creates an @samp{x} by @samp{x} (or @samp{r} by @samp{c})
+unit matrix. And finally, @code{symbolic_matrix} constructs a matrix filled
+with newly generated symbols made of the specified base name and the
+position of each element in the matrix.
Matrix elements can be accessed and set using the parenthesis (function call)
operator:
the @code{op()} method. But C++-style subscripting with square brackets
@samp{[]} is not available.
-Here are a couple of examples that all construct the same 2x2 diagonal
-matrix:
+Here are a couple of examples of constructing matrices:
@example
@{
symbol a("a"), b("b");
- ex e;
matrix M(2, 2);
M(0, 0) = a;
M(1, 1) = b;
- e = M;
-
- e = matrix(2, 2, lst(a, 0, 0, b));
+ cout << M << endl;
+ // -> [[a,0],[0,b]]
- e = lst_to_matrix(lst(lst(a, 0), lst(0, b)));
+ cout << matrix(2, 2, lst(a, 0, 0, b)) << endl;
+ // -> [[a,0],[0,b]]
- e = diag_matrix(lst(a, b));
+ cout << lst_to_matrix(lst(lst(a, 0), lst(0, b))) << endl;
+ // -> [[a,0],[0,b]]
- cout << e << endl;
+ cout << diag_matrix(lst(a, b)) << endl;
// -> [[a,0],[0,b]]
+
+ cout << unit_matrix(3) << endl;
+ // -> [[1,0,0],[0,1,0],[0,0,1]]
+
+ cout << symbolic_matrix(2, 3, "x") << endl;
+ // -> [[x00,x01,x02],[x10,x11,x12]]
@}
@end example
The @code{matrix} class provides a couple of additional methods for
computing determinants, traces, and characteristic polynomials:
+@cindex @code{determinant()}
+@cindex @code{trace()}
+@cindex @code{charpoly()}
@example
ex matrix::determinant(unsigned algo = determinant_algo::automatic) const;
ex matrix::trace(void) const;
// -> 2*A.j.i
cout << indexed(B, sy_anti(), i, j)
+ indexed(B, sy_anti(), j, i) << endl;
- // -> -B.j.i
+ // -> 0
cout << indexed(B, sy_anti(), i, j, k)
- + indexed(B, sy_anti(), j, i, k) << endl;
+ - indexed(B, sy_anti(), j, k, i) << endl;
// -> 0
...
@end example
dummy nor free indices.
To be recognized as a dummy index pair, the two indices must be of the same
-class and dimension and their value must be the same single symbol (an index
-like @samp{2*n+1} is never a dummy index). If the indices are of class
+class and their value must be the same single symbol (an index like
+@samp{2*n+1} is never a dummy index). If the indices are of class
@code{varidx} they must also be of opposite variance; if they are of class
@code{spinidx} they must be both dotted or both undotted.
multiples of the unity element, even though it's customary to omit it.
E.g. instead of @code{dirac_gamma(mu)*(dirac_slash(q,4)+m)} you have to
write @code{dirac_gamma(mu)*(dirac_slash(q,4)+m*dirac_ONE())}. Otherwise,
-GiNaC may produce incorrect results.
+GiNaC will complain and/or produce incorrect results.
@cindex @code{dirac_gamma5()}
-There's a special element @samp{gamma5} that commutes with all other
-gammas and in 4 dimensions equals @samp{gamma~0 gamma~1 gamma~2 gamma~3},
-provided by
+There is a special element @samp{gamma5} that commutes with all other
+gammas, has a unit square, and in 4 dimensions equals
+@samp{gamma~0 gamma~1 gamma~2 gamma~3}, provided by
@example
ex dirac_gamma5(unsigned char rl = 0);
@end example
-@cindex @code{dirac_gamma6()}
-@cindex @code{dirac_gamma7()}
-The two additional functions
+@cindex @code{dirac_gammaL()}
+@cindex @code{dirac_gammaR()}
+The chiral projectors @samp{(1+/-gamma5)/2} are also available as proper
+objects, constructed by
@example
-ex dirac_gamma6(unsigned char rl = 0);
-ex dirac_gamma7(unsigned char rl = 0);
+ex dirac_gammaL(unsigned char rl = 0);
+ex dirac_gammaR(unsigned char rl = 0);
@end example
-return @code{dirac_ONE(rl) + dirac_gamma5(rl)} and @code{dirac_ONE(rl) - dirac_gamma5(rl)},
-respectively.
+They observe the relations @samp{gammaL^2 = gammaL}, @samp{gammaR^2 = gammaR},
+and @samp{gammaL gammaR = gammaR gammaL = 0}.
@cindex @code{dirac_slash()}
Finally, the function
Such slashed expressions are printed with a trailing backslash, e.g. @samp{e\}.
In products of dirac gammas, superfluous unity elements are automatically
-removed, squares are replaced by their values and @samp{gamma5} is
-anticommuted to the front. The @code{simplify_indexed()} function performs
-contractions in gamma strings, for example
+removed, squares are replaced by their values, and @samp{gamma5}, @samp{gammaL}
+and @samp{gammaR} are moved to the front.
+
+The @code{simplify_indexed()} function performs contractions in gamma strings,
+for example
@example
@{
are also valid patterns.
@end itemize
+@subsection Matching expressions
@cindex @code{match()}
The most basic application of patterns is to check whether an expression
matches a given pattern. This is done by the function
@{$0==x^2@}
@end example
+@subsection Matching parts of expressions
@cindex @code{has()}
A more general way to look for patterns in expressions is provided by the
member function
@end example
works a bit like @code{has()} but it doesn't stop upon finding the first
-match. Instead, it appends all found matches to the specified list. If there
-are multiple occurrences of the same expression, it is entered only once to
-the list. @code{find()} returns false if no matches were found (in
+match. Instead, it inserts all found matches into the specified list. If
+there are multiple occurrences of the same expression, it is entered only
+once to the list. @code{find()} returns false if no matches were found (in
@command{ginsh}, it returns an empty list):
@example
@{sin(y),sin(x)@}
@end example
+@subsection Substituting expressions
@cindex @code{subs()}
Probably the most useful application of patterns is to use them for
substituting expressions with the @code{subs()} method. Wildcards can be
@subsection Expanding and collecting
@cindex @code{expand()}
@cindex @code{collect()}
+@cindex @code{collect_common_factors()}
A polynomial in one or more variables has many equivalent
representations. Some useful ones serve a specific purpose. Consider
(1+q+d*(1+q+p)+p)*sin(y)+(1+q+d*(1+q+p)+p)*sin(x)
@end example
+Polynomials can often be brought into a more compact form by collecting
+common factors from the terms of sums. This is accomplished by the function
+
+@example
+ex collect_common_factors(const ex & e);
+@end example
+
+This function doesn't perform a full factorization but only looks for
+factors which are already explicitly present:
+
+@example
+> collect_common_factors(a*x+a*y);
+(x+y)*a
+> collect_common_factors(a*x^2+2*a*x*y+a*y^2);
+a*(2*x*y+y^2+x^2)
+> collect_common_factors(a*(b*(a+c)*x+b*((a+c)*x+(a+c)*y)*y));
+(c+a)*a*(x*y+y^2+x)*b
+@end example
+
@subsection Degree and coefficients
@cindex @code{degree()}
@cindex @code{ldegree()}
@math{1-v^2/c^2+O(v^10)}, without that call we would just have a long
series raised to the power @math{-2}.
-@cindex M@'echain's formula
+@cindex Machin's formula
As another instructive application, let us calculate the numerical
value of Archimedes' constant
@tex
$\pi$
@end tex
(for which there already exists the built-in constant @code{Pi})
-using M@'echain's amazing formula
+using Machin's amazing formula
@tex
$\pi=16$~atan~$\!\left(1 \over 5 \right)-4$~atan~$\!\left(1 \over 239 \right)$.
@end tex
#include <ginac/ginac.h>
using namespace GiNaC;
-ex mechain_pi(int degr)
+ex machin_pi(int degr)
@{
symbol x;
ex pi_expansion = series_to_poly(atan(x).series(x,degr));
using std::endl; // ...dealing with this namespace std.
ex pi_frac;
for (int i=2; i<12; i+=2) @{
- pi_frac = mechain_pi(i);
+ pi_frac = machin_pi(i);
cout << i << ":\t" << pi_frac << endl
<< "\t" << pi_frac.evalf() << endl;
@}
The above example will produce (note the @code{x^2} being converted to @code{x*x}):
@example
-float f = (3.000000e+00/2.000000e+00)*(x*x)+4.500000e+00;
-double d = (3.000000e+00/2.000000e+00)*(x*x)+4.500000e+00;
-cl_N n = (cln::cl_F("3.0")/cln::cl_F("2.0"))*(x*x)+cln::cl_F("4.5");
+float f = (3.0/2.0)*(x*x)+4.500000e+00;
+double d = (3.0/2.0)*(x*x)+4.5000000000000000e+00;
+cl_N n = cln::cl_RA("3/2")*(x*x)+cln::cl_F("4.5_17");
@end example
The @code{print_context} type @code{print_tree} provides a dump of 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:
+list of symbols and indices to be used:
@example
@{
- symbol x("x"), y("y");
- ex e("2*x+sin(y)", lst(x, y));
+ symbol x("x"), y("y"), p("p");
+ idx i(symbol("i"), 3);
+ ex e("2*x+sin(y)+p.i", lst(x, y, p, i));
@}
@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{<<}. The symbols and indices in the string are matched
+by name to the symbols and indices in the list and if GiNaC encounters a
+symbol or index not specified in the list it will throw an exception. Only
+indices whose values are single symbols can be used (i.e. numeric indices
+or compound indices as in "A.(2*n+1)" are not allowed).
With this constructor, it's also easy to implement interactive GiNaC programs:
@end example
This @file{Makefile.am}, says that we are building a single executable,
-from a single sourcefile @file{simple.cpp}. Since every program
+from a single source file @file{simple.cpp}. Since every program
we are building uses GiNaC we simply added the GiNaC options
to @env{$LIBS} and @env{$CPPFLAGS}, but in other circumstances, we might
want to specify them on a per-program basis: for instance by