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
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
@{
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);
+> 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);
+> 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
int ex::ldegree(const ex & s);
@end example
-which also work reliably on non-expanded input polynomials (they even work
-on rational functions, returning the asymptotic degree). To extract
-a coefficient with a certain power from an expanded polynomial you use
+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);
@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;
@}
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: