]> www.ginac.de Git - ginac.git/blobdiff - doc/tutorial/ginac.texi
documentation update
[ginac.git] / doc / tutorial / ginac.texi
index 0320878c6d7a07fe84c5790301ce84a49fe7a88c..98033e40767d1914fc7f8fded5e5a99f4a4127a5 100644 (file)
@@ -23,7 +23,7 @@
 This is a tutorial that documents GiNaC @value{VERSION}, an open
 framework for symbolic computation within the C++ programming language.
 
-Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2002 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
@@ -52,7 +52,7 @@ notice identical to this one.
 
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1999-2001 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2002 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
@@ -135,7 +135,7 @@ the near future.
 
 @section License
 The GiNaC framework for symbolic computation within the C++ programming
-language is Copyright @copyright{} 1999-2001 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2002 Johannes Gutenberg
 University Mainz, Germany.
 
 This program is free software; you can redistribute it and/or
@@ -455,15 +455,14 @@ installation.
 
 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 @acronym{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.  Perl is needed
-by the built process as well, since some of the source files are
-automatically generated by Perl scripts.  Last but not least, Bruno
-Haible's library @acronym{CLN} is extensively used and needs to be
-installed on your system.  Please get it either from
-@uref{ftp://ftp.santafe.edu/pub/gnu/}, from
+ANSI-standard @cite{ISO/IEC 14882:1998(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.  Perl is needed by the built
+process as well, since some of the source files are automatically
+generated by Perl scripts.  Last but not least, Bruno Haible's library
+CLN is extensively used and needs to be installed on your system.
+Please get it either from @uref{ftp://ftp.santafe.edu/pub/gnu/}, from
 @uref{ftp://ftpthep.physik.uni-mainz.de/pub/gnu/, GiNaC's FTP site} or
 from @uref{ftp://ftp.ilog.fr/pub/Users/haible/gnu/, Bruno Haible's FTP
 site} (it is covered by GPL) and install it prior to trying to install
@@ -553,9 +552,9 @@ $ ./configure
 @end example
 
 And here is a configuration for a private static GiNaC library with
-several components sitting in custom places (site-wide @acronym{GCC} and
-private @acronym{CLN}).  The compiler is persuaded to be picky and full
-assertions and debugging information are switched on:
+several components sitting in custom places (site-wide GCC and private
+CLN).  The compiler is persuaded to be picky and full assertions and
+debugging information are switched on:
 
 @example
 $ export CXX=/usr/local/gnu/bin/c++
@@ -893,25 +892,24 @@ can use the expression's @code{.subs()} method (@pxref{Substituting Expressions}
 @cindex CLN
 @cindex rational
 @cindex fraction
-For storing numerical things, GiNaC uses Bruno Haible's library
-@acronym{CLN}.  The classes therein serve as foundation classes for
-GiNaC.  @acronym{CLN} stands for Class Library for Numbers or
-alternatively for Common Lisp Numbers.  In order to find out more about
-@acronym{CLN}'s internals the reader is refered 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 @acronym{GMP}, which is an
+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
+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
 extremely fast library for arbitrary long integers and rationals as well
 as arbitrary precision floating point numbers.  It is very commonly used
-by several popular cryptographic applications.  @acronym{CLN} extends
-@acronym{GMP} by several useful things: First, it introduces the complex
-number field over either reals (i.e. floating point numbers with
-arbitrary precision) or rationals.  Second, it automatically converts
-rationals to integers if the denominator is unity and complex numbers to
-real numbers if the imaginary part vanishes and also correctly treats
-algebraic functions.  Third it provides good implementations of
-state-of-the-art algorithms for all trigonometric and hyperbolic
-functions as well as for calculation of some useful constants.
+by several popular cryptographic applications.  CLN extends GMP by
+several useful things: First, it introduces the complex number field
+over either reals (i.e. floating point numbers with arbitrary precision)
+or rationals.  Second, it automatically converts rationals to integers
+if the denominator is unity and complex numbers to real numbers if the
+imaginary part vanishes and also correctly treats algebraic functions.
+Third it provides good implementations of state-of-the-art algorithms
+for all trigonometric and hyperbolic functions as well as for
+calculation of some useful constants.
 
 The user can construct an object of class @code{numeric} in several
 ways.  The following example shows the four most important constructors.
@@ -933,10 +931,22 @@ int main()
     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
@@ -986,13 +996,22 @@ The above example prints the following output to screen:
 
 @example
 in 17 digits:
-0.333333333333333333
-3.14159265358979324
+0.33333333333333333334
+3.1415926535897932385
 in 60 digits:
-0.333333333333333333333333333333333333333333333333333333333333333333
-3.14159265358979323846264338327950288419716939937510582097494459231
+0.33333333333333333333333333333333333333333333333333333333333333333334
+3.1415926535897932384626433832795028841971693993751058209749445923078
 @end example
 
+@cindex rounding
+Note that the last number is not necessarily rounded as you would
+naively expect it to be rounded in the decimal system.  But note also,
+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
+differ with regard to actually computed digits.
+
 It should be clear that objects of class @code{numeric} should be used
 for constructing numbers or for doing arithmetic with them.  The objects
 one deals with most of the time are the polymorphic expressions @code{ex}.
@@ -1036,13 +1055,12 @@ 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.
-Internally, the underlying @acronym{CLN} is responsible for this
-behavior and we refer the reader to @acronym{CLN}'s documentation.
-Suffice to say that the same behavior applies to complex numbers as
-well as return values of certain functions.  Complex numbers are
-automatically converted to real numbers if the imaginary part becomes
-zero.  The full set of tests that can be applied is listed in the
-following table.
+Internally, the underlying CLN is responsible for this behavior and we
+refer the reader to CLN's documentation.  Suffice to say that
+the same behavior applies to complex numbers as well as return values of
+certain functions.  Complex numbers are automatically converted to real
+numbers if the imaginary part becomes zero.  The full set of tests that
+can be applied is listed in the following table.
 
 @cartouche
 @multitable @columnfractions .30 .70
@@ -1336,21 +1354,31 @@ second one in the range 0@dots{}@math{n-1}.
 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:
@@ -1364,27 +1392,32 @@ It is also possible to access the matrix elements in a linear fashion with
 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
 
@@ -1474,6 +1507,9 @@ general.
 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;
@@ -1860,9 +1896,9 @@ indices into a canonical order which allows for some immediate simplifications:
      // -> 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
@@ -1877,8 +1913,8 @@ 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
+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.
 
@@ -2363,28 +2399,29 @@ ex dirac_ONE(unsigned char rl = 0);
 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
@@ -2399,9 +2436,11 @@ 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
+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
 @{
@@ -3185,11 +3224,11 @@ Some examples:
 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
@@ -3296,7 +3335,7 @@ This function object could then be used like this:
 @}
 @end example
 
-Here is another example for you to meditate over. It removes quadratic
+Here is another example for you to meditate over.  It removes quadratic
 terms in a variable from an expanded polynomial:
 
 @example
@@ -3308,7 +3347,8 @@ struct map_rem_quad : public map_function @{
     @{
         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))
+        else if (is_a<power>(e) && 
+                 e.op(0).is_equal(var) && e.op(1).info(info_flags::even))
             return 0;
         else
             return e;
@@ -3436,9 +3476,34 @@ int ex::degree(const ex & s);
 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);
@@ -3619,28 +3684,32 @@ 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 system has an interface
-for this so called square-free factorization.  So we provide one, too:
+original polynomial and its derivatives.  Any decent system has an
+interface for this so called square-free factorization.  So we provide
+one, too:
 @example
 ex sqrfree(const ex & a, const lst & l = lst());
 @end example
-Here is an example that by the way illustrates how the result may depend
-on the order of differentiation:
+Here is an example that by the way illustrates how the exact form of the
+result may slightly depend on the order of differentiation, calling for
+some care with subsequent processing of the result:
 @example
     ...
     symbol x("x"), y("y");
-    ex BiVarPol = expand(pow(x-2*y*x,3) * pow(x+y,2) * (x-y));
+    ex BiVarPol = expand(pow(2-2*y,3) * pow(1+x*y,2) * pow(x-2*y,2) * (x+y));
 
     cout << sqrfree(BiVarPol, lst(x,y)) << endl;
-     // -> (y+x)^2*(-1+6*y+8*y^3-12*y^2)*(y-x)*x^3
+     // -> 8*(1-y)^3*(y*x^2-2*y+x*(1-2*y^2))^2*(y+x)
 
     cout << sqrfree(BiVarPol, lst(y,x)) << endl;
-     // -> (1-2*y)^3*(y+x)^2*(-y+x)*x^3
+     // -> 8*(1-y)^3*(-y*x^2+2*y+x*(-1+2*y^2))^2*(y+x)
 
     cout << sqrfree(BiVarPol) << endl;
      // -> depending on luck, any of the above
     ...
 @end example
+Note also, how factors with the same exponents are not fully factorized
+with this method.
 
 
 @node Rational Expressions, Symbolic Differentiation, Polynomial Arithmetic, Methods and Functions
@@ -3850,14 +3919,14 @@ Only calling the series method makes the last output simplify to
 @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
@@ -3875,7 +3944,7 @@ the order term off:
 #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));
@@ -3890,7 +3959,7 @@ int main()
     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;
     @}
@@ -4250,19 +4319,22 @@ and have the @samp{x} and @samp{y} correspond to the symbols @code{x} and
 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:
 
@@ -4506,7 +4578,7 @@ evaluate themselves numerically to a precision declared at runtime
 generally.  This ought to be fixed.  However, doing numerical
 computations with GiNaC's quite abstract classes is doomed to be
 inefficient.  For this purpose, the underlying foundation classes
-provided by @acronym{CLN} are much better suited.
+provided by CLN are much better suited.
 
 
 @node Symbolic functions, Adding classes, What does not belong into GiNaC, Extending GiNaC
@@ -5183,9 +5255,10 @@ 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 @acronym{Cint} C++ interpreter has been put
-together (called @acronym{GiNaC-cint}) that allows an interactive
-scripting interface consistent with the C++ language.
+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.
 
 @item
 seamless integration: it is somewhere between difficult and impossible
@@ -5227,15 +5300,17 @@ not planned for the near future).
 portability: While the GiNaC library itself is designed to avoid any
 platform dependent features (it should compile on any ANSI compliant C++
 compiler), the currently used version of the CLN library (fast large
-integer and arbitrary precision arithmetics) can be compiled only on
-systems with a recently new C++ compiler from the GNU Compiler
-Collection (@acronym{GCC}).@footnote{This is because CLN uses
-PROVIDE/REQUIRE like macros to let the compiler gather all static
-initializations, which works for GNU C++ only.}  GiNaC uses recent
-language features like explicit constructors, mutable members, RTTI,
-@code{dynamic_cast}s and STL, so ANSI compliance is meant literally.
-Recent @acronym{GCC} versions starting at 2.95, although itself not yet
-ANSI compliant, support all needed features.
+integer and arbitrary precision arithmetics) can only by compiled
+without hassle on systems with the C++ compiler from the GNU Compiler
+Collection (GCC).@footnote{This is because CLN uses PROVIDE/REQUIRE like
+macros to let the compiler gather all static initializations, which
+works for GNU C++ only.  Feel free to contact the authors in case you
+really believe that you need to use a different compiler.  We have
+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.
     
 @end itemize