<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>
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
</screen>
<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>$</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 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>
</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>
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
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
}
</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*">
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));
<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>
</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>