]> www.ginac.de Git - ginac.git/blobdiff - doc/tutorial/tutorial.sgml.in
- Finished last chapter. I guess it's 95% complete now.
[ginac.git] / doc / tutorial / tutorial.sgml.in
index e2acbc497678b5a4f32ef7aaed084764fa75be55..a8ac0ae204511b288ff2dd98801ec161e18a4a90 100644 (file)
       <address><email>Richard.Kreckel@Uni-Mainz.DE</email></address>
     </affiliation>
   </author>
-  <author>
-    <surname>Others</surname>
-    <affiliation>
-      <address><email>whoever@ThEP.Physik.Uni-Mainz.DE</email></address>
-    </affiliation>
-  </author>
 </authorgroup>
 </bookbiblio>
 </bookinfo>
@@ -124,8 +118,8 @@ int main()
 <para>Assuming the file is called <literal>hello.cc</literal>, on 
 our system we can compile and run it like this:</para>
 <screen>
-<prompt>sysprompt></prompt> c++ hello.cc -o hello -lcln -lginac
-<prompt>sysprompt></prompt> ./hello
+<prompt>$</prompt> c++ hello.cc -o hello -lcln -lginac
+<prompt>$</prompt> ./hello
 355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2
 </screen>
 </example>
@@ -181,8 +175,11 @@ shell that provides a convenient window into GiNaC's capabilities.
 experiment with GiNaC's features much like in other Computer Algebra
 Systems except that it does not provide programming constructs like
 loops or conditionals.  For a concise description of the
-<literal>ginsh</literal> syntax we refer to its accompanied 
-man-page.</para>
+<literal>ginsh</literal> syntax we refer to its accompanied man-page.
+Suffice to say that assignments and comparisons in
+<literal>ginsh</literal> are written as they are in C,
+i.e. <literal>=</literal> assigns and <literal>==</literal>
+compares.</para>
 
 <para>It can manipulate arbitrary precision integers in a very fast
 way.  Rational numbers are automatically converted to fractions of
@@ -305,7 +302,7 @@ x^(-1)-1/3*x+Order(x^2)
 easily installed on your system by three steps: configuration, build,
 installation.</para>
 
-<sect1 id="ind123"><title id="CLN-main">Prerequistes</title>
+<sect1><title id="CLN-main">Prerequistes</title>
 
 <para>In order to install GiNaC on your system, some prerequistes need
 to be met.  First of all, you need to have a C++-compiler adhering to
@@ -404,18 +401,19 @@ your login shell.)
 configure-script</title> <para>Simple configuration for a site-wide
 GiNaC library assuming everything is in default paths:</para>
 <screen>
-<prompt>sysprompt></prompt> export CXXFLAGS="-Wall -O2"
-<prompt>sysprompt></prompt> ./configure --enable-shared
+<prompt>$</prompt> export CXXFLAGS="-Wall -O2"
+<prompt>$</prompt> ./configure
 </screen>
-<para>Configuration for a private GiNaC library with several
+<para>Configuration for a private static GiNaC library with several
 components sitting in custom places (site-wide <literal>GCC</literal>
-and private <literal>CLN</literal>):</para>
+and private <literal>CLN</literal>), the compiler pursueded to be
+picky and full assertions switched on:</para>
 <screen>
-<prompt>sysprompt></prompt> export CXX=/usr/local/gnu/bin/c++
-<prompt>sysprompt></prompt> export CPPFLAGS="${CPPFLAGS} -I${HOME}/include"
-<prompt>sysprompt></prompt> export CXXFLAGS="${CXXFLAGS} -ggdb -Wall -ansi -pedantic -O2"
-<prompt>sysprompt></prompt> export LDFLAGS="${LDFLAGS} -L${HOME}/lib"
-<prompt>sysprompt></prompt> ./configure --enable-shared --prefix=${HOME}
+<prompt>$</prompt> export CXX=/usr/local/gnu/bin/c++
+<prompt>$</prompt> export CPPFLAGS="${CPPFLAGS} -I${HOME}/include"
+<prompt>$</prompt> export CXXFLAGS="${CXXFLAGS} -ggdb -Wall -ansi -pedantic -O2 -DDO_GINAC_ASSERT"
+<prompt>$</prompt> export LDFLAGS="${LDFLAGS} -L${HOME}/lib"
+<prompt>$</prompt> ./configure --disable-shared --prefix=${HOME}
 </screen>
 </example>
 </para>
@@ -433,11 +431,11 @@ suite by typing <literal>make check</literal>.  This will compile some
 sample programs, run them and compare the output to reference output.
 Each of the checks should return a message <literal>passed</literal>
 together with the CPU time used for that particular test.  If it does
-not, something went wrong.  This is mostly intended to be a check if
-something was broken during the development, but not a sanity check of
-your system.  Another intent is to allow people to fiddle around with
-optimization.  If <literal>CLN</literal> was installed all right this
-step is unlikely to return any errors.</para>
+not, something went wrong.  This is mostly intended to be a QA-check
+if something was broken during the development, but not a sanity check
+of your system.  Another intent is to allow people to fiddle around
+with optimization.  If <literal>CLN</literal> was installed all right
+this step is unlikely to return any errors.</para>
 
 </sect1>
 
@@ -605,11 +603,16 @@ argument of <literal>cos()</literal> only holds a reference to
 </para>
 
 <para>As a user of GiNaC, you cannot see this mechanism of
-copy-on-write semantics.  When you insert an expression into a
-second expression, the result behaves exactly as if the contents of
-the first expression were inserted.  But it may be useful to remember
-that this is not what happens.  Knowing this will enable you to write
-much more efficient code.</para>
+copy-on-write semantics.  When you insert an expression into a second
+expression, the result behaves exactly as if the contents of the first
+expression were inserted.  But it may be useful to remember that this
+is not what happens.  Knowing this will enable you to write much more
+efficient code.  If you still have an uncertain feeling with
+copy-on-write semantics, we recommend you have a look at the
+<emphasis>C++-FAQ lite</emphasis> by Marshall Cline.  Chapter 16
+covers this issue and presents an implementation which is pretty close
+to the one in GiNaC.  You can find it on the Web at <ulink
+url="http://www.cerfnet.com/~mpcline/c++-faq-lite/"><literal>http://www.cerfnet.com/~mpcline/c++-faq-lite/</literal></ulink>.</para>
 
 <para>So much for expressions.  But what exactly are these expressions
 handles of?  This will be answered in the following sections.</para>
@@ -687,15 +690,20 @@ interpretation differs.  </para>
 <sect1><title>Symbols</title>
 
 <para>Symbols are for symbolic manipulation what atoms are for
-chemistry.  You can declare objects of type symbol as any other object
-simply by saying <literal>symbol x,y;</literal>.  There is, however, a
-catch in here having to do with the fact that C++ is a compiled
-language.  The information about the symbol's name is thrown away by
-the compiler but at a later stage you may want to print expressions
-holding your symbols.  In order to avoid confusion GiNaC's symbols are
-able to know their own name.  This is accomplished by declaring its
-name for output at construction time in the fashion <literal>symbol
-x("x");</literal>.</para>
+chemistry.  You can declare objects of class <literal>symbol</literal>
+as any other object simply by saying <literal>symbol x,y;</literal>.
+There is, however, a catch in here having to do with the fact that C++
+is a compiled language.  The information about the symbol's name is
+thrown away by the compiler but at a later stage you may want to print
+expressions holding your symbols.  In order to avoid confusion GiNaC's
+symbols are able to know their own name.  This is accomplished by
+declaring its name for output at construction time in the fashion
+<literal>symbol x("x");</literal>.  If you declare a symbol using the
+default constructor (i.e. without string-argument) the system will
+deal out a unique name.  That name may not be suitable for printing
+but for internal routines when no output is desired it is often
+enough.  We'll come across examples of such symbols later in this
+tutorial.  </para>
 
 <para>Although symbols can be assigned expressions for internal
 reasons, you should not do it (and we are not going to tell you how it
@@ -714,7 +722,7 @@ for Numbers or alternatively for Common Lisp Numbers.  In order to
 find out more about <literal>CLN</literal>'s internals the reader is
 refered to the documentation of that library.  Suffice to say that it
 is by itself build on top of another library, the GNU Multiple
-Precision library <literal>GMP</literal>, which is a extremely fast
+Precision library <literal>GMP</literal>, 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.  <literal>CLN</literal> extends
@@ -753,16 +761,24 @@ int main()
 Note that all those constructors are <emphasis>explicit</emphasis>
 which means you are not allowed to write <literal>numeric
 two=2;</literal>.  This is because the basic objects to be handled by
-GiNaC are the expressions and we want to keep things simple and wish
-objects like <literal>pow(x,2)</literal> to be handled the same way
-as <literal>pow(x,a)</literal>, which means that we need to allow a
-general expression as base and exponent.  Therefore there is an
-implicit construction from a C-integer directly to an expression
-handling a numeric in the first example.  This design really becomes
-convenient when one declares own functions having more than one
-parameter but it forbids using implicit constructors because that
-would lead to ambiguities.
-</para>
+GiNaC are the expressions <literal>ex</literal> and we want to keep
+things simple and wish objects like <literal>pow(x,2)</literal> to be
+handled the same way as <literal>pow(x,a)</literal>, which means that
+we need to allow a general <literal>ex</literal> as base and exponent.
+Therefore there is an implicit constructor from C-integers directly to
+expressions handling numerics at work in most of our examples.  This
+design really becomes convenient when one declares own functions
+having more than one parameter but it forbids using implicit
+constructors because that would lead to ambiguities. </para>
+
+<para>It may be tempting to construct numbers writing <literal>numeric
+r(3/2)</literal>.  This would, however, call C's built-in operator
+<literal>/</literal> for integers first and result in a numeric
+holding a plain integer 1.  <emphasis>Never use
+</emphasis><literal>/</literal><emphasis> on integers!</emphasis> Use
+the constructor from two integers instead, as shown in the example
+above.  Writing <literal>numeric(1)/2</literal> may look funny but
+works also. </para>
 
 <para>We have seen now the distinction between exact numbers and
 floating point numbers.  Clearly, the user should never have to worry
@@ -838,18 +854,20 @@ int main()
 }
 </programlisting>
 </example>
+
 Note that the variable <literal>answer</literal> is constructed here
 as an integer but in an intermediate step it holds a rational number
-represented as integer numerator and denominator.  When multiplied by
-10, the denominator becomes unity and the result is automatically
-converted to a pure integer again.  Internally, the underlying
-<literal>CLN</literal> is responsible for this behaviour and we refer
-the reader to <literal>CLN</literal>'s documentation.  Suffice to say
-that the same behaviour 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.
+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 <literal>CLN</literal> is responsible for this behaviour
+and we refer the reader to <literal>CLN</literal>'s documentation.
+Suffice to say that the same behaviour 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.
+
 <informaltable colsep="0" frame="topbot" pgwide="1">
 <tgroup cols="2">
 <colspec colnum="1" colwidth="1*">
@@ -1042,7 +1060,7 @@ explicitly, results in the same canonical form.</para>
 
 <sect1><title>Built-in Functions</title>
 
-<para>This chapter is not here yet</para>
+<para>This section is not here yet</para>
 
 
 
@@ -1187,7 +1205,7 @@ not within the user's sphere of influence.</para>
 
 </sect1>
 
-<sect1 id="gcd-main"><title>Polynomial Arithmetic</title>
+<sect1><title>Polynomial Arithmetic</title>
 
 <sect2><title>GCD and LCM</title>
 
@@ -1237,11 +1255,38 @@ int main()
 <sect2><title>The <function>normal</function> method</title>
 
 <para>While in common symbolic code <function>gcd()</function> and
-<function>lcm()</function> are not too heavily used, some basic
-simplification occurs frequently.  Therefore
-<function>.normal()</function>, which provides some basic form of
-simplification, has become a method of class <literal>ex</literal>,
-just like <literal>.expand()</literal>.</para>
+<function>lcm()</function> are not too heavily used, simplification
+occurs frequently.  Therefore <function>.normal()</function>, which
+provides some basic form of simplification, has become a method of
+class <literal>ex</literal>, just like <literal>.expand()</literal>.
+It converts a rational function into an equivalent rational function
+where numererator and denominator are coprime.  This means, it finds
+the GCD of numerator and denominator and cancels it.  If it encounters
+some object which does not belong to the domain of rationals (a
+function for instance), that object is replaced by a temporary symbol.
+This means that both expressions <literal>t1</literal> and
+<literal>t2</literal> are indeed simplified in this little program:
+<example><title>Cancellation of polynomial GCD (with obstacles)</title>
+<programlisting>
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
+
+int main()
+{
+    symbol x("x");
+    ex t1 = (pow(x,2) + 2*x + 1)/(x + 1);
+    ex t2 = (pow(sin(x),2) + 2*sin(x) + 1)/(sin(x) + 1);
+    cout &lt;&lt; "t1 is " &lt;&lt; t1.normal() &lt;&lt; endl;
+    cout &lt;&lt; "t2 is " &lt;&lt; t2.normal() &lt;&lt; endl;
+    // ...
+}
+</programlisting>
+</example>
+
+Of course this works for multivariate polynomials too, so the ratio of
+the sample-polynomials from the section about GCD and LCM above would
+be normalized to <literal>P_a/P_b</literal> =
+<literal>(4*y+z)/(y+3*z)</literal>.</para>
 
 </sect2>
 
@@ -1249,7 +1294,9 @@ just like <literal>.expand()</literal>.</para>
 
 <sect1><title>Symbolic Differentiation</title>
 
-<para>
+<para>GiNaC's objects know how to differentiate themselves.  Thus, a
+polynomial (class <literal>add</literal>) knows that its derivative is
+the sum of the derivatives of all the monomials:
 <example><title>Simple polynomial differentiation</title>
 <programlisting>
 #include &lt;ginac/ginac.h&gt;
@@ -1267,21 +1314,48 @@ int main()
 }
 </programlisting>
 </example>
-</para>
-
-<para>
-<example><title>Differentiation with nontrivial functions</title>
+If a second integer parameter <emphasis>n</emphasis> is given the
+<function>diff</function> method returns the <emphasis>n</emphasis>th
+derivative.</para>
+
+<para>If <emphasis>every</emphasis> object and every function is told
+what its derivative is, all derivatives of composed objects can be
+calculated using the chain rule and the product rule.  Consider, for
+instance the expression <literal>1/cosh(x)</literal>.  Since the
+derivative of <literal>cosh(x)</literal> is <literal>sinh(x)</literal>
+and the derivative of <literal>pow(x,-1)</literal> is
+<literal>-pow(x,-2)</literal> GiNaC can readily compute the
+composition.  It turns out that the composition is the generating
+function for Euler Numbers, i.e. the so called
+<emphasis>n</emphasis>th Euler number is the coefficient of
+<literal>x^n/n!</literal> in the expansion of
+<literal>1/cosh(x)</literal>.  We may use this identity to code a
+function that generates Euler numbers in just three lines:
+<example><title>Differentiation with nontrivial functions: Euler numbers</title>
 <programlisting>
 #include &lt;ginac/ginac.h&gt;
 using namespace GiNaC;
 
+ex EulerNumber(unsigned n)
+{
+    symbol x;
+    ex generator = pow(cosh(x),-1);
+    return generator.diff(x,n).subs(x==0);
+}
+
 int main()
 {
-    // To Be Done...
+    for (unsigned i=0; i&lt;11; i+=2)
+        cout &lt;&lt; EulerNumber(i) &lt;&lt; endl;
+    return 0;
 }
 </programlisting>
 </example>
-</para>
+When you run it, it produces the sequence <literal>1</literal>,
+<literal>-1</literal>, <literal>5</literal>, <literal>-61</literal>,
+<literal>1385</literal>, <literal>-50521</literal>.  We increment the
+loop variable <literal>i</literal> by two since all odd Euler numbers
+vanish anyways.</para>
 
 </sect1>
 
@@ -1311,7 +1385,7 @@ int main()
     MySeries = MyExpr2.series(x, point, 7);
     cout &lt;&lt; MyExpr2 &lt;&lt; " == " &lt;&lt; MySeries
          &lt;&lt; " for small " &lt;&lt; x &lt;&lt; endl;
-    \\ ...
+    // ...
 }
 </programlisting>
 </example>
@@ -1324,8 +1398,8 @@ wonderful formula <literal>Pi==16*atan(1/5)-4*atan(1/239)</literal>.
 We may expand the arcus tangent around <literal>0</literal> and insert
 the fractions <literal>1/5</literal> and <literal>1/239</literal>.
 But, as we have seen, a series in GiNaC carries an order term with it.
-The preprocessor-macro <literal>series_to_poly</literal> may be used
-to strip this off:
+The function <literal>series_to_poly</literal> may be used to strip 
+this off:
 <example><title>Series expansion using M&eacute;chain's formula for 
 <literal>Pi</literal></title>
 <programlisting>
@@ -1334,7 +1408,7 @@ using namespace GiNaC;
 
 ex mechain_pi(int degr)
 {
-    symbol x("x");
+    symbol x;
     ex pi_expansion = series_to_poly(atan(x).series(x,0,degr));
     ex pi_approx = 16*pi_expansion.subs(x==numeric(1,5))
                    -4*pi_expansion.subs(x==numeric(1,239));
@@ -1376,7 +1450,113 @@ int main()
 <chapter>
 <title>Extending GiNaC</title>
 
-<para>Longish chapter follows here.</para>
+<para>By reading so far you should have gotten a fairly good
+understanding of GiNaC's design-patterns.  From here on you should
+start reading the sources.  All we can do now is issue some
+recommendations how to tackle the many open ends the system still
+has in order to fulfill everybody's dreams.</para>
+
+<sect1><title>What doesn't belong into GiNaC</title>
+
+<para>First of all, GiNaC's name must be read literally.  It is
+designed to be a library for use within C++.  The tiny
+<literal>ginsh</literal> accompanying GiNaC makes this even more
+clear: it doesn't even attempt to provide a language.  There are no
+loops or conditional expressions in <literal>ginsh</literal>, it is
+merely a window into the library for the programmer to test stuff (or
+to show off).  Still, the design of a complete CAS with a language of
+its own, graphical capabilites and all this on top of GiNaC is
+possible and is without doubt a nice project for the future.</para>
+
+<para>There are many built-in functions in GiNaC that do not know how
+to evaluate themselves numerically to a precision declared at runtime
+(using <literal>Digits</literal>).  Some may be evaluated at certain
+points, but not 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 bignum-package
+<literal>CLN</literal> is much better suited.</para>
+
+</sect1>
+
+<sect1><title>Other symbolic functions</title>
+
+<para>The easiest and most instructive way to start with is probably
+to implement your own function.  Objects of class
+<literal>function</literal> are inserted into the system via a kind of
+"registry".  They get a serial number that is used internally to
+identify them but you usually need not worry about this.  What you
+have to care for are functions that are called when the user invokes
+certain methods.  These are usual C++-functions accepting a number of
+<literal>ex</literal> as arguments and returning one
+<literal>ex</literal>.  As an example, if we have a look at a
+simplified implementation of the cosine trigonometric function, we
+first need a function that is called when one wishes to
+<literal>eval</literal> it.  It could look something like this:
+
+<programlisting>
+static ex cos_eval_method(ex const & x)
+{
+    // if x%2*Pi return 1
+    // if x%Pi return -1
+    // if x%Pi/2 return 0
+    // care for other cases...
+    return cos(x).hold();
+}
+</programlisting>
+The last line returns <literal>cos(x)</literal> if we don't know what
+else to do and stops a potential recursive evaluation by saying
+<literal>.hold()</literal>.  We should also implement a method for
+numerical evaluation and since we are lazy we sweep the problem under
+the rug by calling someone else's function that does so, in this case
+the one in class <literal>numeric</literal>:
+<programlisting>
+static ex cos_evalf_method(ex const & x)
+{
+    return sin(ex_to_numeric(x));
+}
+</programlisting>
+Differentiation will surely turn up and so we need to tell
+<literal>sin</literal> how to differentiate itself:
+<programlisting>
+static ex cos_diff_method(ex const & x, unsigned diff_param)
+{
+    return cos(x);
+}
+</programlisting>
+
+The second parameter is obligatory but uninteresting at this point.
+It is used for correct handling of the product rule only.  For Taylor
+expansion, it is enough to know how to differentiate.  But if the
+function you want to implement does have a pole somewhere in the
+complex plane, you need to write another method for Laurent expansion
+around that point.</para>
+
+<para>Now that everything has been written for <literal>cos</literal>,
+we need to tell the system about it.  This is done by a macro and we
+are not going to descibe how it expands, please consult your
+preprocessor if you are curious:
+<programlisting>
+REGISTER_FUNCTION(cos, cos_eval_method, cos_evalf_method, cos_diff, NULL);
+</programlisting>
+The first argument is the function's name, the second, third and
+fourth bind the corresponding methods to this objects and the fifth is
+a slot for inserting a method for series expansion.  Also, the new
+function needs to be declared somewhere.  This may also be done by a
+convenient preprocessor macro:
+<programlisting>
+DECLARE_FUNCTION_1P(cos)
+</programlisting>
+The suffix <literal>_1P</literal> stands for <emphasis>one
+parameter</emphasis>.  Of course, this implementation of
+<literal>cos</literal> is very incomplete and lacks several safety
+mechanisms.  Please, have a look at the real implementation in GiNaC.
+(By the way: in case you are worrying about all the macros above we
+can assure you that functions are GiNaC's most macro-intense classes.
+We have done our best to avoid them where we can.)</para>
+
+<para>That's it. May the source be with you!</para>
+
+</sect1>
 
 </chapter>
 
@@ -1555,6 +1735,16 @@ language.</para>
   </bookbiblio>
 </biblioentry>
 
+<biblioentry>
+  <bookbiblio>
+    <title>C++ FAQs</title>
+    <authorgroup><author><firstname>Marshall</firstname><surname>Cline</surname></author></authorgroup>
+    <isbn>0-201-58958-3</isbn>
+    <pubdate>1995</pubdate>
+    <publisher><publishername>Addison Wesley</publishername></publisher>  
+  </bookbiblio>
+</biblioentry>
+
 <biblioentry>
   <bookbiblio>
     <title>Algorithms for Computer Algebra</title>
@@ -1593,24 +1783,4 @@ language.</para>
 </bibliodiv>
 </bibliography>
 
-
-<index id="index">
-<title>Index</title>
-
-<indexentry>
-  <primaryie linkends="CLN-main">CLN</primaryie>
-  <secondaryie linkends="ind123">obtaining</secondaryie>
-</indexentry>
-
-<indexentry id="ind-gcd">
-  <primaryie linkends="gcd-main">gcd</primaryie>
-</indexentry>
-
-<indexentry>
-  <primaryie>lcm</primaryie>
-  <seeie linkend="ind-gcd">gcd</seeie>
-</indexentry>
-
-</index>
-
 </book>