]> www.ginac.de Git - ginac.git/blobdiff - doc/tutorial/tutorial.sgml.in
- One more hyperclever example and two more fixed from Alex' list.
[ginac.git] / doc / tutorial / tutorial.sgml.in
index cd8b053b0c465486cc6e784be0673a055e8cc5ac..3869936c2401e200eff1811757e3afdaa91d3f91 100644 (file)
@@ -106,7 +106,8 @@ pointless) bivariate polynomial with some large coefficients:
 <example>
 <title>My first GiNaC program (a bivariate polynomial)</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -123,8 +124,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>
@@ -136,7 +137,8 @@ variable.
 <example>
 <title>My second GiNaC program (Hermite polynomials)</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 ex HermitePoly(symbol x, int deg)
 {
@@ -303,7 +305,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
@@ -338,15 +340,10 @@ with the <literal>--help</literal> option.  The most important ones
 will be shortly described in what follows:
 <itemizedlist>
   <listitem>
-    <para><literal>--enable-shared</literal>: When given, this option
-    switches on the build of a shared library, i.e. a
-    <literal>.so</literal>-file. A static libarary (i.e. a
-    <literal>.a</literal>-file) is still built. For this to succeed,
-    GNU libtool needs to be installed on your system. Hence,
-    <literal>configure</literal> checks if it can find an executable
-    <literal>libtool</literal> in the <literal>PATH</literal>. If it
-    doesn't this option is ignored and the default restored, which
-    means that only a static library will be build.</para>
+    <para><literal>--disable-shared</literal>: When given, this option
+    switches off the build of a shared library, i.e. a 
+    <literal>.so</literal>-file.  This may be convenient when developing
+    because it considerably speeds up compilation.</para>
   </listitem>
   <listitem>
     <para><literal>--prefix=</literal><emphasis>PREFIX</emphasis>: The
@@ -367,11 +364,11 @@ will be shortly described in what follows:
     <para><literal>--includedir=</literal><emphasis>INCLUDEDIR</emphasis>:
     Use this option in case you want to have the header files
     installed in some other directory than
-    <emphasis>PREFIX</emphasis><literal>/include/GiNaC/</literal>. For
+    <emphasis>PREFIX</emphasis><literal>/include/ginac/</literal>. For
     instance, if you specify
     <literal>--includedir=/usr/include</literal> you will end up with
     the header files sitting in the directory
-    <literal>/usr/include/GiNaC/</literal>. Note that the subdirectory
+    <literal>/usr/include/ginac/</literal>. Note that the subdirectory
     <literal>GiNaC</literal> is enforced by this process in order to
     keep the header files separated from others.  This avoids some
     clashes and allows for an easier deinstallation of GiNaC. This ought
@@ -407,18 +404,18 @@ 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>
 <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"
+<prompt>$</prompt> export LDFLAGS="${LDFLAGS} -L${HOME}/lib"
+<prompt>$</prompt> ./configure --disable-shared --prefix=${HOME}
 </screen>
 </example>
 </para>
@@ -436,11 +433,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>
 
@@ -463,8 +460,8 @@ directories will be created if they don't already exist):
   </listitem>
   <listitem>
     <para>All the header files will be installed into
-    <emphasis>PREFIX</emphasis><literal>/include/GiNaC/</literal> (or
-    <emphasis>INCLUDEDIR</emphasis><literal>/GiNaC/</literal>, if
+    <emphasis>PREFIX</emphasis><literal>/include/ginac/</literal> (or
+    <emphasis>INCLUDEDIR</emphasis><literal>/ginac/</literal>, if
     specified).</para>
   </listitem>
   <listitem>
@@ -543,7 +540,8 @@ the copying takes place as soon as you try to change the second.
 Consider the simple sequence of code:
 <example><title>Simple copy-on-write semantics</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -576,7 +574,8 @@ less trivial example of differentiation using the chain-rule should
 make clear how powerful this can be.  <example><title>Advanced
 copy-on-write semantics</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -688,15 +687,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
@@ -734,9 +738,10 @@ some useful constants.</para>
 shows the four most important constructors: construction from
 C-integer, construction of fractions from two integers, construction
 from C-float and construction from a string.
-<example><title>Sample C++ program</title>
+<example><title>Construction of numbers</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -776,8 +781,8 @@ objects of class numeric that are constructed from then on will be
 stored with a precision matching that number of decimal digits:
 <example><title>Controlling the precision of floating point numbers</title>
 <programlisting> 
-#include
-&lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 void foo()
 {
@@ -822,7 +827,8 @@ back to invocations of certain CLN functions.)</para>
 with some multiple of its denominator and check what comes out:
 <example><title>Sample test on objects of type numeric</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -963,7 +969,8 @@ type <literal>add</literal> is called to hold the sum of that
 <literal>mul</literal> object and the number one:
 <example><title>Construction of <literal>add</literal> and <literal>mul</literal> objects</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1040,7 +1047,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>
 
 
 
@@ -1060,7 +1067,8 @@ it, so you can alternatively call it in a functional way as shown in
 the simple example:
 <example><title>Methods vs. wrapper functions</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1127,7 +1135,7 @@ a univariate polynomial in one of the variables with the coefficients
 being polynomials in the remaining variables.  The method
 <literal>collect()</literal> accomplishes this task:
 <funcsynopsis>
-  <funcsynopsisinfo>#include &lt;GiNaC/ginac.h></funcsynopsisinfo>
+  <funcsynopsisinfo>#include &lt;ginac/ginac.h></funcsynopsisinfo>
   <funcdef>ex <function>ex::collect</function></funcdef>
   <paramdef>symbol const & <parameter>s</parameter></paramdef>
 </funcsynopsis>
@@ -1135,7 +1143,7 @@ Note that the original polynomial needs to be in expanded form in
 order to be able to find the coefficients properly.  The range of
 occuring coefficients can be checked using the two methods
 <funcsynopsis>
-  <funcsynopsisinfo>#include &lt;GiNaC/ginac.h></funcsynopsisinfo>
+  <funcsynopsisinfo>#include &lt;ginac/ginac.h></funcsynopsisinfo>
   <funcdef>int <function>ex::degree</function></funcdef>
   <paramdef>symbol const & <parameter>s</parameter></paramdef>
 </funcsynopsis>
@@ -1150,7 +1158,8 @@ in the following example:
 
 <example><title>Collecting expressions in multivariate polynomials</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1183,7 +1192,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>
 
@@ -1209,7 +1218,8 @@ and <function>lcm(a,b)</function> returns the product of
 <literal>a</literal> and <literal>b</literal>.
 <example><title>Polynomal GCD/LCM</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1232,11 +1242,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>
 
@@ -1244,10 +1281,13 @@ 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;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1261,20 +1301,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;
+#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>
 
@@ -1287,7 +1355,8 @@ class of its own for storing such series as well as a class for
 storing the order of the series.  A sample program could read:
 <example><title>Series expansion</title>
 <programlisting>
-#include &lt;GiNaC/ginac.h&gt;
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
 
 int main()
 {
@@ -1297,18 +1366,69 @@ int main()
     ex MyExpr2 = 1/(x - pow(x, 2) - pow(x, 3));
     ex MyTailor, MySeries;
     
-    MyTailor = MyExpr1.series(x, numZERO(), 5);
+    MyTailor = MyExpr1.series(x, point, 5);
     cout &lt;&lt; MyExpr1 &lt;&lt; " == " &lt;&lt; MyTailor
          &lt;&lt; " for small " &lt;&lt; x &lt;&lt; endl;
-    MySeries = MyExpr2.series(x, numZERO(), 7);
+    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>
 </para>
 
+<para>As an instructive application, let us calculate the numerical
+value of Archimedes' constant (for which there already exists the
+built-in constant <literal>Pi</literal>) using M&eacute;chain's
+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 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>
+#include &lt;ginac/ginac.h&gt;
+using namespace GiNaC;
+
+ex mechain_pi(int degr)
+{
+    symbol x("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));
+    return pi_approx;
+}
+
+int main()
+{
+    ex pi_frac;
+    for (int i=2; i&lt;12; i+=2) {
+        pi_frac = mechain_pi(i);
+        cout &lt;&lt; i &lt;&lt; ":\t" &lt;&lt; pi_frac &lt;&lt; endl
+             &lt;&lt; "\t" &lt;&lt; pi_frac.evalf() &lt;&lt; endl;
+    }
+    return 0;
+}
+</programlisting>
+<para>When you run this program, it will type out:</para>
+<screen>
+2:      3804/1195
+        3.1832635983263598326
+4:      5359397032/1706489875
+        3.1405970293260603143
+6:      38279241713339684/12184551018734375
+        3.141621029325034425
+8:      76528487109180192540976/24359780855939418203125
+        3.141591772182177295
+10:     327853873402258685803048818236/104359128170408663038552734375
+        3.1415926824043995174
+</screen>
+</example>
+</para>
+
 </sect1>
 
 </chapter>
@@ -1534,24 +1654,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>