X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=doc%2Ftutorial%2Fginac.texi;h=e17d4dfa8f4f59e974bcb0645bfff81f19e00b94;hp=e05f669359a783c0091db570c4cd008e638c4fb3;hb=6f64b39dd25e4d2dcc869995b3d19724fa72afa6;hpb=095f4fbf219bb155c758bbda5a373a70fe6ca91a diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index e05f6693..e17d4dfa 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -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-2008 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-2008 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-2008 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 + +@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 @@ -1019,7 +1025,7 @@ internally such anonymous symbols can be quite useful, however). Now, here is one important property of GiNaC that differentiates it from other computer algebra programs you may have used: GiNaC does @emph{not} use the names of symbols to tell them apart, but a (hidden) serial number that -is unique for each newly created @code{symbol} object. In you want to use +is unique for each newly created @code{symbol} object. If you want to use one and the same symbol in different places in your program, you must only create one @code{symbol} object and pass that around. If you create another symbol, even if it has the same name, GiNaC will treat it as a different @@ -1164,7 +1170,7 @@ the domain of the symbol. Instead of @code{symbol x("x");} you can write @cindex @code{possymbol()} Furthermore, it is also possible to declare a symbol as positive. This will, for instance, enable the automatic simplification of @code{abs(x)} into -@code{x}. This is done by declaying the symbol as @code{possymbol x("x");}. +@code{x}. This is done by declaring the symbol as @code{possymbol x("x");}. @node Numbers, Constants, Symbols, Basic concepts @@ -1335,7 +1341,7 @@ int main() @end example Note that the variable @code{answer} is constructed here as an integer -by @code{numeric}'s copy constructor but in an intermediate step it +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. @@ -1353,6 +1359,8 @@ can be applied is listed in the following table. @tab @dots{}equal to zero @item @code{.is_positive()} @tab @dots{}not complex and greater than 0 +@item @code{.is_negative()} +@tab @dots{}not complex and smaller than 0 @item @code{.is_integer()} @tab @dots{}a (non-complex) integer @item @code{.is_pos_integer()} @@ -1376,6 +1384,8 @@ can be applied is listed in the following table. @end multitable @end cartouche +@page + @subsection Numeric functions The following functions can be applied to @code{numeric} objects and will be @@ -1532,7 +1542,7 @@ specific number when the method @code{.evalf()} is called. The predefined known constants are: @cartouche -@multitable @columnfractions .14 .30 .56 +@multitable @columnfractions .14 .32 .54 @item @strong{Name} @tab @strong{Common Name} @tab @strong{Numerical Value (to 35 digits)} @item @code{Pi} @tab Archimedes' constant @@ -1907,7 +1917,7 @@ return the integral unevaluated. The function that performs the numerical evaluation, is also available as @example ex adaptivesimpson(const ex & x, const ex & a, const ex & b, const ex & f, -const ex & error) + const ex & error) @end example This function will throw an exception if the maximum depth is exceeded. The last parameter of the function is optional and defaults to the @@ -2317,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 @@ -2688,7 +2698,7 @@ ex ex::simplify_indexed(const scalar_products & sp); that performs some more expensive operations: -@itemize +@itemize @bullet @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 @@ -3038,7 +3048,7 @@ 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 +@itemize @bullet @item @code{return_types::commutative}: Commutates with everything. Most GiNaC classes are of this kind. @item @code{return_types::noncommutative}: Non-commutative, belonging to a @@ -3054,8 +3064,8 @@ expressions in GiNaC: 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. +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). Here are a couple of examples: @@ -3204,14 +3214,20 @@ ordinary matrix trace only in @math{D = 4} dimensions. In particular, the functional is not cyclic in @tex $D \ne 4$ @end tex +@ifnottex +@math{D != 4} +@end ifnottex 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}. +@samp{gamma5} scheme is described in greater detail in the article +@cite{The Role of gamma5 in Dimensional Regularization} (@ref{Bibliography}). The value of the trace itself is also usually different in 4 and in @tex $D \ne 4$ @end tex +@ifnottex +@math{D != 4} +@end ifnottex dimensions: @example @@ -3280,16 +3296,21 @@ You can use this to compare two expressions or for further simplifications: @subsubsection A generic Clifford algebra A generic Clifford algebra, i.e. a -@tex -$2^n$ +@tex $2^n$ @end tex +@ifnottex +2^n +@end ifnottex dimensional algebra with generators @tex $e_k$ @end tex +@ifnottex +e_k +@end ifnottex satisfying the identities @tex -$e_i e_j + e_j e_i = M(i, j) + M(j, i) $ +$e_i e_j + e_j e_i = M(i, j) + M(j, i)$ @end tex @ifnottex e~i e~j + e~j e~i = M(i, j) + M(j, i) @@ -3386,8 +3407,20 @@ $v^0 e_0 + v^1 e_1 + ... + v^n e_n$ with @samp{e.k} directly supplied in the second form of the procedure. In the first form the Clifford unit @samp{e.k} is generated by the call of -@code{clifford_unit(mu, metr, rl)}. The previous code may be rewritten -with the help of @code{lst_to_clifford()} as follows +@code{clifford_unit(mu, metr, rl)}. +@cindex pseudo-vector +If the number of components supplied +by @code{v} exceeds the dimensionality of the Clifford unit @code{e} by +1 then function @code{lst_to_clifford()} uses the following +pseudo-vector representation: +@tex +$v^0 {\bf 1} + v^1 e_0 + v^2 e_1 + ... + v^{n+1} e_n$ +@end tex +@ifnottex +@samp{v~0 ONE + v~1 e.0 + v~2 e.1 + ... + v~[n+1] e.n} +@end ifnottex + +The previous code may be rewritten with the help of @code{lst_to_clifford()} as follows @example @{ @@ -3417,17 +3450,25 @@ $v = (v^0, v^1, ..., v^n)$ @ifnottex @samp{v = (v~0, v~1, ..., v~n)} @end ifnottex -such that +such that the expression is either vector @tex $e = v^0 c_0 + v^1 c_1 + ... + v^n c_n$ @end tex @ifnottex @samp{e = v~0 c.0 + v~1 c.1 + ... + v~n c.n} @end ifnottex -with respect to the given Clifford units @code{c} and with none of the -@samp{v~k} containing Clifford units @code{c} (of course, this +or pseudo-vector +@tex +$v^0 {\bf 1} + v^1 e_0 + v^2 e_1 + ... + v^{n+1} e_n$ +@end tex +@ifnottex +@samp{v~0 ONE + v~1 e.0 + v~2 e.1 + ... + v~[n+1] e.n} +@end ifnottex +with respect to the given Clifford units @code{c}. Here none of the +@samp{v~k} should contain Clifford units @code{c} (of course, this may be impossible). This function can use an @code{algebraic} method -(default) or a symbolic one. With the @code{algebraic} method the @samp{v~k} are calculated as +(default) or a symbolic one. With the @code{algebraic} method the +@samp{v~k} are calculated as @tex $(e c_k + c_k e)/c_k^2$. If $c_k^2$ @end tex @@ -3560,7 +3601,7 @@ LaTeX output for Clifford units looks like @code{\clifford[1]@{e@}^@{@{\nu@}@}}, where @code{1} is the @code{representation_label} and @code{\nu} is the index of the corresponding unit. This provides a flexible typesetting with a suitable -defintion of the @code{\clifford} command. For example, the definition +definition of the @code{\clifford} command. For example, the definition @example \newcommand@{\clifford@}[1][]@{@} @end example @@ -4278,10 +4319,10 @@ The optional last argument to @code{subs()} is a combination of large @code{subs()} operations significantly faster if you are not using patterns. The second option, @code{subs_options::algebraic} enables algebraic substitutions in products and powers. -@ref{Pattern matching and advanced substitutions}, for more information +@xref{Pattern matching and advanced substitutions}, for more information about patterns and algebraic substitutions. The third option, @code{subs_options::no_index_renaming} disables the feature that dummy -indices are renamed if the subsitution could give a result in which a +indices are renamed if the substitution could give a result in which a dummy index occurs more than two times. This is sometimes necessary if you want to use @code{subs()} to rename your dummy indices. @@ -4349,7 +4390,7 @@ Some examples for patterns: Notes: -@itemize +@itemize @bullet @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 @@ -4372,17 +4413,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: @@ -4521,7 +4559,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 @@ -4591,7 +4629,7 @@ The last example would be written in C++ in this way: Both @code{has()} and @code{subs()} take an optional argument to pass them extra options. This section describes what happens if you give the former the option @code{has_options::algebraic} or the latter -@code{subs:options::algebraic}. In that case the matching condition for +@code{subs_options::algebraic}. In that case the matching condition for powers and multiplications is changed in such a way that they become more intuitive. Intuition says that @code{x*y} is a part of @code{x*y*z}. If you use these options you will find that @@ -4601,7 +4639,9 @@ often as is possible without getting negative exponents. For example @code{(x^5*y^2*z).subs(x^2*y^2==c, subs_options::algebraic)} will return @code{x*c^2*z}. This also works with negative powers: @code{(x^(-3)*y^(-2)*z).subs(1/(x*y)==c, subs_options::algebraic)} will -return @code{x^(-1)*c^2*z}. Note that this only works for multiplications +return @code{x^(-1)*c^2*z}. + +@strong{Note:} this only works for multiplications and not for locating @code{x+y} within @code{x+y+z}. @@ -5587,6 +5627,9 @@ value of Archimedes' constant @tex $\pi$ @end tex +@ifnottex +@math{Pi} +@end ifnottex (for which there already exists the built-in constant @code{Pi}) using John Machin's amazing formula @tex @@ -5697,6 +5740,8 @@ almost any kind of object (anything that is @code{subs()}able): @} @end example +@page + @node Built-in functions, Multiple polylogarithms, Symmetrization, Methods and functions @c node-name, next, previous, up @section Predefined mathematical functions @@ -5892,11 +5937,20 @@ ${\rm H\;\!}_{m_1,m_2,\ldots,m_k}(x)$ and @tex $\zeta(m_1,m_2,\ldots,m_k)$. @end tex +@ifnottex +@command{\mbox@{Li@}_@{m_1,m_2,...,m_k@}(x_1,x_2,...,x_k)}, +@command{\mbox@{S@}_@{n,p@}(x)}, +@command{\mbox@{H@}_@{m_1,m_2,...,m_k@}(x)} and +@command{\zeta(m_1,m_2,...,m_k)} (with the dots replaced by actual parameters). +@end ifnottex If @code{zeta} is an alternating zeta sum, i.e. @code{zeta(m,s)}, the indices with negative sign are printed with a line above, e.g. @tex $\zeta(5,\overline{2})$. @end tex +@ifnottex +@command{\zeta(5,\overline@{2@})}. +@end ifnottex The order of indices and arguments in the GiNaC @code{lst}s and in the output is the same. Definitions and analytical as well as numerical properties of multiple polylogarithms @@ -5916,8 +5970,13 @@ ${\rm Li\;\!}_{2,1}(1,1) = \zeta(2,1) = \zeta(3)$, but @tex $\zeta(1,2)$ evaluates to infinity. @end tex -So in comparison to the referenced publications the order of indices and arguments for @code{Li} -is reversed. +@ifnottex +@code{Li_@{m_1,m_2,m_3@}(x,1,1) = H_@{m_1,m_2,m_3@}(x)} and +@code{Li_@{2,1@}(1,1) = zeta(2,1) = zeta(3)}, but +@code{zeta(1,2)} evaluates to infinity. +@end ifnottex +So in comparison to the older ones of the referenced publications the order of +indices and arguments for @code{Li} is reversed. The functions only evaluate if the indices are integers greater than zero, except for the indices @code{s} in @code{zeta} and @code{G} as well as @code{m} in @code{H}. Since @code{s} @@ -5928,11 +5987,17 @@ corresponding arguments @code{a}, it must contain 1 or -1, e.g. @tex $\zeta(\overline{3},4)$ @end tex +@ifnottex +@command{zeta(\overline@{3@},4)} +@end ifnottex and @code{G(lst(a,b), lst(-1,1), c)} means @tex $G(a-0\epsilon,b+0\epsilon;c)$. @end tex +@ifnottex +@command{G(a-0\epsilon,b+0\epsilon;c)}. +@end ifnottex The definition of @code{H} allows indices to be 0, 1 or -1 (in expanded notation) or equally to be any integer (in compact notation). With GiNaC expanded and compact notation can be mixed, e.g. @code{lst(0,0,-1,0,1,0,0)}, @code{lst(0,0,-1,2,0,0)} and @code{lst(-3,2,0,0)} are equivalent as @@ -5983,6 +6048,9 @@ unevaluated, e.g. @tex $\zeta(1)$. @end tex +@ifnottex +@command{zeta(1)}. +@end ifnottex In long expressions this helps a lot with debugging, because you can easily spot the divergencies. But on the other hand, you have to make sure for yourself, that no illegal cancellations of divergencies happen. @@ -6017,7 +6085,7 @@ ex ex::imag_part(); that return respectively the complex conjugate, the real part and the imaginary part of an expression. Complex conjugation works as expected -for all built-in functinos and objects. Taking real and imaginary +for all built-in functions and objects. Taking real and imaginary parts has not yet been implemented for all built-in functions. In cases where it is not known how to conjugate or take a real/imaginary part one of the functions @code{conjugate}, @code{real_part} or @code{imag_part} @@ -6312,22 +6380,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: + +@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 -With this constructor, it's also easy to implement interactive GiNaC programs: +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 @@ -6339,19 +6457,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(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 @@ -7757,7 +7875,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: @@ -7782,8 +7901,8 @@ class mystring : public basic GINAC_DECLARE_REGISTERED_CLASS(mystring, basic) public: - mystring(const string &s); - mystring(const char *s); + mystring(const string & s); + mystring(const char * s); private: string str; @@ -7818,23 +7937,23 @@ class: @code{mystring()}, the default constructor. @item -@code{void archive(archive_node &n)}, the archiving function. This stores all +@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 +@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 +@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 +@code{int compare_same_type(const basic & other)}, which is used internally by GiNaC to establish a canonical sort order for terms. It returns 0, +1 or -1, depending on the relative order of this object and the @code{other} object. If it returns 0, the objects are considered equal. @@ -7847,7 +7966,7 @@ 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)} +And, of course, @code{mystring(const string & s)} and @code{mystring(const char * s)} which are the two constructors we declared. @end itemize @@ -7879,7 +7998,7 @@ 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 +void mystring::archive(archive_node & n) const @{ inherited::archive(n); n.add_string("string", str); @@ -7897,7 +8016,7 @@ 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) +mystring::mystring(const archive_node & n, lst & sym_lst) : inherited(n, sym_lst) @{ n.find_string("string", str); @} @@ -7911,7 +8030,7 @@ by the unarchiving constructor of the @code{basic} class. Finally, the unarchiving function: @example -ex mystring::unarchive(const archive_node &n, lst &sym_lst) +ex mystring::unarchive(const archive_node & n, lst & sym_lst) @{ return (new mystring(n, sym_lst))->setflag(status_flags::dynallocated); @} @@ -7930,7 +8049,7 @@ Our @code{compare_same_type()} function uses a provided function to compare the string members: @example -int mystring::compare_same_type(const basic &other) const +int mystring::compare_same_type(const basic & other) const @{ const mystring &o = static_cast(other); int cmpval = str.compare(o.str); @@ -7952,8 +8071,10 @@ all relevant member variables. Now the only thing missing is our two new constructors: @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) + : inherited(&mystring::tinfo_static), str(s) @{@} +mystring::mystring(const char * s) + : inherited(&mystring::tinfo_static), str(s) @{@} @end example No surprises here. We set the @code{str} member from the argument and @@ -7989,11 +8110,11 @@ class mystring : public basic @{ ... protected: - void do_print(const print_context &c, unsigned level = 0) const; + void do_print(const print_context & c, unsigned level = 0) const; ... @}; -void mystring::do_print(const print_context &c, unsigned level) const +void mystring::do_print(const print_context & c, unsigned level) const @{ // print_context::s is a reference to an ostream c.s << '\"' << str << '\"'; @@ -8138,7 +8259,7 @@ required but will make operations with objects of the class more efficient: @cindex @code{is_equal_same_type()} @example unsigned calchash() const; -bool is_equal_same_type(const basic &other) const; +bool is_equal_same_type(const basic & other) const; @end example The @code{calchash()} method returns an @code{unsigned} hash value for the @@ -8482,7 +8603,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 + +@end ifinfo @cindex pair-wise representation However, doing so results in a rather deeply nested tree which will @@ -8493,7 +8619,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 + +@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 @@ -8515,7 +8646,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 + +@end ifinfo @cindex radical This also allows for a better handling of numeric radicals, since