+A @code{varidx} is an @code{idx} with an additional flag that marks it as
+co- or contravariant. The default is a contravariant (upper) index, but
+this can be overridden by supplying a third argument to the @code{varidx}
+constructor. The two methods
+
+@example
+bool varidx::is_covariant(void);
+bool varidx::is_contravariant(void);
+@end example
+
+allow you to check the variance of a @code{varidx} object (use @code{ex_to<varidx>()}
+to get the object reference from an expression). There's also the very useful
+method
+
+@example
+ex varidx::toggle_variance(void);
+@end example
+
+which makes a new index with the same value and dimension but the opposite
+variance. By using it you only have to define the index once.
+
+@cindex @code{spinidx} (class)
+The @code{spinidx} class provides dotted and undotted variant indices, as
+used in the Weyl-van-der-Waerden spinor formalism:
+
+@example
+ ...
+ symbol K("K"), C_sym("C"), D_sym("D");
+ spinidx C(C_sym, 2), D(D_sym); // default is 2-dimensional,
+ // contravariant, undotted
+ spinidx C_co(C_sym, 2, true); // covariant index
+ spinidx D_dot(D_sym, 2, false, true); // contravariant, dotted
+ spinidx D_co_dot(D_sym, 2, true, true); // covariant, dotted
+
+ cout << indexed(K, C, D) << endl;
+ // -> K~C~D
+ cout << indexed(K, C_co, D_dot) << endl;
+ // -> K.C~*D
+ cout << indexed(K, D_co_dot, D) << endl;
+ // -> K.*D~D
+ ...
+@end example
+
+A @code{spinidx} is a @code{varidx} with an additional flag that marks it as
+dotted or undotted. The default is undotted but this can be overridden by
+supplying a fourth argument to the @code{spinidx} constructor. The two
+methods
+
+@example
+bool spinidx::is_dotted(void);
+bool spinidx::is_undotted(void);
+@end example
+
+allow you to check whether or not a @code{spinidx} object is dotted (use
+@code{ex_to<spinidx>()} to get the object reference from an expression).
+Finally, the two methods
+
+@example
+ex spinidx::toggle_dot(void);
+ex spinidx::toggle_variance_dot(void);
+@end example
+
+create a new index with the same value and dimension but opposite dottedness
+and the same or opposite variance.
+
+@subsection Substituting indices
+
+@cindex @code{subs()}
+Sometimes you will want to substitute one symbolic index with another
+symbolic or numeric index, for example when calculating one specific element
+of a tensor expression. This is done with the @code{.subs()} method, as it
+is done for symbols (see @ref{Substituting Expressions}).
+
+You have two possibilities here. You can either substitute the whole index
+by another index or expression:
+
+@example
+ ...
+ ex e = indexed(A, mu_co);
+ cout << e << " becomes " << e.subs(mu_co == nu) << endl;
+ // -> A.mu becomes A~nu
+ cout << e << " becomes " << e.subs(mu_co == varidx(0, 4)) << endl;
+ // -> A.mu becomes A~0
+ cout << e << " becomes " << e.subs(mu_co == 0) << endl;
+ // -> A.mu becomes A.0
+ ...
+@end example
+
+The third example shows that trying to replace an index with something that
+is not an index will substitute the index value instead.
+
+Alternatively, you can substitute the @emph{symbol} of a symbolic index by
+another expression:
+
+@example
+ ...
+ ex e = indexed(A, mu_co);
+ cout << e << " becomes " << e.subs(mu_sym == nu_sym) << endl;
+ // -> A.mu becomes A.nu
+ cout << e << " becomes " << e.subs(mu_sym == 0) << endl;
+ // -> A.mu becomes A.0
+ ...
+@end example
+
+As you see, with the second method only the value of the index will get
+substituted. Its other properties, including its dimension, remain unchanged.
+If you want to change the dimension of an index you have to substitute the
+whole index by another one with the new dimension.
+
+Finally, substituting the base expression of an indexed object works as
+expected:
+
+@example
+ ...
+ ex e = indexed(A, mu_co);
+ cout << e << " becomes " << e.subs(A == A+B) << endl;
+ // -> A.mu becomes (B+A).mu
+ ...
+@end example
+
+@subsection Symmetries
+@cindex @code{symmetry} (class)
+@cindex @code{sy_none()}
+@cindex @code{sy_symm()}
+@cindex @code{sy_anti()}
+@cindex @code{sy_cycl()}
+
+Indexed objects can have certain symmetry properties with respect to their
+indices. Symmetries are specified as a tree of objects of class @code{symmetry}
+that is constructed with the helper functions
+
+@example
+symmetry sy_none(...);
+symmetry sy_symm(...);
+symmetry sy_anti(...);
+symmetry sy_cycl(...);
+@end example
+
+@code{sy_none()} stands for no symmetry, @code{sy_symm()} and @code{sy_anti()}
+specify fully symmetric or antisymmetric, respectively, and @code{sy_cycl()}
+represents a cyclic symmetry. Each of these functions accepts up to four
+arguments which can be either symmetry objects themselves or unsigned integer
+numbers that represent an index position (counting from 0). A symmetry
+specification that consists of only a single @code{sy_symm()}, @code{sy_anti()}
+or @code{sy_cycl()} with no arguments specifies the respective symmetry for
+all indices.
+
+Here are some examples of symmetry definitions:
+
+@example
+ ...
+ // No symmetry:
+ e = indexed(A, i, j);
+ e = indexed(A, sy_none(), i, j); // equivalent
+ e = indexed(A, sy_none(0, 1), i, j); // equivalent
+
+ // Symmetric in all three indices:
+ e = indexed(A, sy_symm(), i, j, k);
+ e = indexed(A, sy_symm(0, 1, 2), i, j, k); // equivalent
+ e = indexed(A, sy_symm(2, 0, 1), i, j, k); // same symmetry, but yields a
+ // different canonical order
+
+ // Symmetric in the first two indices only:
+ e = indexed(A, sy_symm(0, 1), i, j, k);
+ e = indexed(A, sy_none(sy_symm(0, 1), 2), i, j, k); // equivalent
+
+ // Antisymmetric in the first and last index only (index ranges need not
+ // be contiguous):
+ e = indexed(A, sy_anti(0, 2), i, j, k);
+ e = indexed(A, sy_none(sy_anti(0, 2), 1), i, j, k); // equivalent
+
+ // An example of a mixed symmetry: antisymmetric in the first two and
+ // last two indices, symmetric when swapping the first and last index
+ // pairs (like the Riemann curvature tensor):
+ e = indexed(A, sy_symm(sy_anti(0, 1), sy_anti(2, 3)), i, j, k, l);
+
+ // Cyclic symmetry in all three indices:
+ e = indexed(A, sy_cycl(), i, j, k);
+ e = indexed(A, sy_cycl(0, 1, 2), i, j, k); // equivalent
+
+ // The following examples are invalid constructions that will throw
+ // an exception at run time.
+
+ // An index may not appear multiple times:
+ e = indexed(A, sy_symm(0, 0, 1), i, j, k); // ERROR
+ e = indexed(A, sy_none(sy_symm(0, 1), sy_anti(0, 2)), i, j, k); // ERROR
+
+ // Every child of sy_symm(), sy_anti() and sy_cycl() must refer to the
+ // same number of indices:
+ e = indexed(A, sy_symm(sy_anti(0, 1), 2), i, j, k); // ERROR
+
+ // And of course, you cannot specify indices which are not there:
+ e = indexed(A, sy_symm(0, 1, 2, 3), i, j, k); // ERROR
+ ...
+@end example
+
+If you need to specify more than four indices, you have to use the
+@code{.add()} method of the @code{symmetry} class. For example, to specify
+full symmetry in the first six indices you would write
+@code{sy_symm(0, 1, 2, 3).add(4).add(5)}.
+
+If an indexed object has a symmetry, GiNaC will automatically bring the
+indices into a canonical order which allows for some immediate simplifications:
+
+@example
+ ...
+ cout << indexed(A, sy_symm(), i, j)
+ + indexed(A, sy_symm(), j, i) << endl;
+ // -> 2*A.j.i
+ cout << indexed(B, sy_anti(), i, j)
+ + indexed(B, sy_anti(), j, i) << endl;
+ // -> -B.j.i
+ cout << indexed(B, sy_anti(), i, j, k)
+ + indexed(B, sy_anti(), j, i, k) << endl;
+ // -> 0
+ ...
+@end example
+
+@cindex @code{get_free_indices()}
+@cindex Dummy index
+@subsection Dummy indices
+
+GiNaC treats certain symbolic index pairs as @dfn{dummy indices} meaning
+that a summation over the index range is implied. Symbolic indices which are
+not dummy indices are called @dfn{free indices}. Numeric indices are neither
+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
+@code{varidx} they must also be of opposite variance; if they are of class
+@code{spinidx} they must be both dotted or both undotted.
+
+The method @code{.get_free_indices()} returns a vector containing the free
+indices of an expression. It also checks that the free indices of the terms
+of a sum are consistent:
+
+@example
+@{
+ symbol A("A"), B("B"), C("C");
+
+ symbol i_sym("i"), j_sym("j"), k_sym("k"), l_sym("l");
+ idx i(i_sym, 3), j(j_sym, 3), k(k_sym, 3), l(l_sym, 3);
+
+ ex e = indexed(A, i, j) * indexed(B, j, k) + indexed(C, k, l, i, l);
+ cout << exprseq(e.get_free_indices()) << endl;
+ // -> (.i,.k)
+ // 'j' and 'l' are dummy indices
+
+ symbol mu_sym("mu"), nu_sym("nu"), rho_sym("rho"), sigma_sym("sigma");
+ varidx mu(mu_sym, 4), nu(nu_sym, 4), rho(rho_sym, 4), sigma(sigma_sym, 4);
+
+ e = indexed(A, mu, nu) * indexed(B, nu.toggle_variance(), rho)
+ + indexed(C, mu, sigma, rho, sigma.toggle_variance());
+ cout << exprseq(e.get_free_indices()) << endl;
+ // -> (~mu,~rho)
+ // 'nu' is a dummy index, but 'sigma' is not
+
+ e = indexed(A, mu, mu);
+ cout << exprseq(e.get_free_indices()) << endl;
+ // -> (~mu)
+ // 'mu' is not a dummy index because it appears twice with the same
+ // variance
+
+ e = indexed(A, mu, nu) + 42;
+ cout << exprseq(e.get_free_indices()) << endl; // ERROR
+ // this will throw an exception:
+ // "add::get_free_indices: inconsistent indices in sum"
+@}
+@end example
+
+@cindex @code{simplify_indexed()}
+@subsection Simplifying indexed expressions
+
+In addition to the few automatic simplifications that GiNaC performs on
+indexed expressions (such as re-ordering the indices of symmetric tensors
+and calculating traces and convolutions of matrices and predefined tensors)
+there is the method
+
+@example
+ex ex::simplify_indexed(void);
+ex ex::simplify_indexed(const scalar_products & sp);
+@end example
+
+that performs some more expensive operations:
+
+@itemize
+@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
+ the same name to allow simplifications like @math{a_i*b_i-a_j*b_j=0}
+@item it (symbolically) calculates all possible dummy index summations/contractions
+ with the predefined tensors (this will be explained in more detail in the
+ next section)
+@item it detects contractions that vanish for symmetry reasons, for example
+ the contraction of a symmetric and a totally antisymmetric tensor
+@item as a special case of dummy index summation, it can replace scalar products
+ of two tensors with a user-defined value
+@end itemize
+
+The last point is done with the help of the @code{scalar_products} class
+which is used to store scalar products with known values (this is not an
+arithmetic class, you just pass it to @code{simplify_indexed()}):
+
+@example
+@{
+ symbol A("A"), B("B"), C("C"), i_sym("i");
+ idx i(i_sym, 3);
+
+ scalar_products sp;
+ sp.add(A, B, 0); // A and B are orthogonal
+ sp.add(A, C, 0); // A and C are orthogonal
+ sp.add(A, A, 4); // A^2 = 4 (A has length 2)
+
+ e = indexed(A + B, i) * indexed(A + C, i);
+ cout << e << endl;
+ // -> (B+A).i*(A+C).i
+
+ cout << e.expand(expand_options::expand_indexed).simplify_indexed(sp)
+ << endl;
+ // -> 4+C.i*B.i
+@}
+@end example
+
+The @code{scalar_products} object @code{sp} acts as a storage for the
+scalar products added to it with the @code{.add()} method. This method
+takes three arguments: the two expressions of which the scalar product is
+taken, and the expression to replace it with. After @code{sp.add(A, B, 0)},
+@code{simplify_indexed()} will replace all scalar products of indexed
+objects that have the symbols @code{A} and @code{B} as base expressions
+with the single value 0. The number, type and dimension of the indices
+don't matter; @samp{A~mu~nu*B.mu.nu} would also be replaced by 0.
+
+@cindex @code{expand()}
+The example above also illustrates a feature of the @code{expand()} method:
+if passed the @code{expand_indexed} option it will distribute indices
+over sums, so @samp{(A+B).i} becomes @samp{A.i+B.i}.
+
+@cindex @code{tensor} (class)
+@subsection Predefined tensors
+
+Some frequently used special tensors such as the delta, epsilon and metric
+tensors are predefined in GiNaC. They have special properties when
+contracted with other tensor expressions and some of them have constant
+matrix representations (they will evaluate to a number when numeric
+indices are specified).
+
+@cindex @code{delta_tensor()}
+@subsubsection Delta tensor
+
+The delta tensor takes two indices, is symmetric and has the matrix
+representation @code{diag(1, 1, 1, ...)}. It is constructed by the function
+@code{delta_tensor()}:
+
+@example
+@{
+ symbol A("A"), B("B");
+
+ idx i(symbol("i"), 3), j(symbol("j"), 3),
+ k(symbol("k"), 3), l(symbol("l"), 3);
+
+ ex e = indexed(A, i, j) * indexed(B, k, l)
+ * delta_tensor(i, k) * delta_tensor(j, l) << endl;
+ cout << e.simplify_indexed() << endl;
+ // -> B.i.j*A.i.j
+
+ cout << delta_tensor(i, i) << endl;
+ // -> 3
+@}
+@end example
+
+@cindex @code{metric_tensor()}
+@subsubsection General metric tensor
+
+The function @code{metric_tensor()} creates a general symmetric metric
+tensor with two indices that can be used to raise/lower tensor indices. The
+metric tensor is denoted as @samp{g} in the output and if its indices are of
+mixed variance it is automatically replaced by a delta tensor:
+
+@example
+@{
+ symbol A("A");
+
+ varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4), rho(symbol("rho"), 4);
+
+ ex e = metric_tensor(mu, nu) * indexed(A, nu.toggle_variance(), rho);
+ cout << e.simplify_indexed() << endl;
+ // -> A~mu~rho
+
+ e = delta_tensor(mu, nu.toggle_variance()) * metric_tensor(nu, rho);
+ cout << e.simplify_indexed() << endl;
+ // -> g~mu~rho
+
+ e = metric_tensor(mu.toggle_variance(), nu.toggle_variance())
+ * metric_tensor(nu, rho);
+ cout << e.simplify_indexed() << endl;
+ // -> delta.mu~rho
+
+ e = metric_tensor(nu.toggle_variance(), rho.toggle_variance())
+ * metric_tensor(mu, nu) * (delta_tensor(mu.toggle_variance(), rho)
+ + indexed(A, mu.toggle_variance(), rho));
+ cout << e.simplify_indexed() << endl;
+ // -> 4+A.rho~rho
+@}
+@end example
+
+@cindex @code{lorentz_g()}
+@subsubsection Minkowski metric tensor
+
+The Minkowski metric tensor is a special metric tensor with a constant
+matrix representation which is either @code{diag(1, -1, -1, ...)} (negative
+signature, the default) or @code{diag(-1, 1, 1, ...)} (positive signature).
+It is created with the function @code{lorentz_g()} (although it is output as
+@samp{eta}):
+
+@example
+@{
+ varidx mu(symbol("mu"), 4);
+
+ e = delta_tensor(varidx(0, 4), mu.toggle_variance())
+ * lorentz_g(mu, varidx(0, 4)); // negative signature
+ cout << e.simplify_indexed() << endl;
+ // -> 1
+
+ e = delta_tensor(varidx(0, 4), mu.toggle_variance())
+ * lorentz_g(mu, varidx(0, 4), true); // positive signature
+ cout << e.simplify_indexed() << endl;
+ // -> -1
+@}
+@end example
+
+@cindex @code{spinor_metric()}
+@subsubsection Spinor metric tensor
+
+The function @code{spinor_metric()} creates an antisymmetric tensor with
+two indices that is used to raise/lower indices of 2-component spinors.
+It is output as @samp{eps}:
+
+@example
+@{
+ symbol psi("psi");
+
+ spinidx A(symbol("A")), B(symbol("B")), C(symbol("C"));
+ ex A_co = A.toggle_variance(), B_co = B.toggle_variance();
+
+ e = spinor_metric(A, B) * indexed(psi, B_co);
+ cout << e.simplify_indexed() << endl;
+ // -> psi~A
+
+ e = spinor_metric(A, B) * indexed(psi, A_co);
+ cout << e.simplify_indexed() << endl;
+ // -> -psi~B
+
+ e = spinor_metric(A_co, B_co) * indexed(psi, B);
+ cout << e.simplify_indexed() << endl;
+ // -> -psi.A
+
+ e = spinor_metric(A_co, B_co) * indexed(psi, A);
+ cout << e.simplify_indexed() << endl;
+ // -> psi.B
+
+ e = spinor_metric(A_co, B_co) * spinor_metric(A, B);
+ cout << e.simplify_indexed() << endl;
+ // -> 2
+
+ e = spinor_metric(A_co, B_co) * spinor_metric(B, C);
+ cout << e.simplify_indexed() << endl;
+ // -> -delta.A~C
+@}
+@end example
+
+The matrix representation of the spinor metric is @code{[[0, 1], [-1, 0]]}.
+
+@cindex @code{epsilon_tensor()}
+@cindex @code{lorentz_eps()}
+@subsubsection Epsilon tensor
+
+The epsilon tensor is totally antisymmetric, its number of indices is equal
+to the dimension of the index space (the indices must all be of the same
+numeric dimension), and @samp{eps.1.2.3...} (resp. @samp{eps~0~1~2...}) is
+defined to be 1. Its behavior with indices that have a variance also
+depends on the signature of the metric. Epsilon tensors are output as
+@samp{eps}.
+
+There are three functions defined to create epsilon tensors in 2, 3 and 4
+dimensions:
+
+@example
+ex epsilon_tensor(const ex & i1, const ex & i2);
+ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3);
+ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig = false);
+@end example
+
+The first two functions create an epsilon tensor in 2 or 3 Euclidean
+dimensions, the last function creates an epsilon tensor in a 4-dimensional
+Minkowski space (the last @code{bool} argument specifies whether the metric
+has negative or positive signature, as in the case of the Minkowski metric
+tensor):
+
+@example
+@{
+ varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4), rho(symbol("rho"), 4),
+ sig(symbol("sig"), 4), lam(symbol("lam"), 4), bet(symbol("bet"), 4);
+ e = lorentz_eps(mu, nu, rho, sig) *
+ lorentz_eps(mu.toggle_variance(), nu.toggle_variance(), lam, bet);
+ cout << simplify_indexed(e) << endl;
+ // -> 2*eta~bet~rho*eta~sig~lam-2*eta~sig~bet*eta~rho~lam
+
+ idx i(symbol("i"), 3), j(symbol("j"), 3), k(symbol("k"), 3);
+ symbol A("A"), B("B");
+ e = epsilon_tensor(i, j, k) * indexed(A, j) * indexed(B, k);
+ cout << simplify_indexed(e) << endl;
+ // -> -B.k*A.j*eps.i.k.j
+ e = epsilon_tensor(i, j, k) * indexed(A, j) * indexed(A, k);
+ cout << simplify_indexed(e) << endl;
+ // -> 0
+@}
+@end example
+
+@subsection Linear algebra
+
+The @code{matrix} class can be used with indices to do some simple linear
+algebra (linear combinations and products of vectors and matrices, traces
+and scalar products):
+
+@example
+@{
+ idx i(symbol("i"), 2), j(symbol("j"), 2);
+ symbol x("x"), y("y");
+
+ // A is a 2x2 matrix, X is a 2x1 vector
+ matrix A(2, 2, lst(1, 2, 3, 4)), X(2, 1, lst(x, y));
+
+ cout << indexed(A, i, i) << endl;
+ // -> 5
+
+ ex e = indexed(A, i, j) * indexed(X, j);
+ cout << e.simplify_indexed() << endl;
+ // -> [[2*y+x],[4*y+3*x]].i
+
+ e = indexed(A, i, j) * indexed(X, i) + indexed(X, j) * 2;
+ cout << e.simplify_indexed() << endl;
+ // -> [[3*y+3*x,6*y+2*x]].j
+@}
+@end example
+
+You can of course obtain the same results with the @code{matrix::add()},
+@code{matrix::mul()} and @code{matrix::trace()} methods (@pxref{Matrices})
+but with indices you don't have to worry about transposing matrices.
+
+Matrix indices always start at 0 and their dimension must match the number
+of rows/columns of the matrix. Matrices with one row or one column are
+vectors and can have one or two indices (it doesn't matter whether it's a
+row or a column vector). Other matrices must have two indices.
+
+You should be careful when using indices with variance on matrices. GiNaC
+doesn't look at the variance and doesn't know that @samp{F~mu~nu} and
+@samp{F.mu.nu} are different matrices. In this case you should use only
+one form for @samp{F} and explicitly multiply it with a matrix representation
+of the metric tensor.
+
+
+@node Non-commutative objects, Methods and Functions, Indexed objects, Basic Concepts
+@c node-name, next, previous, up
+@section Non-commutative objects
+
+GiNaC is equipped to handle certain non-commutative algebras. Three classes of
+non-commutative objects are built-in which are mostly of use in high energy
+physics:
+
+@itemize
+@item Clifford (Dirac) algebra (class @code{clifford})
+@item su(3) Lie algebra (class @code{color})
+@item Matrices (unindexed) (class @code{matrix})
+@end itemize
+
+The @code{clifford} and @code{color} classes are subclasses of
+@code{indexed} because the elements of these algebras usually carry
+indices. The @code{matrix} class is described in more detail in
+@ref{Matrices}.
+
+Unlike most computer algebra systems, GiNaC does not primarily provide an
+operator (often denoted @samp{&*}) for representing inert products of
+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
+by their class. Consider this example:
+
+@example
+ ...
+ varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4);
+ idx a(symbol("a"), 8), b(symbol("b"), 8);
+ ex e = -dirac_gamma(mu) * (2*color_T(a)) * 8 * color_T(b) * dirac_gamma(nu);
+ cout << e << endl;
+ // -> -16*(gamma~mu*gamma~nu)*(T.a*T.b)
+ ...
+@end 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
+@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.
+
+@cindex @code{ncmul} (class)
+Non-commutative products are internally represented by objects of the class
+@code{ncmul}, as opposed to commutative products which are handled by the
+@code{mul} class. You will normally not have to worry about this distinction,
+though.
+
+The advantage of this approach is that you never have to worry about using
+(or forgetting to use) a special operator when constructing non-commutative
+expressions. Also, non-commutative products in GiNaC are more intelligent
+than in other computer algebra systems; they can, for example, automatically
+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
+using symbols to represent the algebra elements or generators. User-defined
+functions can, however, be specified as being non-commutative.
+
+@cindex @code{return_type()}
+@cindex @code{return_type_tinfo()}
+Information about the commutativity of an object or expression can be
+obtained with the two member functions
+
+@example
+unsigned ex::return_type(void) const;
+unsigned ex::return_type_tinfo(void) 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
+@item @code{return_types::commutative}: Commutes 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
+ 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
+ @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.
+
+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 -
+@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
+non-commutative expressions).
+
+
+@cindex @code{clifford} (class)
+@subsection Clifford algebra
+
+@cindex @code{dirac_gamma()}
+Clifford algebra elements (also called Dirac gamma matrices, although GiNaC
+doesn't treat them as matrices) are designated as @samp{gamma~mu} and satisfy
+@samp{gamma~mu*gamma~nu + gamma~nu*gamma~mu = 2*eta~mu~nu} where @samp{eta~mu~nu}
+is the Minkowski metric tensor. Dirac gammas are constructed by the function
+
+@example
+ex dirac_gamma(const ex & mu, unsigned char rl = 0);
+@end example
+
+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
+the framework of dimensional regularization) any symbolic value. Spinor
+indices on Dirac gammas are not supported in GiNaC.
+
+@cindex @code{dirac_ONE()}
+The unity element of a Clifford algebra is constructed by
+
+@example
+ex dirac_ONE(unsigned char rl = 0);
+@end example
+
+@strong{Note:} You must always use @code{dirac_ONE()} when referring to
+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.
+
+@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
+
+@example
+ex dirac_gamma5(unsigned char rl = 0);
+@end example
+
+@cindex @code{dirac_gamma6()}
+@cindex @code{dirac_gamma7()}
+The two additional functions
+
+@example
+ex dirac_gamma6(unsigned char rl = 0);
+ex dirac_gamma7(unsigned char rl = 0);
+@end example
+
+return @code{dirac_ONE(rl) + dirac_gamma5(rl)} and @code{dirac_ONE(rl) - dirac_gamma5(rl)},
+respectively.
+
+@cindex @code{dirac_slash()}
+Finally, the function
+
+@example
+ex dirac_slash(const ex & e, const ex & dim, unsigned char rl = 0);
+@end example
+
+creates a term that represents a contraction of @samp{e} with the Dirac
+Lorentz vector (it behaves like a term of the form @samp{e.mu gamma~mu}
+with a unique index whose dimension is given by the @code{dim} argument).
+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
+
+@example
+@{
+ ...
+ symbol a("a"), b("b"), D("D");
+ varidx mu(symbol("mu"), D);
+ ex e = dirac_gamma(mu) * dirac_slash(a, D)
+ * dirac_gamma(mu.toggle_variance());
+ cout << e << endl;
+ // -> gamma~mu*a\*gamma.mu
+ e = e.simplify_indexed();
+ cout << e << endl;
+ // -> -D*a\+2*a\
+ cout << e.subs(D == 4) << endl;
+ // -> -2*a\
+ ...
+@}
+@end example
+
+@cindex @code{dirac_trace()}
+To calculate the trace of an expression containing strings of Dirac gammas
+you use the function
+
+@example
+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
+@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
+@cite{The Role of gamma5 in Dimensional Regularization}.
+
+The value of the trace itself is also usually different in 4 and in
+@math{D != 4} dimensions:
+
+@example
+@{
+ // 4 dimensions
+ varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4), rho(symbol("rho"), 4);
+ ex e = dirac_gamma(mu) * dirac_gamma(nu) *
+ dirac_gamma(mu.toggle_variance()) * dirac_gamma(rho);
+ cout << dirac_trace(e).simplify_indexed() << endl;
+ // -> -8*eta~rho~nu
+@}
+...
+@{
+ // D dimensions
+ symbol D("D");
+ varidx mu(symbol("mu"), D), nu(symbol("nu"), D), rho(symbol("rho"), D);
+ ex e = dirac_gamma(mu) * dirac_gamma(nu) *
+ dirac_gamma(mu.toggle_variance()) * dirac_gamma(rho);
+ cout << dirac_trace(e).simplify_indexed() << endl;
+ // -> 8*eta~rho~nu-4*eta~rho~nu*D
+@}
+@end example
+
+Here is an example for using @code{dirac_trace()} to compute a value that
+appears in the calculation of the one-loop vacuum polarization amplitude in
+QED:
+
+@example
+@{
+ symbol q("q"), l("l"), m("m"), ldotq("ldotq"), D("D");
+ varidx mu(symbol("mu"), D), nu(symbol("nu"), D);
+
+ scalar_products sp;
+ sp.add(l, l, pow(l, 2));
+ sp.add(l, q, ldotq);
+
+ ex e = dirac_gamma(mu) *
+ (dirac_slash(l, D) + dirac_slash(q, D) + m * dirac_ONE()) *
+ 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));
+ cout << e << endl;
+ // -> (8-4*D)*l^2+(8-4*D)*ldotq+4*D*m^2
+@}
+@end example
+
+The @code{canonicalize_clifford()} function reorders all gamma products that
+appear in an expression to a canonical (but not necessarily simple) form.
+You can use this to compare two expressions or for further simplifications:
+
+@example
+@{
+ varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4);
+ ex e = dirac_gamma(mu) * dirac_gamma(nu) + dirac_gamma(nu) * dirac_gamma(mu);
+ cout << e << endl;
+ // -> gamma~mu*gamma~nu+gamma~nu*gamma~mu
+
+ e = canonicalize_clifford(e);
+ cout << e << endl;
+ // -> 2*eta~mu~nu
+@}
+@end example
+
+
+@cindex @code{color} (class)
+@subsection Color algebra
+
+@cindex @code{color_T()}
+For computations in quantum chromodynamics, GiNaC implements the base elements
+and structure constants of the su(3) Lie algebra (color algebra). The base
+elements @math{T_a} are constructed by the function
+
+@example
+ex color_T(const ex & a, unsigned char rl = 0);
+@end example
+
+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
+dimension of the index must be exactly 8 and it should be of class @code{idx},
+not @code{varidx}.
+
+@cindex @code{color_ONE()}
+The unity element of a color algebra is constructed by
+
+@example
+ex color_ONE(unsigned char rl = 0);
+@end example
+
+@strong{Note:} You must always use @code{color_ONE()} when referring to
+multiples of the unity element, even though it's customary to omit it.
+E.g. instead of @code{color_T(a)*(color_T(b)*indexed(X,b)+1)} you have to
+write @code{color_T(a)*(color_T(b)*indexed(X,b)+color_ONE())}. Otherwise,
+GiNaC may produce incorrect results.
+
+@cindex @code{color_d()}
+@cindex @code{color_f()}
+The functions
+
+@example
+ex color_d(const ex & a, const ex & b, const ex & c);
+ex color_f(const ex & a, const ex & b, const ex & c);
+@end example
+
+create the symmetric and antisymmetric structure constants @math{d_abc} and
+@math{f_abc} which satisfy @math{@{T_a, T_b@} = 1/3 delta_ab + d_abc T_c}
+and @math{[T_a, T_b] = i f_abc T_c}.
+
+@cindex @code{color_h()}
+There's an additional function
+
+@example
+ex color_h(const ex & a, const ex & b, const ex & c);
+@end example
+
+which returns the linear combination @samp{color_d(a, b, c)+I*color_f(a, b, c)}.
+
+The function @code{simplify_indexed()} performs some simplifications on
+expressions containing color objects:
+
+@example
+@{
+ ...
+ idx a(symbol("a"), 8), b(symbol("b"), 8), c(symbol("c"), 8),
+ k(symbol("k"), 8), l(symbol("l"), 8);
+
+ e = color_d(a, b, l) * color_f(a, b, k);
+ cout << e.simplify_indexed() << endl;
+ // -> 0
+
+ e = color_d(a, b, l) * color_d(a, b, k);
+ cout << e.simplify_indexed() << endl;
+ // -> 5/3*delta.k.l
+
+ e = color_f(l, a, b) * color_f(a, b, k);
+ cout << e.simplify_indexed() << endl;
+ // -> 3*delta.k.l
+
+ e = color_h(a, b, c) * color_h(a, b, c);
+ cout << e.simplify_indexed() << endl;
+ // -> -32/3
+
+ e = color_h(a, b, c) * color_T(b) * color_T(c);
+ cout << e.simplify_indexed() << endl;
+ // -> -2/3*T.a
+
+ e = color_h(a, b, c) * color_T(a) * color_T(b) * color_T(c);
+ cout << e.simplify_indexed() << endl;
+ // -> -8/9*ONE
+
+ e = color_T(k) * color_T(a) * color_T(b) * color_T(k);
+ cout << e.simplify_indexed() << endl;
+ // -> 1/4*delta.b.a*ONE-1/6*T.a*T.b
+ ...
+@end example
+
+@cindex @code{color_trace()}
+To calculate the trace of an expression containing color objects you use the
+function
+
+@example
+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:
+
+@example
+ ...
+ e = color_trace(4 * color_T(a) * color_T(b) * color_T(c));
+ cout << e << endl;
+ // -> -I*f.a.c.b+d.a.c.b
+@}
+@end example
+
+
+@node Methods and Functions, Information About Expressions, Non-commutative objects, Top
+@c node-name, next, previous, up
+@chapter Methods and Functions
+@cindex polynomial
+
+In this chapter the most important algorithms provided by GiNaC will be
+described. Some of them are implemented as functions on expressions,
+others are implemented as methods provided by expression objects. If
+they are methods, there exists a wrapper function around it, so you can
+alternatively call it in a functional way as shown in the simple
+example:
+
+@example
+ ...
+ cout << "As method: " << sin(1).evalf() << endl;
+ cout << "As function: " << evalf(sin(1)) << endl;
+ ...
+@end example
+
+@cindex @code{subs()}
+The general rule is that wherever methods accept one or more parameters
+(@var{arg1}, @var{arg2}, @dots{}) the order of arguments the function
+wrapper accepts is the same but preceded by the object to act on
+(@var{object}, @var{arg1}, @var{arg2}, @dots{}). This approach is the
+most natural one in an OO model but it may lead to confusion for MapleV
+users because where they would type @code{A:=x+1; subs(x=2,A);} GiNaC
+would require @code{A=x+1; subs(A,x==2);} (after proper declaration of
+@code{A} and @code{x}). On the other hand, since MapleV returns 3 on
+@code{A:=x^2+3; coeff(A,x,0);} (GiNaC: @code{A=pow(x,2)+3;
+coeff(A,x,0);}) it is clear that MapleV is not trying to be consistent
+here. Also, users of MuPAD will in most cases feel more comfortable
+with GiNaC's convention. All function wrappers are implemented
+as simple inline functions which just call the corresponding method and
+are only provided for users uncomfortable with OO who are dead set to
+avoid method invocations. Generally, nested function wrappers are much
+harder to read than a sequence of methods and should therefore be
+avoided if possible. On the other hand, not everything in GiNaC is a
+method on class @code{ex} and sometimes calling a function cannot be
+avoided.
+
+@menu
+* Information About Expressions::
+* Substituting Expressions::
+* Pattern Matching and Advanced Substitutions::
+* Applying a Function on Subexpressions::
+* Polynomial Arithmetic:: Working with polynomials.
+* Rational Expressions:: Working with rational functions.
+* Symbolic Differentiation::
+* Series Expansion:: Taylor and Laurent expansion.
+* Symmetrization::
+* Built-in Functions:: List of predefined mathematical functions.
+* Input/Output:: Input and output of expressions.
+@end menu
+
+
+@node Information About Expressions, Substituting Expressions, Methods and Functions, Methods and Functions
+@c node-name, next, previous, up
+@section Getting information about expressions
+
+@subsection Checking expression types
+@cindex @code{is_a<@dots{}>()}
+@cindex @code{is_exactly_a<@dots{}>()}
+@cindex @code{ex_to<@dots{}>()}
+@cindex Converting @code{ex} to other classes
+@cindex @code{info()}
+@cindex @code{return_type()}
+@cindex @code{return_type_tinfo()}
+
+Sometimes it's useful to check whether a given expression is a plain number,
+a sum, a polynomial with integer coefficients, or of some other specific type.
+GiNaC provides a couple of functions for this:
+
+@example
+bool is_a<T>(const ex & e);
+bool is_exactly_a<T>(const ex & e);
+bool ex::info(unsigned flag);
+unsigned ex::return_type(void) const;
+unsigned ex::return_type_tinfo(void) const;
+@end example
+
+When the test made by @code{is_a<T>()} returns true, it is safe to call
+one of the functions @code{ex_to<T>()}, where @code{T} is one of the
+class names (@xref{The Class Hierarchy}, for a list of all classes). For
+example, assuming @code{e} is an @code{ex}:
+
+@example
+@{
+ @dots{}
+ if (is_a<numeric>(e))
+ numeric n = ex_to<numeric>(e);
+ @dots{}
+@}
+@end example
+
+@code{is_a<T>(e)} allows you to check whether the top-level object of
+an expression @samp{e} is an instance of the GiNaC class @samp{T}
+(@xref{The Class Hierarchy}, for a list of all classes). This is most useful,
+e.g., for checking whether an expression is a number, a sum, or a product:
+
+@example
+@{
+ symbol x("x");
+ ex e1 = 42;
+ ex e2 = 4*x - 3;
+ is_a<numeric>(e1); // true
+ is_a<numeric>(e2); // false
+ is_a<add>(e1); // false
+ is_a<add>(e2); // true
+ is_a<mul>(e1); // false
+ is_a<mul>(e2); // false
+@}
+@end example
+
+In contrast, @code{is_exactly_a<T>(e)} allows you to check whether the
+top-level object of an expression @samp{e} is an instance of the GiNaC
+class @samp{T}, not including parent classes.
+
+The @code{info()} method is used for checking certain attributes of
+expressions. The possible values for the @code{flag} argument are defined
+in @file{ginac/flags.h}, the most important being explained in the following
+table:
+
+@cartouche
+@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>(...)})
+@item @code{real}
+@tab @dots{}a real integer, rational or float (i.e. is not complex)
+@item @code{rational}
+@tab @dots{}an exact rational number (integers are rational, too)
+@item @code{integer}
+@tab @dots{}a (non-complex) integer
+@item @code{crational}
+@tab @dots{}an exact (complex) rational number (such as @math{2/3+7/2*I})
+@item @code{cinteger}
+@tab @dots{}a (complex) integer (such as @math{2-3*I})
+@item @code{positive}
+@tab @dots{}not complex and greater than 0
+@item @code{negative}
+@tab @dots{}not complex and less than 0
+@item @code{nonnegative}
+@tab @dots{}not complex and greater than or equal to 0
+@item @code{posint}
+@tab @dots{}an integer greater than 0
+@item @code{negint}
+@tab @dots{}an integer less than 0
+@item @code{nonnegint}
+@tab @dots{}an integer greater than or equal to 0
+@item @code{even}
+@tab @dots{}an even integer
+@item @code{odd}
+@tab @dots{}an odd integer
+@item @code{prime}
+@tab @dots{}a prime integer (probabilistic primality test)
+@item @code{relation}
+@tab @dots{}a relation (same as @code{is_a<relational>(...)})
+@item @code{relation_equal}
+@tab @dots{}a @code{==} relation
+@item @code{relation_not_equal}
+@tab @dots{}a @code{!=} relation
+@item @code{relation_less}
+@tab @dots{}a @code{<} relation
+@item @code{relation_less_or_equal}
+@tab @dots{}a @code{<=} relation
+@item @code{relation_greater}
+@tab @dots{}a @code{>} relation
+@item @code{relation_greater_or_equal}
+@tab @dots{}a @code{>=} relation
+@item @code{symbol}
+@tab @dots{}a symbol (same as @code{is_a<symbol>(...)})
+@item @code{list}
+@tab @dots{}a list (same as @code{is_a<lst>(...)})
+@item @code{polynomial}
+@tab @dots{}a polynomial (i.e. only consists of sums and products of numbers and symbols with positive integer powers)
+@item @code{integer_polynomial}
+@tab @dots{}a polynomial with (non-complex) integer coefficients
+@item @code{cinteger_polynomial}
+@tab @dots{}a polynomial with (possibly complex) integer coefficients (such as @math{2-3*I})
+@item @code{rational_polynomial}
+@tab @dots{}a polynomial with (non-complex) rational coefficients
+@item @code{crational_polynomial}
+@tab @dots{}a polynomial with (possibly complex) rational coefficients (such as @math{2/3+7/2*I})
+@item @code{rational_function}
+@tab @dots{}a rational function (@math{x+y}, @math{z/(x+y)})
+@item @code{algebraic}
+@tab @dots{}an algebraic object (@math{sqrt(2)}, @math{sqrt(x)-1})
+@end multitable
+@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
+@code{return_type()} and @code{return_type_tinfo()}. @xref{Non-commutative objects},
+for an explanation of these.
+
+
+@subsection Accessing subexpressions
+@cindex @code{nops()}
+@cindex @code{op()}
+@cindex container
+@cindex @code{relational} (class)
+
+GiNaC provides the two methods
+
+@example
+unsigned ex::nops();
+ex ex::op(unsigned i);
+@end example
+
+for accessing the subexpressions in the container-like GiNaC classes like
+@code{add}, @code{mul}, @code{lst}, and @code{function}. @code{nops()}
+determines the number of subexpressions (@samp{operands}) contained, while
+@code{op()} returns the @code{i}-th (0..@code{nops()-1}) subexpression.
+In the case of a @code{power} object, @code{op(0)} will return the basis
+and @code{op(1)} the exponent. For @code{indexed} objects, @code{op(0)}
+is the base expression and @code{op(i)}, @math{i>0} are the indices.
+
+The left-hand and right-hand side expressions of objects of class
+@code{relational} (and only of these) can also be accessed with the methods
+
+@example
+ex ex::lhs();
+ex ex::rhs();
+@end example
+
+
+@subsection Comparing expressions
+@cindex @code{is_equal()}
+@cindex @code{is_zero()}
+
+Expressions can be compared with the usual C++ relational operators like
+@code{==}, @code{>}, and @code{<} but if the expressions contain symbols,
+the result is usually not determinable and the result will be @code{false},
+except in the case of the @code{!=} operator. You should also be aware that
+GiNaC will only do the most trivial test for equality (subtracting both
+expressions), so something like @code{(pow(x,2)+x)/x==x+1} will return
+@code{false}.
+
+Actually, if you construct an expression like @code{a == b}, this will be
+represented by an object of the @code{relational} class (@pxref{Relations})
+which is not evaluated until (explicitly or implicitly) cast to a @code{bool}.
+
+There are also two methods
+
+@example
+bool ex::is_equal(const ex & other);
+bool ex::is_zero();
+@end example
+
+for checking whether one expression is equal to another, or equal to zero,
+respectively.
+
+@strong{Warning:} You will also find an @code{ex::compare()} method in the
+GiNaC header files. This method is however only to be used internally by
+GiNaC to establish a canonical sort order for terms, and using it to compare
+expressions will give very surprising results.
+
+
+@node Substituting Expressions, Pattern Matching and Advanced Substitutions, Information About Expressions, Methods and Functions
+@c node-name, next, previous, up
+@section Substituting expressions
+@cindex @code{subs()}
+
+Algebraic objects inside expressions can be replaced with arbitrary
+expressions via the @code{.subs()} method:
+
+@example
+ex ex::subs(const ex & e);
+ex ex::subs(const lst & syms, const lst & repls);
+@end example
+
+In the first form, @code{subs()} accepts a relational of the form
+@samp{object == expression} or a @code{lst} of such relationals:
+
+@example
+@{
+ symbol x("x"), y("y");
+
+ ex e1 = 2*x^2-4*x+3;
+ cout << "e1(7) = " << e1.subs(x == 7) << endl;
+ // -> 73
+
+ ex e2 = x*y + x;
+ 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}.
+
+The second form of @code{subs()} takes two lists, one for the objects to be
+replaced and one for the expressions to be substituted (both lists must
+contain the same number of elements). Using this form, you would write
+@code{subs(lst(x, y), lst(y, x))} to exchange @samp{x} and @samp{y}.
+
+@code{subs()} performs syntactic substitution of any complete algebraic
+object; it does not try to match sub-expressions as is demonstrated by the
+following example:
+
+@example
+@{
+ symbol x("x"), y("y"), z("z");
+
+ ex e1 = pow(x+y, 2);
+ cout << e1.subs(x+y == 4) << endl;
+ // -> 16
+
+ ex e2 = sin(x)*sin(y)*cos(x);
+ cout << e2.subs(sin(x) == cos(x)) << endl;
+ // -> cos(x)^2*sin(y)
+
+ ex e3 = x+y+z;
+ cout << e3.subs(x+y == 4) << endl;
+ // -> x+y+z
+ // (and not 4+z as one might expect)
+@}
+@end example
+
+A more powerful form of substitution using wildcards is described in the
+next section.
+
+
+@node Pattern Matching and Advanced Substitutions, Applying a Function on Subexpressions, Substituting Expressions, Methods and Functions
+@c node-name, next, previous, up
+@section Pattern matching and advanced substitutions
+@cindex @code{wildcard} (class)
+@cindex Pattern matching
+
+GiNaC allows the use of patterns for checking whether an expression is of a
+certain form or contains subexpressions of a certain form, and for
+substituting expressions in a more general way.
+
+A @dfn{pattern} is an algebraic expression that optionally contains wildcards.
+A @dfn{wildcard} is a special kind of object (of class @code{wildcard}) that
+represents an arbitrary expression. Every wildcard has a @dfn{label} which is
+an unsigned integer number to allow having multiple different wildcards in a
+pattern. Wildcards are printed as @samp{$label} (this is also the way they
+are specified in @command{ginsh}). In C++ code, wildcard objects are created
+with the call
+
+@example
+ex wild(unsigned label = 0);
+@end example
+
+which is simply a wrapper for the @code{wildcard()} constructor with a shorter
+name.
+
+Some examples for patterns:
+
+@multitable @columnfractions .5 .5
+@item @strong{Constructed as} @tab @strong{Output as}
+@item @code{wild()} @tab @samp{$0}
+@item @code{pow(x,wild())} @tab @samp{x^$0}
+@item @code{atan2(wild(1),wild(2))} @tab @samp{atan2($1,$2)}
+@item @code{indexed(A,idx(wild(),3))} @tab @samp{A.$0}
+@end multitable
+
+Notes:
+
+@itemize
+@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
+ use them as the value of an @code{idx} object. This is because indices must
+ always be of class @code{idx} (or a subclass).
+@item Wildcards only represent expressions or subexpressions. It is not
+ possible to use them as placeholders for other properties like index
+ dimension or variance, representation labels, symmetry of indexed objects
+ etc.
+@item Because wildcards are commutative, it is not possible to use wildcards
+ as part of noncommutative products.
+@item A pattern does not have to contain wildcards. @samp{x} and @samp{x+y}
+ are also valid patterns.
+@end itemize
+
+@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
+
+@example
+bool ex::match(const ex & pattern);
+bool ex::match(const ex & pattern, lst & 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.
+
+The matching algorithm works as follows:
+
+@itemize
+@item A single wildcard matches any expression. If one wildcard appears
+ multiple times in a pattern, it must match the same expression in all
+ places (e.g. @samp{$0} matches anything, and @samp{$0*($0+1)} matches
+ @samp{x*(x+1)} but not @samp{x*(y+1)}).
+@item If the expression is not of the same class as the pattern, the match
+ fails (i.e. a sum only matches a sum, a function only matches a function,
+ etc.).
+@item If the pattern is a function, it only matches the same function
+ (i.e. @samp{sin($0)} matches @samp{sin(x)} but doesn't match @samp{exp(x)}).
+@item Except for sums and products, the match fails if the number of
+ subexpressions (@code{nops()}) is not equal to the number of subexpressions
+ of the pattern.
+@item If there are no subexpressions, the expressions and the pattern must
+ be equal (in the sense of @code{is_equal()}).
+@item Except for sums and products, each subexpression (@code{op()}) must
+ match the corresponding subexpression of the pattern.
+@end itemize
+
+Sums (@code{add}) and products (@code{mul}) are treated in a special way to
+account for their commutativity and associativity:
+
+@itemize
+@item If the pattern contains a term or factor that is a single wildcard,
+ this one is used as the @dfn{global wildcard}. If there is more than one
+ such wildcard, one of them is chosen as the global wildcard in a random
+ way.
+@item Every term/factor of the pattern, except the global wildcard, is
+ matched against every term of the expression in sequence. If no match is
+ found, the whole match fails. Terms that did match are not considered in
+ further matches.
+@item If there are no unmatched terms left, the match succeeds. Otherwise
+ the match fails unless there is a global wildcard in the pattern, in
+ which case this wildcard matches the remaining terms.
+@end itemize
+
+In general, having more than one single wildcard as a term of a sum or a
+factor of a product (such as @samp{a+$0+$1}) will lead to unpredictable or
+ambiguous results.
+
+Here are some examples in @command{ginsh} to demonstrate how it works (the
+@code{match()} function in @command{ginsh} returns @samp{FAIL} if the
+match fails, and the list of wildcard replacements otherwise):
+
+@example
+> match((x+y)^a,(x+y)^a);
+@{@}
+> match((x+y)^a,(x+y)^b);
+FAIL
+> match((x+y)^a,$1^$2);
+@{$1==x+y,$2==a@}
+> match((x+y)^a,$1^$1);
+FAIL
+> match((x+y)^(x+y),$1^$1);
+@{$1==x+y@}
+> match((x+y)^(x+y),$1^$2);
+@{$1==x+y,$2==x+y@}
+> match((a+b)*(a+c),($1+b)*($1+c));
+@{$1==a@}
+> match((a+b)*(a+c),(a+$1)*(a+$2));
+@{$1==c,$2==b@}
+ (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
+ and the re-ordering of terms in GiNaC, the match for the first factor
+ may be @{$1==a,$2==b@} in which case the match for the second factor
+ succeeds, or it may be @{$1==b,$2==a@} which causes the second match to
+ fail.)
+> match(a*(x+y)+a*z+b,a*$1+$2);
+ (This is also ambiguous and may return either @{$1==z,$2==a*(x+y)+b@} or
+ @{$1=x+y,$2=a*z+b@}.)
+> match(a+b+c+d+e+f,c);
+FAIL
+> match(a+b+c+d+e+f,c+$0);
+@{$0==a+e+b+f+d@}
+> match(a+b+c+d+e+f,c+e+$0);
+@{$0==a+b+f+d@}
+> match(a+b,a+b+$0);
+@{$0==0@}
+> match(a*b^2,a^$1*b^$2);
+FAIL
+ (The matching is syntactic, not algebraic, and "a" doesn't match "a^$1"
+ even though a==a^1.)
+> match(x*atan2(x,x^2),$0*atan2($0,$0^2));
+@{$0==x@}
+> match(atan2(y,x^2),atan2(y,$0));
+@{$0==x^2@}
+@end example
+
+@cindex @code{has()}
+A more general way to look for patterns in expressions is provided by the
+member function
+
+@example
+bool ex::has(const ex & pattern);
+@end example
+
+This function checks whether a pattern is matched by an expression itself or
+by any of its subexpressions.
+
+Again some examples in @command{ginsh} for illustration (in @command{ginsh},
+@code{has()} returns @samp{1} for @code{true} and @samp{0} for @code{false}):
+
+@example
+> has(x*sin(x+y+2*a),y);
+1
+> has(x*sin(x+y+2*a),x+y);
+0
+ (This is because in GiNaC, "x+y" is not a subexpression of "x+y+2*a" (which
+ has the subexpressions "x", "y" and "2*a".)
+> has(x*sin(x+y+2*a),x+y+$1);
+1
+ (But this is possible.)
+> has(x*sin(2*(x+y)+2*a),x+y);
+0
+ (This fails because "2*(x+y)" automatically gets converted to "2*x+2*y" of
+ which "x+y" is not a subexpression.)
+> has(x+1,x^$1);
+0
+ (Although x^1==x and x^0==1, neither "x" nor "1" are actually of the form
+ "x^something".)
+> has(4*x^2-x+3,$1*x);
+1
+> has(4*x^2+x+3,$1*x);
+0
+ (Another possible pitfall. The first expression matches because the term
+ "-x" has the form "(-1)*x" in GiNaC. To check whether a polynomial
+ contains a linear term you should use the coeff() function instead.)
+@end example
+
+@cindex @code{find()}
+The method
+
+@example
+bool ex::find(const ex & pattern, lst & found);
+@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
+@command{ginsh}, it returns an empty list):
+
+@example
+> find(1+x+x^2+x^3,x);
+@{x@}
+> find(1+x+x^2+x^3,y);
+@{@}
+> find(1+x+x^2+x^3,x^$1);
+@{x^3,x^2@}
+ (Note the absence of "x".)
+> expand((sin(x)+sin(y))*(a+b));
+sin(y)*a+sin(x)*b+sin(x)*a+sin(y)*b
+> find(%,sin($1));
+@{sin(y),sin(x)@}
+@end example
+
+@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
+used in the search patterns as well as in the replacement expressions, where
+they get replaced by the expressions matched by them. @code{subs()} doesn't
+know anything about algebra; it performs purely syntactic substitutions.
+
+Some examples:
+
+@example
+> subs(a^2+b^2+(x+y)^2,$1^2==$1^3);
+b^3+a^3+(x+y)^3
+> subs(a^4+b^4+(x+y)^4,$1^2==$1^3);
+b^4+a^4+(x+y)^4
+> subs((a+b+c)^2,a+b==x);
+(a+b+c)^2
+> subs((a+b+c)^2,a+b+$1==x+$1);
+(x+c)^2
+> subs(a+2*b,a+b==x);
+a+2*b
+> subs(4*x^3-2*x^2+5*x-1,x==a);
+-1+5*a-2*a^2+4*a^3
+> subs(4*x^3-2*x^2+5*x-1,x^$0==a^$0);
+-1+5*x-2*a^2+4*a^3
+> subs(sin(1+sin(x)),sin($1)==cos($1));
+cos(1+cos(x))
+> expand(subs(a*sin(x+y)^2+a*cos(x+y)^2+b,cos($1)^2==1-sin($1)^2));
+a+b
+@end example
+
+The last example would be written in C++ in this way:
+
+@example
+@{
+ symbol a("a"), b("b"), x("x"), y("y");
+ e = a*pow(sin(x+y), 2) + a*pow(cos(x+y), 2) + b;
+ e = e.subs(pow(cos(wild()), 2) == 1-pow(sin(wild()), 2));
+ cout << e.expand() << endl;
+ // -> a+b
+@}
+@end example
+
+
+@node Applying a Function on Subexpressions, Polynomial Arithmetic, Pattern Matching and Advanced Substitutions, Methods and Functions
+@c node-name, next, previous, up
+@section Applying a Function on Subexpressions
+@cindex Tree traversal
+@cindex @code{map()}
+
+Sometimes you may want to perform an operation on specific parts of an
+expression while leaving the general structure of it intact. An example
+of this would be a matrix trace operation: the trace of a sum is the sum
+of the traces of the individual terms. That is, the trace should @dfn{map}
+on the sum, by applying itself to each of the sum's operands. It is possible
+to do this manually which usually results in code like this:
+
+@example
+ex calc_trace(ex e)
+@{
+ if (is_a<matrix>(e))
+ return ex_to<matrix>(e).trace();
+ else if (is_a<add>(e)) @{
+ ex sum = 0;
+ for (unsigned i=0; i<e.nops(); i++)
+ sum += calc_trace(e.op(i));
+ return sum;
+ @} else if (is_a<mul>)(e)) @{
+ ...
+ @} else @{
+ ...
+ @}
+@}
+@end example
+
+This is, however, slightly inefficient (if the sum is very large it can take
+a long time to add the terms one-by-one), and its applicability is limited to
+a rather small class of expressions. If @code{calc_trace()} is called with
+a relation or a list as its argument, you will probably want the trace to
+be taken on both sides of the relation or of all elements of the list.
+
+GiNaC offers the @code{map()} method to aid in the implementation of such
+operations:
+
+@example
+ex ex::map(map_function & f) const;
+ex ex::map(ex (*f)(const ex & e)) const;
+@end example
+
+In the first (preferred) form, @code{map()} takes a function object that
+is subclassed from the @code{map_function} class. In the second form, it
+takes a pointer to a function that accepts and returns an expression.
+@code{map()} constructs a new expression of the same type, applying the
+specified function on all subexpressions (in the sense of @code{op()}),
+non-recursively.
+
+The use of a function object makes it possible to supply more arguments to
+the function that is being mapped, or to keep local state information.
+The @code{map_function} class declares a virtual function call operator
+that you can overload. Here is a sample implementation of @code{calc_trace()}
+that uses @code{map()} in a recursive fashion:
+
+@example
+struct calc_trace : public map_function @{
+ ex operator()(const ex &e)
+ @{
+ if (is_a<matrix>(e))
+ return ex_to<matrix>(e).trace();
+ else if (is_a<mul>(e)) @{
+ ...
+ @} else
+ return e.map(*this);
+ @}
+@};
+@end example
+
+This function object could then be used like this:
+
+@example
+@{
+ ex M = ... // expression with matrices
+ calc_trace do_trace;
+ ex tr = do_trace(M);
+@}
+@end example
+
+Here is another example for you to meditate over. It removes quadratic
+terms in a variable from an expanded polynomial:
+
+@example
+struct map_rem_quad : public map_function @{
+ ex var;
+ map_rem_quad(const ex & var_) : var(var_) @{@}
+
+ ex operator()(const ex & e)
+ @{
+ if (is_a<add>(e) || is_a<mul>(e))
+ return e.map(*this);
+ else if (is_a<power>(e) &&
+ e.op(0).is_equal(var) && e.op(1).info(info_flags::even))
+ return 0;
+ else
+ return e;
+ @}
+@};
+
+...
+
+@{
+ symbol x("x"), y("y");
+
+ ex e;
+ for (int i=0; i<8; i++)
+ e += pow(x, i) * pow(y, 8-i) * (i+1);
+ cout << e << endl;
+ // -> 4*y^5*x^3+5*y^4*x^4+8*y*x^7+7*y^2*x^6+2*y^7*x+6*y^3*x^5+3*y^6*x^2+y^8
+
+ map_rem_quad rem_quad(x);
+ cout << rem_quad(e) << endl;
+ // -> 4*y^5*x^3+8*y*x^7+2*y^7*x+6*y^3*x^5+y^8
+@}
+@end example
+
+@command{ginsh} offers a slightly different implementation of @code{map()}
+that allows applying algebraic functions to operands. The second argument
+to @code{map()} is an expression containing the wildcard @samp{$0} which
+acts as the placeholder for the operands:
+
+@example
+> map(a*b,sin($0));
+sin(a)*sin(b)
+> map(a+2*b,sin($0));
+sin(a)+sin(2*b)
+> map(@{a,b,c@},$0^2+$0);
+@{a^2+a,b^2+b,c^2+c@}
+@end example
+
+Note that it is only possible to use algebraic functions in the second
+argument. You can not use functions like @samp{diff()}, @samp{op()},
+@samp{subs()} etc. because these are evaluated immediately:
+
+@example
+> map(@{a,b,c@},diff($0,a));
+@{0,0,0@}
+ This is because "diff($0,a)" evaluates to "0", so the command is equivalent
+ to "map(@{a,b,c@},0)".
+@end example
+
+
+@node Polynomial Arithmetic, Rational Expressions, Applying a Function on Subexpressions, Methods and Functions
+@c node-name, next, previous, up
+@section Polynomial arithmetic
+
+@subsection Expanding and collecting
+@cindex @code{expand()}
+@cindex @code{collect()}
+
+A polynomial in one or more variables has many equivalent
+representations. Some useful ones serve a specific purpose. Consider
+for example the trivariate polynomial @math{4*x*y + x*z + 20*y^2 +
+21*y*z + 4*z^2} (written down here in output-style). It is equivalent
+to the factorized polynomial @math{(x + 5*y + 4*z)*(4*y + z)}. Other
+representations are the recursive ones where one collects for exponents
+in one of the three variable. Since the factors are themselves
+polynomials in the remaining two variables the procedure can be
+repeated. In our example, two possibilities would be @math{(4*y + z)*x
++ 20*y^2 + 21*y*z + 4*z^2} and @math{20*y^2 + (21*z + 4*x)*y + 4*z^2 +
+x*z}.
+
+To bring an expression into expanded form, its method
+
+@example
+ex ex::expand();
+@end example
+
+may be called. In our example above, this corresponds to @math{4*x*y +
+x*z + 20*y^2 + 21*y*z + 4*z^2}. Again, since the canonical form in
+GiNaC is not easily guessable you should be prepared to see different
+orderings of terms in such sums!
+
+Another useful representation of multivariate polynomials is as a
+univariate polynomial in one of the variables with the coefficients
+being polynomials in the remaining variables. The method
+@code{collect()} accomplishes this task:
+
+@example
+ex ex::collect(const ex & s, bool distributed = false);
+@end example
+
+The first argument to @code{collect()} can also be a list of objects in which
+case the result is either a recursively collected polynomial, or a polynomial
+in a distributed form with terms like @math{c*x1^e1*...*xn^en}, as specified
+by the @code{distributed} flag.
+
+Note that the original polynomial needs to be in expanded form (for the
+variables concerned) in order for @code{collect()} to be able to find the
+coefficients properly.
+
+The following @command{ginsh} transcript shows an application of @code{collect()}
+together with @code{find()}:
+
+@example
+> a=expand((sin(x)+sin(y))*(1+p+q)*(1+d));
+d*p*sin(x)+p*sin(x)+q*d*sin(x)+q*sin(y)+d*sin(x)+q*d*sin(y)+sin(y)+d*sin(y)+q*sin(x)+d*sin(y)*p+sin(x)+sin(y)*p
+> collect(a,@{p,q@});
+d*sin(x)+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*p+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*q+sin(y)+d*sin(y)+sin(x)
+> collect(a,find(a,sin($1)));
+(1+q+d+q*d+d*p+p)*sin(y)+(1+q+d+q*d+d*p+p)*sin(x)
+> collect(a,@{find(a,sin($1)),p,q@});
+(1+(1+d)*p+d+q*(1+d))*sin(x)+(1+(1+d)*p+d+q*(1+d))*sin(y)
+> collect(a,@{find(a,sin($1)),d@});
+(1+q+d*(1+q+p)+p)*sin(y)+(1+q+d*(1+q+p)+p)*sin(x)
+@end example
+
+@subsection Degree and coefficients
+@cindex @code{degree()}
+@cindex @code{ldegree()}
+@cindex @code{coeff()}
+
+The degree and low degree of a polynomial can be obtained using the two
+methods
+
+@example
+int ex::degree(const ex & s);
+int ex::ldegree(const ex & s);
+@end example
+
+These functions only work reliably if the input polynomial is collected in
+terms of the object @samp{s}. Otherwise, they are only guaranteed to return
+the upper/lower bounds of the exponents. If you need accurate results, you
+have to call @code{expand()} and/or @code{collect()} on the input polynomial.
+For example
+
+@example
+> a=(x+1)^2-x^2;
+(1+x)^2-x^2;
+> degree(a,x);
+2
+> degree(expand(a),x);
+1
+@end example
+
+@code{degree()} also works on rational functions, returning the asymptotic
+degree:
+
+@example
+> degree((x+1)/(x^3+1),x);
+-2
+@end example
+
+If the input is not a polynomial or rational function in the variable @samp{s},
+the behavior of @code{degree()} and @code{ldegree()} is undefined.
+
+To extract a coefficient with a certain power from an expanded
+polynomial you use
+
+@example
+ex ex::coeff(const ex & s, int n);
+@end example
+
+You can also obtain the leading and trailing coefficients with the methods
+
+@example
+ex ex::lcoeff(const ex & s);
+ex ex::tcoeff(const ex & s);
+@end example
+
+which are equivalent to @code{coeff(s, degree(s))} and @code{coeff(s, ldegree(s))},
+respectively.
+
+An application is illustrated in the next example, where a multivariate
+polynomial is analyzed:
+
+@example
+@{
+ symbol x("x"), y("y");
+ ex PolyInp = 4*pow(x,3)*y + 5*x*pow(y,2) + 3*y
+ - pow(x+y,2) + 2*pow(y+2,2) - 8;
+ ex Poly = PolyInp.expand();
+