]> www.ginac.de Git - ginac.git/blobdiff - doc/tutorial/ginac.texi
Documentation: Update branch cut convention
[ginac.git] / doc / tutorial / ginac.texi
index c92e38dcf9b8e6112b9919d9cbab8433d4b52964..a767d57cd5fb1c389db5c81d643591631023e1dd 100644 (file)
@@ -15,6 +15,7 @@
 
 @include version.texi
 
+@dircategory Mathematics
 @direntry
 * ginac: (ginac).                   C++ library for symbolic computation.
 @end direntry
@@ -23,7 +24,7 @@
 This is a tutorial that documents GiNaC @value{VERSION}, an open
 framework for symbolic computation within the C++ programming language.
 
-Copyright (C) 1999-2007 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2011 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
@@ -51,7 +52,7 @@ notice identical to this one.
 
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1999-2007 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2011 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
@@ -134,7 +135,7 @@ the near future.
 
 @section License
 The GiNaC framework for symbolic computation within the C++ programming
-language is Copyright @copyright{} 1999-2007 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2011 Johannes Gutenberg
 University Mainz, Germany.
 
 This program is free software; you can redistribute it and/or
@@ -552,7 +553,7 @@ environment variable, like optimization, debugging information and
 warning levels.  If omitted, it defaults to @option{-g
 -O2}.@footnote{The @command{configure} script is itself generated from
 the file @file{configure.ac}.  It is only distributed in packaged
-releases of GiNaC.  If you got the naked sources, e.g. from CVS, you
+releases of GiNaC.  If you got the naked sources, e.g. from git, you
 must generate @command{configure} along with the various
 @file{Makefile.in} by using the @command{autoreconf} utility.  This will
 require a fair amount of support from your local toolchain, though.}
@@ -920,7 +921,12 @@ To get an idea about what kinds of symbolic composites may be built we
 have a look at the most important classes in the class hierarchy and
 some of the relations among the classes:
 
+@ifnotinfo
 @image{classhierarchy}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
 
 The abstract classes shown here (the ones without drop-shadow) are of no
 interest for the user.  They are used internally in order to avoid code
@@ -1473,7 +1479,7 @@ evaluated immediately:
 @tab modulus in positive representation (in the range @code{[0, abs(b)-1]} with the sign of b, or zero)
 @cindex @code{mod()}
 @item @code{smod(a, b)}
-@tab modulus in symmetric representation (in the range @code{[-iquo(abs(b)-1, 2), iquo(abs(b), 2)]})
+@tab modulus in symmetric representation (in the range @code{[-iquo(abs(b), 2), iquo(abs(b), 2)]})
 @cindex @code{smod()}
 @item @code{irem(a, b)}
 @tab integer remainder (has the sign of @math{a}, or is zero)
@@ -2321,12 +2327,12 @@ get an error message from this but you will probably not be able to do
 anything useful with it.
 
 @cindex @code{get_value()}
-@cindex @code{get_dimension()}
+@cindex @code{get_dim()}
 The methods
 
 @example
 ex idx::get_value();
-ex idx::get_dimension();
+ex idx::get_dim();
 @end example
 
 return the value and dimension of an @code{idx} object. If you have an index
@@ -3034,8 +3040,8 @@ Information about the commutativity of an object or expression can be
 obtained with the two member functions
 
 @example
-unsigned ex::return_type() const;
-unsigned ex::return_type_tinfo() const;
+unsigned      ex::return_type() const;
+return_type_t ex::return_type_tinfo() const;
 @end example
 
 The @code{return_type()} function returns one of three values (defined in
@@ -3056,31 +3062,27 @@ expressions in GiNaC:
   @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, but may vary every time a
-GiNaC program is being run (it is dynamically assigned on start-up).
+The @code{return_type_tinfo()} method returns an object of type
+@code{return_type_t} that contains information about the type of the expression
+and, if given, its representation label (see section on dirac gamma matrices for
+more details).  The objects of type @code{return_type_t} can be tested for
+equality to test whether two expressions belong to the same category and
+therefore may not commute.
 
 Here are a couple of examples:
 
 @cartouche
-@multitable @columnfractions 0.33 0.33 0.34
-@item @strong{Expression} @tab @strong{@code{return_type()}} @tab @strong{@code{return_type_tinfo()}}
-@item @code{42} @tab @code{commutative} @tab -
-@item @code{2*x-y} @tab @code{commutative} @tab -
-@item @code{dirac_ONE()} @tab @code{noncommutative} @tab @code{TINFO_clifford}
-@item @code{dirac_gamma(mu)*dirac_gamma(nu)} @tab @code{noncommutative} @tab @code{TINFO_clifford}
-@item @code{2*color_T(a)} @tab @code{noncommutative} @tab @code{TINFO_color}
-@item @code{dirac_ONE()*color_T(a)} @tab @code{noncommutative_composite} @tab -
+@multitable @columnfractions .6 .4
+@item @strong{Expression} @tab @strong{@code{return_type()}}
+@item @code{42} @tab @code{commutative}
+@item @code{2*x-y} @tab @code{commutative}
+@item @code{dirac_ONE()} @tab @code{noncommutative}
+@item @code{dirac_gamma(mu)*dirac_gamma(nu)} @tab @code{noncommutative}
+@item @code{2*color_T(a)} @tab @code{noncommutative}
+@item @code{dirac_ONE()*color_T(a)} @tab @code{noncommutative_composite}
 @end multitable
 @end cartouche
 
-Note: the @code{return_type_tinfo()} of Clifford objects is only equal to
-@code{TINFO_clifford} for objects with a representation label of zero.
-Other representation labels yield a different @code{return_type_tinfo()},
-but it's the same for any two objects with the same label. This is also true
-for color objects.
-
 A last note: With the exception of matrices, positive integer powers of
 non-commutative objects are automatically expanded in GiNaC. For example,
 @code{pow(a*b, 2)} becomes @samp{a*b*a*b} if @samp{a} and @samp{b} are
@@ -3864,7 +3866,7 @@ bool is_a<T>(const ex & e);
 bool is_exactly_a<T>(const ex & e);
 bool ex::info(unsigned flag);
 unsigned ex::return_type() const;
-unsigned ex::return_type_tinfo() const;
+return_type_t ex::return_type_tinfo() const;
 @end example
 
 When the test made by @code{is_a<T>()} returns true, it is safe to call
@@ -4261,7 +4263,7 @@ In the first form, @code{subs()} accepts a relational of the form
 @{
     symbol x("x"), y("y");
 
-    ex e1 = 2*x^2-4*x+3;
+    ex e1 = 2*x*x-4*x+3;
     cout << "e1(7) = " << e1.subs(x == 7) << endl;
      // -> 73
 
@@ -4407,17 +4409,14 @@ 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);
+bool ex::match(const ex & pattern, exmap& repls);
 @end example
 
 This function returns @code{true} when the expression matches the pattern
 and @code{false} if it doesn't. If used in the second form, the actual
-subexpressions matched by the wildcards get returned in the @code{repls}
-object as a list of relations of the form @samp{wildcard == expression}.
-If @code{match()} returns false, the state of @code{repls} is undefined.
-For reproducible results, the list should be empty when passed to
-@code{match()}, but it is also possible to find similarities in multiple
-expressions by passing in the result of a previous match.
+subexpressions matched by the wildcards get returned in the associative
+array @code{repls} with @samp{wildcard} as a key. If @code{match()}
+returns false,  @code{repls} remains unmodified.
 
 The matching algorithm works as follows:
 
@@ -4556,7 +4555,7 @@ Again some examples in @command{ginsh} for illustration (in @command{ginsh},
 The method
 
 @example
-bool ex::find(const ex & pattern, lst & found);
+bool ex::find(const ex & pattern, exset& found);
 @end example
 
 works a bit like @code{has()} but it doesn't stop upon finding the first
@@ -4638,7 +4637,7 @@ often as is possible without getting negative exponents. For example
 @code{(x^(-3)*y^(-2)*z).subs(1/(x*y)==c, subs_options::algebraic)} will
 return @code{x^(-1)*c^2*z}. 
 
-@strong{Note:} this only works for multiplications
+@strong{Please notice:} this only works for multiplications
 and not for locating @code{x+y} within @code{x+y+z}.
 
 
@@ -5351,13 +5350,7 @@ int main()
 @cindex factorization
 @cindex @code{sqrfree()}
 
-GiNaC still lacks proper factorization support.  Some form of
-factorization is, however, easily implemented by noting that factors
-appearing in a polynomial with power two or more also appear in the
-derivative and hence can easily be found by computing the GCD of the
-original polynomial and its derivatives.  Any decent system has an
-interface for this so called square-free factorization.  So we provide
-one, too:
+Square-free decomposition is available in GiNaC:
 @example
 ex sqrfree(const ex & a, const lst & l = lst());
 @end example
@@ -5382,6 +5375,57 @@ some care with subsequent processing of the result:
 Note also, how factors with the same exponents are not fully factorized
 with this method.
 
+@subsection Polynomial factorization
+@cindex factorization
+@cindex polynomial factorization
+@cindex @code{factor()}
+
+Polynomials can also be fully factored with a call to the function
+@example
+ex factor(const ex & a, unsigned int options = 0);
+@end example
+The factorization works for univariate and multivariate polynomials with
+rational coefficients. The following code snippet shows its capabilities:
+@example
+    ...
+    cout << factor(pow(x,2)-1) << endl;
+     // -> (1+x)*(-1+x)
+    cout << factor(expand((x-y*z)*(x-pow(y,2)-pow(z,3))*(x+y+z))) << endl;
+     // -> (y+z+x)*(y*z-x)*(y^2-x+z^3)
+    cout << factor(pow(x,2)-1+sin(pow(x,2)-1)) << endl;
+     // -> -1+sin(-1+x^2)+x^2
+    ...
+@end example
+The results are as expected except for the last one where no factorization
+seems to have been done. This is due to the default option
+@command{factor_options::polynomial} (equals zero) to @command{factor()}, which
+tells GiNaC to try a factorization only if the expression is a valid polynomial.
+In the shown example this is not the case, because one term is a function.
+
+There exists a second option @command{factor_options::all}, which tells GiNaC to
+ignore non-polynomial parts of an expression and also to look inside function
+arguments. With this option the example gives:
+@example
+    ...
+    cout << factor(pow(x,2)-1+sin(pow(x,2)-1), factor_options::all)
+         << endl;
+     // -> (-1+x)*(1+x)+sin((-1+x)*(1+x))
+    ...
+@end example
+GiNaC's factorization functions cannot handle algebraic extensions. Therefore
+the following example does not factor:
+@example
+    ...
+    cout << factor(pow(x,2)-2) << endl;
+     // -> -2+x^2  and not  (x-sqrt(2))*(x+sqrt(2))
+    ...
+@end example
+Factorization is useful in many applications. A lot of algorithms in computer
+algebra depend on the ability to factor a polynomial. Of course, factorization
+can also be used to simplify expressions, but it is costly and applying it to
+complicated expressions (high degrees or many terms) may consume far too much
+time. So usually, looking for a GCD at strategic points in a calculation is the
+cheaper and more appropriate alternative.
 
 @node Rational expressions, Symbolic differentiation, Polynomial arithmetic, Methods and functions
 @c    node-name, next, previous, up
@@ -5868,20 +5912,19 @@ GiNaC contains the following predefined mathematical functions:
 @end cartouche
 
 @cindex branch cut
-For functions that have a branch cut in the complex plane GiNaC follows
-the conventions for C++ as defined in the ANSI standard as far as
-possible.  In particular: the natural logarithm (@code{log}) and the
-square root (@code{sqrt}) both have their branch cuts running along the
-negative real axis where the points on the axis itself belong to the
-upper part (i.e. continuous with quadrant II).  The inverse
-trigonometric and hyperbolic functions are not defined for complex
-arguments by the C++ standard, however.  In GiNaC we follow the
-conventions used by CLN, which in turn follow the carefully designed
-definitions in the Common Lisp standard.  It should be noted that this
-convention is identical to the one used by the C99 standard and by most
-serious CAS.  It is to be expected that future revisions of the C++
-standard incorporate these functions in the complex domain in a manner
-compatible with C99.
+For functions that have a branch cut in the complex plane, GiNaC
+follows the conventions of C/C++ for systems that do not support a
+signed zero.  In particular: the natural logarithm (@code{log}) and
+the square root (@code{sqrt}) both have their branch cuts running
+along the negative real axis. The @code{asin}, @code{acos}, and
+@code{atanh} functions all have two branch cuts starting at +/-1 and
+running away towards infinity along the real axis. The @code{atan} and
+@code{asinh} functions have two branch cuts starting at +/-i and
+running away towards infinity along the imaginary axis. The
+@code{acosh} function has one branch cut starting at +1 and running
+towards -infinity.  These functions are continuous as the branch cut
+is approached coming around the finite endpoint of the cut in a
+counter clockwise direction.
 
 @node Multiple polylogarithms, Complex expressions, Built-in functions, Methods and functions
 @c    node-name, next, previous, up
@@ -6105,12 +6148,13 @@ For example,
 @}
 @end example
 
-If you declare your own GiNaC functions, then they will conjugate themselves
-by conjugating their arguments. This is the default strategy. If you want to
-change this behavior, you have to supply a specialized conjugation method
-for your function (see @ref{Symbolic functions} and the GiNaC source-code
-for @code{abs} as an example). Also, specialized methods can be provided
-to take real and imaginary parts of user-defined functions.
+If you declare your own GiNaC functions and you want to conjugate them, you
+will have to supply a specialized conjugation method for them (see
+@ref{Symbolic functions} and the GiNaC source-code for @code{abs} as an
+example). GiNaC does not automatically conjugate user-supplied functions
+by conjugating their arguments because this would be incorrect on branch
+cuts. Also, specialized methods can be provided to take real and imaginary
+parts of user-defined functions.
 
 @node Solving linear systems of equations, Input/output, Complex expressions, Methods and functions
 @c    node-name, next, previous, up
@@ -6377,22 +6421,72 @@ and have the @samp{x} and @samp{y} correspond to the symbols @code{x} and
 @code{y} you defined in your program and there is no way to specify the
 desired symbols to the @code{>>} stream input operator.
 
-Instead, GiNaC lets you construct an expression from a string, specifying the
-list of symbols to be used:
+Instead, GiNaC lets you read an expression from a stream or a string,
+specifying the mapping between the input strings and symbols to be used:
 
 @example
 @{
-    symbol x("x"), y("y");
-    ex e("2*x+sin(y)", lst(x, y));
+    symbol x, y;
+    symtab table;
+    table["x"] = x;
+    table["y"] = y;
+    parser reader(table);
+    ex e = reader("2*x+sin(y)");
 @}
 @end example
 
 The input syntax is the same as that used by @command{ginsh} and the stream
-output operator @code{<<}. The symbols in the string are matched by name to
-the symbols in the list and if GiNaC encounters a symbol not specified in
-the list it will throw an exception.
+output operator @code{<<}. Matching between the input strings and expressions
+is given by @samp{table}. The @samp{table} in this example instructs GiNaC
+to substitute any input substring ``x'' with symbol @code{x}. Likewise,
+the substring ``y'' will be replaced with symbol @code{y}. It's also possible
+to map input (sub)strings to arbitrary expressions:
 
-With this constructor, it's also easy to implement interactive GiNaC programs:
+@example
+@{
+    symbol x, y;
+    symtab table;
+    table["x"] = x+log(y)+1;
+    parser reader(table);
+    ex e = reader("5*x^3 - x^2");
+    // e = 5*(x+log(y)+1)^3 + (x+log(y)+1)^2
+@}
+@end example
+
+If no mapping is specified for a particular string GiNaC will create a symbol
+with corresponding name. Later on you can obtain all parser generated symbols
+with @code{get_syms()} method:
+
+@example
+@{
+    parser reader;
+    ex e = reader("2*x+sin(y)");
+    symtab table = reader.get_syms();
+    symbol x = reader["x"];
+    symbol y = reader["y"];
+@}
+@end example
+
+Sometimes you might want to prevent GiNaC from inserting these extra symbols
+(for example, you want treat an unexpected string in the input as an error).
+
+@example
+@{
+       symtab table;
+       table["x"] = symbol();
+       parser reader(table);
+       parser.strict = true;
+       ex e;
+       try @{
+               e = reader("2*x+sin(y)");
+       @} catch (parse_error& err) @{
+               cerr << err.what() << endl;
+               // prints "unknown symbol "y" in the input"
+       @}
+@}
+@end example
+
+With this parser, it's also easy to implement interactive GiNaC programs:
 
 @example
 #include <iostream>
@@ -6404,19 +6498,19 @@ using namespace GiNaC;
 
 int main()
 @{
-    symbol x("x");
-    string s;
-
-    cout << "Enter an expression containing 'x': ";
-    getline(cin, s);
-
-    try @{
-        ex e(s, lst(x));
-        cout << "The derivative of " << e << " with respect to x is ";
-        cout << e.diff(x) << ".\n";
-    @} catch (exception &p) @{
-        cerr << p.what() << endl;
-    @}
+       cout << "Enter an expression containing 'x': " << flush;
+       parser reader;
+
+       try @{
+               ex e = reader(cin);
+               symtab table = reader.get_syms();
+               symbol x = table.find("x") != table.end() ? 
+                          ex_to<symbol>(table["x"]) : symbol("x");
+               cout << "The derivative of " << e << " with respect to x is ";
+               cout << e.diff(x) << "." << endl;
+       @} catch (exception &p) @{
+               cerr << p.what() << endl;
+       @}
 @}
 @end example
 
@@ -6475,7 +6569,7 @@ pointer types at the moment:
 @cindex Monte Carlo integration
 @code{FUNCP_2P} allows for two variables in the expression. @code{FUNCP_CUBA} is
 the correct type to be used with the CUBA library
-(@uref{http://www.feynarts/cuba}) for numerical integrations. The details for the
+(@uref{http://www.feynarts.de/cuba}) for numerical integrations. The details for the
 parameters of @code{FUNCP_CUBA} are explained in the CUBA manual.
 
 @cindex compile_ex
@@ -7020,15 +7114,30 @@ This tells @code{evalf()} to not recursively evaluate the parameters of the
 function before calling the @code{evalf_func()}.
 
 @example
-set_return_type(unsigned return_type, unsigned return_type_tinfo)
+set_return_type(unsigned return_type, const return_type_t * return_type_tinfo)
 @end example
 
 This allows you to explicitly specify the commutation properties of the
 function (@xref{Non-commutative objects}, for an explanation of
-(non)commutativity in GiNaC). For example, you can use
-@code{set_return_type(return_types::noncommutative, TINFO_matrix)} to make
-GiNaC treat your function like a matrix. By default, functions inherit the
-commutation properties of their first argument.
+(non)commutativity in GiNaC). For example, with an object of type
+@code{return_type_t} created like
+
+@example
+return_type_t my_type = make_return_type_t<matrix>();
+@end example
+
+you can use @code{set_return_type(return_types::noncommutative, &my_type)} to
+make GiNaC treat your function like a matrix. By default, functions inherit the
+commutation properties of their first argument. The utilized template function
+@code{make_return_type_t<>()} 
+
+@example
+template<typename T> inline return_type_t make_return_type_t(const unsigned rl = 0)
+@end example
+
+can also be called with an argument specifying the representation label of the
+non-commutative function (see section on dirac gamma matrices for more
+details).
 
 @example
 set_symmetry(const symmetry & s)
@@ -7777,44 +7886,40 @@ representing tensor products is more involved but this section should give
 you enough information so you can consult the source to GiNaC's predefined
 classes if you want to implement something more complicated.
 
-@subsection GiNaC's run-time type information system
+@subsection Hierarchy of algebraic classes.
 
 @cindex hierarchy of classes
-@cindex RTTI
 All algebraic classes (that is, all classes that can appear in expressions)
 in GiNaC are direct or indirect subclasses of the class @code{basic}. So a
-@code{basic *} (which is essentially what an @code{ex} is) represents a
-generic pointer to an algebraic class. Occasionally it is necessary to find
-out what the class of an object pointed to by a @code{basic *} really is.
-Also, for the unarchiving of expressions it must be possible to find the
-@code{unarchive()} function of a class given the class name (as a string). A
-system that provides this kind of information is called a run-time type
-information (RTTI) system. The C++ language provides such a thing (see the
-standard header file @file{<typeinfo>}) but for efficiency reasons GiNaC
-implements its own, simpler RTTI.
-
-The RTTI in GiNaC is based on two mechanisms:
-
+@code{basic *} represents a generic pointer to an algebraic class. Working
+with such pointers directly is cumbersome (think of memory management), hence
+GiNaC wraps them into @code{ex} (@pxref{Expressions are reference counted}).
+To make such wrapping possible every algebraic class has to implement several
+methods. Visitors (@pxref{Visitors and tree traversal}), printing, and 
+(un)archiving (@pxref{Input/output}) require helper methods too. But don't
+worry, most of the work is simplified by the following macros (defined
+in @file{registrar.h}):
 @itemize @bullet
+@item @code{GINAC_DECLARE_REGISTERED_CLASS}
+@item @code{GINAC_IMPLEMENT_REGISTERED_CLASS}
+@item @code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT}
+@end itemize
 
-@item
-The @code{basic} class declares a member variable @code{tinfo_key} which
-holds a variable of @code{tinfo_t} type (which is actually just
-@code{const void*}) that identifies the object's class.
-
-@item
-By means of some clever tricks with static members, GiNaC maintains a list
-of information for all classes derived from @code{basic}. The information
-available includes the class names, the @code{tinfo_key}s, and pointers
-to the unarchiving functions. This class registry is defined in the
-@file{registrar.h} header file.
+The @code{GINAC_DECLARE_REGISTERED_CLASS} macro inserts declarations
+required for memory management, visitors, printing, and (un)archiving.
+It takes the name of the class and its direct superclass as arguments.
+The @code{GINAC_DECLARE_REGISTERED_CLASS} should be the first line after
+the opening brace of the class definition.
 
-@end itemize
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} takes the same arguments as
+@code{GINAC_DECLARE_REGISTERED_CLASS}. It initializes certain static
+members of a class so that printing and (un)archiving works. The
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} may appear anywhere else in
+the source (at global scope, of course, not inside a function).
 
-The disadvantage of this proprietary RTTI implementation is that there's
-a little more to do when implementing new classes (C++'s RTTI works more
-or less automatically) but don't worry, most of the work is simplified by
-macros.
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT} is a variant of
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS}. It allows specifying additional
+options, such as custom printing functions.
 
 @subsection A minimalistic example
 
@@ -7822,7 +7927,8 @@ Now we will start implementing a new class @code{mystring} that allows
 placing character strings in algebraic expressions (this is not very useful,
 but it's just an example). This class will be a direct subclass of
 @code{basic}. You can use this sample implementation as a starting point
-for your own classes.
+for your own classes @footnote{The self-contained source for this example is
+included in GiNaC, see the @file{doc/examples/mystring.cpp} file.}.
 
 The code snippets given here assume that you have included some header files
 as follows:
@@ -7839,7 +7945,7 @@ using namespace GiNaC;
 
 Now we can write down the class declaration. The class stores a C++
 @code{string} and the user shall be able to construct a @code{mystring}
-object from a C or C++ string:
+object from a string:
 
 @example
 class mystring : public basic
@@ -7848,7 +7954,6 @@ class mystring : public basic
   
 public:
     mystring(const string & s);
-    mystring(const char * s);
 
 private:
     string str;
@@ -7857,24 +7962,12 @@ private:
 GINAC_IMPLEMENT_REGISTERED_CLASS(mystring, basic)
 @end example
 
-The @code{GINAC_DECLARE_REGISTERED_CLASS} and @code{GINAC_IMPLEMENT_REGISTERED_CLASS}
-macros are defined in @file{registrar.h}. They take the name of the class
-and its direct superclass as arguments and insert all required declarations
-for the RTTI system. The @code{GINAC_DECLARE_REGISTERED_CLASS} should be
-the first line after the opening brace of the class definition. The
-@code{GINAC_IMPLEMENT_REGISTERED_CLASS} may appear anywhere else in the
-source (at global scope, of course, not inside a function).
-
-@code{GINAC_DECLARE_REGISTERED_CLASS} contains, among other things the
-declarations of the default constructor and a couple of other functions that
-are required. It also defines a type @code{inherited} which refers to the
-superclass so you don't have to modify your code every time you shuffle around
-the class hierarchy. @code{GINAC_IMPLEMENT_REGISTERED_CLASS} registers the
-class with the GiNaC RTTI (there is also a
-@code{GINAC_IMPLEMENT_REGISTERED_CLASS_OPT} which allows specifying additional
-options for the class, and which we will be using instead in a few minutes).
-
-Now there are seven member functions we have to implement to get a working
+The @code{GINAC_DECLARE_REGISTERED_CLASS} macro insert declarations required
+for memory management, visitors, printing, and (un)archiving.
+@code{GINAC_IMPLEMENT_REGISTERED_CLASS} initializes certain static members
+of a class so that printing and (un)archiving works.
+
+Now there are three member functions we have to implement to get a working
 class:
 
 @itemize
@@ -7882,21 +7975,6 @@ class:
 @item
 @code{mystring()}, the default constructor.
 
-@item
-@code{void archive(archive_node & n)}, the archiving function. This stores all
-information needed to reconstruct an object of this class inside an
-@code{archive_node}.
-
-@item
-@code{mystring(const archive_node & n, lst & sym_lst)}, the unarchiving
-constructor. This constructs an instance of the class from the information
-found in an @code{archive_node}.
-
-@item
-@code{ex unarchive(const archive_node & n, lst & sym_lst)}, the static
-unarchiving function. It constructs a new instance by calling the unarchiving
-constructor.
-
 @item
 @cindex @code{compare_same_type()}
 @code{int compare_same_type(const basic & other)}, which is used internally
@@ -7912,85 +7990,21 @@ objects for which no reasonable algebraic ordering relationship can be
 defined.
 
 @item
-And, of course, @code{mystring(const string & s)} and @code{mystring(const char * s)}
-which are the two constructors we declared.
+And, of course, @code{mystring(const string& s)} which is the constructor
+we declared.
 
 @end itemize
 
 Let's proceed step-by-step. The default constructor looks like this:
 
 @example
-mystring::mystring() : inherited(&mystring::tinfo_static) @{@}
+mystring::mystring() @{ @}
 @end example
 
-The golden rule is that in all constructors you have to set the
-@code{tinfo_key} member to the @code{&your_class_name::tinfo_static}
-@footnote{Each GiNaC class has a static member called tinfo_static.
-This member is declared by the GINAC_DECLARE_REGISTERED_CLASS macros
-and defined by the GINAC_IMPLEMENT_REGISTERED_CLASS macros.}. Otherwise
-it will be set by the constructor of the superclass and all hell will break
-loose in the RTTI. For your convenience, the @code{basic} class provides
-a constructor that takes a @code{tinfo_key} value, which we are using here
-(remember that in our case @code{inherited == basic}).  If the superclass
-didn't have such a constructor, we would have to set the @code{tinfo_key}
-to the right value manually.
-
 In the default constructor you should set all other member variables to
 reasonable default values (we don't need that here since our @code{str}
 member gets set to an empty string automatically).
 
-Next are the three functions for archiving. You have to implement them even
-if you don't plan to use archives, but the minimum required implementation
-is really simple.  First, the archiving function:
-
-@example
-void mystring::archive(archive_node & n) const
-@{
-    inherited::archive(n);
-    n.add_string("string", str);
-@}
-@end example
-
-The only thing that is really required is calling the @code{archive()}
-function of the superclass. Optionally, you can store all information you
-deem necessary for representing the object into the passed
-@code{archive_node}.  We are just storing our string here. For more
-information on how the archiving works, consult the @file{archive.h} header
-file.
-
-The unarchiving constructor is basically the inverse of the archiving
-function:
-
-@example
-mystring::mystring(const archive_node & n, lst & sym_lst) : inherited(n, sym_lst)
-@{
-    n.find_string("string", str);
-@}
-@end example
-
-If you don't need archiving, just leave this function empty (but you must
-invoke the unarchiving constructor of the superclass). Note that we don't
-have to set the @code{tinfo_key} here because it is done automatically
-by the unarchiving constructor of the @code{basic} class.
-
-Finally, the unarchiving function:
-
-@example
-ex mystring::unarchive(const archive_node & n, lst & sym_lst)
-@{
-    return (new mystring(n, sym_lst))->setflag(status_flags::dynallocated);
-@}
-@end example
-
-You don't have to understand how exactly this works. Just copy these
-four lines into your code literally (replacing the class name, of
-course).  It calls the unarchiving constructor of the class and unless
-you are doing something very special (like matching @code{archive_node}s
-to global objects) you don't need a different implementation. For those
-who are interested: setting the @code{dynallocated} flag puts the object
-under the control of GiNaC's garbage collection.  It will get deleted
-automatically once it is no longer referenced.
-
 Our @code{compare_same_type()} function uses a provided function to compare
 the string members:
 
@@ -8014,17 +8028,13 @@ comparable), so the cast is safe. If this function returns 0, the two objects
 are considered equal (in the sense that @math{A-B=0}), so you should compare
 all relevant member variables.
 
-Now the only thing missing is our two new constructors:
+Now the only thing missing is our constructor:
 
 @example
-mystring::mystring(const string & s)
-    : inherited(&mystring::tinfo_static), str(s) @{@}
-mystring::mystring(const char * s)
-    : inherited(&mystring::tinfo_static), str(s) @{@}
+mystring::mystring(const string& s) : str(s) @{ @}
 @end example
 
-No surprises here. We set the @code{str} member from the argument and
-remember to pass the right @code{tinfo_key} to the @code{basic} constructor.
+No surprises here. We set the @code{str} member from the argument.
 
 That's it! We now have a minimal working GiNaC class that can store
 strings in algebraic expressions. Let's confirm that the RTTI works:
@@ -8259,27 +8269,20 @@ That's it. May the source be with you!
 
 @subsection Upgrading extension classes from older version of GiNaC
 
-If you got some extension classes for GiNaC 1.3.X some changes are
-necessary in order to make your code work with GiNaC 1.4.
-
-@itemize @bullet
-@item constructors which set @code{tinfo_key} such as
+GiNaC used to use a custom run time type information system (RTTI). It was
+removed from GiNaC. Thus, one needs to rewrite constructors which set
+@code{tinfo_key} (which does not exist any more). For example,
 
 @example
-myclass::myclass() : inherited(TINFO_myclass) @{@}
+myclass::myclass() : inherited(&myclass::tinfo_static) @{@}
 @end example
 
-need to be rewritten as
+needs to be rewritten as
 
 @example
-myclass::myclass() : inherited(&myclass::tinfo_static) @{@}
+myclass::myclass() @{@}
 @end example
 
-@item TINO_myclass is not necessary any more and can be removed.
-
-@end itemize
-
-
 @node A comparison with other CAS, Advantages, Adding classes, Top
 @c    node-name, next, previous, up
 @chapter A Comparison With Other CAS
@@ -8388,7 +8391,7 @@ Of course it also has some disadvantages:
 advanced features: GiNaC cannot compete with a program like
 @emph{Reduce} which exists for more than 30 years now or @emph{Maple}
 which grows since 1981 by the work of dozens of programmers, with
-respect to mathematical features.  Integration, factorization,
+respect to mathematical features.  Integration, 
 non-trivial simplifications, limits etc. are missing in GiNaC (and are
 not planned for the near future).
 
@@ -8549,7 +8552,12 @@ addition and multiplication, one container for exponentiation with base
 and exponent and some atomic leaves of symbols and numbers in this
 fashion:
 
+@ifnotinfo
 @image{repnaive}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
 
 @cindex pair-wise representation
 However, doing so results in a rather deeply nested tree which will
@@ -8560,7 +8568,12 @@ spirit we can store the multiplication as a sequence of terms, each
 having a numeric exponent and a possibly complicated base, the tree
 becomes much more flat:
 
+@ifnotinfo
 @image{reppair}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
 
 The number @code{3} above the symbol @code{d} shows that @code{mul}
 objects are treated similarly where the coefficients are interpreted as
@@ -8582,7 +8595,12 @@ $2d^3 \left( 4a + 5b - 3 \right)$:
 @math{2*d^3*(4*a+5*b-3)}:
 @end ifnottex
 
+@ifnotinfo
 @image{repreal}
+@end ifnotinfo
+@ifinfo
+<PICTURE MISSING>
+@end ifinfo
 
 @cindex radical
 This also allows for a better handling of numeric radicals, since