<example>
<title>My first GiNaC program (a bivariate polynomial)</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
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>
<example>
<title>My second GiNaC program (Hermite polynomials)</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
ex HermitePoly(symbol x, int deg)
{
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
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
<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
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>
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>
</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>
Consider the simple sequence of code:
<example><title>Simple copy-on-write semantics</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
make clear how powerful this can be. <example><title>Advanced
copy-on-write semantics</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
<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
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 <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
stored with a precision matching that number of decimal digits:
<example><title>Controlling the precision of floating point numbers</title>
<programlisting>
-#include
-<GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
void foo()
{
with some multiple of its denominator and check what comes out:
<example><title>Sample test on objects of type numeric</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
<literal>mul</literal> object and the number one:
<example><title>Construction of <literal>add</literal> and <literal>mul</literal> objects</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
<sect1><title>Built-in Functions</title>
-<para>This chapter is not here yet</para>
+<para>This section is not here yet</para>
the simple example:
<example><title>Methods vs. wrapper functions</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
being polynomials in the remaining variables. The method
<literal>collect()</literal> accomplishes this task:
<funcsynopsis>
- <funcsynopsisinfo>#include <GiNaC/ginac.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <ginac/ginac.h></funcsynopsisinfo>
<funcdef>ex <function>ex::collect</function></funcdef>
<paramdef>symbol const & <parameter>s</parameter></paramdef>
</funcsynopsis>
order to be able to find the coefficients properly. The range of
occuring coefficients can be checked using the two methods
<funcsynopsis>
- <funcsynopsisinfo>#include <GiNaC/ginac.h></funcsynopsisinfo>
+ <funcsynopsisinfo>#include <ginac/ginac.h></funcsynopsisinfo>
<funcdef>int <function>ex::degree</function></funcdef>
<paramdef>symbol const & <parameter>s</parameter></paramdef>
</funcsynopsis>
<example><title>Collecting expressions in multivariate polynomials</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
int main()
{
</sect1>
-<sect1 id="gcd-main"><title>Polynomial Arithmetic</title>
+<sect1><title>Polynomial Arithmetic</title>
<sect2><title>GCD and LCM</title>
<literal>a</literal> and <literal>b</literal>.
<example><title>Polynomal GCD/LCM</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
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 <ginac/ginac.h>
+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 << "t1 is " << t1.normal() << endl;
+ cout << "t2 is " << t2.normal() << 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>
<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 <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
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 <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+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<11; i+=2)
+ cout << EulerNumber(i) << 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>
storing the order of the series. A sample program could read:
<example><title>Series expansion</title>
<programlisting>
-#include <GiNaC/ginac.h>
+#include <ginac/ginac.h>
+using namespace GiNaC;
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 << MyExpr1 << " == " << MyTailor
<< " for small " << x << endl;
- MySeries = MyExpr2.series(x, numZERO(), 7);
+ MySeries = MyExpr2.series(x, point, 7);
cout << MyExpr2 << " == " << MySeries
<< " for small " << x << 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é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échain's formula for
+<literal>Pi</literal></title>
+<programlisting>
+#include <ginac/ginac.h>
+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<12; i+=2) {
+ pi_frac = mechain_pi(i);
+ cout << i << ":\t" << pi_frac << endl
+ << "\t" << pi_frac.evalf() << 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>
</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>