From: Richard Kreckel
Date: Tue, 23 Nov 1999 19:14:32 +0000 (+0000)
Subject:  Finished last chapter. I guess it's 95% complete now.
XGitTag: relase_051~147
XGitUrl: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=956667af1a8aee1a74e4c70c2ff6ad474cced3cd
 Finished last chapter. I guess it's 95% complete now.

diff git a/doc/tutorial/tutorial.sgml.in b/doc/tutorial/tutorial.sgml.in
index 3869936c..a8ac0ae2 100644
 a/doc/tutorial/tutorial.sgml.in
+++ b/doc/tutorial/tutorial.sgml.in
@@ 27,12 +27,6 @@
Richard.Kreckel@UniMainz.DE

 Others

 whoever@ThEP.Physik.UniMainz.DE


@@ 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
ginsh syntax we refer to its accompanied
manpage.
+ginsh syntax we refer to its accompanied manpage.
+Suffice to say that assignments and comparisons in
+ginsh are written as they are in C,
+i.e. = assigns and ==
+compares.
It can manipulate arbitrary precision integers in a very fast
way. Rational numbers are automatically converted to fractions of
@@ 409,11 +406,12 @@ GiNaC library assuming everything is in default paths:
Configuration for a private static GiNaC library with several
components sitting in custom places (sitewide GCC
and private CLN):
+and private CLN), the compiler pursueded to be
+picky and full assertions switched on:
$ export CXX=/usr/local/gnu/bin/c++
$ export CPPFLAGS="${CPPFLAGS} I${HOME}/include"
$ export CXXFLAGS="${CXXFLAGS} ggdb Wall ansi pedantic O2"
+$ export CXXFLAGS="${CXXFLAGS} ggdb Wall ansi pedantic O2 DDO_GINAC_ASSERT"
$ export LDFLAGS="${LDFLAGS} L${HOME}/lib"
$ ./configure disableshared prefix=${HOME}
@@ 605,11 +603,16 @@ argument of cos() only holds a reference to
As a user of GiNaC, you cannot see this mechanism of
copyonwrite 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.
+copyonwrite 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
+copyonwrite semantics, we recommend you have a look at the
+C++FAQ lite 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 http://www.cerfnet.com/~mpcline/c++faqlite/.
So much for expressions. But what exactly are these expressions
handles of? This will be answered in the following sections.
@@ 719,7 +722,7 @@ for Numbers or alternatively for Common Lisp Numbers. In order to
find out more about CLN'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 GMP, which is a extremely fast
+Precision library GMP, 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. CLN extends
@@ 758,16 +761,24 @@ int main()
Note that all those constructors are explicit
which means you are not allowed to write numeric
two=2;. 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 pow(x,2) to be handled the same way
as pow(x,a), which means that we need to allow a
general expression as base and exponent. Therefore there is an
implicit construction from a Cinteger 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.

+GiNaC are the expressions ex and we want to keep
+things simple and wish objects like pow(x,2) to be
+handled the same way as pow(x,a), which means that
+we need to allow a general ex as base and exponent.
+Therefore there is an implicit constructor from Cintegers 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.
+
+It may be tempting to construct numbers writing numeric
+r(3/2). This would, however, call C's builtin operator
+/ for integers first and result in a numeric
+holding a plain integer 1. Never use
+/ on integers! Use
+the constructor from two integers instead, as shown in the example
+above. Writing numeric(1)/2 may look funny but
+works also.
We have seen now the distinction between exact numbers and
floating point numbers. Clearly, the user should never have to worry
@@ 843,18 +854,20 @@ int main()
}
+
Note that the variable answer 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
CLN is responsible for this behaviour and we refer
the reader to CLN'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 CLN is responsible for this behaviour
+and we refer the reader to CLN'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.
+
@@ 1395,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));
@@ 1437,7 +1450,113 @@ int main()
Extending GiNaC
Longish chapter follows here.
+By reading so far you should have gotten a fairly good
+understanding of GiNaC's designpatterns. 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.
+
+What doesn't belong into GiNaC
+
+First of all, GiNaC's name must be read literally. It is
+designed to be a library for use within C++. The tiny
+ginsh accompanying GiNaC makes this even more
+clear: it doesn't even attempt to provide a language. There are no
+loops or conditional expressions in ginsh, 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.
+
+There are many builtin functions in GiNaC that do not know how
+to evaluate themselves numerically to a precision declared at runtime
+(using Digits). 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 bignumpackage
+CLN is much better suited.
+
+
+
+Other symbolic functions
+
+The easiest and most instructive way to start with is probably
+to implement your own function. Objects of class
+function 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
+ex as arguments and returning one
+ex. 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
+eval it. It could look something like this:
+
+
+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();
+}
+
+The last line returns cos(x) if we don't know what
+else to do and stops a potential recursive evaluation by saying
+.hold(). 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 numeric:
+
+static ex cos_evalf_method(ex const & x)
+{
+ return sin(ex_to_numeric(x));
+}
+
+Differentiation will surely turn up and so we need to tell
+sin how to differentiate itself:
+
+static ex cos_diff_method(ex const & x, unsigned diff_param)
+{
+ return cos(x);
+}
+
+
+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.
+
+Now that everything has been written for cos,
+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:
+
+REGISTER_FUNCTION(cos, cos_eval_method, cos_evalf_method, cos_diff, NULL);
+
+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:
+
+DECLARE_FUNCTION_1P(cos)
+
+The suffix _1P stands for one
+parameter. Of course, this implementation of
+cos 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 macrointense classes.
+We have done our best to avoid them where we can.)
+
+That's it. May the source be with you!
+
+
@@ 1616,6 +1735,16 @@ language.
+
+
+ C++ FAQs
+ MarshallCline
+ 0201589583
+ 1995
+ Addison Wesley
+
+
+
Algorithms for Computer Algebra